dcnum 0.25.8__tar.gz → 0.25.10__tar.gz

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.

Files changed (131) hide show
  1. {dcnum-0.25.8 → dcnum-0.25.10}/CHANGELOG +5 -0
  2. {dcnum-0.25.8 → dcnum-0.25.10}/PKG-INFO +1 -1
  3. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/_version.py +2 -2
  4. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_background/base.py +5 -2
  5. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/segm_torch/segm_torch_base.py +11 -4
  6. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum.egg-info/PKG-INFO +1 -1
  7. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum.egg-info/SOURCES.txt +1 -0
  8. dcnum-0.25.10/tests/data/segm-torch-model_unet-dcnum-test_g2_17ec6.zip +0 -0
  9. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_segm_torch.py +76 -0
  10. {dcnum-0.25.8 → dcnum-0.25.10}/.github/workflows/check.yml +0 -0
  11. {dcnum-0.25.8 → dcnum-0.25.10}/.github/workflows/deploy_pypi.yml +0 -0
  12. {dcnum-0.25.8 → dcnum-0.25.10}/.gitignore +0 -0
  13. {dcnum-0.25.8 → dcnum-0.25.10}/.readthedocs.yml +0 -0
  14. {dcnum-0.25.8 → dcnum-0.25.10}/LICENSE +0 -0
  15. {dcnum-0.25.8 → dcnum-0.25.10}/README.rst +0 -0
  16. {dcnum-0.25.8 → dcnum-0.25.10}/benchmark/.gitignore +0 -0
  17. {dcnum-0.25.8 → dcnum-0.25.10}/benchmark/Readme.md +0 -0
  18. {dcnum-0.25.8 → dcnum-0.25.10}/benchmark/benchmark.py +0 -0
  19. {dcnum-0.25.8 → dcnum-0.25.10}/benchmark/bm_write_deque_writer_thread.py +0 -0
  20. {dcnum-0.25.8 → dcnum-0.25.10}/benchmark/bm_write_queue_collector_thread.py +0 -0
  21. {dcnum-0.25.8 → dcnum-0.25.10}/docs/.gitignore +0 -0
  22. {dcnum-0.25.8 → dcnum-0.25.10}/docs/conf.py +0 -0
  23. {dcnum-0.25.8 → dcnum-0.25.10}/docs/extensions/github_changelog.py +0 -0
  24. {dcnum-0.25.8 → dcnum-0.25.10}/docs/index.rst +0 -0
  25. {dcnum-0.25.8 → dcnum-0.25.10}/docs/requirements.txt +0 -0
  26. {dcnum-0.25.8 → dcnum-0.25.10}/docs/sec_design.rst +0 -0
  27. {dcnum-0.25.8 → dcnum-0.25.10}/pyproject.toml +0 -0
  28. {dcnum-0.25.8 → dcnum-0.25.10}/setup.cfg +0 -0
  29. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/__init__.py +0 -0
  30. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/__init__.py +0 -0
  31. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/event_extractor_manager_thread.py +0 -0
  32. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_background/__init__.py +0 -0
  33. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_background/bg_copy.py +0 -0
  34. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_background/bg_roll_median.py +0 -0
  35. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_background/bg_sparse_median.py +0 -0
  36. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_brightness/__init__.py +0 -0
  37. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_brightness/bright_all.py +0 -0
  38. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_brightness/common.py +0 -0
  39. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_contour/__init__.py +0 -0
  40. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_contour/contour.py +0 -0
  41. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_contour/moments.py +0 -0
  42. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_contour/volume.py +0 -0
  43. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_texture/__init__.py +0 -0
  44. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_texture/common.py +0 -0
  45. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/feat_texture/tex_all.py +0 -0
  46. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/gate.py +0 -0
  47. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/feat/queue_event_extractor.py +0 -0
  48. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/logic/__init__.py +0 -0
  49. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/logic/ctrl.py +0 -0
  50. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/logic/job.py +0 -0
  51. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/logic/json_encoder.py +0 -0
  52. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/meta/__init__.py +0 -0
  53. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/meta/paths.py +0 -0
  54. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/meta/ppid.py +0 -0
  55. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/os_env_st.py +0 -0
  56. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/read/__init__.py +0 -0
  57. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/read/cache.py +0 -0
  58. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/read/const.py +0 -0
  59. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/read/detect_flicker.py +0 -0
  60. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/read/hdf5_concat.py +0 -0
  61. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/read/hdf5_data.py +0 -0
  62. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/read/mapped.py +0 -0
  63. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/__init__.py +0 -0
  64. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/segm_thresh.py +0 -0
  65. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/segm_torch/__init__.py +0 -0
  66. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/segm_torch/segm_torch_mpo.py +0 -0
  67. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/segm_torch/segm_torch_sto.py +0 -0
  68. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/segm_torch/torch_model.py +0 -0
  69. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/segm_torch/torch_postproc.py +0 -0
  70. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/segm_torch/torch_preproc.py +0 -0
  71. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/segmenter.py +0 -0
  72. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/segmenter_manager_thread.py +0 -0
  73. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/segmenter_mpo.py +0 -0
  74. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/segm/segmenter_sto.py +0 -0
  75. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/write/__init__.py +0 -0
  76. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/write/deque_writer_thread.py +0 -0
  77. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/write/queue_collector_thread.py +0 -0
  78. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum/write/writer.py +0 -0
  79. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum.egg-info/dependency_links.txt +0 -0
  80. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum.egg-info/requires.txt +0 -0
  81. {dcnum-0.25.8 → dcnum-0.25.10}/src/dcnum.egg-info/top_level.txt +0 -0
  82. {dcnum-0.25.8 → dcnum-0.25.10}/tests/conftest.py +0 -0
  83. {dcnum-0.25.8 → dcnum-0.25.10}/tests/data/fmt-hdf5_cytoshot_extended-moments-features.zip +0 -0
  84. {dcnum-0.25.8 → dcnum-0.25.10}/tests/data/fmt-hdf5_cytoshot_full-features_2023.zip +0 -0
  85. {dcnum-0.25.8 → dcnum-0.25.10}/tests/data/fmt-hdf5_cytoshot_full-features_2024.zip +0 -0
  86. {dcnum-0.25.8 → dcnum-0.25.10}/tests/data/fmt-hdf5_cytoshot_full-features_legacy_allev_2023.zip +0 -0
  87. {dcnum-0.25.8 → dcnum-0.25.10}/tests/data/fmt-hdf5_shapein_empty.zip +0 -0
  88. {dcnum-0.25.8 → dcnum-0.25.10}/tests/data/fmt-hdf5_shapein_raw-with-variable-length-logs.zip +0 -0
  89. {dcnum-0.25.8 → dcnum-0.25.10}/tests/data/segm-torch-model_unet-dcnum-test_g1_910c2.zip +0 -0
  90. {dcnum-0.25.8 → dcnum-0.25.10}/tests/data/segm-torch-test-data_unet-dcnum-test_g1_910c2.zip +0 -0
  91. {dcnum-0.25.8 → dcnum-0.25.10}/tests/helper_methods.py +0 -0
  92. {dcnum-0.25.8 → dcnum-0.25.10}/tests/requirements.txt +0 -0
  93. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_feat_background_base.py +0 -0
  94. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_feat_background_bg_copy.py +0 -0
  95. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_feat_background_bg_roll_median.py +0 -0
  96. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_feat_background_bg_sparsemed.py +0 -0
  97. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_feat_brightness.py +0 -0
  98. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_feat_event_extractor_manager.py +0 -0
  99. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_feat_gate.py +0 -0
  100. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_feat_haralick.py +0 -0
  101. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_feat_moments_based.py +0 -0
  102. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_feat_moments_based_extended.py +0 -0
  103. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_feat_volume.py +0 -0
  104. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_init.py +0 -0
  105. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_logic_job.py +0 -0
  106. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_logic_join.py +0 -0
  107. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_logic_json.py +0 -0
  108. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_logic_pipeline.py +0 -0
  109. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_meta_paths.py +0 -0
  110. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_meta_ppid_base.py +0 -0
  111. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_meta_ppid_bg.py +0 -0
  112. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_meta_ppid_data.py +0 -0
  113. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_meta_ppid_feat.py +0 -0
  114. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_meta_ppid_gate.py +0 -0
  115. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_meta_ppid_segm.py +0 -0
  116. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_read_basin.py +0 -0
  117. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_read_concat_hdf5.py +0 -0
  118. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_read_detect_flicker.py +0 -0
  119. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_read_hdf5.py +0 -0
  120. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_read_hdf5_basins.py +0 -0
  121. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_read_hdf5_concat.py +0 -0
  122. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_read_hdf5_index_mapping.py +0 -0
  123. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_segm_base.py +0 -0
  124. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_segm_mpo.py +0 -0
  125. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_segm_no_mask_proc.py +0 -0
  126. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_segm_sto.py +0 -0
  127. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_segm_thresh.py +0 -0
  128. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_segm_torch_preproc.py +0 -0
  129. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_write_deque_writer_thread.py +0 -0
  130. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_write_queue_collector_thread.py +0 -0
  131. {dcnum-0.25.8 → dcnum-0.25.10}/tests/test_write_writer.py +0 -0
