astro-viewer 3.6.0 → 3.8.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 (67) hide show
  1. package/dist/64.astroviewer.cjs +37 -0
  2. package/dist/64.astroviewer.cjs.map +1 -0
  3. package/dist/64.astroviewer.js +41 -0
  4. package/dist/64.astroviewer.js.map +1 -0
  5. package/dist/64.astroviewer.min.js +2 -0
  6. package/dist/64.astroviewer.min.js.map +1 -0
  7. package/dist/911.astroviewer.cjs +4047 -0
  8. package/dist/911.astroviewer.cjs.map +1 -0
  9. package/dist/911.astroviewer.js +735 -0
  10. package/dist/911.astroviewer.js.map +1 -0
  11. package/dist/911.astroviewer.min.js +2 -0
  12. package/dist/911.astroviewer.min.js.map +1 -0
  13. package/dist/astroviewer.cjs +3019 -479
  14. package/dist/astroviewer.cjs.map +1 -1
  15. package/dist/astroviewer.js +3172 -476
  16. package/dist/astroviewer.js.map +1 -1
  17. package/dist/astroviewer.min.js +1 -1
  18. package/dist/astroviewer.min.js.map +1 -1
  19. package/lib-esm/AstroSphere.d.ts +10 -2
  20. package/lib-esm/AstroSphere.d.ts.map +1 -1
  21. package/lib-esm/AstroSphere.js +92 -28
  22. package/lib-esm/AstroSphere.js.map +1 -1
  23. package/lib-esm/AstroViewer.d.ts +32 -23
  24. package/lib-esm/AstroViewer.d.ts.map +1 -1
  25. package/lib-esm/AstroViewer.js +125 -69
  26. package/lib-esm/AstroViewer.js.map +1 -1
  27. package/lib-esm/model/hips/AllSky.d.ts +7 -4
  28. package/lib-esm/model/hips/AllSky.d.ts.map +1 -1
  29. package/lib-esm/model/hips/AllSky.js +99 -33
  30. package/lib-esm/model/hips/AllSky.js.map +1 -1
  31. package/lib-esm/model/hips/AncestorTile.d.ts +7 -4
  32. package/lib-esm/model/hips/AncestorTile.d.ts.map +1 -1
  33. package/lib-esm/model/hips/AncestorTile.js +97 -53
  34. package/lib-esm/model/hips/AncestorTile.js.map +1 -1
  35. package/lib-esm/model/hips/FitsTileLoader.d.ts +9 -0
  36. package/lib-esm/model/hips/FitsTileLoader.d.ts.map +1 -0
  37. package/lib-esm/model/hips/FitsTileLoader.js +65 -0
  38. package/lib-esm/model/hips/FitsTileLoader.js.map +1 -0
  39. package/lib-esm/model/hips/HiPS.d.ts +16 -5
  40. package/lib-esm/model/hips/HiPS.d.ts.map +1 -1
  41. package/lib-esm/model/hips/HiPS.js +160 -72
  42. package/lib-esm/model/hips/HiPS.js.map +1 -1
  43. package/lib-esm/model/hips/HiPSCoverage.d.ts +20 -0
  44. package/lib-esm/model/hips/HiPSCoverage.d.ts.map +1 -0
  45. package/lib-esm/model/hips/HiPSCoverage.js +166 -0
  46. package/lib-esm/model/hips/HiPSCoverage.js.map +1 -0
  47. package/lib-esm/model/hips/Tile.d.ts +8 -5
  48. package/lib-esm/model/hips/Tile.d.ts.map +1 -1
  49. package/lib-esm/model/hips/Tile.js +116 -56
  50. package/lib-esm/model/hips/Tile.js.map +1 -1
  51. package/lib-esm/model/hips/TileBuffer.d.ts +13 -4
  52. package/lib-esm/model/hips/TileBuffer.d.ts.map +1 -1
  53. package/lib-esm/model/hips/TileBuffer.js +52 -11
  54. package/lib-esm/model/hips/TileBuffer.js.map +1 -1
  55. package/lib-esm/model/hips/VisibleTilesManager.d.ts +5 -5
  56. package/lib-esm/model/hips/VisibleTilesManager.d.ts.map +1 -1
  57. package/lib-esm/model/hips/VisibleTilesManager.js +6 -20
  58. package/lib-esm/model/hips/VisibleTilesManager.js.map +1 -1
  59. package/lib-esm/shader/HiPSShaderProgram.d.ts +11 -2
  60. package/lib-esm/shader/HiPSShaderProgram.d.ts.map +1 -1
  61. package/lib-esm/shader/HiPSShaderProgram.js +99 -53
  62. package/lib-esm/shader/HiPSShaderProgram.js.map +1 -1
  63. package/lib-esm/shader/ShaderManager.d.ts +2 -0
  64. package/lib-esm/shader/ShaderManager.d.ts.map +1 -1
  65. package/lib-esm/shader/ShaderManager.js +199 -96
  66. package/lib-esm/shader/ShaderManager.js.map +1 -1
  67. package/package.json +3 -3
