Rhapso 0.1.92__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.
- Rhapso/__init__.py +1 -0
- Rhapso/data_prep/__init__.py +2 -0
- Rhapso/data_prep/n5_reader.py +188 -0
- Rhapso/data_prep/s3_big_stitcher_reader.py +55 -0
- Rhapso/data_prep/xml_to_dataframe.py +215 -0
- Rhapso/detection/__init__.py +5 -0
- Rhapso/detection/advanced_refinement.py +203 -0
- Rhapso/detection/difference_of_gaussian.py +324 -0
- Rhapso/detection/image_reader.py +117 -0
- Rhapso/detection/metadata_builder.py +130 -0
- Rhapso/detection/overlap_detection.py +327 -0
- Rhapso/detection/points_validation.py +49 -0
- Rhapso/detection/save_interest_points.py +265 -0
- Rhapso/detection/view_transform_models.py +67 -0
- Rhapso/fusion/__init__.py +0 -0
- Rhapso/fusion/affine_fusion/__init__.py +2 -0
- Rhapso/fusion/affine_fusion/blend.py +289 -0
- Rhapso/fusion/affine_fusion/fusion.py +601 -0
- Rhapso/fusion/affine_fusion/geometry.py +159 -0
- Rhapso/fusion/affine_fusion/io.py +546 -0
- Rhapso/fusion/affine_fusion/script_utils.py +111 -0
- Rhapso/fusion/affine_fusion/setup.py +4 -0
- Rhapso/fusion/affine_fusion_worker.py +234 -0
- Rhapso/fusion/multiscale/__init__.py +0 -0
- Rhapso/fusion/multiscale/aind_hcr_data_transformation/__init__.py +19 -0
- Rhapso/fusion/multiscale/aind_hcr_data_transformation/compress/__init__.py +3 -0
- Rhapso/fusion/multiscale/aind_hcr_data_transformation/compress/czi_to_zarr.py +698 -0
- Rhapso/fusion/multiscale/aind_hcr_data_transformation/compress/zarr_writer.py +265 -0
- Rhapso/fusion/multiscale/aind_hcr_data_transformation/models.py +81 -0
- Rhapso/fusion/multiscale/aind_hcr_data_transformation/utils/__init__.py +3 -0
- Rhapso/fusion/multiscale/aind_hcr_data_transformation/utils/utils.py +526 -0
- Rhapso/fusion/multiscale/aind_hcr_data_transformation/zeiss_job.py +249 -0
- Rhapso/fusion/multiscale/aind_z1_radial_correction/__init__.py +21 -0
- Rhapso/fusion/multiscale/aind_z1_radial_correction/array_to_zarr.py +257 -0
- Rhapso/fusion/multiscale/aind_z1_radial_correction/radial_correction.py +557 -0
- Rhapso/fusion/multiscale/aind_z1_radial_correction/run_capsule.py +98 -0
- Rhapso/fusion/multiscale/aind_z1_radial_correction/utils/__init__.py +3 -0
- Rhapso/fusion/multiscale/aind_z1_radial_correction/utils/utils.py +266 -0
- Rhapso/fusion/multiscale/aind_z1_radial_correction/worker.py +89 -0
- Rhapso/fusion/multiscale_worker.py +113 -0
- Rhapso/fusion/neuroglancer_link_gen/__init__.py +8 -0
- Rhapso/fusion/neuroglancer_link_gen/dispim_link.py +235 -0
- Rhapso/fusion/neuroglancer_link_gen/exaspim_link.py +127 -0
- Rhapso/fusion/neuroglancer_link_gen/hcr_link.py +368 -0
- Rhapso/fusion/neuroglancer_link_gen/iSPIM_top.py +47 -0
- Rhapso/fusion/neuroglancer_link_gen/link_utils.py +239 -0
- Rhapso/fusion/neuroglancer_link_gen/main.py +299 -0
- Rhapso/fusion/neuroglancer_link_gen/ng_layer.py +1434 -0
- Rhapso/fusion/neuroglancer_link_gen/ng_state.py +1123 -0
- Rhapso/fusion/neuroglancer_link_gen/parsers.py +336 -0
- Rhapso/fusion/neuroglancer_link_gen/raw_link.py +116 -0
- Rhapso/fusion/neuroglancer_link_gen/utils/__init__.py +4 -0
- Rhapso/fusion/neuroglancer_link_gen/utils/shader_utils.py +85 -0
- Rhapso/fusion/neuroglancer_link_gen/utils/transfer.py +43 -0
- Rhapso/fusion/neuroglancer_link_gen/utils/utils.py +303 -0
- Rhapso/fusion/neuroglancer_link_gen_worker.py +30 -0
- Rhapso/matching/__init__.py +0 -0
- Rhapso/matching/load_and_transform_points.py +458 -0
- Rhapso/matching/ransac_matching.py +544 -0
- Rhapso/matching/save_matches.py +120 -0
- Rhapso/matching/xml_parser.py +302 -0
- Rhapso/pipelines/__init__.py +0 -0
- Rhapso/pipelines/ray/__init__.py +0 -0
- Rhapso/pipelines/ray/aws/__init__.py +0 -0
- Rhapso/pipelines/ray/aws/alignment_pipeline.py +227 -0
- Rhapso/pipelines/ray/aws/config/__init__.py +0 -0
- Rhapso/pipelines/ray/evaluation.py +71 -0
- Rhapso/pipelines/ray/interest_point_detection.py +137 -0
- Rhapso/pipelines/ray/interest_point_matching.py +110 -0
- Rhapso/pipelines/ray/local/__init__.py +0 -0
- Rhapso/pipelines/ray/local/alignment_pipeline.py +167 -0
- Rhapso/pipelines/ray/matching_stats.py +104 -0
- Rhapso/pipelines/ray/param/__init__.py +0 -0
- Rhapso/pipelines/ray/solver.py +120 -0
- Rhapso/pipelines/ray/split_dataset.py +78 -0
- Rhapso/solver/__init__.py +0 -0
- Rhapso/solver/compute_tiles.py +562 -0
- Rhapso/solver/concatenate_models.py +116 -0
- Rhapso/solver/connected_graphs.py +111 -0
- Rhapso/solver/data_prep.py +181 -0
- Rhapso/solver/global_optimization.py +410 -0
- Rhapso/solver/model_and_tile_setup.py +109 -0
- Rhapso/solver/pre_align_tiles.py +323 -0
- Rhapso/solver/save_results.py +97 -0
- Rhapso/solver/view_transforms.py +75 -0
- Rhapso/solver/xml_to_dataframe_solver.py +213 -0
- Rhapso/split_dataset/__init__.py +0 -0
- Rhapso/split_dataset/compute_grid_rules.py +78 -0
- Rhapso/split_dataset/save_points.py +101 -0
- Rhapso/split_dataset/save_xml.py +377 -0
- Rhapso/split_dataset/split_images.py +537 -0
- Rhapso/split_dataset/xml_to_dataframe_split.py +219 -0
- rhapso-0.1.92.dist-info/METADATA +39 -0
- rhapso-0.1.92.dist-info/RECORD +101 -0
- rhapso-0.1.92.dist-info/WHEEL +5 -0
- rhapso-0.1.92.dist-info/licenses/LICENSE +21 -0
- rhapso-0.1.92.dist-info/top_level.txt +2 -0
- tests/__init__.py +1 -0
- tests/test_detection.py +17 -0
- tests/test_matching.py +21 -0
- tests/test_solving.py +21 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import xml.etree.ElementTree as ET
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
XML to Dataframe Solver is a Solver specific XML parsing tool
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
class XMLToDataFrameSolver:
|
|
9
|
+
def __init__(self, xml_file):
|
|
10
|
+
self.xml_content = xml_file
|
|
11
|
+
|
|
12
|
+
def parse_image_loader_zarr(self, root):
|
|
13
|
+
"""
|
|
14
|
+
Parses image loader configuration from a Zarr file's XML structure and constructs a DataFrame containing the
|
|
15
|
+
metadata for each image group.
|
|
16
|
+
"""
|
|
17
|
+
image_loader_data = []
|
|
18
|
+
|
|
19
|
+
for il in root.findall(".//ImageLoader/zgroups/zgroup"):
|
|
20
|
+
view_setup = il.get("setup")
|
|
21
|
+
timepoint = il.get("timepoint")
|
|
22
|
+
file_path = il.find("path").text if il.find("path") is not None else None
|
|
23
|
+
|
|
24
|
+
channel = file_path.split("_ch_", 1)[1].split(".ome.zarr", 1)[0]
|
|
25
|
+
|
|
26
|
+
image_loader_data.append(
|
|
27
|
+
{
|
|
28
|
+
"view_setup": view_setup,
|
|
29
|
+
"timepoint": timepoint,
|
|
30
|
+
"series": 1,
|
|
31
|
+
"channel": channel,
|
|
32
|
+
"file_path": file_path,
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
return pd.DataFrame(image_loader_data)
|
|
37
|
+
|
|
38
|
+
def parse_image_loader_tiff(self, root):
|
|
39
|
+
"""
|
|
40
|
+
Parses image loader configuration from a TIFF file's XML structure and constructs a DataFrame containing
|
|
41
|
+
metadata for each image group.
|
|
42
|
+
"""
|
|
43
|
+
image_loader_data = []
|
|
44
|
+
|
|
45
|
+
# Ensure that file mappings are present in the XML
|
|
46
|
+
if not root.findall(".//ImageLoader/files/FileMapping"):
|
|
47
|
+
raise Exception("There are no files in this XML")
|
|
48
|
+
|
|
49
|
+
# Check for required labels in the XML
|
|
50
|
+
if not self.check_labels(root):
|
|
51
|
+
raise Exception("Required labels do not exist")
|
|
52
|
+
|
|
53
|
+
# Validate that the lengths of view setups, registrations, and tiles match
|
|
54
|
+
if not self.check_length(root):
|
|
55
|
+
raise Exception(
|
|
56
|
+
"The amount of view setups, view registrations, and tiles do not match"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Iterate over each file mapping in the XML
|
|
60
|
+
for fm in root.findall(".//ImageLoader/files/FileMapping"):
|
|
61
|
+
view_setup = fm.get("view_setup")
|
|
62
|
+
timepoint = fm.get("timepoint")
|
|
63
|
+
series = fm.get("series")
|
|
64
|
+
channel = fm.get("channel")
|
|
65
|
+
file_path = fm.find("file").text if fm.find("file") is not None else None
|
|
66
|
+
|
|
67
|
+
image_loader_data.append(
|
|
68
|
+
{
|
|
69
|
+
"view_setup": view_setup,
|
|
70
|
+
"timepoint": timepoint,
|
|
71
|
+
"series": series,
|
|
72
|
+
"channel": channel,
|
|
73
|
+
"file_path": file_path,
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Convert the list to a DataFrame and return
|
|
78
|
+
return pd.DataFrame(image_loader_data)
|
|
79
|
+
|
|
80
|
+
def parse_image_loader_split_zarr(self):
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
def route_image_loader(self, root):
|
|
84
|
+
"""
|
|
85
|
+
Directs the XML parsing process based on the image loader format specified in the XML.
|
|
86
|
+
"""
|
|
87
|
+
format_node = root.find(".//ImageLoader")
|
|
88
|
+
format_type = format_node.get("format")
|
|
89
|
+
|
|
90
|
+
if "filemap" in format_type:
|
|
91
|
+
return self.parse_image_loader_tiff(root)
|
|
92
|
+
else:
|
|
93
|
+
return self.parse_image_loader_zarr(root)
|
|
94
|
+
|
|
95
|
+
def parse_view_setups(self, root):
|
|
96
|
+
"""
|
|
97
|
+
Parses the view setups from an XML structure and constructs a DataFrame containing metadata for each view setup.
|
|
98
|
+
"""
|
|
99
|
+
viewsetups_data = []
|
|
100
|
+
|
|
101
|
+
for vs in root.findall(".//ViewSetup"):
|
|
102
|
+
id_ = vs.find("id").text
|
|
103
|
+
# name = vs.find("name").text
|
|
104
|
+
name = vs.findtext("name")
|
|
105
|
+
size = vs.find("size").text
|
|
106
|
+
voxel_unit = vs.find(".//voxelSize/unit").text
|
|
107
|
+
voxel_size = " ".join(vs.find(".//voxelSize/size").text.split())
|
|
108
|
+
attributes = {attr.tag: attr.text for attr in vs.find("attributes")}
|
|
109
|
+
viewsetups_data.append(
|
|
110
|
+
{
|
|
111
|
+
"id": id_,
|
|
112
|
+
"name": name,
|
|
113
|
+
"size": size,
|
|
114
|
+
"voxel_unit": voxel_unit,
|
|
115
|
+
"voxel_size": voxel_size,
|
|
116
|
+
**attributes,
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
return pd.DataFrame(viewsetups_data)
|
|
120
|
+
|
|
121
|
+
def parse_view_registrations(self, root):
|
|
122
|
+
"""
|
|
123
|
+
Parses view registrations from an XML structure and constructs a DataFrame containing registration metadata
|
|
124
|
+
for each view.
|
|
125
|
+
"""
|
|
126
|
+
viewregistrations_data = []
|
|
127
|
+
for vr in root.findall(".//ViewRegistration"):
|
|
128
|
+
timepoint = vr.get("timepoint")
|
|
129
|
+
setup = vr.get("setup")
|
|
130
|
+
|
|
131
|
+
for vt in vr.findall(".//ViewTransform"):
|
|
132
|
+
affine_text = (
|
|
133
|
+
vt.find("affine").text.replace("\n", "").replace(" ", ", ")
|
|
134
|
+
)
|
|
135
|
+
viewregistrations_data.append(
|
|
136
|
+
{
|
|
137
|
+
"timepoint": timepoint,
|
|
138
|
+
"setup": setup,
|
|
139
|
+
"type": vt.get("type"),
|
|
140
|
+
"name": vt.find("Name").text.strip(),
|
|
141
|
+
"affine": affine_text,
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
return pd.DataFrame(viewregistrations_data)
|
|
145
|
+
|
|
146
|
+
def parse_view_interest_points(self, root):
|
|
147
|
+
"""
|
|
148
|
+
Parses interest points data from an XML structure and constructs a DataFrame containing metadata and paths
|
|
149
|
+
for each set of interest points.
|
|
150
|
+
"""
|
|
151
|
+
view_interest_points_data = []
|
|
152
|
+
|
|
153
|
+
for vip in root.findall(".//ViewInterestPointsFile"):
|
|
154
|
+
timepoint = vip.get("timepoint")
|
|
155
|
+
setup = vip.get("setup")
|
|
156
|
+
label = vip.get("label")
|
|
157
|
+
params = vip.get("params")
|
|
158
|
+
path = vip.text.strip() if vip.text is not None else None
|
|
159
|
+
view_interest_points_data.append(
|
|
160
|
+
{
|
|
161
|
+
"timepoint": timepoint,
|
|
162
|
+
"setup": setup,
|
|
163
|
+
"label": label,
|
|
164
|
+
"params": params,
|
|
165
|
+
"path": path,
|
|
166
|
+
}
|
|
167
|
+
)
|
|
168
|
+
return pd.DataFrame(view_interest_points_data)
|
|
169
|
+
|
|
170
|
+
def check_labels(self, root):
|
|
171
|
+
"""
|
|
172
|
+
Verifies the presence of required XML labels including bounding boxes, point spread functions,
|
|
173
|
+
stitching results, and intensity adjustments.
|
|
174
|
+
"""
|
|
175
|
+
labels = True
|
|
176
|
+
if root.find(".//BoundingBoxes") is None:
|
|
177
|
+
labels = False
|
|
178
|
+
if root.find(".//PointSpreadFunctions") is None:
|
|
179
|
+
labels = False
|
|
180
|
+
if root.find(".//StitchingResults") is None:
|
|
181
|
+
labels = False
|
|
182
|
+
if root.find(".//IntensityAdjustments") is None:
|
|
183
|
+
labels = False
|
|
184
|
+
|
|
185
|
+
return labels
|
|
186
|
+
|
|
187
|
+
def check_length(self, root):
|
|
188
|
+
"""
|
|
189
|
+
Validates that the count of elements within the XML structure aligns with expected relationships
|
|
190
|
+
between file mappings, view setups, and view registrations.
|
|
191
|
+
"""
|
|
192
|
+
length = True
|
|
193
|
+
if len(root.findall(".//ImageLoader/files/FileMapping")) != len(root.findall(".//ViewRegistration")) or \
|
|
194
|
+
len(root.findall(".//ViewSetup")) != len(root.findall(".//ViewRegistration")) * (1 / 2):
|
|
195
|
+
length = False
|
|
196
|
+
return length
|
|
197
|
+
|
|
198
|
+
def run(self):
|
|
199
|
+
"""
|
|
200
|
+
Executes the entry point of the script.
|
|
201
|
+
"""
|
|
202
|
+
root = ET.fromstring(self.xml_content)
|
|
203
|
+
image_loader_df = self.route_image_loader(root)
|
|
204
|
+
view_setups_df = self.parse_view_setups(root)
|
|
205
|
+
view_registrations_df = self.parse_view_registrations(root)
|
|
206
|
+
view_interest_points_df = self.parse_view_interest_points(root)
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
"image_loader": image_loader_df,
|
|
210
|
+
"view_setups": view_setups_df,
|
|
211
|
+
"view_registrations": view_registrations_df,
|
|
212
|
+
"view_interest_points": view_interest_points_df,
|
|
213
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Compute Grid Rules calculates grid-safe values that align with the datasets coarsest resolution. It computes a minimal per-axis step size,
|
|
5
|
+
validates that resolutions are effectively integers, then rounds each target size/overlap up to the nearest multiple of that step.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
class ComputeGridRules:
|
|
9
|
+
def __init__(self, data_global, target_image_size, target_overlap):
|
|
10
|
+
self.view_setups_df = data_global['view_setups']
|
|
11
|
+
self.target_image_size = target_image_size
|
|
12
|
+
self.target_overlap = target_overlap
|
|
13
|
+
|
|
14
|
+
def closest_larger_long_divisible_by(self, a, b):
|
|
15
|
+
"""
|
|
16
|
+
Find the smallest integer ≥ a that is divisible by b
|
|
17
|
+
"""
|
|
18
|
+
if b <= 0:
|
|
19
|
+
raise ValueError("b must be > 0")
|
|
20
|
+
|
|
21
|
+
if a == b or a == 0 or a % b == 0:
|
|
22
|
+
return int(a)
|
|
23
|
+
|
|
24
|
+
return int(a + b - (a % b))
|
|
25
|
+
|
|
26
|
+
def find_min_step_size(self):
|
|
27
|
+
"""
|
|
28
|
+
Compute the minimal integer step size per axis (X,Y,Z) that is compatible with the chosen lowest resolution
|
|
29
|
+
"""
|
|
30
|
+
lowest_resolution=(64.0, 64.0, 64.0)
|
|
31
|
+
min_step_size = [1, 1, 1]
|
|
32
|
+
|
|
33
|
+
for d, r in enumerate(lowest_resolution):
|
|
34
|
+
frac = abs(r % 1.0)
|
|
35
|
+
|
|
36
|
+
if frac > 1e-3 and (1.0 - frac) > 1e-3:
|
|
37
|
+
raise RuntimeError("Downsampling has a fraction > 0.001; cannot split dataset.")
|
|
38
|
+
|
|
39
|
+
min_step_size[d] = math.lcm(min_step_size[d], int(round(r)))
|
|
40
|
+
|
|
41
|
+
return min_step_size
|
|
42
|
+
|
|
43
|
+
def collect_image_sizes(self):
|
|
44
|
+
"""
|
|
45
|
+
Tally how many times each raw size string appears in view setups and compute the per-axis minimum dimensions
|
|
46
|
+
across all rows
|
|
47
|
+
"""
|
|
48
|
+
sizes = {}
|
|
49
|
+
min_size = None
|
|
50
|
+
|
|
51
|
+
for _, row in self.view_setups_df.iterrows():
|
|
52
|
+
dims = row['size']
|
|
53
|
+
sizes[dims] = sizes.get(dims, 0) + 1
|
|
54
|
+
dims = [int(x) for x in dims.split()]
|
|
55
|
+
if min_size is None:
|
|
56
|
+
min_size = dims[:]
|
|
57
|
+
else:
|
|
58
|
+
for d in range(len(dims)):
|
|
59
|
+
min_size[d] = min(min_size[d], dims[d])
|
|
60
|
+
|
|
61
|
+
return (sizes, min_size)
|
|
62
|
+
|
|
63
|
+
def run(self):
|
|
64
|
+
"""
|
|
65
|
+
Executes the entry point of the script.
|
|
66
|
+
"""
|
|
67
|
+
# image_sizes, min_size = self.collect_image_sizes()
|
|
68
|
+
min_step_size = self.find_min_step_size()
|
|
69
|
+
|
|
70
|
+
sx = self.closest_larger_long_divisible_by(self.target_image_size[0], min_step_size[0])
|
|
71
|
+
sy = self.closest_larger_long_divisible_by(self.target_image_size[1], min_step_size[1])
|
|
72
|
+
sz = self.closest_larger_long_divisible_by(self.target_image_size[2], min_step_size[2])
|
|
73
|
+
|
|
74
|
+
ox = self.closest_larger_long_divisible_by(self.target_overlap[0], min_step_size[0])
|
|
75
|
+
oy = self.closest_larger_long_divisible_by(self.target_overlap[1], min_step_size[1])
|
|
76
|
+
oz = self.closest_larger_long_divisible_by(self.target_overlap[2], min_step_size[2])
|
|
77
|
+
|
|
78
|
+
return (sx, sy, sz), (ox, oy, oz), min_step_size
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import zarr
|
|
2
|
+
import s3fs
|
|
3
|
+
import numpy as np
|
|
4
|
+
import boto3
|
|
5
|
+
import json
|
|
6
|
+
|
|
7
|
+
class SavePoints:
|
|
8
|
+
def __init__(self, label_entries, n5_prefix):
|
|
9
|
+
self.label_entries = label_entries
|
|
10
|
+
self.n5_prefix = n5_prefix
|
|
11
|
+
self.s3_filesystem = s3fs.S3FileSystem()
|
|
12
|
+
self.default_block_size = 300000
|
|
13
|
+
|
|
14
|
+
def write_json_to_s3(self, id_dataset_path, loc_dataset_path, attributes):
|
|
15
|
+
"""
|
|
16
|
+
Write attributes file into both the ID and LOC dataset directories on S3
|
|
17
|
+
"""
|
|
18
|
+
bucket, key = id_dataset_path.replace("s3://", "", 1).split("/", 1)
|
|
19
|
+
json_path = key + '/attributes.json'
|
|
20
|
+
json_bytes = json.dumps(attributes).encode('utf-8')
|
|
21
|
+
s3 = boto3.client('s3')
|
|
22
|
+
s3.put_object(Bucket=bucket, Key=json_path, Body=json_bytes)
|
|
23
|
+
|
|
24
|
+
bucket, key = loc_dataset_path.replace("s3://", "", 1).split("/", 1)
|
|
25
|
+
json_path = key + '/attributes.json'
|
|
26
|
+
json_bytes = json.dumps(attributes).encode('utf-8')
|
|
27
|
+
s3 = boto3.client('s3')
|
|
28
|
+
s3.put_object(Bucket=bucket, Key=json_path, Body=json_bytes)
|
|
29
|
+
|
|
30
|
+
def save_interest_points_to_n5(self):
|
|
31
|
+
for label_entry in self.label_entries:
|
|
32
|
+
n5_path = label_entry['ip_list']['n5_path']
|
|
33
|
+
|
|
34
|
+
if self.n5_prefix.startswith("s3://"):
|
|
35
|
+
output_path = self.n5_prefix + n5_path + "/interestpoints"
|
|
36
|
+
store = s3fs.S3Map(root=output_path, s3=self.s3_filesystem, check=False)
|
|
37
|
+
root = zarr.group(store=store, overwrite=False)
|
|
38
|
+
else:
|
|
39
|
+
output_path = self.n5_prefix + n5_path + "/interestpoints"
|
|
40
|
+
store = zarr.N5Store(output_path)
|
|
41
|
+
root = zarr.group(store, overwrite=False)
|
|
42
|
+
|
|
43
|
+
id_dataset = "id"
|
|
44
|
+
loc_dataset = "loc"
|
|
45
|
+
|
|
46
|
+
if self.n5_prefix.startswith("s3://"):
|
|
47
|
+
id_path = f"{output_path}/id"
|
|
48
|
+
loc_path = f"{output_path}/loc"
|
|
49
|
+
attrs_dict = dict(root.attrs)
|
|
50
|
+
self.write_json_to_s3(id_path, loc_path, attrs_dict)
|
|
51
|
+
|
|
52
|
+
interest_points = [point[1] for point in label_entry['ip_list']['interest_points']]
|
|
53
|
+
interest_point_ids = np.arange(len(interest_points), dtype=np.uint64).reshape(-1, 1)
|
|
54
|
+
n = 3
|
|
55
|
+
|
|
56
|
+
if len(interest_points) > 0:
|
|
57
|
+
if id_dataset in root:
|
|
58
|
+
del root[id_dataset]
|
|
59
|
+
root.create_dataset(
|
|
60
|
+
id_dataset,
|
|
61
|
+
data=interest_point_ids,
|
|
62
|
+
dtype='u8',
|
|
63
|
+
chunks=(self.default_block_size,),
|
|
64
|
+
compressor=zarr.GZip()
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
if loc_dataset in root:
|
|
68
|
+
del root[loc_dataset]
|
|
69
|
+
root.create_dataset(
|
|
70
|
+
loc_dataset,
|
|
71
|
+
data=interest_points,
|
|
72
|
+
dtype='f8',
|
|
73
|
+
chunks=(self.default_block_size, n),
|
|
74
|
+
compressor=zarr.GZip()
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# save as empty lists
|
|
78
|
+
else:
|
|
79
|
+
if id_dataset in root:
|
|
80
|
+
del root[id_dataset]
|
|
81
|
+
root.create_dataset(
|
|
82
|
+
id_dataset,
|
|
83
|
+
shape=(0,),
|
|
84
|
+
dtype='u8',
|
|
85
|
+
chunks=(1,),
|
|
86
|
+
compressor=zarr.GZip()
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
if loc_dataset in root:
|
|
90
|
+
del root[loc_dataset]
|
|
91
|
+
root.create_dataset(
|
|
92
|
+
loc_dataset,
|
|
93
|
+
shape=(0,),
|
|
94
|
+
dtype='f8',
|
|
95
|
+
chunks=(1,),
|
|
96
|
+
compressor=zarr.GZip()
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
def run(self):
|
|
100
|
+
self.save_interest_points_to_n5()
|
|
101
|
+
return 1
|