dcnum 0.11.4__py3-none-any.whl → 0.11.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of dcnum might be problematic. Click here for more details.

@@ -1,120 +0,0 @@
1
- import pathlib
2
-
3
- import h5py
4
- import numpy as np
5
-
6
- from dcnum.feat import feat_texture
7
-
8
- from helper_methods import retrieve_data
9
-
10
- data_path = pathlib.Path(__file__).parent / "data"
11
-
12
-
13
- def test_basic_haralick():
14
- # This original file was generated with dcevent for reference.
15
- path = retrieve_data(data_path /
16
- "fmt-hdf5_cytoshot_full-features_2023.zip")
17
- # Make data available
18
- with h5py.File(path) as h5:
19
- ret_arr = feat_texture.haralick_texture_features(
20
- image=h5["events/image"][:],
21
- image_bg=h5["events/image_bg"][:],
22
- mask=h5["events/mask"][:],
23
- )
24
-
25
- assert np.allclose(ret_arr["tex_asm_avg"][1],
26
- 0.001514295993357114,
27
- atol=0, rtol=1e-10)
28
- for feat in feat_texture.haralick_names:
29
- assert np.allclose(h5["events"][feat],
30
- ret_arr[feat])
31
- # control test
32
- assert not np.allclose(h5["events"]["tex_asm_avg"],
33
- ret_arr["tex_asm_ptp"])
34
-
35
-
36
- def test_empty_image():
37
- masks = np.array([
38
- [0, 0, 0, 0, 0, 0],
39
- [0, 0, 0, 0, 0, 0],
40
- [0, 0, 1, 1, 0, 0],
41
- [0, 0, 1, 1, 0, 0],
42
- [0, 0, 0, 0, 0, 0],
43
- [0, 0, 0, 0, 0, 0],
44
- ], dtype=bool)[np.newaxis]
45
- image_corr = np.zeros(6*6, dtype=np.int16).reshape(1, 6, 6)
46
- tex = feat_texture.haralick_texture_features(
47
- image_corr=image_corr,
48
- mask=masks,
49
- )
50
- assert np.allclose(tex["tex_con_avg"][0], 0)
51
-
52
-
53
- def test_empty_mask():
54
- masks = np.array([
55
- [0, 0, 0, 0, 0, 0],
56
- [0, 0, 0, 0, 0, 0],
57
- [0, 0, 0, 0, 0, 0],
58
- [0, 0, 0, 0, 0, 0],
59
- [0, 0, 0, 0, 0, 0],
60
- [0, 0, 0, 0, 0, 0],
61
- ], dtype=bool)[np.newaxis]
62
- image_corr = np.arange(6*6, dtype=np.int16).reshape(1, 6, 6)
63
- tex = feat_texture.haralick_texture_features(
64
- image_corr=image_corr,
65
- mask=masks,
66
- )
67
- assert np.isnan(tex["tex_con_avg"][0])
68
-
69
-
70
- def test_1d_mask_image():
71
- masks = np.array([
72
- [0, 0, 0, 0, 0, 0],
73
- [0, 0, 0, 0, 0, 0],
74
- [0, 0, 1, 0, 0, 0],
75
- [0, 0, 1, 0, 0, 0],
76
- [0, 0, 0, 0, 0, 0],
77
- [0, 0, 0, 0, 0, 0],
78
- ], dtype=bool)[np.newaxis]
79
- image_corr = np.arange(6*6, dtype=np.int16).reshape(1, 6, 6)
80
- tex = feat_texture.haralick_texture_features(
81
- image_corr=image_corr,
82
- mask=masks,
83
- )
84
- assert np.isnan(tex["tex_con_avg"][0])
85
-
86
-
87
- def test_nd_mask_with_1d_image():
88
- mask = np.array([
89
- [0, 0, 0, 0, 0, 0],
90
- [0, 0, 0, 0, 0, 0],
91
- [0, 0, 1, 1, 0, 0],
92
- [0, 0, 1, 1, 0, 0],
93
- [0, 0, 0, 0, 0, 0],
94
- [0, 0, 0, 0, 0, 0],
95
- ], dtype=bool)
96
- masks = np.stack([mask, mask, mask, mask])
97
- image_corr = np.arange(6*6, dtype=np.int16).reshape(1, 6, 6)
98
- tex = feat_texture.haralick_texture_features(
99
- image_corr=image_corr,
100
- mask=masks,
101
- )
102
- assert len(tex["tex_con_avg"]) == 4
103
- assert np.allclose(tex["tex_con_avg"][0], 27.75)
104
-
105
-
106
- def test_simple_mask_image():
107
- masks = np.array([
108
- [0, 0, 0, 0, 0, 0],
109
- [0, 0, 0, 0, 0, 0],
110
- [0, 0, 1, 1, 0, 0],
111
- [0, 0, 1, 1, 0, 0],
112
- [0, 0, 0, 0, 0, 0],
113
- [0, 0, 0, 0, 0, 0],
114
- ], dtype=bool)[np.newaxis]
115
- image_corr = np.arange(6*6, dtype=np.int16).reshape(1, 6, 6)
116
- tex = feat_texture.haralick_texture_features(
117
- image_corr=image_corr,
118
- mask=masks,
119
- )
120
- assert np.allclose(tex["tex_con_avg"][0], 27.75)
@@ -1,108 +0,0 @@
1
- import pathlib
2
-
3
- import h5py
4
- import numpy as np
5
-
6
- from dcnum.feat import feat_moments
7
-
8
- from helper_methods import retrieve_data
9
-
10
- data_path = pathlib.Path(__file__).parent / "data"
11
-
12
-
13
- def test_moments_based_features():
14
- # This original file was generated with dcevent for reference.
15
- path = retrieve_data(data_path /
16
- "fmt-hdf5_cytoshot_full-features_2023.zip")
17
- feats = [
18
- "deform",
19
- "size_x",
20
- "size_y",
21
- "pos_x",
22
- "pos_y",
23
- "area_msd",
24
- "area_ratio",
25
- "area_um",
26
- "aspect",
27
- "tilt",
28
- "inert_ratio_cvx",
29
- "inert_ratio_raw",
30
- "inert_ratio_prnc",
31
- ]
32
-
33
- # Make data available
34
- with h5py.File(path) as h5:
35
- data = feat_moments.moments_based_features(
36
- mask=h5["events/mask"][:],
37
- pixel_size=0.2645
38
- )
39
- for feat in feats:
40
- if feat.count("inert"):
41
- rtol = 2e-5
42
- atol = 1e-8
43
- else:
44
- rtol = 1e-5
45
- atol = 1e-8
46
- assert np.allclose(h5["events"][feat][:],
47
- data[feat],
48
- rtol=rtol,
49
- atol=atol), f"Feature {feat} mismatch!"
50
- # control test
51
- assert not np.allclose(h5["events"]["inert_ratio_cvx"][:],
52
- data["tilt"])
53
-
54
-
55
- def test_mask_0d():
56
- masks = np.array([
57
- [0, 0, 0, 0, 0, 0],
58
- [0, 0, 0, 0, 0, 0],
59
- [0, 0, 1, 0, 0, 0],
60
- [0, 0, 0, 0, 0, 0],
61
- [0, 0, 0, 0, 0, 0],
62
- [0, 0, 0, 0, 0, 0],
63
- ], dtype=bool)[np.newaxis]
64
- data = feat_moments.moments_based_features(
65
- mask=masks,
66
- pixel_size=0.2645
67
- )
68
- assert data["deform"].shape == (1,)
69
- assert np.isnan(data["deform"][0])
70
- assert np.isnan(data["area_um"][0])
71
-
72
-
73
- def test_mask_1d():
74
- masks = np.array([
75
- [0, 0, 0, 0, 0, 0],
76
- [0, 0, 0, 0, 0, 0],
77
- [0, 0, 1, 0, 0, 0],
78
- [0, 0, 1, 0, 0, 0],
79
- [0, 0, 0, 0, 0, 0],
80
- [0, 0, 0, 0, 0, 0],
81
- ], dtype=bool)[np.newaxis]
82
- data = feat_moments.moments_based_features(
83
- mask=masks,
84
- pixel_size=0.2645
85
- )
86
- assert data["deform"].shape == (1,)
87
- assert np.isnan(data["deform"][0])
88
- assert np.isnan(data["area_um"][0])
89
-
90
-
91
- def test_mask_2d():
92
- masks = np.array([
93
- [0, 0, 0, 0, 0, 0],
94
- [0, 0, 0, 0, 0, 0],
95
- [0, 0, 1, 1, 0, 0],
96
- [0, 0, 1, 1, 0, 0],
97
- [0, 0, 0, 0, 0, 0],
98
- [0, 0, 0, 0, 0, 0],
99
- ], dtype=bool)[np.newaxis]
100
- data = feat_moments.moments_based_features(
101
- mask=masks,
102
- pixel_size=0.2645
103
- )
104
- assert data["deform"].shape == (1,)
105
- # This is the deformation of a square (compared to circle)
106
- assert np.allclose(data["deform"][0], 0.11377307454724206)
107
- # Without moments-based computation, this would be 4*pxsize=0.066125
108
- assert np.allclose(data["area_um"][0], 0.06996025)
tests/test_init.py DELETED
@@ -1,5 +0,0 @@
1
- import dcnum
2
-
3
-
4
- def test_init():
5
- assert hasattr(dcnum, "__version__")
tests/test_ppid.py DELETED
@@ -1,94 +0,0 @@
1
- import inspect
2
-
3
- import pytest
4
-
5
- from dcnum.meta import ppid
6
-
7
-
8
- class ExampleClass:
9
- def cook(self, *,
10
- temperature: float = 90.0,
11
- te: str = "a",
12
- outside: bool = False,
13
- with_water: bool = True,
14
- amount: int = 1000,
15
- wine_type: str = "red",
16
- test_oven: bool = True):
17
- return id(self)
18
-
19
- @classmethod
20
- def key(cls):
21
- return cls.__name__
22
-
23
-
24
- @pytest.mark.parametrize("in_list,out_list", [
25
- (["camera", "campus"],
26
- ["came", "camp"]),
27
- (["cole", "coleman"],
28
- ["cole", "colem"]),
29
- (["cole", "coleman", "colemine"],
30
- ["cole", "colema", "colemi"]),
31
- (["cole", "coleman", "cundis"],
32
- ["cole", "colem", "cu"]),
33
- (["an", "and", "anderson", "andersrum", "ant"],
34
- ["an", "and", "anderso", "andersr", "ant"]),
35
- ])
36
- def test_unique_prefix_ordered(in_list, out_list):
37
- t_list = ppid.get_unique_prefix(in_list)
38
- assert t_list == out_list
39
-
40
-
41
- @pytest.mark.parametrize("in_list,out_list", [
42
- (["campus", "camera"],
43
- ["camp", "came"]),
44
- (["coleman", "cole"],
45
- ["colem", "cole"]),
46
- (["coleman", "cole", "colemine"],
47
- ["colema", "cole", "colemi"]),
48
- (["cole", "cundis", "coleman"],
49
- ["cole", "cu", "colem"]),
50
- (["an", "andersrum", "and", "anderson", "ant"],
51
- ["an", "andersr", "and", "anderso", "ant"]),
52
- ])
53
- def test_unique_prefix_unordered(in_list, out_list):
54
- t_list = ppid.get_unique_prefix(in_list)
55
- assert t_list == out_list
56
-
57
-
58
- @pytest.mark.parametrize("kwargs, pid", [
59
- ({},
60
- "tem=90^te=a^o=0^wit=1^a=1000^win=red^tes=1"),
61
- ({"temperature": 10.1},
62
- "tem=10.1^te=a^o=0^wit=1^a=1000^win=red^tes=1"),
63
- ({"with_water": False, "wine_type": "blue"},
64
- "tem=90^te=a^o=0^wit=0^a=1000^win=blue^tes=1"),
65
- ])
66
- def test_kwargs_to_ppid(kwargs, pid):
67
- ptest = ppid.kwargs_to_ppid(ExampleClass, "cook", kwargs)
68
- assert pid == ptest
69
-
70
-
71
- @pytest.mark.parametrize("kwargs, pid", [
72
- ({},
73
- "tem=90^te=a^o=0^wit=1^a=1000^win=red^tes=1"),
74
- ({"temperature": 10.1},
75
- "tem=10.1^te=a^o=0^wit=1^a=1000^win=red^tes=1"),
76
- ({"with_water": False, "wine_type": "blue"},
77
- "tem=90^te=a^o=0^wit=0^a=1000^win=blue^tes=1"),
78
- ({},
79
- "te=a^tem=90^o=0^wit=1^a=1000^win=red^tes=1"), # switch order (evil!)
80
- ({},
81
- "tem=90^te=a^o=0^wit=1^a=1000^win=red"), # remove things
82
- ({},
83
- "tem=90^te=a^o=0^w=1^a=1000"), # remove more things!
84
- ])
85
- def test_ppid_to_kwargs(kwargs, pid):
86
- # get the default keyword arguments
87
- meth = getattr(ExampleClass, "cook")
88
- spec = inspect.getfullargspec(meth)
89
- kwargs_full = spec.kwonlydefaults
90
- # update with given kwargs
91
- kwargs_full.update(kwargs)
92
-
93
- kwargs_test = ppid.ppid_to_kwargs(ExampleClass, "cook", pid)
94
- assert kwargs_test == kwargs_full
tests/test_ppid_segm.py DELETED
@@ -1,8 +0,0 @@
1
- from dcnum import segm
2
-
3
-
4
- def test_ppid_segm_base_with_thresh():
5
- scls = segm.get_available_segmenters()["thresh"]
6
- sthr = scls(thresh=-3)
7
- assert sthr.key() == "thresh"
8
- assert sthr.get_ppid() == "thresh:t=-3:cle=1^f=1^clo=2"
@@ -1,54 +0,0 @@
1
- import pathlib
2
-
3
- from dcnum import read
4
- import h5py
5
- import numpy as np
6
- import pytest
7
-
8
- from helper_methods import retrieve_data
9
-
10
- data_path = pathlib.Path(__file__).parent / "data"
11
-
12
-
13
- @pytest.mark.parametrize("path_out", [None, True])
14
- def test_concat_basic(path_out):
15
- path = retrieve_data(data_path /
16
- "fmt-hdf5_cytoshot_full-features_2023.zip")
17
- # create simple concatenated dataset, repeating a file
18
- data = read.concatenated_hdf5_data([path, path, path],
19
- path_out=path_out)
20
- assert len(data) == 120
21
-
22
-
23
- @pytest.mark.parametrize("path_out", [None, True])
24
- def test_concat_basic_frame(path_out):
25
- path = retrieve_data(data_path /
26
- "fmt-hdf5_cytoshot_full-features_2023.zip")
27
- # create simple concatenated dataset, repeating a file
28
- data = read.concatenated_hdf5_data([path, path, path],
29
- path_out=path_out)
30
- with h5py.File(path) as h5:
31
- frame = h5["events/frame"][:]
32
- assert frame[0] == 101
33
-
34
- assert np.allclose(data["frame"][:frame.size],
35
- frame - 101 + 1)
36
- offset1 = frame[-1] - 101 + 1
37
- assert np.allclose(offset1, data["frame"][frame.size-1])
38
- assert np.allclose(offset1 + 1, data["frame"][frame.size])
39
- assert np.allclose(data["frame"][frame.size:2*frame.size],
40
- frame - 101 + offset1 + 1)
41
- diff = frame[-1] - frame[0]
42
- assert np.allclose(data["frame"][-1], 3 * (diff + 1))
43
-
44
-
45
- def test_concat_basic_to_file(tmp_path):
46
- path = retrieve_data(data_path /
47
- "fmt-hdf5_cytoshot_full-features_2023.zip")
48
- # create simple concatenated dataset, repeating a file
49
- path_out = tmp_path / "test.rtdc"
50
- assert not path_out.exists()
51
- data = read.concatenated_hdf5_data([path, path, path],
52
- path_out=path_out)
53
- assert len(data) == 120
54
- assert path_out.exists()
tests/test_read_hdf5.py DELETED
@@ -1,196 +0,0 @@
1
- import pathlib
2
- import pickle
3
-
4
- import h5py
5
- import numpy as np
6
- import pytest
7
-
8
- from dcnum import read
9
-
10
- from helper_methods import retrieve_data
11
-
12
- data_path = pathlib.Path(__file__).parent / "data"
13
-
14
-
15
- def test_image_cache(tmp_path):
16
- path = tmp_path / "test.hdf5"
17
- with h5py.File(path, "w") as hw:
18
- hw["events/image"] = np.random.rand(210, 80, 180)
19
-
20
- with h5py.File(path, "r") as h5:
21
- hic = read.HDF5ImageCache(h5["events/image"],
22
- chunk_size=100,
23
- cache_size=2)
24
-
25
- # Get something from the first chunk
26
- assert np.allclose(hic[10], h5["events/image"][10])
27
- assert len(hic.cache) == 1
28
- assert 0 in hic.cache
29
-
30
- # Get something from the last chunk
31
- assert np.allclose(hic[205], h5["events/image"][205])
32
- assert len(hic.cache) == 2
33
- assert 0 in hic.cache
34
- assert 2 in hic.cache
35
- assert np.allclose(hic.cache[2], h5["events/image"][200:])
36
-
37
- # Get something from the first chunk again
38
- assert np.allclose(hic[90], h5["events/image"][90])
39
- assert len(hic.cache) == 2
40
- assert 0 in hic.cache
41
- assert 2 in hic.cache
42
-
43
- # Get something from the middle chunk
44
- assert np.allclose(hic[140], h5["events/image"][140])
45
- assert len(hic.cache) == 2 # limited to two
46
- assert 0 not in hic.cache # first item gets removed
47
- assert 1 in hic.cache
48
- assert 2 in hic.cache
49
-
50
-
51
- def test_image_cache_index_out_of_range(tmp_path):
52
- path = tmp_path / "test.hdf5"
53
- size = 20
54
- chunk_size = 8
55
- with h5py.File(path, "w") as hw:
56
- hw["events/image"] = np.random.rand(size, 80, 180)
57
- with h5py.File(path, "r") as h5:
58
- hic = read.HDF5ImageCache(h5["events/image"],
59
- chunk_size=chunk_size,
60
- cache_size=2)
61
- # Get something from first chunk. This should just work
62
- hic.__getitem__(10)
63
- # Now test out-of-bounds error
64
- with pytest.raises(IndexError, match="of bounds for HDF5ImageCache"):
65
- hic.__getitem__(20)
66
-
67
-
68
- def test_image_chache_get_chunk_size(tmp_path):
69
- path = tmp_path / "test.hdf5"
70
- size = 20
71
- chunk_size = 8
72
- with h5py.File(path, "w") as hw:
73
- hw["events/image"] = np.random.rand(size, 80, 180)
74
- with h5py.File(path, "r") as h5:
75
- hic = read.HDF5ImageCache(h5["events/image"],
76
- chunk_size=chunk_size,
77
- cache_size=2)
78
- # Get something from first chunk. This should just work
79
- assert hic.get_chunk_size(0) == 8
80
- assert hic.get_chunk_size(1) == 8
81
- assert hic.get_chunk_size(2) == 4
82
- with pytest.raises(IndexError, match="only has 3 chunks"):
83
- hic.get_chunk_size(3)
84
-
85
-
86
- @pytest.mark.parametrize("size, chunks", [(209, 21),
87
- (210, 21),
88
- (211, 22)])
89
- def test_image_cache_iter_chunks(size, chunks, tmp_path):
90
- path = tmp_path / "test.hdf5"
91
- with h5py.File(path, "w") as hw:
92
- hw["events/image"] = np.random.rand(size, 80, 180)
93
- with h5py.File(path, "r") as h5:
94
- hic = read.HDF5ImageCache(h5["events/image"],
95
- chunk_size=10,
96
- cache_size=2)
97
- assert list(hic.iter_chunks()) == list(range(chunks))
98
-
99
-
100
- def test_pixel_size_getset(tmp_path):
101
- path = tmp_path / "test.hdf5"
102
- with h5py.File(path, "w") as hw:
103
- hw["events/image"] = np.random.rand(10, 80, 180)
104
- hw.attrs["imaging:pixel size"] = 0.123
105
-
106
- h5dat = read.HDF5Data(path)
107
- assert np.allclose(h5dat.pixel_size, 0.123)
108
- h5dat.pixel_size = 0.321
109
- assert np.allclose(h5dat.pixel_size, 0.321)
110
-
111
-
112
- def test_open_real_data():
113
- path = retrieve_data(data_path /
114
- "fmt-hdf5_cytoshot_full-features_2023.zip")
115
- with read.HDF5Data(path) as h5dat: # context manager
116
- # properties
117
- assert len(h5dat) == 40
118
- assert h5dat.md5_5m == "599c8c7a112632d007be60b9c37961c5"
119
-
120
- # scalar features
121
- fsc = h5dat.features_scalar_frame
122
- exp = ['bg_med', 'frame', 'time']
123
- assert set(fsc) == set(exp)
124
-
125
- # feature names
126
- assert len(h5dat.keys()) == 48
127
- assert "deform" in h5dat.keys()
128
- assert "deform" in h5dat
129
-
130
-
131
- def test_pickling_state():
132
- path = retrieve_data(data_path /
133
- "fmt-hdf5_cytoshot_full-features_2023.zip")
134
-
135
- h5d1 = read.HDF5Data(path)
136
- h5d1.pixel_size = 0.124
137
- pstate = pickle.dumps(h5d1)
138
- h5d2 = pickle.loads(pstate)
139
- assert h5d1.md5_5m == h5d2.md5_5m
140
- assert h5d1.md5_5m == h5d2.md5_5m
141
- assert h5d1.pixel_size == h5d2.pixel_size
142
- assert np.allclose(h5d2.pixel_size, 0.124)
143
-
144
-
145
- def test_pickling_state_logs():
146
- path = retrieve_data(
147
- data_path / "fmt-hdf5_cytoshot_full-features_legacy_allev_2023.zip")
148
- h5d1 = read.HDF5Data(path)
149
- h5d1.pixel_size = 0.124
150
- pstate = pickle.dumps(h5d1)
151
- h5d2 = pickle.loads(pstate)
152
- assert h5d1.logs
153
- for lk in h5d1.logs:
154
- assert h5d1.logs[lk] == h5d2.logs[lk]
155
-
156
-
157
- def test_pickling_state_tables():
158
- path = retrieve_data(
159
- data_path / "fmt-hdf5_cytoshot_full-features_legacy_allev_2023.zip")
160
- # The original file does not contain any tables, so we write
161
- # generate a table
162
- columns = ["alot", "of", "tables"]
163
- ds_dt = np.dtype({'names': columns,
164
- 'formats': [float] * len(columns)})
165
- tab_data = np.zeros((11, len(columns)))
166
- tab_data[:, 0] = np.arange(11)
167
- tab_data[:, 1] = 1000
168
- tab_data[:, 2] = np.linspace(1, np.sqrt(2), 11)
169
- rec_arr = np.rec.array(tab_data, dtype=ds_dt)
170
-
171
- # add table to source file
172
- with h5py.File(path, "a") as h5:
173
- h5tab = h5.require_group("tables")
174
- h5tab.create_dataset(name="sample_table",
175
- data=rec_arr)
176
-
177
- h5d1 = read.HDF5Data(path)
178
- h5d1.pixel_size = 0.124
179
- pstate = pickle.dumps(h5d1)
180
- h5d2 = pickle.loads(pstate)
181
- assert h5d1.tables
182
- table = h5d1.tables["sample_table"]
183
- assert len(table) == 3
184
- for lk in table:
185
- assert np.allclose(h5d1.tables["sample_table"][lk],
186
- h5d2.tables["sample_table"][lk])
187
-
188
-
189
- def test_read_empty_logs():
190
- path = retrieve_data(
191
- data_path / "fmt-hdf5_cytoshot_full-features_legacy_allev_2023.zip")
192
- with h5py.File(path, "a") as h5:
193
- h5.require_group("logs").create_dataset(name="empty_log",
194
- data=[])
195
- h5r = read.HDF5Data(path)
196
- assert "empty_log" not in h5r.logs