@@ -3627,6 +3627,7 @@ class AstroSphere {
3627
3627
  pointerDownY = null;
3628
3628
  pointerDownAt = 0;
3629
3629
  _activeHiPS = null;
3630
+ _activeHiPSLayers = [];
3630
3631
  _activeXYZ2 = null;
3631
3632
  _activeMeshHiPS = null;
3632
3633
  _activeBaseLayer = null;
@@ -3980,9 +3981,15 @@ class AstroSphere {
3980
3981
  document.body.style.cursor = "grab";
3981
3982
  const dragDirection = Global_js_1.default.insideSphere ? -1 : 1;
3982
3983
  const dragSpeed = Global_js_1.default.insideSphere ? 10.0 : 1;
3983
- const deltaX = (dragDirection * dragSpeed * (newX - (this.lastMouseX ?? newX)) * Math.PI) /
3984
+ const deltaX = (dragDirection *
3985
+ dragSpeed *
3986
+ (newX - (this.lastMouseX ?? newX)) *
3987
+ Math.PI) /
3984
3988
  canvas.width;
3985
- const deltaY = (dragDirection * dragSpeed * (newY - (this.lastMouseY ?? newY)) * Math.PI) /
3989
+ const deltaY = (dragDirection *
3990
+ dragSpeed *
3991
+ (newY - (this.lastMouseY ?? newY)) *
3992
+ Math.PI) /
3986
3993
  canvas.height;
3987
3994
  const filteredDelta = this.filterRotationDeltaByAstroLocks(deltaX, deltaY);
3988
3995
  this.inertiaX += 0.1 * filteredDelta.deltaX;
@@ -4117,26 +4124,75 @@ class AstroSphere {
4117
4124
  const pickerPoint = RayPickingUtils_js_1.default.getIntersectionPointWithSingleModel(maxX / 2, maxY / 2, this._healpixGrid, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
4118
4125
  return (0, Utils_js_1.cartesianToSpherical)(pickerPoint);
4119
4126
  }
4120
- collectViewportSphericalSamples(sampleCount = 5) {
4121
- const rect = this.canvas.getBoundingClientRect();
4122
- const width = rect.width;
4123
- const height = rect.height;
4124
- const samples = [];
4125
- for (let ix = 0; ix < sampleCount; ix++) {
4126
- const x = sampleCount === 1 ? width / 2 : (ix / (sampleCount - 1)) * width;
4127
- for (let iy = 0; iy < sampleCount; iy++) {
4128
- const y = sampleCount === 1 ? height / 2 : (iy / (sampleCount - 1)) * height;
4129
- const hit = RayPickingUtils_js_1.default.getIntersectionPointWithSingleModel(x, y, this._healpixGrid, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
4130
- if (hit && hit.length > 0) {
4131
- samples.push((0, Utils_js_1.cartesianToSpherical)(hit));
4132
- }
4133
- }
4127
+ changeHiPSFormat(format) {
4128
+ if (!this._activeHiPS) {
4129
+ throw new Error("No active HiPS.");
4134
4130
  }
4135
- return samples;
4131
+ this._activeHiPS.changeFormat(format);
4132
+ }
4133
+ createHiPS(hipsDescriptor) {
4134
+ return new HiPS_js_1.HiPS(1, [0.0, 0.0, 0.0], 0, 0, hipsDescriptor, this._webgl, this._healpixGrid);
4136
4135
  }
4137
4136
  activateHiPS(hipsDescriptor) {
4138
- this._activeHiPS = new HiPS_js_1.HiPS(1, [0.0, 0.0, 0.0], 0, 0, hipsDescriptor, this._webgl, this._healpixGrid);
4137
+ const tileBuffer = this._healpixGrid.visibleTilesManager.tileBuffer;
4138
+ for (const hips of this._activeHiPSLayers) {
4139
+ tileBuffer.removeHiPS(hips);
4140
+ }
4141
+ this._activeHiPSLayers = [];
4142
+ const hips = this.createHiPS(hipsDescriptor);
4143
+ this._activeHiPSLayers.push(hips);
4144
+ this._activeHiPS = hips;
4145
+ this._activeBaseLayer = "hips";
4146
+ return hips;
4147
+ }
4148
+ setHiPSOpacity(hips, opacity) {
4149
+ if (!this._activeHiPSLayers.includes(hips)) {
4150
+ throw new Error("HiPS layer is not active in this AstroSphere.");
4151
+ }
4152
+ hips.setOpacity(opacity);
4153
+ }
4154
+ addHiPS(hipsDescriptor) {
4155
+ const normalizeURL = (url) => String(url).replace(/\/+$/, "");
4156
+ const descriptorURL = normalizeURL(hipsDescriptor.url);
4157
+ const existing = this._activeHiPSLayers.find((hips) => normalizeURL(hips.baseURL) === descriptorURL);
4158
+ if (existing) {
4159
+ throw new Error(`HiPS already active: ${String(hipsDescriptor.url)}`);
4160
+ }
4161
+ const hips = this.createHiPS(hipsDescriptor);
4162
+ this._activeHiPSLayers.push(hips);
4163
+ this._activeHiPS = hips;
4139
4164
  this._activeBaseLayer = "hips";
4165
+ return hips;
4166
+ }
4167
+ removeHiPS(hips) {
4168
+ const index = this._activeHiPSLayers.indexOf(hips);
4169
+ if (index === -1) {
4170
+ return;
4171
+ }
4172
+ this._healpixGrid.visibleTilesManager.tileBuffer.removeHiPS(hips);
4173
+ this._activeHiPSLayers.splice(index, 1);
4174
+ if (this._activeHiPSLayers.length === 0) {
4175
+ this._activeHiPS = null;
4176
+ if (this._activeBaseLayer === "hips") {
4177
+ this._activeBaseLayer = null;
4178
+ }
4179
+ return;
4180
+ }
4181
+ if (this._activeHiPS === hips) {
4182
+ this._activeHiPS =
4183
+ this._activeHiPSLayers[this._activeHiPSLayers.length - 1];
4184
+ }
4185
+ }
4186
+ removeAllHiPS() {
4187
+ const tileBuffer = this._healpixGrid.visibleTilesManager.tileBuffer;
4188
+ for (const hips of this._activeHiPSLayers) {
4189
+ tileBuffer.removeHiPS(hips);
4190
+ }
4191
+ this._activeHiPSLayers = [];
4192
+ this._activeHiPS = null;
4193
+ if (this._activeBaseLayer === "hips") {
4194
+ this._activeBaseLayer = null;
4195
+ }
4140
4196
  }
4141
4197
  activateXYZ(config) {
4142
4198
  this.activateXYZ2(new XYZMapDescriptor_js_1.XYZMapDescriptor(config.name ?? "XYZ Earth2 Layer", config.urlTemplate, config.minZoom ?? 0, config.maxZoom ?? 8, config.segmentsPerSide ?? 48, config.maxCachedTiles ?? 384, 8, config.urlResolver));
@@ -4369,6 +4425,16 @@ class AstroSphere {
4369
4425
  get activeHiPS() {
4370
4426
  return this._activeHiPS;
4371
4427
  }
4428
+ get activeHiPSLayers() {
4429
+ return this._activeHiPSLayers;
4430
+ }
4431
+ setActiveHiPS(hips) {
4432
+ if (!this._activeHiPSLayers.includes(hips)) {
4433
+ throw new Error("HiPS layer is not active in this AstroSphere.");
4434
+ }
4435
+ this._activeHiPS = hips;
4436
+ this._activeBaseLayer = "hips";
4437
+ }
4372
4438
  get activeXYZ() {
4373
4439
  return this._activeXYZ2;
4374
4440
  }
@@ -4528,8 +4594,9 @@ class AstroSphere {
4528
4594
  this._webgl.enable(this._webgl.CULL_FACE);
4529
4595
  this._webgl.cullFace(Global_js_1.default.insideSphere ? this._webgl.FRONT : this._webgl.BACK);
4530
4596
  this._webgl.blendFunc(this._webgl.SRC_ALPHA, this._webgl.ONE_MINUS_SRC_ALPHA);
4531
- if (this._activeBaseLayer === "hips" && this._activeHiPS) {
4532
- const visibleOrder = Math.min(this._healpixGrid.visibleorder, this._activeHiPS.maxOrder);
4597
+ if (this._activeBaseLayer === "hips" && this._activeHiPSLayers.length > 0) {
4598
+ const maxHiPSOrder = Math.max(...this._activeHiPSLayers.map((hips) => hips.maxOrder));
4599
+ const visibleOrder = Math.min(this._healpixGrid.visibleorder, maxHiPSOrder);
4533
4600
  this._healpixGrid.visibleTilesManager.computeVisiblePixels(visibleOrder, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
4534
4601
  }
4535
4602
  if (this._activeBaseLayer === "meships" && this._activeMeshHiPS) {
@@ -4544,14 +4611,6 @@ class AstroSphere {
4544
4611
  Math.abs(this.inertiaX) > 0.02 ||
4545
4612
  Math.abs(this.inertiaY) > 0.02 ||
4546
4613
  nowForGrid - this.lastCameraMotionAt < 220;
4547
- // const skyEntityDrawInput: SkyEntityDrawInput = {
4548
- // fovDeg: this._healpixGrid.getMinFoV(),
4549
- // camera: this._camera,
4550
- // pMatrix: this._perspectiveMatrixManager.pMatrix,
4551
- // centerSphericalDeg: this.updateCentralPoint().sphericalDeg,
4552
- // fovPolygon: this._activeBaseLayer === 'xyz' ? this.getFoVPolygon() : undefined,
4553
- // viewportSphericalSamples: this._activeBaseLayer === 'xyz' ? this.collectViewportSphericalSamples(7) : undefined,
4554
- // }
4555
4614
  const skyEntityDrawInput = {
4556
4615
  fovDeg: stableFovDeg,
4557
4616
  camera: this._camera,
@@ -4562,6 +4621,11 @@ class AstroSphere {
4562
4621
  cameraMoving: cameraMovingForGrid,
4563
4622
  };
4564
4623
  if (this._activeBaseLayer === "hips") {
4624
+ for (const hips of this._activeHiPSLayers) {
4625
+ if (hips !== this._activeHiPS) {
4626
+ hips.draw(skyEntityDrawInput);
4627
+ }
4628
+ }
4565
4629
  this._activeHiPS?.draw(skyEntityDrawInput);
4566
4630
  }
4567
4631
  if (this._activeBaseLayer === "xyz") {
@@ -4703,7 +4767,7 @@ class AstroViewer {
4703
4767
  webglContextList = new Map();
4704
4768
  viewfinderEl = null;
4705
4769
  viewfinderVisible = Config_js_1.bootSetup.showViewfinder;
4706
- viewfinderColor = 'rgba(75,148,226,0.68)';
4770
+ viewfinderColor = "rgba(75,148,226,0.68)";
4707
4771
  options = {};
4708
4772
  // API
4709
4773
  run() {
@@ -4841,7 +4905,7 @@ class AstroViewer {
4841
4905
  this.astroSphere.activateXYZ(config);
4842
4906
  }
4843
4907
  activateXYZ2(config) {
4844
- const descriptor = new XYZMapDescriptor_js_1.XYZMapDescriptor(config.name ?? 'XYZ Earth2 Layer', config.urlTemplate, config.minZoom ?? 0, config.maxZoom ?? 8, config.segmentsPerSide ?? 48, config.maxCachedTiles ?? 384, 8, config.urlResolver);
4908
+ const descriptor = new XYZMapDescriptor_js_1.XYZMapDescriptor(config.name ?? "XYZ Earth2 Layer", config.urlTemplate, config.minZoom ?? 0, config.maxZoom ?? 8, config.segmentsPerSide ?? 48, config.maxCachedTiles ?? 384, 8, config.urlResolver);
4845
4909
  this.astroSphere.activateXYZ2(descriptor);
4846
4910
  }
4847
4911
  activateWMTS(config) {
@@ -4866,8 +4930,8 @@ class AstroViewer {
4866
4930
  return this.astroSphere.getMeshHiPSDebugStats();
4867
4931
  }
4868
4932
  async loadHiPS(baseUrl) {
4869
- const hipsUrl = baseUrl.endsWith('/') ? baseUrl : baseUrl + '/';
4870
- const resp = await fetch(hipsUrl + 'properties');
4933
+ const hipsUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
4934
+ const resp = await fetch(hipsUrl + "properties");
4871
4935
  if (!resp.ok)
4872
4936
  throw new Error(`HTTP ${resp.status} fetching properties`);
4873
4937
  const propsText = await resp.text();
@@ -4877,37 +4941,69 @@ class AstroViewer {
4877
4941
  // this.activateHiPS(desc);
4878
4942
  }
4879
4943
  async loadMeshHiPS(baseUrl, config = {}) {
4880
- const meshHiPSUrl = baseUrl.endsWith('/') ? baseUrl : baseUrl + '/';
4881
- let propsText = '';
4882
- const resp = await fetch(meshHiPSUrl + 'properties');
4944
+ const meshHiPSUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
4945
+ let propsText = "";
4946
+ const resp = await fetch(meshHiPSUrl + "properties");
4883
4947
  if (resp.ok) {
4884
4948
  propsText = await resp.text();
4885
4949
  }
4886
4950
  else {
4887
- const jsonResp = await fetch(meshHiPSUrl + 'properties.json');
4951
+ const jsonResp = await fetch(meshHiPSUrl + "properties.json");
4888
4952
  if (!jsonResp.ok)
4889
4953
  throw new Error(`HTTP ${jsonResp.status} fetching MeshHiPS properties`);
4890
4954
  const json = await jsonResp.json();
4891
4955
  propsText = Object.entries(json)
4892
4956
  .map(([key, value]) => `${key}=${String(value)}`)
4893
- .join('\n');
4957
+ .join("\n");
4894
4958
  }
4895
4959
  const desc = new MeshHiPSDescriptor_js_1.MeshHiPSDescriptor({ ...config, baseUrl: meshHiPSUrl }, propsText);
4896
4960
  this.astroSphere.activateMeshHiPS(desc);
4897
4961
  return desc.name;
4898
4962
  }
4899
- // changeColorMap(hips: HiPS, colorMapName: ColorMapName) {
4963
+ setActiveHiPS(hips) {
4964
+ this.astroSphere.setActiveHiPS(hips);
4965
+ }
4966
+ setHiPSOpacity(hips, opacity) {
4967
+ this.astroSphere.setHiPSOpacity(hips, opacity);
4968
+ }
4900
4969
  changeColorMap(colorMapName) {
4901
4970
  const colorMap = ColorMaps_js_1.default[colorMapName];
4902
- // hips.changeColorMap(colorMap)
4903
4971
  this.astroSphere.changeColorMap(colorMap);
4904
4972
  }
4905
4973
  changeCustomColorMap(colorMap) {
4906
4974
  this.astroSphere.changeColorMap(colorMap);
4907
4975
  }
4976
+ addHiPS(hipsDescriptor) {
4977
+ return this.astroSphere.addHiPS(hipsDescriptor);
4978
+ }
4979
+ async addHiPSFromUrl(baseUrl) {
4980
+ const hipsUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
4981
+ const resp = await fetch(hipsUrl + "properties");
4982
+ if (!resp.ok) {
4983
+ throw new Error(`HTTP ${resp.status} fetching properties`);
4984
+ }
4985
+ const propsText = await resp.text();
4986
+ const desc = new HiPSDescriptor_js_1.HiPSDescriptor(propsText, hipsUrl);
4987
+ return this.astroSphere.addHiPS(desc);
4988
+ }
4989
+ removeHiPS(hips) {
4990
+ this.astroSphere.removeHiPS(hips);
4991
+ }
4992
+ removeAllHiPS() {
4993
+ this.astroSphere.removeAllHiPS();
4994
+ }
4995
+ getActiveHiPSLayers() {
4996
+ return this.astroSphere.activeHiPSLayers;
4997
+ }
4908
4998
  getActiveHiPS() {
4909
4999
  return this.astroSphere.activeHiPS;
4910
5000
  }
5001
+ changeHiPSFormat(format) {
5002
+ this.astroSphere.changeHiPSFormat(format);
5003
+ }
5004
+ getActiveHiPSFormats() {
5005
+ return this.astroSphere.activeHiPS?.availableFormats ?? [];
5006
+ }
4911
5007
  getActiveXYZ() {
4912
5008
  return this.astroSphere.activeXYZ;
4913
5009
  }
@@ -4995,13 +5091,13 @@ class AstroViewer {
4995
5091
  return this.astroSphere.getFoVPolygon();
4996
5092
  }
4997
5093
  changeFoV(deg) {
4998
- this, this.astroSphere.changeFoV(deg);
5094
+ (this, this.astroSphere.changeFoV(deg));
4999
5095
  }
5000
5096
  changeFoV2(deg) {
5001
- this, this.astroSphere.changeFoV2(deg);
5097
+ (this, this.astroSphere.changeFoV2(deg));
5002
5098
  }
5003
5099
  changeFoV3(deg) {
5004
- this, this.astroSphere.changeFoV3(deg);
5100
+ (this, this.astroSphere.changeFoV3(deg));
5005
5101
  }
5006
5102
  getInsideSphere() {
5007
5103
  return this.astroSphere.getInsideSphere();
@@ -5047,13 +5143,13 @@ class AstroViewer {
5047
5143
  this.webglContextList = new Map();
5048
5144
  }
5049
5145
  init(canvasEl) {
5050
- console.log('init webgl');
5146
+ console.log("init webgl");
5051
5147
  this.canvas = canvasEl;
5052
5148
  this.initViewfinder();
5053
- const gl = this.canvas.getContext('webgl2', { alpha: false });
5149
+ const gl = this.canvas.getContext("webgl2", { alpha: false });
5054
5150
  if (!gl) {
5055
- alert('Could not initialise WebGL, sorry :-(');
5056
- throw new Error('WebGL2 not available');
5151
+ alert("Could not initialise WebGL, sorry :-(");
5152
+ throw new Error("WebGL2 not available");
5057
5153
  }
5058
5154
  // Extend with custom fields used elsewhere
5059
5155
  this.webgl = gl;
@@ -5064,7 +5160,7 @@ class AstroViewer {
5064
5160
  this.webgl.clearColor(0 * 0.00392156862, 16 * 0.00392156862, 50 * 0.00392156862, 0.7);
5065
5161
  }
5066
5162
  catch (e) {
5067
- console.log('Error instantiating WebGL context');
5163
+ console.log("Error instantiating WebGL context");
5068
5164
  }
5069
5165
  this.initListeners();
5070
5166
  // ; (global as any).gl = this.webgl
@@ -5076,40 +5172,64 @@ class AstroViewer {
5076
5172
  const parent = this.canvas.parentElement;
5077
5173
  if (!parent)
5078
5174
  return;
5079
- if (window.getComputedStyle(parent).position === 'static') {
5080
- parent.style.position = 'relative';
5081
- }
5082
- const viewfinder = document.createElement('div');
5083
- viewfinder.setAttribute('data-astro-viewfinder', 'true');
5084
- viewfinder.setAttribute('aria-hidden', 'true');
5085
- viewfinder.style.position = 'absolute';
5086
- viewfinder.style.left = '50%';
5087
- viewfinder.style.top = '50%';
5088
- viewfinder.style.width = '44px';
5089
- viewfinder.style.height = '44px';
5090
- viewfinder.style.transform = 'translate(-50%, -50%)';
5091
- viewfinder.style.pointerEvents = 'none';
5092
- viewfinder.style.zIndex = '1';
5093
- viewfinder.style.boxSizing = 'border-box';
5175
+ if (window.getComputedStyle(parent).position === "static") {
5176
+ parent.style.position = "relative";
5177
+ }
5178
+ const viewfinder = document.createElement("div");
5179
+ viewfinder.setAttribute("data-astro-viewfinder", "true");
5180
+ viewfinder.setAttribute("aria-hidden", "true");
5181
+ viewfinder.style.position = "absolute";
5182
+ viewfinder.style.left = "50%";
5183
+ viewfinder.style.top = "50%";
5184
+ viewfinder.style.width = "44px";
5185
+ viewfinder.style.height = "44px";
5186
+ viewfinder.style.transform = "translate(-50%, -50%)";
5187
+ viewfinder.style.pointerEvents = "none";
5188
+ viewfinder.style.zIndex = "1";
5189
+ viewfinder.style.boxSizing = "border-box";
5094
5190
  const segments = [
5095
- { left: '50%', top: '7px', width: '1px', height: '11px', transform: 'translateX(-50%)' },
5096
- { left: '50%', bottom: '7px', width: '1px', height: '11px', transform: 'translateX(-50%)' },
5097
- { left: '7px', top: '50%', width: '11px', height: '1px', transform: 'translateY(-50%)' },
5098
- { right: '7px', top: '50%', width: '11px', height: '1px', transform: 'translateY(-50%)' },
5191
+ {
5192
+ left: "50%",
5193
+ top: "7px",
5194
+ width: "1px",
5195
+ height: "11px",
5196
+ transform: "translateX(-50%)",
5197
+ },
5198
+ {
5199
+ left: "50%",
5200
+ bottom: "7px",
5201
+ width: "1px",
5202
+ height: "11px",
5203
+ transform: "translateX(-50%)",
5204
+ },
5205
+ {
5206
+ left: "7px",
5207
+ top: "50%",
5208
+ width: "11px",
5209
+ height: "1px",
5210
+ transform: "translateY(-50%)",
5211
+ },
5212
+ {
5213
+ right: "7px",
5214
+ top: "50%",
5215
+ width: "11px",
5216
+ height: "1px",
5217
+ transform: "translateY(-50%)",
5218
+ },
5099
5219
  ];
5100
5220
  for (const segmentDef of segments) {
5101
- const segment = document.createElement('div');
5102
- segment.style.position = 'absolute';
5103
- segment.style.left = segmentDef.left ?? 'auto';
5104
- segment.style.right = segmentDef.right ?? 'auto';
5105
- segment.style.top = segmentDef.top ?? 'auto';
5106
- segment.style.bottom = segmentDef.bottom ?? 'auto';
5221
+ const segment = document.createElement("div");
5222
+ segment.style.position = "absolute";
5223
+ segment.style.left = segmentDef.left ?? "auto";
5224
+ segment.style.right = segmentDef.right ?? "auto";
5225
+ segment.style.top = segmentDef.top ?? "auto";
5226
+ segment.style.bottom = segmentDef.bottom ?? "auto";
5107
5227
  segment.style.width = segmentDef.width;
5108
5228
  segment.style.height = segmentDef.height;
5109
5229
  segment.style.transform = segmentDef.transform;
5110
- segment.style.background = 'currentColor';
5111
- segment.style.borderRadius = '999px';
5112
- segment.style.boxShadow = '0 0 0 1px rgba(0, 0, 0, 0.14)';
5230
+ segment.style.background = "currentColor";
5231
+ segment.style.borderRadius = "999px";
5232
+ segment.style.boxShadow = "0 0 0 1px rgba(0, 0, 0, 0.14)";
5113
5233
  viewfinder.appendChild(segment);
5114
5234
  }
5115
5235
  parent.appendChild(viewfinder);
@@ -5120,7 +5240,7 @@ class AstroViewer {
5120
5240
  syncViewfinderVisibility() {
5121
5241
  if (!this.viewfinderEl)
5122
5242
  return;
5123
- this.viewfinderEl.style.display = this.viewfinderVisible ? 'block' : 'none';
5243
+ this.viewfinderEl.style.display = this.viewfinderVisible ? "block" : "none";
5124
5244
  }
5125
5245
  syncViewfinderColor() {
5126
5246
  if (!this.viewfinderEl)
@@ -5128,9 +5248,9 @@ class AstroViewer {
5128
5248
  this.viewfinderEl.style.color = this.viewfinderColor;
5129
5249
  }
5130
5250
  initListeners() {
5131
- console.log('inside initListeners');
5251
+ console.log("inside initListeners");
5132
5252
  const resizeCanvas = () => {
5133
- console.log('[resizeCanvas]');
5253
+ console.log("[resizeCanvas]");
5134
5254
  const rect = this.canvas.getBoundingClientRect();
5135
5255
  const dpr = window.devicePixelRatio || 1;
5136
5256
  const newWidth = Math.max(1, Math.floor(rect.width * dpr));
@@ -5144,7 +5264,7 @@ class AstroViewer {
5144
5264
  }
5145
5265
  };
5146
5266
  const handleContextLost = (event) => {
5147
- console.log('[handleContextLost]');
5267
+ console.log("[handleContextLost]");
5148
5268
  event.preventDefault();
5149
5269
  if (this.rafId !== null) {
5150
5270
  cancelAnimationFrame(this.rafId);
@@ -5152,7 +5272,7 @@ class AstroViewer {
5152
5272
  }
5153
5273
  };
5154
5274
  const handleContextRestored = (_event) => {
5155
- console.log('[handleContextRestored]');
5275
+ console.log("[handleContextRestored]");
5156
5276
  // this.webgl.viewportWidth = this.canvas.width
5157
5277
  // this.webgl.viewportHeight = this.canvas.height
5158
5278
  this.webgl.clearColor(0 * 0.00392156862, 16 * 0.00392156862, 50 * 0.00392156862, 0.7);
@@ -5160,16 +5280,16 @@ class AstroViewer {
5160
5280
  this.rafId = requestAnimationFrame(() => this.tick());
5161
5281
  };
5162
5282
  // 🔥 ResizeObserver per pannelli / split / layout dinamici
5163
- if ('ResizeObserver' in window) {
5283
+ if ("ResizeObserver" in window) {
5164
5284
  const ro = new ResizeObserver(() => {
5165
5285
  resizeCanvas();
5166
5286
  });
5167
5287
  // Osserva il canvas o il suo parent (a tua scelta)
5168
5288
  ro.observe(this.canvas);
5169
5289
  }
5170
- window.addEventListener('resize', resizeCanvas);
5171
- this.canvas.addEventListener('webglcontextlost', handleContextLost, false);
5172
- this.canvas.addEventListener('webglcontextrestored', handleContextRestored, false);
5290
+ window.addEventListener("resize", resizeCanvas);
5291
+ this.canvas.addEventListener("webglcontextlost", handleContextLost, false);
5292
+ this.canvas.addEventListener("webglcontextrestored", handleContextRestored, false);
5173
5293
  resizeCanvas();
5174
5294
  }
5175
5295
  tick() {
@@ -11887,6 +12007,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
11887
12007
  };
11888
12008
  Object.defineProperty(exports, "__esModule", ({ value: true }));
11889
12009
  const Global_js_1 = __importDefault(__webpack_require__(4382));
12010
+ const FitsTileLoader_js_1 = __webpack_require__(1399);
11890
12011
  class AllSky {
11891
12012
  _ready = false;
11892
12013
  _hips;
@@ -11894,11 +12015,12 @@ class AllSky {
11894
12015
  _baseurl;
11895
12016
  _isGalacticHips;
11896
12017
  _order = 3;
11897
- opacity = 1.0;
12018
+ // public opacity = 1.0;
11898
12019
  _hipsShaderIndex = 0;
11899
12020
  _texture = null;
11900
12021
  _image;
11901
12022
  _texurl;
12023
+ _fitsTile;
11902
12024
  _textureLoaded = false;
11903
12025
  _maxTiles = 0;
11904
12026
  _numFacesXTile = 0;
@@ -11921,15 +12043,34 @@ class AllSky {
11921
12043
  this.initImage();
11922
12044
  }
11923
12045
  initImage() {
11924
- this._image = new Image();
11925
12046
  this._texurl = `${this._baseurl}/Norder3/Allsky.${this._format}`;
12047
+ if (this._format === "fits") {
12048
+ void this.loadFits();
12049
+ return;
12050
+ }
12051
+ this.loadImage();
12052
+ }
12053
+ loadImage() {
12054
+ this._image = new Image();
11926
12055
  this._image.onload = () => this.imageLoaded();
11927
12056
  this._image.onerror = () => {
11928
- console.error('File not found? %s', this._texurl);
12057
+ console.error("File not found? %s", this._texurl);
11929
12058
  };
11930
- this._image.setAttribute('crossorigin', 'anonymous');
12059
+ this._image.setAttribute("crossorigin", "anonymous");
11931
12060
  this._image.src = this._texurl;
11932
12061
  }
12062
+ async loadFits() {
12063
+ try {
12064
+ this._fitsTile = await (0, FitsTileLoader_js_1.loadFitsTile)(this._texurl);
12065
+ this.textureLoaded();
12066
+ this.initModelBuffer();
12067
+ this._textureLoaded = true;
12068
+ this._ready = true;
12069
+ }
12070
+ catch (error) {
12071
+ console.error(`[AllSky] Unable to load FITS atlas ${this._texurl}`, error);
12072
+ }
12073
+ }
11933
12074
  imageLoaded() {
11934
12075
  this.textureLoaded();
11935
12076
  this.initModelBuffer();
@@ -11937,31 +12078,58 @@ class AllSky {
11937
12078
  this._ready = true;
11938
12079
  }
11939
12080
  textureLoaded() {
11940
- // hipsShaderProgram.enableProgram()
11941
12081
  this._hipsShaderProgram.enableProgram();
11942
12082
  const gl = this._webgl;
11943
12083
  this._texture = gl.createTexture();
11944
12084
  gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
11945
- gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
12085
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._format !== "fits");
11946
12086
  gl.bindTexture(gl.TEXTURE_2D, this._texture);
11947
- // gl.uniform1i(hipsShaderProgram.shaderProgram.samplerUniform, this._hipsShaderIndex)
11948
- if (!gl.isTexture(this._texture)) {
11949
- console.log('error in texture');
12087
+ if (this._format === "fits") {
12088
+ const fits = this._fitsTile;
12089
+ if (!fits) {
12090
+ throw new Error(`FITS AllSky data not loaded: ${this._texurl}`);
12091
+ }
12092
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, fits.width, fits.height, 0, gl.RED, gl.FLOAT, fits.pixels);
12093
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
12094
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
12095
+ }
12096
+ else {
12097
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
12098
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
12099
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
12100
+ gl.generateMipmap(gl.TEXTURE_2D);
11950
12101
  }
11951
- gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
11952
- gl.bindTexture(gl.TEXTURE_2D, this._texture);
11953
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
11954
12102
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
11955
12103
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
11956
- const useMipmaps = true;
11957
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useMipmaps ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR);
11958
- // MAG filter: ONLY NEAREST or LINEAR are valid
11959
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
11960
- // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)
11961
- // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR_MIPMAP_LINEAR)
11962
- // gl.generateMipmap(gl.TEXTURE_2D)
11963
- if (useMipmaps)
11964
- gl.generateMipmap(gl.TEXTURE_2D);
12104
+ if (!gl.isTexture(this._texture)) {
12105
+ console.log("error in texture");
12106
+ }
12107
+ }
12108
+ getFitsDataRange() {
12109
+ const hipsRange = this._hips.dataRange;
12110
+ if (hipsRange.min !== undefined &&
12111
+ hipsRange.max !== undefined &&
12112
+ Number.isFinite(hipsRange.min) &&
12113
+ Number.isFinite(hipsRange.max) &&
12114
+ hipsRange.max > hipsRange.min) {
12115
+ return {
12116
+ min: hipsRange.min,
12117
+ max: hipsRange.max,
12118
+ };
12119
+ }
12120
+ const fits = this._fitsTile;
12121
+ if (fits &&
12122
+ fits.dataMin !== null &&
12123
+ fits.dataMax !== null &&
12124
+ Number.isFinite(fits.dataMin) &&
12125
+ Number.isFinite(fits.dataMax) &&
12126
+ fits.dataMax > fits.dataMin) {
12127
+ return {
12128
+ min: fits.dataMin,
12129
+ max: fits.dataMax,
12130
+ };
12131
+ }
12132
+ return null;
11965
12133
  }
11966
12134
  initModelBuffer() {
11967
12135
  const gl = this._webgl;
@@ -12026,13 +12194,16 @@ class AllSky {
12026
12194
  this.vertexPosition[20 * this.vidx] = facesVec3Array[0].x;
12027
12195
  this.vertexPosition[20 * this.vidx + 1] = facesVec3Array[0].y;
12028
12196
  this.vertexPosition[20 * this.vidx + 2] = facesVec3Array[0].z;
12029
- this.vertexPosition[20 * this.vidx + 3] = s_step + base_s - s_pixel_size;
12030
- this.vertexPosition[20 * this.vidx + 4] = 1 - (t_step + base_t) + t_pixel_size;
12197
+ this.vertexPosition[20 * this.vidx + 3] =
12198
+ s_step + base_s - s_pixel_size;
12199
+ this.vertexPosition[20 * this.vidx + 4] =
12200
+ 1 - (t_step + base_t) + t_pixel_size;
12031
12201
  // top right
12032
12202
  this.vertexPosition[20 * this.vidx + 5] = facesVec3Array[1].x;
12033
12203
  this.vertexPosition[20 * this.vidx + 6] = facesVec3Array[1].y;
12034
12204
  this.vertexPosition[20 * this.vidx + 7] = facesVec3Array[1].z;
12035
- this.vertexPosition[20 * this.vidx + 8] = s_step + base_s - s_pixel_size;
12205
+ this.vertexPosition[20 * this.vidx + 8] =
12206
+ s_step + base_s - s_pixel_size;
12036
12207
  this.vertexPosition[20 * this.vidx + 9] = 1 - base_t - t_pixel_size;
12037
12208
  // top left
12038
12209
  this.vertexPosition[20 * this.vidx + 10] = facesVec3Array[2].x;
@@ -12045,7 +12216,8 @@ class AllSky {
12045
12216
  this.vertexPosition[20 * this.vidx + 16] = facesVec3Array[3].y;
12046
12217
  this.vertexPosition[20 * this.vidx + 17] = facesVec3Array[3].z;
12047
12218
  this.vertexPosition[20 * this.vidx + 18] = base_s + s_pixel_size;
12048
- this.vertexPosition[20 * this.vidx + 19] = 1 - (t_step + base_t) + t_pixel_size;
12219
+ this.vertexPosition[20 * this.vidx + 19] =
12220
+ 1 - (t_step + base_t) + t_pixel_size;
12049
12221
  this.vidx++;
12050
12222
  }
12051
12223
  }
@@ -12065,6 +12237,17 @@ class AllSky {
12065
12237
  }
12066
12238
  const gl = this._webgl;
12067
12239
  this._hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx);
12240
+ if (this._format === "fits") {
12241
+ const range = this.getFitsDataRange();
12242
+ if (!range) {
12243
+ console.error(`[AllSky] No display range available for FITS atlas ${this._texurl}`);
12244
+ return false;
12245
+ }
12246
+ this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max);
12247
+ }
12248
+ else {
12249
+ this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, false);
12250
+ }
12068
12251
  gl.enableVertexAttribArray(this._hipsShaderProgram.locations.vertexPositionAttribute);
12069
12252
  gl.enableVertexAttribArray(this._hipsShaderProgram.locations.textureCoordAttribute);
12070
12253
  // hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx)
@@ -12072,8 +12255,11 @@ class AllSky {
12072
12255
  // gl.enableVertexAttribArray((hipsShaderProgram as any).locations.textureCoordAttribute)
12073
12256
  gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
12074
12257
  gl.bindTexture(gl.TEXTURE_2D, this._texture);
12075
- // gl.uniform1f(hipsShaderProgram.locations.textureAlpha, this.opacity)
12076
- gl.uniform1f(this._hipsShaderProgram.locations.textureAlpha, this.opacity);
12258
+ const factorLocation = this._hipsShaderProgram.locations.textureAlpha[this._hipsShaderIndex];
12259
+ if (factorLocation !== null) {
12260
+ gl.uniform1f(factorLocation, 1.0);
12261
+ }
12262
+ this._hipsShaderProgram.setLayerOpacity(this._hips.opacity);
12077
12263
  gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBuffer);
12078
12264
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
12079
12265
  gl.vertexAttribPointer(
@@ -12101,13 +12287,13 @@ class AllSky {
12101
12287
  const allSkyTiles2Skip = [];
12102
12288
  for (let i = 0; i < visibleTiles.length; i++) {
12103
12289
  const tileno = visibleTiles[i];
12290
+ if (!this._hips.intersectsCoverage(childrenOrder, tileno)) {
12291
+ allSkyTiles2Skip.push(tileno);
12292
+ continue;
12293
+ }
12104
12294
  const childTile = this._isGalacticHips
12105
12295
  ? this._tileBuffer.getGalTile(tileno, childrenOrder, this._hips)
12106
12296
  : this._tileBuffer.getTile(tileno, childrenOrder, this._hips);
12107
- // const childTile = this._isGalacticHips
12108
- // ? newTileBuffer.getGalTile(tileno, childrenOrder, this._hips)
12109
- // : newTileBuffer.getTile(tileno, childrenOrder, this._hips)
12110
- // childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx)
12111
12297
  childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx, this._hipsShaderProgram);
12112
12298
  if (childTile.getReadyState()) {
12113
12299
  allSkyTiles2Skip.push(tileno);
@@ -12141,6 +12327,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12141
12327
  Object.defineProperty(exports, "__esModule", ({ value: true }));
12142
12328
  const Global_js_1 = __importDefault(__webpack_require__(4382));
12143
12329
  const FoVHelper_js_1 = __webpack_require__(229);
12330
+ const FitsTileLoader_js_1 = __webpack_require__(1399);
12144
12331
  class AncestorTile {
12145
12332
  _hips;
12146
12333
  _tileno;
@@ -12154,7 +12341,8 @@ class AncestorTile {
12154
12341
  _pixels = [];
12155
12342
  _texture = null;
12156
12343
  _image;
12157
- _texurl = '';
12344
+ _texurl = "";
12345
+ _fitsTile;
12158
12346
  vertexPosition;
12159
12347
  vertexPositionBuffer;
12160
12348
  vertexIndices;
@@ -12180,14 +12368,41 @@ class AncestorTile {
12180
12368
  }
12181
12369
  initImage() {
12182
12370
  const dirnumber = Math.floor(this._tileno / 10000) * 10000;
12183
- this._texurl = `${this._baseurl}/Norder${this._order}/Dir${dirnumber}/Npix${this._tileno}.${this._format}`;
12371
+ this._texurl =
12372
+ `${this._baseurl}/Norder${this._order}/Dir${dirnumber}` +
12373
+ `/Npix${this._tileno}.${this._format}`;
12374
+ if (this._format === "fits") {
12375
+ void this.loadFits();
12376
+ return;
12377
+ }
12378
+ this.loadImage();
12379
+ }
12380
+ async loadFits() {
12381
+ try {
12382
+ this._fitsTile = await (0, FitsTileLoader_js_1.loadFitsTile)(this._texurl);
12383
+ this.textureLoaded();
12384
+ const fits = this._fitsTile;
12385
+ if (!fits) {
12386
+ throw new Error(`FITS tile data not loaded: ${this._texurl}`);
12387
+ }
12388
+ const gl = this._webgl;
12389
+ gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
12390
+ gl.bindTexture(gl.TEXTURE_2D, this._texture);
12391
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, fits.width, fits.height, 0, gl.RED, gl.FLOAT, fits.pixels);
12392
+ this.initModelBuffer();
12393
+ this._ready = true;
12394
+ }
12395
+ catch (error) {
12396
+ console.error(`[AncestorTile] Unable to load FITS tile ${this._texurl}`, error);
12397
+ }
12398
+ }
12399
+ loadImage() {
12184
12400
  this._image = new Image();
12185
12401
  this._image.onload = () => this.imageLoaded();
12186
12402
  this._image.onerror = () => {
12187
- console.error('File not found? %s', this._texurl);
12403
+ console.error("File not found? %s", this._texurl);
12188
12404
  };
12189
- this._image.crossOrigin = 'anonymous';
12190
- // If you ever need FITS handling, call this.loadImage() instead.
12405
+ this._image.crossOrigin = "anonymous";
12191
12406
  this._image.src = this._texurl;
12192
12407
  }
12193
12408
  imageLoaded() {
@@ -12205,15 +12420,47 @@ class AncestorTile {
12205
12420
  const gl = this._webgl;
12206
12421
  this._texture = gl.createTexture();
12207
12422
  gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
12208
- gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
12423
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._format !== "fits");
12209
12424
  gl.bindTexture(gl.TEXTURE_2D, this._texture);
12210
12425
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
12211
12426
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
12212
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
12213
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
12427
+ if (this._format === "fits") {
12428
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
12429
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
12430
+ }
12431
+ else {
12432
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
12433
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
12434
+ }
12214
12435
  if (!gl.isTexture(this._texture)) {
12215
- console.log('error in texture');
12436
+ console.log("error in texture");
12437
+ }
12438
+ }
12439
+ getFitsDataRange() {
12440
+ const hipsRange = this._hips.dataRange;
12441
+ if (hipsRange.min !== undefined &&
12442
+ hipsRange.max !== undefined &&
12443
+ Number.isFinite(hipsRange.min) &&
12444
+ Number.isFinite(hipsRange.max) &&
12445
+ hipsRange.max > hipsRange.min) {
12446
+ return {
12447
+ min: hipsRange.min,
12448
+ max: hipsRange.max,
12449
+ };
12216
12450
  }
12451
+ const fits = this._fitsTile;
12452
+ if (fits &&
12453
+ fits.dataMin !== null &&
12454
+ fits.dataMax !== null &&
12455
+ Number.isFinite(fits.dataMin) &&
12456
+ Number.isFinite(fits.dataMax) &&
12457
+ fits.dataMax > fits.dataMin) {
12458
+ return {
12459
+ min: fits.dataMin,
12460
+ max: fits.dataMax,
12461
+ };
12462
+ }
12463
+ return null;
12217
12464
  }
12218
12465
  initModelBuffer() {
12219
12466
  const gl = this._webgl;
@@ -12256,43 +12503,6 @@ class AncestorTile {
12256
12503
  }
12257
12504
  return vertexIndices;
12258
12505
  }
12259
- // Version that uses getPointsForXyfNoStep (kept for reference; not used in this class)
12260
- setupPositionAndTexture4Quadrant2(dxmin, dxmax, dymin, dymax, qidx, healpix, orderjump, origxyf) {
12261
- this.vertexPosition[qidx] = new Float32Array(20 * (dxmax - dxmin) * (dymax - dymin));
12262
- const step = 1 / (1 << orderjump);
12263
- let p = 0;
12264
- for (let dx = dxmin; dx < dxmax; dx++) {
12265
- for (let dy = dymin; dy < dymax; dy++) {
12266
- const facesVec3Array = healpix.getPointsForXyfNoStep(dx, dy, origxyf.face);
12267
- const uindex = dy - (origxyf.iy << orderjump);
12268
- const vindex = dx - (origxyf.ix << orderjump);
12269
- this.vertexPosition[qidx][20 * p] = facesVec3Array[0].x;
12270
- this.vertexPosition[qidx][20 * p + 1] = facesVec3Array[0].y;
12271
- this.vertexPosition[qidx][20 * p + 2] = facesVec3Array[0].z;
12272
- this.vertexPosition[qidx][20 * p + 3] = step + step * uindex;
12273
- this.vertexPosition[qidx][20 * p + 4] = 1 - (step + step * vindex);
12274
- this.vertexPosition[qidx][20 * p + 5] = facesVec3Array[1].x;
12275
- this.vertexPosition[qidx][20 * p + 6] = facesVec3Array[1].y;
12276
- this.vertexPosition[qidx][20 * p + 7] = facesVec3Array[1].z;
12277
- this.vertexPosition[qidx][20 * p + 8] = step + step * uindex;
12278
- this.vertexPosition[qidx][20 * p + 9] = 1 - step * vindex;
12279
- this.vertexPosition[qidx][20 * p + 10] = facesVec3Array[2].x;
12280
- this.vertexPosition[qidx][20 * p + 11] = facesVec3Array[2].y;
12281
- this.vertexPosition[qidx][20 * p + 12] = facesVec3Array[2].z;
12282
- this.vertexPosition[qidx][20 * p + 13] = step * uindex;
12283
- this.vertexPosition[qidx][20 * p + 14] = 1 - step * vindex;
12284
- this.vertexPosition[qidx][20 * p + 15] = facesVec3Array[3].x;
12285
- this.vertexPosition[qidx][20 * p + 16] = facesVec3Array[3].y;
12286
- this.vertexPosition[qidx][20 * p + 17] = facesVec3Array[3].z;
12287
- this.vertexPosition[qidx][20 * p + 18] = step * uindex;
12288
- this.vertexPosition[qidx][20 * p + 19] = 1 - (step + step * vindex);
12289
- p++;
12290
- }
12291
- }
12292
- this.vertexPositionBuffer[qidx] = this._webgl.createBuffer();
12293
- this._webgl.bindBuffer(this._webgl.ARRAY_BUFFER, this.vertexPositionBuffer[qidx]);
12294
- this._webgl.bufferData(this._webgl.ARRAY_BUFFER, this.vertexPosition[qidx], this._webgl.STATIC_DRAW);
12295
- }
12296
12506
  // Version used by the original JS, collecting _pixels via xyf2nest + getBoundaries
12297
12507
  setupPositionAndTexture4Quadrant(dxmin, dxmax, dymin, dymax, qidx, healpix, orderjump, origxyf) {
12298
12508
  const gl = this._webgl;
@@ -12344,12 +12554,26 @@ class AncestorTile {
12344
12554
  quadrantsToDraw = q;
12345
12555
  }
12346
12556
  this._hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx);
12557
+ if (this._format === "fits") {
12558
+ const range = this.getFitsDataRange();
12559
+ if (!range) {
12560
+ console.error(`[AncestorTile] No display range available for FITS tile ${this._texurl}`);
12561
+ return false;
12562
+ }
12563
+ this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max);
12564
+ }
12565
+ else {
12566
+ this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, false);
12567
+ }
12347
12568
  const gl = this._webgl;
12348
12569
  gl.enableVertexAttribArray(this._hipsShaderProgram.locations.vertexPositionAttribute);
12349
12570
  gl.enableVertexAttribArray(this._hipsShaderProgram.locations.textureCoordAttribute);
12350
12571
  gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
12351
12572
  gl.bindTexture(gl.TEXTURE_2D, this._texture);
12352
- gl.uniform1f(this._hipsShaderProgram.locations.textureAlpha, this.opacity);
12573
+ const factorLocation = this._hipsShaderProgram.locations.textureAlpha[this._hipsShaderIndex];
12574
+ if (factorLocation) {
12575
+ gl.uniform1f(factorLocation, this.opacity);
12576
+ }
12353
12577
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
12354
12578
  const elemno = this.vertexIndices.length;
12355
12579
  quadrantsToDraw.forEach((qidx) => {
@@ -12369,15 +12593,21 @@ class AncestorTile {
12369
12593
  return;
12370
12594
  for (let c = 0; c < 4; c++) {
12371
12595
  const childTileNo = (this._tileno << 2) + c;
12596
+ if (!this._hips.intersectsCoverage(childrenOrder, childTileNo)) {
12597
+ continue;
12598
+ }
12372
12599
  const visibleChildren = visibleTilesMap.get(childrenOrder);
12373
12600
  if (visibleChildren.includes(childTileNo)) {
12601
+ if (!this._hips.intersectsCoverage(childrenOrder, childTileNo)) {
12602
+ quadrantsToDraw.delete(c);
12603
+ continue;
12604
+ }
12374
12605
  const childTile = this._isGalacticHips
12375
12606
  ? this._tileBuffer.getGalTile(childTileNo, childrenOrder, this._hips)
12376
12607
  : this._tileBuffer.getTile(childTileNo, childrenOrder, this._hips);
12377
- // childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx)
12378
12608
  childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx, this._hipsShaderProgram);
12379
- if (childTile._ready) {
12380
- quadrantsToDraw.delete(childTile._tileno - (this._tileno << 2));
12609
+ if (childTile.getReadyState()) {
12610
+ quadrantsToDraw.delete(c);
12381
12611
  }
12382
12612
  }
12383
12613
  }
@@ -12387,6 +12617,81 @@ class AncestorTile {
12387
12617
  exports["default"] = AncestorTile;
12388
12618
 
12389
12619
 
12620
+ /***/ },
12621
+
12622
+ /***/ 1399
12623
+ (__unused_webpack_module, exports, __webpack_require__) {
12624
+
12625
+ var __webpack_unused_export__;
12626
+
12627
+ /*
12628
+ * AstroViewer
12629
+ * Copyright (C) Fabrizio Giordano
12630
+ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-AstroViewer-Commercial
12631
+ *
12632
+ * AstroViewer is dual-licensed under the GNU Affero General Public License
12633
+ * version 3 and a separate commercial license.
12634
+ *
12635
+ * See LICENSE.md, LICENSE-AGPL.md, and LICENSE-COMMERCIAL.md for details.
12636
+ */
12637
+ __webpack_unused_export__ = ({ value: true });
12638
+ exports.loadFitsTile = loadFitsTile;
12639
+ const jsfitsio_1 = __webpack_require__(4971);
12640
+ async function loadFitsTile(url) {
12641
+ const fitsFile = await jsfitsio_1.FITSParser.loadFITSFile(url);
12642
+ if (!fitsFile?.primaryHDU) {
12643
+ throw new Error(`Unable to load FITS tile: ${url}`);
12644
+ }
12645
+ const image = fitsFile.primaryHDU;
12646
+ if (image.naxis !== 2) {
12647
+ throw new Error(`Expected a 2D FITS tile, got NAXIS=${image.naxis}: ${url}`);
12648
+ }
12649
+ const [width, height] = image.shape;
12650
+ if (!Number.isInteger(width) ||
12651
+ !Number.isInteger(height) ||
12652
+ width <= 0 ||
12653
+ height <= 0) {
12654
+ throw new Error(`Invalid FITS tile dimensions: ${url}`);
12655
+ }
12656
+ const data = image.typedData;
12657
+ if (!data || data.length !== width * height) {
12658
+ throw new Error(`Invalid FITS tile payload: ${url}`);
12659
+ }
12660
+ if (data instanceof BigInt64Array) {
12661
+ throw new Error(`BITPIX=64 FITS tiles are not supported for HiPS rendering: ${url}`);
12662
+ }
12663
+ const bscale = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.BSCALE) ?? 1;
12664
+ const bzero = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.BZERO) ?? 0;
12665
+ const blank = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.BLANK);
12666
+ const dataMin = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.DATAMIN);
12667
+ const dataMax = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.DATAMAX);
12668
+ const pixels = new Float32Array(data.length);
12669
+ for (let i = 0; i < data.length; i++) {
12670
+ const rawValue = data[i];
12671
+ if (!Number.isFinite(rawValue) || (blank !== null && rawValue === blank)) {
12672
+ pixels[i] = Number.NaN;
12673
+ continue;
12674
+ }
12675
+ pixels[i] = rawValue * bscale + bzero;
12676
+ }
12677
+ return {
12678
+ width,
12679
+ height,
12680
+ pixels,
12681
+ dataMin,
12682
+ dataMax,
12683
+ };
12684
+ }
12685
+ function getNumericHeaderValue(header, key) {
12686
+ const item = header.findById(key);
12687
+ if (!item) {
12688
+ return null;
12689
+ }
12690
+ const value = Number(item.value);
12691
+ return Number.isFinite(value) ? value : null;
12692
+ }
12693
+
12694
+
12390
12695
  /***/ },
12391
12696
 
12392
12697
  /***/ 229
@@ -12579,10 +12884,14 @@ const FoVHelper_js_1 = __webpack_require__(229);
12579
12884
  const ColorMaps_js_1 = __importDefault(__webpack_require__(619));
12580
12885
  const AncestorTile_js_1 = __importDefault(__webpack_require__(2885));
12581
12886
  const AllSky_js_1 = __importDefault(__webpack_require__(2368));
12887
+ const HiPSCoverage_js_1 = __webpack_require__(9912);
12582
12888
  class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12583
12889
  _ancestorTiles;
12584
12890
  _allSkyTile;
12585
12891
  _descriptor;
12892
+ _coverage;
12893
+ _coverageResolved = false;
12894
+ _opacity = 1.0;
12586
12895
  _format;
12587
12896
  _baseurl;
12588
12897
  _maxorder;
@@ -12591,30 +12900,58 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12591
12900
  _allSky = true;
12592
12901
  samplerIdx = 0;
12593
12902
  colorMapIdx = 0;
12594
- colorMap = ColorMaps_js_1.default['native'];
12903
+ colorMap = ColorMaps_js_1.default["native"];
12595
12904
  _healpixGrid;
12596
12905
  // exposed read-only helpers
12597
- get maxOrder() { return this._maxorder; }
12598
- get minOrder() { return this._minorder; }
12599
- get baseURL() { return this._baseurl; }
12600
- get format() { return this._format; }
12601
- get propertiesRawText() { return this._descriptor.propertiesRawText; }
12602
- get properties() { return this._descriptor.properties; }
12906
+ get maxOrder() {
12907
+ return this._maxorder;
12908
+ }
12909
+ get minOrder() {
12910
+ return this._minorder;
12911
+ }
12912
+ get baseURL() {
12913
+ return this._baseurl;
12914
+ }
12915
+ get format() {
12916
+ return this._format;
12917
+ }
12918
+ get propertiesRawText() {
12919
+ return this._descriptor.propertiesRawText;
12920
+ }
12921
+ get properties() {
12922
+ return this._descriptor.properties;
12923
+ }
12603
12924
  constructor(radius, position, xrad, yrad, descriptor, webgl, healpixGrid) {
12604
12925
  super(radius, position, xrad, yrad, descriptor.surveyName, webgl, descriptor.isGalactic);
12605
12926
  this._descriptor = descriptor;
12606
12927
  this.initGL(webgl);
12607
12928
  this._healpixGrid = healpixGrid;
12608
- this._healpixGrid.visibleTilesManager.tileBuffer.addHiPS(this);
12609
- // DEBUG logs kept from JS (optional)
12610
- // eslint-disable-next-line no-console
12611
- console.log('HiPS frame ' + descriptor.hipsFrame);
12612
- // eslint-disable-next-line no-console
12613
- console.log('HiPS minOrder ' + descriptor.minOrder);
12614
- this._format = descriptor.imgFormats[0];
12929
+ this._format = this.selectDefaultFormat(descriptor.imgFormats);
12615
12930
  this._baseurl = descriptor.url;
12616
12931
  this._maxorder = descriptor.maxOrder;
12617
12932
  this._minorder = descriptor.minOrder;
12933
+ this._coverage = new HiPSCoverage_js_1.HiPSCoverage();
12934
+ void this._coverage
12935
+ .load(this._baseurl)
12936
+ .then(() => {
12937
+ this._coverageResolved = true;
12938
+ })
12939
+ .catch((error) => {
12940
+ console.warn(`[HiPS] Coverage unavailable for ${this._baseurl}; continuing without MOC filtering.`, error);
12941
+ this._coverage.clear();
12942
+ this._coverageResolved = true;
12943
+ });
12944
+ if (this.isGalacticHips) {
12945
+ this._healpixGrid.visibleTilesManager.tileBuffer.addGalHiPS(this);
12946
+ }
12947
+ else {
12948
+ this._healpixGrid.visibleTilesManager.tileBuffer.addHiPS(this);
12949
+ }
12950
+ // DEBUG logs kept from JS (optional)
12951
+ // eslint-disable-next-line no-console
12952
+ console.log("HiPS frame " + descriptor.hipsFrame);
12953
+ // eslint-disable-next-line no-console
12954
+ console.log("HiPS minOrder " + descriptor.minOrder);
12618
12955
  this.initShaders();
12619
12956
  // pick initial order from a starting FoV
12620
12957
  const fov = 180;
@@ -12624,39 +12961,77 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12624
12961
  this._allSkyTile = null;
12625
12962
  // auto-detect all-sky: original code forces true
12626
12963
  this._allSky = true;
12964
+ this.initBaseTiles();
12965
+ }
12966
+ setOpacity(opacity) {
12967
+ if (!Number.isFinite(opacity)) {
12968
+ throw new Error(`Invalid HiPS opacity: ${opacity}`);
12969
+ }
12970
+ this._opacity = Math.min(1, Math.max(0, opacity));
12971
+ }
12972
+ get opacity() {
12973
+ return this._opacity;
12974
+ }
12975
+ intersectsCoverage(order, pixel) {
12976
+ /*
12977
+ * While Moc.fits is being resolved, do not start tile requests.
12978
+ *
12979
+ * Once loading has completed:
12980
+ * - valid MOC -> filter using coverage
12981
+ * - unavailable MOC -> HiPSCoverage is cleared and normal loading resumes
12982
+ */
12983
+ if (!this._coverageResolved) {
12984
+ return false;
12985
+ }
12986
+ return this._coverage.intersectsTile(order, pixel);
12987
+ }
12988
+ get coverageLoaded() {
12989
+ return this._coverage.loaded;
12990
+ }
12991
+ initBaseTiles() {
12992
+ this._ancestorTiles = [];
12993
+ this._allSkyTile = null;
12627
12994
  if (this._allSky) {
12628
12995
  this._allSkyTile = new AllSky_js_1.default(this, this._webgl, this._healpixGrid.visibleTilesManager.tileBuffer, super.hipsShaderProgram);
12996
+ return;
12629
12997
  }
12630
- else {
12631
- for (let t = 0; t < 12; t++) {
12632
- this._ancestorTiles.push(new AncestorTile_js_1.default(t, 0, this, this._healpixGrid.visibleTilesManager.tileBuffer, super.hipsShaderProgram, this._webgl));
12633
- }
12998
+ for (let t = 0; t < 12; t++) {
12999
+ this._ancestorTiles.push(new AncestorTile_js_1.default(t, 0, this, this._healpixGrid.visibleTilesManager.tileBuffer, super.hipsShaderProgram, this._webgl));
12634
13000
  }
12635
13001
  }
12636
13002
  getProperty(key) {
12637
13003
  return this._descriptor.getProperty(key);
12638
13004
  }
12639
13005
  changeFormat(format) {
12640
- this._format = format;
12641
- // original code referenced _tileBuffer; if you have one, wire it back.
12642
- // Keeping calls no-op to avoid breaking at runtime if _tileBuffer is undefined.
12643
- // (newVisibleTilesManager + TileBuffer drive the actual tile lifecycle)
12644
- // @ts-ignore
12645
- if (this._tileBuffer?.clearAll)
12646
- this._tileBuffer.clearAll();
12647
- // @ts-ignore
12648
- if (this._tileBuffer)
12649
- this._tileBuffer._format = this._format;
12650
- const pixelByOrder = this.isGalacticHips
12651
- ? this._healpixGrid.visibleTilesManager.galVisibleTilesByOrder
12652
- : this._healpixGrid.visibleTilesManager.visibleTilesByOrder;
12653
- // const pixelByOrder =
12654
- // this.isGalacticHips
12655
- // ? visibleTilesManager.galVisibleTilesByOrder
12656
- // : visibleTilesManager.visibleTilesByOrder
12657
- // @ts-ignore
12658
- if (this._tileBuffer?.updateTiles)
12659
- this._tileBuffer.updateTiles(pixelByOrder.pixels, pixelByOrder.order);
13006
+ const normalizedFormat = format.toLowerCase();
13007
+ if (!this._descriptor.imgFormats.includes(normalizedFormat)) {
13008
+ throw new Error(`HiPS format "${format}" is not supported. ` +
13009
+ `Available formats: ${this._descriptor.imgFormats.join(", ")}`);
13010
+ }
13011
+ if (normalizedFormat === this._format.toLowerCase()) {
13012
+ return;
13013
+ }
13014
+ const tileBuffer = this._healpixGrid.visibleTilesManager.tileBuffer;
13015
+ /*
13016
+ * Remove Tile instances created using the previous format.
13017
+ *
13018
+ * TileBuffer invalidates by HiPS identity/base URL rather than by the
13019
+ * current format, so both active and cached resources are discarded.
13020
+ */
13021
+ tileBuffer.invalidateHiPS(this);
13022
+ /*
13023
+ * Change format before recreating AllSky/AncestorTile because their
13024
+ * constructors read hips.format.
13025
+ */
13026
+ this._format = normalizedFormat;
13027
+ /*
13028
+ * AllSky and AncestorTile also keep the format they were constructed
13029
+ * with, so they must be recreated.
13030
+ */
13031
+ this.initBaseTiles();
13032
+ }
13033
+ get availableFormats() {
13034
+ return this._descriptor.imgFormats;
12660
13035
  }
12661
13036
  /**
12662
13037
  * Shader colormap switcher
@@ -12669,60 +13044,60 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12669
13044
  * 6 -> cubehelix
12670
13045
  */
12671
13046
  changeColorMap(colorMap) {
12672
- console.log('HiPS.changeColorMap -> shaderProgram', super.hipsShaderProgram.shaderProgram);
13047
+ console.log("HiPS.changeColorMap -> shaderProgram", super.hipsShaderProgram.shaderProgram);
12673
13048
  this.colorMap = colorMap;
12674
13049
  switch (colorMap.name) {
12675
- case 'grayscale':
13050
+ case "grayscale":
12676
13051
  this.colorMapIdx = 1;
12677
13052
  // hipsShaderProgram.setGrayscaleShader()
12678
- this.colorMap = ColorMaps_js_1.default['grayscale'];
13053
+ this.colorMap = ColorMaps_js_1.default["grayscale"];
12679
13054
  super.hipsShaderProgram.setGrayscaleShader();
12680
13055
  break;
12681
- case 'planck':
13056
+ case "planck":
12682
13057
  this.colorMapIdx = 2;
12683
- this.colorMap = ColorMaps_js_1.default['planck'];
13058
+ this.colorMap = ColorMaps_js_1.default["planck"];
12684
13059
  // hipsShaderProgram.setColorMapShader()
12685
13060
  super.hipsShaderProgram.setColorMapShader();
12686
13061
  break;
12687
- case 'cmb':
13062
+ case "cmb":
12688
13063
  this.colorMapIdx = 3;
12689
- this.colorMap = ColorMaps_js_1.default['cmb'];
13064
+ this.colorMap = ColorMaps_js_1.default["cmb"];
12690
13065
  // hipsShaderProgram.setColorMapShader()
12691
13066
  super.hipsShaderProgram.setColorMapShader();
12692
13067
  break;
12693
- case 'rainbow':
13068
+ case "rainbow":
12694
13069
  this.colorMapIdx = 4;
12695
- this.colorMap = ColorMaps_js_1.default['rainbow'];
13070
+ this.colorMap = ColorMaps_js_1.default["rainbow"];
12696
13071
  // hipsShaderProgram.setColorMapShader()
12697
13072
  super.hipsShaderProgram.setColorMapShader();
12698
13073
  break;
12699
- case 'eosb':
13074
+ case "eosb":
12700
13075
  this.colorMapIdx = 5;
12701
- this.colorMap = ColorMaps_js_1.default['eosb'];
13076
+ this.colorMap = ColorMaps_js_1.default["eosb"];
12702
13077
  super.hipsShaderProgram.setColorMapShader();
12703
13078
  // hipsShaderProgram.setColorMapShader()
12704
13079
  break;
12705
- case 'cubehelix':
13080
+ case "cubehelix":
12706
13081
  this.colorMapIdx = 6;
12707
- this.colorMap = ColorMaps_js_1.default['cubehelix'];
13082
+ this.colorMap = ColorMaps_js_1.default["cubehelix"];
12708
13083
  super.hipsShaderProgram.setColorMapShader();
12709
13084
  // hipsShaderProgram.setColorMapShader()
12710
13085
  break;
12711
- case 'hot':
13086
+ case "hot":
12712
13087
  this.colorMapIdx = 7;
12713
- this.colorMap = ColorMaps_js_1.default['hot'];
13088
+ this.colorMap = ColorMaps_js_1.default["hot"];
12714
13089
  super.hipsShaderProgram.setColorMapShader();
12715
13090
  // hipsShaderProgram.setColorMapShader()
12716
13091
  break;
12717
- case 'gray':
13092
+ case "gray":
12718
13093
  this.colorMapIdx = 8;
12719
- this.colorMap = ColorMaps_js_1.default['gray'];
13094
+ this.colorMap = ColorMaps_js_1.default["gray"];
12720
13095
  super.hipsShaderProgram.setColorMapShader();
12721
13096
  // hipsShaderProgram.setColorMapShader()
12722
13097
  break;
12723
- case 'native':
13098
+ case "native":
12724
13099
  this.colorMapIdx = 0;
12725
- this.colorMap = ColorMaps_js_1.default['native'];
13100
+ this.colorMap = ColorMaps_js_1.default["native"];
12726
13101
  super.hipsShaderProgram.setNativeShader();
12727
13102
  break;
12728
13103
  default:
@@ -12737,6 +13112,30 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12737
13112
  // this.shaderProgram = super.hipsShaderProgram.shaderProgram
12738
13113
  // this.shaderProgram = hipsShaderProgram.shaderProgram
12739
13114
  }
13115
+ // private selectDefaultFormat(formats: string[]): string {
13116
+ // if (formats.includes("fits")) return "fits";
13117
+ // if (formats.includes("png")) return "png";
13118
+ // if (formats.includes("jpg")) return "jpg";
13119
+ // if (formats.length > 0) {
13120
+ // return formats[0];
13121
+ // }
13122
+ // throw new Error("HiPS descriptor does not define a tile format");
13123
+ // }
13124
+ selectDefaultFormat(formats) {
13125
+ if (formats.includes("png"))
13126
+ return "png";
13127
+ if (formats.includes("jpg"))
13128
+ return "jpg";
13129
+ if (formats.includes("fits"))
13130
+ return "fits";
13131
+ if (formats.length > 0) {
13132
+ return formats[0];
13133
+ }
13134
+ throw new Error("HiPS descriptor does not define a tile format");
13135
+ }
13136
+ get dataRange() {
13137
+ return this._descriptor.dataRange;
13138
+ }
12740
13139
  getCurrentHealpixOrder() {
12741
13140
  return this._visibleorder;
12742
13141
  }
@@ -12746,7 +13145,7 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12746
13145
  ? this._healpixGrid.visibleTilesManager.galVisibleTilesByOrder
12747
13146
  : this._healpixGrid.visibleTilesManager.visibleTilesByOrder;
12748
13147
  return {
12749
- activeBaseLayer: 'hips',
13148
+ activeBaseLayer: "hips",
12750
13149
  hipsName: this._descriptor.surveyName,
12751
13150
  hipsUrl: this._baseurl,
12752
13151
  isGalactic: this.isGalacticHips,
@@ -12778,16 +13177,10 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12778
13177
  super.hipsShaderProgram.setRuntimeColorMap(this.colorMap);
12779
13178
  if (this._allSky && this._allSkyTile) {
12780
13179
  if (this.isGalacticHips) {
12781
- this._allSkyTile.draw(this._healpixGrid.visibleTilesManager.galVisibleTilesByOrder.order, this._healpixGrid.visibleTilesManager.galAncestorsMap,
12782
- // visibleTilesManager.galVisibleTilesByOrder.order,
12783
- // visibleTilesManager.galAncestorsMap,
12784
- pMatrix, vMatrix, mMatrix, this.colorMapIdx);
13180
+ this._allSkyTile.draw(this._healpixGrid.visibleTilesManager.galVisibleTilesByOrder.order, this._healpixGrid.visibleTilesManager.galAncestorsMap, pMatrix, vMatrix, mMatrix, this.colorMapIdx);
12785
13181
  }
12786
13182
  else {
12787
- this._allSkyTile.draw(this._healpixGrid.visibleTilesManager.visibleTilesByOrder.order, this._healpixGrid.visibleTilesManager.ancestorsMap,
12788
- // visibleTilesManager.visibleTilesByOrder.order,
12789
- // visibleTilesManager.ancestorsMap,
12790
- pMatrix, vMatrix, mMatrix, this.colorMapIdx);
13183
+ this._allSkyTile.draw(this._healpixGrid.visibleTilesManager.visibleTilesByOrder.order, this._healpixGrid.visibleTilesManager.ancestorsMap, pMatrix, vMatrix, mMatrix, this.colorMapIdx);
12791
13184
  }
12792
13185
  return;
12793
13186
  }
@@ -12808,8 +13201,10 @@ exports.HiPS = HiPS;
12808
13201
 
12809
13202
  /***/ },
12810
13203
 
12811
- /***/ 5087
12812
- (__unused_webpack_module, exports) {
13204
+ /***/ 9912
13205
+ (__unused_webpack_module, exports, __webpack_require__) {
13206
+
13207
+ var __webpack_unused_export__;
12813
13208
 
12814
13209
  /*
12815
13210
  * AstroViewer
@@ -12821,10 +13216,185 @@ exports.HiPS = HiPS;
12821
13216
  *
12822
13217
  * See LICENSE.md, LICENSE-AGPL.md, and LICENSE-COMMERCIAL.md for details.
12823
13218
  */
12824
- // HiPSDescriptor.ts
12825
-
12826
- Object.defineProperty(exports, "__esModule", ({ value: true }));
12827
- exports.HiPSDescriptor = void 0;
13219
+ __webpack_unused_export__ = ({ value: true });
13220
+ exports.HiPSCoverage = void 0;
13221
+ const jsfitsio_1 = __webpack_require__(4971);
13222
+ class HiPSCoverage {
13223
+ intersec(intersec, arg1) {
13224
+ throw new Error("Method not implemented.");
13225
+ }
13226
+ ises(ises, expents, of, arg3) {
13227
+ throw new Error("Method not implemented.");
13228
+ }
13229
+ intersexpect(co, t, expe, arg3) {
13230
+ throw new Error("Method not implemented.");
13231
+ }
13232
+ intersectsT19(intersectsT19, arg1) {
13233
+ throw new Error("Method not implemented.");
13234
+ }
13235
+ _maxOrder = 0;
13236
+ _intervals = [];
13237
+ _loaded = false;
13238
+ get loaded() {
13239
+ return this._loaded;
13240
+ }
13241
+ get maxOrder() {
13242
+ return this._maxOrder;
13243
+ }
13244
+ get intervalCount() {
13245
+ return this._intervals.length;
13246
+ }
13247
+ clear() {
13248
+ this._maxOrder = 0;
13249
+ this._intervals = [];
13250
+ this._loaded = false;
13251
+ }
13252
+ async load(baseUrl) {
13253
+ const baseUrlString = baseUrl instanceof URL ? baseUrl.href : String(baseUrl);
13254
+ const normalizedBaseUrl = baseUrlString.endsWith("/")
13255
+ ? baseUrlString
13256
+ : `${baseUrlString}/`;
13257
+ await this.loadMoc(`${normalizedBaseUrl}Moc.fits`);
13258
+ }
13259
+ async loadMoc(mocUrl) {
13260
+ this.clear();
13261
+ const fits = await jsfitsio_1.FITSParser.loadFITSFile(mocUrl);
13262
+ if (!fits) {
13263
+ throw new Error("Unable to load HiPS Moc.fits");
13264
+ }
13265
+ const mocHDU = fits.hdus.find((hdu) => hdu instanceof jsfitsio_1.BinaryTableHDU);
13266
+ if (!(mocHDU instanceof jsfitsio_1.BinaryTableHDU)) {
13267
+ throw new Error("HiPS Moc.fits does not contain a BINTABLE HDU.");
13268
+ }
13269
+ const mocOrderItem = mocHDU.header.findById("MOCORDER");
13270
+ if (!mocOrderItem) {
13271
+ throw new Error("HiPS Moc.fits does not define MOCORDER.");
13272
+ }
13273
+ const maxOrder = Number(mocOrderItem.value);
13274
+ if (!Number.isInteger(maxOrder) || maxOrder < 0) {
13275
+ throw new Error(`Invalid MOCORDER value: ${mocOrderItem.value}`);
13276
+ }
13277
+ this._maxOrder = maxOrder;
13278
+ const intervals = [];
13279
+ for (let row = 0; row < mocHDU.rowCount; row++) {
13280
+ const rawUniq = mocHDU.getCell(row, "UNIQ");
13281
+ if (typeof rawUniq !== "number" ||
13282
+ !Number.isInteger(rawUniq) ||
13283
+ rawUniq < 4) {
13284
+ throw new Error(`Invalid MOC UNIQ value at row ${row}: ${String(rawUniq)}`);
13285
+ }
13286
+ const { order, pixel } = HiPSCoverage.decodeUniq(rawUniq);
13287
+ if (order > this._maxOrder) {
13288
+ throw new Error(`MOC cell order ${order} exceeds MOCORDER ${this._maxOrder}.`);
13289
+ }
13290
+ const scale = 4 ** (this._maxOrder - order);
13291
+ intervals.push({
13292
+ first: pixel * scale,
13293
+ last: (pixel + 1) * scale - 1,
13294
+ });
13295
+ }
13296
+ this._intervals = HiPSCoverage.mergeIntervals(intervals);
13297
+ this._loaded = true;
13298
+ }
13299
+ intersectsTile(order, pixel) {
13300
+ if (!this._loaded) {
13301
+ return true;
13302
+ }
13303
+ if (!Number.isInteger(order) ||
13304
+ order < 0 ||
13305
+ !Number.isInteger(pixel) ||
13306
+ pixel < 0) {
13307
+ return false;
13308
+ }
13309
+ let first;
13310
+ let last;
13311
+ if (order <= this._maxOrder) {
13312
+ const scale = 4 ** (this._maxOrder - order);
13313
+ first = pixel * scale;
13314
+ last = (pixel + 1) * scale - 1;
13315
+ }
13316
+ else {
13317
+ /*
13318
+ * At orders finer than the MOC resolution, reduce the tile
13319
+ * to its ancestor at MOCORDER.
13320
+ */
13321
+ const shift = 2 * (order - this._maxOrder);
13322
+ const ancestor = Math.floor(pixel / 2 ** shift);
13323
+ first = ancestor;
13324
+ last = ancestor;
13325
+ }
13326
+ return this.intersectsInterval(first, last);
13327
+ }
13328
+ intersectsInterval(first, last) {
13329
+ let low = 0;
13330
+ let high = this._intervals.length - 1;
13331
+ while (low <= high) {
13332
+ const middle = Math.floor((low + high) / 2);
13333
+ const interval = this._intervals[middle];
13334
+ if (interval.last < first) {
13335
+ low = middle + 1;
13336
+ continue;
13337
+ }
13338
+ if (interval.first > last) {
13339
+ high = middle - 1;
13340
+ continue;
13341
+ }
13342
+ return true;
13343
+ }
13344
+ return false;
13345
+ }
13346
+ static decodeUniq(uniq) {
13347
+ let order = 0;
13348
+ while (4 ** (order + 2) <= uniq) {
13349
+ order++;
13350
+ }
13351
+ const base = 4 ** (order + 1);
13352
+ return {
13353
+ order,
13354
+ pixel: uniq - base,
13355
+ };
13356
+ }
13357
+ static mergeIntervals(intervals) {
13358
+ if (intervals.length === 0) {
13359
+ return [];
13360
+ }
13361
+ intervals.sort((a, b) => a.first - b.first);
13362
+ const merged = [{ ...intervals[0] }];
13363
+ for (let i = 1; i < intervals.length; i++) {
13364
+ const current = intervals[i];
13365
+ const previous = merged[merged.length - 1];
13366
+ if (current.first <= previous.last + 1) {
13367
+ previous.last = Math.max(previous.last, current.last);
13368
+ }
13369
+ else {
13370
+ merged.push({ ...current });
13371
+ }
13372
+ }
13373
+ return merged;
13374
+ }
13375
+ }
13376
+ exports.HiPSCoverage = HiPSCoverage;
13377
+
13378
+
13379
+ /***/ },
13380
+
13381
+ /***/ 5087
13382
+ (__unused_webpack_module, exports) {
13383
+
13384
+ /*
13385
+ * AstroViewer
13386
+ * Copyright (C) Fabrizio Giordano
13387
+ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-AstroViewer-Commercial
13388
+ *
13389
+ * AstroViewer is dual-licensed under the GNU Affero General Public License
13390
+ * version 3 and a separate commercial license.
13391
+ *
13392
+ * See LICENSE.md, LICENSE-AGPL.md, and LICENSE-COMMERCIAL.md for details.
13393
+ */
13394
+ // HiPSDescriptor.ts
13395
+
13396
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
13397
+ exports.HiPSDescriptor = void 0;
12828
13398
  class HiPSDescriptor {
12829
13399
  _minOrder = 3;
12830
13400
  _imgformats = [];
@@ -12980,6 +13550,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
12980
13550
  // Tile.ts
12981
13551
  const Global_js_1 = __importDefault(__webpack_require__(4382));
12982
13552
  const FoVHelper_js_1 = __webpack_require__(229);
13553
+ const FitsTileLoader_js_1 = __webpack_require__(1399);
12983
13554
  // ------------------------------------------------------------------------
12984
13555
  class Tile {
12985
13556
  _hips;
@@ -12994,8 +13565,9 @@ class Tile {
12994
13565
  _image;
12995
13566
  _textureLoaded = false;
12996
13567
  _texture;
12997
- _texurl = '';
13568
+ _texurl = "";
12998
13569
  _hipsShaderIndex = 0;
13570
+ _fitsTile;
12999
13571
  _cacheTime0;
13000
13572
  _inView = true;
13001
13573
  _amIStillInFoV_requsetID;
@@ -13005,7 +13577,7 @@ class Tile {
13005
13577
  vertexIndices = new Uint16Array();
13006
13578
  vertexIndexBuffer;
13007
13579
  _tileBuffer;
13008
- opacity = 1.0;
13580
+ // public opacity = 1.0;
13009
13581
  _webgl;
13010
13582
  _visibleTileManager;
13011
13583
  // private _hipsShaderProgram
@@ -13052,50 +13624,66 @@ class Tile {
13052
13624
  console.warn(`[Tile] Skipping tile request above max order: requested order ${this._order}, max order ${this._maxorder}, url ${this._baseurl}`);
13053
13625
  return;
13054
13626
  }
13055
- this._image = new Image();
13056
13627
  const dirnumber = Math.floor(this._tileno / 10000) * 10000;
13057
13628
  this._texurl = `${this._baseurl}/Norder${this._order}/Dir${dirnumber}/Npix${this._tileno}.${this._format}`;
13629
+ if (this._format === "fits") {
13630
+ void this.loadFits();
13631
+ return;
13632
+ }
13633
+ this.loadImage();
13634
+ }
13635
+ loadImage() {
13636
+ this._image = new Image();
13058
13637
  this._image.onload = () => this.imageLoaded();
13059
13638
  this._image.onerror = () => {
13060
- // console.error('File not found?', this._texurl)
13061
13639
  this._ready = false;
13062
13640
  this._abort = true;
13063
13641
  this.destroyIntervals();
13064
13642
  };
13065
- this._image.crossOrigin = 'anonymous';
13643
+ this._image.crossOrigin = "anonymous";
13066
13644
  this._image.src = this._texurl;
13067
13645
  }
13646
+ async loadFits() {
13647
+ try {
13648
+ this._fitsTile = await (0, FitsTileLoader_js_1.loadFitsTile)(this._texurl);
13649
+ this._ready = true;
13650
+ }
13651
+ catch (error) {
13652
+ console.error(`[Tile] Unable to load FITS tile ${this._texurl}`, error);
13653
+ this._ready = false;
13654
+ this._abort = true;
13655
+ this.destroyIntervals();
13656
+ }
13657
+ }
13068
13658
  imageLoaded() {
13069
13659
  // this.textureLoaded()
13070
13660
  // this.initModelBuffer()
13071
13661
  // this._textureLoaded = true
13072
13662
  this._ready = true;
13073
13663
  }
13074
- // private textureLoaded(): void {
13075
13664
  textureLoaded(hipsShaderProgram) {
13076
- // this._hipsShaderProgram.enableProgram()
13077
13665
  hipsShaderProgram.enableProgram();
13078
13666
  const gl = this._webgl;
13079
13667
  this._texture = gl.createTexture();
13080
13668
  gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
13081
- gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
13669
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._format !== "fits");
13082
13670
  gl.bindTexture(gl.TEXTURE_2D, this._texture);
13083
- if (!gl.isTexture(this._texture)) {
13084
- console.log('error in texture');
13671
+ if (this._format === "fits") {
13672
+ const fits = this._fitsTile;
13673
+ if (!fits) {
13674
+ throw new Error(`FITS tile data not loaded: ${this._texurl}`);
13675
+ }
13676
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, fits.width, fits.height, 0, gl.RED, gl.FLOAT, fits.pixels);
13677
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
13678
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
13679
+ }
13680
+ else {
13681
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
13682
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
13683
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
13085
13684
  }
13086
- gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
13087
- gl.bindTexture(gl.TEXTURE_2D, this._texture);
13088
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
13089
13685
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
13090
13686
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
13091
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
13092
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
13093
- // FIX: use the sampler location we fetched in enableShaders()
13094
- // gl.uniform1i((this._hipsShaderProgram.locations as ShaderLocations).sampler, this._hipsShaderIndex)
13095
- // gl.uniform1i((hipsShaderProgram.locations as ShaderLocations).sampler, this._hipsShaderIndex)
13096
- if (!gl.isTexture(this._texture)) {
13097
- console.warn('Texture creation failed');
13098
- }
13099
13687
  this.initModelBuffer();
13100
13688
  this._textureLoaded = true;
13101
13689
  }
@@ -13162,26 +13750,32 @@ class Tile {
13162
13750
  this.vertexPosition[qidx][20 * p] = facesVec3Array[0].x;
13163
13751
  this.vertexPosition[qidx][20 * p + 1] = facesVec3Array[0].y;
13164
13752
  this.vertexPosition[qidx][20 * p + 2] = facesVec3Array[0].z;
13165
- this.vertexPosition[qidx][20 * p + 3] = step + step * uindex + s_pixel_size;
13166
- this.vertexPosition[qidx][20 * p + 4] = 1 - (step + step * vindex) - t_pixel_size;
13753
+ this.vertexPosition[qidx][20 * p + 3] =
13754
+ step + step * uindex + s_pixel_size;
13755
+ this.vertexPosition[qidx][20 * p + 4] =
13756
+ 1 - (step + step * vindex) - t_pixel_size;
13167
13757
  // v1
13168
13758
  this.vertexPosition[qidx][20 * p + 5] = facesVec3Array[1].x;
13169
13759
  this.vertexPosition[qidx][20 * p + 6] = facesVec3Array[1].y;
13170
13760
  this.vertexPosition[qidx][20 * p + 7] = facesVec3Array[1].z;
13171
- this.vertexPosition[qidx][20 * p + 8] = step + step * uindex + s_pixel_size;
13172
- this.vertexPosition[qidx][20 * p + 9] = 1 - step * vindex + t_pixel_size;
13761
+ this.vertexPosition[qidx][20 * p + 8] =
13762
+ step + step * uindex + s_pixel_size;
13763
+ this.vertexPosition[qidx][20 * p + 9] =
13764
+ 1 - step * vindex + t_pixel_size;
13173
13765
  // v2
13174
13766
  this.vertexPosition[qidx][20 * p + 10] = facesVec3Array[2].x;
13175
13767
  this.vertexPosition[qidx][20 * p + 11] = facesVec3Array[2].y;
13176
13768
  this.vertexPosition[qidx][20 * p + 12] = facesVec3Array[2].z;
13177
13769
  this.vertexPosition[qidx][20 * p + 13] = step * uindex - s_pixel_size;
13178
- this.vertexPosition[qidx][20 * p + 14] = 1 - step * vindex + t_pixel_size;
13770
+ this.vertexPosition[qidx][20 * p + 14] =
13771
+ 1 - step * vindex + t_pixel_size;
13179
13772
  // v3
13180
13773
  this.vertexPosition[qidx][20 * p + 15] = facesVec3Array[3].x;
13181
13774
  this.vertexPosition[qidx][20 * p + 16] = facesVec3Array[3].y;
13182
13775
  this.vertexPosition[qidx][20 * p + 17] = facesVec3Array[3].z;
13183
13776
  this.vertexPosition[qidx][20 * p + 18] = step * uindex - s_pixel_size;
13184
- this.vertexPosition[qidx][20 * p + 19] = 1 - (step + step * vindex) - t_pixel_size;
13777
+ this.vertexPosition[qidx][20 * p + 19] =
13778
+ 1 - (step + step * vindex) - t_pixel_size;
13185
13779
  p++;
13186
13780
  }
13187
13781
  }
@@ -13189,6 +13783,32 @@ class Tile {
13189
13783
  gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBuffer[qidx]);
13190
13784
  gl.bufferData(gl.ARRAY_BUFFER, this.vertexPosition[qidx], gl.STATIC_DRAW);
13191
13785
  }
13786
+ getFitsDataRange() {
13787
+ const hipsRange = this._hips.dataRange;
13788
+ if (hipsRange.min !== undefined &&
13789
+ hipsRange.max !== undefined &&
13790
+ Number.isFinite(hipsRange.min) &&
13791
+ Number.isFinite(hipsRange.max) &&
13792
+ hipsRange.max > hipsRange.min) {
13793
+ return {
13794
+ min: hipsRange.min,
13795
+ max: hipsRange.max,
13796
+ };
13797
+ }
13798
+ const fits = this._fitsTile;
13799
+ if (fits &&
13800
+ fits.dataMin !== null &&
13801
+ fits.dataMax !== null &&
13802
+ Number.isFinite(fits.dataMin) &&
13803
+ Number.isFinite(fits.dataMax) &&
13804
+ fits.dataMax > fits.dataMin) {
13805
+ return {
13806
+ min: fits.dataMin,
13807
+ max: fits.dataMax,
13808
+ };
13809
+ }
13810
+ return null;
13811
+ }
13192
13812
  get inView() {
13193
13813
  return this._inView;
13194
13814
  }
@@ -13203,7 +13823,9 @@ class Tile {
13203
13823
  this._ready = true;
13204
13824
  if (this._isGalacticHips) {
13205
13825
  if (this._visibleTileManager.galAncestorsMap.has(this._order)) {
13206
- if (!this._visibleTileManager.galAncestorsMap.get(this._order).includes(this._tileno)) {
13826
+ if (!this._visibleTileManager.galAncestorsMap
13827
+ .get(this._order)
13828
+ .includes(this._tileno)) {
13207
13829
  this.moveToCache();
13208
13830
  }
13209
13831
  else {
@@ -13235,7 +13857,9 @@ class Tile {
13235
13857
  }
13236
13858
  else {
13237
13859
  if (this._visibleTileManager.ancestorsMap.has(this._order)) {
13238
- if (!this._visibleTileManager.ancestorsMap.get(this._order).includes(this._tileno)) {
13860
+ if (!this._visibleTileManager.ancestorsMap
13861
+ .get(this._order)
13862
+ .includes(this._tileno)) {
13239
13863
  this.moveToCache();
13240
13864
  }
13241
13865
  else {
@@ -13281,33 +13905,40 @@ class Tile {
13281
13905
  }
13282
13906
  const gl = this._webgl;
13283
13907
  hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx);
13284
- // this._hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx)
13285
- // Enable attributes (these locations are retrieved in enableShaders)
13286
- // gl.enableVertexAttribArray(this._hipsShaderProgram.locations.vertexPositionAttribute)
13287
- // gl.enableVertexAttribArray(this._hipsShaderProgram.locations.textureCoordAttribute)
13288
- gl.enableVertexAttribArray(hipsShaderProgram.locations.vertexPositionAttribute);
13289
- gl.enableVertexAttribArray(hipsShaderProgram.locations.textureCoordAttribute);
13908
+ if (this._format === "fits") {
13909
+ const range = this.getFitsDataRange();
13910
+ if (!range) {
13911
+ console.error(`[Tile] No display range available for FITS tile ${this._texurl}`);
13912
+ return;
13913
+ }
13914
+ hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max);
13915
+ }
13916
+ else {
13917
+ hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, false);
13918
+ }
13919
+ const locations = hipsShaderProgram.locations;
13920
+ gl.enableVertexAttribArray(locations.vertexPositionAttribute);
13921
+ gl.enableVertexAttribArray(locations.textureCoordAttribute);
13290
13922
  gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
13291
13923
  gl.bindTexture(gl.TEXTURE_2D, this._texture);
13292
- // gl.uniform1f(this._hipsShaderProgram.locations.textureAlpha, this.opacity)
13293
- gl.uniform1f(hipsShaderProgram.locations.textureAlpha, this.opacity);
13924
+ const factorLocation = locations.textureAlpha[this._hipsShaderIndex];
13925
+ if (factorLocation) {
13926
+ gl.uniform1f(factorLocation, 1.0);
13927
+ }
13928
+ hipsShaderProgram.setLayerOpacity(this._hips.opacity);
13294
13929
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
13295
13930
  const elemno = this.vertexIndices.length;
13296
- const indexType = this.vertexIndices instanceof Uint32Array ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT;
13931
+ const indexType = this.vertexIndices instanceof Uint32Array
13932
+ ? gl.UNSIGNED_INT
13933
+ : gl.UNSIGNED_SHORT;
13297
13934
  quadrantsToDraw.forEach((qidx) => {
13298
13935
  gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBuffer[qidx]);
13299
- gl.vertexAttribPointer(
13300
- // this._hipsShaderProgram.locations.vertexPositionAttribute,
13301
- hipsShaderProgram.locations.vertexPositionAttribute, 3, gl.FLOAT, false, 5 * 4, 0);
13302
- gl.vertexAttribPointer(
13303
- // this._hipsShaderProgram.locations.textureCoordAttribute,
13304
- hipsShaderProgram.locations.textureCoordAttribute, 2, gl.FLOAT, false, 5 * 4, 3 * 4);
13936
+ gl.vertexAttribPointer(locations.vertexPositionAttribute, 3, gl.FLOAT, false, 5 * 4, 0);
13937
+ gl.vertexAttribPointer(locations.textureCoordAttribute, 2, gl.FLOAT, false, 5 * 4, 3 * 4);
13305
13938
  gl.drawElements(gl.TRIANGLES, elemno, indexType, 0);
13306
13939
  });
13307
- // gl.disableVertexAttribArray(this._hipsShaderProgram.locations.vertexPositionAttribute)
13308
- // gl.disableVertexAttribArray(this._hipsShaderProgram.locations.textureCoordAttribute)
13309
- gl.disableVertexAttribArray(hipsShaderProgram.locations.vertexPositionAttribute);
13310
- gl.disableVertexAttribArray(hipsShaderProgram.locations.textureCoordAttribute);
13940
+ gl.disableVertexAttribArray(locations.vertexPositionAttribute);
13941
+ gl.disableVertexAttribArray(locations.textureCoordAttribute);
13311
13942
  }
13312
13943
  drawChildren(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx, hipsShaderProgram) {
13313
13944
  const quadrantsToDraw = new Set([0, 1, 2, 3]);
@@ -13318,16 +13949,15 @@ class Tile {
13318
13949
  const childTileNo = (this._tileno << 2) + c;
13319
13950
  const list = visibleTilesMap.get(childrenOrder);
13320
13951
  if (list.includes(childTileNo)) {
13952
+ if (!this._hips.intersectsCoverage(childrenOrder, childTileNo)) {
13953
+ continue;
13954
+ }
13321
13955
  const childTile = this._isGalacticHips
13322
13956
  ? this._tileBuffer.getGalTile(childTileNo, childrenOrder, this._hips)
13323
13957
  : this._tileBuffer.getTile(childTileNo, childrenOrder, this._hips);
13324
- // const childTile = this._isGalacticHips
13325
- // ? newTileBuffer.getGalTile(childTileNo, childrenOrder, this._hips)
13326
- // : newTileBuffer.getTile(childTileNo, childrenOrder, this._hips)
13327
- // childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx)
13328
13958
  childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx, hipsShaderProgram);
13329
- if (childTile._ready) {
13330
- quadrantsToDraw.delete(childTileNo - (this._tileno << 2));
13959
+ if (childTile.getReadyState()) {
13960
+ quadrantsToDraw.delete(c);
13331
13961
  }
13332
13962
  }
13333
13963
  }
@@ -13393,7 +14023,7 @@ class TileBuffer {
13393
14023
  /** Register an equatorial HiPS into the buffer. */
13394
14024
  addHiPS(hips) {
13395
14025
  if (this._activeHiPS.has(hips)) {
13396
- console.error('HiPS already present in TileBuffer');
14026
+ console.error("HiPS already present in TileBuffer");
13397
14027
  return;
13398
14028
  }
13399
14029
  this._activeHiPS.set(hips, new Map());
@@ -13401,7 +14031,7 @@ class TileBuffer {
13401
14031
  /** Register a galactic HiPS into the buffer. */
13402
14032
  addGalHiPS(hips) {
13403
14033
  if (this._galActiveHiPS.has(hips)) {
13404
- console.error('HiPS already present in TileBuffer');
14034
+ console.error("HiPS already present in TileBuffer");
13405
14035
  return;
13406
14036
  }
13407
14037
  this._galActiveHiPS.set(hips, new Map());
@@ -13412,6 +14042,9 @@ class TileBuffer {
13412
14042
  if (order > hips.maxOrder) {
13413
14043
  continue;
13414
14044
  }
14045
+ if (!hips.intersectsCoverage(order, tileno)) {
14046
+ continue;
14047
+ }
13415
14048
  this.getTile(tileno, order, hips);
13416
14049
  }
13417
14050
  }
@@ -13421,12 +14054,15 @@ class TileBuffer {
13421
14054
  if (order > hips.maxOrder) {
13422
14055
  continue;
13423
14056
  }
14057
+ if (!hips.intersectsCoverage(order, tileno)) {
14058
+ continue;
14059
+ }
13424
14060
  this.getGalTile(tileno, order, hips);
13425
14061
  }
13426
14062
  }
13427
14063
  /** Fetch (or create) an equatorial tile, reviving from cache if present. */
13428
14064
  getTile(tileno, order, hips) {
13429
- const tileKey = this.key(order, tileno, hips.baseURL);
14065
+ const tileKey = this.key(order, tileno, hips);
13430
14066
  if (!this._tiles.has(tileKey)) {
13431
14067
  if (this._cachedTiles.has(tileKey)) {
13432
14068
  const tile = this._cachedTiles.get(tileKey);
@@ -13444,7 +14080,7 @@ class TileBuffer {
13444
14080
  }
13445
14081
  /** Fetch (or create) a galactic tile, reviving from cache if present. */
13446
14082
  getGalTile(tileno, order, hips) {
13447
- const tileKey = this.key(order, tileno, hips.baseURL);
14083
+ const tileKey = this.key(order, tileno, hips);
13448
14084
  if (!this._galTiles.has(tileKey)) {
13449
14085
  if (this._galCachedTiles.has(tileKey)) {
13450
14086
  const tile = this._galCachedTiles.get(tileKey);
@@ -13462,7 +14098,7 @@ class TileBuffer {
13462
14098
  }
13463
14099
  /** Move a tile (equatorial or galactic) into cache. */
13464
14100
  moveTileToCache(tileno, order, hips) {
13465
- const tileKey = this.key(order, tileno, hips.baseURL);
14101
+ const tileKey = this.key(order, tileno, hips);
13466
14102
  if (this._tiles.has(tileKey)) {
13467
14103
  const tile = this._tiles.get(tileKey);
13468
14104
  tile.setCacheTime0();
@@ -13481,29 +14117,64 @@ class TileBuffer {
13481
14117
  const now = Date.now();
13482
14118
  for (const [tileKey, tile] of this._cachedTiles) {
13483
14119
  const t0 = tile.cacheTime0;
13484
- if (!tile.inView && t0 !== undefined && now - t0 > this._cacheAliveMilliSeconds) {
14120
+ if (!tile.inView &&
14121
+ t0 !== undefined &&
14122
+ now - t0 > this._cacheAliveMilliSeconds) {
13485
14123
  tile.destroyIntervals();
13486
14124
  this._cachedTiles.delete(tileKey);
13487
14125
  }
13488
14126
  }
13489
14127
  for (const [tileKey, tile] of this._galCachedTiles) {
13490
14128
  const t0 = tile.cacheTime0;
13491
- if (!tile.inView && t0 !== undefined && now - t0 > this._cacheAliveMilliSeconds) {
14129
+ if (!tile.inView &&
14130
+ t0 !== undefined &&
14131
+ now - t0 > this._cacheAliveMilliSeconds) {
13492
14132
  tile.destroyIntervals();
13493
14133
  this._galCachedTiles.delete(tileKey);
13494
14134
  }
13495
14135
  }
13496
14136
  }
13497
14137
  /** Compose a stable key for maps. */
13498
- key(order, tileno, baseURL) {
13499
- return `${order}#${tileno}#${baseURL}`;
14138
+ key(order, tileno, hips) {
14139
+ return `${order}#${tileno}#${hips.baseURL}#${hips.format}`;
14140
+ }
14141
+ removeHiPS(hips) {
14142
+ this.invalidateHiPS(hips);
14143
+ this._activeHiPS.delete(hips);
14144
+ this._galActiveHiPS.delete(hips);
14145
+ }
14146
+ /**
14147
+ * Remove all active and cached tiles belonging to a specific HiPS.
14148
+ *
14149
+ * Tile keys contain the HiPS base URL and format. We intentionally
14150
+ * ignore the format here so that a format change removes resources
14151
+ * created with the previous format as well.
14152
+ */
14153
+ invalidateHiPS(hips) {
14154
+ const belongsToHiPS = (tileKey) => tileKey.includes(`#${hips.baseURL}#`);
14155
+ const clearTiles = (tiles) => {
14156
+ for (const [tileKey, tile] of tiles) {
14157
+ if (!belongsToHiPS(tileKey)) {
14158
+ continue;
14159
+ }
14160
+ tile.destroyIntervals();
14161
+ tiles.delete(tileKey);
14162
+ }
14163
+ };
14164
+ clearTiles(this._tiles);
14165
+ clearTiles(this._cachedTiles);
14166
+ clearTiles(this._galTiles);
14167
+ clearTiles(this._galCachedTiles);
13500
14168
  }
13501
14169
  /** Optional: call to stop internal timers if you dispose this buffer. */
13502
14170
  dispose() {
13503
14171
  window.clearInterval(this._cleanerId);
13504
14172
  }
13505
14173
  get size() {
13506
- return this._tiles.size + this._cachedTiles.size + this._galTiles.size + this._galCachedTiles.size;
14174
+ return (this._tiles.size +
14175
+ this._cachedTiles.size +
14176
+ this._galTiles.size +
14177
+ this._galCachedTiles.size);
13507
14178
  }
13508
14179
  get activeTileCount() {
13509
14180
  return this._tiles.size + this._galTiles.size;
@@ -13581,11 +14252,8 @@ exports.VisibleTilesManager = void 0;
13581
14252
  const Global_js_1 = __importDefault(__webpack_require__(4382));
13582
14253
  const healpix_1 = __webpack_require__(4851);
13583
14254
  const RayPickingUtils_js_1 = __importDefault(__webpack_require__(4639));
13584
- // import { newTileBuffer } from './TileBuffer.js';
13585
14255
  const TileBuffer_js_1 = __webpack_require__(4006);
13586
14256
  const gl_matrix_1 = __webpack_require__(3890);
13587
- // import healpixGridSingleton from '../grid/HealpixGridSingleton.js';
13588
- // import {HealpixGridSingleton} from '../grid/HealpixGridSingleton.js';
13589
14257
  const Config_js_1 = __webpack_require__(2919);
13590
14258
  class VisibleTilesManager {
13591
14259
  _visibleTilesByOrder;
@@ -13625,18 +14293,13 @@ class VisibleTilesManager {
13625
14293
  init(insideSphere) {
13626
14294
  this.initialised = true;
13627
14295
  this.insideSphere = insideSphere;
13628
- // this.computeVisiblePixels();
13629
- // setInterval(() => this.computeVisiblePixels(), 500);
13630
14296
  }
13631
14297
  getVisibleOrder() {
13632
- // return healpixGridSingleton.visibleorder;
13633
14298
  return this._healpixGrid.visibleorder;
13634
14299
  }
13635
- // computeVisiblePixels(): void {
13636
14300
  computeVisiblePixels(order, webgl, camera, pMatrix) {
13637
14301
  if (!this.initialised)
13638
14302
  return;
13639
- // let order = healpixGridSingleton.visibleorder;
13640
14303
  if (Global_js_1.default.insideSphere && order < 3) {
13641
14304
  order = 3;
13642
14305
  }
@@ -13656,8 +14319,6 @@ class VisibleTilesManager {
13656
14319
  }
13657
14320
  else {
13658
14321
  const geomhealpix = Global_js_1.default.getHealpix(order);
13659
- // const maxX = (global.gl as GL).canvas.width;
13660
- // const maxY = (global.gl as GL).canvas.height;
13661
14322
  const maxX = webgl.canvas.width;
13662
14323
  const maxY = webgl.canvas.height;
13663
14324
  // Sample a grid of screen points, project to the sphere, then to galactic
@@ -13677,13 +14338,11 @@ class VisibleTilesManager {
13677
14338
  if (!pixels.includes(currPixNo)) {
13678
14339
  pixels.push(currPixNo);
13679
14340
  this._ancestorsMap.get(order).push(currPixNo);
13680
- // newTileBuffer.addTile(order, currPixNo);
13681
14341
  this._tileBuffer.addTile(order, currPixNo);
13682
14342
  }
13683
14343
  if (!galTiles.includes(galTileNo)) {
13684
14344
  galTiles.push(galTileNo);
13685
14345
  this._galAncestorsMap.get(order).push(galTileNo);
13686
- // newTileBuffer.addGalTile(order, galTileNo);
13687
14346
  this._tileBuffer.addGalTile(order, galTileNo);
13688
14347
  }
13689
14348
  }
@@ -13701,7 +14360,6 @@ class VisibleTilesManager {
13701
14360
  const parent = pixels[p] >> (2 * o);
13702
14361
  if (!list.includes(parent)) {
13703
14362
  list.push(parent);
13704
- // newTileBuffer.addTile(tgtOrder, parent);
13705
14363
  this._tileBuffer.addTile(tgtOrder, parent);
13706
14364
  }
13707
14365
  }
@@ -13714,7 +14372,6 @@ class VisibleTilesManager {
13714
14372
  const parent = galTiles[p] >> (2 * o);
13715
14373
  if (!list.includes(parent)) {
13716
14374
  list.push(parent);
13717
- // newTileBuffer.addGalTile(tgtOrder, parent);
13718
14375
  this._tileBuffer.addGalTile(tgtOrder, parent);
13719
14376
  }
13720
14377
  }
@@ -16078,7 +16735,7 @@ class HiPSShaderProgram {
16078
16735
  _UBO_colorMapVariableInfo = {
16079
16736
  r_palette: { index: 0, offset: 0 },
16080
16737
  g_palette: { index: 0, offset: 0 },
16081
- b_palette: { index: 0, offset: 0 }
16738
+ b_palette: { index: 0, offset: 0 },
16082
16739
  };
16083
16740
  gl_uniforms;
16084
16741
  gl_attributes;
@@ -16087,54 +16744,68 @@ class HiPSShaderProgram {
16087
16744
  constructor(webgl) {
16088
16745
  this._webgl = webgl;
16089
16746
  this.gl_uniforms = {
16090
- sampler: 'uSampler0',
16091
- factor: 'uFactor0',
16092
- m_perspective: 'uPMatrix',
16093
- m_model: 'uMMatrix',
16094
- m_view: 'uVMatrix',
16095
- colormapIdx: 'cmapIdx',
16096
- colormap_red: 'r',
16097
- colormap_green: 'g',
16098
- colormap_blue: 'b'
16747
+ sampler: "uSampler0",
16748
+ factor: "uFactor0",
16749
+ m_perspective: "uPMatrix",
16750
+ m_model: "uMMatrix",
16751
+ m_view: "uVMatrix",
16752
+ colormapIdx: "cmapIdx",
16753
+ colormap_red: "r",
16754
+ colormap_green: "g",
16755
+ colormap_blue: "b",
16756
+ textureMode: "uTextureMode",
16757
+ dataMin: "uDataMin",
16758
+ dataMax: "uDataMax",
16099
16759
  };
16100
16760
  this.gl_attributes = {
16101
- vertex_pos: 'aVertexPosition',
16102
- text_coords: 'aTextureCoord'
16761
+ vertex_pos: "aVertexPosition",
16762
+ text_coords: "aTextureCoord",
16103
16763
  };
16104
16764
  this.locations = {
16105
16765
  pMatrix: null,
16106
16766
  mMatrix: null,
16107
16767
  vMatrix: null,
16108
- sampler: null,
16109
- textureAlpha: null,
16768
+ samplers: new Array(8).fill(null),
16769
+ textureAlpha: new Array(8).fill(null),
16770
+ textureMode: new Array(8).fill(null),
16771
+ dataMin: new Array(8).fill(null),
16772
+ dataMax: new Array(8).fill(null),
16773
+ layerOpacity: null,
16110
16774
  clorMapIdx: null,
16111
16775
  vertexPositionAttribute: -1,
16112
- textureCoordAttribute: -1
16776
+ textureCoordAttribute: -1,
16113
16777
  };
16114
16778
  }
16115
16779
  get shaderProgram() {
16116
16780
  const gl = this._webgl;
16117
16781
  if (!this._shaderProgram) {
16118
- // const gl = global.gl as GL
16119
- this._shaderProgram = gl.createProgram();
16120
- this.initShaders();
16782
+ const program = gl.createProgram();
16783
+ this._shaderProgram = program;
16784
+ this.initShaders(program);
16121
16785
  }
16122
- ;
16123
16786
  gl.useProgram(this._shaderProgram);
16124
16787
  return this._shaderProgram;
16125
16788
  }
16789
+ setLayerOpacity(opacity) {
16790
+ const gl = this._webgl;
16791
+ this.locations.layerOpacity = gl.getUniformLocation(this.shaderProgram, "uLayerOpacity");
16792
+ if (this.locations.layerOpacity !== null) {
16793
+ gl.uniform1f(this.locations.layerOpacity, opacity);
16794
+ }
16795
+ }
16126
16796
  setRuntimeColorMap(colorMap) {
16127
16797
  this._runtimeColorMap = colorMap;
16128
16798
  }
16129
- initShaders() {
16130
- // const gl = global.gl as GL
16799
+ initShaders(program) {
16800
+ // const gl = global.gl
16131
16801
  const gl = this._webgl;
16132
16802
  const fragmentShaderStr = ShaderManager_js_1.default.hipsNativeFS();
16133
16803
  this._fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
16134
16804
  gl.shaderSource(this._fragmentShader, fragmentShaderStr);
16135
16805
  gl.compileShader(this._fragmentShader);
16136
16806
  if (!gl.getShaderParameter(this._fragmentShader, gl.COMPILE_STATUS)) {
16137
- alert(gl.getShaderInfoLog(this._fragmentShader) || 'Fragment shader compile error');
16807
+ alert(gl.getShaderInfoLog(this._fragmentShader) ||
16808
+ "Fragment shader compile error");
16138
16809
  return;
16139
16810
  }
16140
16811
  const vertexShaderStr = ShaderManager_js_1.default.hipsVS();
@@ -16142,43 +16813,44 @@ class HiPSShaderProgram {
16142
16813
  gl.shaderSource(this._vertexShader, vertexShaderStr);
16143
16814
  gl.compileShader(this._vertexShader);
16144
16815
  if (!gl.getShaderParameter(this._vertexShader, gl.COMPILE_STATUS)) {
16145
- alert(gl.getShaderInfoLog(this._vertexShader) || 'Vertex shader compile error');
16816
+ alert(gl.getShaderInfoLog(this._vertexShader) ||
16817
+ "Vertex shader compile error");
16146
16818
  return;
16147
16819
  }
16148
- gl.attachShader(this._shaderProgram, this._vertexShader);
16149
- gl.attachShader(this._shaderProgram, this._fragmentShader);
16150
- gl.linkProgram(this._shaderProgram);
16151
- if (!gl.getProgramParameter(this._shaderProgram, gl.LINK_STATUS)) {
16152
- alert('Could not initialise shaders');
16820
+ gl.attachShader(program, this._vertexShader);
16821
+ gl.attachShader(program, this._fragmentShader);
16822
+ gl.linkProgram(program);
16823
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
16824
+ alert("Could not initialise shaders");
16153
16825
  }
16154
16826
  }
16155
16827
  enableProgram() {
16156
- // (global.gl as GL).useProgram(this._shaderProgram as WebGLProgram)
16828
+ // (global.gl).useProgram(this._shaderProgram)
16157
16829
  this._webgl.useProgram(this.shaderProgram);
16158
16830
  }
16159
16831
  setGrayscaleShader() {
16160
- // const gl = global.gl as GL
16832
+ // const gl = global.gl
16161
16833
  const gl = this._webgl;
16162
16834
  gl.detachShader(this.shaderProgram, this._fragmentShader);
16163
16835
  const fragmentShaderStr = ShaderManager_js_1.default.hipsGrayscaleFS();
16164
16836
  this.changeFSShader(fragmentShaderStr);
16165
16837
  }
16166
16838
  setNativeShader() {
16167
- // const gl = global.gl as GL
16839
+ // const gl = global.gl
16168
16840
  const gl = this._webgl;
16169
16841
  gl.detachShader(this.shaderProgram, this._fragmentShader);
16170
16842
  const fragmentShaderStr = ShaderManager_js_1.default.hipsNativeFS();
16171
16843
  this.changeFSShader(fragmentShaderStr);
16172
16844
  }
16173
16845
  setColorMapShader() {
16174
- // const gl = global.gl as GL
16846
+ // const gl = global.gl
16175
16847
  const gl = this._webgl;
16176
16848
  // Swap fragment shader
16177
16849
  gl.detachShader(this.shaderProgram, this._fragmentShader);
16178
16850
  const fragmentShaderStr = ShaderManager_js_1.default.hipsColorMapFS();
16179
16851
  this.changeFSShader(fragmentShaderStr);
16180
16852
  // UBO discovery for the "colormap" block
16181
- const blockIndex = gl.getUniformBlockIndex(this.shaderProgram, 'colormap');
16853
+ const blockIndex = gl.getUniformBlockIndex(this.shaderProgram, "colormap");
16182
16854
  // INVALID_INDEX == 0xFFFFFFFF in WebGL2
16183
16855
  if (blockIndex === gl.INVALID_INDEX) {
16184
16856
  console.warn('HiPSShaderProgram: uniform block "colormap" not found in hipsColorMapFS()');
@@ -16188,11 +16860,11 @@ class HiPSShaderProgram {
16188
16860
  }
16189
16861
  this._colorMapBlockIndex = blockIndex;
16190
16862
  // const blockSize = gl.getActiveUniformBlockParameter(
16191
- // this.shaderProgram as WebGLProgram,
16863
+ // this.shaderProgram,
16192
16864
  // blockIndex,
16193
16865
  // gl.UNIFORM_BLOCK_DATA_SIZE
16194
16866
  // ) as number
16195
- const uboVariableNames = ['r_palette', 'g_palette', 'b_palette'];
16867
+ const uboVariableNames = ["r_palette", "g_palette", "b_palette"];
16196
16868
  const uboVariableIndices = gl.getUniformIndices(this.shaderProgram, uboVariableNames);
16197
16869
  const uboVariableOffsets = gl.getActiveUniforms(this.shaderProgram, uboVariableIndices, gl.UNIFORM_OFFSET);
16198
16870
  // Create buffer only once
@@ -16209,49 +16881,80 @@ class HiPSShaderProgram {
16209
16881
  uboVariableNames.forEach((name, index) => {
16210
16882
  this._UBO_colorMapVariableInfo[name] = {
16211
16883
  index: uboVariableIndices[index],
16212
- offset: uboVariableOffsets[index]
16884
+ offset: uboVariableOffsets[index],
16213
16885
  };
16214
16886
  });
16215
16887
  }
16216
16888
  changeFSShader(fragmentShaderStr) {
16217
- // const gl = global.gl as GL
16889
+ // const gl = global.gl
16218
16890
  const gl = this._webgl;
16219
16891
  this._fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
16220
16892
  gl.shaderSource(this._fragmentShader, fragmentShaderStr);
16221
16893
  gl.compileShader(this._fragmentShader);
16222
16894
  if (!gl.getShaderParameter(this._fragmentShader, gl.COMPILE_STATUS)) {
16223
- alert(gl.getShaderInfoLog(this._fragmentShader) || 'Fragment shader compile error');
16895
+ alert(gl.getShaderInfoLog(this._fragmentShader) ||
16896
+ "Fragment shader compile error");
16224
16897
  return;
16225
16898
  }
16226
16899
  gl.attachShader(this.shaderProgram, this._fragmentShader);
16227
16900
  gl.linkProgram(this.shaderProgram);
16228
16901
  if (!gl.getProgramParameter(this.shaderProgram, gl.LINK_STATUS)) {
16229
- alert('Could not initialise shaders');
16902
+ alert("Could not initialise shaders");
16230
16903
  }
16231
16904
  gl.useProgram(this.shaderProgram);
16232
16905
  }
16906
+ setTextureDataMode(samplerIndex, fits, min, max) {
16907
+ if (samplerIndex < 0 || samplerIndex >= 8) {
16908
+ throw new Error(`Invalid HiPS sampler index: ${samplerIndex}`);
16909
+ }
16910
+ const gl = this._webgl;
16911
+ const modeLocation = this.locations.textureMode[samplerIndex];
16912
+ if (modeLocation) {
16913
+ gl.uniform1i(modeLocation, fits ? 1 : 0);
16914
+ }
16915
+ if (!fits) {
16916
+ return;
16917
+ }
16918
+ if (min === undefined ||
16919
+ max === undefined ||
16920
+ !Number.isFinite(min) ||
16921
+ !Number.isFinite(max) ||
16922
+ max <= min) {
16923
+ throw new Error("Invalid FITS display range.");
16924
+ }
16925
+ const minLocation = this.locations.dataMin[samplerIndex];
16926
+ const maxLocation = this.locations.dataMax[samplerIndex];
16927
+ if (minLocation) {
16928
+ gl.uniform1f(minLocation, min);
16929
+ }
16930
+ if (maxLocation) {
16931
+ gl.uniform1f(maxLocation, max);
16932
+ }
16933
+ }
16233
16934
  enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx) {
16234
- // const gl = global.gl as GL
16935
+ // const gl = global.gl
16235
16936
  const gl = this._webgl;
16236
16937
  gl.useProgram(this.shaderProgram);
16237
16938
  this.locations.pMatrix = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.m_perspective);
16238
16939
  this.locations.mMatrix = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.m_model);
16239
16940
  this.locations.vMatrix = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.m_view);
16240
- this.locations.sampler = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.sampler);
16241
- this.locations.textureAlpha = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.factor);
16242
16941
  this.locations.clorMapIdx = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.colormapIdx);
16243
- // NEW
16244
- // if (this.locations.clorMapIdx) {
16245
- gl.uniform1i(this.locations.clorMapIdx, colorMapIdx);
16246
- // }
16247
- // Make sampler explicit: we always use TEXTURE0 in your draw code
16248
- if (this.locations.sampler) {
16249
- gl.uniform1i(this.locations.sampler, 0);
16942
+ for (let i = 0; i < 8; i++) {
16943
+ this.locations.samplers[i] = gl.getUniformLocation(this.shaderProgram, `uSampler${i}`);
16944
+ this.locations.textureAlpha[i] = gl.getUniformLocation(this.shaderProgram, `uFactor${i}`);
16945
+ this.locations.textureMode[i] = gl.getUniformLocation(this.shaderProgram, `uTextureMode${i}`);
16946
+ this.locations.dataMin[i] = gl.getUniformLocation(this.shaderProgram, `uDataMin${i}`);
16947
+ this.locations.dataMax[i] = gl.getUniformLocation(this.shaderProgram, `uDataMax${i}`);
16948
+ if (this.locations.samplers[i]) {
16949
+ gl.uniform1i(this.locations.samplers[i], i);
16950
+ }
16250
16951
  }
16251
- // END NEW
16952
+ gl.uniform1i(this.locations.clorMapIdx, colorMapIdx);
16252
16953
  this.locations.vertexPositionAttribute = gl.getAttribLocation(this.shaderProgram, this.gl_attributes.vertex_pos);
16253
16954
  this.locations.textureCoordAttribute = gl.getAttribLocation(this.shaderProgram, this.gl_attributes.text_coords);
16254
- if (colorMapIdx >= 2 && this._UBO_colorMapBuffer && this._colorMapBlockIndex !== null) {
16955
+ if (colorMapIdx >= 2 &&
16956
+ this._UBO_colorMapBuffer &&
16957
+ this._colorMapBlockIndex !== null) {
16255
16958
  gl.uniformBlockBinding(this.shaderProgram, this._colorMapBlockIndex, 0);
16256
16959
  gl.bindBuffer(gl.UNIFORM_BUFFER, this._UBO_colorMapBuffer);
16257
16960
  let currentColorMap;
@@ -16624,15 +17327,7 @@ class ShaderManager {
16624
17327
 
16625
17328
  in vec2 vTextureCoord;
16626
17329
 
16627
- uniform sampler2D uSampler0;
16628
- uniform sampler2D uSampler1;
16629
- uniform sampler2D uSampler2;
16630
- uniform sampler2D uSampler3;
16631
- uniform sampler2D uSampler4;
16632
- uniform sampler2D uSampler5;
16633
- uniform sampler2D uSampler6;
16634
- uniform sampler2D uSampler7;
16635
-
17330
+ uniform float uLayerOpacity;
16636
17331
  uniform float uFactor0;
16637
17332
  uniform float uFactor1;
16638
17333
  uniform float uFactor2;
@@ -16642,24 +17337,54 @@ class ShaderManager {
16642
17337
  uniform float uFactor6;
16643
17338
  uniform float uFactor7;
16644
17339
 
17340
+ ${ShaderManager.hipsSamplersGLSL()}
17341
+
16645
17342
  out vec4 fragColor;
16646
17343
 
16647
17344
  void main() {
16648
17345
  vec3 finalColor = vec3(0.0);
16649
17346
 
16650
- if (uFactor0 >= 0.0){
16651
- vec4 mycolor;
16652
- #if __VERSION__ > 120
16653
- vec4 color0 = texture(uSampler0, vTextureCoord);
16654
- #else
16655
- vec4 color0 = texture2D(uSampler0, vTextureCoord);
16656
- #endif
16657
- mycolor = color0;
16658
- finalColor += mycolor.rgb * uFactor0;
16659
- } else if (uFactor7 >= 0.0){
16660
- finalColor = vec3(1.0, 0.0, 0.0);
17347
+ if (uFactor0 >= 0.0) {
17348
+ finalColor +=
17349
+ sampleHiPSTexture0(vTextureCoord).rgb * uFactor0;
17350
+ }
17351
+
17352
+ if (uFactor1 >= 0.0) {
17353
+ finalColor +=
17354
+ sampleHiPSTexture1(vTextureCoord).rgb * uFactor1;
17355
+ }
17356
+
17357
+ if (uFactor2 >= 0.0) {
17358
+ finalColor +=
17359
+ sampleHiPSTexture2(vTextureCoord).rgb * uFactor2;
17360
+ }
17361
+
17362
+ if (uFactor3 >= 0.0) {
17363
+ finalColor +=
17364
+ sampleHiPSTexture3(vTextureCoord).rgb * uFactor3;
17365
+ }
17366
+
17367
+ if (uFactor4 >= 0.0) {
17368
+ finalColor +=
17369
+ sampleHiPSTexture4(vTextureCoord).rgb * uFactor4;
17370
+ }
17371
+
17372
+ if (uFactor5 >= 0.0) {
17373
+ finalColor +=
17374
+ sampleHiPSTexture5(vTextureCoord).rgb * uFactor5;
17375
+ }
17376
+
17377
+ if (uFactor6 >= 0.0) {
17378
+ finalColor +=
17379
+ sampleHiPSTexture6(vTextureCoord).rgb * uFactor6;
17380
+ }
17381
+
17382
+ if (uFactor7 >= 0.0) {
17383
+ finalColor +=
17384
+ sampleHiPSTexture7(vTextureCoord).rgb * uFactor7;
16661
17385
  }
16662
- fragColor = vec4(finalColor, 1.0);
17386
+
17387
+ fragColor = vec4(finalColor, uLayerOpacity);
16663
17388
  }`;
16664
17389
  }
16665
17390
  static hipsGrayscaleFS() {
@@ -16668,15 +17393,7 @@ class ShaderManager {
16668
17393
 
16669
17394
  in vec2 vTextureCoord;
16670
17395
 
16671
- uniform sampler2D uSampler0;
16672
- uniform sampler2D uSampler1;
16673
- uniform sampler2D uSampler2;
16674
- uniform sampler2D uSampler3;
16675
- uniform sampler2D uSampler4;
16676
- uniform sampler2D uSampler5;
16677
- uniform sampler2D uSampler6;
16678
- uniform sampler2D uSampler7;
16679
-
17396
+ uniform float uLayerOpacity;
16680
17397
  uniform float uFactor0;
16681
17398
  uniform float uFactor1;
16682
17399
  uniform float uFactor2;
@@ -16686,117 +17403,206 @@ class ShaderManager {
16686
17403
  uniform float uFactor6;
16687
17404
  uniform float uFactor7;
16688
17405
 
17406
+ ${ShaderManager.hipsSamplersGLSL()}
17407
+
16689
17408
  out vec4 fragColor;
16690
17409
 
16691
17410
  void main() {
16692
17411
  vec3 finalColor = vec3(0.0);
16693
17412
 
16694
- if (uFactor0 >= 0.0){
16695
- #if __VERSION__ > 120
16696
- vec4 color0 = texture(uSampler0, vTextureCoord);
16697
- #else
16698
- vec4 color0 = texture2D(uSampler0, vTextureCoord);
16699
- #endif
16700
- float gray = 0.21 * color0.r + 0.71 * color0.g + 0.07 * color0.b;
16701
- finalColor = color0.rgb * (1.0 - uFactor0) + vec3(gray) * uFactor0;
17413
+ if (uFactor0 >= 0.0) {
17414
+ vec4 color0 = sampleHiPSTexture0(vTextureCoord);
17415
+
17416
+ float gray =
17417
+ 0.21 * color0.r +
17418
+ 0.71 * color0.g +
17419
+ 0.07 * color0.b;
17420
+
17421
+ finalColor =
17422
+ color0.rgb * (1.0 - uFactor0) +
17423
+ vec3(gray) * uFactor0;
16702
17424
  }
16703
- if (uFactor1 >= 0.0){
16704
- #if __VERSION__ > 120
16705
- vec4 color1 = texture(uSampler1, vTextureCoord);
16706
- #else
16707
- vec4 color1 = texture2D(uSampler1, vTextureCoord);
16708
- #endif
17425
+
17426
+ if (uFactor1 >= 0.0) {
17427
+ vec4 color1 = sampleHiPSTexture1(vTextureCoord);
16709
17428
  finalColor += color1.rgb * uFactor1;
16710
17429
  }
16711
- if (uFactor2 >= 0.0){
16712
- #if __VERSION__ > 120
16713
- vec4 color2 = texture(uSampler2, vTextureCoord);
16714
- #else
16715
- vec4 color2 = texture2D(uSampler2, vTextureCoord);
16716
- #endif
17430
+
17431
+ if (uFactor2 >= 0.0) {
17432
+ vec4 color2 = sampleHiPSTexture2(vTextureCoord);
16717
17433
  finalColor += color2.rgb * uFactor2;
16718
17434
  }
16719
- if (uFactor3 >= 0.0){
16720
- #if __VERSION__ > 120
16721
- vec4 color3 = texture(uSampler3, vTextureCoord);
16722
- #else
16723
- vec4 color3 = texture2D(uSampler3, vTextureCoord);
16724
- #endif
17435
+
17436
+ if (uFactor3 >= 0.0) {
17437
+ vec4 color3 = sampleHiPSTexture3(vTextureCoord);
16725
17438
  finalColor += color3.rgb * uFactor3;
16726
17439
  }
16727
- if (uFactor4 >= 0.0){
16728
- #if __VERSION__ > 120
16729
- vec4 color4 = texture(uSampler4, vTextureCoord);
16730
- #else
16731
- vec4 color4 = texture2D(uSampler4, vTextureCoord);
16732
- #endif
17440
+
17441
+ if (uFactor4 >= 0.0) {
17442
+ vec4 color4 = sampleHiPSTexture4(vTextureCoord);
16733
17443
  finalColor += color4.rgb * uFactor4;
16734
17444
  }
16735
- if (uFactor5 >= 0.0){
16736
- #if __VERSION__ > 120
16737
- vec4 color5 = texture(uSampler5, vTextureCoord);
16738
- #else
16739
- vec4 color5 = texture2D(uSampler5, vTextureCoord);
16740
- #endif
17445
+
17446
+ if (uFactor5 >= 0.0) {
17447
+ vec4 color5 = sampleHiPSTexture5(vTextureCoord);
16741
17448
  finalColor += color5.rgb * uFactor5;
16742
17449
  }
16743
- if (uFactor6 >= 0.0){
16744
- #if __VERSION__ > 120
16745
- vec4 color6 = texture(uSampler6, vTextureCoord);
16746
- #else
16747
- vec4 color6 = texture2D(uSampler6, vTextureCoord);
16748
- #endif
17450
+
17451
+ if (uFactor6 >= 0.0) {
17452
+ vec4 color6 = sampleHiPSTexture6(vTextureCoord);
16749
17453
  finalColor += color6.rgb * uFactor6;
16750
17454
  }
16751
- if (uFactor7 >= 0.0){
16752
- #if __VERSION__ > 120
16753
- vec4 color7 = texture(uSampler7, vTextureCoord);
16754
- #else
16755
- vec4 color7 = texture2D(uSampler7, vTextureCoord);
16756
- #endif
17455
+
17456
+ if (uFactor7 >= 0.0) {
17457
+ vec4 color7 = sampleHiPSTexture7(vTextureCoord);
16757
17458
  finalColor += color7.rgb * uFactor7;
16758
17459
  }
16759
- fragColor = vec4(finalColor, 1.0);
17460
+
17461
+ fragColor = vec4(finalColor, uLayerOpacity);
16760
17462
  }`;
16761
17463
  }
16762
17464
  static hipsColorMapFS() {
16763
17465
  return `#version 300 es
16764
17466
  precision mediump float;
16765
17467
 
17468
+ uniform float uLayerOpacity;
17469
+
16766
17470
  in vec2 vTextureCoord;
16767
17471
 
16768
- // UBO
16769
17472
  layout (std140) uniform colormap {
16770
17473
  float r_palette[256];
16771
17474
  float g_palette[256];
16772
17475
  float b_palette[256];
16773
17476
  };
16774
17477
 
16775
- uniform sampler2D uSampler0;
16776
17478
  uniform float uFactor0;
17479
+ uniform float uFactor1;
17480
+ uniform float uFactor2;
17481
+ uniform float uFactor3;
17482
+ uniform float uFactor4;
17483
+ uniform float uFactor5;
17484
+ uniform float uFactor6;
17485
+ uniform float uFactor7;
17486
+
17487
+ ${ShaderManager.hipsSamplersGLSL()}
16777
17488
 
16778
17489
  out vec4 fragColor;
16779
17490
 
16780
- void main() {
16781
- #if __VERSION__ > 120
16782
- vec4 color0 = texture(uSampler0, vTextureCoord);
16783
- #else
16784
- vec4 color0 = texture2D(uSampler0, vTextureCoord);
16785
- #endif
17491
+ vec3 applyColorMap(vec4 color) {
17492
+ int x = int(clamp(color.r, 0.0, 1.0) * 255.0);
17493
+ int y = int(clamp(color.g, 0.0, 1.0) * 255.0);
17494
+ int z = int(clamp(color.b, 0.0, 1.0) * 255.0);
16786
17495
 
16787
- int x = int(color0.r * 255.0);
16788
17496
  float px = r_palette[x] / 256.0;
16789
-
16790
- int y = int(color0.g * 255.0);
16791
17497
  float py = g_palette[y] / 256.0;
16792
-
16793
- int z = int(color0.b * 255.0);
16794
17498
  float pz = b_palette[z] / 256.0;
16795
17499
 
16796
- // uFactor0 reserved for future blending if needed
16797
- fragColor = vec4(px, py, pz, 1.0);
17500
+ return vec3(px, py, pz);
17501
+ }
17502
+
17503
+ void main() {
17504
+ vec3 finalColor = vec3(0.0);
17505
+
17506
+ if (uFactor0 >= 0.0) {
17507
+ finalColor +=
17508
+ applyColorMap(
17509
+ sampleHiPSTexture0(vTextureCoord)
17510
+ ) * uFactor0;
17511
+ }
17512
+
17513
+ if (uFactor1 >= 0.0) {
17514
+ finalColor +=
17515
+ applyColorMap(
17516
+ sampleHiPSTexture1(vTextureCoord)
17517
+ ) * uFactor1;
17518
+ }
17519
+
17520
+ if (uFactor2 >= 0.0) {
17521
+ finalColor +=
17522
+ applyColorMap(
17523
+ sampleHiPSTexture2(vTextureCoord)
17524
+ ) * uFactor2;
17525
+ }
17526
+
17527
+ if (uFactor3 >= 0.0) {
17528
+ finalColor +=
17529
+ applyColorMap(
17530
+ sampleHiPSTexture3(vTextureCoord)
17531
+ ) * uFactor3;
17532
+ }
17533
+
17534
+ if (uFactor4 >= 0.0) {
17535
+ finalColor +=
17536
+ applyColorMap(
17537
+ sampleHiPSTexture4(vTextureCoord)
17538
+ ) * uFactor4;
17539
+ }
17540
+
17541
+ if (uFactor5 >= 0.0) {
17542
+ finalColor +=
17543
+ applyColorMap(
17544
+ sampleHiPSTexture5(vTextureCoord)
17545
+ ) * uFactor5;
17546
+ }
17547
+
17548
+ if (uFactor6 >= 0.0) {
17549
+ finalColor +=
17550
+ applyColorMap(
17551
+ sampleHiPSTexture6(vTextureCoord)
17552
+ ) * uFactor6;
17553
+ }
17554
+
17555
+ if (uFactor7 >= 0.0) {
17556
+ finalColor +=
17557
+ applyColorMap(
17558
+ sampleHiPSTexture7(vTextureCoord)
17559
+ ) * uFactor7;
17560
+ }
17561
+
17562
+ fragColor = vec4(finalColor, uLayerOpacity);
16798
17563
  }`;
16799
17564
  }
17565
+ static hipsSamplerGLSL(index) {
17566
+ return `
17567
+ uniform sampler2D uSampler${index};
17568
+ uniform int uTextureMode${index};
17569
+ uniform float uDataMin${index};
17570
+ uniform float uDataMax${index};
17571
+
17572
+ vec4 sampleHiPSTexture${index}(vec2 uv) {
17573
+ vec4 color = texture(uSampler${index}, uv);
17574
+
17575
+ // JPG / PNG
17576
+ if (uTextureMode${index} == 0) {
17577
+ return color;
17578
+ }
17579
+
17580
+ // FITS physical value stored in red channel
17581
+ float value = color.r;
17582
+
17583
+ if (isnan(value)) {
17584
+ discard;
17585
+ }
17586
+
17587
+ float normalized = clamp(
17588
+ (value - uDataMin${index}) /
17589
+ (uDataMax${index} - uDataMin${index}),
17590
+ 0.0,
17591
+ 1.0
17592
+ );
17593
+
17594
+ return vec4(
17595
+ normalized,
17596
+ normalized,
17597
+ normalized,
17598
+ 1.0
17599
+ );
17600
+ }
17601
+ `;
17602
+ }
17603
+ static hipsSamplersGLSL() {
17604
+ return Array.from({ length: 8 }, (_, index) => ShaderManager.hipsSamplerGLSL(index)).join("\n");
17605
+ }
16800
17606
  }
16801
17607
  exports["default"] = ShaderManager;
16802
17608
 
@@ -18469,27 +19275,76 @@ exports["default"] = XYZRayPickingUtils;
18469
19275
 
18470
19276
  /***/ },
18471
19277
 
18472
- /***/ 4851
18473
- (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
19278
+ /***/ 8611
19279
+ (module) {
18474
19280
 
19281
+ module.exports = require("http");
18475
19282
 
18476
- // EXPORTS
18477
- __webpack_require__.d(__webpack_exports__, {
18478
- Healpix: () => (/* reexport */ Healpix),
18479
- Pointing: () => (/* reexport */ Pointing),
18480
- Vec3: () => (/* reexport */ Vec3)
18481
- });
19283
+ /***/ },
18482
19284
 
18483
- // UNUSED EXPORTS: Hploc, RangeSet
19285
+ /***/ 5692
19286
+ (module) {
18484
19287
 
18485
- ;// ./node_modules/astrospatial-core/lib-esm/healpix/vec3.js
18486
- class Vec3 {
18487
- x;
18488
- y;
18489
- z;
18490
- constructor(x, y, z) {
18491
- if (![x, y, z].every(Number.isFinite)) {
18492
- throw new RangeError("Vec3 coordinates must be finite numbers.");
19288
+ module.exports = require("https");
19289
+
19290
+ /***/ },
19291
+
19292
+ /***/ 1455
19293
+ (module) {
19294
+
19295
+ module.exports = require("node:fs/promises");
19296
+
19297
+ /***/ },
19298
+
19299
+ /***/ 4876
19300
+ (module) {
19301
+
19302
+ module.exports = require("punycode");
19303
+
19304
+ /***/ },
19305
+
19306
+ /***/ 2203
19307
+ (module) {
19308
+
19309
+ module.exports = require("stream");
19310
+
19311
+ /***/ },
19312
+
19313
+ /***/ 7016
19314
+ (module) {
19315
+
19316
+ module.exports = require("url");
19317
+
19318
+ /***/ },
19319
+
19320
+ /***/ 3106
19321
+ (module) {
19322
+
19323
+ module.exports = require("zlib");
19324
+
19325
+ /***/ },
19326
+
19327
+ /***/ 4851
19328
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
19329
+
19330
+
19331
+ // EXPORTS
19332
+ __webpack_require__.d(__webpack_exports__, {
19333
+ Healpix: () => (/* reexport */ Healpix),
19334
+ Pointing: () => (/* reexport */ Pointing),
19335
+ Vec3: () => (/* reexport */ Vec3)
19336
+ });
19337
+
19338
+ // UNUSED EXPORTS: Hploc, RangeSet
19339
+
19340
+ ;// ./node_modules/astrospatial-core/lib-esm/healpix/vec3.js
19341
+ class Vec3 {
19342
+ x;
19343
+ y;
19344
+ z;
19345
+ constructor(x, y, z) {
19346
+ if (![x, y, z].every(Number.isFinite)) {
19347
+ throw new RangeError("Vec3 coordinates must be finite numbers.");
18493
19348
  }
18494
19349
  this.x = x;
18495
19350
  this.y = y;
@@ -19265,6 +20120,1621 @@ function findCircleThroughTwoPoints(points, q1, q2) {
19265
20120
 
19266
20121
 
19267
20122
 
20123
+ /***/ },
20124
+
20125
+ /***/ 4971
20126
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
20127
+
20128
+
20129
+ // EXPORTS
20130
+ __webpack_require__.d(__webpack_exports__, {
20131
+ BinaryTableHDU: () => (/* reexport */ BinaryTableHDU),
20132
+ FITSHeaderManager: () => (/* reexport */ FITSHeaderManager),
20133
+ FITSParser: () => (/* reexport */ FITSParser)
20134
+ });
20135
+
20136
+ // UNUSED EXPORTS: AsciiTableHDU, FITSFile, FITSHDU, FITSHeaderItem, FITSWriter, ImageHDU, ParseHeader, ParsePayload, PrimaryHDU
20137
+
20138
+ ;// ./node_modules/jsfitsio/lib-esm/model/FITSHeaderItem.js
20139
+ /**
20140
+ * Summary. (bla bla bla)
20141
+ *
20142
+ * Description. (bla bla bla)
20143
+ *
20144
+ * @link github https://github.com/fab77/FITSParser
20145
+ * @author Fabrizio Giordano <fabriziogiordano77@gmail.com>
20146
+ */
20147
+ class FITSHeaderItem {
20148
+ _key = "";
20149
+ _value = "";
20150
+ _comment = "";
20151
+ constructor(key, value, comment) {
20152
+ this._key = key;
20153
+ this._value = value;
20154
+ this._comment = comment;
20155
+ }
20156
+ get key() {
20157
+ return this._key;
20158
+ }
20159
+ get comment() {
20160
+ return this._comment;
20161
+ }
20162
+ get value() {
20163
+ return this._value;
20164
+ }
20165
+ }
20166
+ //# sourceMappingURL=FITSHeaderItem.js.map
20167
+ ;// ./node_modules/jsfitsio/lib-esm/model/FITSHeaderManager.js
20168
+
20169
+ class FITSHeaderManager {
20170
+ static SIMPLE = "SIMPLE";
20171
+ static BITPIX = "BITPIX";
20172
+ static BZERO = "BZERO";
20173
+ static BSCALE = "BSCALE";
20174
+ static BLANK = "BLANK";
20175
+ static NAXIS = "NAXIS";
20176
+ static NAXIS1 = "NAXIS1";
20177
+ static NAXIS2 = "NAXIS2";
20178
+ static DATAMIN = "DATAMIN";
20179
+ static DATAMAX = "DATAMAX";
20180
+ static CRVAL1 = "CRVAL1";
20181
+ static CRVAL2 = "CRVAL2";
20182
+ static CTYPE1 = "CTYPE1";
20183
+ static CTYPE2 = "CTYPE2";
20184
+ static CRPIX1 = "CRPIX1";
20185
+ static CRPIX2 = "CRPIX2";
20186
+ static ORIGIN = "ORIGIN";
20187
+ static COMMENT = "COMMENT";
20188
+ static XTENSION = "XTENSION";
20189
+ static PCOUNT = "PCOUNT";
20190
+ static GCOUNT = "GCOUNT";
20191
+ static TFIELDS = "TFIELDS";
20192
+ static TFORM = "TFORM";
20193
+ static TTYPE = "TTYPE";
20194
+ static TUNIT = "TUNIT";
20195
+ static TSCAL = "TSCAL";
20196
+ static TZERO = "TZERO";
20197
+ static TNULL = "TNULL";
20198
+ static TBCOL = "TBCOL";
20199
+ items = [];
20200
+ constructor(initializeDefaults = true) {
20201
+ if (!initializeDefaults) {
20202
+ return;
20203
+ }
20204
+ this.items[0] = new FITSHeaderItem(FITSHeaderManager.SIMPLE, "T", "");
20205
+ this.items[1] = new FITSHeaderItem(FITSHeaderManager.BITPIX, "", "");
20206
+ this.items[2] = new FITSHeaderItem(FITSHeaderManager.NAXIS, 2, "");
20207
+ this.items[3] = new FITSHeaderItem(FITSHeaderManager.NAXIS1, "", "");
20208
+ this.items[4] = new FITSHeaderItem(FITSHeaderManager.NAXIS2, "", "");
20209
+ }
20210
+ // insert(item: FITSHeaderItem, position?: number): void {
20211
+ insert(item) {
20212
+ if (item.key === FITSHeaderManager.SIMPLE) {
20213
+ // this.items.splice(0, 0, item);
20214
+ this.items[0] = item;
20215
+ }
20216
+ else if (item.key === FITSHeaderManager.BITPIX) {
20217
+ // this.items.splice(1, 0, item);
20218
+ this.items[1] = item;
20219
+ }
20220
+ else if (item.key === FITSHeaderManager.NAXIS) {
20221
+ // this.items.splice(2, 0, item);
20222
+ this.items[2] = item;
20223
+ }
20224
+ else if (item.key === FITSHeaderManager.NAXIS1) {
20225
+ // this.items.splice(3, 0, item);
20226
+ this.items[3] = item;
20227
+ }
20228
+ else if (item.key === FITSHeaderManager.NAXIS2) {
20229
+ // this.items.splice(4, 0, item);
20230
+ this.items[4] = item;
20231
+ }
20232
+ else {
20233
+ this.items.push(item);
20234
+ }
20235
+ // if (position !== undefined && position >= 0 && position <= this.items.length) {
20236
+ // this.items.splice(position, 0, item);
20237
+ // } else {
20238
+ // this.items.push(item);
20239
+ // }
20240
+ }
20241
+ getItems() {
20242
+ return this.items;
20243
+ }
20244
+ remove(key) {
20245
+ this.items = this.items.filter((item) => item.key !== key);
20246
+ }
20247
+ findById(key) {
20248
+ const item = this.items.find((item) => item.key === key);
20249
+ if (!item) {
20250
+ return null;
20251
+ }
20252
+ return item;
20253
+ }
20254
+ static tableFieldKey(prefix, index) {
20255
+ if (!Number.isInteger(index) || index < 1) {
20256
+ throw new RangeError(`FITS table field index must be >= 1, received ${index}.`);
20257
+ }
20258
+ return `${prefix}${index}`;
20259
+ }
20260
+ static naxisKey(axis) {
20261
+ if (!Number.isInteger(axis) || axis < 1) {
20262
+ throw new RangeError(`FITS axis must be a positive integer, received ${axis}.`);
20263
+ }
20264
+ return `NAXIS${axis}`;
20265
+ }
20266
+ static getFITSItemStringValue(header, key) {
20267
+ const item = header.findById(key);
20268
+ if (!item) {
20269
+ return null;
20270
+ }
20271
+ return String(item.value).trim().replace(/^'/, "").replace(/'$/, "").trim();
20272
+ }
20273
+ }
20274
+ //# sourceMappingURL=FITSHeaderManager.js.map
20275
+ ;// external "fs"
20276
+ const external_fs_namespaceObject = require("fs");
20277
+ ;// ./node_modules/jsfitsio/lib-esm/FITSHeaderWriter.js
20278
+ class FITSHeaderWriter {
20279
+ static BLOCK_SIZE = 2880;
20280
+ static CARD_SIZE = 80;
20281
+ static INTEGER_KEYWORDS = new Set([
20282
+ "BITPIX",
20283
+ "NAXIS",
20284
+ "PCOUNT",
20285
+ "GCOUNT",
20286
+ ]);
20287
+ static LOGICAL_KEYWORDS = new Set(["SIMPLE", "EXTEND"]);
20288
+ static serialize(header, primary) {
20289
+ const items = header.getItems();
20290
+ const map = new Map(items.map((item) => [item.key.toUpperCase(), item]));
20291
+ const cards = [];
20292
+ FITSHeaderWriter.appendMandatoryCards(cards, map, primary);
20293
+ FITSHeaderWriter.appendRemainingCards(cards, items);
20294
+ cards.push(FITSHeaderWriter.card80("END"));
20295
+ return FITSHeaderWriter.encodeAndPad(cards);
20296
+ }
20297
+ static appendMandatoryCards(cards, map, primary) {
20298
+ if (primary) {
20299
+ const simple = map.get("SIMPLE");
20300
+ if (!simple) {
20301
+ throw new Error("Missing mandatory SIMPLE card in Primary HDU");
20302
+ }
20303
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("SIMPLE", simple.value, simple.comment));
20304
+ }
20305
+ else {
20306
+ const xtension = map.get("XTENSION");
20307
+ if (!xtension) {
20308
+ throw new Error("Missing mandatory XTENSION card in extension HDU");
20309
+ }
20310
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("XTENSION", xtension.value, xtension.comment));
20311
+ }
20312
+ const bitpix = map.get("BITPIX");
20313
+ if (!bitpix) {
20314
+ throw new Error("Missing mandatory BITPIX card");
20315
+ }
20316
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("BITPIX", bitpix.value, bitpix.comment));
20317
+ const naxis = map.get("NAXIS");
20318
+ if (!naxis) {
20319
+ throw new Error("Missing mandatory NAXIS card");
20320
+ }
20321
+ const nAxes = Number(naxis.value);
20322
+ if (!Number.isInteger(nAxes) || nAxes < 0) {
20323
+ throw new Error(`Invalid NAXIS value: ${naxis.value}`);
20324
+ }
20325
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("NAXIS", nAxes, naxis.comment));
20326
+ for (let axis = 1; axis <= nAxes; axis++) {
20327
+ const key = `NAXIS${axis}`;
20328
+ const item = map.get(key);
20329
+ if (!item) {
20330
+ throw new Error(`Missing mandatory ${key} card`);
20331
+ }
20332
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment(key, item.value, item.comment));
20333
+ }
20334
+ if (!primary) {
20335
+ const pcount = map.get("PCOUNT");
20336
+ const gcount = map.get("GCOUNT");
20337
+ if (!pcount) {
20338
+ throw new Error("Missing mandatory PCOUNT card in extension HDU");
20339
+ }
20340
+ if (!gcount) {
20341
+ throw new Error("Missing mandatory GCOUNT card in extension HDU");
20342
+ }
20343
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("PCOUNT", pcount.value, pcount.comment));
20344
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("GCOUNT", gcount.value, gcount.comment));
20345
+ }
20346
+ if (primary) {
20347
+ const extend = map.get("EXTEND");
20348
+ if (extend) {
20349
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("EXTEND", extend.value, extend.comment));
20350
+ }
20351
+ }
20352
+ }
20353
+ static appendRemainingCards(cards, items) {
20354
+ for (const item of items) {
20355
+ const key = item.key.toUpperCase();
20356
+ if (key === "SIMPLE" ||
20357
+ key === "XTENSION" ||
20358
+ key === "BITPIX" ||
20359
+ key === "NAXIS" ||
20360
+ /^NAXIS\d+$/.test(key) ||
20361
+ key === "PCOUNT" ||
20362
+ key === "GCOUNT" ||
20363
+ key === "EXTEND" ||
20364
+ key === "END") {
20365
+ continue;
20366
+ }
20367
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment(item.key, item.value, item.comment));
20368
+ }
20369
+ }
20370
+ static makeKeywordWithComment(key, value, comment) {
20371
+ const normalized = key.toUpperCase();
20372
+ if (normalized === "END") {
20373
+ return [FITSHeaderWriter.card80("END")];
20374
+ }
20375
+ if (normalized === "COMMENT" || normalized === "HISTORY") {
20376
+ return FITSHeaderWriter.makeCommentCards(normalized, String(value ?? comment ?? ""));
20377
+ }
20378
+ let base = FITSHeaderWriter.keyword(normalized) +
20379
+ FITSHeaderWriter.valueField20(normalized, value);
20380
+ if (!comment || comment.length === 0) {
20381
+ return [FITSHeaderWriter.card80(base)];
20382
+ }
20383
+ const addition = ` / ${comment}`;
20384
+ const spaceLeft = FITSHeaderWriter.CARD_SIZE - base.length;
20385
+ if (spaceLeft <= 0) {
20386
+ return [
20387
+ FITSHeaderWriter.card80(base),
20388
+ ...FITSHeaderWriter.makeCommentCards("COMMENT", comment),
20389
+ ];
20390
+ }
20391
+ base += addition.slice(0, spaceLeft);
20392
+ const overflow = addition.slice(spaceLeft).replace(/^\s*\/\s*/, "");
20393
+ if (overflow.length === 0) {
20394
+ return [FITSHeaderWriter.card80(base)];
20395
+ }
20396
+ return [
20397
+ FITSHeaderWriter.card80(base),
20398
+ ...FITSHeaderWriter.makeCommentCards("COMMENT", overflow),
20399
+ ];
20400
+ }
20401
+ static makeCommentCards(kind, text) {
20402
+ const prefix = FITSHeaderWriter.keyword(kind);
20403
+ const width = FITSHeaderWriter.CARD_SIZE - prefix.length;
20404
+ const value = String(text ?? "");
20405
+ if (value.length === 0) {
20406
+ return [FITSHeaderWriter.card80(prefix)];
20407
+ }
20408
+ const cards = [];
20409
+ for (let offset = 0; offset < value.length; offset += width) {
20410
+ cards.push(FITSHeaderWriter.card80(prefix + value.slice(offset, offset + width)));
20411
+ }
20412
+ return cards;
20413
+ }
20414
+ static valueField20(key, value) {
20415
+ if (FITSHeaderWriter.LOGICAL_KEYWORDS.has(key)) {
20416
+ const logical = value === true || value === "T" || value === "t" ? "T" : "F";
20417
+ return `= ${logical.padStart(20, " ")}`;
20418
+ }
20419
+ if (FITSHeaderWriter.INTEGER_KEYWORDS.has(key) || /^NAXIS\d+$/.test(key)) {
20420
+ const number = Number(value);
20421
+ if (!Number.isFinite(number) || !Number.isInteger(number)) {
20422
+ throw new Error(`FITS header: ${key} must be an integer, got ${value}`);
20423
+ }
20424
+ return `= ${String(number).padStart(20, " ")}`;
20425
+ }
20426
+ if (typeof value === "number") {
20427
+ let encoded = Number.isInteger(value)
20428
+ ? String(value)
20429
+ : value.toExponential(10).replace("e", "E");
20430
+ if (encoded.length > 20) {
20431
+ encoded = value.toExponential(8).replace("e", "E");
20432
+ }
20433
+ return `= ${encoded.padStart(20, " ")}`;
20434
+ }
20435
+ if (typeof value === "string") {
20436
+ return `= ${FITSHeaderWriter.quoteFitsString(value)}`;
20437
+ }
20438
+ return "";
20439
+ }
20440
+ static quoteFitsString(value) {
20441
+ const unquoted = value.replace(/^'+|'+$/g, "");
20442
+ const escaped = unquoted.replace(/'/g, "''");
20443
+ return `'${escaped}'`;
20444
+ }
20445
+ static keyword(value) {
20446
+ return (value ?? "").toUpperCase().padEnd(8, " ").slice(0, 8);
20447
+ }
20448
+ static card80(value) {
20449
+ if (value.length >= FITSHeaderWriter.CARD_SIZE) {
20450
+ return value.slice(0, FITSHeaderWriter.CARD_SIZE);
20451
+ }
20452
+ return value.padEnd(FITSHeaderWriter.CARD_SIZE, " ");
20453
+ }
20454
+ static encodeAndPad(cards) {
20455
+ let header = cards.join("");
20456
+ const remainder = header.length % FITSHeaderWriter.BLOCK_SIZE;
20457
+ if (remainder !== 0) {
20458
+ header += " ".repeat(FITSHeaderWriter.BLOCK_SIZE - remainder);
20459
+ }
20460
+ return new TextEncoder().encode(header);
20461
+ }
20462
+ }
20463
+ //# sourceMappingURL=FITSHeaderWriter.js.map
20464
+ ;// ./node_modules/jsfitsio/lib-esm/FITSWriter.js
20465
+ /**
20466
+ * FITS serialization and file writing support.
20467
+ *
20468
+ * FITSWriter provides two serialization APIs:
20469
+ *
20470
+ * - The jsfitsio 3.x API serializes the FITSFile/HDU data model,
20471
+ * including PrimaryHDU, ImageHDU, BinaryTableHDU and AsciiTableHDU.
20472
+ *
20473
+ * - The legacy API serializes the former FITSParsed representation
20474
+ * and is retained for backward compatibility with jsfitsio 2.x
20475
+ * consumers.
20476
+ *
20477
+ * FITS headers are serialized according to the FITS 80-character
20478
+ * card format and padded to 2880-byte FITS logical blocks.
20479
+ * HDU payloads are likewise padded to 2880-byte boundaries.
20480
+ *
20481
+ * New code should use FITSFile together with createFITSFile() and
20482
+ * writeFITSFileModel().
20483
+ *
20484
+ * @see https://fits.gsfc.nasa.gov/
20485
+ */
20486
+
20487
+
20488
+ class FITSWriter {
20489
+ /**
20490
+ * Serializes the legacy FITSParsed representation.
20491
+ *
20492
+ * @deprecated Use createFITSFile() with the FITSFile/HDU model.
20493
+ * This method is retained for backward compatibility with jsfitsio 2.x.
20494
+ */
20495
+ static createFITS(fitsParsed) {
20496
+ const headerBytes = FITSHeaderWriter.serialize(fitsParsed.header, true);
20497
+ const dataBytes = this.createData(fitsParsed.data, fitsParsed.header);
20498
+ const fitsFile = new Uint8Array(headerBytes.length + dataBytes.length);
20499
+ fitsFile.set(headerBytes, 0);
20500
+ fitsFile.set(dataBytes, headerBytes.length);
20501
+ return fitsFile;
20502
+ }
20503
+ static createHDU(hdu, primary) {
20504
+ const headerBytes = FITSHeaderWriter.serialize(hdu.header, primary);
20505
+ const rawData = hdu.rawData ?? new Uint8Array(0);
20506
+ if (rawData.byteLength !== hdu.dataByteLength) {
20507
+ throw new Error(`HDU payload length mismatch: ` +
20508
+ `rawData contains ${rawData.byteLength} bytes, ` +
20509
+ `but dataByteLength=${hdu.dataByteLength}.`);
20510
+ }
20511
+ const dataBytes = FITSWriter.padData(rawData);
20512
+ const result = new Uint8Array(headerBytes.byteLength + dataBytes.byteLength);
20513
+ result.set(headerBytes, 0);
20514
+ result.set(dataBytes, headerBytes.byteLength);
20515
+ return result;
20516
+ }
20517
+ static padData(data) {
20518
+ const BLOCK = 2880;
20519
+ if (data.byteLength === 0) {
20520
+ return new Uint8Array(0);
20521
+ }
20522
+ const remainder = data.byteLength % BLOCK;
20523
+ if (remainder === 0) {
20524
+ return data.slice();
20525
+ }
20526
+ const padded = new Uint8Array(data.byteLength + (BLOCK - remainder));
20527
+ padded.set(data);
20528
+ return padded;
20529
+ }
20530
+ static createData(data, header) {
20531
+ // concat
20532
+ const totalLength = data.reduce((s, c) => s + c.length, 0);
20533
+ // OPTIONAL: verify size from BITPIX/NAXIS
20534
+ const bitpix = Math.abs(Number(header.findById("BITPIX")?.value ?? 0));
20535
+ const naxis = Number(header.findById("NAXIS")?.value ?? 0);
20536
+ let elems = 1;
20537
+ for (let k = 1; k <= naxis; k++) {
20538
+ elems *= Number(header.findById(`NAXIS${k}`)?.value ?? 0);
20539
+ }
20540
+ const bytesPerElem = bitpix / 8;
20541
+ const expectedUnpadded = naxis > 0 ? elems * bytesPerElem : 0;
20542
+ if (expectedUnpadded && expectedUnpadded !== totalLength) {
20543
+ throw new Error(`Data length ${totalLength} does not match header expectation ${expectedUnpadded} (BITPIX=${bitpix}, NAXIS=${naxis})`);
20544
+ }
20545
+ // build and pad
20546
+ let dataBytes = new Uint8Array(totalLength);
20547
+ let off = 0;
20548
+ for (const chunk of data) {
20549
+ dataBytes.set(chunk, off);
20550
+ off += chunk.length;
20551
+ }
20552
+ return FITSWriter.padData(dataBytes);
20553
+ }
20554
+ /**
20555
+ * Serializes a jsfitsio 3.x FITSFile, including all contained HDUs.
20556
+ */
20557
+ static createFITSFile(fitsFile) {
20558
+ if (fitsFile.length === 0) {
20559
+ throw new Error("Cannot write an empty FITSFile.");
20560
+ }
20561
+ if (fitsFile.primaryHDU === null) {
20562
+ throw new Error("FITSFile must start with a PrimaryHDU.");
20563
+ }
20564
+ const serializedHDUs = fitsFile.hdus.map((hdu, index) => FITSWriter.createHDU(hdu, index === 0));
20565
+ const totalLength = serializedHDUs.reduce((sum, hdu) => sum + hdu.byteLength, 0);
20566
+ const result = new Uint8Array(totalLength);
20567
+ let offset = 0;
20568
+ for (const hdu of serializedHDUs) {
20569
+ result.set(hdu, offset);
20570
+ offset += hdu.byteLength;
20571
+ }
20572
+ return result;
20573
+ }
20574
+ /**
20575
+ * Serializes a jsfitsio 3.x FITSFile and writes it to the local filesystem.
20576
+ */
20577
+ static writeFITSFileModel(fitsFile, filePath) {
20578
+ const data = FITSWriter.createFITSFile(fitsFile);
20579
+ external_fs_namespaceObject.writeFileSync(filePath, data);
20580
+ }
20581
+ /**
20582
+ * Writes the legacy FITSParsed representation to a local file.
20583
+ *
20584
+ * @deprecated Use writeFITSFileModel() with FITSFile instead.
20585
+ * This method is retained for backward compatibility with jsfitsio 2.x.
20586
+ */
20587
+ static writeFITSFile(fitsParsed, filePath) {
20588
+ const fitsFile = FITSWriter.createFITS(fitsParsed);
20589
+ external_fs_namespaceObject.writeFileSync(filePath, fitsFile);
20590
+ }
20591
+ }
20592
+ //# sourceMappingURL=FITSWriter.js.map
20593
+ ;// ./node_modules/jsfitsio/lib-esm/ParseHeader.js
20594
+ // import { FITSHeader } from "./model/FITSHeader.js";
20595
+
20596
+
20597
+ /**
20598
+ * Summary. (bla bla bla)
20599
+ *
20600
+ * Description. (bla bla bla)
20601
+ *
20602
+ * @link github https://github.com/fab77/FITSParser
20603
+ * @author Fabrizio Giordano <fabriziogiordano77@gmail.com>
20604
+ */
20605
+ class ParseHeader {
20606
+ static CARD_SIZE = 80;
20607
+ static BLOCK_SIZE = 2880;
20608
+ static getFITSItemStringValue(header, key) {
20609
+ const item = header.findById(key);
20610
+ if (!item) {
20611
+ return null;
20612
+ }
20613
+ return String(item.value).trim().replace(/^'/, "").replace(/'$/, "").trim();
20614
+ }
20615
+ static getFITSItemValue(header, key) {
20616
+ const item = header.findById(key);
20617
+ if (!item) {
20618
+ return null;
20619
+ }
20620
+ const value = Number(item.value);
20621
+ return Number.isNaN(value) ? null : value;
20622
+ }
20623
+ /**
20624
+ * Returns the complete FITS header size, including padding
20625
+ * up to the next 2880-byte boundary.
20626
+ */
20627
+ static getHeaderByteLength(rawData, startOffset = 0) {
20628
+ const decoder = new TextDecoder("ascii");
20629
+ for (let offset = startOffset; offset + ParseHeader.CARD_SIZE <= rawData.byteLength; offset += ParseHeader.CARD_SIZE) {
20630
+ const key = decoder.decode(rawData.subarray(offset, offset + 8)).trim();
20631
+ if (key === "END") {
20632
+ const consumed = offset + ParseHeader.CARD_SIZE - startOffset;
20633
+ return (Math.ceil(consumed / ParseHeader.BLOCK_SIZE) * ParseHeader.BLOCK_SIZE);
20634
+ }
20635
+ }
20636
+ throw new Error("Invalid FITS header: END card not found.");
20637
+ }
20638
+ static parse(rawData, startOffset = 0) {
20639
+ const decoder = new TextDecoder("ascii");
20640
+ const headerLength = ParseHeader.getHeaderByteLength(rawData, startOffset);
20641
+ const header = new FITSHeaderManager(false);
20642
+ for (let offset = startOffset; offset < startOffset + headerLength; offset += ParseHeader.CARD_SIZE) {
20643
+ const line = decoder.decode(rawData.subarray(offset, offset + ParseHeader.CARD_SIZE));
20644
+ const key = line.slice(0, 8).trim();
20645
+ if (key === "END") {
20646
+ break;
20647
+ }
20648
+ if (!key) {
20649
+ continue;
20650
+ }
20651
+ let value;
20652
+ let comment = "";
20653
+ const rawValue = line.slice(10).trim().split("/")[0].trim();
20654
+ if (Number.isNaN(Number(rawValue))) {
20655
+ value = rawValue;
20656
+ }
20657
+ else {
20658
+ value = Number(rawValue);
20659
+ }
20660
+ if (line.includes("/")) {
20661
+ comment = line.slice(10).trim().split("/")[1]?.trim() ?? "";
20662
+ }
20663
+ header.insert(new FITSHeaderItem(key, value, comment));
20664
+ }
20665
+ return header;
20666
+ }
20667
+ }
20668
+ //# sourceMappingURL=ParseHeader.js.map
20669
+ ;// ./node_modules/jsfitsio/lib-esm/FITSImageUtils.js
20670
+
20671
+
20672
+ class FITSImageUtils {
20673
+ static getShape(header) {
20674
+ const naxis = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS);
20675
+ if (naxis === null) {
20676
+ throw new Error("NAXIS not defined.");
20677
+ }
20678
+ if (!Number.isInteger(naxis) || naxis < 0) {
20679
+ throw new Error(`Invalid FITS NAXIS value: ${naxis}`);
20680
+ }
20681
+ const shape = [];
20682
+ for (let axis = 1; axis <= naxis; axis++) {
20683
+ const size = ParseHeader.getFITSItemValue(header, FITSHeaderManager.naxisKey(axis));
20684
+ if (size === null) {
20685
+ throw new Error(`NAXIS${axis} not defined.`);
20686
+ }
20687
+ shape.push(size);
20688
+ }
20689
+ return shape;
20690
+ }
20691
+ static getElementCount(shape) {
20692
+ if (shape.length === 0) {
20693
+ return 0;
20694
+ }
20695
+ return shape.reduce((total, dimension) => total * dimension, 1);
20696
+ }
20697
+ }
20698
+ //# sourceMappingURL=FITSImageUtils.js.map
20699
+ ;// ./node_modules/jsfitsio/lib-esm/ParsePayload.js
20700
+ // "use strict";
20701
+ /**
20702
+ * Summary. (bla bla bla)
20703
+ *
20704
+ * Description. (bla bla bla)
20705
+ *
20706
+ * @link github https://github.com/fab77/FITSParser
20707
+ * @author Fabrizio Giordano <fabriziogiordano77@gmail.com>
20708
+ */
20709
+
20710
+
20711
+
20712
+
20713
+ class ParsePayload {
20714
+ static SUPPORTED_BITPIX = new Set([8, 16, 32, 64, -32, -64]);
20715
+ static assertSupportedBITPIX(bitpix) {
20716
+ if (!ParsePayload.SUPPORTED_BITPIX.has(bitpix)) {
20717
+ throw new Error(`Unsupported FITS BITPIX value: ${bitpix}`);
20718
+ }
20719
+ }
20720
+ static extractPixelFromView(view, offset, bitpix) {
20721
+ switch (bitpix) {
20722
+ case 8:
20723
+ return view.getUint8(offset);
20724
+ case 16:
20725
+ return view.getInt16(offset, false);
20726
+ case 32:
20727
+ return view.getInt32(offset, false);
20728
+ case -32:
20729
+ return view.getFloat32(offset, false);
20730
+ case -64:
20731
+ return view.getFloat64(offset, false);
20732
+ case 64: {
20733
+ const value = view.getBigInt64(offset, false);
20734
+ const numeric = Number(value);
20735
+ if (!Number.isSafeInteger(numeric)) {
20736
+ throw new RangeError(`BITPIX=64 value ${value} cannot be represented ` +
20737
+ `exactly as a JavaScript number.`);
20738
+ }
20739
+ return numeric;
20740
+ }
20741
+ default:
20742
+ throw new Error(`Unsupported FITS BITPIX value: ${bitpix}`);
20743
+ }
20744
+ }
20745
+ static computePhysicalMinAndMax(header, payload) {
20746
+ const bitpix = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BITPIX);
20747
+ if (bitpix === null) {
20748
+ return null;
20749
+ }
20750
+ ParsePayload.assertSupportedBITPIX(bitpix);
20751
+ const shape = FITSImageUtils.getShape(header);
20752
+ /*
20753
+ * NAXIS=0 is a valid FITS HDU.
20754
+ */
20755
+ if (shape.length === 0 || payload.byteLength === 0) {
20756
+ return header;
20757
+ }
20758
+ const dataMinItem = header.findById(FITSHeaderManager.DATAMIN);
20759
+ const dataMaxItem = header.findById(FITSHeaderManager.DATAMAX);
20760
+ if (dataMinItem === null || dataMaxItem === null) {
20761
+ try {
20762
+ const [min, max] = ParsePayload.computePhysicalValues(payload, header);
20763
+ if (dataMinItem === null && min !== null) {
20764
+ header.insert(new FITSHeaderItem(FITSHeaderManager.DATAMIN, min, "computed by jsfitsio"));
20765
+ }
20766
+ if (dataMaxItem === null && max !== null) {
20767
+ header.insert(new FITSHeaderItem(FITSHeaderManager.DATAMAX, max, "computed by jsfitsio"));
20768
+ }
20769
+ }
20770
+ catch (error) {
20771
+ if (bitpix === 64 && error instanceof RangeError) {
20772
+ return header;
20773
+ }
20774
+ throw error;
20775
+ }
20776
+ }
20777
+ return header;
20778
+ }
20779
+ static createTypedArray(rawData, bitpix) {
20780
+ ParsePayload.assertSupportedBITPIX(bitpix);
20781
+ const bytesPerElement = Math.abs(bitpix) / 8;
20782
+ if (rawData.byteLength % bytesPerElement !== 0) {
20783
+ throw new Error(`Payload byte length ${rawData.byteLength} ` +
20784
+ `is not aligned with BITPIX=${bitpix}.`);
20785
+ }
20786
+ const count = rawData.byteLength / bytesPerElement;
20787
+ const view = new DataView(rawData.buffer, rawData.byteOffset, rawData.byteLength);
20788
+ switch (bitpix) {
20789
+ case 8: {
20790
+ /*
20791
+ * For 8-bit FITS, byte order is irrelevant.
20792
+ *
20793
+ * Use slice() so typedData has its own correctly
20794
+ * sized backing store.
20795
+ */
20796
+ return rawData.slice();
20797
+ }
20798
+ case 16: {
20799
+ const result = new Int16Array(count);
20800
+ for (let i = 0; i < count; i++) {
20801
+ result[i] = view.getInt16(i * 2, false);
20802
+ }
20803
+ return result;
20804
+ }
20805
+ case 32: {
20806
+ const result = new Int32Array(count);
20807
+ for (let i = 0; i < count; i++) {
20808
+ result[i] = view.getInt32(i * 4, false);
20809
+ }
20810
+ return result;
20811
+ }
20812
+ case 64: {
20813
+ const result = new BigInt64Array(count);
20814
+ for (let i = 0; i < count; i++) {
20815
+ result[i] = view.getBigInt64(i * 8, false);
20816
+ }
20817
+ return result;
20818
+ }
20819
+ case -32: {
20820
+ const result = new Float32Array(count);
20821
+ for (let i = 0; i < count; i++) {
20822
+ result[i] = view.getFloat32(i * 4, false);
20823
+ }
20824
+ return result;
20825
+ }
20826
+ case -64: {
20827
+ const result = new Float64Array(count);
20828
+ for (let i = 0; i < count; i++) {
20829
+ result[i] = view.getFloat64(i * 8, false);
20830
+ }
20831
+ return result;
20832
+ }
20833
+ default:
20834
+ throw new Error(`Unsupported FITS BITPIX value: ${bitpix}`);
20835
+ }
20836
+ }
20837
+ static computePhysicalValues(rawData, header) {
20838
+ const bitpix = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BITPIX);
20839
+ if (bitpix === null) {
20840
+ return [null, null];
20841
+ }
20842
+ ParsePayload.assertSupportedBITPIX(bitpix);
20843
+ const shape = FITSImageUtils.getShape(header);
20844
+ const pixelCount = FITSImageUtils.getElementCount(shape);
20845
+ if (pixelCount === 0) {
20846
+ return [null, null];
20847
+ }
20848
+ const blank = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BLANK);
20849
+ const bzero = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BZERO) ?? 0;
20850
+ const bscale = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BSCALE) ?? 1;
20851
+ const bytesPerElement = Math.abs(bitpix) / 8;
20852
+ const requiredBytes = pixelCount * bytesPerElement;
20853
+ if (rawData.byteLength < requiredBytes) {
20854
+ throw new Error(`FITS payload is too short: expected ${requiredBytes} bytes, ` +
20855
+ `received ${rawData.byteLength}.`);
20856
+ }
20857
+ const view = new DataView(rawData.buffer, rawData.byteOffset, rawData.byteLength);
20858
+ let min = null;
20859
+ let max = null;
20860
+ for (let i = 0; i < pixelCount; i++) {
20861
+ const rawValue = ParsePayload.extractPixelFromView(view, i * bytesPerElement, bitpix);
20862
+ // BLANK applies to integer FITS image data.
20863
+ if (bitpix > 0 && blank !== null && rawValue === blank) {
20864
+ continue;
20865
+ }
20866
+ const physicalValue = ParsePayload.pixel2physicalValue(rawValue, bscale, bzero);
20867
+ // Floating-point FITS images may contain NaN.
20868
+ if (Number.isNaN(physicalValue)) {
20869
+ continue;
20870
+ }
20871
+ if (min === null || physicalValue < min) {
20872
+ min = physicalValue;
20873
+ }
20874
+ if (max === null || physicalValue > max) {
20875
+ max = physicalValue;
20876
+ }
20877
+ }
20878
+ return [min, max];
20879
+ }
20880
+ static pixel2physicalValue(pxval, BSCALE, BZERO) {
20881
+ if (BZERO === null || BSCALE === null) {
20882
+ throw new Error("Either BZERO or BSCALE is null");
20883
+ }
20884
+ return BZERO + BSCALE * pxval;
20885
+ }
20886
+ static extractPixelValue(rawData, offset, bitpix) {
20887
+ ParsePayload.assertSupportedBITPIX(bitpix);
20888
+ const view = new DataView(rawData.buffer, rawData.byteOffset, rawData.byteLength);
20889
+ return ParsePayload.extractPixelFromView(view, offset, bitpix);
20890
+ }
20891
+ }
20892
+ //# sourceMappingURL=ParsePayload.js.map
20893
+ ;// ./node_modules/jsfitsio/lib-esm/model/FITSHDU.js
20894
+ class FITSHDU {
20895
+ header;
20896
+ rawData;
20897
+ dataOffset;
20898
+ dataByteLength;
20899
+ constructor(header, rawData, dataOffset, dataByteLength) {
20900
+ this.header = header;
20901
+ this.rawData = rawData;
20902
+ this.dataOffset = dataOffset;
20903
+ this.dataByteLength = dataByteLength;
20904
+ }
20905
+ }
20906
+ //# sourceMappingURL=FITSHDU.js.map
20907
+ ;// ./node_modules/jsfitsio/lib-esm/model/ImageHDU.js
20908
+
20909
+ class ImageHDU extends FITSHDU {
20910
+ bitpix;
20911
+ shape;
20912
+ typedData;
20913
+ type = "IMAGE";
20914
+ constructor(header, rawData, dataOffset, dataByteLength, bitpix, shape, typedData) {
20915
+ super(header, rawData, dataOffset, dataByteLength);
20916
+ this.bitpix = bitpix;
20917
+ this.shape = shape;
20918
+ this.typedData = typedData;
20919
+ }
20920
+ get naxis() {
20921
+ return this.shape.length;
20922
+ }
20923
+ get elementCount() {
20924
+ if (this.shape.length === 0) {
20925
+ return 0;
20926
+ }
20927
+ return this.shape.reduce((accumulator, dimension) => accumulator * dimension, 1);
20928
+ }
20929
+ }
20930
+ //# sourceMappingURL=ImageHDU.js.map
20931
+ ;// ./node_modules/jsfitsio/lib-esm/model/PrimaryHDU.js
20932
+
20933
+ class PrimaryHDU extends ImageHDU {
20934
+ type = "PRIMARY";
20935
+ constructor(header, rawData, dataOffset, dataByteLength, bitpix, shape, typedData) {
20936
+ super(header, rawData, dataOffset, dataByteLength, bitpix, shape, typedData);
20937
+ }
20938
+ }
20939
+ //# sourceMappingURL=PrimaryHDU.js.map
20940
+ ;// ./node_modules/jsfitsio/lib-esm/model/FITSFile.js
20941
+
20942
+ class FITSFile {
20943
+ _hdus;
20944
+ constructor(hdus = []) {
20945
+ this._hdus = [...hdus];
20946
+ }
20947
+ get hdus() {
20948
+ return this._hdus;
20949
+ }
20950
+ get length() {
20951
+ return this._hdus.length;
20952
+ }
20953
+ get primaryHDU() {
20954
+ const hdu = this._hdus[0];
20955
+ if (hdu instanceof PrimaryHDU) {
20956
+ return hdu;
20957
+ }
20958
+ return null;
20959
+ }
20960
+ getHDU(index) {
20961
+ return this._hdus[index] ?? null;
20962
+ }
20963
+ addHDU(hdu) {
20964
+ this._hdus.push(hdu);
20965
+ }
20966
+ }
20967
+ //# sourceMappingURL=FITSFile.js.map
20968
+ ;// ./node_modules/jsfitsio/lib-esm/model/BinaryTableHDU.js
20969
+
20970
+ class BinaryTableHDU extends FITSHDU {
20971
+ rowByteLength;
20972
+ rowCount;
20973
+ columns;
20974
+ type = "BINTABLE";
20975
+ constructor(header, rawData, dataOffset, dataByteLength, rowByteLength, rowCount, columns) {
20976
+ super(header, rawData, dataOffset, dataByteLength);
20977
+ this.rowByteLength = rowByteLength;
20978
+ this.rowCount = rowCount;
20979
+ this.columns = columns;
20980
+ }
20981
+ get columnCount() {
20982
+ return this.columns.length;
20983
+ }
20984
+ getRowView(rowIndex) {
20985
+ if (rowIndex < 0 || rowIndex >= this.rowCount) {
20986
+ throw new RangeError(`Invalid row index ${rowIndex}.`);
20987
+ }
20988
+ const offset = rowIndex * this.rowByteLength;
20989
+ return new DataView(this.rawData.buffer, this.rawData.byteOffset + offset, this.rowByteLength);
20990
+ }
20991
+ getRow(rowIndex) {
20992
+ return this.columns.map((_, columnIndex) => this.getCell(rowIndex, columnIndex));
20993
+ }
20994
+ getCell(rowIndex, column) {
20995
+ const columnDefinition = this.resolveColumn(column);
20996
+ const row = this.getRowView(rowIndex);
20997
+ const offset = columnDefinition.byteOffset;
20998
+ const repeat = columnDefinition.repeat;
20999
+ switch (columnDefinition.type) {
21000
+ case "CHAR": {
21001
+ const bytes = new Uint8Array(row.buffer, row.byteOffset + offset, columnDefinition.byteWidth);
21002
+ return new TextDecoder("ascii").decode(bytes).replace(/\s+$/, "");
21003
+ }
21004
+ case "LOGICAL": {
21005
+ const values = [];
21006
+ for (let i = 0; i < repeat; i++) {
21007
+ const value = String.fromCharCode(row.getUint8(offset + i));
21008
+ values.push(value === "T");
21009
+ }
21010
+ return repeat === 1 ? values[0] : values;
21011
+ }
21012
+ case "UINT8": {
21013
+ const values = [];
21014
+ for (let i = 0; i < repeat; i++) {
21015
+ const raw = row.getUint8(offset + i);
21016
+ values.push(this.applyNumericScaling(raw, columnDefinition.scale, columnDefinition.zero));
21017
+ }
21018
+ return repeat === 1 ? values[0] : values;
21019
+ }
21020
+ case "INT16":
21021
+ return this.readNumericColumn(row, offset, repeat, 2, (view, position) => view.getInt16(position, false), columnDefinition.scale, columnDefinition.zero, columnDefinition.nullValue);
21022
+ case "INT32":
21023
+ return this.readNumericColumn(row, offset, repeat, 4, (view, position) => view.getInt32(position, false), columnDefinition.scale, columnDefinition.zero, columnDefinition.nullValue);
21024
+ case "INT64": {
21025
+ const values = [];
21026
+ for (let i = 0; i < repeat; i++) {
21027
+ const raw = row.getBigInt64(offset + i * 8, false);
21028
+ /*
21029
+ * Preserve exact 64-bit integers.
21030
+ *
21031
+ * Do not silently convert bigint to number.
21032
+ */
21033
+ values.push(raw);
21034
+ }
21035
+ return repeat === 1 ? values[0] : values;
21036
+ }
21037
+ case "FLOAT32":
21038
+ return this.readNumericColumn(row, offset, repeat, 4, (view, position) => view.getFloat32(position, false), columnDefinition.scale, columnDefinition.zero, null);
21039
+ case "FLOAT64":
21040
+ return this.readNumericColumn(row, offset, repeat, 8, (view, position) => view.getFloat64(position, false), columnDefinition.scale, columnDefinition.zero, null);
21041
+ case "COMPLEX64": {
21042
+ const values = [];
21043
+ for (let i = 0; i < repeat; i++) {
21044
+ const position = offset + i * 8;
21045
+ values.push({
21046
+ real: row.getFloat32(position, false),
21047
+ imaginary: row.getFloat32(position + 4, false),
21048
+ });
21049
+ }
21050
+ return repeat === 1 ? values[0] : values;
21051
+ }
21052
+ case "COMPLEX128": {
21053
+ const values = [];
21054
+ for (let i = 0; i < repeat; i++) {
21055
+ const position = offset + i * 16;
21056
+ values.push({
21057
+ real: row.getFloat64(position, false),
21058
+ imaginary: row.getFloat64(position + 8, false),
21059
+ });
21060
+ }
21061
+ return repeat === 1 ? values[0] : values;
21062
+ }
21063
+ case "BIT":
21064
+ /*
21065
+ * I'd defer bit-array decoding for the moment.
21066
+ * The raw bytes remain available.
21067
+ */
21068
+ return new Uint8Array(row.buffer, row.byteOffset + offset, columnDefinition.byteWidth).slice();
21069
+ default:
21070
+ throw new Error(`Unsupported BINTABLE column type: ${columnDefinition.type}`);
21071
+ }
21072
+ }
21073
+ readNumericColumn(view, offset, repeat, bytesPerElement, reader, scale, zero, nullValue) {
21074
+ const values = [];
21075
+ for (let i = 0; i < repeat; i++) {
21076
+ const raw = reader(view, offset + i * bytesPerElement);
21077
+ if (nullValue !== null && raw === nullValue) {
21078
+ values.push(null);
21079
+ continue;
21080
+ }
21081
+ values.push(this.applyNumericScaling(raw, scale, zero));
21082
+ }
21083
+ if (repeat === 1) {
21084
+ return values[0];
21085
+ }
21086
+ /*
21087
+ * Because repeated integer fields may contain NULL,
21088
+ * we cannot represent every case as number[].
21089
+ *
21090
+ * For now return a generic value array.
21091
+ */
21092
+ return values;
21093
+ }
21094
+ applyNumericScaling(raw, scale, zero) {
21095
+ return zero + scale * raw;
21096
+ }
21097
+ resolveColumn(column) {
21098
+ if (typeof column === "number") {
21099
+ if (!Number.isInteger(column) ||
21100
+ column < 0 ||
21101
+ column >= this.columns.length) {
21102
+ throw new RangeError(`Invalid column index ${column}.`);
21103
+ }
21104
+ return this.columns[column];
21105
+ }
21106
+ const found = this.columns.find((candidate) => candidate.name === column);
21107
+ if (!found) {
21108
+ throw new Error(`BINTABLE column '${column}' not found.`);
21109
+ }
21110
+ return found;
21111
+ }
21112
+ }
21113
+ //# sourceMappingURL=BinaryTableHDU.js.map
21114
+ ;// ./node_modules/jsfitsio/lib-esm/FITSBinaryTableUtils.js
21115
+ class FITSBinaryTableUtils {
21116
+ static parseTFORM(format) {
21117
+ const normalized = format
21118
+ .trim()
21119
+ .replace(/^'/, "")
21120
+ .replace(/'$/, "")
21121
+ .trim()
21122
+ .toUpperCase();
21123
+ const match = normalized.match(/^(\d*)([LXBIJKAEDCM])$/);
21124
+ if (!match) {
21125
+ throw new Error(`Unsupported FITS TFORM value: ${format}`);
21126
+ }
21127
+ const repeat = match[1] ? Number(match[1]) : 1;
21128
+ const code = match[2];
21129
+ const bytesPerElement = FITSBinaryTableUtils.bytesPerType(code);
21130
+ return {
21131
+ repeat,
21132
+ code,
21133
+ byteWidth: code === "X" ? Math.ceil(repeat / 8) : repeat * bytesPerElement,
21134
+ };
21135
+ }
21136
+ static bytesPerType(code) {
21137
+ switch (code) {
21138
+ case "L":
21139
+ case "B":
21140
+ case "A":
21141
+ return 1;
21142
+ case "I":
21143
+ return 2;
21144
+ case "J":
21145
+ case "E":
21146
+ return 4;
21147
+ case "K":
21148
+ case "D":
21149
+ return 8;
21150
+ case "C":
21151
+ return 8;
21152
+ case "M":
21153
+ return 16;
21154
+ case "X":
21155
+ return 0;
21156
+ default:
21157
+ throw new Error(`Unsupported FITS binary table type: ${code}`);
21158
+ }
21159
+ }
21160
+ }
21161
+ //# sourceMappingURL=FITSBinaryTableUtils.js.map
21162
+ ;// ./node_modules/jsfitsio/lib-esm/model/AsciiTableHDU.js
21163
+
21164
+ class AsciiTableHDU extends FITSHDU {
21165
+ rowByteLength;
21166
+ rowCount;
21167
+ columns;
21168
+ type = "TABLE";
21169
+ constructor(header, rawData, dataOffset, dataByteLength, rowByteLength, rowCount, columns) {
21170
+ super(header, rawData, dataOffset, dataByteLength);
21171
+ this.rowByteLength = rowByteLength;
21172
+ this.rowCount = rowCount;
21173
+ this.columns = columns;
21174
+ }
21175
+ get columnCount() {
21176
+ return this.columns.length;
21177
+ }
21178
+ getRowView(rowIndex) {
21179
+ if (!Number.isInteger(rowIndex) ||
21180
+ rowIndex < 0 ||
21181
+ rowIndex >= this.rowCount) {
21182
+ throw new RangeError(`Invalid row index ${rowIndex}.`);
21183
+ }
21184
+ const start = rowIndex * this.rowByteLength;
21185
+ return this.rawData.subarray(start, start + this.rowByteLength);
21186
+ }
21187
+ getRowText(rowIndex) {
21188
+ return new TextDecoder("ascii").decode(this.getRowView(rowIndex));
21189
+ }
21190
+ resolveColumn(column) {
21191
+ if (typeof column === "number") {
21192
+ if (!Number.isInteger(column) ||
21193
+ column < 0 ||
21194
+ column >= this.columns.length) {
21195
+ throw new RangeError(`Invalid column index ${column}.`);
21196
+ }
21197
+ return this.columns[column];
21198
+ }
21199
+ const found = this.columns.find((candidate) => candidate.name === column);
21200
+ if (!found) {
21201
+ throw new Error(`ASCII TABLE column '${column}' not found.`);
21202
+ }
21203
+ return found;
21204
+ }
21205
+ getCell(rowIndex, column) {
21206
+ const definition = this.resolveColumn(column);
21207
+ const row = this.getRowView(rowIndex);
21208
+ const bytes = row.subarray(definition.byteOffset, definition.byteOffset + definition.width);
21209
+ const raw = new TextDecoder("ascii").decode(bytes);
21210
+ const trimmed = raw.trim();
21211
+ /*
21212
+ * Blank numeric fields are treated as null.
21213
+ */
21214
+ if (trimmed.length === 0) {
21215
+ return definition.type === "CHAR" ? "" : null;
21216
+ }
21217
+ switch (definition.type) {
21218
+ case "CHAR":
21219
+ return raw.replace(/\s+$/, "");
21220
+ case "INTEGER": {
21221
+ const value = Number.parseInt(trimmed, 10);
21222
+ if (Number.isNaN(value)) {
21223
+ return null;
21224
+ }
21225
+ return value;
21226
+ }
21227
+ case "FLOAT":
21228
+ case "EXPONENTIAL":
21229
+ case "DOUBLE": {
21230
+ /*
21231
+ * FITS ASCII tables may use D exponent notation.
21232
+ * JavaScript expects E.
21233
+ */
21234
+ const normalized = trimmed.replace(/[dD]/, "E");
21235
+ const value = Number.parseFloat(normalized);
21236
+ if (Number.isNaN(value)) {
21237
+ return null;
21238
+ }
21239
+ return value;
21240
+ }
21241
+ default:
21242
+ throw new Error(`Unsupported ASCII TABLE column type: ${definition.type}`);
21243
+ }
21244
+ }
21245
+ getRow(rowIndex) {
21246
+ return this.columns.map((_, columnIndex) => this.getCell(rowIndex, columnIndex));
21247
+ }
21248
+ }
21249
+ //# sourceMappingURL=AsciiTableHDU.js.map
21250
+ ;// ./node_modules/jsfitsio/lib-esm/FITSAsciiTableUtils.js
21251
+ class FITSAsciiTableUtils {
21252
+ static parseTFORM(format) {
21253
+ const normalized = format
21254
+ .trim()
21255
+ .replace(/^'/, "")
21256
+ .replace(/'$/, "")
21257
+ .trim()
21258
+ .toUpperCase();
21259
+ /*
21260
+ * FITS ASCII table formats:
21261
+ *
21262
+ * Aw
21263
+ * Iw
21264
+ * Fw.d
21265
+ * Ew.d
21266
+ * Dw.d
21267
+ */
21268
+ const match = normalized.match(/^([AIFED])(\d+)(?:\.(\d+))?$/);
21269
+ if (!match) {
21270
+ throw new Error(`Unsupported FITS ASCII table TFORM value: ${format}`);
21271
+ }
21272
+ const code = match[1];
21273
+ const width = Number(match[2]);
21274
+ const decimals = match[3] !== undefined
21275
+ ? Number(match[3])
21276
+ : null;
21277
+ if (!Number.isInteger(width) ||
21278
+ width <= 0) {
21279
+ throw new Error(`Invalid FITS ASCII table field width: ${width}`);
21280
+ }
21281
+ if (code === "A" ||
21282
+ code === "I") {
21283
+ if (decimals !== null) {
21284
+ throw new Error(`TFORM ${format} must not specify decimal places.`);
21285
+ }
21286
+ }
21287
+ else if (decimals === null) {
21288
+ throw new Error(`TFORM ${format} requires decimal places.`);
21289
+ }
21290
+ return {
21291
+ code,
21292
+ width,
21293
+ decimals,
21294
+ };
21295
+ }
21296
+ }
21297
+ //# sourceMappingURL=FITSAsciiTableUtils.js.map
21298
+ ;// ./node_modules/jsfitsio/lib-esm/FITSParser.js
21299
+
21300
+
21301
+
21302
+
21303
+
21304
+
21305
+
21306
+
21307
+
21308
+
21309
+
21310
+
21311
+ class FITSParser {
21312
+ /**
21313
+ * @deprecated Use loadFITSFile() instead.
21314
+ *
21315
+ * This legacy API supports only 2-dimensional image FITS files
21316
+ * and returns the former FITSParsed structure.
21317
+ */
21318
+ static async loadFITS(path, options = {}) {
21319
+ const fitsFile = await FITSParser.loadFITSFile(path, options);
21320
+ if (fitsFile === null) {
21321
+ return null;
21322
+ }
21323
+ const primary = fitsFile.primaryHDU;
21324
+ if (primary === null || primary.rawData === null) {
21325
+ return null;
21326
+ }
21327
+ const shape = FITSImageUtils.getShape(primary.header);
21328
+ if (shape.length !== 2) {
21329
+ throw new Error("Legacy loadFITS() supports only 2D FITS images. " +
21330
+ "Use loadFITSFile() for N-dimensional images.");
21331
+ }
21332
+ return {
21333
+ header: primary.header,
21334
+ data: FITSParser.createMatrix(primary.rawData, primary.header),
21335
+ };
21336
+ }
21337
+ static async loadFITSFile(path, options = {}) {
21338
+ const rawData = await FITSParser.getFile(path);
21339
+ if (rawData.byteLength === 0) {
21340
+ return null;
21341
+ }
21342
+ return FITSParser.processFITSFile(rawData, options);
21343
+ }
21344
+ static processFITSFile(rawData, options) {
21345
+ const fitsFile = new FITSFile();
21346
+ let offset = 0;
21347
+ let hduIndex = 0;
21348
+ while (offset < rawData.byteLength) {
21349
+ /*
21350
+ * Ignore trailing zero/space padding.
21351
+ */
21352
+ if (FITSParser.isPaddingOnly(rawData, offset)) {
21353
+ break;
21354
+ }
21355
+ const header = ParseHeader.parse(rawData, offset);
21356
+ const headerByteLength = ParseHeader.getHeaderByteLength(rawData, offset);
21357
+ const dataOffset = offset + headerByteLength;
21358
+ const hduType = FITSParser.getHDUType(header, hduIndex);
21359
+ switch (hduType) {
21360
+ case "PRIMARY":
21361
+ case "IMAGE": {
21362
+ const dataByteLength = FITSParser.getImagePayloadByteLength(header);
21363
+ if (dataOffset + dataByteLength > rawData.byteLength) {
21364
+ throw new Error(`Invalid FITS HDU ${hduIndex}: ` +
21365
+ `expected ${dataByteLength} payload bytes ` +
21366
+ `at offset ${dataOffset}, but only ` +
21367
+ `${rawData.byteLength - dataOffset} remain.`);
21368
+ }
21369
+ const rawPayload = rawData.subarray(dataOffset, dataOffset + dataByteLength);
21370
+ const hdu = FITSParser.createImageHDU(header, rawPayload, dataOffset, dataByteLength, hduIndex === 0, options);
21371
+ fitsFile.addHDU(hdu);
21372
+ const paddedPayloadLength = FITSParser.getPaddedByteLength(dataByteLength);
21373
+ offset = dataOffset + paddedPayloadLength;
21374
+ break;
21375
+ }
21376
+ case "BINTABLE": {
21377
+ const dataByteLength = FITSParser.getBinaryTablePayloadByteLength(header);
21378
+ if (dataOffset + dataByteLength > rawData.byteLength) {
21379
+ throw new Error(`Invalid BINTABLE HDU ${hduIndex}.`);
21380
+ }
21381
+ const rawPayload = rawData.subarray(dataOffset, dataOffset + dataByteLength);
21382
+ const hdu = FITSParser.createBinaryTableHDU(header, rawPayload, dataOffset, dataByteLength);
21383
+ fitsFile.addHDU(hdu);
21384
+ offset = dataOffset + FITSParser.getPaddedByteLength(dataByteLength);
21385
+ break;
21386
+ }
21387
+ case "TABLE": {
21388
+ const dataByteLength = FITSParser.getAsciiTablePayloadByteLength(header);
21389
+ if (dataOffset + dataByteLength > rawData.byteLength) {
21390
+ throw new Error(`Invalid ASCII TABLE HDU ${hduIndex}: ` +
21391
+ `expected ${dataByteLength} payload bytes ` +
21392
+ `at offset ${dataOffset}, but only ` +
21393
+ `${rawData.byteLength - dataOffset} remain.`);
21394
+ }
21395
+ const rawPayload = rawData.subarray(dataOffset, dataOffset + dataByteLength);
21396
+ const hdu = FITSParser.createAsciiTableHDU(header, rawPayload, dataOffset, dataByteLength);
21397
+ fitsFile.addHDU(hdu);
21398
+ offset = dataOffset + FITSParser.getPaddedByteLength(dataByteLength);
21399
+ break;
21400
+ }
21401
+ default:
21402
+ throw new Error(`Unsupported FITS HDU type at index ${hduIndex}.`);
21403
+ }
21404
+ hduIndex++;
21405
+ }
21406
+ return fitsFile;
21407
+ }
21408
+ static getPaddedByteLength(byteLength) {
21409
+ if (byteLength === 0) {
21410
+ return 0;
21411
+ }
21412
+ return (Math.ceil(byteLength / ParseHeader.BLOCK_SIZE) * ParseHeader.BLOCK_SIZE);
21413
+ }
21414
+ static isPaddingOnly(rawData, offset) {
21415
+ for (let i = offset; i < rawData.byteLength; i++) {
21416
+ const value = rawData[i];
21417
+ if (value !== 0x00 && value !== 0x20) {
21418
+ return false;
21419
+ }
21420
+ }
21421
+ return true;
21422
+ }
21423
+ static getHDUType(header, index) {
21424
+ if (index === 0) {
21425
+ return "PRIMARY";
21426
+ }
21427
+ const xtension = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.XTENSION);
21428
+ if (xtension === null) {
21429
+ return "UNKNOWN";
21430
+ }
21431
+ switch (xtension.toUpperCase()) {
21432
+ case "IMAGE":
21433
+ return "IMAGE";
21434
+ case "BINTABLE":
21435
+ return "BINTABLE";
21436
+ case "TABLE":
21437
+ return "TABLE";
21438
+ default:
21439
+ return "UNKNOWN";
21440
+ }
21441
+ }
21442
+ static createImageHDU(header, rawPayload, dataOffset, dataByteLength, primary, options) {
21443
+ const finalHeader = options.computeDataMinMax
21444
+ ? (ParsePayload.computePhysicalMinAndMax(header, rawPayload) ?? header)
21445
+ : header;
21446
+ const bitpix = ParseHeader.getFITSItemValue(finalHeader, FITSHeaderManager.BITPIX);
21447
+ if (bitpix === null) {
21448
+ throw new Error("BITPIX not defined.");
21449
+ }
21450
+ const shape = FITSImageUtils.getShape(finalHeader);
21451
+ const typedData = ParsePayload.createTypedArray(rawPayload, bitpix);
21452
+ if (primary) {
21453
+ return new PrimaryHDU(finalHeader, rawPayload, dataOffset, dataByteLength, bitpix, shape, typedData);
21454
+ }
21455
+ return new ImageHDU(finalHeader, rawPayload, dataOffset, dataByteLength, bitpix, shape, typedData);
21456
+ }
21457
+ static getImagePayloadByteLength(header) {
21458
+ const bitpix = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BITPIX);
21459
+ if (bitpix === null) {
21460
+ throw new Error("BITPIX not defined.");
21461
+ }
21462
+ ParsePayload.assertSupportedBITPIX(bitpix);
21463
+ const shape = FITSImageUtils.getShape(header);
21464
+ if (shape.length === 0) {
21465
+ return 0;
21466
+ }
21467
+ const elementCount = shape.reduce((total, dimension) => total * dimension, 1);
21468
+ const bytesPerElement = Math.abs(bitpix) / 8;
21469
+ return elementCount * bytesPerElement;
21470
+ }
21471
+ static getBinaryTablePayloadByteLength(header) {
21472
+ const rowByteLength = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
21473
+ const rowCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
21474
+ const pcount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.PCOUNT) ?? 0;
21475
+ if (rowByteLength === null || rowCount === null) {
21476
+ throw new Error("BINTABLE requires NAXIS1 and NAXIS2.");
21477
+ }
21478
+ return rowByteLength * rowCount + pcount;
21479
+ }
21480
+ static getBinaryTableColumns(header) {
21481
+ const fieldCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.TFIELDS);
21482
+ if (fieldCount === null) {
21483
+ throw new Error("BINTABLE requires TFIELDS.");
21484
+ }
21485
+ const columns = [];
21486
+ let byteOffset = 0;
21487
+ for (let index = 1; index <= fieldCount; index++) {
21488
+ const tform = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TFORM", index));
21489
+ if (tform === null) {
21490
+ throw new Error(`Missing TFORM${index}.`);
21491
+ }
21492
+ const parsed = FITSBinaryTableUtils.parseTFORM(tform);
21493
+ const name = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TTYPE", index));
21494
+ const unit = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TUNIT", index));
21495
+ columns.push({
21496
+ index,
21497
+ name,
21498
+ format: tform,
21499
+ type: FITSParser.mapBinaryType(parsed.code),
21500
+ repeat: parsed.repeat,
21501
+ byteOffset,
21502
+ byteWidth: parsed.byteWidth,
21503
+ unit,
21504
+ scale: ParseHeader.getFITSItemValue(header, FITSHeaderManager.tableFieldKey("TSCAL", index)) ?? 1,
21505
+ zero: ParseHeader.getFITSItemValue(header, FITSHeaderManager.tableFieldKey("TZERO", index)) ?? 0,
21506
+ nullValue: ParseHeader.getFITSItemValue(header, FITSHeaderManager.tableFieldKey("TNULL", index)),
21507
+ });
21508
+ byteOffset += parsed.byteWidth;
21509
+ }
21510
+ return columns;
21511
+ }
21512
+ static mapBinaryType(code) {
21513
+ switch (code.toUpperCase()) {
21514
+ case "L":
21515
+ return "LOGICAL";
21516
+ case "X":
21517
+ return "BIT";
21518
+ case "B":
21519
+ return "UINT8";
21520
+ case "I":
21521
+ return "INT16";
21522
+ case "J":
21523
+ return "INT32";
21524
+ case "K":
21525
+ return "INT64";
21526
+ case "A":
21527
+ return "CHAR";
21528
+ case "E":
21529
+ return "FLOAT32";
21530
+ case "D":
21531
+ return "FLOAT64";
21532
+ case "C":
21533
+ return "COMPLEX64";
21534
+ case "M":
21535
+ return "COMPLEX128";
21536
+ default:
21537
+ return "UNKNOWN";
21538
+ }
21539
+ }
21540
+ static createBinaryTableHDU(header, rawPayload, dataOffset, dataByteLength) {
21541
+ const rowByteLength = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
21542
+ const rowCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
21543
+ if (rowByteLength === null || rowCount === null) {
21544
+ throw new Error("Invalid BINTABLE header.");
21545
+ }
21546
+ const columns = FITSParser.getBinaryTableColumns(header);
21547
+ const columnsByteWidth = columns.reduce((sum, column) => sum + column.byteWidth, 0);
21548
+ if (columnsByteWidth !== rowByteLength) {
21549
+ throw new Error(`BINTABLE columns occupy ${columnsByteWidth} bytes per row, ` +
21550
+ `but NAXIS1=${rowByteLength}.`);
21551
+ }
21552
+ return new BinaryTableHDU(header, rawPayload, dataOffset, dataByteLength, rowByteLength, rowCount, columns);
21553
+ }
21554
+ static getAsciiTablePayloadByteLength(header) {
21555
+ const rowByteLength = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
21556
+ const rowCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
21557
+ if (rowByteLength === null || rowCount === null) {
21558
+ throw new Error("ASCII TABLE requires NAXIS1 and NAXIS2.");
21559
+ }
21560
+ if (!Number.isInteger(rowByteLength) || rowByteLength < 0) {
21561
+ throw new Error(`Invalid ASCII TABLE NAXIS1=${rowByteLength}.`);
21562
+ }
21563
+ if (!Number.isInteger(rowCount) || rowCount < 0) {
21564
+ throw new Error(`Invalid ASCII TABLE NAXIS2=${rowCount}.`);
21565
+ }
21566
+ const pcount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.PCOUNT) ?? 0;
21567
+ if (pcount !== 0) {
21568
+ throw new Error(`ASCII TABLE requires PCOUNT=0, received ${pcount}.`);
21569
+ }
21570
+ return rowByteLength * rowCount;
21571
+ }
21572
+ static mapAsciiType(code) {
21573
+ switch (code.toUpperCase()) {
21574
+ case "A":
21575
+ return "CHAR";
21576
+ case "I":
21577
+ return "INTEGER";
21578
+ case "F":
21579
+ return "FLOAT";
21580
+ case "E":
21581
+ return "EXPONENTIAL";
21582
+ case "D":
21583
+ return "DOUBLE";
21584
+ default:
21585
+ return "UNKNOWN";
21586
+ }
21587
+ }
21588
+ static getAsciiTableColumns(header) {
21589
+ const fieldCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.TFIELDS);
21590
+ if (fieldCount === null) {
21591
+ throw new Error("ASCII TABLE requires TFIELDS.");
21592
+ }
21593
+ if (!Number.isInteger(fieldCount) || fieldCount < 0) {
21594
+ throw new Error(`Invalid ASCII TABLE TFIELDS=${fieldCount}.`);
21595
+ }
21596
+ const columns = [];
21597
+ for (let index = 1; index <= fieldCount; index++) {
21598
+ const tform = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TFORM", index));
21599
+ if (tform === null) {
21600
+ throw new Error(`Missing TFORM${index}.`);
21601
+ }
21602
+ const tbcol = ParseHeader.getFITSItemValue(header, FITSHeaderManager.tableFieldKey("TBCOL", index));
21603
+ if (tbcol === null) {
21604
+ throw new Error(`Missing TBCOL${index}.`);
21605
+ }
21606
+ if (!Number.isInteger(tbcol) || tbcol < 1) {
21607
+ throw new Error(`Invalid TBCOL${index}=${tbcol}.`);
21608
+ }
21609
+ const parsed = FITSAsciiTableUtils.parseTFORM(tform);
21610
+ const name = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TTYPE", index));
21611
+ const unit = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TUNIT", index));
21612
+ columns.push({
21613
+ index,
21614
+ name,
21615
+ format: tform,
21616
+ type: FITSParser.mapAsciiType(parsed.code),
21617
+ startColumn: tbcol,
21618
+ /*
21619
+ * FITS TBCOL is 1-based.
21620
+ * JavaScript offsets are 0-based.
21621
+ */
21622
+ byteOffset: tbcol - 1,
21623
+ width: parsed.width,
21624
+ decimals: parsed.decimals,
21625
+ unit,
21626
+ });
21627
+ }
21628
+ return columns;
21629
+ }
21630
+ static validateAsciiTableColumns(columns, rowByteLength) {
21631
+ for (const column of columns) {
21632
+ const endOffset = column.byteOffset + column.width;
21633
+ if (endOffset > rowByteLength) {
21634
+ throw new Error(`ASCII TABLE column ${column.index} ` +
21635
+ `extends to byte ${endOffset}, ` +
21636
+ `but NAXIS1=${rowByteLength}.`);
21637
+ }
21638
+ }
21639
+ }
21640
+ static createAsciiTableHDU(header, rawPayload, dataOffset, dataByteLength) {
21641
+ const rowByteLength = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
21642
+ const rowCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
21643
+ if (rowByteLength === null || rowCount === null) {
21644
+ throw new Error("Invalid ASCII TABLE header.");
21645
+ }
21646
+ const columns = FITSParser.getAsciiTableColumns(header);
21647
+ FITSParser.validateAsciiTableColumns(columns, rowByteLength);
21648
+ return new AsciiTableHDU(header, rawPayload, dataOffset, dataByteLength, rowByteLength, rowCount, columns);
21649
+ }
21650
+ static createMatrix(payload, header) {
21651
+ const NAXIS1 = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
21652
+ if (NAXIS1 === null) {
21653
+ throw new Error("NAXIS1 not defined.");
21654
+ }
21655
+ const NAXIS2 = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
21656
+ if (NAXIS2 === null) {
21657
+ throw new Error("NAXIS2 not defined.");
21658
+ }
21659
+ const BITPIX = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BITPIX);
21660
+ if (BITPIX === null) {
21661
+ throw new Error("BITPIX not defined.");
21662
+ }
21663
+ const bytesXelem = Math.abs(BITPIX / 8);
21664
+ // if (payload.length !== NAXIS1 * NAXIS2 * bytesXelem) {
21665
+ // throw new Error("Payload size does not match the expected matrix dimensions.");
21666
+ // }
21667
+ // const matrix: Array<Uint8Array> = [];
21668
+ const matrix = [];
21669
+ for (let i = 0; i < NAXIS2; i++) {
21670
+ matrix.push(payload.slice(i * NAXIS1 * bytesXelem, (i + 1) * NAXIS1 * bytesXelem));
21671
+ }
21672
+ return matrix;
21673
+ }
21674
+ /**
21675
+ * @deprecated Legacy FITSParsed writer API.
21676
+ */
21677
+ static saveFITSLocally(fitsParsed, path) {
21678
+ return FITSWriter.writeFITSFile(fitsParsed, path);
21679
+ }
21680
+ static async getFile(uri) {
21681
+ if (!uri.substring(0, 5).toLowerCase().includes("http")) {
21682
+ const p = await __webpack_require__.e(/* import() */ 64).then(__webpack_require__.bind(__webpack_require__, 7064));
21683
+ const rawData = await p.getLocalFile(uri);
21684
+ if (rawData?.length) {
21685
+ const uint8 = new Uint8Array(rawData);
21686
+ return uint8;
21687
+ }
21688
+ return new Uint8Array(0);
21689
+ }
21690
+ else {
21691
+ const p = await __webpack_require__.e(/* import() */ 911).then(__webpack_require__.bind(__webpack_require__, 1911));
21692
+ const rawData = await p.getFile(uri);
21693
+ if (rawData?.byteLength) {
21694
+ const uint8 = new Uint8Array(rawData);
21695
+ return uint8;
21696
+ }
21697
+ return new Uint8Array(0);
21698
+ }
21699
+ }
21700
+ }
21701
+ // const url = "http://skies.esac.esa.int/Herschel/normalized/PACS_hips160//Norder8/Dir40000/Npix47180.fits"
21702
+ // FITSParser.loadFITS(url).then((fits) => {
21703
+ // if (fits == null) {
21704
+ // return null
21705
+ // }
21706
+ // const path = "./fitsTest1.fits"
21707
+ // console.log(fits.header)
21708
+ // FITSParser.saveFITSLocally(fits, path)
21709
+ // console.log("finished")
21710
+ // })
21711
+ // // const file = "/Users/fabriziogiordano/Desktop/PhD/code/new/FITSParser/tests/inputs/empty.fits"
21712
+ // const file = "/Users/fabriziogiordano/Desktop/PhD/code/new/FITSParser/tests/inputs/Npix43348.fits"
21713
+ // FITSParser.loadFITS(file).then((fits) => {
21714
+ // if (fits == null) {
21715
+ // return null
21716
+ // }
21717
+ // const path = "./fitsTest2.fits"
21718
+ // console.log(fits.header)
21719
+ // FITSParser.saveFITSLocally(fits, path)
21720
+ // console.log("finished")
21721
+ // })
21722
+ //# sourceMappingURL=FITSParser.js.map
21723
+ ;// ./node_modules/jsfitsio/lib-esm/index.js
21724
+
21725
+
21726
+
21727
+
21728
+
21729
+
21730
+
21731
+
21732
+
21733
+
21734
+
21735
+
21736
+ //# sourceMappingURL=index.js.map
21737
+
19268
21738
  /***/ }
19269
21739
 
19270
21740
  /******/ });
@@ -19293,6 +21763,9 @@ function findCircleThroughTwoPoints(points, q1, q2) {
19293
21763
  /******/ return module.exports;
19294
21764
  /******/ }
19295
21765
  /******/
21766
+ /******/ // expose the modules object (__webpack_modules__)
21767
+ /******/ __webpack_require__.m = __webpack_modules__;
21768
+ /******/
19296
21769
  /************************************************************************/
19297
21770
  /******/ /* webpack/runtime/define property getters */
19298
21771
  /******/ (() => {
@@ -19321,6 +21794,28 @@ function findCircleThroughTwoPoints(points, q1, q2) {
19321
21794
  /******/ };
19322
21795
  /******/ })();
19323
21796
  /******/
21797
+ /******/ /* webpack/runtime/ensure chunk */
21798
+ /******/ (() => {
21799
+ /******/ __webpack_require__.f = {};
21800
+ /******/ // This file contains only the entry chunk.
21801
+ /******/ // The chunk loading function for additional chunks
21802
+ /******/ __webpack_require__.e = (chunkId) => {
21803
+ /******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
21804
+ /******/ __webpack_require__.f[key](chunkId, promises);
21805
+ /******/ return promises;
21806
+ /******/ }, []));
21807
+ /******/ };
21808
+ /******/ })();
21809
+ /******/
21810
+ /******/ /* webpack/runtime/get javascript chunk filename */
21811
+ /******/ (() => {
21812
+ /******/ // This function allow to reference async chunks
21813
+ /******/ __webpack_require__.u = (chunkId) => {
21814
+ /******/ // return url for filenames based on template
21815
+ /******/ return "" + chunkId + ".astroviewer.cjs";
21816
+ /******/ };
21817
+ /******/ })();
21818
+ /******/
19324
21819
  /******/ /* webpack/runtime/hasOwnProperty shorthand */
19325
21820
  /******/ (() => {
19326
21821
  /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
@@ -19337,6 +21832,51 @@ function findCircleThroughTwoPoints(points, q1, q2) {
19337
21832
  /******/ };
19338
21833
  /******/ })();
19339
21834
  /******/
21835
+ /******/ /* webpack/runtime/require chunk loading */
21836
+ /******/ (() => {
21837
+ /******/ // no baseURI
21838
+ /******/
21839
+ /******/ // object to store loaded chunks
21840
+ /******/ // "1" means "loaded", otherwise not loaded yet
21841
+ /******/ const installedChunks = {
21842
+ /******/ 792: 1
21843
+ /******/ };
21844
+ /******/
21845
+ /******/ // no on chunks loaded
21846
+ /******/
21847
+ /******/ const installChunk = (chunk) => {
21848
+ /******/ const moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime;
21849
+ /******/ for(var moduleId in moreModules) {
21850
+ /******/ if(__webpack_require__.o(moreModules, moduleId)) {
21851
+ /******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
21852
+ /******/ }
21853
+ /******/ }
21854
+ /******/ if(runtime) runtime(__webpack_require__);
21855
+ /******/ for(var i = 0; i < chunkIds.length; i++)
21856
+ /******/ installedChunks[chunkIds[i]] = 1;
21857
+ /******/
21858
+ /******/ };
21859
+ /******/
21860
+ /******/ // require() chunk loading for javascript
21861
+ /******/ __webpack_require__.f.require = (chunkId, promises) => {
21862
+ /******/ // "1" is the signal for "already loaded"
21863
+ /******/ if(!installedChunks[chunkId]) {
21864
+ /******/ if(true) { // all chunks have JS
21865
+ /******/ const installedChunk = require("./" + __webpack_require__.u(chunkId));
21866
+ /******/ if (!installedChunks[chunkId]) {
21867
+ /******/ installChunk(installedChunk);
21868
+ /******/ }
21869
+ /******/ } else installedChunks[chunkId] = 1;
21870
+ /******/ }
21871
+ /******/ };
21872
+ /******/
21873
+ /******/ // no external install chunk
21874
+ /******/
21875
+ /******/ // no HMR
21876
+ /******/
21877
+ /******/ // no HMR manifest
21878
+ /******/ })();
21879
+ /******/
19340
21880
  /************************************************************************/
19341
21881
  /******/
19342
21882
  /******/ // startup