-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial base classes and qpimage support
- Loading branch information
1 parent
46ba0c7
commit 2d1f677
Showing
9 changed files
with
203 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .core import load_data # noqa: F401 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,23 @@ | ||
from .group_folder import GroupFolder | ||
from .group_hdf5_qpimage import GroupHdf5Qimage | ||
from .group_zip_tif_phasics import GroupZipTifPhasics | ||
from .single_hdf5_qimage import SingleHdf5Qimage | ||
from .single_tif_phasics import SingleTifPhasics | ||
# from .group_folder import GroupFolder | ||
# from .group_hdf5_qpimage import GroupHdf5Qpimage | ||
# from .group_zip_tif_phasics import GroupZipTifPhasics | ||
from .single_hdf5_qimage import SingleHdf5Qpimage | ||
# from .single_tif_phasics import SingleTifPhasics | ||
|
||
|
||
def guess_format(path): | ||
"""Determine the file format of a folder or a file""" | ||
for fmt in formats: | ||
if fmt.verify(path): | ||
return path | ||
class UnknownFileFormatError(BaseException): | ||
pass | ||
|
||
|
||
# the order is important for | ||
formats = [GroupFolder, | ||
GroupZipTifPhasics, | ||
GroupHdf5Qimage, | ||
SingleHdf5Qimage, | ||
SingleTifPhasics, | ||
] | ||
|
||
# the order is important for | ||
formats = [ # GroupFolder, | ||
# GroupZipTifPhasics, | ||
# GroupHdf5Qpimage, | ||
SingleHdf5Qpimage, | ||
# SingleTifPhasics, | ||
] | ||
|
||
# convenience dictionary | ||
formats_dict = {} | ||
for _fmt in formats: | ||
formats_dict[_fmt.name] = _fmt | ||
for fmt in formats: | ||
formats_dict[fmt.__name__] = fmt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,118 @@ | ||
import abc | ||
import copy | ||
|
||
import qpimage | ||
|
||
|
||
class DataSet(object): | ||
__meta__ = abs.ABCMeta | ||
__meta__ = abc.ABCMeta | ||
|
||
def __init__(self, path, meta_data): | ||
def __init__(self, path, meta_data={}): | ||
self.path = path | ||
self.meta_data = copy.copy(meta_data) | ||
self._bgdata = [] | ||
|
||
def __repr__(self): | ||
# class name | ||
# path | ||
# length | ||
# if present: | ||
# - resolution | ||
# - wavelength | ||
pass | ||
rep = "QPFormat '{}'".format(self.__class__.__name__) \ | ||
+ ", {} event(s)".format(len(self)) \ | ||
+ "\nfile: {}".format(self.path) | ||
|
||
meta = [] | ||
if "wavelength" in self.meta_data: | ||
wl = self.meta_data["wavelength"] | ||
if wl < 2000e-9 and wl > 10e-9: | ||
# convenience for light microscopy | ||
meta.append("λ={:.1f}nm".format(wl * 1e9)) | ||
else: | ||
meta.append("λ={:.2e}m".format(wl)) | ||
if "pixel size" in self.meta_data: | ||
pxm = self.meta_data["pixel size"] | ||
if pxm < 1e-3 and pxm > 1e-8: | ||
# convenience for light microscopy | ||
meta.append("1px={}µm".format(pxm * 1e6)) | ||
else: | ||
meta.append("1px={}m".format(pxm)) | ||
rep += ", ".join(meta) | ||
return rep | ||
|
||
@abc.abstractmethod | ||
def __len__(self): | ||
return len(self.data) | ||
"""Return number of samples of a data set""" | ||
|
||
@abc.abstractmethod | ||
def verify(path): | ||
"""Verify that `path` has this file format | ||
def get_name(self, idx): | ||
"""Return name of data at index `idx`""" | ||
return "{} [{}]".format(self.path, idx) | ||
|
||
def get_qpimage(self, idx): | ||
"""Return background-corrected QPImage of data at index `idx`""" | ||
# raw data | ||
qpi = self.get_qpimage_raw(idx) | ||
# bg data | ||
if len(self._bgdata) == 1: | ||
# One background for all | ||
bgidx = 0 | ||
else: | ||
bgidx = idx | ||
|
||
if isinstance(self._bgdata, DataSet): | ||
bg = self._bgdata.get_qpimage_raw(bgidx) | ||
else: | ||
bg = self._bgdata[bgidx] | ||
qpi.set_bg(bg_data=bg) | ||
return qpi | ||
|
||
@abc.abstractmethod | ||
def get_qpimage_raw(self, idx): | ||
"""Return QPImage without background correction""" | ||
|
||
Returns `True` if the file format matches. | ||
""" | ||
|
||
def get_data(self, idx): | ||
pass | ||
|
||
def get_time(self, idx): | ||
"""Return time of data at in dex `idx` | ||
By default, this returns zero and must be | ||
overridden if the file format supports timing. | ||
""" | ||
return 0 | ||
|
||
|
||
def saveh5(self, h5file): | ||
"""Save the data set as an hdf5 file (QPImage format)""" | ||
|
||
def set_bg(self, dataset): | ||
"""Set background data | ||
Parameters | ||
---------- | ||
dataset: `DataSet` or `qpimage.QPImage` | ||
If the ``len(dataset)`` matches ``len(self)``, | ||
then background correction is performed | ||
element-wise. Otherwise, ``len(dataset)`` | ||
must be one and is used for all data of ``self``. | ||
See Also | ||
-------- | ||
get_qpimage: obtain the background corrected QPImage | ||
""" | ||
|
||
if isinstance(dataset, qpimage.QPImage): | ||
# Single QPImage | ||
self._bgdata = [dataset] | ||
elif (isinstance(dataset, list) and | ||
len(dataset) == len(self) and | ||
isinstance(dataset[0], qpimage.QPImage)): | ||
# List of QPImage | ||
self.bgdata = dataset | ||
elif (isinstance(dataset, DataSet) and | ||
(len(dataset) == 1 or | ||
len(dataset) == len(self))): | ||
# DataSet | ||
self.bgdata = dataset | ||
else: | ||
raise ValueError("Bad length or type for bg: {}".format(dataset)) | ||
self._bgdata = dataset | ||
|
||
@staticmethod | ||
@abc.abstractmethod | ||
def verify(path): | ||
"""Verify that `path` has this file format | ||
Returns `True` if the file format matches. | ||
""" | ||
pass | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from dataset import DataSet | ||
|
||
|
||
class GroupHdf5Qpimage(DataSet): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import h5py | ||
import qpimage | ||
|
||
from .dataset import DataSet | ||
|
||
|
||
class SingleHdf5Qpimage(DataSet): | ||
def __len__(self): | ||
return 1 | ||
|
||
def get_qpimage(self, idx): | ||
"""Return background-corrected QPImage of data at index `idx`""" | ||
if self._bgdata: | ||
# The user has explicitly chosen different background data | ||
# using `get_qpimage_raw`. | ||
return super(SingleHdf5Qpimage, self).get_qpimage(idx) | ||
else: | ||
# We can use the background data stored in the qpimage hdf5 file | ||
return qpimage.QPImage(h5file=self.path, h5mode="r").copy() | ||
|
||
def get_qpimage_raw(self, idx=0): | ||
"""Return QPImage without background correction""" | ||
if idx != 0: | ||
raise ValueError("Single file format, only one entry (`idx!=0`)!") | ||
qpi = qpimage.QPImage(h5file=self.path, h5mode="r").copy() | ||
# Remove previously performed background correction | ||
qpi.set_bg_data(None) | ||
return qpi | ||
|
||
def get_time(self, idx=0): | ||
"""Return the time of the QPImage data""" | ||
qpi = qpimage.QPImage(h5file=self.path, h5mode="r") | ||
if "time" in qpi.meta: | ||
return qpi.meta["time"] | ||
else: | ||
return 0 | ||
|
||
@staticmethod | ||
def verify(path): | ||
"""Verify that `path` has the qpimage file format | ||
Returns `True` if the file format matches. | ||
""" | ||
valid = False | ||
try: | ||
h5 = h5py.File(path, mode="r") | ||
except: | ||
pass | ||
else: | ||
if ("qpimage version" in h5.attrs and | ||
"phase" in h5 and | ||
"amplitude" in h5 and | ||
"bg_data" in h5["phase"] and | ||
"bg_data" in h5["amplitude"]): | ||
valid = True | ||
return valid |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,22 @@ | ||
import os | ||
from os.path import abspath, dirname | ||
from os.path import abspath, dirname, join | ||
import sys | ||
import tempfile | ||
|
||
import numpy as np | ||
|
||
# Add parent directory to beginning of path variable | ||
sys.path.insert(0, dirname(dirname(abspath(__file__)))) | ||
import qpformat # noqa: E402 | ||
|
||
|
||
def test_nothing(): | ||
pass | ||
def test_load_data(): | ||
path = join(dirname(abspath(__file__)), "data/bg_ramp.h5") | ||
ds = qpformat.load_data(path) | ||
assert ds.path == path | ||
assert ds.get_time() == 0 | ||
assert "SingleHdf5Qpimage" in ds.__repr__() | ||
|
||
|
||
if __name__ == "__main__": | ||
# Run all tests | ||
loc = locals() | ||
for key in list(loc.keys()): | ||
if key.startswith("test_") and hasattr(loc[key], "__call__"): | ||
loc[key]() | ||
|