@jax-data-science/sci-image-visualizer 0.3.1 → 0.3.2

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.
@@ -1002,6 +1002,62 @@ class MultiPolygon {
1002
1002
  this.polygons = [];
1003
1003
  }
1004
1004
  }
1005
+ /**
1006
+ * Rebuild a plain-object `bounds` as the class instance the renderers expect
1007
+ * (jit-ui#124).
1008
+ *
1009
+ * Regions that arrive as JSON — a host's server response, a `structuredClone`,
1010
+ * anything that has been through `JSON.parse` — carry a `bounds` that has the
1011
+ * right *fields* but not the right *prototype*. The renderers disagree about
1012
+ * whether that is acceptable: `Region.getShape()` (Plotly) and the napari
1013
+ * overlay duck-type the bounds, while the OpenSeadragon overlay discriminates
1014
+ * with `bounds instanceof Rectangle`. So a JSON region drew in Heatmap mode and
1015
+ * silently vanished in Image mode. `instanceof` also gates the store's own
1016
+ * geometry de-duplication, `moveRegion`, and the GeoJSON export — a JSON region
1017
+ * is undraggable and absent from a save in *every* mode.
1018
+ *
1019
+ * Rather than duck-type ~20 call sites, the store normalizes here on the way in,
1020
+ * so everything downstream can keep relying on `instanceof`. Values that are
1021
+ * already instances are returned **by reference**, untouched: overlays and tools
1022
+ * hold onto the bounds they created and mutate them in place during a drag.
1023
+ */
1024
+ function hydrateBounds(bounds) {
1025
+ if (!bounds ||
1026
+ bounds instanceof Rectangle ||
1027
+ bounds instanceof Polygon ||
1028
+ bounds instanceof MultiPolygon) {
1029
+ return bounds;
1030
+ }
1031
+ if (Array.isArray(bounds.polygons)) {
1032
+ const multi = new MultiPolygon();
1033
+ multi.polygons = bounds.polygons.map((part) => hydratePolygon(part));
1034
+ return multi;
1035
+ }
1036
+ if ('npoints' in bounds || 'xpoints' in bounds) {
1037
+ return hydratePolygon(bounds);
1038
+ }
1039
+ if ('width' in bounds && 'height' in bounds) {
1040
+ return Object.assign(new Rectangle(), bounds);
1041
+ }
1042
+ // Nothing recognisable — hand it back rather than coerce it into the wrong
1043
+ // geometry. It renders nowhere either way, but a caller can still inspect it.
1044
+ return bounds;
1045
+ }
1046
+ /** {@link hydrateBounds} for one polygon, deriving the fields a lean serializer
1047
+ * omits: JIT's Java `PolygonSerializer` writes only `npoints`/`xpoints`/
1048
+ * `ypoints`, while the GeoJSON export reads `coordinates` and the overlays read
1049
+ * `closed`. */
1050
+ function hydratePolygon(raw) {
1051
+ if (raw instanceof Polygon)
1052
+ return raw;
1053
+ const polygon = Object.assign(new Polygon(), raw);
1054
+ polygon.xpoints = [...(raw.xpoints ?? [])];
1055
+ polygon.ypoints = [...(raw.ypoints ?? [])];
1056
+ polygon.npoints = raw.npoints ?? polygon.xpoints.length;
1057
+ polygon.coordinates = raw.coordinates ?? polygon.xpoints.map((x, i) => [x, polygon.ypoints[i]]);
1058
+ polygon.closed = raw.closed ?? true;
1059
+ return polygon;
1060
+ }
1005
1061
 
