fusion-tools 2.2.2__tar.gz → 2.2.4__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.
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/PKG-INFO +1 -1
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/setup.py +1 -1
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/components/maps.py +0 -2
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/components/segmentation.py +20 -13
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/utils/shapes.py +9 -22
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools.egg-info/PKG-INFO +1 -1
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/LICENSE +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/README.md +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/pyproject.toml +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/setup.cfg +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/__init__.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/components/__init__.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/components/tools.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/dataset.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/feature_extraction.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/handler.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/tileserver.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/utils/__init__.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/utils/omics.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/utils/stats.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/visualization/__init__.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/visualization/components.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools/visualization/vis_utils.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools.egg-info/SOURCES.txt +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools.egg-info/dependency_links.txt +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools.egg-info/requires.txt +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/src/fusion_tools.egg-info/top_level.txt +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_classification_model.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_custom_component.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_dataset_classes.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_extract_nested_prop.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_feature_annotation.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_feature_extraction.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_generate_property_dict.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_get_gene_info.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_hra_viewer.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_image_overlay.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_model_train.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_multiframe_rgb.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_multiframeslidemap.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_property_plotter.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_read_anndata.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_remote_slide_annotations.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_remote_tileserver.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_segmentation.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_slide_annotations.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_spatial_aggregation.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_tile_server.py +0 -0
- {fusion_tools-2.2.2 → fusion_tools-2.2.4}/tests/test_visualization_component.py +0 -0
|
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setuptools.setup(
|
|
7
7
|
name="fusion-tools",
|
|
8
|
-
version="2.2.
|
|
8
|
+
version="2.2.4",
|
|
9
9
|
author="Sam Border",
|
|
10
10
|
author_email="sam.border2256@gmail.com",
|
|
11
11
|
description="Modular visualization and analysis dashboard creation for high-resolution microscopy images",
|
|
@@ -1346,8 +1346,6 @@ class MultiFrameSlideMap(SlideMap):
|
|
|
1346
1346
|
else:
|
|
1347
1347
|
frame_names = [f'Frame {i}' for i in range(len(image_metadata['frames']))]
|
|
1348
1348
|
|
|
1349
|
-
print(frame_names)
|
|
1350
|
-
print(len(image_metadata['frames']))
|
|
1351
1349
|
# This is a multi-frame image
|
|
1352
1350
|
if len(image_metadata['frames'])==3:
|
|
1353
1351
|
# Treat this as an RGB image by default
|
|
@@ -1258,7 +1258,8 @@ class BulkLabels(Tool):
|
|
|
1258
1258
|
State({'type': 'bulk-labels-include-structures','index': ALL},'value'),
|
|
1259
1259
|
State({'type': 'bulk-labels-add-property-div','index': ALL},'children'),
|
|
1260
1260
|
State({'type':'bulk-labels-spatial-query-div','index': ALL},'children'),
|
|
1261
|
-
State({'type': 'map-annotations-store','index': ALL},'data')
|
|
1261
|
+
State({'type': 'map-annotations-store','index': ALL},'data'),
|
|
1262
|
+
State({'type': 'map-slide-information','index': ALL},'data')
|
|
1262
1263
|
]
|
|
1263
1264
|
)(self.update_label_structures)
|
|
1264
1265
|
|
|
@@ -1316,7 +1317,8 @@ class BulkLabels(Tool):
|
|
|
1316
1317
|
State({'type': 'bulk-labels-label-rationale','index': ALL},'value'),
|
|
1317
1318
|
State({'type': 'bulk-labels-label-source','index': ALL},'children'),
|
|
1318
1319
|
State({'type': 'bulk-labels-label-method','index': ALL},'value'),
|
|
1319
|
-
State({'type': 'map-annotations-store','index': ALL},'data')
|
|
1320
|
+
State({'type': 'map-annotations-store','index': ALL},'data'),
|
|
1321
|
+
State({'type':'map-slide-information','index':ALL},'data')
|
|
1320
1322
|
]
|
|
1321
1323
|
)(self.apply_labels)
|
|
1322
1324
|
|
|
@@ -1592,7 +1594,7 @@ class BulkLabels(Tool):
|
|
|
1592
1594
|
|
|
1593
1595
|
return processed_filters
|
|
1594
1596
|
|
|
1595
|
-
def parse_spatial_divs(self, spatial_query_parent: list)->list:
|
|
1597
|
+
def parse_spatial_divs(self, spatial_query_parent: list, slide_information:dict)->list:
|
|
1596
1598
|
"""Parsing through parent div containing all spatial queries and returning them in list form
|
|
1597
1599
|
|
|
1598
1600
|
:param spatial_query_parent: Div containing spatial query child divs
|
|
@@ -1601,6 +1603,7 @@ class BulkLabels(Tool):
|
|
|
1601
1603
|
:rtype: list
|
|
1602
1604
|
"""
|
|
1603
1605
|
processed_queries = []
|
|
1606
|
+
x_scale = slide_information['x_scale']
|
|
1604
1607
|
if not spatial_query_parent is None:
|
|
1605
1608
|
for div in spatial_query_parent:
|
|
1606
1609
|
div_children = div['props']['children'][0]['props']['children']
|
|
@@ -1622,12 +1625,12 @@ class BulkLabels(Tool):
|
|
|
1622
1625
|
processed_queries.append({
|
|
1623
1626
|
'type': query_type,
|
|
1624
1627
|
'structure': query_structure,
|
|
1625
|
-
'distance': query_distance*
|
|
1628
|
+
'distance': query_distance*x_scale
|
|
1626
1629
|
})
|
|
1627
1630
|
|
|
1628
1631
|
return processed_queries
|
|
1629
1632
|
|
|
1630
|
-
def update_label_structures(self, update_structures_click:list, include_structures:list, filter_properties:list, spatial_queries:list, current_features:list):
|
|
1633
|
+
def update_label_structures(self, update_structures_click:list, include_structures:list, filter_properties:list, spatial_queries:list, current_features:list, slide_information:list):
|
|
1631
1634
|
"""Go through current structures and return all those that pass spatial and property filters.
|
|
1632
1635
|
|
|
1633
1636
|
:param update_structures_click: Button clicked
|
|
@@ -1650,11 +1653,13 @@ class BulkLabels(Tool):
|
|
|
1650
1653
|
include_structures = get_pattern_matching_value(include_structures)
|
|
1651
1654
|
current_features = json.loads(get_pattern_matching_value(current_features))
|
|
1652
1655
|
|
|
1656
|
+
slide_information = json.loads(get_pattern_matching_value(slide_information))
|
|
1657
|
+
|
|
1653
1658
|
include_properties = get_pattern_matching_value(filter_properties)
|
|
1654
1659
|
spatial_queries = get_pattern_matching_value(spatial_queries)
|
|
1655
1660
|
|
|
1656
1661
|
processed_filters = self.parse_filter_divs(include_properties)
|
|
1657
|
-
processed_spatial_queries = self.parse_spatial_divs(spatial_queries)
|
|
1662
|
+
processed_spatial_queries = self.parse_spatial_divs(spatial_queries, slide_information)
|
|
1658
1663
|
|
|
1659
1664
|
filtered_geojson, filtered_ref_list = process_filters_queries(processed_filters, processed_spatial_queries, include_structures, current_features)
|
|
1660
1665
|
|
|
@@ -1823,7 +1828,7 @@ class BulkLabels(Tool):
|
|
|
1823
1828
|
|
|
1824
1829
|
return values_selector
|
|
1825
1830
|
|
|
1826
|
-
def parse_marker_div(self, parent_marker_div):
|
|
1831
|
+
def parse_marker_div(self, parent_marker_div,slide_information):
|
|
1827
1832
|
"""Parse div containing markers, extracting position and data from each
|
|
1828
1833
|
|
|
1829
1834
|
:param parent_marker_div: Div containing all current Markers
|
|
@@ -1839,7 +1844,7 @@ class BulkLabels(Tool):
|
|
|
1839
1844
|
data = json.loads(p['props']['children'][-1]['props']['children'])
|
|
1840
1845
|
|
|
1841
1846
|
marker_coords.append(
|
|
1842
|
-
[coords[1]/
|
|
1847
|
+
[coords[1]/slide_information['x_scale'],coords[0]/slide_information['y_scale']]
|
|
1843
1848
|
)
|
|
1844
1849
|
marker_data.append(data)
|
|
1845
1850
|
|
|
@@ -1914,7 +1919,7 @@ class BulkLabels(Tool):
|
|
|
1914
1919
|
|
|
1915
1920
|
return current_labels
|
|
1916
1921
|
|
|
1917
|
-
def apply_labels(self, button_click, current_markers, current_data, label_type, label_text, label_rationale, label_source, label_method, current_annotations):
|
|
1922
|
+
def apply_labels(self, button_click, current_markers, current_data, label_type, label_text, label_rationale, label_source, label_method, current_annotations,slide_information):
|
|
1918
1923
|
"""Applying current label to marked structures
|
|
1919
1924
|
|
|
1920
1925
|
:param button_click: Button clicked
|
|
@@ -1954,8 +1959,9 @@ class BulkLabels(Tool):
|
|
|
1954
1959
|
current_data = json.loads(get_pattern_matching_value(current_data))
|
|
1955
1960
|
current_annotations = json.loads(get_pattern_matching_value(current_annotations))
|
|
1956
1961
|
current_markers = get_pattern_matching_value(current_markers)
|
|
1962
|
+
slide_information = json.loads(get_pattern_matching_value(slide_information))
|
|
1957
1963
|
|
|
1958
|
-
marker_positions, marker_data = self.parse_marker_div(current_markers)
|
|
1964
|
+
marker_positions, marker_data = self.parse_marker_div(current_markers,slide_information)
|
|
1959
1965
|
labeled_items = self.search_labels(marker_positions, current_data, label_type, label_text, label_method)
|
|
1960
1966
|
|
|
1961
1967
|
#TODO: Applying property to structures
|
|
@@ -2091,9 +2097,10 @@ class BulkLabels(Tool):
|
|
|
2091
2097
|
n_marked = len(get_pattern_matching_value(current_markers))
|
|
2092
2098
|
|
|
2093
2099
|
patched_list = Patch()
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2100
|
+
for v_idx,v in enumerate(clear_click):
|
|
2101
|
+
if v:
|
|
2102
|
+
del patched_list[v_idx]
|
|
2103
|
+
break
|
|
2097
2104
|
|
|
2098
2105
|
new_structures_div = [
|
|
2099
2106
|
dbc.Alert(
|
|
@@ -67,33 +67,30 @@ def load_geojson(geojson_path: str, name:Union[str,None]=None) -> dict:
|
|
|
67
67
|
with open(geojson_path,'r') as f:
|
|
68
68
|
geojson_anns = json.load(f)
|
|
69
69
|
f.close()
|
|
70
|
-
|
|
71
|
-
print(type(geojson_anns))
|
|
72
|
-
print(len(geojson_anns))
|
|
73
70
|
|
|
74
71
|
if type(geojson_anns)==list:
|
|
75
72
|
for g in geojson_anns:
|
|
76
73
|
if not 'properties' in g:
|
|
77
74
|
g['properties'] = {}
|
|
75
|
+
else:
|
|
76
|
+
if 'name' in g['properties'] and name is None:
|
|
77
|
+
name = g['properties']['name']
|
|
78
78
|
|
|
79
79
|
geo_id = uuid.uuid4().hex[:24] if not '_id' in g['properties'] else g['properties']['_id']
|
|
80
80
|
g['properties'] = g['properties'] | {'name': name if not name is None else geo_id, '_id': geo_id}
|
|
81
81
|
|
|
82
|
-
|
|
83
82
|
for f_idx, f in enumerate(g['features']):
|
|
84
83
|
f['properties'] = f['properties'] | {'name': name if not name is None else geo_id, '_id': uuid.uuid4().hex[:24], '_index': f_idx}
|
|
85
84
|
|
|
86
85
|
elif type(geojson_anns)==dict:
|
|
87
86
|
if not 'properties' in geojson_anns:
|
|
88
87
|
geojson_anns['properties'] = {}
|
|
89
|
-
geo_id = uuid.uuid4().hex[:24] if not '_id' in g['properties'] else geojson_anns['properties']['_id']
|
|
90
|
-
geojson_anns['properties'] = geojson_anns['properties'] | {'name': name if not name is None else geo_id, '_id': geo_id}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
for f_idx, f in enumerate(geojson_anns['features']):
|
|
94
|
-
f['properties'] = f['properties'] | {'name': name if not name is None else geo_id, '_id': uuid.uuid4().hex[:24], '_index': f_idx}
|
|
95
88
|
|
|
89
|
+
geo_id = uuid.uuid4().hex[:24] if not '_id' in g['properties'] else geojson_anns['properties']['_id']
|
|
90
|
+
geojson_anns['properties'] = geojson_anns['properties'] | {'name': name if not name is None else geo_id, '_id': geo_id}
|
|
96
91
|
|
|
92
|
+
for f_idx, f in enumerate(geojson_anns['features']):
|
|
93
|
+
f['properties'] = f['properties'] | {'name': name if not name is None else geo_id, '_id': uuid.uuid4().hex[:24], '_index': f_idx}
|
|
97
94
|
|
|
98
95
|
return geojson_anns
|
|
99
96
|
|
|
@@ -1016,8 +1013,6 @@ def process_filters_queries(filter_list:list, spatial_list:list, structures:list
|
|
|
1016
1013
|
structure_filtered = [gpd.GeoDataFrame.from_features(i['features']) for i in all_geo_list]
|
|
1017
1014
|
name_order = [i['properties']['name'] for i in all_geo_list]
|
|
1018
1015
|
|
|
1019
|
-
#all_names = [i['properties']['name'] for i in all_geo_list]
|
|
1020
|
-
|
|
1021
1016
|
# Now going through spatial queries
|
|
1022
1017
|
filter_reference_list = {
|
|
1023
1018
|
n: {}
|
|
@@ -1048,6 +1043,8 @@ def process_filters_queries(filter_list:list, spatial_list:list, structures:list
|
|
|
1048
1043
|
)
|
|
1049
1044
|
|
|
1050
1045
|
intermediate_gdf = intermediate_gdf.drop([i for i in ['index_left','index_right'] if i in intermediate_gdf], axis = 1)
|
|
1046
|
+
intermediate_gdf = intermediate_gdf.drop([i for i in intermediate_gdf if '_right' in i],axis=1)
|
|
1047
|
+
intermediate_gdf.columns = [i.replace('_left','') if '_left' in i else i for i in intermediate_gdf ]
|
|
1051
1048
|
|
|
1052
1049
|
remainder_structures.append(intermediate_gdf)
|
|
1053
1050
|
else:
|
|
@@ -1060,21 +1057,11 @@ def process_filters_queries(filter_list:list, spatial_list:list, structures:list
|
|
|
1060
1057
|
}
|
|
1061
1058
|
for g,name in zip(remainder_structures,name_order):
|
|
1062
1059
|
g_json = g.to_geo_dict(show_bbox=True)
|
|
1063
|
-
#feature_geos = [i['geometry'] for i in g_json['features']]
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
1060
|
filter_reference_list[name] = {
|
|
1067
1061
|
i+len(combined_geojson['features']):j['properties']['_index']
|
|
1068
1062
|
for i,j in enumerate(g_json['features'])
|
|
1069
1063
|
}
|
|
1070
1064
|
combined_geojson['features'].extend(g_json['features'])
|
|
1071
|
-
"""
|
|
1072
|
-
if len(g_json['features'])>0:
|
|
1073
|
-
for idx, i in enumerate(all_geo_list[all_names.index(name)]['features']):
|
|
1074
|
-
if i['geometry'] in feature_geos:
|
|
1075
|
-
filter_reference_list[name][len(combined_geojson['features'])] = idx
|
|
1076
|
-
combined_geojson['features'].append(g_json['features'][feature_geos.index(i['geometry'])])
|
|
1077
|
-
"""
|
|
1078
1065
|
|
|
1079
1066
|
# Going through property filters:
|
|
1080
1067
|
if len(filter_list)>0:
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|