astro-viewer 3.8.0 → 3.10.0

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.
Files changed (84) hide show
  1. package/README.md +325 -222
  2. package/dist/astroviewer.cjs +469 -198
  3. package/dist/astroviewer.cjs.map +1 -1
  4. package/dist/astroviewer.js +469 -198
  5. package/dist/astroviewer.js.map +1 -1
  6. package/dist/astroviewer.min.js +1 -1
  7. package/dist/astroviewer.min.js.map +1 -1
  8. package/lib-esm/AstroSphere.d.ts +4 -0
  9. package/lib-esm/AstroSphere.d.ts.map +1 -1
  10. package/lib-esm/AstroSphere.js +15 -0
  11. package/lib-esm/AstroSphere.js.map +1 -1
  12. package/lib-esm/AstroViewer.d.ts +4 -0
  13. package/lib-esm/AstroViewer.d.ts.map +1 -1
  14. package/lib-esm/AstroViewer.js +12 -3
  15. package/lib-esm/AstroViewer.js.map +1 -1
  16. package/lib-esm/Global.d.ts +3 -3
  17. package/lib-esm/Global.d.ts.map +1 -1
  18. package/lib-esm/Global.js +38 -16
  19. package/lib-esm/Global.js.map +1 -1
  20. package/lib-esm/index.d.ts +1 -0
  21. package/lib-esm/index.d.ts.map +1 -1
  22. package/lib-esm/index.js +0 -1
  23. package/lib-esm/index.js.map +1 -1
  24. package/lib-esm/model/Source.d.ts.map +1 -1
  25. package/lib-esm/model/Source.js +2 -1
  26. package/lib-esm/model/Source.js.map +1 -1
  27. package/lib-esm/model/catalogues/CatalogueGL.d.ts +8 -7
  28. package/lib-esm/model/catalogues/CatalogueGL.d.ts.map +1 -1
  29. package/lib-esm/model/catalogues/CatalogueGL.js +63 -86
  30. package/lib-esm/model/catalogues/CatalogueGL.js.map +1 -1
  31. package/lib-esm/model/footprints/FootprintSetGL.d.ts +1 -3
  32. package/lib-esm/model/footprints/FootprintSetGL.d.ts.map +1 -1
  33. package/lib-esm/model/footprints/FootprintSetGL.js +1 -3
  34. package/lib-esm/model/footprints/FootprintSetGL.js.map +1 -1
  35. package/lib-esm/model/grid/HealpixGrid.d.ts.map +1 -1
  36. package/lib-esm/model/grid/HealpixGrid.js +7 -1
  37. package/lib-esm/model/grid/HealpixGrid.js.map +1 -1
  38. package/lib-esm/model/hips/AllSky.d.ts.map +1 -1
  39. package/lib-esm/model/hips/AllSky.js +3 -25
  40. package/lib-esm/model/hips/AllSky.js.map +1 -1
  41. package/lib-esm/model/hips/AncestorTile.d.ts.map +1 -1
  42. package/lib-esm/model/hips/AncestorTile.js +3 -25
  43. package/lib-esm/model/hips/AncestorTile.js.map +1 -1
  44. package/lib-esm/model/hips/FitsTileLoader.d.ts +4 -0
  45. package/lib-esm/model/hips/FitsTileLoader.d.ts.map +1 -1
  46. package/lib-esm/model/hips/FitsTileLoader.js +39 -1
  47. package/lib-esm/model/hips/FitsTileLoader.js.map +1 -1
  48. package/lib-esm/model/hips/HiPS.d.ts +24 -0
  49. package/lib-esm/model/hips/HiPS.d.ts.map +1 -1
  50. package/lib-esm/model/hips/HiPS.js +153 -0
  51. package/lib-esm/model/hips/HiPS.js.map +1 -1
  52. package/lib-esm/model/hips/Tile.d.ts.map +1 -1
  53. package/lib-esm/model/hips/Tile.js +3 -25
  54. package/lib-esm/model/hips/Tile.js.map +1 -1
  55. package/lib-esm/model/hips/VisibleTilesManager.d.ts +6 -3
  56. package/lib-esm/model/hips/VisibleTilesManager.d.ts.map +1 -1
  57. package/lib-esm/model/hips/VisibleTilesManager.js.map +1 -1
  58. package/lib-esm/model/meships/MeshHiPS.d.ts +4 -4
  59. package/lib-esm/model/meships/MeshHiPS.d.ts.map +1 -1
  60. package/lib-esm/model/meships/MeshHiPS.js +28 -12
  61. package/lib-esm/model/meships/MeshHiPS.js.map +1 -1
  62. package/lib-esm/model/terra/TerraFootprintSetGL.d.ts +2 -0
  63. package/lib-esm/model/terra/TerraFootprintSetGL.d.ts.map +1 -1
  64. package/lib-esm/model/terra/TerraFootprintSetGL.js +19 -0
  65. package/lib-esm/model/terra/TerraFootprintSetGL.js.map +1 -1
  66. package/lib-esm/model/terra/TerraPointSetGL.d.ts +4 -0
  67. package/lib-esm/model/terra/TerraPointSetGL.d.ts.map +1 -1
  68. package/lib-esm/model/terra/TerraPointSetGL.js +36 -0
  69. package/lib-esm/model/terra/TerraPointSetGL.js.map +1 -1
  70. package/lib-esm/model/terra/TerraPolylineSetGL.d.ts +1 -3
  71. package/lib-esm/model/terra/TerraPolylineSetGL.d.ts.map +1 -1
  72. package/lib-esm/model/terra/TerraPolylineSetGL.js +1 -3
  73. package/lib-esm/model/terra/TerraPolylineSetGL.js.map +1 -1
  74. package/lib-esm/shader/HiPSShaderProgram.d.ts +5 -1
  75. package/lib-esm/shader/HiPSShaderProgram.d.ts.map +1 -1
  76. package/lib-esm/shader/HiPSShaderProgram.js +15 -1
  77. package/lib-esm/shader/HiPSShaderProgram.js.map +1 -1
  78. package/lib-esm/shader/ShaderManager.d.ts.map +1 -1
  79. package/lib-esm/shader/ShaderManager.js +39 -7
  80. package/lib-esm/shader/ShaderManager.js.map +1 -1
  81. package/lib-esm/utils/MouseHelper.d.ts.map +1 -1
  82. package/lib-esm/utils/MouseHelper.js +2 -1
  83. package/lib-esm/utils/MouseHelper.js.map +1 -1
  84. package/package.json +1 -1
@@ -4141,6 +4141,21 @@ class AstroSphere {
4141
4141
  }
4142
4142
  this._activeHiPS.changeFormat(format);
4143
4143
  }
4144
+ setHiPSFITSScaleFunction(scaleFunction, scaleParam) {
4145
+ if (!this._activeHiPS) {
4146
+ throw new Error("No active HiPS.");
4147
+ }
4148
+ this._activeHiPS.setFITSScaleFunction(scaleFunction, scaleParam);
4149
+ }
4150
+ getActiveHiPSFITSStretch() {
4151
+ return this._activeHiPS?.fitsStretch ?? null;
4152
+ }
4153
+ setHiPSFITSRangeMode(rangeMode) {
4154
+ if (!this._activeHiPS) {
4155
+ throw new Error("No active HiPS.");
4156
+ }
4157
+ this._activeHiPS.setFITSRangeMode(rangeMode);
4158
+ }
4144
4159
  createHiPS(hipsDescriptor) {
4145
4160
  return new HiPS_js_1.HiPS(1, [0.0, 0.0, 0.0], 0, 0, hipsDescriptor, this._webgl, this._healpixGrid);
4146
4161
  }
@@ -4823,7 +4838,7 @@ class AstroViewer {
4823
4838
  }
4824
4839
  //FOOTPRINT
4825
4840
  createFootprintSet(footprintSetName, footprintSetDescription, providerUrl, metadataManager) {
4826
- return new FootprintSetGL_js_1.FootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl, this.astroSphere.healpixGrid.visibleTilesManager);
4841
+ return new FootprintSetGL_js_1.FootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl);
4827
4842
  }