1006
1062
  /**
1007
1063
  * Preset annotation classes (jit-ui#70).
@@ -10359,6 +10415,10 @@ class RegionStore {
10359
10415
  region.id = this.nextId++;
10360
10416
  if (region.name == null)
10361
10417
  region.name = `shape${region.id}`;
10418
+ // JSON in, class instances out — everything downstream (the overlays'
10419
+ // rendering, geometry de-dup, moveRegion, GeoJSON export) discriminates
10420
+ // the bounds with `instanceof` (jit-ui#124).
10421
+ region.bounds = hydrateBounds(region.bounds);
10362
10422
  }
10363
10423
  this.applyClassificationColors(regions);
10364
10424
  this.isRegionSavedOn = isRegionSaveOn;
@@ -10511,6 +10571,7 @@ class RegionStore {
10511
10571
  if (region.name == null)
10512
10572
  region.name = `shape${region.id}`;
10513
10573
  region.z = z;
10574
+ region.bounds = hydrateBounds(region.bounds); // jit-ui#124
10514
10575
  }
10515
10576
  this.applyClassificationColors(regions);
10516
10577
  return regions.slice();
@@ -10762,6 +10823,7 @@ class RegionStore {
10762
10823
  region.id = this.nextId++;
10763
10824
  if (region.name == null)
10764
10825
  region.name = `shape${region.id}`;
10826
+ region.bounds = hydrateBounds(region.bounds); // jit-ui#124
10765
10827
  // A region drawn on a stack belongs to the slice currently displayed, so
10766
10828
  // it saves/reloads on that slice (jit-ui#93). No-op for single-plane images
10767
10829
  // (currentSliceZ stays 0).
@@ -22098,5 +22160,5 @@ function provideVisualization() {
22098
22160
  * Generated bundle index. Do not edit.
22099
22161
  */
22100
22162
 
22101
- export { ALL_TOOLBAR_TOOLS, CELL_SEGMENTER, CHANNEL_HISTOGRAM_API, CellposeSegmenterService, ChannelHistogramComponent, DEFAULT_FALLBACK_PALETTE, DEFAULT_SAM_MODEL_ID, HexColorPickerComponent, IMAGE_STATE_PORT, INSTANCE_SEGMENTER, ImageConverterService, LUT_COLORS, MultiPolygon, NAPARI_DECIMATE_OPTIONS, NAPARI_DEFAULT_DECIMATE, PLOT_TYPE_DESCRIPTORS, PREFERENCES_PORT, PlotType, Polygon, ProcessingImage, REGION_EDITOR_API, REGION_IO_PORT, Rectangle, Region, RegionEditorComponent, RoutingVisualizerService, SAM_MODELS, SEMANTIC_SEGMENTER, ShapeSelection, TILE_ACCESS_PORT, TOOLBAR_TOOLS, VISUALIZER, VIZ_CONFIG, ViewerFeature, VisualizationModule, VisualizerComponent, capabilitiesOf, cropImage, defaultPresetSet, getDefaultSamModelId, getOrtWasmBase, getPlotTypeDescriptor, getSamModel, isEmptyPresetSet, isNapari3d, isNapariIsosurface, isNapariScatter, isNapariScatter3d, isNapariSurface, isNapariVolume, isSamModelReady, isThreeDimensional, provideVisualization, setDefaultSamModel, setOrtWasmBase, setSamModelUrls, sortToolContributions, visibleToolContributions };
22163
+ export { ALL_TOOLBAR_TOOLS, CELL_SEGMENTER, CHANNEL_HISTOGRAM_API, CellposeSegmenterService, ChannelHistogramComponent, DEFAULT_FALLBACK_PALETTE, DEFAULT_SAM_MODEL_ID, HexColorPickerComponent, IMAGE_STATE_PORT, INSTANCE_SEGMENTER, ImageConverterService, LUT_COLORS, MultiPolygon, NAPARI_DECIMATE_OPTIONS, NAPARI_DEFAULT_DECIMATE, PLOT_TYPE_DESCRIPTORS, PREFERENCES_PORT, PlotType, Polygon, ProcessingImage, REGION_EDITOR_API, REGION_IO_PORT, Rectangle, Region, RegionEditorComponent, RoutingVisualizerService, SAM_MODELS, SEMANTIC_SEGMENTER, ShapeSelection, TILE_ACCESS_PORT, TOOLBAR_TOOLS, VISUALIZER, VIZ_CONFIG, ViewerFeature, VisualizationModule, VisualizerComponent, capabilitiesOf, cropImage, defaultPresetSet, getDefaultSamModelId, getOrtWasmBase, getPlotTypeDescriptor, getSamModel, hydrateBounds, isEmptyPresetSet, isNapari3d, isNapariIsosurface, isNapariScatter, isNapariScatter3d, isNapariSurface, isNapariVolume, isSamModelReady, isThreeDimensional, provideVisualization, setDefaultSamModel, setOrtWasmBase, setSamModelUrls, sortToolContributions, visibleToolContributions };
22102
22164
  //# sourceMappingURL=jax-data-science-sci-image-visualizer.mjs.map