@@ -1,3 +1,8 @@
1
+ 0.25.10
2
+ - fix: search for validation strings in logs did not use re.MULTILINE
3
+ - enh: allow to validate torch model applicability based on meta values
4
+ 0.25.9
5
+ - fix: md5 sum caused PermissionError on Windows for background computation
1
6
  0.25.8
2
7
  - fix: invalid type definition for `concatenated_hdf5_data`
3
8
  - enh: make sure `HDF5Data.path` is converted to `pathlib.Path` if it is `str`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dcnum
3
- Version: 0.25.8
3
+ Version: 0.25.10
4
4
  Summary: numerics toolbox for imaging deformability cytometry
5
5
  Author: Maximilian Schlögel, Paul Müller, Raghava Alajangi
6
6
  Maintainer-email: Paul Müller <dev@craban.de>
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.25.8'
21
- __version_tuple__ = version_tuple = (0, 25, 8)
20
+ __version__ = version = '0.25.10'
21
+ __version_tuple__ = version_tuple = (0, 25, 10)
@@ -9,7 +9,7 @@ import time
9
9
  import h5py
10
10
 
11
11
  from ...meta import ppid
12
- from ...read import HDF5Data
12
+ from ...read import HDF5Data, md5sum
13
13
  from ...write import HDF5Writer, create_with_basins, set_default_filter_kwargs