4828
4843
  showFootprintSet(footprintSet) {
4829
4844
  this.astroSphere.showFootprintSet(footprintSet);
@@ -4848,7 +4863,7 @@ class AstroViewer {
4848
4863
  this.astroSphere.deleteCatalogue(pointSet);
4849
4864
  }
4850
4865
  createTerraFootprintSet(footprintSetName, footprintSetDescription, providerUrl, metadataManager) {
4851
- return new TerraFootprintSetGL_js_1.TerraFootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl, this.astroSphere.healpixGrid.visibleTilesManager);
4866
+ return new TerraFootprintSetGL_js_1.TerraFootprintSetGL(footprintSetName, footprintSetDescription, providerUrl, metadataManager, this.webgl);
4852
4867
  }
4853
4868
  showTerraFootprintSet(footprintSet) {
4854
4869
  this.astroSphere.showFootprintSet(footprintSet);
@@ -4860,7 +4875,7 @@ class AstroViewer {
4860
4875
  this.astroSphere.deleteFootprintSet(footprintSet);
4861
4876
  }
4862
4877
  createTerraPolylineSet(polylineSetName, polylineSetDescription, providerUrl, metadataManager) {
4863
- return new TerraPolylineSetGL_js_1.TerraPolylineSetGL(polylineSetName, polylineSetDescription, providerUrl, metadataManager, this.webgl, this.astroSphere.healpixGrid.visibleTilesManager);
4878
+ return new TerraPolylineSetGL_js_1.TerraPolylineSetGL(polylineSetName, polylineSetDescription, providerUrl, metadataManager, this.webgl);
4864
4879
  }
4865
4880
  showTerraPolylineSet(polylineSet) {
4866
4881
  this.astroSphere.showPolylineSet(polylineSet);
@@ -5013,6 +5028,15 @@ class AstroViewer {
5013
5028
  changeHiPSFormat(format) {
5014
5029
  this.astroSphere.changeHiPSFormat(format);
5015
5030
  }
5031
+ setHiPSFITSScaleFunction(scaleFunction, scaleParam) {
5032
+ this.astroSphere.setHiPSFITSScaleFunction(scaleFunction, scaleParam);
5033
+ }
5034
+ getActiveHiPSFITSStretch() {
5035
+ return this.astroSphere.getActiveHiPSFITSStretch();
5036
+ }
5037
+ setHiPSFITSRangeMode(rangeMode) {
5038
+ this.astroSphere.setHiPSFITSRangeMode(rangeMode);
5039
+ }
5016
5040
  getActiveHiPSFormats() {
5017
5041
  return this.astroSphere.activeHiPS?.availableFormats ?? [];
5018
5042
  }
@@ -5753,7 +5777,7 @@ class Global {
5753
5777
  // private _gl: GL | null;
5754
5778
  _healpix;
5755
5779
  // --- config/state flags ---
5756
- _selectionnside;
5780
+ // private _selectionnside: number;
5757
5781
  // private _healpix4footprints: boolean;
5758
5782
  _useCORSProxy;
5759
5783
  _corsProxyUrl;
@@ -5761,6 +5785,7 @@ class Global {
5761
5785
  _debug;
5762
5786
  _insideSphere;
5763
5787
  _version;
5788
+ _selectionOrder;
5764
5789
  constructor() {
5765
5790
  this._useCORSProxy = Config_js_1.bootSetup.useCORSProxy;
5766
5791
  this._corsProxyUrl = Config_js_1.bootSetup.corsProxyUrl;
@@ -5769,18 +5794,34 @@ class Global {
5769
5794
  this._insideSphere = Config_js_1.bootSetup.insideView;
5770
5795
  this._version = Config_js_1.bootSetup.version;
5771
5796
  this._healpix = {};
5772
- this._selectionnside = 32;
5797
+ // this._selectionnside = 32;
5798
+ this._selectionOrder = 5;
5799
+ }
5800
+ get selectionOrder() {
5801
+ return this._selectionOrder;
5773
5802
  }
5774
5803
  init() {
5775
- console.log('Global.init()');
5804
+ console.log("Global.init()");
5776
5805
  }
5777
5806
  // --- getters/setters ---
5778
- get version() { return this._version; }
5779
- set corsProxyUrl(url) { this._corsProxyUrl = url; }
5780
- get corsProxyUrl() { return this._corsProxyUrl; }
5781
- get useCORSProxy() { return this._useCORSProxy; }
5782
- set useCORSProxy(enabled) { this._useCORSProxy = enabled; }
5783
- get debug() { return this._debug; }
5807
+ get version() {
5808
+ return this._version;
5809
+ }
5810
+ set corsProxyUrl(url) {
5811
+ this._corsProxyUrl = url;
5812
+ }
5813
+ get corsProxyUrl() {
5814
+ return this._corsProxyUrl;
5815
+ }
5816
+ get useCORSProxy() {
5817
+ return this._useCORSProxy;
5818
+ }
5819
+ set useCORSProxy(enabled) {
5820
+ this._useCORSProxy = enabled;
5821
+ }
5822
+ get debug() {
5823
+ return this._debug;
5824
+ }
5784
5825
  getHealpix(order) {
5785
5826
  if (this._healpix[order] === undefined) {
5786
5827
  // order is HEALPix "order" ⇒ nside = 2^order
@@ -5788,10 +5829,15 @@ class Global {
5788
5829
  }
5789
5830
  return this._healpix[order];
5790
5831
  }
5791
- get MAX_DECIMALS() { return this._maxDecimals; }
5792
- set insideSphere(v) { this._insideSphere = v; }
5793
- get insideSphere() { return this._insideSphere; }
5794
- get nsideForSelection() { return this._selectionnside; }
5832
+ get MAX_DECIMALS() {
5833
+ return this._maxDecimals;
5834
+ }
5835
+ set insideSphere(v) {
5836
+ this._insideSphere = v;
5837
+ }
5838
+ get insideSphere() {
5839
+ return this._insideSphere;
5840
+ }
5795
5841
  }
5796
5842
  const global = new Global();
5797
5843
  exports["default"] = global;
@@ -5883,7 +5929,6 @@ var Source_js_1 = __webpack_require__(146);
5883
5929
  Object.defineProperty(exports, "Source", ({ enumerable: true, get: function () { return Source_js_1.Source; } }));
5884
5930
  var Footprint_js_1 = __webpack_require__(2475);
5885
5931
  Object.defineProperty(exports, "Footprint", ({ enumerable: true, get: function () { return Footprint_js_1.Footprint; } }));
5886
- console.log('astroviewer UMD loaded');
5887
5932
 
5888
5933
 
5889
5934
  /***/ },
@@ -7880,7 +7925,8 @@ class Source {
7880
7925
  }
7881
7926
  computeHealpixPixel() {
7882
7927
  // Get Healpix instance from global
7883
- const healpix = Global_js_1.default.getHealpix(Global_js_1.default.nsideForSelection);
7928
+ // const healpix: Healpix = global.getHealpix(global.nsideForSelection);
7929
+ const healpix = Global_js_1.default.getHealpix(Global_js_1.default.selectionOrder);
7884
7930
  const vec3 = new healpix_1.Vec3(this._point.x, this._point.y, this._point.z);
7885
7931
  const ptg = new healpix_1.Pointing(vec3, false);
7886
7932
  this._h_pix = healpix.ang2pix(ptg, false);
@@ -8170,7 +8216,7 @@ class CatalogueGL {
8170
8216
  _oldMouseCoords;
8171
8217
  _metadataManager;
8172
8218
  _isVisible = true;
8173
- _shapeColor = '#8F00FF';
8219
+ _shapeColor = "#8F00FF";
8174
8220
  _healpixDensityMap;
8175
8221
  _providerUrl;
8176
8222
  _catalogueShaderProgram;
@@ -8179,7 +8225,7 @@ class CatalogueGL {
8179
8225
  this._webgl = webgl;
8180
8226
  this._ready = false;
8181
8227
  this._visibleTilesManager = visibleTilesManager;
8182
- this.TYPE = 'SOURCE_CATALOGUE';
8228
+ this.TYPE = "SOURCE_CATALOGUE";
8183
8229
  this._name = catalogueName;
8184
8230
  this._description = catalogueDescription;
8185
8231
  this._providerUrl = providerUrl;
@@ -8197,7 +8243,7 @@ class CatalogueGL {
8197
8243
  this._oldMouseCoords = null;
8198
8244
  this._healpixDensityMap = new Map();
8199
8245
  // this.catalogueProps = new CatalogueProps(metadataManager, defaultColor);
8200
- // call catalogueShaderProgram to init shaders if they are not yet initialised
8246
+ // call catalogueShaderProgram to init shaders if they are not yet initialised
8201
8247
  this._catalogueShaderProgram = new CatalogueShaderProgram_js_1.CatalogueShaderProgram(this._webgl);
8202
8248
  this._catalogueShaderProgram.shaderProgram;
8203
8249
  // catalogueShaderProgram.shaderProgram
@@ -8242,7 +8288,7 @@ class CatalogueGL {
8242
8288
  }
8243
8289
  return {
8244
8290
  min: Number(min),
8245
- max: Number(max)
8291
+ max: Number(max),
8246
8292
  };
8247
8293
  }
8248
8294
  get metadataManager() {
@@ -8291,7 +8337,7 @@ class CatalogueGL {
8291
8337
  const raw = Number(source.getDetailByindex(idx));
8292
8338
  const min = Number(minmax.min);
8293
8339
  const max = Number(minmax.max);
8294
- const norm = (raw - min) / Math.max(1e-12, (max - min));
8340
+ const norm = (raw - min) / Math.max(1e-12, max - min);
8295
8341
  const size = norm * (20 - 8) + 8;
8296
8342
  source.shapeSize = size;
8297
8343
  }
@@ -8328,7 +8374,7 @@ class CatalogueGL {
8328
8374
  const raw = Number(source.getDetailByindex(idx));
8329
8375
  const min = Number(minmax.min);
8330
8376
  const max = Number(minmax.max);
8331
- const norm = (raw - min) / Math.max(1e-12, (max - min));
8377
+ const norm = (raw - min) / Math.max(1e-12, max - min);
8332
8378
  // map [0,1] -> [1,-1]
8333
8379
  source.brightnessFactor = -(norm * 2 - 1);
8334
8380
  }
@@ -8358,7 +8404,7 @@ class CatalogueGL {
8358
8404
  for (let j = 0; j < in_data.length; j++) {
8359
8405
  const point = new Point_js_1.Point({
8360
8406
  raDeg: in_data[j][raDataIndex],
8361
- decDeg: in_data[j][decDataIndex]
8407
+ decDeg: in_data[j][decDataIndex],
8362
8408
  }, CoordsType_js_1.CoordsType.ASTRO);
8363
8409
  const source = new Source_js_1.Source(point, in_data[j]);
8364
8410
  // Ensure optional fields exist
@@ -8429,7 +8475,8 @@ class CatalogueGL {
8429
8475
  if (i >= 0) {
8430
8476
  this.hoveredIndexes.splice(i, 1);
8431
8477
  this.vertexCataloguePosition[base + 3] = 0.0; // not hovered
8432
- this.vertexCataloguePosition[base + 4] = this._sources[sIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8478
+ this.vertexCataloguePosition[base + 4] =
8479
+ this._sources[sIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8433
8480
  }
8434
8481
  }
8435
8482
  }
@@ -8453,7 +8500,8 @@ class CatalogueGL {
8453
8500
  if (i >= 0) {
8454
8501
  this.selectedIndexes.splice(i, 1);
8455
8502
  this.vertexCataloguePosition[base + 3] = 0.0; // not selected
8456
- this.vertexCataloguePosition[base + 4] = this._sources[sIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8503
+ this.vertexCataloguePosition[base + 4] =
8504
+ this._sources[sIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8457
8505
  }
8458
8506
  }
8459
8507
  }
@@ -8484,9 +8532,11 @@ class CatalogueGL {
8484
8532
  // hovered flag
8485
8533
  this.vertexCataloguePosition[positionIndex + 3] = 0.0;
8486
8534
  // size
8487
- this.vertexCataloguePosition[positionIndex + 4] = currSource.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8535
+ this.vertexCataloguePosition[positionIndex + 4] =
8536
+ currSource.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8488
8537
  // brightness
8489
- this.vertexCataloguePosition[positionIndex + 5] = currSource.brightnessFactor ?? 0.0;
8538
+ this.vertexCataloguePosition[positionIndex + 5] =
8539
+ currSource.brightnessFactor ?? 0.0;
8490
8540
  positionIndex += CatalogueGL.ELEM_SIZE;
8491
8541
  }
8492
8542
  this._webgl.bufferData(this._webgl.ARRAY_BUFFER, this.vertexCataloguePosition, this._webgl.STATIC_DRAW);
@@ -8520,50 +8570,8 @@ class CatalogueGL {
8520
8570
  return 0.0001;
8521
8571
  }
8522
8572
  }
8523
- checkClicking(in_mouseHelper) {
8524
- if (in_mouseHelper.x == null || in_mouseHelper.y == null || in_mouseHelper.z == null) {
8525
- console.log('CatalogueGL.checkClicking: missing mouse coords');
8526
- return [];
8527
- }
8528
- const clickedIndexes = [];
8529
- const mousePix = in_mouseHelper.computeNpix();
8530
- if (mousePix != null && this._healpixDensityMap.has(mousePix)) {
8531
- const candidates = this._healpixDensityMap.get(mousePix);
8532
- const selR = this.getSelectionRadius();
8533
- for (let i = 0; i < candidates.length; i++) {
8534
- const sourceIdx = candidates[i];
8535
- const source = this._sources[sourceIdx];
8536
- if (!source)
8537
- continue;
8538
- const dx = source.point.x - in_mouseHelper.x;
8539
- const dy = source.point.y - in_mouseHelper.y;
8540
- const dz = source.point.z - in_mouseHelper.z;
8541
- const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
8542
- if (dist <= selR) {
8543
- clickedIndexes.push(sourceIdx);
8544
- }
8545
- }
8546
- }
8547
- return clickedIndexes;
8548
- }
8549
- // private setSelectedIndexes(nextSelected: number[]) {
8550
- // const deduped = Array.from(new Set(nextSelected))
8551
- // .filter((idx) => idx >= 0 && idx < this._sources.length);
8552
- // if (this.vertexCataloguePosition.length) {
8553
- // for (const prevIdx of this.selectedIndexes) {
8554
- // if (deduped.includes(prevIdx)) continue;
8555
- // const base = prevIdx * CatalogueGL.ELEM_SIZE;
8556
- // if (base + 4 >= this.vertexCataloguePosition.length) continue;
8557
- // if (!this.hoveredIndexes.includes(prevIdx) && !this.extHoveredIndexes.includes(prevIdx)) {
8558
- // this.vertexCataloguePosition[base + 3] = 0.0;
8559
- // }
8560
- // this.vertexCataloguePosition[base + 4] = this._sources[prevIdx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8561
- // }
8562
- // }
8563
- // this.selectedIndexes = deduped;
8564
- // }
8565
8573
  setSelectedIndexes(selectedIndex) {
8566
- selectedIndex.forEach(idx => {
8574
+ selectedIndex.forEach((idx) => {
8567
8575
  if (idx < 0 || idx >= this._sources.length)
8568
8576
  return;
8569
8577
  const base = idx * CatalogueGL.ELEM_SIZE;
@@ -8572,12 +8580,14 @@ class CatalogueGL {
8572
8580
  if (this.selectedIndexes.includes(idx)) {
8573
8581
  this.selectedIndexes.splice(this.selectedIndexes.indexOf(idx), 1);
8574
8582
  this.vertexCataloguePosition[base + 3] = 0.0; // not selected
8575
- this.vertexCataloguePosition[base + 4] = this._sources[idx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8583
+ this.vertexCataloguePosition[base + 4] =
8584
+ this._sources[idx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8576
8585
  }
8577
8586
  else {
8578
8587
  this.selectedIndexes.push(idx);
8579
8588
  this.vertexCataloguePosition[base + 3] = 2.0; // selected
8580
- this.vertexCataloguePosition[base + 4] = this._sources[idx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8589
+ this.vertexCataloguePosition[base + 4] =
8590
+ this._sources[idx]?.shapeSize ?? CatalogueGL.STANDARD_SHAPE_SIZE;
8581
8591
  }
8582
8592
  });
8583
8593
  }
@@ -8594,7 +8604,7 @@ class CatalogueGL {
8594
8604
  };
8595
8605
  }
8596
8606
  const sources = [];
8597
- pickedIndexes.forEach(idx => {
8607
+ pickedIndexes.forEach((idx) => {
8598
8608
  const source = this._sources[idx];
8599
8609
  if (source)
8600
8610
  sources.push(source);
@@ -8624,7 +8634,7 @@ class CatalogueGL {
8624
8634
  }
8625
8635
  const selectionState = [];
8626
8636
  const selectedSources = [];
8627
- clickedIndexes.forEach(idx => {
8637
+ clickedIndexes.forEach((idx) => {
8628
8638
  const source = this._sources[idx];
8629
8639
  if (!source)
8630
8640
  return;
@@ -8642,31 +8652,43 @@ class CatalogueGL {
8642
8652
  const idx = this.hoveredIndexes[0];
8643
8653
  return this._sources[idx] ?? null;
8644
8654
  }
8645
- checkHovering(in_mouseHelper) {
8646
- if (in_mouseHelper.x == null || in_mouseHelper.y == null || in_mouseHelper.z == null) {
8647
- console.log('CatalogueGL.checkHovering: missing mouse coords');
8648
- return [];
8655
+ findNearestSourceIndex(in_mouseHelper) {
8656
+ if (in_mouseHelper.x == null ||
8657
+ in_mouseHelper.y == null ||
8658
+ in_mouseHelper.z == null) {
8659
+ return null;
8649
8660
  }
8650
- const hoveredIndexes = [];
8651
8661
  const mousePix = in_mouseHelper.computeNpix();
8652
- if (mousePix != null && this._healpixDensityMap.has(mousePix)) {
8653
- const candidates = this._healpixDensityMap.get(mousePix);
8654
- const selR = this.getSelectionRadius();
8655
- for (let i = 0; i < candidates.length; i++) {
8656
- const sourceIdx = candidates[i];
8657
- const source = this._sources[sourceIdx];
8658
- if (!source)
8659
- continue;
8660
- const dx = source.point.x - in_mouseHelper.x;
8661
- const dy = source.point.y - in_mouseHelper.y;
8662
- const dz = source.point.z - in_mouseHelper.z;
8663
- const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
8664
- if (dist <= selR) {
8665
- hoveredIndexes.push(sourceIdx);
8666
- }
8662
+ if (mousePix == null)
8663
+ return null;
8664
+ const candidates = this._healpixDensityMap.get(mousePix);
8665
+ if (!candidates?.length)
8666
+ return null;
8667
+ const selR = this.getSelectionRadius();
8668
+ let nearestIndex = null;
8669
+ let nearestDistance = Number.POSITIVE_INFINITY;
8670
+ for (const sourceIdx of candidates) {
8671
+ const source = this._sources[sourceIdx];
8672
+ if (!source)
8673
+ continue;
8674
+ const dx = source.point.x - in_mouseHelper.x;
8675
+ const dy = source.point.y - in_mouseHelper.y;
8676
+ const dz = source.point.z - in_mouseHelper.z;
8677
+ const dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
8678
+ if (dist <= selR && dist < nearestDistance) {
8679
+ nearestDistance = dist;
8680
+ nearestIndex = sourceIdx;
8667
8681
  }
8668
8682
  }
8669
- return hoveredIndexes;
8683
+ return nearestIndex;
8684
+ }
8685
+ checkClicking(in_mouseHelper) {
8686
+ const nearestIndex = this.findNearestSourceIndex(in_mouseHelper);
8687
+ return nearestIndex == null ? [] : [nearestIndex];
8688
+ }
8689
+ checkHovering(in_mouseHelper) {
8690
+ const nearestIndex = this.findNearestSourceIndex(in_mouseHelper);
8691
+ return nearestIndex == null ? [] : [nearestIndex];
8670
8692
  }
8671
8693
  /**
8672
8694
  * @param in_mMatrix Model matrix the current catalogue is associated to (e.g. HiPS matrix)
@@ -8713,7 +8735,8 @@ class CatalogueGL {
8713
8735
  const base = this.hoveredIndexes[k] * CatalogueGL.ELEM_SIZE;
8714
8736
  // if (this.vertexCataloguePosition[base + 3] == 2.0) continue; // selected, skip hover
8715
8737
  this.vertexCataloguePosition[base + 3] = 0.0; // not hovered
8716
- this.vertexCataloguePosition[base + 4] = this._sources[this.hoveredIndexes[k]].shapeSize; // size
8738
+ this.vertexCataloguePosition[base + 4] =
8739
+ this._sources[this.hoveredIndexes[k]].shapeSize; // size
8717
8740
  }
8718
8741
  // Hover logic on mouse move
8719
8742
  if (in_mouseHelper != null && in_mouseHelper.xyz !== this._oldMouseCoords) {
@@ -10350,11 +10373,9 @@ class FootprintSetGL {
10350
10373
  _metadataManager;
10351
10374
  _providerUrl;
10352
10375
  _footprintShaderProgram;
10353
- _visibleTilesManager;
10354
- constructor(fsetName, fsetDescription, providerUrl, metadataManager, webgl, visibleTilesManager) {
10376
+ constructor(fsetName, fsetDescription, providerUrl, metadataManager, webgl) {
10355
10377
  this._webgl = webgl;
10356
10378
  this._ready = false;
10357
- this._visibleTilesManager = visibleTilesManager;
10358
10379
  this.TYPE = "FOOTPRINT_SET";
10359
10380
  this._name = fsetName;
10360
10381
  this._description = fsetDescription;
@@ -11673,8 +11694,14 @@ class HealpixGrid extends AbstractSkyEntity_js_1.AbstractSkyEntity {
11673
11694
  // FIX: pass model & pMatrix to match FoVUtils TS signature
11674
11695
  const center = FoVUtils_js_1.FoVUtils.getCenterJ2000(gl.canvas, this, this._webgl, camera, pMatrix);
11675
11696
  const fovMin = (this.getMinFoV() * Math.PI) / 180 / 2;
11697
+ const visibleHealpix = Global_js_1.default.getHealpix(this._visibleorder);
11698
+ const maxPixel = visibleHealpix.getNPix();
11676
11699
  for (let p = 0; p < pixels.length; p++) {
11677
- const pixCenter = Global_js_1.default.getHealpix(this._visibleorder).pix2vec(pixels[p]);
11700
+ const pixel = pixels[p];
11701
+ if (!Number.isInteger(pixel) || pixel < 0 || pixel >= maxPixel) {
11702
+ continue;
11703
+ }
11704
+ const pixCenter = visibleHealpix.pix2vec(pixel);
11678
11705
  // const pixCenter = (global.getHealpix(global.order).pix2vec(pixels[p]) as BoundVec);
11679
11706
  const point = new Point_js_1.Point({ x: pixCenter.x, y: pixCenter.y, z: pixCenter.z }, CoordsType_js_1.CoordsType.CARTESIAN);
11680
11707
  const distance = GeomUtils_js_1.default.orthodromicDistance(center, point);
@@ -12104,6 +12131,7 @@ class AllSky {
12104
12131
  async loadFits() {
12105
12132
  try {
12106
12133
  this._fitsTile = await (0, FitsTileLoader_js_1.loadFitsTile)(this._texurl);
12134
+ this._hips.observeFITSDataRange(this._fitsTile);
12107
12135
  this.textureLoaded();
12108
12136
  this.initModelBuffer();
12109
12137
  this._textureLoaded = true;
@@ -12148,30 +12176,7 @@ class AllSky {
12148
12176
  }
12149
12177
  }
12150
12178
  getFitsDataRange() {
12151
- const hipsRange = this._hips.dataRange;
12152
- if (hipsRange.min !== undefined &&
12153
- hipsRange.max !== undefined &&
12154
- Number.isFinite(hipsRange.min) &&
12155
- Number.isFinite(hipsRange.max) &&
12156
- hipsRange.max > hipsRange.min) {
12157
- return {
12158
- min: hipsRange.min,
12159
- max: hipsRange.max,
12160
- };
12161
- }
12162
- const fits = this._fitsTile;
12163
- if (fits &&
12164
- fits.dataMin !== null &&
12165
- fits.dataMax !== null &&
12166
- Number.isFinite(fits.dataMin) &&
12167
- Number.isFinite(fits.dataMax) &&
12168
- fits.dataMax > fits.dataMin) {
12169
- return {
12170
- min: fits.dataMin,
12171
- max: fits.dataMax,
12172
- };
12173
- }
12174
- return null;
12179
+ return this._hips.getFITSDisplayRange(this._fitsTile);
12175
12180
  }
12176
12181
  initModelBuffer() {
12177
12182
  const gl = this._webgl;
@@ -12285,7 +12290,7 @@ class AllSky {
12285
12290
  console.error(`[AllSky] No display range available for FITS atlas ${this._texurl}`);
12286
12291
  return false;
12287
12292
  }
12288
- this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max);
12293
+ this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max, this._hips.fitsStretch.scaleFunctionIndex, this._hips.fitsStretch.scaleParam);
12289
12294
  }
12290
12295
  else {
12291
12296
  this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, false);
@@ -12423,6 +12428,7 @@ class AncestorTile {
12423
12428
  async loadFits() {
12424
12429
  try {
12425
12430
  this._fitsTile = await (0, FitsTileLoader_js_1.loadFitsTile)(this._texurl);
12431
+ this._hips.observeFITSDataRange(this._fitsTile);
12426
12432
  this.textureLoaded();
12427
12433
  const fits = this._fitsTile;
12428
12434
  if (!fits) {
@@ -12480,30 +12486,7 @@ class AncestorTile {
12480
12486
  }
12481
12487
  }
12482
12488
  getFitsDataRange() {
12483
- const hipsRange = this._hips.dataRange;
12484
- if (hipsRange.min !== undefined &&
12485
- hipsRange.max !== undefined &&
12486
- Number.isFinite(hipsRange.min) &&
12487
- Number.isFinite(hipsRange.max) &&
12488
- hipsRange.max > hipsRange.min) {
12489
- return {
12490
- min: hipsRange.min,
12491
- max: hipsRange.max,
12492
- };
12493
- }
12494
- const fits = this._fitsTile;
12495
- if (fits &&
12496
- fits.dataMin !== null &&
12497
- fits.dataMax !== null &&
12498
- Number.isFinite(fits.dataMin) &&
12499
- Number.isFinite(fits.dataMax) &&
12500
- fits.dataMax > fits.dataMin) {
12501
- return {
12502
- min: fits.dataMin,
12503
- max: fits.dataMax,
12504
- };
12505
- }
12506
- return null;
12489
+ return this._hips.getFITSDisplayRange(this._fitsTile);
12507
12490
  }
12508
12491
  initModelBuffer() {
12509
12492
  const gl = this._webgl;
@@ -12603,7 +12586,7 @@ class AncestorTile {
12603
12586
  console.error(`[AncestorTile] No display range available for FITS tile ${this._texurl}`);
12604
12587
  return false;
12605
12588
  }
12606
- this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max);
12589
+ this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max, this._hips.fitsStretch.scaleFunctionIndex, this._hips.fitsStretch.scaleParam);
12607
12590
  }
12608
12591
  else {
12609
12592
  this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, false);
@@ -12681,6 +12664,9 @@ var __webpack_unused_export__;
12681
12664
  __webpack_unused_export__ = ({ value: true });
12682
12665
  exports.loadFitsTile = loadFitsTile;
12683
12666
  const jsfitsio_1 = __webpack_require__(1677);
12667
+ const ROBUST_SAMPLE_COUNT = 8192;
12668
+ const ROBUST_LOW_PERCENTILE = 0.005;
12669
+ const ROBUST_HIGH_PERCENTILE = 0.995;
12684
12670
  async function loadFitsTile(url) {
12685
12671
  const fitsFile = await jsfitsio_1.FITSParser.loadFITSFile(url);
12686
12672
  if (!fitsFile?.primaryHDU) {
@@ -12710,22 +12696,57 @@ async function loadFitsTile(url) {
12710
12696
  const dataMin = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.DATAMIN);
12711
12697
  const dataMax = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.DATAMAX);
12712
12698
  const pixels = new Float32Array(data.length);
12699
+ let physicalMin = null;
12700
+ let physicalMax = null;
12701
+ const robustSamples = [];
12702
+ const sampleStep = Math.max(1, Math.floor(data.length / ROBUST_SAMPLE_COUNT));
12713
12703
  for (let i = 0; i < data.length; i++) {
12714
12704
  const rawValue = data[i];
12715
12705
  if (!Number.isFinite(rawValue) || (blank !== null && rawValue === blank)) {
12716
12706
  pixels[i] = Number.NaN;
12717
12707
  continue;
12718
12708
  }
12719
- pixels[i] = rawValue * bscale + bzero;
12709
+ const physicalValue = rawValue * bscale + bzero;
12710
+ pixels[i] = physicalValue;
12711
+ if (Number.isFinite(physicalValue)) {
12712
+ physicalMin =
12713
+ physicalMin === null ? physicalValue : Math.min(physicalMin, physicalValue);
12714
+ physicalMax =
12715
+ physicalMax === null ? physicalValue : Math.max(physicalMax, physicalValue);
12716
+ if (i % sampleStep === 0) {
12717
+ robustSamples.push(physicalValue);
12718
+ }
12719
+ }
12720
12720
  }
12721
+ const robustRange = computeRobustRange(robustSamples);
12721
12722
  return {
12722
12723
  width,
12723
12724
  height,
12724
12725
  pixels,
12725
12726
  dataMin,
12726
12727
  dataMax,
12728
+ physicalMin,
12729
+ physicalMax,
12730
+ robustMin: robustRange?.min ?? null,
12731
+ robustMax: robustRange?.max ?? null,
12727
12732
  };
12728
12733
  }
12734
+ function computeRobustRange(samples) {
12735
+ if (samples.length === 0) {
12736
+ return null;
12737
+ }
12738
+ samples.sort((a, b) => a - b);
12739
+ const min = percentile(samples, ROBUST_LOW_PERCENTILE);
12740
+ const max = percentile(samples, ROBUST_HIGH_PERCENTILE);
12741
+ if (!Number.isFinite(min) || !Number.isFinite(max) || max <= min) {
12742
+ return null;
12743
+ }
12744
+ return { min, max };
12745
+ }
12746
+ function percentile(sortedValues, p) {
12747
+ const index = Math.min(sortedValues.length - 1, Math.max(0, Math.round((sortedValues.length - 1) * p)));
12748
+ return sortedValues[index];
12749
+ }
12729
12750
  function getNumericHeaderValue(header, key) {
12730
12751
  const item = header.findById(key);
12731
12752
  if (!item) {
@@ -12931,6 +12952,21 @@ const ColorMaps_js_1 = __importDefault(__webpack_require__(619));
12931
12952
  const AncestorTile_js_1 = __importDefault(__webpack_require__(2885));
12932
12953
  const AllSky_js_1 = __importDefault(__webpack_require__(2368));
12933
12954
  const HiPSCoverage_js_1 = __webpack_require__(9912);
12955
+ const FITS_SCALE_FUNCTION_INDEX = {
12956
+ linear: 0,
12957
+ sqrt: 1,
12958
+ log: 2,
12959
+ asinh: 3,
12960
+ gamma: 4,
12961
+ };
12962
+ const DEFAULT_FITS_SCALE_PARAM = {
12963
+ linear: 1,
12964
+ sqrt: 1,
12965
+ log: 100,
12966
+ asinh: 10,
12967
+ gamma: 0.5,
12968
+ };
12969
+ const MAX_ROBUST_TILE_RANGES = 512;
12934
12970
  class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12935
12971
  _ancestorTiles;
12936
12972
  _allSkyTile;
@@ -12947,6 +12983,13 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12947
12983
  samplerIdx = 0;
12948
12984
  colorMapIdx = 0;
12949
12985
  colorMap = ColorMaps_js_1.default["native"];
12986
+ _fitsStretch = {
12987
+ scaleFunction: "linear",
12988
+ scaleFunctionIndex: FITS_SCALE_FUNCTION_INDEX.linear,
12989
+ scaleParam: DEFAULT_FITS_SCALE_PARAM.linear,
12990
+ rangeMode: "robust",
12991
+ };
12992
+ _robustFITSRanges = [];
12950
12993
  _healpixGrid;
12951
12994
  // exposed read-only helpers
12952
12995
  get maxOrder() {
@@ -13182,6 +13225,137 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
13182
13225
  get dataRange() {
13183
13226
  return this._descriptor.dataRange;
13184
13227
  }
13228
+ get fitsStretch() {
13229
+ return this._fitsStretch;
13230
+ }
13231
+ setFITSScaleFunction(scaleFunction, scaleParam) {
13232
+ const scaleFunctionIndex = FITS_SCALE_FUNCTION_INDEX[scaleFunction];
13233
+ if (scaleFunctionIndex === undefined) {
13234
+ throw new Error(`Unsupported FITS scale function: ${scaleFunction}`);
13235
+ }
13236
+ const defaultParam = DEFAULT_FITS_SCALE_PARAM[scaleFunction];
13237
+ const param = scaleParam ?? defaultParam;
13238
+ if (!Number.isFinite(param) || param <= 0) {
13239
+ throw new Error(`Invalid FITS scale parameter: ${param}`);
13240
+ }
13241
+ this._fitsStretch = {
13242
+ ...this._fitsStretch,
13243
+ scaleFunction,
13244
+ scaleFunctionIndex,
13245
+ scaleParam: param,
13246
+ };
13247
+ }
13248
+ setFITSRangeMode(rangeMode) {
13249
+ if (rangeMode !== "robust" && rangeMode !== "hips" && rangeMode !== "tile") {
13250
+ throw new Error(`Unsupported FITS range mode: ${rangeMode}`);
13251
+ }
13252
+ this._fitsStretch = {
13253
+ ...this._fitsStretch,
13254
+ rangeMode,
13255
+ };
13256
+ }
13257
+ observeFITSDataRange(fits) {
13258
+ if (fits.robustMin === null ||
13259
+ fits.robustMax === null ||
13260
+ !Number.isFinite(fits.robustMin) ||
13261
+ !Number.isFinite(fits.robustMax) ||
13262
+ fits.robustMax <= fits.robustMin) {
13263
+ return;
13264
+ }
13265
+ this._robustFITSRanges.push({
13266
+ min: fits.robustMin,
13267
+ max: fits.robustMax,
13268
+ });
13269
+ if (this._robustFITSRanges.length > MAX_ROBUST_TILE_RANGES) {
13270
+ this._robustFITSRanges.shift();
13271
+ }
13272
+ }
13273
+ getFITSDisplayRange(fits) {
13274
+ const hipsRange = this.getHiPSDataRange();
13275
+ if (this._fitsStretch.rangeMode === "hips" && hipsRange) {
13276
+ return hipsRange;
13277
+ }
13278
+ if (this._fitsStretch.rangeMode === "robust") {
13279
+ const robustRange = this.getRobustFITSRange() ?? this.getTileRobustRange(fits);
13280
+ if (robustRange) {
13281
+ return robustRange;
13282
+ }
13283
+ }
13284
+ const tileRange = this.getTilePhysicalRange(fits) ?? this.getTileHeaderRange(fits);
13285
+ if (tileRange) {
13286
+ return tileRange;
13287
+ }
13288
+ return hipsRange;
13289
+ }
13290
+ getHiPSDataRange() {
13291
+ const hipsRange = this.dataRange;
13292
+ if (hipsRange.min !== undefined &&
13293
+ hipsRange.max !== undefined &&
13294
+ Number.isFinite(hipsRange.min) &&
13295
+ Number.isFinite(hipsRange.max) &&
13296
+ hipsRange.max > hipsRange.min) {
13297
+ return {
13298
+ min: hipsRange.min,
13299
+ max: hipsRange.max,
13300
+ };
13301
+ }
13302
+ return null;
13303
+ }
13304
+ getRobustFITSRange() {
13305
+ if (this._robustFITSRanges.length === 0) {
13306
+ return null;
13307
+ }
13308
+ const lows = this._robustFITSRanges.map((range) => range.min).sort((a, b) => a - b);
13309
+ const highs = this._robustFITSRanges.map((range) => range.max).sort((a, b) => a - b);
13310
+ const min = lows[Math.floor((lows.length - 1) * 0.1)];
13311
+ const max = highs[Math.ceil((highs.length - 1) * 0.9)];
13312
+ if (!Number.isFinite(min) || !Number.isFinite(max) || max <= min) {
13313
+ return null;
13314
+ }
13315
+ return { min, max };
13316
+ }
13317
+ getTileRobustRange(fits) {
13318
+ if (fits &&
13319
+ fits.robustMin !== null &&
13320
+ fits.robustMax !== null &&
13321
+ Number.isFinite(fits.robustMin) &&
13322
+ Number.isFinite(fits.robustMax) &&
13323
+ fits.robustMax > fits.robustMin) {
13324
+ return {
13325
+ min: fits.robustMin,
13326
+ max: fits.robustMax,
13327
+ };
13328
+ }
13329
+ return null;
13330
+ }
13331
+ getTilePhysicalRange(fits) {
13332
+ if (fits &&
13333
+ fits.physicalMin !== null &&
13334
+ fits.physicalMax !== null &&
13335
+ Number.isFinite(fits.physicalMin) &&
13336
+ Number.isFinite(fits.physicalMax) &&
13337
+ fits.physicalMax > fits.physicalMin) {
13338
+ return {
13339
+ min: fits.physicalMin,
13340
+ max: fits.physicalMax,
13341
+ };
13342
+ }
13343
+ return null;
13344
+ }
13345
+ getTileHeaderRange(fits) {
13346
+ if (fits &&
13347
+ fits.dataMin !== null &&
13348
+ fits.dataMax !== null &&
13349
+ Number.isFinite(fits.dataMin) &&
13350
+ Number.isFinite(fits.dataMax) &&
13351
+ fits.dataMax > fits.dataMin) {
13352
+ return {
13353
+ min: fits.dataMin,
13354
+ max: fits.dataMax,
13355
+ };
13356
+ }
13357
+ return null;
13358
+ }
13185
13359
  getCurrentHealpixOrder() {
13186
13360
  return this._visibleorder;
13187
13361
  }
@@ -13695,6 +13869,7 @@ class Tile {
13695
13869
  async loadFits() {
13696
13870
  try {
13697
13871
  this._fitsTile = await (0, FitsTileLoader_js_1.loadFitsTile)(this._texurl);
13872
+ this._hips.observeFITSDataRange(this._fitsTile);
13698
13873
  this._ready = true;
13699
13874
  }
13700
13875
  catch (error) {
@@ -13833,30 +14008,7 @@ class Tile {
13833
14008
  gl.bufferData(gl.ARRAY_BUFFER, this.vertexPosition[qidx], gl.STATIC_DRAW);
13834
14009
  }
13835
14010
  getFitsDataRange() {
13836
- const hipsRange = this._hips.dataRange;
13837
- if (hipsRange.min !== undefined &&
13838
- hipsRange.max !== undefined &&
13839
- Number.isFinite(hipsRange.min) &&
13840
- Number.isFinite(hipsRange.max) &&
13841
- hipsRange.max > hipsRange.min) {
13842
- return {
13843
- min: hipsRange.min,
13844
- max: hipsRange.max,
13845
- };
13846
- }
13847
- const fits = this._fitsTile;
13848
- if (fits &&
13849
- fits.dataMin !== null &&
13850
- fits.dataMax !== null &&
13851
- Number.isFinite(fits.dataMin) &&
13852
- Number.isFinite(fits.dataMax) &&
13853
- fits.dataMax > fits.dataMin) {
13854
- return {
13855
- min: fits.dataMin,
13856
- max: fits.dataMax,
13857
- };
13858
- }
13859
- return null;
14011
+ return this._hips.getFITSDisplayRange(this._fitsTile);
13860
14012
  }
13861
14013
  get inView() {
13862
14014
  return this._inView;
@@ -13960,7 +14112,7 @@ class Tile {
13960
14112
  console.error(`[Tile] No display range available for FITS tile ${this._texurl}`);
13961
14113
  return;
13962
14114
  }
13963
- hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max);
14115
+ hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max, this._hips.fitsStretch.scaleFunctionIndex, this._hips.fitsStretch.scaleParam);
13964
14116
  }
13965
14117
  else {
13966
14118
  hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, false);
@@ -14541,7 +14693,9 @@ class MeshHiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
14541
14693
  const orders = Array.from(byOrder.keys()).sort((a, b) => a - b);
14542
14694
  for (const order of orders) {
14543
14695
  for (const coord of byOrder.get(order) ?? []) {
14544
- this._tiles.get(this.tileKey(coord))?.draw(pMatrix, vMatrix, mMatrix, this._descriptor.color, this._descriptor.wireframe);
14696
+ this._tiles
14697
+ .get(this.tileKey(coord))
14698
+ ?.draw(pMatrix, vMatrix, mMatrix, this._descriptor.color, this._descriptor.wireframe);
14545
14699
  }
14546
14700
  }
14547
14701
  if (wasCullFace)
@@ -14554,7 +14708,7 @@ class MeshHiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
14554
14708
  getDebugStats() {
14555
14709
  const tiles = Array.from(this._tiles.values());
14556
14710
  return {
14557
- activeBaseLayer: 'meships',
14711
+ activeBaseLayer: "meships",
14558
14712
  meshHiPSName: this._descriptor.name,
14559
14713
  meshHiPSUrl: this._descriptor.baseUrl,
14560
14714
  currentOrder: this._currentOrder,
@@ -14573,33 +14727,47 @@ class MeshHiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
14573
14727
  ? byOrder.pixels
14574
14728
  : [];
14575
14729
  if (pixels.length > 0) {
14576
- return pixels.map((ipix) => ({ order: this._currentOrder, ipix }));
14730
+ return pixels.map((ipix) => ({
14731
+ order: this._currentOrder,
14732
+ ipix,
14733
+ }));
14577
14734
  }
14578
14735
  const tileCount = 12 * 4 ** this._currentOrder;
14579
- return Array.from({ length: tileCount }, (_, ipix) => ({ order: this._currentOrder, ipix }));
14736
+ return Array.from({ length: tileCount }, (_, ipix) => ({
14737
+ order: this._currentOrder,
14738
+ ipix,
14739
+ }));
14580
14740
  }
14581
14741
  resolveCoverageTiles(visibleTiles) {
14582
14742
  const tiles = new Map();
14583
14743
  const add = (coord) => {
14584
- if (coord.order < this._descriptor.minOrder || coord.order > this._descriptor.maxOrder)
14744
+ if (coord.order < this._descriptor.minOrder ||
14745
+ coord.order > this._descriptor.maxOrder) {
14585
14746
  return;
14747
+ }
14586
14748
  tiles.set(this.tileKey(coord), coord);
14587
14749
  };
14588
14750
  for (const coord of visibleTiles) {
14589
14751
  add(coord);
14590
14752
  for (let order = coord.order - 1; order >= this._descriptor.minOrder; order--) {
14591
14753
  const shift = 2 * (coord.order - order);
14592
- add({ order, ipix: coord.ipix >> shift });
14754
+ add({
14755
+ order,
14756
+ ipix: coord.ipix >> shift,
14757
+ });
14593
14758
  }
14594
14759
  }
14595
14760
  const manager = this._healpixGrid.visibleTilesManager;
14596
14761
  const ancestorsMap = manager?.ancestorsMap;
14597
14762
  if (ancestorsMap) {
14598
14763
  for (const [order, ipixes] of ancestorsMap) {
14599
- if (order < this._descriptor.minOrder || order > this._descriptor.maxOrder)
14764
+ if (order < this._descriptor.minOrder ||
14765
+ order > this._descriptor.maxOrder) {
14600
14766
  continue;
14601
- for (const ipix of ipixes)
14767
+ }
14768
+ for (const ipix of ipixes) {
14602
14769
  add({ order, ipix });
14770
+ }
14603
14771
  }
14604
14772
  }
14605
14773
  return Array.from(tiles.values());
@@ -16225,6 +16393,9 @@ function normalizeLongitudeDeg(longitudeDeg) {
16225
16393
  *
16226
16394
  * See LICENSE.md, LICENSE-AGPL.md, and LICENSE-COMMERCIAL.md for details.
16227
16395
  */
16396
+ var __importDefault = (this && this.__importDefault) || function (mod) {
16397
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16398
+ };
16228
16399
  Object.defineProperty(exports, "__esModule", ({ value: true }));
16229
16400
  exports.TerraFootprintSetGL = void 0;
16230
16401
  const FootprintSetGL_js_1 = __webpack_require__(592);
@@ -16233,6 +16404,8 @@ const Footprint_js_1 = __webpack_require__(2475);
16233
16404
  const MetadataColumn_js_1 = __webpack_require__(1072);
16234
16405
  const MetadataManager_js_1 = __webpack_require__(5403);
16235
16406
  const MetadataColumn_js_2 = __webpack_require__(1072);
16407
+ const Point_js_1 = __webpack_require__(6553);
16408
+ const GeomUtils_js_1 = __importDefault(__webpack_require__(2930));
16236
16409
  class TerraFootprintSetGL extends FootprintSetGL_js_1.FootprintSetGL {
16237
16410
  _kind = 'TerraFootprintSetGL';
16238
16411
  _coordsType = CoordsType_js_1.CoordsType.GEOGRAPHIC;
@@ -16251,6 +16424,23 @@ class TerraFootprintSetGL extends FootprintSetGL_js_1.FootprintSetGL {
16251
16424
  this._ready = true;
16252
16425
  this._bufferInitialised = false;
16253
16426
  }
16427
+ checkSelection(mouseHelper) {
16428
+ if (mouseHelper.x == null || mouseHelper.y == null || mouseHelper.z == null)
16429
+ return;
16430
+ const hoverState = this;
16431
+ hoverState._hoveredFootprints = [];
16432
+ this.totHoveredPoints = 0;
16433
+ const mousePoint = new Point_js_1.Point({ x: mouseHelper.x, y: mouseHelper.y, z: mouseHelper.z }, CoordsType_js_1.CoordsType.CARTESIAN);
16434
+ for (const footprint of this.footprintPolygons) {
16435
+ if (!footprint.selectionObj)
16436
+ continue;
16437
+ if (GeomUtils_js_1.default.checkPointInsidePolygon5(footprint.selectionObj, mousePoint)) {
16438
+ hoverState._hoveredFootprints.push(footprint);
16439
+ this.totHoveredPoints += footprint.totPoints;
16440
+ }
16441
+ }
16442
+ this.initHoveringBuffer();
16443
+ }
16254
16444
  createGeoJSONMetadataColumns(features) {
16255
16445
  const names = new Set();
16256
16446
  features.forEach(feature => Object.keys(feature.properties).forEach(name => names.add(name)));
@@ -16296,8 +16486,44 @@ exports.TerraFootprintSetGL = TerraFootprintSetGL;
16296
16486
  Object.defineProperty(exports, "__esModule", ({ value: true }));
16297
16487
  exports.TerraPointSetGL = void 0;
16298
16488
  const CatalogueGL_js_1 = __webpack_require__(1232);
16489
+ const MetadataManager_js_1 = __webpack_require__(5403);
16490
+ const Point_js_1 = __webpack_require__(6553);
16491
+ const CoordsType_js_1 = __webpack_require__(8145);
16299
16492
  class TerraPointSetGL extends CatalogueGL_js_1.CatalogueGL {
16300
16493
  _kind = 'TerraPointSetGL';
16494
+ addSources(inData, columnsMeta) {
16495
+ this._ready = false;
16496
+ this._sources = [];
16497
+ const metadataManager = new MetadataManager_js_1.MetadataManager(columnsMeta);
16498
+ this._metadataManager = metadataManager;
16499
+ const lonDataIndex = metadataManager.selectedRaColumn?.index ?? -1;
16500
+ const latDataIndex = metadataManager.selectedDecColumn?.index ?? -1;
16501
+ if (lonDataIndex < 0 || latDataIndex < 0) {
16502
+ throw new Error(`(lon, lat) idx not defined (${lonDataIndex}, ${latDataIndex}) `);
16503
+ }
16504
+ for (const row of inData) {
16505
+ const point = new Point_js_1.Point({
16506
+ lonDeg: Number(row[lonDataIndex]),
16507
+ latDeg: Number(row[latDataIndex]),
16508
+ }, CoordsType_js_1.CoordsType.GEOGRAPHIC);
16509
+ this.addSource({
16510
+ point,
16511
+ details: row,
16512
+ healpixPixel: 0,
16513
+ shapeSize: CatalogueGL_js_1.CatalogueGL.STANDARD_SHAPE_SIZE,
16514
+ brightnessFactor: 3,
16515
+ getDetailByindex(index) {
16516
+ return index < 0 || index >= row.length ? undefined : row[index];
16517
+ },
16518
+ });
16519
+ }
16520
+ this._ready = true;
16521
+ this._bufferInitialised = false;
16522
+ }
16523
+ draw(inMatrix, inMouseHelper, viewMatrix, projectionMatrix) {
16524
+ this._oldMouseCoords = inMouseHelper?.xyz ?? null;
16525
+ super.draw(inMatrix, inMouseHelper, viewMatrix, projectionMatrix);
16526
+ }
16301
16527
  }
16302
16528
  exports.TerraPointSetGL = TerraPointSetGL;
16303
16529
 
@@ -16331,7 +16557,6 @@ class TerraPolylineSetGL {
16331
16557
  _providerUrl;
16332
16558
  _metadataManager;
16333
16559
  _webgl;
16334
- _visibleTilesManager;
16335
16560
  static ELEM_SIZE = 3;
16336
16561
  static BYTES_X_ELEM = new Float32Array().BYTES_PER_ELEMENT;
16337
16562
  _kind = 'TerraPolylineSetGL';
@@ -16342,13 +16567,12 @@ class TerraPolylineSetGL {
16342
16567
  paths = [];
16343
16568
  renderSegments = [];
16344
16569
  _polylineShaderProgram;
16345
- constructor(_name, _description, _providerUrl, _metadataManager, _webgl, _visibleTilesManager) {
16570
+ constructor(_name, _description, _providerUrl, _metadataManager, _webgl) {
16346
16571
  this._name = _name;
16347
16572
  this._description = _description;
16348
16573
  this._providerUrl = _providerUrl;
16349
16574
  this._metadataManager = _metadataManager;
16350
16575
  this._webgl = _webgl;
16351
- this._visibleTilesManager = _visibleTilesManager;
16352
16576
  this._polylineShaderProgram = new FootprintShaderProgram_js_1.FootprintShaderProgram(this._webgl);
16353
16577
  }
16354
16578
  addPath(points, metadata) {
@@ -16823,6 +17047,8 @@ class HiPSShaderProgram {
16823
17047
  textureMode: "uTextureMode",
16824
17048
  dataMin: "uDataMin",
16825
17049
  dataMax: "uDataMax",
17050
+ scaleFunction: "uScaleFunction",
17051
+ scaleParam: "uScaleParam",
16826
17052
  };
16827
17053
  this.gl_attributes = {
16828
17054
  vertex_pos: "aVertexPosition",
@@ -16837,6 +17063,8 @@ class HiPSShaderProgram {
16837
17063
  textureMode: new Array(8).fill(null),
16838
17064
  dataMin: new Array(8).fill(null),
16839
17065
  dataMax: new Array(8).fill(null),
17066
+ scaleFunction: new Array(8).fill(null),
17067
+ scaleParam: new Array(8).fill(null),
16840
17068
  layerOpacity: null,
16841
17069
  clorMapIdx: null,
16842
17070
  vertexPositionAttribute: -1,
@@ -16970,7 +17198,7 @@ class HiPSShaderProgram {
16970
17198
  }
16971
17199
  gl.useProgram(this.shaderProgram);
16972
17200
  }
16973
- setTextureDataMode(samplerIndex, fits, min, max) {
17201
+ setTextureDataMode(samplerIndex, fits, min, max, scaleFunction = 0, scaleParam = 1) {
16974
17202
  if (samplerIndex < 0 || samplerIndex >= 8) {
16975
17203
  throw new Error(`Invalid HiPS sampler index: ${samplerIndex}`);
16976
17204
  }
@@ -16991,12 +17219,20 @@ class HiPSShaderProgram {
16991
17219
  }
16992
17220
  const minLocation = this.locations.dataMin[samplerIndex];
16993
17221
  const maxLocation = this.locations.dataMax[samplerIndex];
17222
+ const scaleFunctionLocation = this.locations.scaleFunction[samplerIndex];
17223
+ const scaleParamLocation = this.locations.scaleParam[samplerIndex];
16994
17224
  if (minLocation) {
16995
17225
  gl.uniform1f(minLocation, min);
16996
17226
  }
16997
17227
  if (maxLocation) {
16998
17228
  gl.uniform1f(maxLocation, max);
16999
17229
  }
17230
+ if (scaleFunctionLocation) {
17231
+ gl.uniform1i(scaleFunctionLocation, scaleFunction);
17232
+ }
17233
+ if (scaleParamLocation) {
17234
+ gl.uniform1f(scaleParamLocation, scaleParam);
17235
+ }
17000
17236
  }
17001
17237
  enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx) {
17002
17238
  // const gl = global.gl
@@ -17012,6 +17248,8 @@ class HiPSShaderProgram {
17012
17248
  this.locations.textureMode[i] = gl.getUniformLocation(this.shaderProgram, `uTextureMode${i}`);
17013
17249
  this.locations.dataMin[i] = gl.getUniformLocation(this.shaderProgram, `uDataMin${i}`);
17014
17250
  this.locations.dataMax[i] = gl.getUniformLocation(this.shaderProgram, `uDataMax${i}`);
17251
+ this.locations.scaleFunction[i] = gl.getUniformLocation(this.shaderProgram, `uScaleFunction${i}`);
17252
+ this.locations.scaleParam[i] = gl.getUniformLocation(this.shaderProgram, `uScaleParam${i}`);
17015
17253
  if (this.locations.samplers[i]) {
17016
17254
  gl.uniform1i(this.locations.samplers[i], i);
17017
17255
  }
@@ -17350,7 +17588,7 @@ class ShaderManager {
17350
17588
  }
17351
17589
  static footprintVS() {
17352
17590
  return `#version 300 es
17353
- precision highp float;
17591
+ precision mediump float;
17354
17592
 
17355
17593
  layout(location = 0) in vec4 aCatPosition;
17356
17594
 
@@ -17392,7 +17630,7 @@ class ShaderManager {
17392
17630
  }
17393
17631
  static hipsNativeFS() {
17394
17632
  return `#version 300 es
17395
- precision mediump float;
17633
+ precision highp float;
17396
17634
 
17397
17635
  in vec2 vTextureCoord;
17398
17636
 
@@ -17458,7 +17696,7 @@ class ShaderManager {
17458
17696
  }
17459
17697
  static hipsGrayscaleFS() {
17460
17698
  return `#version 300 es
17461
- precision mediump float;
17699
+ precision highp float;
17462
17700
 
17463
17701
  in vec2 vTextureCoord;
17464
17702
 
@@ -17532,7 +17770,7 @@ class ShaderManager {
17532
17770
  }
17533
17771
  static hipsColorMapFS() {
17534
17772
  return `#version 300 es
17535
- precision mediump float;
17773
+ precision highp float;
17536
17774
 
17537
17775
  uniform float uLayerOpacity;
17538
17776
 
@@ -17637,6 +17875,36 @@ class ShaderManager {
17637
17875
  uniform int uTextureMode${index};
17638
17876
  uniform float uDataMin${index};
17639
17877
  uniform float uDataMax${index};
17878
+ uniform int uScaleFunction${index};
17879
+ uniform float uScaleParam${index};
17880
+
17881
+ float asinhCompat${index}(float value) {
17882
+ return log(value + sqrt(value * value + 1.0));
17883
+ }
17884
+
17885
+ float applyFitsScale${index}(float normalized) {
17886
+ float x = clamp(normalized, 0.0, 1.0);
17887
+
17888
+ if (uScaleFunction${index} == 1) {
17889
+ return sqrt(x);
17890
+ }
17891
+
17892
+ if (uScaleFunction${index} == 2) {
17893
+ float strength = max(uScaleParam${index}, 1.0);
17894
+ return log(1.0 + strength * x) / log(1.0 + strength);
17895
+ }
17896
+
17897
+ if (uScaleFunction${index} == 3) {
17898
+ float strength = max(uScaleParam${index}, 1.0);
17899
+ return asinhCompat${index}(strength * x) / asinhCompat${index}(strength);
17900
+ }
17901
+
17902
+ if (uScaleFunction${index} == 4) {
17903
+ return pow(x, max(uScaleParam${index}, 0.0001));
17904
+ }
17905
+
17906
+ return x;
17907
+ }
17640
17908
 
17641
17909
  vec4 sampleHiPSTexture${index}(vec2 uv) {
17642
17910
  vec4 color = texture(uSampler${index}, uv);
@@ -17660,10 +17928,12 @@ class ShaderManager {
17660
17928
  1.0
17661
17929
  );
17662
17930
 
17931
+ float scaled = applyFitsScale${index}(normalized);
17932
+
17663
17933
  return vec4(
17664
- normalized,
17665
- normalized,
17666
- normalized,
17934
+ scaled,
17935
+ scaled,
17936
+ scaled,
17667
17937
  1.0
17668
17938
  );
17669
17939
  }
@@ -18640,7 +18910,8 @@ class MouseHelper {
18640
18910
  computeNpix() {
18641
18911
  if (!this._xyz)
18642
18912
  return null;
18643
- const hp = Global_js_1.default.getHealpix(Global_js_1.default.nsideForSelection);
18913
+ // const hp: Healpix = global.getHealpix(global.nsideForSelection);
18914
+ const hp = Global_js_1.default.getHealpix(Global_js_1.default.selectionOrder);
18644
18915
  const v = new healpix_1.Vec3(this._xyz[0], this._xyz[1], this._xyz[2]);
18645
18916
  const ptg = new healpix_1.Pointing(v, false);
18646
18917
  return hp.ang2pix(ptg, false);