fusion-tools 2.2.3__tar.gz → 2.2.5__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.3 → fusion_tools-2.2.5}/PKG-INFO +1 -1
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/setup.py +1 -1
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/components/maps.py +1 -3
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/components/segmentation.py +142 -5
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/feature_extraction.py +1 -1
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/utils/shapes.py +9 -22
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/visualization/components.py +6 -7
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools.egg-info/PKG-INFO +1 -1
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/LICENSE +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/README.md +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/pyproject.toml +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/setup.cfg +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/__init__.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/components/__init__.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/components/tools.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/dataset.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/handler.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/tileserver.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/utils/__init__.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/utils/omics.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/utils/stats.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/visualization/__init__.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools/visualization/vis_utils.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools.egg-info/SOURCES.txt +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools.egg-info/dependency_links.txt +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools.egg-info/requires.txt +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/src/fusion_tools.egg-info/top_level.txt +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_classification_model.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_custom_component.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_dataset_classes.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_extract_nested_prop.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_feature_annotation.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_feature_extraction.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_generate_property_dict.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_get_gene_info.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_hra_viewer.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_image_overlay.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_model_train.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_multiframe_rgb.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_multiframeslidemap.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_property_plotter.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_read_anndata.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_remote_slide_annotations.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_remote_tileserver.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_segmentation.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_slide_annotations.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_spatial_aggregation.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/tests/test_tile_server.py +0 -0
- {fusion_tools-2.2.3 → fusion_tools-2.2.5}/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.5",
|
|
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",
|
|
@@ -314,7 +314,7 @@ class SlideMap(MapComponent):
|
|
|
314
314
|
|
|
315
315
|
"""
|
|
316
316
|
self.js_namespace = Namespace(
|
|
317
|
-
"fusionTools","
|
|
317
|
+
"fusionTools","slideMap"
|
|
318
318
|
)
|
|
319
319
|
|
|
320
320
|
self.js_namespace.add(
|
|
@@ -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
|
|
@@ -23,10 +23,11 @@ from skimage.measure import label
|
|
|
23
23
|
import dash
|
|
24
24
|
dash._dash_renderer._set_react_version('18.2.0')
|
|
25
25
|
import dash_leaflet as dl
|
|
26
|
-
from dash import dcc, callback, ctx, ALL, MATCH, exceptions, Patch, no_update, dash_table
|
|
26
|
+
from dash import dcc, callback, ctx, ALL, MATCH, exceptions, Patch, no_update, dash_table, ClientsideFunction
|
|
27
27
|
import dash_bootstrap_components as dbc
|
|
28
28
|
import dash_mantine_components as dmc
|
|
29
29
|
from dash_extensions.enrich import DashBlueprint, html, Input, Output, State, PrefixIdTransform, MultiplexerTransform
|
|
30
|
+
from dash_extensions.javascript import Namespace
|
|
30
31
|
|
|
31
32
|
# fusion-tools imports
|
|
32
33
|
from fusion_tools.visualization.vis_utils import get_pattern_matching_value
|
|
@@ -917,6 +918,9 @@ class BulkLabels(Tool):
|
|
|
917
918
|
self.ignore_list = ignore_list
|
|
918
919
|
self.property_depth = property_depth
|
|
919
920
|
|
|
921
|
+
self.assets_folder = os.getcwd()+'/.fusion_assets/'
|
|
922
|
+
self.get_namespace()
|
|
923
|
+
|
|
920
924
|
def __str__(self):
|
|
921
925
|
return 'Bulk Labels'
|
|
922
926
|
|
|
@@ -954,6 +958,112 @@ class BulkLabels(Tool):
|
|
|
954
958
|
|
|
955
959
|
return x_scale, y_scale
|
|
956
960
|
|
|
961
|
+
def get_namespace(self):
|
|
962
|
+
"""Adding JavaScript functions to the BulkLabels Namespace
|
|
963
|
+
"""
|
|
964
|
+
self.js_namespace = Namespace(
|
|
965
|
+
"fusionTools","bulkLabels"
|
|
966
|
+
)
|
|
967
|
+
|
|
968
|
+
self.js_namespace.add(
|
|
969
|
+
name = "propertyFilter",
|
|
970
|
+
src = """
|
|
971
|
+
function(butt_click, structure_names, filter_json, map_annotations, slide_information) {
|
|
972
|
+
var returnFeature = true;
|
|
973
|
+
// Defining function to extract property value
|
|
974
|
+
function checkFilter(feature, filterItem) {
|
|
975
|
+
if (filterItem.name) {
|
|
976
|
+
var filterSubProps = filterItem.name.split(" --> ");
|
|
977
|
+
var prop_dict = feature.properties;
|
|
978
|
+
for (let i=0; i<filterSubProps.length; i++) {
|
|
979
|
+
if (filterSubProps[j] in prop_dict) {
|
|
980
|
+
var prop_dict = prop_dict[filterSubProps[j]];
|
|
981
|
+
var testVal = prop_dict;
|
|
982
|
+
} else {
|
|
983
|
+
var testVal = false;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
if (filterItem.range & testVal) {
|
|
988
|
+
if (typeof filterItem.range[0]==='number') {
|
|
989
|
+
if (testVal < filterItem.range[0]) {
|
|
990
|
+
returnFeature = returnFeature & false;
|
|
991
|
+
}
|
|
992
|
+
if (testVal > filterItem.range[1]) {
|
|
993
|
+
returnFeature = returnFeature & false;
|
|
994
|
+
}
|
|
995
|
+
} else {
|
|
996
|
+
if (filterItem.range.includes(testVal)) {
|
|
997
|
+
returnFeature = returnFeature & true;
|
|
998
|
+
} else {
|
|
999
|
+
returnFeature = returnFeature & false;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
} else {
|
|
1003
|
+
returnFeature = returnFeature & false;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
return returnFeature;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
// Reading in filters dictionary
|
|
1011
|
+
const filters = JSON.parse(filter_json);
|
|
1012
|
+
console.log(filters);
|
|
1013
|
+
|
|
1014
|
+
// Reading in annotations
|
|
1015
|
+
const annotations = JSON.parse(map_annotations);
|
|
1016
|
+
var namesList = [];
|
|
1017
|
+
for (let i = 0; i<annotations.length; i++) {
|
|
1018
|
+
namesList.push(annotations[i]["properties"]["name"]);
|
|
1019
|
+
}
|
|
1020
|
+
console.log(namesList);
|
|
1021
|
+
|
|
1022
|
+
// Getting desired annotation for left joins
|
|
1023
|
+
var baseAnnotations = {
|
|
1024
|
+
"type": "FeatureCollection",
|
|
1025
|
+
"features": []
|
|
1026
|
+
};
|
|
1027
|
+
|
|
1028
|
+
for (let i = 0; i<structure_names.length; i++) {
|
|
1029
|
+
baseAnnotations["features"].push(annotations[namesList.indexOf(structure_names[i])]);
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
// Performing filtration
|
|
1033
|
+
for (let j = 0; j < filters.length; j++) {
|
|
1034
|
+
// Checking if this is a spatial query
|
|
1035
|
+
if ("structure" in filters[j]) {
|
|
1036
|
+
var sqAnnotation = annotations[namesList.indexOf(filters[j]["structure"])];
|
|
1037
|
+
baseAnnotations.splice(i,1,sjoin(baseAnnotations[i],sqAnnotation, { how: "inner", op: filters[j]["type"] }));
|
|
1038
|
+
} else {
|
|
1039
|
+
for (let k = 0; k < baseAnnotations['features'].length; k++) {
|
|
1040
|
+
var check = checkFilter(baseAnnotations["features"], filters[j]);
|
|
1041
|
+
if (!check) {
|
|
1042
|
+
baseAnnotations['features'].splice(k,1);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
console.log(baseAnnotations['features'].length);
|
|
1048
|
+
|
|
1049
|
+
// Creating L.Marker() objects
|
|
1050
|
+
var marker_list = [];
|
|
1051
|
+
for (let j = 0; j < baseAnnotations['features'].length; j++) {
|
|
1052
|
+
var centroid = turf.centroid(turf.polygon(baseAnnotations['features'][j]['geometry']));
|
|
1053
|
+
|
|
1054
|
+
marker_list.push(
|
|
1055
|
+
L.Marker(
|
|
1056
|
+
centroid
|
|
1057
|
+
).bindPopup()
|
|
1058
|
+
);
|
|
1059
|
+
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
"""
|
|
1063
|
+
)
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
|
|
957
1067
|
def gen_layout(self, session_data:dict):
|
|
958
1068
|
"""Generating layout for BulkLabels component
|
|
959
1069
|
|
|
@@ -1254,6 +1364,32 @@ class BulkLabels(Tool):
|
|
|
1254
1364
|
Output({'type': 'bulk-labels-apply-labels','index': ALL},'disabled'),
|
|
1255
1365
|
Output({'type': 'bulk-labels-download-labels','index': ALL},'disabled')
|
|
1256
1366
|
],
|
|
1367
|
+
[
|
|
1368
|
+
State({'type': 'bulk-labels-include-structures','index': ALL},'value'),
|
|
1369
|
+
State({'type': 'bulk-labels-filter-data','index': ALL},'data'),
|
|
1370
|
+
State({'type': 'map-annotations-store','index': ALL},'data'),
|
|
1371
|
+
State({'type': 'map-slide-information','index': ALL},'data')
|
|
1372
|
+
]
|
|
1373
|
+
)(self.update_label_structures)
|
|
1374
|
+
|
|
1375
|
+
self.blueprint.clinetside_callback(
|
|
1376
|
+
ClientsideFunction(
|
|
1377
|
+
namespace = 'fusionTools',
|
|
1378
|
+
function_name = ''
|
|
1379
|
+
),
|
|
1380
|
+
[
|
|
1381
|
+
Input({'type': 'bulk-labels-update-structures','index': ALL},'n_clicks')
|
|
1382
|
+
],
|
|
1383
|
+
[
|
|
1384
|
+
Output({'type': 'bulk-labels-current-structures','index': ALL},'children'),
|
|
1385
|
+
Output({'type': 'map-marker-div','index': ALL},'children'),
|
|
1386
|
+
Output({'type': 'bulk-labels-label-source','index': ALL},'children'),
|
|
1387
|
+
Output({'type': 'bulk-labels-label-type','index': ALL},'disabled'),
|
|
1388
|
+
Output({'type': 'bulk-labels-label-text','index': ALL},'disabled'),
|
|
1389
|
+
Output({'type': 'bulk-labels-label-rationale','index': ALL},'disabled'),
|
|
1390
|
+
Output({'type': 'bulk-labels-apply-labels','index': ALL},'disabled'),
|
|
1391
|
+
Output({'type': 'bulk-labels-download-labels','index': ALL},'disabled')
|
|
1392
|
+
],
|
|
1257
1393
|
[
|
|
1258
1394
|
State({'type': 'bulk-labels-include-structures','index': ALL},'value'),
|
|
1259
1395
|
State({'type': 'bulk-labels-add-property-div','index': ALL},'children'),
|
|
@@ -1261,7 +1397,7 @@ class BulkLabels(Tool):
|
|
|
1261
1397
|
State({'type': 'map-annotations-store','index': ALL},'data'),
|
|
1262
1398
|
State({'type': 'map-slide-information','index': ALL},'data')
|
|
1263
1399
|
]
|
|
1264
|
-
)
|
|
1400
|
+
)
|
|
1265
1401
|
|
|
1266
1402
|
# Adding new property
|
|
1267
1403
|
self.blueprint.callback(
|
|
@@ -2097,9 +2233,10 @@ class BulkLabels(Tool):
|
|
|
2097
2233
|
n_marked = len(get_pattern_matching_value(current_markers))
|
|
2098
2234
|
|
|
2099
2235
|
patched_list = Patch()
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2236
|
+
for v_idx,v in enumerate(clear_click):
|
|
2237
|
+
if v:
|
|
2238
|
+
del patched_list[v_idx]
|
|
2239
|
+
break
|
|
2103
2240
|
|
|
2104
2241
|
new_structures_div = [
|
|
2105
2242
|
dbc.Alert(
|
|
@@ -156,7 +156,7 @@ class ParallelFeatureExtractor:
|
|
|
156
156
|
width = int(bbox[2] - bbox[0])
|
|
157
157
|
|
|
158
158
|
# polygon2mask expects y,x coordinates, scaled to within shape bounding box
|
|
159
|
-
scaled_coords = np.flip(np.squeeze(coords_array)-np.array([bbox[0], bbox[1]
|
|
159
|
+
scaled_coords = np.flip(np.squeeze(coords_array)-np.array([bbox[0], bbox[1]]),axis=1)
|
|
160
160
|
if np.shape(scaled_coords)[-1]==3:
|
|
161
161
|
scaled_coords = scaled_coords[:,1:]
|
|
162
162
|
|
|
@@ -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:
|
|
@@ -29,15 +29,12 @@ class Visualization:
|
|
|
29
29
|
|
|
30
30
|
components = [
|
|
31
31
|
[
|
|
32
|
-
SlideMap(
|
|
33
|
-
tile_server = LocalTileServer("/path/to/slide.svs"),
|
|
34
|
-
annotations = geojson_list
|
|
35
|
-
)
|
|
32
|
+
SlideMap()
|
|
36
33
|
],
|
|
37
34
|
[
|
|
38
35
|
[
|
|
39
|
-
OverlayOptions(
|
|
40
|
-
PropertyViewer(
|
|
36
|
+
OverlayOptions(),
|
|
37
|
+
PropertyViewer()
|
|
41
38
|
]
|
|
42
39
|
]
|
|
43
40
|
]
|
|
@@ -95,7 +92,9 @@ class Visualization:
|
|
|
95
92
|
MultiplexerTransform()
|
|
96
93
|
],
|
|
97
94
|
'external_scripts': [
|
|
98
|
-
'https://cdnjs.cloudflare.com/ajax/libs/chroma-js/2.1.0/chroma.min.js'
|
|
95
|
+
'https://cdnjs.cloudflare.com/ajax/libs/chroma-js/2.1.0/chroma.min.js',
|
|
96
|
+
'https://cdn.jsdelivr.net/npm/spatialmerge',
|
|
97
|
+
'https://cdn.jsdelivr.net/npm/@turf/turf@7/turf.min.js'
|
|
99
98
|
]
|
|
100
99
|
}
|
|
101
100
|
|
|
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
|