14
14
 
15
15
 
@@ -87,6 +87,9 @@ class Background(abc.ABC):
87
87
 
88
88
  # Check whether user passed an array or a path
89
89
  if isinstance(input_data, pathlib.Path):
90
+ # Compute MD5 sum before opening the file so that we don't
91
+ # get a file-locking issue (PermissionError) on Windows.
92
+ md5_5m = md5sum(input_data, blocksize=65536, count=80)
90
93
  if str(input_data.resolve()) == str(output_path.resolve()):
91
94
  self.h5in = h5py.File(input_data, "a", libver="latest")
92
95
  self.h5out = self.h5in
@@ -98,7 +101,7 @@ class Background(abc.ABC):
98
101
  # the ImageCache. We have to go via the ImageCache route,
99
102
  # because HDF5Data properly resolves basins and the image
100
103
  # feature might be in a basin.
101
- self.hdin = HDF5Data(self.h5in)
104
+ self.hdin = HDF5Data(self.h5in, md5_5m=md5_5m)
102
105
  self.input_data = self.hdin.image.h5ds
103
106
  else:
104
107
  self.input_data = input_data
@@ -3,6 +3,8 @@ import pathlib
3
3
  import re
4
4
  from typing import Dict
5
5
 
6
+ import numpy as np
7
+
6
8
  from ...meta import paths
7
9
 
8
10
  from ..segmenter import Segmenter, SegmenterNotApplicableError
@@ -116,10 +118,15 @@ class TorchSegmenterBase(Segmenter):
116
118
  """
117
119
  key = item["key"]
118
120
  if key in data_dict:
119
- regexp = re.compile(item["regexp"])
120
- matched = bool(regexp.match(data_dict[key]))
121
- negate = item.get("regexp-negate", False)
122
- valid = matched if not negate else not matched
121
+ valid = True
122
+ if "regexp" in item:
123
+ re_match = bool(re.search(item["regexp"], data_dict[key],
124
+ re.MULTILINE))
125
+ negate = item.get("regexp-negate", False)
126
+ valid = valid and (re_match if not negate else not re_match)
127
+ if "value" in item:
128
+ valid = valid and np.allclose(item["value"], data_dict[key],
129
+ atol=0, rtol=0.01)
123
130
  if not valid:
124
131
  reasons_list.append(item.get("reason", "unknown reason"))
125
132
  elif not item.get("allow-missing-key", False):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dcnum
3
- Version: 0.25.8
3
+ Version: 0.25.10
4
4
  Summary: numerics toolbox for imaging deformability cytometry
5
5
  Author: Maximilian Schlögel, Paul Müller, Raghava Alajangi
6
6
  Maintainer-email: Paul Müller <dev@craban.de>
@@ -125,4 +125,5 @@ tests/data/fmt-hdf5_cytoshot_full-features_legacy_allev_2023.zip
125
125
  tests/data/fmt-hdf5_shapein_empty.zip
126
126
  tests/data/fmt-hdf5_shapein_raw-with-variable-length-logs.zip
127
127
  tests/data/segm-torch-model_unet-dcnum-test_g1_910c2.zip
128
+ tests/data/segm-torch-model_unet-dcnum-test_g2_17ec6.zip
128
129
  tests/data/segm-torch-test-data_unet-dcnum-test_g1_910c2.zip
@@ -54,6 +54,43 @@ def test_segm_torch_validate_model_file_logs():
54
54
  )
55
55
 
56
56
 
57
+ def test_segm_torch_validate_model_file_logs_negate():
58
+ """Test whether model validation fails for invalid logs"""
59
+ model_file = retrieve_model(
60
+ "segm-torch-model_unet-dcnum-test_g2_17ec6.zip")
61
+ sm = segm.segm_torch.SegmentTorchMPO
62
+
63
+ # Creating a specific log file will mak the model invalid
64
+ path = retrieve_data(
65
+ "fmt-hdf5_cytoshot_full-features_2024.zip")
66
+
67
+ with read.HDF5Data(path) as hd:
68
+ # sanity check
69
+ assert "dclab-compress" in hd.logs
70
+ with pytest.raises(
71
+ segm_torch_base.SegmenterNotApplicableError,
72
+ match="must not be compressed 2024-05-07"):
73
+ sm.validate_applicability(
74
+ segmenter_kwargs={"model_file": model_file},
75
+ meta=hd.meta,
76
+ logs=hd.logs
77
+ )
78
+
79
+ # Remove the offending log
80
+ with h5py.File(path, "a") as h5:
81
+ del h5["logs/dclab-compress"]
82
+
83
+ # Try again, this should work now.
84
+ with read.HDF5Data(path) as hd:
85
+ # sanity check
86
+ assert "dclab-compress" not in hd.logs
87
+ sm.validate_applicability(
88
+ segmenter_kwargs={"model_file": model_file},
89
+ meta=hd.meta,
90
+ logs=hd.logs
91
+ )
92
+
93
+
57
94
  def test_segm_torch_validate_model_file_meta():
58
95
  """Test whether model validation fails for invalid metadata"""
59
96
  model_file = retrieve_model(
@@ -96,6 +133,45 @@ def test_segm_torch_validate_model_file_meta():
96
133
  )
97
134
 
98
135
 
136
+ def test_segm_torch_validate_model_file_meta_value():
137
+ """Test whether model validation fails for invalid metadata"""
138
+ model_file = retrieve_model(
139
+ "segm-torch-model_unet-dcnum-test_g2_17ec6.zip")
140
+ sm = segm.segm_torch.SegmentTorchMPO
141
+
142
+ # Create a test dataset with metadata that will make the model invalid
143
+ path = retrieve_data(
144
+ "fmt-hdf5_cytoshot_full-features_2023.zip")
145
+
146
+ with h5py.File(path, "a") as h5:
147
+ h5.attrs["setup:channel width"] = 30.
148
+
149
+ with read.HDF5Data(path) as hd:
150
+ # sanity check
151
+ assert hd.meta["setup:channel width"] == 30
152
+ with pytest.raises(
153
+ segm_torch_base.SegmenterNotApplicableError,
154
+ match="channel width must be 20 micrometers"):
155
+ sm.validate_applicability(
156
+ segmenter_kwargs={"model_file": model_file},
157
+ meta=hd.meta,
158
+ logs=hd.logs
159
+ )
160
+
161
+ # Repeat the same thing, this time fixing the attribute
162
+ with h5py.File(path, "a") as h5:
163
+ h5.attrs["setup:channel width"] = 20.
164
+
165
+ with read.HDF5Data(path) as hd:
166
+ # sanity check
167
+ assert hd.meta["setup:channel width"] == 20
168
+ sm.validate_applicability(
169
+ segmenter_kwargs={"model_file": model_file},
170
+ meta=hd.meta,
171
+ logs=hd.logs
172
+ )
173
+
174
+
99
175
  def test_segm_torch_mpo():
100
176
  """Basic PyTorch segmenter"""
101
177
  path = retrieve_data(
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes