astro-viewer 3.6.0 → 3.7.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 +2704 -510
  14. package/dist/astroviewer.cjs.map +1 -1
  15. package/dist/astroviewer.js +2861 -512
  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 +1 -1
  20. package/lib-esm/AstroSphere.d.ts.map +1 -1
  21. package/lib-esm/AstroSphere.js +15 -25
  22. package/lib-esm/AstroSphere.js.map +1 -1
  23. package/lib-esm/AstroViewer.d.ts +25 -23
  24. package/lib-esm/AstroViewer.d.ts.map +1 -1
  25. package/lib-esm/AstroViewer.js +97 -67
  26. package/lib-esm/AstroViewer.js.map +1 -1
  27. package/lib-esm/model/hips/AllSky.d.ts +7 -3
  28. package/lib-esm/model/hips/AllSky.d.ts.map +1 -1
  29. package/lib-esm/model/hips/AllSky.js +93 -28
  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 +91 -52
  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 +9 -5
  40. package/lib-esm/model/hips/HiPS.d.ts.map +1 -1
  41. package/lib-esm/model/hips/HiPS.js +120 -72
  42. package/lib-esm/model/hips/HiPS.js.map +1 -1
  43. package/lib-esm/model/hips/HiPSCoverage.d.ts +15 -0
  44. package/lib-esm/model/hips/HiPSCoverage.d.ts.map +1 -0
  45. package/lib-esm/model/hips/HiPSCoverage.js +148 -0
  46. package/lib-esm/model/hips/HiPSCoverage.js.map +1 -0
  47. package/lib-esm/model/hips/Tile.d.ts +8 -4
  48. package/lib-esm/model/hips/Tile.d.ts.map +1 -1
  49. package/lib-esm/model/hips/Tile.js +111 -55
  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 +46 -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 +9 -2
  60. package/lib-esm/shader/HiPSShaderProgram.d.ts.map +1 -1
  61. package/lib-esm/shader/HiPSShaderProgram.js +91 -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 +193 -94
  66. package/lib-esm/shader/ShaderManager.js.map +1 -1
  67. package/package.json +3 -3
@@ -9,12 +9,12 @@
9
9
  root["astroviewer"] = factory();
10
10
  })(self, () => {
11
11
  return /******/ (() => { // webpackBootstrap
12
- /******/ "use strict";
13
12
  /******/ var __webpack_modules__ = ({
14
13
 
15
14
  /***/ 3890
16
15
  (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
17
16
 
17
+ "use strict";
18
18
 
19
19
  // EXPORTS
20
20
  __webpack_require__.d(__webpack_exports__, {
@@ -3578,6 +3578,7 @@ var vec4_forEach = function () {
3578
3578
  /***/ 4723
3579
3579
  (__unused_webpack_module, exports, __webpack_require__) {
3580
3580
 
3581
+ "use strict";
3581
3582
 
3582
3583
  /*
3583
3584
  * AstroViewer
@@ -3990,9 +3991,15 @@ class AstroSphere {
3990
3991
  document.body.style.cursor = "grab";
3991
3992
  const dragDirection = Global_js_1.default.insideSphere ? -1 : 1;
3992
3993
  const dragSpeed = Global_js_1.default.insideSphere ? 10.0 : 1;
3993
- const deltaX = (dragDirection * dragSpeed * (newX - (this.lastMouseX ?? newX)) * Math.PI) /
3994
+ const deltaX = (dragDirection *
3995
+ dragSpeed *
3996
+ (newX - (this.lastMouseX ?? newX)) *
3997
+ Math.PI) /
3994
3998
  canvas.width;
3995
- const deltaY = (dragDirection * dragSpeed * (newY - (this.lastMouseY ?? newY)) * Math.PI) /
3999
+ const deltaY = (dragDirection *
4000
+ dragSpeed *
4001
+ (newY - (this.lastMouseY ?? newY)) *
4002
+ Math.PI) /
3996
4003
  canvas.height;
3997
4004
  const filteredDelta = this.filterRotationDeltaByAstroLocks(deltaX, deltaY);
3998
4005
  this.inertiaX += 0.1 * filteredDelta.deltaX;
@@ -4127,24 +4134,16 @@ class AstroSphere {
4127
4134
  const pickerPoint = RayPickingUtils_js_1.default.getIntersectionPointWithSingleModel(maxX / 2, maxY / 2, this._healpixGrid, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
4128
4135
  return (0, Utils_js_1.cartesianToSpherical)(pickerPoint);
4129
4136
  }
4130
- collectViewportSphericalSamples(sampleCount = 5) {
4131
- const rect = this.canvas.getBoundingClientRect();
4132
- const width = rect.width;
4133
- const height = rect.height;
4134
- const samples = [];
4135
- for (let ix = 0; ix < sampleCount; ix++) {
4136
- const x = sampleCount === 1 ? width / 2 : (ix / (sampleCount - 1)) * width;
4137
- for (let iy = 0; iy < sampleCount; iy++) {
4138
- const y = sampleCount === 1 ? height / 2 : (iy / (sampleCount - 1)) * height;
4139
- const hit = RayPickingUtils_js_1.default.getIntersectionPointWithSingleModel(x, y, this._healpixGrid, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
4140
- if (hit && hit.length > 0) {
4141
- samples.push((0, Utils_js_1.cartesianToSpherical)(hit));
4142
- }
4143
- }
4137
+ changeHiPSFormat(format) {
4138
+ if (!this._activeHiPS) {
4139
+ throw new Error("No active HiPS.");
4144
4140
  }
4145
- return samples;
4141
+ this._activeHiPS.changeFormat(format);
4146
4142
  }
4147
4143
  activateHiPS(hipsDescriptor) {
4144
+ if (this._activeHiPS) {
4145
+ this._healpixGrid.visibleTilesManager.tileBuffer.removeHiPS(this._activeHiPS);
4146
+ }
4148
4147
  this._activeHiPS = new HiPS_js_1.HiPS(1, [0.0, 0.0, 0.0], 0, 0, hipsDescriptor, this._webgl, this._healpixGrid);
4149
4148
  this._activeBaseLayer = "hips";
4150
4149
  }
@@ -4554,14 +4553,6 @@ class AstroSphere {
4554
4553
  Math.abs(this.inertiaX) > 0.02 ||
4555
4554
  Math.abs(this.inertiaY) > 0.02 ||
4556
4555
  nowForGrid - this.lastCameraMotionAt < 220;
4557
- // const skyEntityDrawInput: SkyEntityDrawInput = {
4558
- // fovDeg: this._healpixGrid.getMinFoV(),
4559
- // camera: this._camera,
4560
- // pMatrix: this._perspectiveMatrixManager.pMatrix,
4561
- // centerSphericalDeg: this.updateCentralPoint().sphericalDeg,
4562
- // fovPolygon: this._activeBaseLayer === 'xyz' ? this.getFoVPolygon() : undefined,
4563
- // viewportSphericalSamples: this._activeBaseLayer === 'xyz' ? this.collectViewportSphericalSamples(7) : undefined,
4564
- // }
4565
4556
  const skyEntityDrawInput = {
4566
4557
  fovDeg: stableFovDeg,
4567
4558
  camera: this._camera,
@@ -4674,6 +4665,7 @@ exports["default"] = AstroSphere;
4674
4665
  /***/ 772
4675
4666
  (__unused_webpack_module, exports, __webpack_require__) {
4676
4667
 
4668
+ "use strict";
4677
4669
 
4678
4670
  /*
4679
4671
  * AstroViewer
@@ -4713,7 +4705,7 @@ class AstroViewer {
4713
4705
  webglContextList = new Map();
4714
4706
  viewfinderEl = null;
4715
4707
  viewfinderVisible = Config_js_1.bootSetup.showViewfinder;
4716
- viewfinderColor = 'rgba(75,148,226,0.68)';
4708
+ viewfinderColor = "rgba(75,148,226,0.68)";
4717
4709
  options = {};
4718
4710
  // API
4719
4711
  run() {
@@ -4851,7 +4843,7 @@ class AstroViewer {
4851
4843
  this.astroSphere.activateXYZ(config);
4852
4844
  }
4853
4845
  activateXYZ2(config) {
4854
- 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);
4846
+ 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);
4855
4847
  this.astroSphere.activateXYZ2(descriptor);
4856
4848
  }
4857
4849
  activateWMTS(config) {
@@ -4876,8 +4868,8 @@ class AstroViewer {
4876
4868
  return this.astroSphere.getMeshHiPSDebugStats();
4877
4869
  }
4878
4870
  async loadHiPS(baseUrl) {
4879
- const hipsUrl = baseUrl.endsWith('/') ? baseUrl : baseUrl + '/';
4880
- const resp = await fetch(hipsUrl + 'properties');
4871
+ const hipsUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
4872
+ const resp = await fetch(hipsUrl + "properties");
4881
4873
  if (!resp.ok)
4882
4874
  throw new Error(`HTTP ${resp.status} fetching properties`);
4883
4875
  const propsText = await resp.text();
@@ -4887,20 +4879,20 @@ class AstroViewer {
4887
4879
  // this.activateHiPS(desc);
4888
4880
  }
4889
4881
  async loadMeshHiPS(baseUrl, config = {}) {
4890
- const meshHiPSUrl = baseUrl.endsWith('/') ? baseUrl : baseUrl + '/';
4891
- let propsText = '';
4892
- const resp = await fetch(meshHiPSUrl + 'properties');
4882
+ const meshHiPSUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
4883
+ let propsText = "";
4884
+ const resp = await fetch(meshHiPSUrl + "properties");
4893
4885
  if (resp.ok) {
4894
4886
  propsText = await resp.text();
4895
4887
  }
4896
4888
  else {
4897
- const jsonResp = await fetch(meshHiPSUrl + 'properties.json');
4889
+ const jsonResp = await fetch(meshHiPSUrl + "properties.json");
4898
4890
  if (!jsonResp.ok)
4899
4891
  throw new Error(`HTTP ${jsonResp.status} fetching MeshHiPS properties`);
4900
4892
  const json = await jsonResp.json();
4901
4893
  propsText = Object.entries(json)
4902
4894
  .map(([key, value]) => `${key}=${String(value)}`)
4903
- .join('\n');
4895
+ .join("\n");
4904
4896
  }
4905
4897
  const desc = new MeshHiPSDescriptor_js_1.MeshHiPSDescriptor({ ...config, baseUrl: meshHiPSUrl }, propsText);
4906
4898
  this.astroSphere.activateMeshHiPS(desc);
@@ -4918,6 +4910,12 @@ class AstroViewer {
4918
4910
  getActiveHiPS() {
4919
4911
  return this.astroSphere.activeHiPS;
4920
4912
  }
4913
+ changeHiPSFormat(format) {
4914
+ this.astroSphere.changeHiPSFormat(format);
4915
+ }
4916
+ getActiveHiPSFormats() {
4917
+ return this.astroSphere.activeHiPS?.availableFormats ?? [];
4918
+ }
4921
4919
  getActiveXYZ() {
4922
4920
  return this.astroSphere.activeXYZ;
4923
4921
  }
@@ -5005,13 +5003,13 @@ class AstroViewer {
5005
5003
  return this.astroSphere.getFoVPolygon();
5006
5004
  }
5007
5005
  changeFoV(deg) {
5008
- this, this.astroSphere.changeFoV(deg);
5006
+ (this, this.astroSphere.changeFoV(deg));
5009
5007
  }
5010
5008
  changeFoV2(deg) {
5011
- this, this.astroSphere.changeFoV2(deg);
5009
+ (this, this.astroSphere.changeFoV2(deg));
5012
5010
  }
5013
5011
  changeFoV3(deg) {
5014
- this, this.astroSphere.changeFoV3(deg);
5012
+ (this, this.astroSphere.changeFoV3(deg));
5015
5013
  }
5016
5014
  getInsideSphere() {
5017
5015
  return this.astroSphere.getInsideSphere();
@@ -5057,13 +5055,13 @@ class AstroViewer {
5057
5055
  this.webglContextList = new Map();
5058
5056
  }
5059
5057
  init(canvasEl) {
5060
- console.log('init webgl');
5058
+ console.log("init webgl");
5061
5059
  this.canvas = canvasEl;
5062
5060
  this.initViewfinder();
5063
- const gl = this.canvas.getContext('webgl2', { alpha: false });
5061
+ const gl = this.canvas.getContext("webgl2", { alpha: false });
5064
5062
  if (!gl) {
5065
- alert('Could not initialise WebGL, sorry :-(');
5066
- throw new Error('WebGL2 not available');
5063
+ alert("Could not initialise WebGL, sorry :-(");
5064
+ throw new Error("WebGL2 not available");
5067
5065
  }
5068
5066
  // Extend with custom fields used elsewhere
5069
5067
  this.webgl = gl;
@@ -5074,7 +5072,7 @@ class AstroViewer {
5074
5072
  this.webgl.clearColor(0 * 0.00392156862, 16 * 0.00392156862, 50 * 0.00392156862, 0.7);
5075
5073
  }
5076
5074
  catch (e) {
5077
- console.log('Error instantiating WebGL context');
5075
+ console.log("Error instantiating WebGL context");
5078
5076
  }
5079
5077
  this.initListeners();
5080
5078
  // ; (global as any).gl = this.webgl
@@ -5086,40 +5084,64 @@ class AstroViewer {
5086
5084
  const parent = this.canvas.parentElement;
5087
5085
  if (!parent)
5088
5086
  return;
5089
- if (window.getComputedStyle(parent).position === 'static') {
5090
- parent.style.position = 'relative';
5091
- }
5092
- const viewfinder = document.createElement('div');
5093
- viewfinder.setAttribute('data-astro-viewfinder', 'true');
5094
- viewfinder.setAttribute('aria-hidden', 'true');
5095
- viewfinder.style.position = 'absolute';
5096
- viewfinder.style.left = '50%';
5097
- viewfinder.style.top = '50%';
5098
- viewfinder.style.width = '44px';
5099
- viewfinder.style.height = '44px';
5100
- viewfinder.style.transform = 'translate(-50%, -50%)';
5101
- viewfinder.style.pointerEvents = 'none';
5102
- viewfinder.style.zIndex = '1';
5103
- viewfinder.style.boxSizing = 'border-box';
5087
+ if (window.getComputedStyle(parent).position === "static") {
5088
+ parent.style.position = "relative";
5089
+ }
5090
+ const viewfinder = document.createElement("div");
5091
+ viewfinder.setAttribute("data-astro-viewfinder", "true");
5092
+ viewfinder.setAttribute("aria-hidden", "true");
5093
+ viewfinder.style.position = "absolute";
5094
+ viewfinder.style.left = "50%";
5095
+ viewfinder.style.top = "50%";
5096
+ viewfinder.style.width = "44px";
5097
+ viewfinder.style.height = "44px";
5098
+ viewfinder.style.transform = "translate(-50%, -50%)";
5099
+ viewfinder.style.pointerEvents = "none";
5100
+ viewfinder.style.zIndex = "1";
5101
+ viewfinder.style.boxSizing = "border-box";
5104
5102
  const segments = [
5105
- { left: '50%', top: '7px', width: '1px', height: '11px', transform: 'translateX(-50%)' },
5106
- { left: '50%', bottom: '7px', width: '1px', height: '11px', transform: 'translateX(-50%)' },
5107
- { left: '7px', top: '50%', width: '11px', height: '1px', transform: 'translateY(-50%)' },
5108
- { right: '7px', top: '50%', width: '11px', height: '1px', transform: 'translateY(-50%)' },
5103
+ {
5104
+ left: "50%",
5105
+ top: "7px",
5106
+ width: "1px",
5107
+ height: "11px",
5108
+ transform: "translateX(-50%)",
5109
+ },
5110
+ {
5111
+ left: "50%",
5112
+ bottom: "7px",
5113
+ width: "1px",
5114
+ height: "11px",
5115
+ transform: "translateX(-50%)",
5116
+ },
5117
+ {
5118
+ left: "7px",
5119
+ top: "50%",
5120
+ width: "11px",
5121
+ height: "1px",
5122
+ transform: "translateY(-50%)",
5123
+ },
5124
+ {
5125
+ right: "7px",
5126
+ top: "50%",
5127
+ width: "11px",
5128
+ height: "1px",
5129
+ transform: "translateY(-50%)",
5130
+ },
5109
5131
  ];
5110
5132
  for (const segmentDef of segments) {
5111
- const segment = document.createElement('div');
5112
- segment.style.position = 'absolute';
5113
- segment.style.left = segmentDef.left ?? 'auto';
5114
- segment.style.right = segmentDef.right ?? 'auto';
5115
- segment.style.top = segmentDef.top ?? 'auto';
5116
- segment.style.bottom = segmentDef.bottom ?? 'auto';
5133
+ const segment = document.createElement("div");
5134
+ segment.style.position = "absolute";
5135
+ segment.style.left = segmentDef.left ?? "auto";
5136
+ segment.style.right = segmentDef.right ?? "auto";
5137
+ segment.style.top = segmentDef.top ?? "auto";
5138
+ segment.style.bottom = segmentDef.bottom ?? "auto";
5117
5139
  segment.style.width = segmentDef.width;
5118
5140
  segment.style.height = segmentDef.height;
5119
5141
  segment.style.transform = segmentDef.transform;
5120
- segment.style.background = 'currentColor';
5121
- segment.style.borderRadius = '999px';
5122
- segment.style.boxShadow = '0 0 0 1px rgba(0, 0, 0, 0.14)';
5142
+ segment.style.background = "currentColor";
5143
+ segment.style.borderRadius = "999px";
5144
+ segment.style.boxShadow = "0 0 0 1px rgba(0, 0, 0, 0.14)";
5123
5145
  viewfinder.appendChild(segment);
5124
5146
  }
5125
5147
  parent.appendChild(viewfinder);
@@ -5130,7 +5152,7 @@ class AstroViewer {
5130
5152
  syncViewfinderVisibility() {
5131
5153
  if (!this.viewfinderEl)
5132
5154
  return;
5133
- this.viewfinderEl.style.display = this.viewfinderVisible ? 'block' : 'none';
5155
+ this.viewfinderEl.style.display = this.viewfinderVisible ? "block" : "none";
5134
5156
  }
5135
5157
  syncViewfinderColor() {
5136
5158
  if (!this.viewfinderEl)
@@ -5138,9 +5160,9 @@ class AstroViewer {
5138
5160
  this.viewfinderEl.style.color = this.viewfinderColor;
5139
5161
  }
5140
5162
  initListeners() {
5141
- console.log('inside initListeners');
5163
+ console.log("inside initListeners");
5142
5164
  const resizeCanvas = () => {
5143
- console.log('[resizeCanvas]');
5165
+ console.log("[resizeCanvas]");
5144
5166
  const rect = this.canvas.getBoundingClientRect();
5145
5167
  const dpr = window.devicePixelRatio || 1;
5146
5168
  const newWidth = Math.max(1, Math.floor(rect.width * dpr));
@@ -5154,7 +5176,7 @@ class AstroViewer {
5154
5176
  }
5155
5177
  };
5156
5178
  const handleContextLost = (event) => {
5157
- console.log('[handleContextLost]');
5179
+ console.log("[handleContextLost]");
5158
5180
  event.preventDefault();
5159
5181
  if (this.rafId !== null) {
5160
5182
  cancelAnimationFrame(this.rafId);
@@ -5162,7 +5184,7 @@ class AstroViewer {
5162
5184
  }
5163
5185
  };
5164
5186
  const handleContextRestored = (_event) => {
5165
- console.log('[handleContextRestored]');
5187
+ console.log("[handleContextRestored]");
5166
5188
  // this.webgl.viewportWidth = this.canvas.width
5167
5189
  // this.webgl.viewportHeight = this.canvas.height
5168
5190
  this.webgl.clearColor(0 * 0.00392156862, 16 * 0.00392156862, 50 * 0.00392156862, 0.7);
@@ -5170,16 +5192,16 @@ class AstroViewer {
5170
5192
  this.rafId = requestAnimationFrame(() => this.tick());
5171
5193
  };
5172
5194
  // 🔥 ResizeObserver per pannelli / split / layout dinamici
5173
- if ('ResizeObserver' in window) {
5195
+ if ("ResizeObserver" in window) {
5174
5196
  const ro = new ResizeObserver(() => {
5175
5197
  resizeCanvas();
5176
5198
  });
5177
5199
  // Osserva il canvas o il suo parent (a tua scelta)
5178
5200
  ro.observe(this.canvas);
5179
5201
  }
5180
- window.addEventListener('resize', resizeCanvas);
5181
- this.canvas.addEventListener('webglcontextlost', handleContextLost, false);
5182
- this.canvas.addEventListener('webglcontextrestored', handleContextRestored, false);
5202
+ window.addEventListener("resize", resizeCanvas);
5203
+ this.canvas.addEventListener("webglcontextlost", handleContextLost, false);
5204
+ this.canvas.addEventListener("webglcontextrestored", handleContextRestored, false);
5183
5205
  resizeCanvas();
5184
5206
  }
5185
5207
  tick() {
@@ -5199,6 +5221,7 @@ exports.AstroViewer = AstroViewer;
5199
5221
  /***/ 7734
5200
5222
  (__unused_webpack_module, exports, __webpack_require__) {
5201
5223
 
5224
+ "use strict";
5202
5225
 
5203
5226
  /*
5204
5227
  * AstroViewer
@@ -5554,6 +5577,7 @@ exports["default"] = Camera;
5554
5577
  /***/ 2919
5555
5578
  (__unused_webpack_module, exports) {
5556
5579
 
5580
+ "use strict";
5557
5581
  var __webpack_unused_export__;
5558
5582
 
5559
5583
  /*
@@ -5608,6 +5632,7 @@ exports.bootSetup = {
5608
5632
  /***/ 4382
5609
5633
  (__unused_webpack_module, exports, __webpack_require__) {
5610
5634
 
5635
+ "use strict";
5611
5636
  /*
5612
5637
  * AstroViewer
5613
5638
  * Copyright (C) Fabrizio Giordano
@@ -5677,6 +5702,7 @@ exports["default"] = global;
5677
5702
  /***/ 1229
5678
5703
  (__unused_webpack_module, exports, __webpack_require__) {
5679
5704
 
5705
+ "use strict";
5680
5706
 
5681
5707
  /*
5682
5708
  * AstroViewer
@@ -5765,6 +5791,7 @@ console.log('astroviewer UMD loaded');
5765
5791
  /***/ 4735
5766
5792
  (__unused_webpack_module, exports, __webpack_require__) {
5767
5793
 
5794
+ "use strict";
5768
5795
  var __webpack_unused_export__;
5769
5796
 
5770
5797
  /*
@@ -5931,6 +5958,7 @@ exports.AbstractSkyEntity = AbstractSkyEntity;
5931
5958
  /***/ 619
5932
5959
  (__unused_webpack_module, exports) {
5933
5960
 
5961
+ "use strict";
5934
5962
 
5935
5963
  /*
5936
5964
  * AstroViewer
@@ -7239,6 +7267,7 @@ exports["default"] = exports.ColorMaps;
7239
7267
  /***/ 1072
7240
7268
  (__unused_webpack_module, exports) {
7241
7269
 
7270
+ "use strict";
7242
7271
  /*
7243
7272
  * AstroViewer
7244
7273
  * Copyright (C) Fabrizio Giordano
@@ -7353,6 +7382,7 @@ exports.MetadataColumn = MetadataColumn;
7353
7382
  /***/ 5403
7354
7383
  (__unused_webpack_module, exports, __webpack_require__) {
7355
7384
 
7385
+ "use strict";
7356
7386
 
7357
7387
  /*
7358
7388
  * AstroViewer
@@ -7493,6 +7523,7 @@ exports.MetadataManager = MetadataManager;
7493
7523
  /***/ 6553
7494
7524
  (__unused_webpack_module, exports, __webpack_require__) {
7495
7525
 
7526
+ "use strict";
7496
7527
  /*
7497
7528
  * AstroViewer
7498
7529
  * Copyright (C) Fabrizio Giordano
@@ -7666,6 +7697,7 @@ exports.Point = Point;
7666
7697
  /***/ 7559
7667
7698
  (__unused_webpack_module, exports) {
7668
7699
 
7700
+ "use strict";
7669
7701
 
7670
7702
  /*
7671
7703
  * AstroViewer
@@ -7700,6 +7732,7 @@ exports["default"] = Point2D;
7700
7732
  /***/ 146
7701
7733
  (__unused_webpack_module, exports, __webpack_require__) {
7702
7734
 
7735
+ "use strict";
7703
7736
  /*
7704
7737
  * AstroViewer
7705
7738
  * Copyright (C) Fabrizio Giordano
@@ -7785,6 +7818,7 @@ exports.Source = Source;
7785
7818
  /***/ 5803
7786
7819
  (__unused_webpack_module, exports, __webpack_require__) {
7787
7820
 
7821
+ "use strict";
7788
7822
 
7789
7823
  /*
7790
7824
  * AstroViewer
@@ -7990,6 +8024,7 @@ exports.SphereFoV = SphereFoV;
7990
8024
  /***/ 1232
7991
8025
  (__unused_webpack_module, exports, __webpack_require__) {
7992
8026
 
8027
+ "use strict";
7993
8028
 
7994
8029
  /*
7995
8030
  * AstroViewer
@@ -8624,6 +8659,7 @@ exports.CatalogueGL = CatalogueGL;
8624
8659
  /***/ 3956
8625
8660
  (__unused_webpack_module, exports) {
8626
8661
 
8662
+ "use strict";
8627
8663
 
8628
8664
  /*
8629
8665
  * AstroViewer
@@ -8730,6 +8766,7 @@ exports.WMTSAdapter = WMTSAdapter;
8730
8766
  /***/ 3174
8731
8767
  (__unused_webpack_module, exports, __webpack_require__) {
8732
8768
 
8769
+ "use strict";
8733
8770
  var __webpack_unused_export__;
8734
8771
 
8735
8772
  /*
@@ -8827,6 +8864,7 @@ __webpack_unused_export__ = XYZAnchestorTile;
8827
8864
  /***/ 8284
8828
8865
  (__unused_webpack_module, exports) {
8829
8866
 
8867
+ "use strict";
8830
8868
  var __webpack_unused_export__;
8831
8869
  /*
8832
8870
  * AstroViewer
@@ -8973,6 +9011,7 @@ __webpack_unused_export__ = XYZFoVHelper;
8973
9011
  /***/ 1741
8974
9012
  (__unused_webpack_module, exports, __webpack_require__) {
8975
9013
 
9014
+ "use strict";
8976
9015
 
8977
9016
  /*
8978
9017
  * AstroViewer
@@ -9190,6 +9229,7 @@ exports.XYZMap = XYZMap;
9190
9229
  /***/ 8868
9191
9230
  (__unused_webpack_module, exports) {
9192
9231
 
9232
+ "use strict";
9193
9233
  var __webpack_unused_export__;
9194
9234
 
9195
9235
  /*
@@ -9277,6 +9317,7 @@ exports.XYZMapDescriptor = XYZMapDescriptor;
9277
9317
  /***/ 8819
9278
9318
  (__unused_webpack_module, exports, __webpack_require__) {
9279
9319
 
9320
+ "use strict";
9280
9321
  var __webpack_unused_export__;
9281
9322
 
9282
9323
  /*
@@ -9395,6 +9436,7 @@ exports.XYZMeshBuilder = XYZMeshBuilder;
9395
9436
  /***/ 1375
9396
9437
  (__unused_webpack_module, exports, __webpack_require__) {
9397
9438
 
9439
+ "use strict";
9398
9440
  var __webpack_unused_export__;
9399
9441
 
9400
9442
  /*
@@ -9572,6 +9614,7 @@ exports.XYZTile = XYZTile;
9572
9614
  /***/ 2737
9573
9615
  (__unused_webpack_module, exports) {
9574
9616
 
9617
+ "use strict";
9575
9618
  var __webpack_unused_export__;
9576
9619
 
9577
9620
  /*
@@ -9721,6 +9764,7 @@ exports.XYZTileBuffer = XYZTileBuffer;
9721
9764
  /***/ 5409
9722
9765
  (__unused_webpack_module, exports) {
9723
9766
 
9767
+ "use strict";
9724
9768
  var __webpack_unused_export__;
9725
9769
 
9726
9770
  /*
@@ -9904,6 +9948,7 @@ exports.xyzTileRequestScheduler = new XYZTileRequestScheduler();
9904
9948
  /***/ 6937
9905
9949
  (__unused_webpack_module, exports, __webpack_require__) {
9906
9950
 
9951
+ "use strict";
9907
9952
 
9908
9953
  /*
9909
9954
  * AstroViewer
@@ -9993,6 +10038,7 @@ exports.XYZVisibleTilesManager = XYZVisibleTilesManager;
9993
10038
  /***/ 2475
9994
10039
  (__unused_webpack_module, exports, __webpack_require__) {
9995
10040
 
10041
+ "use strict";
9996
10042
  /*
9997
10043
  * AstroViewer
9998
10044
  * Copyright (C) Fabrizio Giordano
@@ -10132,6 +10178,7 @@ exports.Footprint = Footprint;
10132
10178
  /***/ 592
10133
10179
  (__unused_webpack_module, exports, __webpack_require__) {
10134
10180
 
10181
+ "use strict";
10135
10182
 
10136
10183
  /*
10137
10184
  * AstroViewer
@@ -10750,6 +10797,7 @@ exports.FootprintSetGL = FootprintSetGL;
10750
10797
  /***/ 9839
10751
10798
  (__unused_webpack_module, exports, __webpack_require__) {
10752
10799
 
10800
+ "use strict";
10753
10801
 
10754
10802
  /*
10755
10803
  * AstroViewer
@@ -11082,6 +11130,7 @@ exports.EquatorialGrid = EquatorialGrid;
11082
11130
  /***/ 5361
11083
11131
  (__unused_webpack_module, exports) {
11084
11132
 
11133
+ "use strict";
11085
11134
 
11086
11135
  /*
11087
11136
  * AstroViewer
@@ -11226,6 +11275,7 @@ exports["default"] = GridTextHelper;
11226
11275
  /***/ 4595
11227
11276
  (__unused_webpack_module, exports, __webpack_require__) {
11228
11277
 
11278
+ "use strict";
11229
11279
  /*
11230
11280
  * AstroViewer
11231
11281
  * Copyright (C) Fabrizio Giordano
@@ -11559,6 +11609,7 @@ exports.HealpixGrid = HealpixGrid;
11559
11609
  /***/ 8124
11560
11610
  (__unused_webpack_module, exports, __webpack_require__) {
11561
11611
 
11612
+ "use strict";
11562
11613
 
11563
11614
  /*
11564
11615
  * AstroViewer
@@ -11881,6 +11932,7 @@ exports.LatLonGrid = LatLonGrid;
11881
11932
  /***/ 2368
11882
11933
  (__unused_webpack_module, exports, __webpack_require__) {
11883
11934
 
11935
+ "use strict";
11884
11936
  /*
11885
11937
  * AstroViewer
11886
11938
  * Copyright (C) Fabrizio Giordano
@@ -11897,6 +11949,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
11897
11949
  };
11898
11950
  Object.defineProperty(exports, "__esModule", ({ value: true }));
11899
11951
  const Global_js_1 = __importDefault(__webpack_require__(4382));
11952
+ const FitsTileLoader_js_1 = __webpack_require__(1399);
11900
11953
  class AllSky {
11901
11954
  _ready = false;
11902
11955
  _hips;
@@ -11909,6 +11962,7 @@ class AllSky {
11909
11962
  _texture = null;
11910
11963
  _image;
11911
11964
  _texurl;
11965
+ _fitsTile;
11912
11966
  _textureLoaded = false;
11913
11967
  _maxTiles = 0;
11914
11968
  _numFacesXTile = 0;
@@ -11931,15 +11985,34 @@ class AllSky {
11931
11985
  this.initImage();
11932
11986
  }
11933
11987
  initImage() {
11934
- this._image = new Image();
11935
11988
  this._texurl = `${this._baseurl}/Norder3/Allsky.${this._format}`;
11989
+ if (this._format === "fits") {
11990
+ void this.loadFits();
11991
+ return;
11992
+ }
11993
+ this.loadImage();
11994
+ }
11995
+ loadImage() {
11996
+ this._image = new Image();
11936
11997
  this._image.onload = () => this.imageLoaded();
11937
11998
  this._image.onerror = () => {
11938
- console.error('File not found? %s', this._texurl);
11999
+ console.error("File not found? %s", this._texurl);
11939
12000
  };
11940
- this._image.setAttribute('crossorigin', 'anonymous');
12001
+ this._image.setAttribute("crossorigin", "anonymous");
11941
12002
  this._image.src = this._texurl;
11942
12003
  }
12004
+ async loadFits() {
12005
+ try {
12006
+ this._fitsTile = await (0, FitsTileLoader_js_1.loadFitsTile)(this._texurl);
12007
+ this.textureLoaded();
12008
+ this.initModelBuffer();
12009
+ this._textureLoaded = true;
12010
+ this._ready = true;
12011
+ }
12012
+ catch (error) {
12013
+ console.error(`[AllSky] Unable to load FITS atlas ${this._texurl}`, error);
12014
+ }
12015
+ }
11943
12016
  imageLoaded() {
11944
12017
  this.textureLoaded();
11945
12018
  this.initModelBuffer();
@@ -11947,31 +12020,58 @@ class AllSky {
11947
12020
  this._ready = true;
11948
12021
  }
11949
12022
  textureLoaded() {
11950
- // hipsShaderProgram.enableProgram()
11951
12023
  this._hipsShaderProgram.enableProgram();
11952
12024
  const gl = this._webgl;
11953
12025
  this._texture = gl.createTexture();
11954
12026
  gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
11955
- gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
12027
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._format !== "fits");
11956
12028
  gl.bindTexture(gl.TEXTURE_2D, this._texture);
11957
- // gl.uniform1i(hipsShaderProgram.shaderProgram.samplerUniform, this._hipsShaderIndex)
11958
- if (!gl.isTexture(this._texture)) {
11959
- console.log('error in texture');
12029
+ if (this._format === "fits") {
12030
+ const fits = this._fitsTile;
12031
+ if (!fits) {
12032
+ throw new Error(`FITS AllSky data not loaded: ${this._texurl}`);
12033
+ }
12034
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, fits.width, fits.height, 0, gl.RED, gl.FLOAT, fits.pixels);
12035
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
12036
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
12037
+ }
12038
+ else {
12039
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
12040
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
12041
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
12042
+ gl.generateMipmap(gl.TEXTURE_2D);
11960
12043
  }
11961
- gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
11962
- gl.bindTexture(gl.TEXTURE_2D, this._texture);
11963
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
11964
12044
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
11965
12045
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
11966
- const useMipmaps = true;
11967
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useMipmaps ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR);
11968
- // MAG filter: ONLY NEAREST or LINEAR are valid
11969
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
11970
- // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)
11971
- // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR_MIPMAP_LINEAR)
11972
- // gl.generateMipmap(gl.TEXTURE_2D)
11973
- if (useMipmaps)
11974
- gl.generateMipmap(gl.TEXTURE_2D);
12046
+ if (!gl.isTexture(this._texture)) {
12047
+ console.log("error in texture");
12048
+ }
12049
+ }
12050
+ getFitsDataRange() {
12051
+ const hipsRange = this._hips.dataRange;
12052
+ if (hipsRange.min !== undefined &&
12053
+ hipsRange.max !== undefined &&
12054
+ Number.isFinite(hipsRange.min) &&
12055
+ Number.isFinite(hipsRange.max) &&
12056
+ hipsRange.max > hipsRange.min) {
12057
+ return {
12058
+ min: hipsRange.min,
12059
+ max: hipsRange.max,
12060
+ };
12061
+ }
12062
+ const fits = this._fitsTile;
12063
+ if (fits &&
12064
+ fits.dataMin !== null &&
12065
+ fits.dataMax !== null &&
12066
+ Number.isFinite(fits.dataMin) &&
12067
+ Number.isFinite(fits.dataMax) &&
12068
+ fits.dataMax > fits.dataMin) {
12069
+ return {
12070
+ min: fits.dataMin,
12071
+ max: fits.dataMax,
12072
+ };
12073
+ }
12074
+ return null;
11975
12075
  }
11976
12076
  initModelBuffer() {
11977
12077
  const gl = this._webgl;
@@ -12036,13 +12136,16 @@ class AllSky {
12036
12136
  this.vertexPosition[20 * this.vidx] = facesVec3Array[0].x;
12037
12137
  this.vertexPosition[20 * this.vidx + 1] = facesVec3Array[0].y;
12038
12138
  this.vertexPosition[20 * this.vidx + 2] = facesVec3Array[0].z;
12039
- this.vertexPosition[20 * this.vidx + 3] = s_step + base_s - s_pixel_size;
12040
- this.vertexPosition[20 * this.vidx + 4] = 1 - (t_step + base_t) + t_pixel_size;
12139
+ this.vertexPosition[20 * this.vidx + 3] =
12140
+ s_step + base_s - s_pixel_size;
12141
+ this.vertexPosition[20 * this.vidx + 4] =
12142
+ 1 - (t_step + base_t) + t_pixel_size;
12041
12143
  // top right
12042
12144
  this.vertexPosition[20 * this.vidx + 5] = facesVec3Array[1].x;
12043
12145
  this.vertexPosition[20 * this.vidx + 6] = facesVec3Array[1].y;
12044
12146
  this.vertexPosition[20 * this.vidx + 7] = facesVec3Array[1].z;
12045
- this.vertexPosition[20 * this.vidx + 8] = s_step + base_s - s_pixel_size;
12147
+ this.vertexPosition[20 * this.vidx + 8] =
12148
+ s_step + base_s - s_pixel_size;
12046
12149
  this.vertexPosition[20 * this.vidx + 9] = 1 - base_t - t_pixel_size;
12047
12150
  // top left
12048
12151
  this.vertexPosition[20 * this.vidx + 10] = facesVec3Array[2].x;
@@ -12055,7 +12158,8 @@ class AllSky {
12055
12158
  this.vertexPosition[20 * this.vidx + 16] = facesVec3Array[3].y;
12056
12159
  this.vertexPosition[20 * this.vidx + 17] = facesVec3Array[3].z;
12057
12160
  this.vertexPosition[20 * this.vidx + 18] = base_s + s_pixel_size;
12058
- this.vertexPosition[20 * this.vidx + 19] = 1 - (t_step + base_t) + t_pixel_size;
12161
+ this.vertexPosition[20 * this.vidx + 19] =
12162
+ 1 - (t_step + base_t) + t_pixel_size;
12059
12163
  this.vidx++;
12060
12164
  }
12061
12165
  }
@@ -12075,6 +12179,17 @@ class AllSky {
12075
12179
  }
12076
12180
  const gl = this._webgl;
12077
12181
  this._hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx);
12182
+ if (this._format === "fits") {
12183
+ const range = this.getFitsDataRange();
12184
+ if (!range) {
12185
+ console.error(`[AllSky] No display range available for FITS atlas ${this._texurl}`);
12186
+ return false;
12187
+ }
12188
+ this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max);
12189
+ }
12190
+ else {
12191
+ this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, false);
12192
+ }
12078
12193
  gl.enableVertexAttribArray(this._hipsShaderProgram.locations.vertexPositionAttribute);
12079
12194
  gl.enableVertexAttribArray(this._hipsShaderProgram.locations.textureCoordAttribute);
12080
12195
  // hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx)
@@ -12082,8 +12197,10 @@ class AllSky {
12082
12197
  // gl.enableVertexAttribArray((hipsShaderProgram as any).locations.textureCoordAttribute)
12083
12198
  gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
12084
12199
  gl.bindTexture(gl.TEXTURE_2D, this._texture);
12085
- // gl.uniform1f(hipsShaderProgram.locations.textureAlpha, this.opacity)
12086
- gl.uniform1f(this._hipsShaderProgram.locations.textureAlpha, this.opacity);
12200
+ const factorLocation = this._hipsShaderProgram.locations.textureAlpha[this._hipsShaderIndex];
12201
+ if (factorLocation) {
12202
+ gl.uniform1f(factorLocation, this.opacity);
12203
+ }
12087
12204
  gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBuffer);
12088
12205
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
12089
12206
  gl.vertexAttribPointer(
@@ -12134,6 +12251,7 @@ exports["default"] = AllSky;
12134
12251
  /***/ 2885
12135
12252
  (__unused_webpack_module, exports, __webpack_require__) {
12136
12253
 
12254
+ "use strict";
12137
12255
  /*
12138
12256
  * AstroViewer
12139
12257
  * Copyright (C) Fabrizio Giordano
@@ -12151,6 +12269,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12151
12269
  Object.defineProperty(exports, "__esModule", ({ value: true }));
12152
12270
  const Global_js_1 = __importDefault(__webpack_require__(4382));
12153
12271
  const FoVHelper_js_1 = __webpack_require__(229);
12272
+ const FitsTileLoader_js_1 = __webpack_require__(1399);
12154
12273
  class AncestorTile {
12155
12274
  _hips;
12156
12275
  _tileno;
@@ -12164,7 +12283,8 @@ class AncestorTile {
12164
12283
  _pixels = [];
12165
12284
  _texture = null;
12166
12285
  _image;
12167
- _texurl = '';
12286
+ _texurl = "";
12287
+ _fitsTile;
12168
12288
  vertexPosition;
12169
12289
  vertexPositionBuffer;
12170
12290
  vertexIndices;
@@ -12190,14 +12310,41 @@ class AncestorTile {
12190
12310
  }
12191
12311
  initImage() {
12192
12312
  const dirnumber = Math.floor(this._tileno / 10000) * 10000;
12193
- this._texurl = `${this._baseurl}/Norder${this._order}/Dir${dirnumber}/Npix${this._tileno}.${this._format}`;
12313
+ this._texurl =
12314
+ `${this._baseurl}/Norder${this._order}/Dir${dirnumber}` +
12315
+ `/Npix${this._tileno}.${this._format}`;
12316
+ if (this._format === "fits") {
12317
+ void this.loadFits();
12318
+ return;
12319
+ }
12320
+ this.loadImage();
12321
+ }
12322
+ async loadFits() {
12323
+ try {
12324
+ this._fitsTile = await (0, FitsTileLoader_js_1.loadFitsTile)(this._texurl);
12325
+ this.textureLoaded();
12326
+ const fits = this._fitsTile;
12327
+ if (!fits) {
12328
+ throw new Error(`FITS tile data not loaded: ${this._texurl}`);
12329
+ }
12330
+ const gl = this._webgl;
12331
+ gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
12332
+ gl.bindTexture(gl.TEXTURE_2D, this._texture);
12333
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, fits.width, fits.height, 0, gl.RED, gl.FLOAT, fits.pixels);
12334
+ this.initModelBuffer();
12335
+ this._ready = true;
12336
+ }
12337
+ catch (error) {
12338
+ console.error(`[AncestorTile] Unable to load FITS tile ${this._texurl}`, error);
12339
+ }
12340
+ }
12341
+ loadImage() {
12194
12342
  this._image = new Image();
12195
12343
  this._image.onload = () => this.imageLoaded();
12196
12344
  this._image.onerror = () => {
12197
- console.error('File not found? %s', this._texurl);
12345
+ console.error("File not found? %s", this._texurl);
12198
12346
  };
12199
- this._image.crossOrigin = 'anonymous';
12200
- // If you ever need FITS handling, call this.loadImage() instead.
12347
+ this._image.crossOrigin = "anonymous";
12201
12348
  this._image.src = this._texurl;
12202
12349
  }
12203
12350
  imageLoaded() {
@@ -12215,15 +12362,47 @@ class AncestorTile {
12215
12362
  const gl = this._webgl;
12216
12363
  this._texture = gl.createTexture();
12217
12364
  gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
12218
- gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
12365
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._format !== "fits");
12219
12366
  gl.bindTexture(gl.TEXTURE_2D, this._texture);
12220
12367
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
12221
12368
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
12222
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
12223
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
12369
+ if (this._format === "fits") {
12370
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
12371
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
12372
+ }
12373
+ else {
12374
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
12375
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
12376
+ }
12224
12377
  if (!gl.isTexture(this._texture)) {
12225
- console.log('error in texture');
12378
+ console.log("error in texture");
12379
+ }
12380
+ }
12381
+ getFitsDataRange() {
12382
+ const hipsRange = this._hips.dataRange;
12383
+ if (hipsRange.min !== undefined &&
12384
+ hipsRange.max !== undefined &&
12385
+ Number.isFinite(hipsRange.min) &&
12386
+ Number.isFinite(hipsRange.max) &&
12387
+ hipsRange.max > hipsRange.min) {
12388
+ return {
12389
+ min: hipsRange.min,
12390
+ max: hipsRange.max,
12391
+ };
12392
+ }
12393
+ const fits = this._fitsTile;
12394
+ if (fits &&
12395
+ fits.dataMin !== null &&
12396
+ fits.dataMax !== null &&
12397
+ Number.isFinite(fits.dataMin) &&
12398
+ Number.isFinite(fits.dataMax) &&
12399
+ fits.dataMax > fits.dataMin) {
12400
+ return {
12401
+ min: fits.dataMin,
12402
+ max: fits.dataMax,
12403
+ };
12226
12404
  }
12405
+ return null;
12227
12406
  }
12228
12407
  initModelBuffer() {
12229
12408
  const gl = this._webgl;
@@ -12266,43 +12445,6 @@ class AncestorTile {
12266
12445
  }
12267
12446
  return vertexIndices;
12268
12447
  }
12269
- // Version that uses getPointsForXyfNoStep (kept for reference; not used in this class)
12270
- setupPositionAndTexture4Quadrant2(dxmin, dxmax, dymin, dymax, qidx, healpix, orderjump, origxyf) {
12271
- this.vertexPosition[qidx] = new Float32Array(20 * (dxmax - dxmin) * (dymax - dymin));
12272
- const step = 1 / (1 << orderjump);
12273
- let p = 0;
12274
- for (let dx = dxmin; dx < dxmax; dx++) {
12275
- for (let dy = dymin; dy < dymax; dy++) {
12276
- const facesVec3Array = healpix.getPointsForXyfNoStep(dx, dy, origxyf.face);
12277
- const uindex = dy - (origxyf.iy << orderjump);
12278
- const vindex = dx - (origxyf.ix << orderjump);
12279
- this.vertexPosition[qidx][20 * p] = facesVec3Array[0].x;
12280
- this.vertexPosition[qidx][20 * p + 1] = facesVec3Array[0].y;
12281
- this.vertexPosition[qidx][20 * p + 2] = facesVec3Array[0].z;
12282
- this.vertexPosition[qidx][20 * p + 3] = step + step * uindex;
12283
- this.vertexPosition[qidx][20 * p + 4] = 1 - (step + step * vindex);
12284
- this.vertexPosition[qidx][20 * p + 5] = facesVec3Array[1].x;
12285
- this.vertexPosition[qidx][20 * p + 6] = facesVec3Array[1].y;
12286
- this.vertexPosition[qidx][20 * p + 7] = facesVec3Array[1].z;
12287
- this.vertexPosition[qidx][20 * p + 8] = step + step * uindex;
12288
- this.vertexPosition[qidx][20 * p + 9] = 1 - step * vindex;
12289
- this.vertexPosition[qidx][20 * p + 10] = facesVec3Array[2].x;
12290
- this.vertexPosition[qidx][20 * p + 11] = facesVec3Array[2].y;
12291
- this.vertexPosition[qidx][20 * p + 12] = facesVec3Array[2].z;
12292
- this.vertexPosition[qidx][20 * p + 13] = step * uindex;
12293
- this.vertexPosition[qidx][20 * p + 14] = 1 - step * vindex;
12294
- this.vertexPosition[qidx][20 * p + 15] = facesVec3Array[3].x;
12295
- this.vertexPosition[qidx][20 * p + 16] = facesVec3Array[3].y;
12296
- this.vertexPosition[qidx][20 * p + 17] = facesVec3Array[3].z;
12297
- this.vertexPosition[qidx][20 * p + 18] = step * uindex;
12298
- this.vertexPosition[qidx][20 * p + 19] = 1 - (step + step * vindex);
12299
- p++;
12300
- }
12301
- }
12302
- this.vertexPositionBuffer[qidx] = this._webgl.createBuffer();
12303
- this._webgl.bindBuffer(this._webgl.ARRAY_BUFFER, this.vertexPositionBuffer[qidx]);
12304
- this._webgl.bufferData(this._webgl.ARRAY_BUFFER, this.vertexPosition[qidx], this._webgl.STATIC_DRAW);
12305
- }
12306
12448
  // Version used by the original JS, collecting _pixels via xyf2nest + getBoundaries
12307
12449
  setupPositionAndTexture4Quadrant(dxmin, dxmax, dymin, dymax, qidx, healpix, orderjump, origxyf) {
12308
12450
  const gl = this._webgl;
@@ -12354,12 +12496,26 @@ class AncestorTile {
12354
12496
  quadrantsToDraw = q;
12355
12497
  }
12356
12498
  this._hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx);
12499
+ if (this._format === "fits") {
12500
+ const range = this.getFitsDataRange();
12501
+ if (!range) {
12502
+ console.error(`[AncestorTile] No display range available for FITS tile ${this._texurl}`);
12503
+ return false;
12504
+ }
12505
+ this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max);
12506
+ }
12507
+ else {
12508
+ this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, false);
12509
+ }
12357
12510
  const gl = this._webgl;
12358
12511
  gl.enableVertexAttribArray(this._hipsShaderProgram.locations.vertexPositionAttribute);
12359
12512
  gl.enableVertexAttribArray(this._hipsShaderProgram.locations.textureCoordAttribute);
12360
12513
  gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
12361
12514
  gl.bindTexture(gl.TEXTURE_2D, this._texture);
12362
- gl.uniform1f(this._hipsShaderProgram.locations.textureAlpha, this.opacity);
12515
+ const factorLocation = this._hipsShaderProgram.locations.textureAlpha[this._hipsShaderIndex];
12516
+ if (factorLocation) {
12517
+ gl.uniform1f(factorLocation, this.opacity);
12518
+ }
12363
12519
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
12364
12520
  const elemno = this.vertexIndices.length;
12365
12521
  quadrantsToDraw.forEach((qidx) => {
@@ -12386,8 +12542,9 @@ class AncestorTile {
12386
12542
  : this._tileBuffer.getTile(childTileNo, childrenOrder, this._hips);
12387
12543
  // childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx)
12388
12544
  childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx, this._hipsShaderProgram);
12389
- if (childTile._ready) {
12390
- quadrantsToDraw.delete(childTile._tileno - (this._tileno << 2));
12545
+ if (childTile.getReadyState()) {
12546
+ quadrantsToDraw.delete(c);
12547
+ // quadrantsToDraw.delete((childTile as any)._tileno - (this._tileno << 2))
12391
12548
  }
12392
12549
  }
12393
12550
  }
@@ -12397,11 +12554,88 @@ class AncestorTile {
12397
12554
  exports["default"] = AncestorTile;
12398
12555
 
12399
12556
 
12557
+ /***/ },
12558
+
12559
+ /***/ 1399
12560
+ (__unused_webpack_module, exports, __webpack_require__) {
12561
+
12562
+ "use strict";
12563
+ var __webpack_unused_export__;
12564
+
12565
+ /*
12566
+ * AstroViewer
12567
+ * Copyright (C) Fabrizio Giordano
12568
+ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-AstroViewer-Commercial
12569
+ *
12570
+ * AstroViewer is dual-licensed under the GNU Affero General Public License
12571
+ * version 3 and a separate commercial license.
12572
+ *
12573
+ * See LICENSE.md, LICENSE-AGPL.md, and LICENSE-COMMERCIAL.md for details.
12574
+ */
12575
+ __webpack_unused_export__ = ({ value: true });
12576
+ exports.loadFitsTile = loadFitsTile;
12577
+ const jsfitsio_1 = __webpack_require__(1677);
12578
+ async function loadFitsTile(url) {
12579
+ const fitsFile = await jsfitsio_1.FITSParser.loadFITSFile(url);
12580
+ if (!fitsFile?.primaryHDU) {
12581
+ throw new Error(`Unable to load FITS tile: ${url}`);
12582
+ }
12583
+ const image = fitsFile.primaryHDU;
12584
+ if (image.naxis !== 2) {
12585
+ throw new Error(`Expected a 2D FITS tile, got NAXIS=${image.naxis}: ${url}`);
12586
+ }
12587
+ const [width, height] = image.shape;
12588
+ if (!Number.isInteger(width) ||
12589
+ !Number.isInteger(height) ||
12590
+ width <= 0 ||
12591
+ height <= 0) {
12592
+ throw new Error(`Invalid FITS tile dimensions: ${url}`);
12593
+ }
12594
+ const data = image.typedData;
12595
+ if (!data || data.length !== width * height) {
12596
+ throw new Error(`Invalid FITS tile payload: ${url}`);
12597
+ }
12598
+ if (data instanceof BigInt64Array) {
12599
+ throw new Error(`BITPIX=64 FITS tiles are not supported for HiPS rendering: ${url}`);
12600
+ }
12601
+ const bscale = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.BSCALE) ?? 1;
12602
+ const bzero = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.BZERO) ?? 0;
12603
+ const blank = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.BLANK);
12604
+ const dataMin = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.DATAMIN);
12605
+ const dataMax = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.DATAMAX);
12606
+ const pixels = new Float32Array(data.length);
12607
+ for (let i = 0; i < data.length; i++) {
12608
+ const rawValue = data[i];
12609
+ if (!Number.isFinite(rawValue) || (blank !== null && rawValue === blank)) {
12610
+ pixels[i] = Number.NaN;
12611
+ continue;
12612
+ }
12613
+ pixels[i] = rawValue * bscale + bzero;
12614
+ }
12615
+ return {
12616
+ width,
12617
+ height,
12618
+ pixels,
12619
+ dataMin,
12620
+ dataMax,
12621
+ };
12622
+ }
12623
+ function getNumericHeaderValue(header, key) {
12624
+ const item = header.findById(key);
12625
+ if (!item) {
12626
+ return null;
12627
+ }
12628
+ const value = Number(item.value);
12629
+ return Number.isFinite(value) ? value : null;
12630
+ }
12631
+
12632
+
12400
12633
  /***/ },
12401
12634
 
12402
12635
  /***/ 229
12403
12636
  (__unused_webpack_module, exports) {
12404
12637
 
12638
+ "use strict";
12405
12639
  var __webpack_unused_export__;
12406
12640
  /*
12407
12641
  * AstroViewer
@@ -12565,6 +12799,7 @@ __webpack_unused_export__ = FoVHelper;
12565
12799
  /***/ 3726
12566
12800
  (__unused_webpack_module, exports, __webpack_require__) {
12567
12801
 
12802
+ "use strict";
12568
12803
  /*
12569
12804
  * AstroViewer
12570
12805
  * Copyright (C) Fabrizio Giordano
@@ -12601,30 +12836,47 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12601
12836
  _allSky = true;
12602
12837
  samplerIdx = 0;
12603
12838
  colorMapIdx = 0;
12604
- colorMap = ColorMaps_js_1.default['native'];
12839
+ colorMap = ColorMaps_js_1.default["native"];
12605
12840
  _healpixGrid;
12606
12841
  // exposed read-only helpers
12607
- get maxOrder() { return this._maxorder; }
12608
- get minOrder() { return this._minorder; }
12609
- get baseURL() { return this._baseurl; }
12610
- get format() { return this._format; }
12611
- get propertiesRawText() { return this._descriptor.propertiesRawText; }
12612
- get properties() { return this._descriptor.properties; }
12842
+ get maxOrder() {
12843
+ return this._maxorder;
12844
+ }
12845
+ get minOrder() {
12846
+ return this._minorder;
12847
+ }
12848
+ get baseURL() {
12849
+ return this._baseurl;
12850
+ }
12851
+ get format() {
12852
+ return this._format;
12853
+ }
12854
+ get propertiesRawText() {
12855
+ return this._descriptor.propertiesRawText;
12856
+ }
12857
+ get properties() {
12858
+ return this._descriptor.properties;
12859
+ }
12613
12860
  constructor(radius, position, xrad, yrad, descriptor, webgl, healpixGrid) {
12614
12861
  super(radius, position, xrad, yrad, descriptor.surveyName, webgl, descriptor.isGalactic);
12615
12862
  this._descriptor = descriptor;
12616
12863
  this.initGL(webgl);
12617
12864
  this._healpixGrid = healpixGrid;
12618
- this._healpixGrid.visibleTilesManager.tileBuffer.addHiPS(this);
12619
- // DEBUG logs kept from JS (optional)
12620
- // eslint-disable-next-line no-console
12621
- console.log('HiPS frame ' + descriptor.hipsFrame);
12622
- // eslint-disable-next-line no-console
12623
- console.log('HiPS minOrder ' + descriptor.minOrder);
12624
- this._format = descriptor.imgFormats[0];
12865
+ this._format = this.selectDefaultFormat(descriptor.imgFormats);
12625
12866
  this._baseurl = descriptor.url;
12626
12867
  this._maxorder = descriptor.maxOrder;
12627
12868
  this._minorder = descriptor.minOrder;
12869
+ if (this.isGalacticHips) {
12870
+ this._healpixGrid.visibleTilesManager.tileBuffer.addGalHiPS(this);
12871
+ }
12872
+ else {
12873
+ this._healpixGrid.visibleTilesManager.tileBuffer.addHiPS(this);
12874
+ }
12875
+ // DEBUG logs kept from JS (optional)
12876
+ // eslint-disable-next-line no-console
12877
+ console.log("HiPS frame " + descriptor.hipsFrame);
12878
+ // eslint-disable-next-line no-console
12879
+ console.log("HiPS minOrder " + descriptor.minOrder);
12628
12880
  this.initShaders();
12629
12881
  // pick initial order from a starting FoV
12630
12882
  const fov = 180;
@@ -12634,39 +12886,52 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12634
12886
  this._allSkyTile = null;
12635
12887
  // auto-detect all-sky: original code forces true
12636
12888
  this._allSky = true;
12889
+ this.initBaseTiles();
12890
+ }
12891
+ initBaseTiles() {
12892
+ this._ancestorTiles = [];
12893
+ this._allSkyTile = null;
12637
12894
  if (this._allSky) {
12638
12895
  this._allSkyTile = new AllSky_js_1.default(this, this._webgl, this._healpixGrid.visibleTilesManager.tileBuffer, super.hipsShaderProgram);
12896
+ return;
12639
12897
  }
12640
- else {
12641
- for (let t = 0; t < 12; t++) {
12642
- this._ancestorTiles.push(new AncestorTile_js_1.default(t, 0, this, this._healpixGrid.visibleTilesManager.tileBuffer, super.hipsShaderProgram, this._webgl));
12643
- }
12898
+ for (let t = 0; t < 12; t++) {
12899
+ this._ancestorTiles.push(new AncestorTile_js_1.default(t, 0, this, this._healpixGrid.visibleTilesManager.tileBuffer, super.hipsShaderProgram, this._webgl));
12644
12900
  }
12645
12901
  }
12646
12902
  getProperty(key) {
12647
12903
  return this._descriptor.getProperty(key);
12648
12904
  }
12649
12905
  changeFormat(format) {
12650
- this._format = format;
12651
- // original code referenced _tileBuffer; if you have one, wire it back.
12652
- // Keeping calls no-op to avoid breaking at runtime if _tileBuffer is undefined.
12653
- // (newVisibleTilesManager + TileBuffer drive the actual tile lifecycle)
12654
- // @ts-ignore
12655
- if (this._tileBuffer?.clearAll)
12656
- this._tileBuffer.clearAll();
12657
- // @ts-ignore
12658
- if (this._tileBuffer)
12659
- this._tileBuffer._format = this._format;
12660
- const pixelByOrder = this.isGalacticHips
12661
- ? this._healpixGrid.visibleTilesManager.galVisibleTilesByOrder
12662
- : this._healpixGrid.visibleTilesManager.visibleTilesByOrder;
12663
- // const pixelByOrder =
12664
- // this.isGalacticHips
12665
- // ? visibleTilesManager.galVisibleTilesByOrder
12666
- // : visibleTilesManager.visibleTilesByOrder
12667
- // @ts-ignore
12668
- if (this._tileBuffer?.updateTiles)
12669
- this._tileBuffer.updateTiles(pixelByOrder.pixels, pixelByOrder.order);
12906
+ const normalizedFormat = format.toLowerCase();
12907
+ if (!this._descriptor.imgFormats.includes(normalizedFormat)) {
12908
+ throw new Error(`HiPS format "${format}" is not supported. ` +
12909
+ `Available formats: ${this._descriptor.imgFormats.join(", ")}`);
12910
+ }
12911
+ if (normalizedFormat === this._format.toLowerCase()) {
12912
+ return;
12913
+ }
12914
+ const tileBuffer = this._healpixGrid.visibleTilesManager.tileBuffer;
12915
+ /*
12916
+ * Remove Tile instances created using the previous format.
12917
+ *
12918
+ * TileBuffer invalidates by HiPS identity/base URL rather than by the
12919
+ * current format, so both active and cached resources are discarded.
12920
+ */
12921
+ tileBuffer.invalidateHiPS(this);
12922
+ /*
12923
+ * Change format before recreating AllSky/AncestorTile because their
12924
+ * constructors read hips.format.
12925
+ */
12926
+ this._format = normalizedFormat;
12927
+ /*
12928
+ * AllSky and AncestorTile also keep the format they were constructed
12929
+ * with, so they must be recreated.
12930
+ */
12931
+ this.initBaseTiles();
12932
+ }
12933
+ get availableFormats() {
12934
+ return this._descriptor.imgFormats;
12670
12935
  }
12671
12936
  /**
12672
12937
  * Shader colormap switcher
@@ -12679,60 +12944,60 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12679
12944
  * 6 -> cubehelix
12680
12945
  */
12681
12946
  changeColorMap(colorMap) {
12682
- console.log('HiPS.changeColorMap -> shaderProgram', super.hipsShaderProgram.shaderProgram);
12947
+ console.log("HiPS.changeColorMap -> shaderProgram", super.hipsShaderProgram.shaderProgram);
12683
12948
  this.colorMap = colorMap;
12684
12949
  switch (colorMap.name) {
12685
- case 'grayscale':
12950
+ case "grayscale":
12686
12951
  this.colorMapIdx = 1;
12687
12952
  // hipsShaderProgram.setGrayscaleShader()
12688
- this.colorMap = ColorMaps_js_1.default['grayscale'];
12953
+ this.colorMap = ColorMaps_js_1.default["grayscale"];
12689
12954
  super.hipsShaderProgram.setGrayscaleShader();
12690
12955
  break;
12691
- case 'planck':
12956
+ case "planck":
12692
12957
  this.colorMapIdx = 2;
12693
- this.colorMap = ColorMaps_js_1.default['planck'];
12958
+ this.colorMap = ColorMaps_js_1.default["planck"];
12694
12959
  // hipsShaderProgram.setColorMapShader()
12695
12960
  super.hipsShaderProgram.setColorMapShader();
12696
12961
  break;
12697
- case 'cmb':
12962
+ case "cmb":
12698
12963
  this.colorMapIdx = 3;
12699
- this.colorMap = ColorMaps_js_1.default['cmb'];
12964
+ this.colorMap = ColorMaps_js_1.default["cmb"];
12700
12965
  // hipsShaderProgram.setColorMapShader()
12701
12966
  super.hipsShaderProgram.setColorMapShader();
12702
12967
  break;
12703
- case 'rainbow':
12968
+ case "rainbow":
12704
12969
  this.colorMapIdx = 4;
12705
- this.colorMap = ColorMaps_js_1.default['rainbow'];
12970
+ this.colorMap = ColorMaps_js_1.default["rainbow"];
12706
12971
  // hipsShaderProgram.setColorMapShader()
12707
12972
  super.hipsShaderProgram.setColorMapShader();
12708
12973
  break;
12709
- case 'eosb':
12974
+ case "eosb":
12710
12975
  this.colorMapIdx = 5;
12711
- this.colorMap = ColorMaps_js_1.default['eosb'];
12976
+ this.colorMap = ColorMaps_js_1.default["eosb"];
12712
12977
  super.hipsShaderProgram.setColorMapShader();
12713
12978
  // hipsShaderProgram.setColorMapShader()
12714
12979
  break;
12715
- case 'cubehelix':
12980
+ case "cubehelix":
12716
12981
  this.colorMapIdx = 6;
12717
- this.colorMap = ColorMaps_js_1.default['cubehelix'];
12982
+ this.colorMap = ColorMaps_js_1.default["cubehelix"];
12718
12983
  super.hipsShaderProgram.setColorMapShader();
12719
12984
  // hipsShaderProgram.setColorMapShader()
12720
12985
  break;
12721
- case 'hot':
12986
+ case "hot":
12722
12987
  this.colorMapIdx = 7;
12723
- this.colorMap = ColorMaps_js_1.default['hot'];
12988
+ this.colorMap = ColorMaps_js_1.default["hot"];
12724
12989
  super.hipsShaderProgram.setColorMapShader();
12725
12990
  // hipsShaderProgram.setColorMapShader()
12726
12991
  break;
12727
- case 'gray':
12992
+ case "gray":
12728
12993
  this.colorMapIdx = 8;
12729
- this.colorMap = ColorMaps_js_1.default['gray'];
12994
+ this.colorMap = ColorMaps_js_1.default["gray"];
12730
12995
  super.hipsShaderProgram.setColorMapShader();
12731
12996
  // hipsShaderProgram.setColorMapShader()
12732
12997
  break;
12733
- case 'native':
12998
+ case "native":
12734
12999
  this.colorMapIdx = 0;
12735
- this.colorMap = ColorMaps_js_1.default['native'];
13000
+ this.colorMap = ColorMaps_js_1.default["native"];
12736
13001
  super.hipsShaderProgram.setNativeShader();
12737
13002
  break;
12738
13003
  default:
@@ -12747,6 +13012,30 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12747
13012
  // this.shaderProgram = super.hipsShaderProgram.shaderProgram
12748
13013
  // this.shaderProgram = hipsShaderProgram.shaderProgram
12749
13014
  }
13015
+ // private selectDefaultFormat(formats: string[]): string {
13016
+ // if (formats.includes("fits")) return "fits";
13017
+ // if (formats.includes("png")) return "png";
13018
+ // if (formats.includes("jpg")) return "jpg";
13019
+ // if (formats.length > 0) {
13020
+ // return formats[0];
13021
+ // }
13022
+ // throw new Error("HiPS descriptor does not define a tile format");
13023
+ // }
13024
+ selectDefaultFormat(formats) {
13025
+ if (formats.includes("png"))
13026
+ return "png";
13027
+ if (formats.includes("jpg"))
13028
+ return "jpg";
13029
+ if (formats.includes("fits"))
13030
+ return "fits";
13031
+ if (formats.length > 0) {
13032
+ return formats[0];
13033
+ }
13034
+ throw new Error("HiPS descriptor does not define a tile format");
13035
+ }
13036
+ get dataRange() {
13037
+ return this._descriptor.dataRange;
13038
+ }
12750
13039
  getCurrentHealpixOrder() {
12751
13040
  return this._visibleorder;
12752
13041
  }
@@ -12756,7 +13045,7 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12756
13045
  ? this._healpixGrid.visibleTilesManager.galVisibleTilesByOrder
12757
13046
  : this._healpixGrid.visibleTilesManager.visibleTilesByOrder;
12758
13047
  return {
12759
- activeBaseLayer: 'hips',
13048
+ activeBaseLayer: "hips",
12760
13049
  hipsName: this._descriptor.surveyName,
12761
13050
  hipsUrl: this._baseurl,
12762
13051
  isGalactic: this.isGalacticHips,
@@ -12788,16 +13077,10 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
12788
13077
  super.hipsShaderProgram.setRuntimeColorMap(this.colorMap);
12789
13078
  if (this._allSky && this._allSkyTile) {
12790
13079
  if (this.isGalacticHips) {
12791
- this._allSkyTile.draw(this._healpixGrid.visibleTilesManager.galVisibleTilesByOrder.order, this._healpixGrid.visibleTilesManager.galAncestorsMap,
12792
- // visibleTilesManager.galVisibleTilesByOrder.order,
12793
- // visibleTilesManager.galAncestorsMap,
12794
- pMatrix, vMatrix, mMatrix, this.colorMapIdx);
13080
+ this._allSkyTile.draw(this._healpixGrid.visibleTilesManager.galVisibleTilesByOrder.order, this._healpixGrid.visibleTilesManager.galAncestorsMap, pMatrix, vMatrix, mMatrix, this.colorMapIdx);
12795
13081
  }
12796
13082
  else {
12797
- this._allSkyTile.draw(this._healpixGrid.visibleTilesManager.visibleTilesByOrder.order, this._healpixGrid.visibleTilesManager.ancestorsMap,
12798
- // visibleTilesManager.visibleTilesByOrder.order,
12799
- // visibleTilesManager.ancestorsMap,
12800
- pMatrix, vMatrix, mMatrix, this.colorMapIdx);
13083
+ this._allSkyTile.draw(this._healpixGrid.visibleTilesManager.visibleTilesByOrder.order, this._healpixGrid.visibleTilesManager.ancestorsMap, pMatrix, vMatrix, mMatrix, this.colorMapIdx);
12801
13084
  }
12802
13085
  return;
12803
13086
  }
@@ -12821,6 +13104,7 @@ exports.HiPS = HiPS;
12821
13104
  /***/ 5087
12822
13105
  (__unused_webpack_module, exports) {
12823
13106
 
13107
+ "use strict";
12824
13108
  /*
12825
13109
  * AstroViewer
12826
13110
  * Copyright (C) Fabrizio Giordano
@@ -12972,6 +13256,7 @@ exports.HiPSDescriptor = HiPSDescriptor;
12972
13256
  /***/ 8256
12973
13257
  (__unused_webpack_module, exports, __webpack_require__) {
12974
13258
 
13259
+ "use strict";
12975
13260
 
12976
13261
  /*
12977
13262
  * AstroViewer
@@ -12990,6 +13275,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
12990
13275
  // Tile.ts
12991
13276
  const Global_js_1 = __importDefault(__webpack_require__(4382));
12992
13277
  const FoVHelper_js_1 = __webpack_require__(229);
13278
+ const FitsTileLoader_js_1 = __webpack_require__(1399);
12993
13279
  // ------------------------------------------------------------------------
12994
13280
  class Tile {
12995
13281
  _hips;
@@ -13004,8 +13290,9 @@ class Tile {
13004
13290
  _image;
13005
13291
  _textureLoaded = false;
13006
13292
  _texture;
13007
- _texurl = '';
13293
+ _texurl = "";
13008
13294
  _hipsShaderIndex = 0;
13295
+ _fitsTile;
13009
13296
  _cacheTime0;
13010
13297
  _inView = true;
13011
13298
  _amIStillInFoV_requsetID;
@@ -13062,50 +13349,66 @@ class Tile {
13062
13349
  console.warn(`[Tile] Skipping tile request above max order: requested order ${this._order}, max order ${this._maxorder}, url ${this._baseurl}`);
13063
13350
  return;
13064
13351
  }
13065
- this._image = new Image();
13066
13352
  const dirnumber = Math.floor(this._tileno / 10000) * 10000;
13067
13353
  this._texurl = `${this._baseurl}/Norder${this._order}/Dir${dirnumber}/Npix${this._tileno}.${this._format}`;
13354
+ if (this._format === "fits") {
13355
+ void this.loadFits();
13356
+ return;
13357
+ }
13358
+ this.loadImage();
13359
+ }
13360
+ loadImage() {
13361
+ this._image = new Image();
13068
13362
  this._image.onload = () => this.imageLoaded();
13069
13363
  this._image.onerror = () => {
13070
- // console.error('File not found?', this._texurl)
13071
13364
  this._ready = false;
13072
13365
  this._abort = true;
13073
13366
  this.destroyIntervals();
13074
13367
  };
13075
- this._image.crossOrigin = 'anonymous';
13368
+ this._image.crossOrigin = "anonymous";
13076
13369
  this._image.src = this._texurl;
13077
13370
  }
13371
+ async loadFits() {
13372
+ try {
13373
+ this._fitsTile = await (0, FitsTileLoader_js_1.loadFitsTile)(this._texurl);
13374
+ this._ready = true;
13375
+ }
13376
+ catch (error) {
13377
+ console.error(`[Tile] Unable to load FITS tile ${this._texurl}`, error);
13378
+ this._ready = false;
13379
+ this._abort = true;
13380
+ this.destroyIntervals();
13381
+ }
13382
+ }
13078
13383
  imageLoaded() {
13079
13384
  // this.textureLoaded()
13080
13385
  // this.initModelBuffer()
13081
13386
  // this._textureLoaded = true
13082
13387
  this._ready = true;
13083
13388
  }
13084
- // private textureLoaded(): void {
13085
13389
  textureLoaded(hipsShaderProgram) {
13086
- // this._hipsShaderProgram.enableProgram()
13087
13390
  hipsShaderProgram.enableProgram();
13088
13391
  const gl = this._webgl;
13089
13392
  this._texture = gl.createTexture();
13090
13393
  gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
13091
- gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
13394
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._format !== "fits");
13092
13395
  gl.bindTexture(gl.TEXTURE_2D, this._texture);
13093
- if (!gl.isTexture(this._texture)) {
13094
- console.log('error in texture');
13396
+ if (this._format === "fits") {
13397
+ const fits = this._fitsTile;
13398
+ if (!fits) {
13399
+ throw new Error(`FITS tile data not loaded: ${this._texurl}`);
13400
+ }
13401
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, fits.width, fits.height, 0, gl.RED, gl.FLOAT, fits.pixels);
13402
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
13403
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
13404
+ }
13405
+ else {
13406
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
13407
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
13408
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
13095
13409
  }
13096
- gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
13097
- gl.bindTexture(gl.TEXTURE_2D, this._texture);
13098
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
13099
13410
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
13100
13411
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
13101
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
13102
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
13103
- // FIX: use the sampler location we fetched in enableShaders()
13104
- // gl.uniform1i((this._hipsShaderProgram.locations as ShaderLocations).sampler, this._hipsShaderIndex)
13105
- // gl.uniform1i((hipsShaderProgram.locations as ShaderLocations).sampler, this._hipsShaderIndex)
13106
- if (!gl.isTexture(this._texture)) {
13107
- console.warn('Texture creation failed');
13108
- }
13109
13412
  this.initModelBuffer();
13110
13413
  this._textureLoaded = true;
13111
13414
  }
@@ -13172,26 +13475,32 @@ class Tile {
13172
13475
  this.vertexPosition[qidx][20 * p] = facesVec3Array[0].x;
13173
13476
  this.vertexPosition[qidx][20 * p + 1] = facesVec3Array[0].y;
13174
13477
  this.vertexPosition[qidx][20 * p + 2] = facesVec3Array[0].z;
13175
- this.vertexPosition[qidx][20 * p + 3] = step + step * uindex + s_pixel_size;
13176
- this.vertexPosition[qidx][20 * p + 4] = 1 - (step + step * vindex) - t_pixel_size;
13478
+ this.vertexPosition[qidx][20 * p + 3] =
13479
+ step + step * uindex + s_pixel_size;
13480
+ this.vertexPosition[qidx][20 * p + 4] =
13481
+ 1 - (step + step * vindex) - t_pixel_size;
13177
13482
  // v1
13178
13483
  this.vertexPosition[qidx][20 * p + 5] = facesVec3Array[1].x;
13179
13484
  this.vertexPosition[qidx][20 * p + 6] = facesVec3Array[1].y;
13180
13485
  this.vertexPosition[qidx][20 * p + 7] = facesVec3Array[1].z;
13181
- this.vertexPosition[qidx][20 * p + 8] = step + step * uindex + s_pixel_size;
13182
- this.vertexPosition[qidx][20 * p + 9] = 1 - step * vindex + t_pixel_size;
13486
+ this.vertexPosition[qidx][20 * p + 8] =
13487
+ step + step * uindex + s_pixel_size;
13488
+ this.vertexPosition[qidx][20 * p + 9] =
13489
+ 1 - step * vindex + t_pixel_size;
13183
13490
  // v2
13184
13491
  this.vertexPosition[qidx][20 * p + 10] = facesVec3Array[2].x;
13185
13492
  this.vertexPosition[qidx][20 * p + 11] = facesVec3Array[2].y;
13186
13493
  this.vertexPosition[qidx][20 * p + 12] = facesVec3Array[2].z;
13187
13494
  this.vertexPosition[qidx][20 * p + 13] = step * uindex - s_pixel_size;
13188
- this.vertexPosition[qidx][20 * p + 14] = 1 - step * vindex + t_pixel_size;
13495
+ this.vertexPosition[qidx][20 * p + 14] =
13496
+ 1 - step * vindex + t_pixel_size;
13189
13497
  // v3
13190
13498
  this.vertexPosition[qidx][20 * p + 15] = facesVec3Array[3].x;
13191
13499
  this.vertexPosition[qidx][20 * p + 16] = facesVec3Array[3].y;
13192
13500
  this.vertexPosition[qidx][20 * p + 17] = facesVec3Array[3].z;
13193
13501
  this.vertexPosition[qidx][20 * p + 18] = step * uindex - s_pixel_size;
13194
- this.vertexPosition[qidx][20 * p + 19] = 1 - (step + step * vindex) - t_pixel_size;
13502
+ this.vertexPosition[qidx][20 * p + 19] =
13503
+ 1 - (step + step * vindex) - t_pixel_size;
13195
13504
  p++;
13196
13505
  }
13197
13506
  }
@@ -13199,6 +13508,32 @@ class Tile {
13199
13508
  gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBuffer[qidx]);
13200
13509
  gl.bufferData(gl.ARRAY_BUFFER, this.vertexPosition[qidx], gl.STATIC_DRAW);
13201
13510
  }
13511
+ getFitsDataRange() {
13512
+ const hipsRange = this._hips.dataRange;
13513
+ if (hipsRange.min !== undefined &&
13514
+ hipsRange.max !== undefined &&
13515
+ Number.isFinite(hipsRange.min) &&
13516
+ Number.isFinite(hipsRange.max) &&
13517
+ hipsRange.max > hipsRange.min) {
13518
+ return {
13519
+ min: hipsRange.min,
13520
+ max: hipsRange.max,
13521
+ };
13522
+ }
13523
+ const fits = this._fitsTile;
13524
+ if (fits &&
13525
+ fits.dataMin !== null &&
13526
+ fits.dataMax !== null &&
13527
+ Number.isFinite(fits.dataMin) &&
13528
+ Number.isFinite(fits.dataMax) &&
13529
+ fits.dataMax > fits.dataMin) {
13530
+ return {
13531
+ min: fits.dataMin,
13532
+ max: fits.dataMax,
13533
+ };
13534
+ }
13535
+ return null;
13536
+ }
13202
13537
  get inView() {
13203
13538
  return this._inView;
13204
13539
  }
@@ -13213,7 +13548,9 @@ class Tile {
13213
13548
  this._ready = true;
13214
13549
  if (this._isGalacticHips) {
13215
13550
  if (this._visibleTileManager.galAncestorsMap.has(this._order)) {
13216
- if (!this._visibleTileManager.galAncestorsMap.get(this._order).includes(this._tileno)) {
13551
+ if (!this._visibleTileManager.galAncestorsMap
13552
+ .get(this._order)
13553
+ .includes(this._tileno)) {
13217
13554
  this.moveToCache();
13218
13555
  }
13219
13556
  else {
@@ -13245,7 +13582,9 @@ class Tile {
13245
13582
  }
13246
13583
  else {
13247
13584
  if (this._visibleTileManager.ancestorsMap.has(this._order)) {
13248
- if (!this._visibleTileManager.ancestorsMap.get(this._order).includes(this._tileno)) {
13585
+ if (!this._visibleTileManager.ancestorsMap
13586
+ .get(this._order)
13587
+ .includes(this._tileno)) {
13249
13588
  this.moveToCache();
13250
13589
  }
13251
13590
  else {
@@ -13291,33 +13630,39 @@ class Tile {
13291
13630
  }
13292
13631
  const gl = this._webgl;
13293
13632
  hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx);
13294
- // this._hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx)
13295
- // Enable attributes (these locations are retrieved in enableShaders)
13296
- // gl.enableVertexAttribArray(this._hipsShaderProgram.locations.vertexPositionAttribute)
13297
- // gl.enableVertexAttribArray(this._hipsShaderProgram.locations.textureCoordAttribute)
13298
- gl.enableVertexAttribArray(hipsShaderProgram.locations.vertexPositionAttribute);
13299
- gl.enableVertexAttribArray(hipsShaderProgram.locations.textureCoordAttribute);
13633
+ if (this._format === "fits") {
13634
+ const range = this.getFitsDataRange();
13635
+ if (!range) {
13636
+ console.error(`[Tile] No display range available for FITS tile ${this._texurl}`);
13637
+ return;
13638
+ }
13639
+ hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max);
13640
+ }
13641
+ else {
13642
+ hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, false);
13643
+ }
13644
+ const locations = hipsShaderProgram.locations;
13645
+ gl.enableVertexAttribArray(locations.vertexPositionAttribute);
13646
+ gl.enableVertexAttribArray(locations.textureCoordAttribute);
13300
13647
  gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
13301
13648
  gl.bindTexture(gl.TEXTURE_2D, this._texture);
13302
- // gl.uniform1f(this._hipsShaderProgram.locations.textureAlpha, this.opacity)
13303
- gl.uniform1f(hipsShaderProgram.locations.textureAlpha, this.opacity);
13649
+ const factorLocation = locations.textureAlpha[this._hipsShaderIndex];
13650
+ if (factorLocation) {
13651
+ gl.uniform1f(factorLocation, this.opacity);
13652
+ }
13304
13653
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
13305
13654
  const elemno = this.vertexIndices.length;
13306
- const indexType = this.vertexIndices instanceof Uint32Array ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT;
13655
+ const indexType = this.vertexIndices instanceof Uint32Array
13656
+ ? gl.UNSIGNED_INT
13657
+ : gl.UNSIGNED_SHORT;
13307
13658
  quadrantsToDraw.forEach((qidx) => {
13308
13659
  gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBuffer[qidx]);
13309
- gl.vertexAttribPointer(
13310
- // this._hipsShaderProgram.locations.vertexPositionAttribute,
13311
- hipsShaderProgram.locations.vertexPositionAttribute, 3, gl.FLOAT, false, 5 * 4, 0);
13312
- gl.vertexAttribPointer(
13313
- // this._hipsShaderProgram.locations.textureCoordAttribute,
13314
- hipsShaderProgram.locations.textureCoordAttribute, 2, gl.FLOAT, false, 5 * 4, 3 * 4);
13660
+ gl.vertexAttribPointer(locations.vertexPositionAttribute, 3, gl.FLOAT, false, 5 * 4, 0);
13661
+ gl.vertexAttribPointer(locations.textureCoordAttribute, 2, gl.FLOAT, false, 5 * 4, 3 * 4);
13315
13662
  gl.drawElements(gl.TRIANGLES, elemno, indexType, 0);
13316
13663
  });
13317
- // gl.disableVertexAttribArray(this._hipsShaderProgram.locations.vertexPositionAttribute)
13318
- // gl.disableVertexAttribArray(this._hipsShaderProgram.locations.textureCoordAttribute)
13319
- gl.disableVertexAttribArray(hipsShaderProgram.locations.vertexPositionAttribute);
13320
- gl.disableVertexAttribArray(hipsShaderProgram.locations.textureCoordAttribute);
13664
+ gl.disableVertexAttribArray(locations.vertexPositionAttribute);
13665
+ gl.disableVertexAttribArray(locations.textureCoordAttribute);
13321
13666
  }
13322
13667
  drawChildren(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx, hipsShaderProgram) {
13323
13668
  const quadrantsToDraw = new Set([0, 1, 2, 3]);
@@ -13331,13 +13676,9 @@ class Tile {
13331
13676
  const childTile = this._isGalacticHips
13332
13677
  ? this._tileBuffer.getGalTile(childTileNo, childrenOrder, this._hips)
13333
13678
  : this._tileBuffer.getTile(childTileNo, childrenOrder, this._hips);
13334
- // const childTile = this._isGalacticHips
13335
- // ? newTileBuffer.getGalTile(childTileNo, childrenOrder, this._hips)
13336
- // : newTileBuffer.getTile(childTileNo, childrenOrder, this._hips)
13337
- // childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx)
13338
13679
  childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx, hipsShaderProgram);
13339
- if (childTile._ready) {
13340
- quadrantsToDraw.delete(childTileNo - (this._tileno << 2));
13680
+ if (childTile.getReadyState()) {
13681
+ quadrantsToDraw.delete(c);
13341
13682
  }
13342
13683
  }
13343
13684
  }
@@ -13352,6 +13693,7 @@ exports["default"] = Tile;
13352
13693
  /***/ 4006
13353
13694
  (__unused_webpack_module, exports, __webpack_require__) {
13354
13695
 
13696
+ "use strict";
13355
13697
 
13356
13698
  /*
13357
13699
  * AstroViewer
@@ -13403,7 +13745,7 @@ class TileBuffer {
13403
13745
  /** Register an equatorial HiPS into the buffer. */
13404
13746
  addHiPS(hips) {
13405
13747
  if (this._activeHiPS.has(hips)) {
13406
- console.error('HiPS already present in TileBuffer');
13748
+ console.error("HiPS already present in TileBuffer");
13407
13749
  return;
13408
13750
  }
13409
13751
  this._activeHiPS.set(hips, new Map());
@@ -13411,7 +13753,7 @@ class TileBuffer {
13411
13753
  /** Register a galactic HiPS into the buffer. */
13412
13754
  addGalHiPS(hips) {
13413
13755
  if (this._galActiveHiPS.has(hips)) {
13414
- console.error('HiPS already present in TileBuffer');
13756
+ console.error("HiPS already present in TileBuffer");
13415
13757
  return;
13416
13758
  }
13417
13759
  this._galActiveHiPS.set(hips, new Map());
@@ -13436,7 +13778,7 @@ class TileBuffer {
13436
13778
  }
13437
13779
  /** Fetch (or create) an equatorial tile, reviving from cache if present. */
13438
13780
  getTile(tileno, order, hips) {
13439
- const tileKey = this.key(order, tileno, hips.baseURL);
13781
+ const tileKey = this.key(order, tileno, hips);
13440
13782
  if (!this._tiles.has(tileKey)) {
13441
13783
  if (this._cachedTiles.has(tileKey)) {
13442
13784
  const tile = this._cachedTiles.get(tileKey);
@@ -13454,7 +13796,7 @@ class TileBuffer {
13454
13796
  }
13455
13797
  /** Fetch (or create) a galactic tile, reviving from cache if present. */
13456
13798
  getGalTile(tileno, order, hips) {
13457
- const tileKey = this.key(order, tileno, hips.baseURL);
13799
+ const tileKey = this.key(order, tileno, hips);
13458
13800
  if (!this._galTiles.has(tileKey)) {
13459
13801
  if (this._galCachedTiles.has(tileKey)) {
13460
13802
  const tile = this._galCachedTiles.get(tileKey);
@@ -13472,7 +13814,7 @@ class TileBuffer {
13472
13814
  }
13473
13815
  /** Move a tile (equatorial or galactic) into cache. */
13474
13816
  moveTileToCache(tileno, order, hips) {
13475
- const tileKey = this.key(order, tileno, hips.baseURL);
13817
+ const tileKey = this.key(order, tileno, hips);
13476
13818
  if (this._tiles.has(tileKey)) {
13477
13819
  const tile = this._tiles.get(tileKey);
13478
13820
  tile.setCacheTime0();
@@ -13491,29 +13833,64 @@ class TileBuffer {
13491
13833
  const now = Date.now();
13492
13834
  for (const [tileKey, tile] of this._cachedTiles) {
13493
13835
  const t0 = tile.cacheTime0;
13494
- if (!tile.inView && t0 !== undefined && now - t0 > this._cacheAliveMilliSeconds) {
13836
+ if (!tile.inView &&
13837
+ t0 !== undefined &&
13838
+ now - t0 > this._cacheAliveMilliSeconds) {
13495
13839
  tile.destroyIntervals();
13496
13840
  this._cachedTiles.delete(tileKey);
13497
13841
  }
13498
13842
  }
13499
13843
  for (const [tileKey, tile] of this._galCachedTiles) {
13500
13844
  const t0 = tile.cacheTime0;
13501
- if (!tile.inView && t0 !== undefined && now - t0 > this._cacheAliveMilliSeconds) {
13845
+ if (!tile.inView &&
13846
+ t0 !== undefined &&
13847
+ now - t0 > this._cacheAliveMilliSeconds) {
13502
13848
  tile.destroyIntervals();
13503
13849
  this._galCachedTiles.delete(tileKey);
13504
13850
  }
13505
13851
  }
13506
13852
  }
13507
13853
  /** Compose a stable key for maps. */
13508
- key(order, tileno, baseURL) {
13509
- return `${order}#${tileno}#${baseURL}`;
13854
+ key(order, tileno, hips) {
13855
+ return `${order}#${tileno}#${hips.baseURL}#${hips.format}`;
13856
+ }
13857
+ removeHiPS(hips) {
13858
+ this.invalidateHiPS(hips);
13859
+ this._activeHiPS.delete(hips);
13860
+ this._galActiveHiPS.delete(hips);
13861
+ }
13862
+ /**
13863
+ * Remove all active and cached tiles belonging to a specific HiPS.
13864
+ *
13865
+ * Tile keys contain the HiPS base URL and format. We intentionally
13866
+ * ignore the format here so that a format change removes resources
13867
+ * created with the previous format as well.
13868
+ */
13869
+ invalidateHiPS(hips) {
13870
+ const belongsToHiPS = (tileKey) => tileKey.includes(`#${hips.baseURL}#`);
13871
+ const clearTiles = (tiles) => {
13872
+ for (const [tileKey, tile] of tiles) {
13873
+ if (!belongsToHiPS(tileKey)) {
13874
+ continue;
13875
+ }
13876
+ tile.destroyIntervals();
13877
+ tiles.delete(tileKey);
13878
+ }
13879
+ };
13880
+ clearTiles(this._tiles);
13881
+ clearTiles(this._cachedTiles);
13882
+ clearTiles(this._galTiles);
13883
+ clearTiles(this._galCachedTiles);
13510
13884
  }
13511
13885
  /** Optional: call to stop internal timers if you dispose this buffer. */
13512
13886
  dispose() {
13513
13887
  window.clearInterval(this._cleanerId);
13514
13888
  }
13515
13889
  get size() {
13516
- return this._tiles.size + this._cachedTiles.size + this._galTiles.size + this._galCachedTiles.size;
13890
+ return (this._tiles.size +
13891
+ this._cachedTiles.size +
13892
+ this._galTiles.size +
13893
+ this._galCachedTiles.size);
13517
13894
  }
13518
13895
  get activeTileCount() {
13519
13896
  return this._tiles.size + this._galTiles.size;
@@ -13572,6 +13949,7 @@ exports.TileBuffer = TileBuffer;
13572
13949
  /***/ 2056
13573
13950
  (__unused_webpack_module, exports, __webpack_require__) {
13574
13951
 
13952
+ "use strict";
13575
13953
 
13576
13954
  /*
13577
13955
  * AstroViewer
@@ -13591,11 +13969,8 @@ exports.VisibleTilesManager = void 0;
13591
13969
  const Global_js_1 = __importDefault(__webpack_require__(4382));
13592
13970
  const healpix_1 = __webpack_require__(4851);
13593
13971
  const RayPickingUtils_js_1 = __importDefault(__webpack_require__(4639));
13594
- // import { newTileBuffer } from './TileBuffer.js';
13595
13972
  const TileBuffer_js_1 = __webpack_require__(4006);
13596
13973
  const gl_matrix_1 = __webpack_require__(3890);
13597
- // import healpixGridSingleton from '../grid/HealpixGridSingleton.js';
13598
- // import {HealpixGridSingleton} from '../grid/HealpixGridSingleton.js';
13599
13974
  const Config_js_1 = __webpack_require__(2919);
13600
13975
  class VisibleTilesManager {
13601
13976
  _visibleTilesByOrder;
@@ -13635,18 +14010,13 @@ class VisibleTilesManager {
13635
14010
  init(insideSphere) {
13636
14011
  this.initialised = true;
13637
14012
  this.insideSphere = insideSphere;
13638
- // this.computeVisiblePixels();
13639
- // setInterval(() => this.computeVisiblePixels(), 500);
13640
14013
  }
13641
14014
  getVisibleOrder() {
13642
- // return healpixGridSingleton.visibleorder;
13643
14015
  return this._healpixGrid.visibleorder;
13644
14016
  }
13645
- // computeVisiblePixels(): void {
13646
14017
  computeVisiblePixels(order, webgl, camera, pMatrix) {
13647
14018
  if (!this.initialised)
13648
14019
  return;
13649
- // let order = healpixGridSingleton.visibleorder;
13650
14020
  if (Global_js_1.default.insideSphere && order < 3) {
13651
14021
  order = 3;
13652
14022
  }
@@ -13666,8 +14036,6 @@ class VisibleTilesManager {
13666
14036
  }
13667
14037
  else {
13668
14038
  const geomhealpix = Global_js_1.default.getHealpix(order);
13669
- // const maxX = (global.gl as GL).canvas.width;
13670
- // const maxY = (global.gl as GL).canvas.height;
13671
14039
  const maxX = webgl.canvas.width;
13672
14040
  const maxY = webgl.canvas.height;
13673
14041
  // Sample a grid of screen points, project to the sphere, then to galactic
@@ -13687,13 +14055,11 @@ class VisibleTilesManager {
13687
14055
  if (!pixels.includes(currPixNo)) {
13688
14056
  pixels.push(currPixNo);
13689
14057
  this._ancestorsMap.get(order).push(currPixNo);
13690
- // newTileBuffer.addTile(order, currPixNo);
13691
14058
  this._tileBuffer.addTile(order, currPixNo);
13692
14059
  }
13693
14060
  if (!galTiles.includes(galTileNo)) {
13694
14061
  galTiles.push(galTileNo);
13695
14062
  this._galAncestorsMap.get(order).push(galTileNo);
13696
- // newTileBuffer.addGalTile(order, galTileNo);
13697
14063
  this._tileBuffer.addGalTile(order, galTileNo);
13698
14064
  }
13699
14065
  }
@@ -13711,7 +14077,6 @@ class VisibleTilesManager {
13711
14077
  const parent = pixels[p] >> (2 * o);
13712
14078
  if (!list.includes(parent)) {
13713
14079
  list.push(parent);
13714
- // newTileBuffer.addTile(tgtOrder, parent);
13715
14080
  this._tileBuffer.addTile(tgtOrder, parent);
13716
14081
  }
13717
14082
  }
@@ -13724,7 +14089,6 @@ class VisibleTilesManager {
13724
14089
  const parent = galTiles[p] >> (2 * o);
13725
14090
  if (!list.includes(parent)) {
13726
14091
  list.push(parent);
13727
- // newTileBuffer.addGalTile(tgtOrder, parent);
13728
14092
  this._tileBuffer.addGalTile(tgtOrder, parent);
13729
14093
  }
13730
14094
  }
@@ -13755,6 +14119,7 @@ exports.VisibleTilesManager = VisibleTilesManager;
13755
14119
  /***/ 6878
13756
14120
  (__unused_webpack_module, exports, __webpack_require__) {
13757
14121
 
14122
+ "use strict";
13758
14123
 
13759
14124
  /*
13760
14125
  * AstroViewer
@@ -13948,6 +14313,7 @@ exports.MeshHiPS = MeshHiPS;
13948
14313
  /***/ 847
13949
14314
  (__unused_webpack_module, exports) {
13950
14315
 
14316
+ "use strict";
13951
14317
 
13952
14318
  /*
13953
14319
  * AstroViewer
@@ -14091,6 +14457,7 @@ exports.MeshHiPSDescriptor = MeshHiPSDescriptor;
14091
14457
  /***/ 8170
14092
14458
  (__unused_webpack_module, exports, __webpack_require__) {
14093
14459
 
14460
+ "use strict";
14094
14461
  var __webpack_unused_export__;
14095
14462
 
14096
14463
  /*
@@ -14251,6 +14618,7 @@ exports.MeshHiPSTile = MeshHiPSTile;
14251
14618
  /***/ 4322
14252
14619
  (__unused_webpack_module, exports) {
14253
14620
 
14621
+ "use strict";
14254
14622
  var __webpack_unused_export__;
14255
14623
 
14256
14624
  /*
@@ -14471,6 +14839,7 @@ exports.OBJMeshParser = OBJMeshParser;
14471
14839
  /***/ 8022
14472
14840
  (__unused_webpack_module, exports) {
14473
14841
 
14842
+ "use strict";
14474
14843
 
14475
14844
  Object.defineProperty(exports, "__esModule", ({ value: true }));
14476
14845
  exports.ObservationTrackTimeline = void 0;
@@ -14715,6 +15084,7 @@ function clamp01(value) {
14715
15084
  /***/ 5772
14716
15085
  (__unused_webpack_module, exports, __webpack_require__) {
14717
15086
 
15087
+ "use strict";
14718
15088
 
14719
15089
  var __importDefault = (this && this.__importDefault) || function (mod) {
14720
15090
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -15056,6 +15426,7 @@ function createMarkerColumns() {
15056
15426
  /***/ 5866
15057
15427
  (__unused_webpack_module, exports, __webpack_require__) {
15058
15428
 
15429
+ "use strict";
15059
15430
 
15060
15431
  Object.defineProperty(exports, "__esModule", ({ value: true }));
15061
15432
  exports.ObservationTrackViewerAdapter = exports.ObservationTrackTimeline = exports.footprintToRing = exports.createObservationTrackTimeline = void 0;
@@ -15072,6 +15443,7 @@ Object.defineProperty(exports, "ObservationTrackViewerAdapter", ({ enumerable: t
15072
15443
  /***/ 3603
15073
15444
  (__unused_webpack_module, exports, __webpack_require__) {
15074
15445
 
15446
+ "use strict";
15075
15447
 
15076
15448
  /*
15077
15449
  * AstroViewer
@@ -15303,6 +15675,7 @@ function normalizeLongitudeDeg(longitudeDeg) {
15303
15675
  /***/ 3102
15304
15676
  (__unused_webpack_module, exports, __webpack_require__) {
15305
15677
 
15678
+ "use strict";
15306
15679
 
15307
15680
  /*
15308
15681
  * AstroViewer
@@ -15506,6 +15879,7 @@ function normalizeLongitudeDeg(longitudeDeg) {
15506
15879
  /***/ 9022
15507
15880
  (__unused_webpack_module, exports, __webpack_require__) {
15508
15881
 
15882
+ "use strict";
15509
15883
 
15510
15884
  /*
15511
15885
  * AstroViewer
@@ -15573,6 +15947,7 @@ exports.TerraFootprintSetGL = TerraFootprintSetGL;
15573
15947
  /***/ 5781
15574
15948
  (__unused_webpack_module, exports, __webpack_require__) {
15575
15949
 
15950
+ "use strict";
15576
15951
 
15577
15952
  /*
15578
15953
  * AstroViewer
@@ -15598,6 +15973,7 @@ exports.TerraPointSetGL = TerraPointSetGL;
15598
15973
  /***/ 3665
15599
15974
  (__unused_webpack_module, exports, __webpack_require__) {
15600
15975
 
15976
+ "use strict";
15601
15977
 
15602
15978
  /*
15603
15979
  * AstroViewer
@@ -15786,6 +16162,7 @@ function normalizeLongitudeDeg(longitudeDeg) {
15786
16162
  /***/ 3559
15787
16163
  (__unused_webpack_module, exports, __webpack_require__) {
15788
16164
 
16165
+ "use strict";
15789
16166
 
15790
16167
  /*
15791
16168
  * AstroViewer
@@ -15903,6 +16280,7 @@ exports.CatalogueShaderProgram = CatalogueShaderProgram;
15903
16280
  /***/ 8909
15904
16281
  (__unused_webpack_module, exports, __webpack_require__) {
15905
16282
 
16283
+ "use strict";
15906
16284
 
15907
16285
  /*
15908
16286
  * AstroViewer
@@ -16012,6 +16390,7 @@ exports.FootprintShaderProgram = FootprintShaderProgram;
16012
16390
  /***/ 4707
16013
16391
  (__unused_webpack_module, exports) {
16014
16392
 
16393
+ "use strict";
16015
16394
  /*
16016
16395
  * AstroViewer
16017
16396
  * Copyright (C) Fabrizio Giordano
@@ -16058,6 +16437,7 @@ exports["default"] = GridShaderManager;
16058
16437
  /***/ 7786
16059
16438
  (__unused_webpack_module, exports, __webpack_require__) {
16060
16439
 
16440
+ "use strict";
16061
16441
 
16062
16442
  /*
16063
16443
  * AstroViewer
@@ -16088,7 +16468,7 @@ class HiPSShaderProgram {
16088
16468
  _UBO_colorMapVariableInfo = {
16089
16469
  r_palette: { index: 0, offset: 0 },
16090
16470
  g_palette: { index: 0, offset: 0 },
16091
- b_palette: { index: 0, offset: 0 }
16471
+ b_palette: { index: 0, offset: 0 },
16092
16472
  };
16093
16473
  gl_uniforms;
16094
16474
  gl_attributes;
@@ -16097,54 +16477,60 @@ class HiPSShaderProgram {
16097
16477
  constructor(webgl) {
16098
16478
  this._webgl = webgl;
16099
16479
  this.gl_uniforms = {
16100
- sampler: 'uSampler0',
16101
- factor: 'uFactor0',
16102
- m_perspective: 'uPMatrix',
16103
- m_model: 'uMMatrix',
16104
- m_view: 'uVMatrix',
16105
- colormapIdx: 'cmapIdx',
16106
- colormap_red: 'r',
16107
- colormap_green: 'g',
16108
- colormap_blue: 'b'
16480
+ sampler: "uSampler0",
16481
+ factor: "uFactor0",
16482
+ m_perspective: "uPMatrix",
16483
+ m_model: "uMMatrix",
16484
+ m_view: "uVMatrix",
16485
+ colormapIdx: "cmapIdx",
16486
+ colormap_red: "r",
16487
+ colormap_green: "g",
16488
+ colormap_blue: "b",
16489
+ textureMode: "uTextureMode",
16490
+ dataMin: "uDataMin",
16491
+ dataMax: "uDataMax",
16109
16492
  };
16110
16493
  this.gl_attributes = {
16111
- vertex_pos: 'aVertexPosition',
16112
- text_coords: 'aTextureCoord'
16494
+ vertex_pos: "aVertexPosition",
16495
+ text_coords: "aTextureCoord",
16113
16496
  };
16114
16497
  this.locations = {
16115
16498
  pMatrix: null,
16116
16499
  mMatrix: null,
16117
16500
  vMatrix: null,
16118
- sampler: null,
16119
- textureAlpha: null,
16501
+ samplers: new Array(8).fill(null),
16502
+ textureAlpha: new Array(8).fill(null),
16503
+ textureMode: new Array(8).fill(null),
16504
+ dataMin: new Array(8).fill(null),
16505
+ dataMax: new Array(8).fill(null),
16120
16506
  clorMapIdx: null,
16121
16507
  vertexPositionAttribute: -1,
16122
- textureCoordAttribute: -1
16508
+ textureCoordAttribute: -1,
16123
16509
  };
16124
16510
  }
16125
16511
  get shaderProgram() {
16126
16512
  const gl = this._webgl;
16127
16513
  if (!this._shaderProgram) {
16128
- // const gl = global.gl as GL
16129
- this._shaderProgram = gl.createProgram();
16130
- this.initShaders();
16514
+ const program = gl.createProgram();
16515
+ this._shaderProgram = program;
16516
+ this.initShaders(program);
16131
16517
  }
16132
- ;
16133
16518
  gl.useProgram(this._shaderProgram);
16134
16519
  return this._shaderProgram;
16135
16520
  }
16136
16521
  setRuntimeColorMap(colorMap) {
16137
16522
  this._runtimeColorMap = colorMap;
16138
16523
  }
16139
- initShaders() {
16140
- // const gl = global.gl as GL
16524
+ initShaders(program) {
16525
+ // const gl = global.gl
16141
16526
  const gl = this._webgl;
16142
16527
  const fragmentShaderStr = ShaderManager_js_1.default.hipsNativeFS();
16143
16528
  this._fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
16144
16529
  gl.shaderSource(this._fragmentShader, fragmentShaderStr);
16145
16530
  gl.compileShader(this._fragmentShader);
16146
16531
  if (!gl.getShaderParameter(this._fragmentShader, gl.COMPILE_STATUS)) {
16147
- alert(gl.getShaderInfoLog(this._fragmentShader) || 'Fragment shader compile error');
16532
+ alert(gl.getShaderInfoLog(this._fragmentShader) ||
16533
+ "Fragment shader compile error");
16148
16534
  return;
16149
16535
  }
16150
16536
  const vertexShaderStr = ShaderManager_js_1.default.hipsVS();
@@ -16152,43 +16538,44 @@ class HiPSShaderProgram {
16152
16538
  gl.shaderSource(this._vertexShader, vertexShaderStr);
16153
16539
  gl.compileShader(this._vertexShader);
16154
16540
  if (!gl.getShaderParameter(this._vertexShader, gl.COMPILE_STATUS)) {
16155
- alert(gl.getShaderInfoLog(this._vertexShader) || 'Vertex shader compile error');
16541
+ alert(gl.getShaderInfoLog(this._vertexShader) ||
16542
+ "Vertex shader compile error");
16156
16543
  return;
16157
16544
  }
16158
- gl.attachShader(this._shaderProgram, this._vertexShader);
16159
- gl.attachShader(this._shaderProgram, this._fragmentShader);
16160
- gl.linkProgram(this._shaderProgram);
16161
- if (!gl.getProgramParameter(this._shaderProgram, gl.LINK_STATUS)) {
16162
- alert('Could not initialise shaders');
16545
+ gl.attachShader(program, this._vertexShader);
16546
+ gl.attachShader(program, this._fragmentShader);
16547
+ gl.linkProgram(program);
16548
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
16549
+ alert("Could not initialise shaders");
16163
16550
  }
16164
16551
  }
16165
16552
  enableProgram() {
16166
- // (global.gl as GL).useProgram(this._shaderProgram as WebGLProgram)
16553
+ // (global.gl).useProgram(this._shaderProgram)
16167
16554
  this._webgl.useProgram(this.shaderProgram);
16168
16555
  }
16169
16556
  setGrayscaleShader() {
16170
- // const gl = global.gl as GL
16557
+ // const gl = global.gl
16171
16558
  const gl = this._webgl;
16172
16559
  gl.detachShader(this.shaderProgram, this._fragmentShader);
16173
16560
  const fragmentShaderStr = ShaderManager_js_1.default.hipsGrayscaleFS();
16174
16561
  this.changeFSShader(fragmentShaderStr);
16175
16562
  }
16176
16563
  setNativeShader() {
16177
- // const gl = global.gl as GL
16564
+ // const gl = global.gl
16178
16565
  const gl = this._webgl;
16179
16566
  gl.detachShader(this.shaderProgram, this._fragmentShader);
16180
16567
  const fragmentShaderStr = ShaderManager_js_1.default.hipsNativeFS();
16181
16568
  this.changeFSShader(fragmentShaderStr);
16182
16569
  }
16183
16570
  setColorMapShader() {
16184
- // const gl = global.gl as GL
16571
+ // const gl = global.gl
16185
16572
  const gl = this._webgl;
16186
16573
  // Swap fragment shader
16187
16574
  gl.detachShader(this.shaderProgram, this._fragmentShader);
16188
16575
  const fragmentShaderStr = ShaderManager_js_1.default.hipsColorMapFS();
16189
16576
  this.changeFSShader(fragmentShaderStr);
16190
16577
  // UBO discovery for the "colormap" block
16191
- const blockIndex = gl.getUniformBlockIndex(this.shaderProgram, 'colormap');
16578
+ const blockIndex = gl.getUniformBlockIndex(this.shaderProgram, "colormap");
16192
16579
  // INVALID_INDEX == 0xFFFFFFFF in WebGL2
16193
16580
  if (blockIndex === gl.INVALID_INDEX) {
16194
16581
  console.warn('HiPSShaderProgram: uniform block "colormap" not found in hipsColorMapFS()');
@@ -16198,11 +16585,11 @@ class HiPSShaderProgram {
16198
16585
  }
16199
16586
  this._colorMapBlockIndex = blockIndex;
16200
16587
  // const blockSize = gl.getActiveUniformBlockParameter(
16201
- // this.shaderProgram as WebGLProgram,
16588
+ // this.shaderProgram,
16202
16589
  // blockIndex,
16203
16590
  // gl.UNIFORM_BLOCK_DATA_SIZE
16204
16591
  // ) as number
16205
- const uboVariableNames = ['r_palette', 'g_palette', 'b_palette'];
16592
+ const uboVariableNames = ["r_palette", "g_palette", "b_palette"];
16206
16593
  const uboVariableIndices = gl.getUniformIndices(this.shaderProgram, uboVariableNames);
16207
16594
  const uboVariableOffsets = gl.getActiveUniforms(this.shaderProgram, uboVariableIndices, gl.UNIFORM_OFFSET);
16208
16595
  // Create buffer only once
@@ -16219,49 +16606,80 @@ class HiPSShaderProgram {
16219
16606
  uboVariableNames.forEach((name, index) => {
16220
16607
  this._UBO_colorMapVariableInfo[name] = {
16221
16608
  index: uboVariableIndices[index],
16222
- offset: uboVariableOffsets[index]
16609
+ offset: uboVariableOffsets[index],
16223
16610
  };
16224
16611
  });
16225
16612
  }
16226
16613
  changeFSShader(fragmentShaderStr) {
16227
- // const gl = global.gl as GL
16614
+ // const gl = global.gl
16228
16615
  const gl = this._webgl;
16229
16616
  this._fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
16230
16617
  gl.shaderSource(this._fragmentShader, fragmentShaderStr);
16231
16618
  gl.compileShader(this._fragmentShader);
16232
16619
  if (!gl.getShaderParameter(this._fragmentShader, gl.COMPILE_STATUS)) {
16233
- alert(gl.getShaderInfoLog(this._fragmentShader) || 'Fragment shader compile error');
16620
+ alert(gl.getShaderInfoLog(this._fragmentShader) ||
16621
+ "Fragment shader compile error");
16234
16622
  return;
16235
16623
  }
16236
16624
  gl.attachShader(this.shaderProgram, this._fragmentShader);
16237
16625
  gl.linkProgram(this.shaderProgram);
16238
16626
  if (!gl.getProgramParameter(this.shaderProgram, gl.LINK_STATUS)) {
16239
- alert('Could not initialise shaders');
16627
+ alert("Could not initialise shaders");
16240
16628
  }
16241
16629
  gl.useProgram(this.shaderProgram);
16242
16630
  }
16631
+ setTextureDataMode(samplerIndex, fits, min, max) {
16632
+ if (samplerIndex < 0 || samplerIndex >= 8) {
16633
+ throw new Error(`Invalid HiPS sampler index: ${samplerIndex}`);
16634
+ }
16635
+ const gl = this._webgl;
16636
+ const modeLocation = this.locations.textureMode[samplerIndex];
16637
+ if (modeLocation) {
16638
+ gl.uniform1i(modeLocation, fits ? 1 : 0);
16639
+ }
16640
+ if (!fits) {
16641
+ return;
16642
+ }
16643
+ if (min === undefined ||
16644
+ max === undefined ||
16645
+ !Number.isFinite(min) ||
16646
+ !Number.isFinite(max) ||
16647
+ max <= min) {
16648
+ throw new Error("Invalid FITS display range.");
16649
+ }
16650
+ const minLocation = this.locations.dataMin[samplerIndex];
16651
+ const maxLocation = this.locations.dataMax[samplerIndex];
16652
+ if (minLocation) {
16653
+ gl.uniform1f(minLocation, min);
16654
+ }
16655
+ if (maxLocation) {
16656
+ gl.uniform1f(maxLocation, max);
16657
+ }
16658
+ }
16243
16659
  enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx) {
16244
- // const gl = global.gl as GL
16660
+ // const gl = global.gl
16245
16661
  const gl = this._webgl;
16246
16662
  gl.useProgram(this.shaderProgram);
16247
16663
  this.locations.pMatrix = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.m_perspective);
16248
16664
  this.locations.mMatrix = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.m_model);
16249
16665
  this.locations.vMatrix = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.m_view);
16250
- this.locations.sampler = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.sampler);
16251
- this.locations.textureAlpha = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.factor);
16252
16666
  this.locations.clorMapIdx = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.colormapIdx);
16253
- // NEW
16254
- // if (this.locations.clorMapIdx) {
16255
- gl.uniform1i(this.locations.clorMapIdx, colorMapIdx);
16256
- // }
16257
- // Make sampler explicit: we always use TEXTURE0 in your draw code
16258
- if (this.locations.sampler) {
16259
- gl.uniform1i(this.locations.sampler, 0);
16667
+ for (let i = 0; i < 8; i++) {
16668
+ this.locations.samplers[i] = gl.getUniformLocation(this.shaderProgram, `uSampler${i}`);
16669
+ this.locations.textureAlpha[i] = gl.getUniformLocation(this.shaderProgram, `uFactor${i}`);
16670
+ this.locations.textureMode[i] = gl.getUniformLocation(this.shaderProgram, `uTextureMode${i}`);
16671
+ this.locations.dataMin[i] = gl.getUniformLocation(this.shaderProgram, `uDataMin${i}`);
16672
+ this.locations.dataMax[i] = gl.getUniformLocation(this.shaderProgram, `uDataMax${i}`);
16673
+ if (this.locations.samplers[i]) {
16674
+ gl.uniform1i(this.locations.samplers[i], i);
16675
+ }
16260
16676
  }
16261
- // END NEW
16677
+ gl.uniform1i(this.locations.clorMapIdx, colorMapIdx);
16262
16678
  this.locations.vertexPositionAttribute = gl.getAttribLocation(this.shaderProgram, this.gl_attributes.vertex_pos);
16263
16679
  this.locations.textureCoordAttribute = gl.getAttribLocation(this.shaderProgram, this.gl_attributes.text_coords);
16264
- if (colorMapIdx >= 2 && this._UBO_colorMapBuffer && this._colorMapBlockIndex !== null) {
16680
+ if (colorMapIdx >= 2 &&
16681
+ this._UBO_colorMapBuffer &&
16682
+ this._colorMapBlockIndex !== null) {
16265
16683
  gl.uniformBlockBinding(this.shaderProgram, this._colorMapBlockIndex, 0);
16266
16684
  gl.bindBuffer(gl.UNIFORM_BUFFER, this._UBO_colorMapBuffer);
16267
16685
  let currentColorMap;
@@ -16338,6 +16756,7 @@ exports.HiPSShaderProgram = HiPSShaderProgram;
16338
16756
  /***/ 2257
16339
16757
  (__unused_webpack_module, exports) {
16340
16758
 
16759
+ "use strict";
16341
16760
  var __webpack_unused_export__;
16342
16761
 
16343
16762
  /*
@@ -16454,6 +16873,7 @@ exports.MeshHiPSShaderProgram = MeshHiPSShaderProgram;
16454
16873
  /***/ 5947
16455
16874
  (__unused_webpack_module, exports) {
16456
16875
 
16876
+ "use strict";
16457
16877
 
16458
16878
  /*
16459
16879
  * AstroViewer
@@ -16634,15 +17054,6 @@ class ShaderManager {
16634
17054
 
16635
17055
  in vec2 vTextureCoord;
16636
17056
 
16637
- uniform sampler2D uSampler0;
16638
- uniform sampler2D uSampler1;
16639
- uniform sampler2D uSampler2;
16640
- uniform sampler2D uSampler3;
16641
- uniform sampler2D uSampler4;
16642
- uniform sampler2D uSampler5;
16643
- uniform sampler2D uSampler6;
16644
- uniform sampler2D uSampler7;
16645
-
16646
17057
  uniform float uFactor0;
16647
17058
  uniform float uFactor1;
16648
17059
  uniform float uFactor2;
@@ -16652,23 +17063,53 @@ class ShaderManager {
16652
17063
  uniform float uFactor6;
16653
17064
  uniform float uFactor7;
16654
17065
 
17066
+ ${ShaderManager.hipsSamplersGLSL()}
17067
+
16655
17068
  out vec4 fragColor;
16656
17069
 
16657
17070
  void main() {
16658
17071
  vec3 finalColor = vec3(0.0);
16659
17072
 
16660
- if (uFactor0 >= 0.0){
16661
- vec4 mycolor;
16662
- #if __VERSION__ > 120
16663
- vec4 color0 = texture(uSampler0, vTextureCoord);
16664
- #else
16665
- vec4 color0 = texture2D(uSampler0, vTextureCoord);
16666
- #endif
16667
- mycolor = color0;
16668
- finalColor += mycolor.rgb * uFactor0;
16669
- } else if (uFactor7 >= 0.0){
16670
- finalColor = vec3(1.0, 0.0, 0.0);
17073
+ if (uFactor0 >= 0.0) {
17074
+ finalColor +=
17075
+ sampleHiPSTexture0(vTextureCoord).rgb * uFactor0;
17076
+ }
17077
+
17078
+ if (uFactor1 >= 0.0) {
17079
+ finalColor +=
17080
+ sampleHiPSTexture1(vTextureCoord).rgb * uFactor1;
17081
+ }
17082
+
17083
+ if (uFactor2 >= 0.0) {
17084
+ finalColor +=
17085
+ sampleHiPSTexture2(vTextureCoord).rgb * uFactor2;
16671
17086
  }
17087
+
17088
+ if (uFactor3 >= 0.0) {
17089
+ finalColor +=
17090
+ sampleHiPSTexture3(vTextureCoord).rgb * uFactor3;
17091
+ }
17092
+
17093
+ if (uFactor4 >= 0.0) {
17094
+ finalColor +=
17095
+ sampleHiPSTexture4(vTextureCoord).rgb * uFactor4;
17096
+ }
17097
+
17098
+ if (uFactor5 >= 0.0) {
17099
+ finalColor +=
17100
+ sampleHiPSTexture5(vTextureCoord).rgb * uFactor5;
17101
+ }
17102
+
17103
+ if (uFactor6 >= 0.0) {
17104
+ finalColor +=
17105
+ sampleHiPSTexture6(vTextureCoord).rgb * uFactor6;
17106
+ }
17107
+
17108
+ if (uFactor7 >= 0.0) {
17109
+ finalColor +=
17110
+ sampleHiPSTexture7(vTextureCoord).rgb * uFactor7;
17111
+ }
17112
+
16672
17113
  fragColor = vec4(finalColor, 1.0);
16673
17114
  }`;
16674
17115
  }
@@ -16678,15 +17119,6 @@ class ShaderManager {
16678
17119
 
16679
17120
  in vec2 vTextureCoord;
16680
17121
 
16681
- uniform sampler2D uSampler0;
16682
- uniform sampler2D uSampler1;
16683
- uniform sampler2D uSampler2;
16684
- uniform sampler2D uSampler3;
16685
- uniform sampler2D uSampler4;
16686
- uniform sampler2D uSampler5;
16687
- uniform sampler2D uSampler6;
16688
- uniform sampler2D uSampler7;
16689
-
16690
17122
  uniform float uFactor0;
16691
17123
  uniform float uFactor1;
16692
17124
  uniform float uFactor2;
@@ -16696,76 +17128,61 @@ class ShaderManager {
16696
17128
  uniform float uFactor6;
16697
17129
  uniform float uFactor7;
16698
17130
 
17131
+ ${ShaderManager.hipsSamplersGLSL()}
17132
+
16699
17133
  out vec4 fragColor;
16700
17134
 
16701
17135
  void main() {
16702
17136
  vec3 finalColor = vec3(0.0);
16703
17137
 
16704
- if (uFactor0 >= 0.0){
16705
- #if __VERSION__ > 120
16706
- vec4 color0 = texture(uSampler0, vTextureCoord);
16707
- #else
16708
- vec4 color0 = texture2D(uSampler0, vTextureCoord);
16709
- #endif
16710
- float gray = 0.21 * color0.r + 0.71 * color0.g + 0.07 * color0.b;
16711
- finalColor = color0.rgb * (1.0 - uFactor0) + vec3(gray) * uFactor0;
17138
+ if (uFactor0 >= 0.0) {
17139
+ vec4 color0 = sampleHiPSTexture0(vTextureCoord);
17140
+
17141
+ float gray =
17142
+ 0.21 * color0.r +
17143
+ 0.71 * color0.g +
17144
+ 0.07 * color0.b;
17145
+
17146
+ finalColor =
17147
+ color0.rgb * (1.0 - uFactor0) +
17148
+ vec3(gray) * uFactor0;
16712
17149
  }
16713
- if (uFactor1 >= 0.0){
16714
- #if __VERSION__ > 120
16715
- vec4 color1 = texture(uSampler1, vTextureCoord);
16716
- #else
16717
- vec4 color1 = texture2D(uSampler1, vTextureCoord);
16718
- #endif
17150
+
17151
+ if (uFactor1 >= 0.0) {
17152
+ vec4 color1 = sampleHiPSTexture1(vTextureCoord);
16719
17153
  finalColor += color1.rgb * uFactor1;
16720
17154
  }
16721
- if (uFactor2 >= 0.0){
16722
- #if __VERSION__ > 120
16723
- vec4 color2 = texture(uSampler2, vTextureCoord);
16724
- #else
16725
- vec4 color2 = texture2D(uSampler2, vTextureCoord);
16726
- #endif
17155
+
17156
+ if (uFactor2 >= 0.0) {
17157
+ vec4 color2 = sampleHiPSTexture2(vTextureCoord);
16727
17158
  finalColor += color2.rgb * uFactor2;
16728
17159
  }
16729
- if (uFactor3 >= 0.0){
16730
- #if __VERSION__ > 120
16731
- vec4 color3 = texture(uSampler3, vTextureCoord);
16732
- #else
16733
- vec4 color3 = texture2D(uSampler3, vTextureCoord);
16734
- #endif
17160
+
17161
+ if (uFactor3 >= 0.0) {
17162
+ vec4 color3 = sampleHiPSTexture3(vTextureCoord);
16735
17163
  finalColor += color3.rgb * uFactor3;
16736
17164
  }
16737
- if (uFactor4 >= 0.0){
16738
- #if __VERSION__ > 120
16739
- vec4 color4 = texture(uSampler4, vTextureCoord);
16740
- #else
16741
- vec4 color4 = texture2D(uSampler4, vTextureCoord);
16742
- #endif
17165
+
17166
+ if (uFactor4 >= 0.0) {
17167
+ vec4 color4 = sampleHiPSTexture4(vTextureCoord);
16743
17168
  finalColor += color4.rgb * uFactor4;
16744
17169
  }
16745
- if (uFactor5 >= 0.0){
16746
- #if __VERSION__ > 120
16747
- vec4 color5 = texture(uSampler5, vTextureCoord);
16748
- #else
16749
- vec4 color5 = texture2D(uSampler5, vTextureCoord);
16750
- #endif
17170
+
17171
+ if (uFactor5 >= 0.0) {
17172
+ vec4 color5 = sampleHiPSTexture5(vTextureCoord);
16751
17173
  finalColor += color5.rgb * uFactor5;
16752
17174
  }
16753
- if (uFactor6 >= 0.0){
16754
- #if __VERSION__ > 120
16755
- vec4 color6 = texture(uSampler6, vTextureCoord);
16756
- #else
16757
- vec4 color6 = texture2D(uSampler6, vTextureCoord);
16758
- #endif
17175
+
17176
+ if (uFactor6 >= 0.0) {
17177
+ vec4 color6 = sampleHiPSTexture6(vTextureCoord);
16759
17178
  finalColor += color6.rgb * uFactor6;
16760
17179
  }
16761
- if (uFactor7 >= 0.0){
16762
- #if __VERSION__ > 120
16763
- vec4 color7 = texture(uSampler7, vTextureCoord);
16764
- #else
16765
- vec4 color7 = texture2D(uSampler7, vTextureCoord);
16766
- #endif
17180
+
17181
+ if (uFactor7 >= 0.0) {
17182
+ vec4 color7 = sampleHiPSTexture7(vTextureCoord);
16767
17183
  finalColor += color7.rgb * uFactor7;
16768
17184
  }
17185
+
16769
17186
  fragColor = vec4(finalColor, 1.0);
16770
17187
  }`;
16771
17188
  }
@@ -16775,38 +17192,140 @@ class ShaderManager {
16775
17192
 
16776
17193
  in vec2 vTextureCoord;
16777
17194
 
16778
- // UBO
16779
17195
  layout (std140) uniform colormap {
16780
17196
  float r_palette[256];
16781
17197
  float g_palette[256];
16782
17198
  float b_palette[256];
16783
17199
  };
16784
17200
 
16785
- uniform sampler2D uSampler0;
16786
17201
  uniform float uFactor0;
17202
+ uniform float uFactor1;
17203
+ uniform float uFactor2;
17204
+ uniform float uFactor3;
17205
+ uniform float uFactor4;
17206
+ uniform float uFactor5;
17207
+ uniform float uFactor6;
17208
+ uniform float uFactor7;
17209
+
17210
+ ${ShaderManager.hipsSamplersGLSL()}
16787
17211
 
16788
17212
  out vec4 fragColor;
16789
17213
 
16790
- void main() {
16791
- #if __VERSION__ > 120
16792
- vec4 color0 = texture(uSampler0, vTextureCoord);
16793
- #else
16794
- vec4 color0 = texture2D(uSampler0, vTextureCoord);
16795
- #endif
17214
+ vec3 applyColorMap(vec4 color) {
17215
+ int x = int(clamp(color.r, 0.0, 1.0) * 255.0);
17216
+ int y = int(clamp(color.g, 0.0, 1.0) * 255.0);
17217
+ int z = int(clamp(color.b, 0.0, 1.0) * 255.0);
16796
17218
 
16797
- int x = int(color0.r * 255.0);
16798
17219
  float px = r_palette[x] / 256.0;
16799
-
16800
- int y = int(color0.g * 255.0);
16801
17220
  float py = g_palette[y] / 256.0;
16802
-
16803
- int z = int(color0.b * 255.0);
16804
17221
  float pz = b_palette[z] / 256.0;
16805
17222
 
16806
- // uFactor0 reserved for future blending if needed
16807
- fragColor = vec4(px, py, pz, 1.0);
17223
+ return vec3(px, py, pz);
17224
+ }
17225
+
17226
+ void main() {
17227
+ vec3 finalColor = vec3(0.0);
17228
+
17229
+ if (uFactor0 >= 0.0) {
17230
+ finalColor +=
17231
+ applyColorMap(
17232
+ sampleHiPSTexture0(vTextureCoord)
17233
+ ) * uFactor0;
17234
+ }
17235
+
17236
+ if (uFactor1 >= 0.0) {
17237
+ finalColor +=
17238
+ applyColorMap(
17239
+ sampleHiPSTexture1(vTextureCoord)
17240
+ ) * uFactor1;
17241
+ }
17242
+
17243
+ if (uFactor2 >= 0.0) {
17244
+ finalColor +=
17245
+ applyColorMap(
17246
+ sampleHiPSTexture2(vTextureCoord)
17247
+ ) * uFactor2;
17248
+ }
17249
+
17250
+ if (uFactor3 >= 0.0) {
17251
+ finalColor +=
17252
+ applyColorMap(
17253
+ sampleHiPSTexture3(vTextureCoord)
17254
+ ) * uFactor3;
17255
+ }
17256
+
17257
+ if (uFactor4 >= 0.0) {
17258
+ finalColor +=
17259
+ applyColorMap(
17260
+ sampleHiPSTexture4(vTextureCoord)
17261
+ ) * uFactor4;
17262
+ }
17263
+
17264
+ if (uFactor5 >= 0.0) {
17265
+ finalColor +=
17266
+ applyColorMap(
17267
+ sampleHiPSTexture5(vTextureCoord)
17268
+ ) * uFactor5;
17269
+ }
17270
+
17271
+ if (uFactor6 >= 0.0) {
17272
+ finalColor +=
17273
+ applyColorMap(
17274
+ sampleHiPSTexture6(vTextureCoord)
17275
+ ) * uFactor6;
17276
+ }
17277
+
17278
+ if (uFactor7 >= 0.0) {
17279
+ finalColor +=
17280
+ applyColorMap(
17281
+ sampleHiPSTexture7(vTextureCoord)
17282
+ ) * uFactor7;
17283
+ }
17284
+
17285
+ fragColor = vec4(finalColor, 1.0);
16808
17286
  }`;
16809
17287
  }
17288
+ static hipsSamplerGLSL(index) {
17289
+ return `
17290
+ uniform sampler2D uSampler${index};
17291
+ uniform int uTextureMode${index};
17292
+ uniform float uDataMin${index};
17293
+ uniform float uDataMax${index};
17294
+
17295
+ vec4 sampleHiPSTexture${index}(vec2 uv) {
17296
+ vec4 color = texture(uSampler${index}, uv);
17297
+
17298
+ // JPG / PNG
17299
+ if (uTextureMode${index} == 0) {
17300
+ return color;
17301
+ }
17302
+
17303
+ // FITS physical value stored in red channel
17304
+ float value = color.r;
17305
+
17306
+ if (isnan(value)) {
17307
+ discard;
17308
+ }
17309
+
17310
+ float normalized = clamp(
17311
+ (value - uDataMin${index}) /
17312
+ (uDataMax${index} - uDataMin${index}),
17313
+ 0.0,
17314
+ 1.0
17315
+ );
17316
+
17317
+ return vec4(
17318
+ normalized,
17319
+ normalized,
17320
+ normalized,
17321
+ 1.0
17322
+ );
17323
+ }
17324
+ `;
17325
+ }
17326
+ static hipsSamplersGLSL() {
17327
+ return Array.from({ length: 8 }, (_, index) => ShaderManager.hipsSamplerGLSL(index)).join("\n");
17328
+ }
16810
17329
  }
16811
17330
  exports["default"] = ShaderManager;
16812
17331
 
@@ -16816,6 +17335,7 @@ exports["default"] = ShaderManager;
16816
17335
  /***/ 149
16817
17336
  (__unused_webpack_module, exports, __webpack_require__) {
16818
17337
 
17338
+ "use strict";
16819
17339
  var __webpack_unused_export__;
16820
17340
 
16821
17341
  /*
@@ -17039,6 +17559,7 @@ exports.XYZShaderProgram = XYZShaderProgram;
17039
17559
  /***/ 8145
17040
17560
  (__unused_webpack_module, exports) {
17041
17561
 
17562
+ "use strict";
17042
17563
 
17043
17564
  /*
17044
17565
  * AstroViewer
@@ -17071,6 +17592,7 @@ var CoordsType;
17071
17592
  /***/ 8083
17072
17593
  (__unused_webpack_module, exports, __webpack_require__) {
17073
17594
 
17595
+ "use strict";
17074
17596
  /*
17075
17597
  * AstroViewer
17076
17598
  * Copyright (C) Fabrizio Giordano
@@ -17310,6 +17832,7 @@ exports.FoVUtils = FoVUtils;
17310
17832
  /***/ 8755
17311
17833
  (__unused_webpack_module, exports, __webpack_require__) {
17312
17834
 
17835
+ "use strict";
17313
17836
 
17314
17837
  /*
17315
17838
  * AstroViewer
@@ -17429,6 +17952,7 @@ exports["default"] = GeoJSONParser;
17429
17952
  /***/ 2930
17430
17953
  (__unused_webpack_module, exports, __webpack_require__) {
17431
17954
 
17955
+ "use strict";
17432
17956
 
17433
17957
  /*
17434
17958
  * AstroViewer
@@ -17717,6 +18241,7 @@ exports["default"] = GeomUtils;
17717
18241
  /***/ 4396
17718
18242
  (__unused_webpack_module, exports, __webpack_require__) {
17719
18243
 
18244
+ "use strict";
17720
18245
 
17721
18246
  /*
17722
18247
  * AstroViewer
@@ -17832,6 +18357,7 @@ exports["default"] = MouseHelper;
17832
18357
  /***/ 9685
17833
18358
  (__unused_webpack_module, exports, __webpack_require__) {
17834
18359
 
18360
+ "use strict";
17835
18361
  var __webpack_unused_export__;
17836
18362
 
17837
18363
  /*
@@ -17893,6 +18419,7 @@ exports.PerspectiveMatrixManager = PerspectiveMatrixManager;
17893
18419
  /***/ 4639
17894
18420
  (__unused_webpack_module, exports, __webpack_require__) {
17895
18421
 
18422
+ "use strict";
17896
18423
  /*
17897
18424
  * AstroViewer
17898
18425
  * Copyright (C) Fabrizio Giordano
@@ -18022,6 +18549,7 @@ exports["default"] = RayPickingUtils;
18022
18549
  /***/ 9665
18023
18550
  (__unused_webpack_module, exports, __webpack_require__) {
18024
18551
 
18552
+ "use strict";
18025
18553
 
18026
18554
  /*
18027
18555
  * AstroViewer
@@ -18145,6 +18673,7 @@ exports["default"] = STCSParser;
18145
18673
  /***/ 7930
18146
18674
  (__unused_webpack_module, exports, __webpack_require__) {
18147
18675
 
18676
+ "use strict";
18148
18677
  var __webpack_unused_export__;
18149
18678
 
18150
18679
  /*
@@ -18250,6 +18779,7 @@ function decDegToDMS(decDeg) {
18250
18779
  /***/ 2166
18251
18780
  (__unused_webpack_module, exports, __webpack_require__) {
18252
18781
 
18782
+ "use strict";
18253
18783
  /*
18254
18784
  * AstroViewer
18255
18785
  * Copyright (C) Fabrizio Giordano
@@ -18477,11 +19007,19 @@ class XYZRayPickingUtils {
18477
19007
  exports["default"] = XYZRayPickingUtils;
18478
19008
 
18479
19009
 
19010
+ /***/ },
19011
+
19012
+ /***/ 7223
19013
+ () {
19014
+
19015
+ /* (ignored) */
19016
+
18480
19017
  /***/ },
18481
19018
 
18482
19019
  /***/ 4851
18483
19020
  (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
18484
19021
 
19022
+ "use strict";
18485
19023
 
18486
19024
  // EXPORTS
18487
19025
  __webpack_require__.d(__webpack_exports__, {
@@ -19275,76 +19813,1887 @@ function findCircleThroughTwoPoints(points, q1, q2) {
19275
19813
 
19276
19814
 
19277
19815
 
19278
- /***/ }
19816
+ /***/ },
19279
19817
 
19280
- /******/ });
19281
- /************************************************************************/
19282
- /******/ // The module cache
19283
- /******/ const __webpack_module_cache__ = {};
19284
- /******/
19285
- /******/ // The require function
19286
- /******/ function __webpack_require__(moduleId) {
19287
- /******/ // Check if module is in cache
19288
- /******/ const cachedModule = __webpack_module_cache__[moduleId];
19289
- /******/ if (cachedModule !== undefined) {
19290
- /******/ return cachedModule.exports;
19291
- /******/ }
19292
- /******/ // Create a new module (and put it into the cache)
19293
- /******/ const module = __webpack_module_cache__[moduleId] = {
19294
- /******/ // no module.id needed
19295
- /******/ // no module.loaded needed
19296
- /******/ exports: {}
19297
- /******/ };
19298
- /******/
19299
- /******/ // Execute the module function
19300
- /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
19301
- /******/
19302
- /******/ // Return the exports of the module
19303
- /******/ return module.exports;
19304
- /******/ }
19305
- /******/
19306
- /************************************************************************/
19307
- /******/ /* webpack/runtime/define property getters */
19308
- /******/ (() => {
19309
- /******/ // define getter/value functions for harmony exports
19310
- /******/ __webpack_require__.d = (exports, definition) => {
19311
- /******/ if(Array.isArray(definition)) {
19312
- /******/ var i = 0;
19313
- /******/ while(i < definition.length) {
19314
- /******/ var key = definition[i++];
19315
- /******/ var binding = definition[i++];
19316
- /******/ if(!__webpack_require__.o(exports, key)) {
19317
- /******/ if(binding === 0) {
19318
- /******/ Object.defineProperty(exports, key, { enumerable: true, value: definition[i++] });
19319
- /******/ } else {
19320
- /******/ Object.defineProperty(exports, key, { enumerable: true, get: binding });
19321
- /******/ }
19322
- /******/ } else if(binding === 0) { i++; }
19323
- /******/ }
19324
- /******/ } else {
19325
- /******/ for(var key in definition) {
19326
- /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
19327
- /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
19328
- /******/ }
19329
- /******/ }
19330
- /******/ }
19331
- /******/ };
19332
- /******/ })();
19333
- /******/
19334
- /******/ /* webpack/runtime/hasOwnProperty shorthand */
19335
- /******/ (() => {
19336
- /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
19337
- /******/ })();
19338
- /******/
19339
- /******/ /* webpack/runtime/make namespace object */
19340
- /******/ (() => {
19341
- /******/ // define __esModule on exports
19342
- /******/ __webpack_require__.r = (exports) => {
19343
- /******/ if(Symbol.toStringTag) {
19344
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
19345
- /******/ }
19346
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
19347
- /******/ };
19818
+ /***/ 1677
19819
+ (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
19820
+
19821
+ "use strict";
19822
+
19823
+ // EXPORTS
19824
+ __webpack_require__.d(__webpack_exports__, {
19825
+ FITSHeaderManager: () => (/* reexport */ FITSHeaderManager),
19826
+ FITSParser: () => (/* reexport */ FITSParser)
19827
+ });
19828
+
19829
+ // UNUSED EXPORTS: AsciiTableHDU, BinaryTableHDU, FITSFile, FITSHDU, FITSHeaderItem, FITSWriter, ImageHDU, ParseHeader, ParsePayload, PrimaryHDU
19830
+
19831
+ ;// ./node_modules/jsfitsio/lib-esm/model/FITSHeaderItem.js
19832
+ /**
19833
+ * Summary. (bla bla bla)
19834
+ *
19835
+ * Description. (bla bla bla)
19836
+ *
19837
+ * @link github https://github.com/fab77/FITSParser
19838
+ * @author Fabrizio Giordano <fabriziogiordano77@gmail.com>
19839
+ */
19840
+ class FITSHeaderItem {
19841
+ _key = "";
19842
+ _value = "";
19843
+ _comment = "";
19844
+ constructor(key, value, comment) {
19845
+ this._key = key;
19846
+ this._value = value;
19847
+ this._comment = comment;
19848
+ }
19849
+ get key() {
19850
+ return this._key;
19851
+ }
19852
+ get comment() {
19853
+ return this._comment;
19854
+ }
19855
+ get value() {
19856
+ return this._value;
19857
+ }
19858
+ }
19859
+ //# sourceMappingURL=FITSHeaderItem.js.map
19860
+ ;// ./node_modules/jsfitsio/lib-esm/model/FITSHeaderManager.js
19861
+
19862
+ class FITSHeaderManager {
19863
+ static SIMPLE = "SIMPLE";
19864
+ static BITPIX = "BITPIX";
19865
+ static BZERO = "BZERO";
19866
+ static BSCALE = "BSCALE";
19867
+ static BLANK = "BLANK";
19868
+ static NAXIS = "NAXIS";
19869
+ static NAXIS1 = "NAXIS1";
19870
+ static NAXIS2 = "NAXIS2";
19871
+ static DATAMIN = "DATAMIN";
19872
+ static DATAMAX = "DATAMAX";
19873
+ static CRVAL1 = "CRVAL1";
19874
+ static CRVAL2 = "CRVAL2";
19875
+ static CTYPE1 = "CTYPE1";
19876
+ static CTYPE2 = "CTYPE2";
19877
+ static CRPIX1 = "CRPIX1";
19878
+ static CRPIX2 = "CRPIX2";
19879
+ static ORIGIN = "ORIGIN";
19880
+ static COMMENT = "COMMENT";
19881
+ static XTENSION = "XTENSION";
19882
+ static PCOUNT = "PCOUNT";
19883
+ static GCOUNT = "GCOUNT";
19884
+ static TFIELDS = "TFIELDS";
19885
+ static TFORM = "TFORM";
19886
+ static TTYPE = "TTYPE";
19887
+ static TUNIT = "TUNIT";
19888
+ static TSCAL = "TSCAL";
19889
+ static TZERO = "TZERO";
19890
+ static TNULL = "TNULL";
19891
+ static TBCOL = "TBCOL";
19892
+ items = [];
19893
+ constructor(initializeDefaults = true) {
19894
+ if (!initializeDefaults) {
19895
+ return;
19896
+ }
19897
+ this.items[0] = new FITSHeaderItem(FITSHeaderManager.SIMPLE, "T", "");
19898
+ this.items[1] = new FITSHeaderItem(FITSHeaderManager.BITPIX, "", "");
19899
+ this.items[2] = new FITSHeaderItem(FITSHeaderManager.NAXIS, 2, "");
19900
+ this.items[3] = new FITSHeaderItem(FITSHeaderManager.NAXIS1, "", "");
19901
+ this.items[4] = new FITSHeaderItem(FITSHeaderManager.NAXIS2, "", "");
19902
+ }
19903
+ // insert(item: FITSHeaderItem, position?: number): void {
19904
+ insert(item) {
19905
+ if (item.key === FITSHeaderManager.SIMPLE) {
19906
+ // this.items.splice(0, 0, item);
19907
+ this.items[0] = item;
19908
+ }
19909
+ else if (item.key === FITSHeaderManager.BITPIX) {
19910
+ // this.items.splice(1, 0, item);
19911
+ this.items[1] = item;
19912
+ }
19913
+ else if (item.key === FITSHeaderManager.NAXIS) {
19914
+ // this.items.splice(2, 0, item);
19915
+ this.items[2] = item;
19916
+ }
19917
+ else if (item.key === FITSHeaderManager.NAXIS1) {
19918
+ // this.items.splice(3, 0, item);
19919
+ this.items[3] = item;
19920
+ }
19921
+ else if (item.key === FITSHeaderManager.NAXIS2) {
19922
+ // this.items.splice(4, 0, item);
19923
+ this.items[4] = item;
19924
+ }
19925
+ else {
19926
+ this.items.push(item);
19927
+ }
19928
+ // if (position !== undefined && position >= 0 && position <= this.items.length) {
19929
+ // this.items.splice(position, 0, item);
19930
+ // } else {
19931
+ // this.items.push(item);
19932
+ // }
19933
+ }
19934
+ getItems() {
19935
+ return this.items;
19936
+ }
19937
+ remove(key) {
19938
+ this.items = this.items.filter((item) => item.key !== key);
19939
+ }
19940
+ findById(key) {
19941
+ const item = this.items.find((item) => item.key === key);
19942
+ if (!item) {
19943
+ return null;
19944
+ }
19945
+ return item;
19946
+ }
19947
+ static tableFieldKey(prefix, index) {
19948
+ if (!Number.isInteger(index) || index < 1) {
19949
+ throw new RangeError(`FITS table field index must be >= 1, received ${index}.`);
19950
+ }
19951
+ return `${prefix}${index}`;
19952
+ }
19953
+ static naxisKey(axis) {
19954
+ if (!Number.isInteger(axis) || axis < 1) {
19955
+ throw new RangeError(`FITS axis must be a positive integer, received ${axis}.`);
19956
+ }
19957
+ return `NAXIS${axis}`;
19958
+ }
19959
+ static getFITSItemStringValue(header, key) {
19960
+ const item = header.findById(key);
19961
+ if (!item) {
19962
+ return null;
19963
+ }
19964
+ return String(item.value).trim().replace(/^'/, "").replace(/'$/, "").trim();
19965
+ }
19966
+ }
19967
+ //# sourceMappingURL=FITSHeaderManager.js.map
19968
+ // EXTERNAL MODULE: fs (ignored)
19969
+ var fs_ignored_ = __webpack_require__(7223);
19970
+ ;// ./node_modules/jsfitsio/lib-esm/FITSHeaderWriter.js
19971
+ class FITSHeaderWriter {
19972
+ static BLOCK_SIZE = 2880;
19973
+ static CARD_SIZE = 80;
19974
+ static INTEGER_KEYWORDS = new Set([
19975
+ "BITPIX",
19976
+ "NAXIS",
19977
+ "PCOUNT",
19978
+ "GCOUNT",
19979
+ ]);
19980
+ static LOGICAL_KEYWORDS = new Set(["SIMPLE", "EXTEND"]);
19981
+ static serialize(header, primary) {
19982
+ const items = header.getItems();
19983
+ const map = new Map(items.map((item) => [item.key.toUpperCase(), item]));
19984
+ const cards = [];
19985
+ FITSHeaderWriter.appendMandatoryCards(cards, map, primary);
19986
+ FITSHeaderWriter.appendRemainingCards(cards, items);
19987
+ cards.push(FITSHeaderWriter.card80("END"));
19988
+ return FITSHeaderWriter.encodeAndPad(cards);
19989
+ }
19990
+ static appendMandatoryCards(cards, map, primary) {
19991
+ if (primary) {
19992
+ const simple = map.get("SIMPLE");
19993
+ if (!simple) {
19994
+ throw new Error("Missing mandatory SIMPLE card in Primary HDU");
19995
+ }
19996
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("SIMPLE", simple.value, simple.comment));
19997
+ }
19998
+ else {
19999
+ const xtension = map.get("XTENSION");
20000
+ if (!xtension) {
20001
+ throw new Error("Missing mandatory XTENSION card in extension HDU");
20002
+ }
20003
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("XTENSION", xtension.value, xtension.comment));
20004
+ }
20005
+ const bitpix = map.get("BITPIX");
20006
+ if (!bitpix) {
20007
+ throw new Error("Missing mandatory BITPIX card");
20008
+ }
20009
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("BITPIX", bitpix.value, bitpix.comment));
20010
+ const naxis = map.get("NAXIS");
20011
+ if (!naxis) {
20012
+ throw new Error("Missing mandatory NAXIS card");
20013
+ }
20014
+ const nAxes = Number(naxis.value);
20015
+ if (!Number.isInteger(nAxes) || nAxes < 0) {
20016
+ throw new Error(`Invalid NAXIS value: ${naxis.value}`);
20017
+ }
20018
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("NAXIS", nAxes, naxis.comment));
20019
+ for (let axis = 1; axis <= nAxes; axis++) {
20020
+ const key = `NAXIS${axis}`;
20021
+ const item = map.get(key);
20022
+ if (!item) {
20023
+ throw new Error(`Missing mandatory ${key} card`);
20024
+ }
20025
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment(key, item.value, item.comment));
20026
+ }
20027
+ if (!primary) {
20028
+ const pcount = map.get("PCOUNT");
20029
+ const gcount = map.get("GCOUNT");
20030
+ if (!pcount) {
20031
+ throw new Error("Missing mandatory PCOUNT card in extension HDU");
20032
+ }
20033
+ if (!gcount) {
20034
+ throw new Error("Missing mandatory GCOUNT card in extension HDU");
20035
+ }
20036
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("PCOUNT", pcount.value, pcount.comment));
20037
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("GCOUNT", gcount.value, gcount.comment));
20038
+ }
20039
+ if (primary) {
20040
+ const extend = map.get("EXTEND");
20041
+ if (extend) {
20042
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment("EXTEND", extend.value, extend.comment));
20043
+ }
20044
+ }
20045
+ }
20046
+ static appendRemainingCards(cards, items) {
20047
+ for (const item of items) {
20048
+ const key = item.key.toUpperCase();
20049
+ if (key === "SIMPLE" ||
20050
+ key === "XTENSION" ||
20051
+ key === "BITPIX" ||
20052
+ key === "NAXIS" ||
20053
+ /^NAXIS\d+$/.test(key) ||
20054
+ key === "PCOUNT" ||
20055
+ key === "GCOUNT" ||
20056
+ key === "EXTEND" ||
20057
+ key === "END") {
20058
+ continue;
20059
+ }
20060
+ cards.push(...FITSHeaderWriter.makeKeywordWithComment(item.key, item.value, item.comment));
20061
+ }
20062
+ }
20063
+ static makeKeywordWithComment(key, value, comment) {
20064
+ const normalized = key.toUpperCase();
20065
+ if (normalized === "END") {
20066
+ return [FITSHeaderWriter.card80("END")];
20067
+ }
20068
+ if (normalized === "COMMENT" || normalized === "HISTORY") {
20069
+ return FITSHeaderWriter.makeCommentCards(normalized, String(value ?? comment ?? ""));
20070
+ }
20071
+ let base = FITSHeaderWriter.keyword(normalized) +
20072
+ FITSHeaderWriter.valueField20(normalized, value);
20073
+ if (!comment || comment.length === 0) {
20074
+ return [FITSHeaderWriter.card80(base)];
20075
+ }
20076
+ const addition = ` / ${comment}`;
20077
+ const spaceLeft = FITSHeaderWriter.CARD_SIZE - base.length;
20078
+ if (spaceLeft <= 0) {
20079
+ return [
20080
+ FITSHeaderWriter.card80(base),
20081
+ ...FITSHeaderWriter.makeCommentCards("COMMENT", comment),
20082
+ ];
20083
+ }
20084
+ base += addition.slice(0, spaceLeft);
20085
+ const overflow = addition.slice(spaceLeft).replace(/^\s*\/\s*/, "");
20086
+ if (overflow.length === 0) {
20087
+ return [FITSHeaderWriter.card80(base)];
20088
+ }
20089
+ return [
20090
+ FITSHeaderWriter.card80(base),
20091
+ ...FITSHeaderWriter.makeCommentCards("COMMENT", overflow),
20092
+ ];
20093
+ }
20094
+ static makeCommentCards(kind, text) {
20095
+ const prefix = FITSHeaderWriter.keyword(kind);
20096
+ const width = FITSHeaderWriter.CARD_SIZE - prefix.length;
20097
+ const value = String(text ?? "");
20098
+ if (value.length === 0) {
20099
+ return [FITSHeaderWriter.card80(prefix)];
20100
+ }
20101
+ const cards = [];
20102
+ for (let offset = 0; offset < value.length; offset += width) {
20103
+ cards.push(FITSHeaderWriter.card80(prefix + value.slice(offset, offset + width)));
20104
+ }
20105
+ return cards;
20106
+ }
20107
+ static valueField20(key, value) {
20108
+ if (FITSHeaderWriter.LOGICAL_KEYWORDS.has(key)) {
20109
+ const logical = value === true || value === "T" || value === "t" ? "T" : "F";
20110
+ return `= ${logical.padStart(20, " ")}`;
20111
+ }
20112
+ if (FITSHeaderWriter.INTEGER_KEYWORDS.has(key) || /^NAXIS\d+$/.test(key)) {
20113
+ const number = Number(value);
20114
+ if (!Number.isFinite(number) || !Number.isInteger(number)) {
20115
+ throw new Error(`FITS header: ${key} must be an integer, got ${value}`);
20116
+ }
20117
+ return `= ${String(number).padStart(20, " ")}`;
20118
+ }
20119
+ if (typeof value === "number") {
20120
+ let encoded = Number.isInteger(value)
20121
+ ? String(value)
20122
+ : value.toExponential(10).replace("e", "E");
20123
+ if (encoded.length > 20) {
20124
+ encoded = value.toExponential(8).replace("e", "E");
20125
+ }
20126
+ return `= ${encoded.padStart(20, " ")}`;
20127
+ }
20128
+ if (typeof value === "string") {
20129
+ return `= ${FITSHeaderWriter.quoteFitsString(value)}`;
20130
+ }
20131
+ return "";
20132
+ }
20133
+ static quoteFitsString(value) {
20134
+ const unquoted = value.replace(/^'+|'+$/g, "");
20135
+ const escaped = unquoted.replace(/'/g, "''");
20136
+ return `'${escaped}'`;
20137
+ }
20138
+ static keyword(value) {
20139
+ return (value ?? "").toUpperCase().padEnd(8, " ").slice(0, 8);
20140
+ }
20141
+ static card80(value) {
20142
+ if (value.length >= FITSHeaderWriter.CARD_SIZE) {
20143
+ return value.slice(0, FITSHeaderWriter.CARD_SIZE);
20144
+ }
20145
+ return value.padEnd(FITSHeaderWriter.CARD_SIZE, " ");
20146
+ }
20147
+ static encodeAndPad(cards) {
20148
+ let header = cards.join("");
20149
+ const remainder = header.length % FITSHeaderWriter.BLOCK_SIZE;
20150
+ if (remainder !== 0) {
20151
+ header += " ".repeat(FITSHeaderWriter.BLOCK_SIZE - remainder);
20152
+ }
20153
+ return new TextEncoder().encode(header);
20154
+ }
20155
+ }
20156
+ //# sourceMappingURL=FITSHeaderWriter.js.map
20157
+ ;// ./node_modules/jsfitsio/lib-esm/FITSWriter.js
20158
+ /**
20159
+ * FITS serialization and file writing support.
20160
+ *
20161
+ * FITSWriter provides two serialization APIs:
20162
+ *
20163
+ * - The jsfitsio 3.x API serializes the FITSFile/HDU data model,
20164
+ * including PrimaryHDU, ImageHDU, BinaryTableHDU and AsciiTableHDU.
20165
+ *
20166
+ * - The legacy API serializes the former FITSParsed representation
20167
+ * and is retained for backward compatibility with jsfitsio 2.x
20168
+ * consumers.
20169
+ *
20170
+ * FITS headers are serialized according to the FITS 80-character
20171
+ * card format and padded to 2880-byte FITS logical blocks.
20172
+ * HDU payloads are likewise padded to 2880-byte boundaries.
20173
+ *
20174
+ * New code should use FITSFile together with createFITSFile() and
20175
+ * writeFITSFileModel().
20176
+ *
20177
+ * @see https://fits.gsfc.nasa.gov/
20178
+ */
20179
+
20180
+
20181
+ class FITSWriter {
20182
+ /**
20183
+ * Serializes the legacy FITSParsed representation.
20184
+ *
20185
+ * @deprecated Use createFITSFile() with the FITSFile/HDU model.
20186
+ * This method is retained for backward compatibility with jsfitsio 2.x.
20187
+ */
20188
+ static createFITS(fitsParsed) {
20189
+ const headerBytes = FITSHeaderWriter.serialize(fitsParsed.header, true);
20190
+ const dataBytes = this.createData(fitsParsed.data, fitsParsed.header);
20191
+ const fitsFile = new Uint8Array(headerBytes.length + dataBytes.length);
20192
+ fitsFile.set(headerBytes, 0);
20193
+ fitsFile.set(dataBytes, headerBytes.length);
20194
+ return fitsFile;
20195
+ }
20196
+ static createHDU(hdu, primary) {
20197
+ const headerBytes = FITSHeaderWriter.serialize(hdu.header, primary);
20198
+ const rawData = hdu.rawData ?? new Uint8Array(0);
20199
+ if (rawData.byteLength !== hdu.dataByteLength) {
20200
+ throw new Error(`HDU payload length mismatch: ` +
20201
+ `rawData contains ${rawData.byteLength} bytes, ` +
20202
+ `but dataByteLength=${hdu.dataByteLength}.`);
20203
+ }
20204
+ const dataBytes = FITSWriter.padData(rawData);
20205
+ const result = new Uint8Array(headerBytes.byteLength + dataBytes.byteLength);
20206
+ result.set(headerBytes, 0);
20207
+ result.set(dataBytes, headerBytes.byteLength);
20208
+ return result;
20209
+ }
20210
+ static padData(data) {
20211
+ const BLOCK = 2880;
20212
+ if (data.byteLength === 0) {
20213
+ return new Uint8Array(0);
20214
+ }
20215
+ const remainder = data.byteLength % BLOCK;
20216
+ if (remainder === 0) {
20217
+ return data.slice();
20218
+ }
20219
+ const padded = new Uint8Array(data.byteLength + (BLOCK - remainder));
20220
+ padded.set(data);
20221
+ return padded;
20222
+ }
20223
+ static createData(data, header) {
20224
+ // concat
20225
+ const totalLength = data.reduce((s, c) => s + c.length, 0);
20226
+ // OPTIONAL: verify size from BITPIX/NAXIS
20227
+ const bitpix = Math.abs(Number(header.findById("BITPIX")?.value ?? 0));
20228
+ const naxis = Number(header.findById("NAXIS")?.value ?? 0);
20229
+ let elems = 1;
20230
+ for (let k = 1; k <= naxis; k++) {
20231
+ elems *= Number(header.findById(`NAXIS${k}`)?.value ?? 0);
20232
+ }
20233
+ const bytesPerElem = bitpix / 8;
20234
+ const expectedUnpadded = naxis > 0 ? elems * bytesPerElem : 0;
20235
+ if (expectedUnpadded && expectedUnpadded !== totalLength) {
20236
+ throw new Error(`Data length ${totalLength} does not match header expectation ${expectedUnpadded} (BITPIX=${bitpix}, NAXIS=${naxis})`);
20237
+ }
20238
+ // build and pad
20239
+ let dataBytes = new Uint8Array(totalLength);
20240
+ let off = 0;
20241
+ for (const chunk of data) {
20242
+ dataBytes.set(chunk, off);
20243
+ off += chunk.length;
20244
+ }
20245
+ return FITSWriter.padData(dataBytes);
20246
+ }
20247
+ /**
20248
+ * Serializes a jsfitsio 3.x FITSFile, including all contained HDUs.
20249
+ */
20250
+ static createFITSFile(fitsFile) {
20251
+ if (fitsFile.length === 0) {
20252
+ throw new Error("Cannot write an empty FITSFile.");
20253
+ }
20254
+ if (fitsFile.primaryHDU === null) {
20255
+ throw new Error("FITSFile must start with a PrimaryHDU.");
20256
+ }
20257
+ const serializedHDUs = fitsFile.hdus.map((hdu, index) => FITSWriter.createHDU(hdu, index === 0));
20258
+ const totalLength = serializedHDUs.reduce((sum, hdu) => sum + hdu.byteLength, 0);
20259
+ const result = new Uint8Array(totalLength);
20260
+ let offset = 0;
20261
+ for (const hdu of serializedHDUs) {
20262
+ result.set(hdu, offset);
20263
+ offset += hdu.byteLength;
20264
+ }
20265
+ return result;
20266
+ }
20267
+ /**
20268
+ * Serializes a jsfitsio 3.x FITSFile and writes it to the local filesystem.
20269
+ */
20270
+ static writeFITSFileModel(fitsFile, filePath) {
20271
+ const data = FITSWriter.createFITSFile(fitsFile);
20272
+ fs_ignored_.writeFileSync(filePath, data);
20273
+ }
20274
+ /**
20275
+ * Writes the legacy FITSParsed representation to a local file.
20276
+ *
20277
+ * @deprecated Use writeFITSFileModel() with FITSFile instead.
20278
+ * This method is retained for backward compatibility with jsfitsio 2.x.
20279
+ */
20280
+ static writeFITSFile(fitsParsed, filePath) {
20281
+ const fitsFile = FITSWriter.createFITS(fitsParsed);
20282
+ fs_ignored_.writeFileSync(filePath, fitsFile);
20283
+ }
20284
+ }
20285
+ //# sourceMappingURL=FITSWriter.js.map
20286
+ ;// ./node_modules/jsfitsio/lib-esm/ParseHeader.js
20287
+ // import { FITSHeader } from "./model/FITSHeader.js";
20288
+
20289
+
20290
+ /**
20291
+ * Summary. (bla bla bla)
20292
+ *
20293
+ * Description. (bla bla bla)
20294
+ *
20295
+ * @link github https://github.com/fab77/FITSParser
20296
+ * @author Fabrizio Giordano <fabriziogiordano77@gmail.com>
20297
+ */
20298
+ class ParseHeader {
20299
+ static CARD_SIZE = 80;
20300
+ static BLOCK_SIZE = 2880;
20301
+ static getFITSItemStringValue(header, key) {
20302
+ const item = header.findById(key);
20303
+ if (!item) {
20304
+ return null;
20305
+ }
20306
+ return String(item.value).trim().replace(/^'/, "").replace(/'$/, "").trim();
20307
+ }
20308
+ static getFITSItemValue(header, key) {
20309
+ const item = header.findById(key);
20310
+ if (!item) {
20311
+ return null;
20312
+ }
20313
+ const value = Number(item.value);
20314
+ return Number.isNaN(value) ? null : value;
20315
+ }
20316
+ /**
20317
+ * Returns the complete FITS header size, including padding
20318
+ * up to the next 2880-byte boundary.
20319
+ */
20320
+ static getHeaderByteLength(rawData, startOffset = 0) {
20321
+ const decoder = new TextDecoder("ascii");
20322
+ for (let offset = startOffset; offset + ParseHeader.CARD_SIZE <= rawData.byteLength; offset += ParseHeader.CARD_SIZE) {
20323
+ const key = decoder.decode(rawData.subarray(offset, offset + 8)).trim();
20324
+ if (key === "END") {
20325
+ const consumed = offset + ParseHeader.CARD_SIZE - startOffset;
20326
+ return (Math.ceil(consumed / ParseHeader.BLOCK_SIZE) * ParseHeader.BLOCK_SIZE);
20327
+ }
20328
+ }
20329
+ throw new Error("Invalid FITS header: END card not found.");
20330
+ }
20331
+ static parse(rawData, startOffset = 0) {
20332
+ const decoder = new TextDecoder("ascii");
20333
+ const headerLength = ParseHeader.getHeaderByteLength(rawData, startOffset);
20334
+ const header = new FITSHeaderManager(false);
20335
+ for (let offset = startOffset; offset < startOffset + headerLength; offset += ParseHeader.CARD_SIZE) {
20336
+ const line = decoder.decode(rawData.subarray(offset, offset + ParseHeader.CARD_SIZE));
20337
+ const key = line.slice(0, 8).trim();
20338
+ if (key === "END") {
20339
+ break;
20340
+ }
20341
+ if (!key) {
20342
+ continue;
20343
+ }
20344
+ let value;
20345
+ let comment = "";
20346
+ const rawValue = line.slice(10).trim().split("/")[0].trim();
20347
+ if (Number.isNaN(Number(rawValue))) {
20348
+ value = rawValue;
20349
+ }
20350
+ else {
20351
+ value = Number(rawValue);
20352
+ }
20353
+ if (line.includes("/")) {
20354
+ comment = line.slice(10).trim().split("/")[1]?.trim() ?? "";
20355
+ }
20356
+ header.insert(new FITSHeaderItem(key, value, comment));
20357
+ }
20358
+ return header;
20359
+ }
20360
+ }
20361
+ //# sourceMappingURL=ParseHeader.js.map
20362
+ ;// ./node_modules/jsfitsio/lib-esm/FITSImageUtils.js
20363
+
20364
+
20365
+ class FITSImageUtils {
20366
+ static getShape(header) {
20367
+ const naxis = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS);
20368
+ if (naxis === null) {
20369
+ throw new Error("NAXIS not defined.");
20370
+ }
20371
+ if (!Number.isInteger(naxis) || naxis < 0) {
20372
+ throw new Error(`Invalid FITS NAXIS value: ${naxis}`);
20373
+ }
20374
+ const shape = [];
20375
+ for (let axis = 1; axis <= naxis; axis++) {
20376
+ const size = ParseHeader.getFITSItemValue(header, FITSHeaderManager.naxisKey(axis));
20377
+ if (size === null) {
20378
+ throw new Error(`NAXIS${axis} not defined.`);
20379
+ }
20380
+ shape.push(size);
20381
+ }
20382
+ return shape;
20383
+ }
20384
+ static getElementCount(shape) {
20385
+ if (shape.length === 0) {
20386
+ return 0;
20387
+ }
20388
+ return shape.reduce((total, dimension) => total * dimension, 1);
20389
+ }
20390
+ }
20391
+ //# sourceMappingURL=FITSImageUtils.js.map
20392
+ ;// ./node_modules/jsfitsio/lib-esm/ParsePayload.js
20393
+ // "use strict";
20394
+ /**
20395
+ * Summary. (bla bla bla)
20396
+ *
20397
+ * Description. (bla bla bla)
20398
+ *
20399
+ * @link github https://github.com/fab77/FITSParser
20400
+ * @author Fabrizio Giordano <fabriziogiordano77@gmail.com>
20401
+ */
20402
+
20403
+
20404
+
20405
+
20406
+ class ParsePayload {
20407
+ static SUPPORTED_BITPIX = new Set([8, 16, 32, 64, -32, -64]);
20408
+ static assertSupportedBITPIX(bitpix) {
20409
+ if (!ParsePayload.SUPPORTED_BITPIX.has(bitpix)) {
20410
+ throw new Error(`Unsupported FITS BITPIX value: ${bitpix}`);
20411
+ }
20412
+ }
20413
+ static extractPixelFromView(view, offset, bitpix) {
20414
+ switch (bitpix) {
20415
+ case 8:
20416
+ return view.getUint8(offset);
20417
+ case 16:
20418
+ return view.getInt16(offset, false);
20419
+ case 32:
20420
+ return view.getInt32(offset, false);
20421
+ case -32:
20422
+ return view.getFloat32(offset, false);
20423
+ case -64:
20424
+ return view.getFloat64(offset, false);
20425
+ case 64: {
20426
+ const value = view.getBigInt64(offset, false);
20427
+ const numeric = Number(value);
20428
+ if (!Number.isSafeInteger(numeric)) {
20429
+ throw new RangeError(`BITPIX=64 value ${value} cannot be represented ` +
20430
+ `exactly as a JavaScript number.`);
20431
+ }
20432
+ return numeric;
20433
+ }
20434
+ default:
20435
+ throw new Error(`Unsupported FITS BITPIX value: ${bitpix}`);
20436
+ }
20437
+ }
20438
+ static computePhysicalMinAndMax(header, payload) {
20439
+ const bitpix = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BITPIX);
20440
+ if (bitpix === null) {
20441
+ return null;
20442
+ }
20443
+ ParsePayload.assertSupportedBITPIX(bitpix);
20444
+ const shape = FITSImageUtils.getShape(header);
20445
+ /*
20446
+ * NAXIS=0 is a valid FITS HDU.
20447
+ */
20448
+ if (shape.length === 0 || payload.byteLength === 0) {
20449
+ return header;
20450
+ }
20451
+ const dataMinItem = header.findById(FITSHeaderManager.DATAMIN);
20452
+ const dataMaxItem = header.findById(FITSHeaderManager.DATAMAX);
20453
+ if (dataMinItem === null || dataMaxItem === null) {
20454
+ try {
20455
+ const [min, max] = ParsePayload.computePhysicalValues(payload, header);
20456
+ if (dataMinItem === null && min !== null) {
20457
+ header.insert(new FITSHeaderItem(FITSHeaderManager.DATAMIN, min, "computed by jsfitsio"));
20458
+ }
20459
+ if (dataMaxItem === null && max !== null) {
20460
+ header.insert(new FITSHeaderItem(FITSHeaderManager.DATAMAX, max, "computed by jsfitsio"));
20461
+ }
20462
+ }
20463
+ catch (error) {
20464
+ if (bitpix === 64 && error instanceof RangeError) {
20465
+ return header;
20466
+ }
20467
+ throw error;
20468
+ }
20469
+ }
20470
+ return header;
20471
+ }
20472
+ static createTypedArray(rawData, bitpix) {
20473
+ ParsePayload.assertSupportedBITPIX(bitpix);
20474
+ const bytesPerElement = Math.abs(bitpix) / 8;
20475
+ if (rawData.byteLength % bytesPerElement !== 0) {
20476
+ throw new Error(`Payload byte length ${rawData.byteLength} ` +
20477
+ `is not aligned with BITPIX=${bitpix}.`);
20478
+ }
20479
+ const count = rawData.byteLength / bytesPerElement;
20480
+ const view = new DataView(rawData.buffer, rawData.byteOffset, rawData.byteLength);
20481
+ switch (bitpix) {
20482
+ case 8: {
20483
+ /*
20484
+ * For 8-bit FITS, byte order is irrelevant.
20485
+ *
20486
+ * Use slice() so typedData has its own correctly
20487
+ * sized backing store.
20488
+ */
20489
+ return rawData.slice();
20490
+ }
20491
+ case 16: {
20492
+ const result = new Int16Array(count);
20493
+ for (let i = 0; i < count; i++) {
20494
+ result[i] = view.getInt16(i * 2, false);
20495
+ }
20496
+ return result;
20497
+ }
20498
+ case 32: {
20499
+ const result = new Int32Array(count);
20500
+ for (let i = 0; i < count; i++) {
20501
+ result[i] = view.getInt32(i * 4, false);
20502
+ }
20503
+ return result;
20504
+ }
20505
+ case 64: {
20506
+ const result = new BigInt64Array(count);
20507
+ for (let i = 0; i < count; i++) {
20508
+ result[i] = view.getBigInt64(i * 8, false);
20509
+ }
20510
+ return result;
20511
+ }
20512
+ case -32: {
20513
+ const result = new Float32Array(count);
20514
+ for (let i = 0; i < count; i++) {
20515
+ result[i] = view.getFloat32(i * 4, false);
20516
+ }
20517
+ return result;
20518
+ }
20519
+ case -64: {
20520
+ const result = new Float64Array(count);
20521
+ for (let i = 0; i < count; i++) {
20522
+ result[i] = view.getFloat64(i * 8, false);
20523
+ }
20524
+ return result;
20525
+ }
20526
+ default:
20527
+ throw new Error(`Unsupported FITS BITPIX value: ${bitpix}`);
20528
+ }
20529
+ }
20530
+ static computePhysicalValues(rawData, header) {
20531
+ const bitpix = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BITPIX);
20532
+ if (bitpix === null) {
20533
+ return [null, null];
20534
+ }
20535
+ ParsePayload.assertSupportedBITPIX(bitpix);
20536
+ const shape = FITSImageUtils.getShape(header);
20537
+ const pixelCount = FITSImageUtils.getElementCount(shape);
20538
+ if (pixelCount === 0) {
20539
+ return [null, null];
20540
+ }
20541
+ const blank = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BLANK);
20542
+ const bzero = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BZERO) ?? 0;
20543
+ const bscale = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BSCALE) ?? 1;
20544
+ const bytesPerElement = Math.abs(bitpix) / 8;
20545
+ const requiredBytes = pixelCount * bytesPerElement;
20546
+ if (rawData.byteLength < requiredBytes) {
20547
+ throw new Error(`FITS payload is too short: expected ${requiredBytes} bytes, ` +
20548
+ `received ${rawData.byteLength}.`);
20549
+ }
20550
+ const view = new DataView(rawData.buffer, rawData.byteOffset, rawData.byteLength);
20551
+ let min = null;
20552
+ let max = null;
20553
+ for (let i = 0; i < pixelCount; i++) {
20554
+ const rawValue = ParsePayload.extractPixelFromView(view, i * bytesPerElement, bitpix);
20555
+ // BLANK applies to integer FITS image data.
20556
+ if (bitpix > 0 && blank !== null && rawValue === blank) {
20557
+ continue;
20558
+ }
20559
+ const physicalValue = ParsePayload.pixel2physicalValue(rawValue, bscale, bzero);
20560
+ // Floating-point FITS images may contain NaN.
20561
+ if (Number.isNaN(physicalValue)) {
20562
+ continue;
20563
+ }
20564
+ if (min === null || physicalValue < min) {
20565
+ min = physicalValue;
20566
+ }
20567
+ if (max === null || physicalValue > max) {
20568
+ max = physicalValue;
20569
+ }
20570
+ }
20571
+ return [min, max];
20572
+ }
20573
+ static pixel2physicalValue(pxval, BSCALE, BZERO) {
20574
+ if (BZERO === null || BSCALE === null) {
20575
+ throw new Error("Either BZERO or BSCALE is null");
20576
+ }
20577
+ return BZERO + BSCALE * pxval;
20578
+ }
20579
+ static extractPixelValue(rawData, offset, bitpix) {
20580
+ ParsePayload.assertSupportedBITPIX(bitpix);
20581
+ const view = new DataView(rawData.buffer, rawData.byteOffset, rawData.byteLength);
20582
+ return ParsePayload.extractPixelFromView(view, offset, bitpix);
20583
+ }
20584
+ }
20585
+ //# sourceMappingURL=ParsePayload.js.map
20586
+ ;// ./node_modules/jsfitsio/lib-esm/model/FITSHDU.js
20587
+ class FITSHDU {
20588
+ header;
20589
+ rawData;
20590
+ dataOffset;
20591
+ dataByteLength;
20592
+ constructor(header, rawData, dataOffset, dataByteLength) {
20593
+ this.header = header;
20594
+ this.rawData = rawData;
20595
+ this.dataOffset = dataOffset;
20596
+ this.dataByteLength = dataByteLength;
20597
+ }
20598
+ }
20599
+ //# sourceMappingURL=FITSHDU.js.map
20600
+ ;// ./node_modules/jsfitsio/lib-esm/model/ImageHDU.js
20601
+
20602
+ class ImageHDU extends FITSHDU {
20603
+ bitpix;
20604
+ shape;
20605
+ typedData;
20606
+ type = "IMAGE";
20607
+ constructor(header, rawData, dataOffset, dataByteLength, bitpix, shape, typedData) {
20608
+ super(header, rawData, dataOffset, dataByteLength);
20609
+ this.bitpix = bitpix;
20610
+ this.shape = shape;
20611
+ this.typedData = typedData;
20612
+ }
20613
+ get naxis() {
20614
+ return this.shape.length;
20615
+ }
20616
+ get elementCount() {
20617
+ if (this.shape.length === 0) {
20618
+ return 0;
20619
+ }
20620
+ return this.shape.reduce((accumulator, dimension) => accumulator * dimension, 1);
20621
+ }
20622
+ }
20623
+ //# sourceMappingURL=ImageHDU.js.map
20624
+ ;// ./node_modules/jsfitsio/lib-esm/model/PrimaryHDU.js
20625
+
20626
+ class PrimaryHDU extends ImageHDU {
20627
+ type = "PRIMARY";
20628
+ constructor(header, rawData, dataOffset, dataByteLength, bitpix, shape, typedData) {
20629
+ super(header, rawData, dataOffset, dataByteLength, bitpix, shape, typedData);
20630
+ }
20631
+ }
20632
+ //# sourceMappingURL=PrimaryHDU.js.map
20633
+ ;// ./node_modules/jsfitsio/lib-esm/model/FITSFile.js
20634
+
20635
+ class FITSFile {
20636
+ _hdus;
20637
+ constructor(hdus = []) {
20638
+ this._hdus = [...hdus];
20639
+ }
20640
+ get hdus() {
20641
+ return this._hdus;
20642
+ }
20643
+ get length() {
20644
+ return this._hdus.length;
20645
+ }
20646
+ get primaryHDU() {
20647
+ const hdu = this._hdus[0];
20648
+ if (hdu instanceof PrimaryHDU) {
20649
+ return hdu;
20650
+ }
20651
+ return null;
20652
+ }
20653
+ getHDU(index) {
20654
+ return this._hdus[index] ?? null;
20655
+ }
20656
+ addHDU(hdu) {
20657
+ this._hdus.push(hdu);
20658
+ }
20659
+ }
20660
+ //# sourceMappingURL=FITSFile.js.map
20661
+ ;// ./node_modules/jsfitsio/lib-esm/model/BinaryTableHDU.js
20662
+
20663
+ class BinaryTableHDU extends FITSHDU {
20664
+ rowByteLength;
20665
+ rowCount;
20666
+ columns;
20667
+ type = "BINTABLE";
20668
+ constructor(header, rawData, dataOffset, dataByteLength, rowByteLength, rowCount, columns) {
20669
+ super(header, rawData, dataOffset, dataByteLength);
20670
+ this.rowByteLength = rowByteLength;
20671
+ this.rowCount = rowCount;
20672
+ this.columns = columns;
20673
+ }
20674
+ get columnCount() {
20675
+ return this.columns.length;
20676
+ }
20677
+ getRowView(rowIndex) {
20678
+ if (rowIndex < 0 || rowIndex >= this.rowCount) {
20679
+ throw new RangeError(`Invalid row index ${rowIndex}.`);
20680
+ }
20681
+ const offset = rowIndex * this.rowByteLength;
20682
+ return new DataView(this.rawData.buffer, this.rawData.byteOffset + offset, this.rowByteLength);
20683
+ }
20684
+ getRow(rowIndex) {
20685
+ return this.columns.map((_, columnIndex) => this.getCell(rowIndex, columnIndex));
20686
+ }
20687
+ getCell(rowIndex, column) {
20688
+ const columnDefinition = this.resolveColumn(column);
20689
+ const row = this.getRowView(rowIndex);
20690
+ const offset = columnDefinition.byteOffset;
20691
+ const repeat = columnDefinition.repeat;
20692
+ switch (columnDefinition.type) {
20693
+ case "CHAR": {
20694
+ const bytes = new Uint8Array(row.buffer, row.byteOffset + offset, columnDefinition.byteWidth);
20695
+ return new TextDecoder("ascii").decode(bytes).replace(/\s+$/, "");
20696
+ }
20697
+ case "LOGICAL": {
20698
+ const values = [];
20699
+ for (let i = 0; i < repeat; i++) {
20700
+ const value = String.fromCharCode(row.getUint8(offset + i));
20701
+ values.push(value === "T");
20702
+ }
20703
+ return repeat === 1 ? values[0] : values;
20704
+ }
20705
+ case "UINT8": {
20706
+ const values = [];
20707
+ for (let i = 0; i < repeat; i++) {
20708
+ const raw = row.getUint8(offset + i);
20709
+ values.push(this.applyNumericScaling(raw, columnDefinition.scale, columnDefinition.zero));
20710
+ }
20711
+ return repeat === 1 ? values[0] : values;
20712
+ }
20713
+ case "INT16":
20714
+ return this.readNumericColumn(row, offset, repeat, 2, (view, position) => view.getInt16(position, false), columnDefinition.scale, columnDefinition.zero, columnDefinition.nullValue);
20715
+ case "INT32":
20716
+ return this.readNumericColumn(row, offset, repeat, 4, (view, position) => view.getInt32(position, false), columnDefinition.scale, columnDefinition.zero, columnDefinition.nullValue);
20717
+ case "INT64": {
20718
+ const values = [];
20719
+ for (let i = 0; i < repeat; i++) {
20720
+ const raw = row.getBigInt64(offset + i * 8, false);
20721
+ /*
20722
+ * Preserve exact 64-bit integers.
20723
+ *
20724
+ * Do not silently convert bigint to number.
20725
+ */
20726
+ values.push(raw);
20727
+ }
20728
+ return repeat === 1 ? values[0] : values;
20729
+ }
20730
+ case "FLOAT32":
20731
+ return this.readNumericColumn(row, offset, repeat, 4, (view, position) => view.getFloat32(position, false), columnDefinition.scale, columnDefinition.zero, null);
20732
+ case "FLOAT64":
20733
+ return this.readNumericColumn(row, offset, repeat, 8, (view, position) => view.getFloat64(position, false), columnDefinition.scale, columnDefinition.zero, null);
20734
+ case "COMPLEX64": {
20735
+ const values = [];
20736
+ for (let i = 0; i < repeat; i++) {
20737
+ const position = offset + i * 8;
20738
+ values.push({
20739
+ real: row.getFloat32(position, false),
20740
+ imaginary: row.getFloat32(position + 4, false),
20741
+ });
20742
+ }
20743
+ return repeat === 1 ? values[0] : values;
20744
+ }
20745
+ case "COMPLEX128": {
20746
+ const values = [];
20747
+ for (let i = 0; i < repeat; i++) {
20748
+ const position = offset + i * 16;
20749
+ values.push({
20750
+ real: row.getFloat64(position, false),
20751
+ imaginary: row.getFloat64(position + 8, false),
20752
+ });
20753
+ }
20754
+ return repeat === 1 ? values[0] : values;
20755
+ }
20756
+ case "BIT":
20757
+ /*
20758
+ * I'd defer bit-array decoding for the moment.
20759
+ * The raw bytes remain available.
20760
+ */
20761
+ return new Uint8Array(row.buffer, row.byteOffset + offset, columnDefinition.byteWidth).slice();
20762
+ default:
20763
+ throw new Error(`Unsupported BINTABLE column type: ${columnDefinition.type}`);
20764
+ }
20765
+ }
20766
+ readNumericColumn(view, offset, repeat, bytesPerElement, reader, scale, zero, nullValue) {
20767
+ const values = [];
20768
+ for (let i = 0; i < repeat; i++) {
20769
+ const raw = reader(view, offset + i * bytesPerElement);
20770
+ if (nullValue !== null && raw === nullValue) {
20771
+ values.push(null);
20772
+ continue;
20773
+ }
20774
+ values.push(this.applyNumericScaling(raw, scale, zero));
20775
+ }
20776
+ if (repeat === 1) {
20777
+ return values[0];
20778
+ }
20779
+ /*
20780
+ * Because repeated integer fields may contain NULL,
20781
+ * we cannot represent every case as number[].
20782
+ *
20783
+ * For now return a generic value array.
20784
+ */
20785
+ return values;
20786
+ }
20787
+ applyNumericScaling(raw, scale, zero) {
20788
+ return zero + scale * raw;
20789
+ }
20790
+ resolveColumn(column) {
20791
+ if (typeof column === "number") {
20792
+ if (!Number.isInteger(column) ||
20793
+ column < 0 ||
20794
+ column >= this.columns.length) {
20795
+ throw new RangeError(`Invalid column index ${column}.`);
20796
+ }
20797
+ return this.columns[column];
20798
+ }
20799
+ const found = this.columns.find((candidate) => candidate.name === column);
20800
+ if (!found) {
20801
+ throw new Error(`BINTABLE column '${column}' not found.`);
20802
+ }
20803
+ return found;
20804
+ }
20805
+ }
20806
+ //# sourceMappingURL=BinaryTableHDU.js.map
20807
+ ;// ./node_modules/jsfitsio/lib-esm/FITSBinaryTableUtils.js
20808
+ class FITSBinaryTableUtils {
20809
+ static parseTFORM(format) {
20810
+ const normalized = format
20811
+ .trim()
20812
+ .replace(/^'/, "")
20813
+ .replace(/'$/, "")
20814
+ .trim()
20815
+ .toUpperCase();
20816
+ const match = normalized.match(/^(\d*)([LXBIJKAEDCM])$/);
20817
+ if (!match) {
20818
+ throw new Error(`Unsupported FITS TFORM value: ${format}`);
20819
+ }
20820
+ const repeat = match[1] ? Number(match[1]) : 1;
20821
+ const code = match[2];
20822
+ const bytesPerElement = FITSBinaryTableUtils.bytesPerType(code);
20823
+ return {
20824
+ repeat,
20825
+ code,
20826
+ byteWidth: code === "X" ? Math.ceil(repeat / 8) : repeat * bytesPerElement,
20827
+ };
20828
+ }
20829
+ static bytesPerType(code) {
20830
+ switch (code) {
20831
+ case "L":
20832
+ case "B":
20833
+ case "A":
20834
+ return 1;
20835
+ case "I":
20836
+ return 2;
20837
+ case "J":
20838
+ case "E":
20839
+ return 4;
20840
+ case "K":
20841
+ case "D":
20842
+ return 8;
20843
+ case "C":
20844
+ return 8;
20845
+ case "M":
20846
+ return 16;
20847
+ case "X":
20848
+ return 0;
20849
+ default:
20850
+ throw new Error(`Unsupported FITS binary table type: ${code}`);
20851
+ }
20852
+ }
20853
+ }
20854
+ //# sourceMappingURL=FITSBinaryTableUtils.js.map
20855
+ ;// ./node_modules/jsfitsio/lib-esm/model/AsciiTableHDU.js
20856
+
20857
+ class AsciiTableHDU extends FITSHDU {
20858
+ rowByteLength;
20859
+ rowCount;
20860
+ columns;
20861
+ type = "TABLE";
20862
+ constructor(header, rawData, dataOffset, dataByteLength, rowByteLength, rowCount, columns) {
20863
+ super(header, rawData, dataOffset, dataByteLength);
20864
+ this.rowByteLength = rowByteLength;
20865
+ this.rowCount = rowCount;
20866
+ this.columns = columns;
20867
+ }
20868
+ get columnCount() {
20869
+ return this.columns.length;
20870
+ }
20871
+ getRowView(rowIndex) {
20872
+ if (!Number.isInteger(rowIndex) ||
20873
+ rowIndex < 0 ||
20874
+ rowIndex >= this.rowCount) {
20875
+ throw new RangeError(`Invalid row index ${rowIndex}.`);
20876
+ }
20877
+ const start = rowIndex * this.rowByteLength;
20878
+ return this.rawData.subarray(start, start + this.rowByteLength);
20879
+ }
20880
+ getRowText(rowIndex) {
20881
+ return new TextDecoder("ascii").decode(this.getRowView(rowIndex));
20882
+ }
20883
+ resolveColumn(column) {
20884
+ if (typeof column === "number") {
20885
+ if (!Number.isInteger(column) ||
20886
+ column < 0 ||
20887
+ column >= this.columns.length) {
20888
+ throw new RangeError(`Invalid column index ${column}.`);
20889
+ }
20890
+ return this.columns[column];
20891
+ }
20892
+ const found = this.columns.find((candidate) => candidate.name === column);
20893
+ if (!found) {
20894
+ throw new Error(`ASCII TABLE column '${column}' not found.`);
20895
+ }
20896
+ return found;
20897
+ }
20898
+ getCell(rowIndex, column) {
20899
+ const definition = this.resolveColumn(column);
20900
+ const row = this.getRowView(rowIndex);
20901
+ const bytes = row.subarray(definition.byteOffset, definition.byteOffset + definition.width);
20902
+ const raw = new TextDecoder("ascii").decode(bytes);
20903
+ const trimmed = raw.trim();
20904
+ /*
20905
+ * Blank numeric fields are treated as null.
20906
+ */
20907
+ if (trimmed.length === 0) {
20908
+ return definition.type === "CHAR" ? "" : null;
20909
+ }
20910
+ switch (definition.type) {
20911
+ case "CHAR":
20912
+ return raw.replace(/\s+$/, "");
20913
+ case "INTEGER": {
20914
+ const value = Number.parseInt(trimmed, 10);
20915
+ if (Number.isNaN(value)) {
20916
+ return null;
20917
+ }
20918
+ return value;
20919
+ }
20920
+ case "FLOAT":
20921
+ case "EXPONENTIAL":
20922
+ case "DOUBLE": {
20923
+ /*
20924
+ * FITS ASCII tables may use D exponent notation.
20925
+ * JavaScript expects E.
20926
+ */
20927
+ const normalized = trimmed.replace(/[dD]/, "E");
20928
+ const value = Number.parseFloat(normalized);
20929
+ if (Number.isNaN(value)) {
20930
+ return null;
20931
+ }
20932
+ return value;
20933
+ }
20934
+ default:
20935
+ throw new Error(`Unsupported ASCII TABLE column type: ${definition.type}`);
20936
+ }
20937
+ }
20938
+ getRow(rowIndex) {
20939
+ return this.columns.map((_, columnIndex) => this.getCell(rowIndex, columnIndex));
20940
+ }
20941
+ }
20942
+ //# sourceMappingURL=AsciiTableHDU.js.map
20943
+ ;// ./node_modules/jsfitsio/lib-esm/FITSAsciiTableUtils.js
20944
+ class FITSAsciiTableUtils {
20945
+ static parseTFORM(format) {
20946
+ const normalized = format
20947
+ .trim()
20948
+ .replace(/^'/, "")
20949
+ .replace(/'$/, "")
20950
+ .trim()
20951
+ .toUpperCase();
20952
+ /*
20953
+ * FITS ASCII table formats:
20954
+ *
20955
+ * Aw
20956
+ * Iw
20957
+ * Fw.d
20958
+ * Ew.d
20959
+ * Dw.d
20960
+ */
20961
+ const match = normalized.match(/^([AIFED])(\d+)(?:\.(\d+))?$/);
20962
+ if (!match) {
20963
+ throw new Error(`Unsupported FITS ASCII table TFORM value: ${format}`);
20964
+ }
20965
+ const code = match[1];
20966
+ const width = Number(match[2]);
20967
+ const decimals = match[3] !== undefined
20968
+ ? Number(match[3])
20969
+ : null;
20970
+ if (!Number.isInteger(width) ||
20971
+ width <= 0) {
20972
+ throw new Error(`Invalid FITS ASCII table field width: ${width}`);
20973
+ }
20974
+ if (code === "A" ||
20975
+ code === "I") {
20976
+ if (decimals !== null) {
20977
+ throw new Error(`TFORM ${format} must not specify decimal places.`);
20978
+ }
20979
+ }
20980
+ else if (decimals === null) {
20981
+ throw new Error(`TFORM ${format} requires decimal places.`);
20982
+ }
20983
+ return {
20984
+ code,
20985
+ width,
20986
+ decimals,
20987
+ };
20988
+ }
20989
+ }
20990
+ //# sourceMappingURL=FITSAsciiTableUtils.js.map
20991
+ ;// ./node_modules/jsfitsio/lib-esm/FITSParser.js
20992
+
20993
+
20994
+
20995
+
20996
+
20997
+
20998
+
20999
+
21000
+
21001
+
21002
+
21003
+
21004
+ class FITSParser {
21005
+ /**
21006
+ * @deprecated Use loadFITSFile() instead.
21007
+ *
21008
+ * This legacy API supports only 2-dimensional image FITS files
21009
+ * and returns the former FITSParsed structure.
21010
+ */
21011
+ static async loadFITS(path, options = {}) {
21012
+ const fitsFile = await FITSParser.loadFITSFile(path, options);
21013
+ if (fitsFile === null) {
21014
+ return null;
21015
+ }
21016
+ const primary = fitsFile.primaryHDU;
21017
+ if (primary === null || primary.rawData === null) {
21018
+ return null;
21019
+ }
21020
+ const shape = FITSImageUtils.getShape(primary.header);
21021
+ if (shape.length !== 2) {
21022
+ throw new Error("Legacy loadFITS() supports only 2D FITS images. " +
21023
+ "Use loadFITSFile() for N-dimensional images.");
21024
+ }
21025
+ return {
21026
+ header: primary.header,
21027
+ data: FITSParser.createMatrix(primary.rawData, primary.header),
21028
+ };
21029
+ }
21030
+ static async loadFITSFile(path, options = {}) {
21031
+ const rawData = await FITSParser.getFile(path);
21032
+ if (rawData.byteLength === 0) {
21033
+ return null;
21034
+ }
21035
+ return FITSParser.processFITSFile(rawData, options);
21036
+ }
21037
+ static processFITSFile(rawData, options) {
21038
+ const fitsFile = new FITSFile();
21039
+ let offset = 0;
21040
+ let hduIndex = 0;
21041
+ while (offset < rawData.byteLength) {
21042
+ /*
21043
+ * Ignore trailing zero/space padding.
21044
+ */
21045
+ if (FITSParser.isPaddingOnly(rawData, offset)) {
21046
+ break;
21047
+ }
21048
+ const header = ParseHeader.parse(rawData, offset);
21049
+ const headerByteLength = ParseHeader.getHeaderByteLength(rawData, offset);
21050
+ const dataOffset = offset + headerByteLength;
21051
+ const hduType = FITSParser.getHDUType(header, hduIndex);
21052
+ switch (hduType) {
21053
+ case "PRIMARY":
21054
+ case "IMAGE": {
21055
+ const dataByteLength = FITSParser.getImagePayloadByteLength(header);
21056
+ if (dataOffset + dataByteLength > rawData.byteLength) {
21057
+ throw new Error(`Invalid FITS HDU ${hduIndex}: ` +
21058
+ `expected ${dataByteLength} payload bytes ` +
21059
+ `at offset ${dataOffset}, but only ` +
21060
+ `${rawData.byteLength - dataOffset} remain.`);
21061
+ }
21062
+ const rawPayload = rawData.subarray(dataOffset, dataOffset + dataByteLength);
21063
+ const hdu = FITSParser.createImageHDU(header, rawPayload, dataOffset, dataByteLength, hduIndex === 0, options);
21064
+ fitsFile.addHDU(hdu);
21065
+ const paddedPayloadLength = FITSParser.getPaddedByteLength(dataByteLength);
21066
+ offset = dataOffset + paddedPayloadLength;
21067
+ break;
21068
+ }
21069
+ case "BINTABLE": {
21070
+ const dataByteLength = FITSParser.getBinaryTablePayloadByteLength(header);
21071
+ if (dataOffset + dataByteLength > rawData.byteLength) {
21072
+ throw new Error(`Invalid BINTABLE HDU ${hduIndex}.`);
21073
+ }
21074
+ const rawPayload = rawData.subarray(dataOffset, dataOffset + dataByteLength);
21075
+ const hdu = FITSParser.createBinaryTableHDU(header, rawPayload, dataOffset, dataByteLength);
21076
+ fitsFile.addHDU(hdu);
21077
+ offset = dataOffset + FITSParser.getPaddedByteLength(dataByteLength);
21078
+ break;
21079
+ }
21080
+ case "TABLE": {
21081
+ const dataByteLength = FITSParser.getAsciiTablePayloadByteLength(header);
21082
+ if (dataOffset + dataByteLength > rawData.byteLength) {
21083
+ throw new Error(`Invalid ASCII TABLE HDU ${hduIndex}: ` +
21084
+ `expected ${dataByteLength} payload bytes ` +
21085
+ `at offset ${dataOffset}, but only ` +
21086
+ `${rawData.byteLength - dataOffset} remain.`);
21087
+ }
21088
+ const rawPayload = rawData.subarray(dataOffset, dataOffset + dataByteLength);
21089
+ const hdu = FITSParser.createAsciiTableHDU(header, rawPayload, dataOffset, dataByteLength);
21090
+ fitsFile.addHDU(hdu);
21091
+ offset = dataOffset + FITSParser.getPaddedByteLength(dataByteLength);
21092
+ break;
21093
+ }
21094
+ default:
21095
+ throw new Error(`Unsupported FITS HDU type at index ${hduIndex}.`);
21096
+ }
21097
+ hduIndex++;
21098
+ }
21099
+ return fitsFile;
21100
+ }
21101
+ static getPaddedByteLength(byteLength) {
21102
+ if (byteLength === 0) {
21103
+ return 0;
21104
+ }
21105
+ return (Math.ceil(byteLength / ParseHeader.BLOCK_SIZE) * ParseHeader.BLOCK_SIZE);
21106
+ }
21107
+ static isPaddingOnly(rawData, offset) {
21108
+ for (let i = offset; i < rawData.byteLength; i++) {
21109
+ const value = rawData[i];
21110
+ if (value !== 0x00 && value !== 0x20) {
21111
+ return false;
21112
+ }
21113
+ }
21114
+ return true;
21115
+ }
21116
+ static getHDUType(header, index) {
21117
+ if (index === 0) {
21118
+ return "PRIMARY";
21119
+ }
21120
+ const xtension = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.XTENSION);
21121
+ if (xtension === null) {
21122
+ return "UNKNOWN";
21123
+ }
21124
+ switch (xtension.toUpperCase()) {
21125
+ case "IMAGE":
21126
+ return "IMAGE";
21127
+ case "BINTABLE":
21128
+ return "BINTABLE";
21129
+ case "TABLE":
21130
+ return "TABLE";
21131
+ default:
21132
+ return "UNKNOWN";
21133
+ }
21134
+ }
21135
+ static createImageHDU(header, rawPayload, dataOffset, dataByteLength, primary, options) {
21136
+ const finalHeader = options.computeDataMinMax
21137
+ ? (ParsePayload.computePhysicalMinAndMax(header, rawPayload) ?? header)
21138
+ : header;
21139
+ const bitpix = ParseHeader.getFITSItemValue(finalHeader, FITSHeaderManager.BITPIX);
21140
+ if (bitpix === null) {
21141
+ throw new Error("BITPIX not defined.");
21142
+ }
21143
+ const shape = FITSImageUtils.getShape(finalHeader);
21144
+ const typedData = ParsePayload.createTypedArray(rawPayload, bitpix);
21145
+ if (primary) {
21146
+ return new PrimaryHDU(finalHeader, rawPayload, dataOffset, dataByteLength, bitpix, shape, typedData);
21147
+ }
21148
+ return new ImageHDU(finalHeader, rawPayload, dataOffset, dataByteLength, bitpix, shape, typedData);
21149
+ }
21150
+ static getImagePayloadByteLength(header) {
21151
+ const bitpix = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BITPIX);
21152
+ if (bitpix === null) {
21153
+ throw new Error("BITPIX not defined.");
21154
+ }
21155
+ ParsePayload.assertSupportedBITPIX(bitpix);
21156
+ const shape = FITSImageUtils.getShape(header);
21157
+ if (shape.length === 0) {
21158
+ return 0;
21159
+ }
21160
+ const elementCount = shape.reduce((total, dimension) => total * dimension, 1);
21161
+ const bytesPerElement = Math.abs(bitpix) / 8;
21162
+ return elementCount * bytesPerElement;
21163
+ }
21164
+ static getBinaryTablePayloadByteLength(header) {
21165
+ const rowByteLength = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
21166
+ const rowCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
21167
+ const pcount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.PCOUNT) ?? 0;
21168
+ if (rowByteLength === null || rowCount === null) {
21169
+ throw new Error("BINTABLE requires NAXIS1 and NAXIS2.");
21170
+ }
21171
+ return rowByteLength * rowCount + pcount;
21172
+ }
21173
+ static getBinaryTableColumns(header) {
21174
+ const fieldCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.TFIELDS);
21175
+ if (fieldCount === null) {
21176
+ throw new Error("BINTABLE requires TFIELDS.");
21177
+ }
21178
+ const columns = [];
21179
+ let byteOffset = 0;
21180
+ for (let index = 1; index <= fieldCount; index++) {
21181
+ const tform = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TFORM", index));
21182
+ if (tform === null) {
21183
+ throw new Error(`Missing TFORM${index}.`);
21184
+ }
21185
+ const parsed = FITSBinaryTableUtils.parseTFORM(tform);
21186
+ const name = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TTYPE", index));
21187
+ const unit = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TUNIT", index));
21188
+ columns.push({
21189
+ index,
21190
+ name,
21191
+ format: tform,
21192
+ type: FITSParser.mapBinaryType(parsed.code),
21193
+ repeat: parsed.repeat,
21194
+ byteOffset,
21195
+ byteWidth: parsed.byteWidth,
21196
+ unit,
21197
+ scale: ParseHeader.getFITSItemValue(header, FITSHeaderManager.tableFieldKey("TSCAL", index)) ?? 1,
21198
+ zero: ParseHeader.getFITSItemValue(header, FITSHeaderManager.tableFieldKey("TZERO", index)) ?? 0,
21199
+ nullValue: ParseHeader.getFITSItemValue(header, FITSHeaderManager.tableFieldKey("TNULL", index)),
21200
+ });
21201
+ byteOffset += parsed.byteWidth;
21202
+ }
21203
+ return columns;
21204
+ }
21205
+ static mapBinaryType(code) {
21206
+ switch (code.toUpperCase()) {
21207
+ case "L":
21208
+ return "LOGICAL";
21209
+ case "X":
21210
+ return "BIT";
21211
+ case "B":
21212
+ return "UINT8";
21213
+ case "I":
21214
+ return "INT16";
21215
+ case "J":
21216
+ return "INT32";
21217
+ case "K":
21218
+ return "INT64";
21219
+ case "A":
21220
+ return "CHAR";
21221
+ case "E":
21222
+ return "FLOAT32";
21223
+ case "D":
21224
+ return "FLOAT64";
21225
+ case "C":
21226
+ return "COMPLEX64";
21227
+ case "M":
21228
+ return "COMPLEX128";
21229
+ default:
21230
+ return "UNKNOWN";
21231
+ }
21232
+ }
21233
+ static createBinaryTableHDU(header, rawPayload, dataOffset, dataByteLength) {
21234
+ const rowByteLength = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
21235
+ const rowCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
21236
+ if (rowByteLength === null || rowCount === null) {
21237
+ throw new Error("Invalid BINTABLE header.");
21238
+ }
21239
+ const columns = FITSParser.getBinaryTableColumns(header);
21240
+ const columnsByteWidth = columns.reduce((sum, column) => sum + column.byteWidth, 0);
21241
+ if (columnsByteWidth !== rowByteLength) {
21242
+ throw new Error(`BINTABLE columns occupy ${columnsByteWidth} bytes per row, ` +
21243
+ `but NAXIS1=${rowByteLength}.`);
21244
+ }
21245
+ return new BinaryTableHDU(header, rawPayload, dataOffset, dataByteLength, rowByteLength, rowCount, columns);
21246
+ }
21247
+ static getAsciiTablePayloadByteLength(header) {
21248
+ const rowByteLength = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
21249
+ const rowCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
21250
+ if (rowByteLength === null || rowCount === null) {
21251
+ throw new Error("ASCII TABLE requires NAXIS1 and NAXIS2.");
21252
+ }
21253
+ if (!Number.isInteger(rowByteLength) || rowByteLength < 0) {
21254
+ throw new Error(`Invalid ASCII TABLE NAXIS1=${rowByteLength}.`);
21255
+ }
21256
+ if (!Number.isInteger(rowCount) || rowCount < 0) {
21257
+ throw new Error(`Invalid ASCII TABLE NAXIS2=${rowCount}.`);
21258
+ }
21259
+ const pcount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.PCOUNT) ?? 0;
21260
+ if (pcount !== 0) {
21261
+ throw new Error(`ASCII TABLE requires PCOUNT=0, received ${pcount}.`);
21262
+ }
21263
+ return rowByteLength * rowCount;
21264
+ }
21265
+ static mapAsciiType(code) {
21266
+ switch (code.toUpperCase()) {
21267
+ case "A":
21268
+ return "CHAR";
21269
+ case "I":
21270
+ return "INTEGER";
21271
+ case "F":
21272
+ return "FLOAT";
21273
+ case "E":
21274
+ return "EXPONENTIAL";
21275
+ case "D":
21276
+ return "DOUBLE";
21277
+ default:
21278
+ return "UNKNOWN";
21279
+ }
21280
+ }
21281
+ static getAsciiTableColumns(header) {
21282
+ const fieldCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.TFIELDS);
21283
+ if (fieldCount === null) {
21284
+ throw new Error("ASCII TABLE requires TFIELDS.");
21285
+ }
21286
+ if (!Number.isInteger(fieldCount) || fieldCount < 0) {
21287
+ throw new Error(`Invalid ASCII TABLE TFIELDS=${fieldCount}.`);
21288
+ }
21289
+ const columns = [];
21290
+ for (let index = 1; index <= fieldCount; index++) {
21291
+ const tform = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TFORM", index));
21292
+ if (tform === null) {
21293
+ throw new Error(`Missing TFORM${index}.`);
21294
+ }
21295
+ const tbcol = ParseHeader.getFITSItemValue(header, FITSHeaderManager.tableFieldKey("TBCOL", index));
21296
+ if (tbcol === null) {
21297
+ throw new Error(`Missing TBCOL${index}.`);
21298
+ }
21299
+ if (!Number.isInteger(tbcol) || tbcol < 1) {
21300
+ throw new Error(`Invalid TBCOL${index}=${tbcol}.`);
21301
+ }
21302
+ const parsed = FITSAsciiTableUtils.parseTFORM(tform);
21303
+ const name = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TTYPE", index));
21304
+ const unit = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TUNIT", index));
21305
+ columns.push({
21306
+ index,
21307
+ name,
21308
+ format: tform,
21309
+ type: FITSParser.mapAsciiType(parsed.code),
21310
+ startColumn: tbcol,
21311
+ /*
21312
+ * FITS TBCOL is 1-based.
21313
+ * JavaScript offsets are 0-based.
21314
+ */
21315
+ byteOffset: tbcol - 1,
21316
+ width: parsed.width,
21317
+ decimals: parsed.decimals,
21318
+ unit,
21319
+ });
21320
+ }
21321
+ return columns;
21322
+ }
21323
+ static validateAsciiTableColumns(columns, rowByteLength) {
21324
+ for (const column of columns) {
21325
+ const endOffset = column.byteOffset + column.width;
21326
+ if (endOffset > rowByteLength) {
21327
+ throw new Error(`ASCII TABLE column ${column.index} ` +
21328
+ `extends to byte ${endOffset}, ` +
21329
+ `but NAXIS1=${rowByteLength}.`);
21330
+ }
21331
+ }
21332
+ }
21333
+ static createAsciiTableHDU(header, rawPayload, dataOffset, dataByteLength) {
21334
+ const rowByteLength = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
21335
+ const rowCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
21336
+ if (rowByteLength === null || rowCount === null) {
21337
+ throw new Error("Invalid ASCII TABLE header.");
21338
+ }
21339
+ const columns = FITSParser.getAsciiTableColumns(header);
21340
+ FITSParser.validateAsciiTableColumns(columns, rowByteLength);
21341
+ return new AsciiTableHDU(header, rawPayload, dataOffset, dataByteLength, rowByteLength, rowCount, columns);
21342
+ }
21343
+ static createMatrix(payload, header) {
21344
+ const NAXIS1 = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
21345
+ if (NAXIS1 === null) {
21346
+ throw new Error("NAXIS1 not defined.");
21347
+ }
21348
+ const NAXIS2 = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
21349
+ if (NAXIS2 === null) {
21350
+ throw new Error("NAXIS2 not defined.");
21351
+ }
21352
+ const BITPIX = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BITPIX);
21353
+ if (BITPIX === null) {
21354
+ throw new Error("BITPIX not defined.");
21355
+ }
21356
+ const bytesXelem = Math.abs(BITPIX / 8);
21357
+ // if (payload.length !== NAXIS1 * NAXIS2 * bytesXelem) {
21358
+ // throw new Error("Payload size does not match the expected matrix dimensions.");
21359
+ // }
21360
+ // const matrix: Array<Uint8Array> = [];
21361
+ const matrix = [];
21362
+ for (let i = 0; i < NAXIS2; i++) {
21363
+ matrix.push(payload.slice(i * NAXIS1 * bytesXelem, (i + 1) * NAXIS1 * bytesXelem));
21364
+ }
21365
+ return matrix;
21366
+ }
21367
+ /**
21368
+ * @deprecated Legacy FITSParsed writer API.
21369
+ */
21370
+ static saveFITSLocally(fitsParsed, path) {
21371
+ return FITSWriter.writeFITSFile(fitsParsed, path);
21372
+ }
21373
+ static async getFile(uri) {
21374
+ if (!uri.substring(0, 5).toLowerCase().includes("http")) {
21375
+ const p = await __webpack_require__.e(/* import() */ 64).then(__webpack_require__.bind(__webpack_require__, 7064));
21376
+ const rawData = await p.getLocalFile(uri);
21377
+ if (rawData?.length) {
21378
+ const uint8 = new Uint8Array(rawData);
21379
+ return uint8;
21380
+ }
21381
+ return new Uint8Array(0);
21382
+ }
21383
+ else {
21384
+ const p = await __webpack_require__.e(/* import() */ 911).then(__webpack_require__.bind(__webpack_require__, 1911));
21385
+ const rawData = await p.getFile(uri);
21386
+ if (rawData?.byteLength) {
21387
+ const uint8 = new Uint8Array(rawData);
21388
+ return uint8;
21389
+ }
21390
+ return new Uint8Array(0);
21391
+ }
21392
+ }
21393
+ }
21394
+ // const url = "http://skies.esac.esa.int/Herschel/normalized/PACS_hips160//Norder8/Dir40000/Npix47180.fits"
21395
+ // FITSParser.loadFITS(url).then((fits) => {
21396
+ // if (fits == null) {
21397
+ // return null
21398
+ // }
21399
+ // const path = "./fitsTest1.fits"
21400
+ // console.log(fits.header)
21401
+ // FITSParser.saveFITSLocally(fits, path)
21402
+ // console.log("finished")
21403
+ // })
21404
+ // // const file = "/Users/fabriziogiordano/Desktop/PhD/code/new/FITSParser/tests/inputs/empty.fits"
21405
+ // const file = "/Users/fabriziogiordano/Desktop/PhD/code/new/FITSParser/tests/inputs/Npix43348.fits"
21406
+ // FITSParser.loadFITS(file).then((fits) => {
21407
+ // if (fits == null) {
21408
+ // return null
21409
+ // }
21410
+ // const path = "./fitsTest2.fits"
21411
+ // console.log(fits.header)
21412
+ // FITSParser.saveFITSLocally(fits, path)
21413
+ // console.log("finished")
21414
+ // })
21415
+ //# sourceMappingURL=FITSParser.js.map
21416
+ ;// ./node_modules/jsfitsio/lib-esm/index.js
21417
+
21418
+
21419
+
21420
+
21421
+
21422
+
21423
+
21424
+
21425
+
21426
+
21427
+
21428
+
21429
+ //# sourceMappingURL=index.js.map
21430
+
21431
+ /***/ }
21432
+
21433
+ /******/ });
21434
+ /************************************************************************/
21435
+ /******/ // The module cache
21436
+ /******/ const __webpack_module_cache__ = {};
21437
+ /******/
21438
+ /******/ // The require function
21439
+ /******/ function __webpack_require__(moduleId) {
21440
+ /******/ // Check if module is in cache
21441
+ /******/ const cachedModule = __webpack_module_cache__[moduleId];
21442
+ /******/ if (cachedModule !== undefined) {
21443
+ /******/ return cachedModule.exports;
21444
+ /******/ }
21445
+ /******/ // Create a new module (and put it into the cache)
21446
+ /******/ const module = __webpack_module_cache__[moduleId] = {
21447
+ /******/ // no module.id needed
21448
+ /******/ // no module.loaded needed
21449
+ /******/ exports: {}
21450
+ /******/ };
21451
+ /******/
21452
+ /******/ // Execute the module function
21453
+ /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21454
+ /******/
21455
+ /******/ // Return the exports of the module
21456
+ /******/ return module.exports;
21457
+ /******/ }
21458
+ /******/
21459
+ /******/ // expose the modules object (__webpack_modules__)
21460
+ /******/ __webpack_require__.m = __webpack_modules__;
21461
+ /******/
21462
+ /************************************************************************/
21463
+ /******/ /* webpack/runtime/define property getters */
21464
+ /******/ (() => {
21465
+ /******/ // define getter/value functions for harmony exports
21466
+ /******/ __webpack_require__.d = (exports, definition) => {
21467
+ /******/ if(Array.isArray(definition)) {
21468
+ /******/ var i = 0;
21469
+ /******/ while(i < definition.length) {
21470
+ /******/ var key = definition[i++];
21471
+ /******/ var binding = definition[i++];
21472
+ /******/ if(!__webpack_require__.o(exports, key)) {
21473
+ /******/ if(binding === 0) {
21474
+ /******/ Object.defineProperty(exports, key, { enumerable: true, value: definition[i++] });
21475
+ /******/ } else {
21476
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: binding });
21477
+ /******/ }
21478
+ /******/ } else if(binding === 0) { i++; }
21479
+ /******/ }
21480
+ /******/ } else {
21481
+ /******/ for(var key in definition) {
21482
+ /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
21483
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
21484
+ /******/ }
21485
+ /******/ }
21486
+ /******/ }
21487
+ /******/ };
21488
+ /******/ })();
21489
+ /******/
21490
+ /******/ /* webpack/runtime/ensure chunk */
21491
+ /******/ (() => {
21492
+ /******/ __webpack_require__.f = {};
21493
+ /******/ // This file contains only the entry chunk.
21494
+ /******/ // The chunk loading function for additional chunks
21495
+ /******/ __webpack_require__.e = (chunkId) => {
21496
+ /******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
21497
+ /******/ __webpack_require__.f[key](chunkId, promises);
21498
+ /******/ return promises;
21499
+ /******/ }, []));
21500
+ /******/ };
21501
+ /******/ })();
21502
+ /******/
21503
+ /******/ /* webpack/runtime/get javascript chunk filename */
21504
+ /******/ (() => {
21505
+ /******/ // This function allow to reference async chunks
21506
+ /******/ __webpack_require__.u = (chunkId) => {
21507
+ /******/ // return url for filenames based on template
21508
+ /******/ return "" + chunkId + ".astroviewer.js";
21509
+ /******/ };
21510
+ /******/ })();
21511
+ /******/
21512
+ /******/ /* webpack/runtime/global */
21513
+ /******/ (() => {
21514
+ /******/ __webpack_require__.g = (function() {
21515
+ /******/ if (typeof globalThis === 'object') return globalThis;
21516
+ /******/ try {
21517
+ /******/ return this || new Function('return this')();
21518
+ /******/ } catch (e) {
21519
+ /******/ if (typeof window === 'object') return window;
21520
+ /******/ }
21521
+ /******/ })();
21522
+ /******/ })();
21523
+ /******/
21524
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
21525
+ /******/ (() => {
21526
+ /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
21527
+ /******/ })();
21528
+ /******/
21529
+ /******/ /* webpack/runtime/load script */
21530
+ /******/ (() => {
21531
+ /******/ const inProgress = {};
21532
+ /******/ const dataWebpackPrefix = "astroviewer:";
21533
+ /******/ // loadScript function to load a script via script tag
21534
+ /******/ __webpack_require__.l = (url, done, key, chunkId) => {
21535
+ /******/ if(inProgress[url]) { inProgress[url].push(done); return; }
21536
+ /******/ let script, needAttach;
21537
+ /******/ if(key !== undefined) {
21538
+ /******/ const scripts = document.getElementsByTagName("script");
21539
+ /******/ for(var i = 0; i < scripts.length; i++) {
21540
+ /******/ const s = scripts[i];
21541
+ /******/ if(s.getAttribute("src") == url || s.getAttribute("data-webpack") == dataWebpackPrefix + key) { script = s; break; }
21542
+ /******/ }
21543
+ /******/ }
21544
+ /******/ if(!script) {
21545
+ /******/ needAttach = true;
21546
+ /******/ script = document.createElement('script');
21547
+ /******/
21548
+ /******/ script.charset = 'utf-8';
21549
+ /******/ if (__webpack_require__.nc) {
21550
+ /******/ script.setAttribute("nonce", __webpack_require__.nc);
21551
+ /******/ }
21552
+ /******/ script.setAttribute("data-webpack", dataWebpackPrefix + key);
21553
+ /******/
21554
+ /******/ script.src = url;
21555
+ /******/ }
21556
+ /******/ inProgress[url] = [done];
21557
+ /******/ const onScriptComplete = (prev, event) => {
21558
+ /******/ // avoid mem leaks in IE.
21559
+ /******/ script.onerror = script.onload = null;
21560
+ /******/ clearTimeout(timeout);
21561
+ /******/ const doneFns = inProgress[url];
21562
+ /******/ delete inProgress[url];
21563
+ /******/ script.parentNode?.removeChild(script);
21564
+ /******/ doneFns?.forEach((fn) => (fn(event)));
21565
+ /******/ if(prev) return prev(event);
21566
+ /******/ }
21567
+ /******/ const timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);
21568
+ /******/ script.onerror = onScriptComplete.bind(null, script.onerror);
21569
+ /******/ script.onload = onScriptComplete.bind(null, script.onload);
21570
+ /******/ needAttach && document.head.appendChild(script);
21571
+ /******/ };
21572
+ /******/ })();
21573
+ /******/
21574
+ /******/ /* webpack/runtime/make namespace object */
21575
+ /******/ (() => {
21576
+ /******/ // define __esModule on exports
21577
+ /******/ __webpack_require__.r = (exports) => {
21578
+ /******/ if(Symbol.toStringTag) {
21579
+ /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
21580
+ /******/ }
21581
+ /******/ Object.defineProperty(exports, '__esModule', { value: true });
21582
+ /******/ };
21583
+ /******/ })();
21584
+ /******/
21585
+ /******/ /* webpack/runtime/publicPath */
21586
+ /******/ (() => {
21587
+ /******/ let scriptUrl;
21588
+ /******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + "";
21589
+ /******/ const document = __webpack_require__.g.document;
21590
+ /******/ if (!scriptUrl && document) {
21591
+ /******/ if (document.currentScript?.tagName.toUpperCase() === 'SCRIPT')
21592
+ /******/ scriptUrl = document.currentScript.src;
21593
+ /******/ if (!scriptUrl) {
21594
+ /******/ const scripts = document.getElementsByTagName("script");
21595
+ /******/ if(scripts.length) {
21596
+ /******/ let i = scripts.length - 1;
21597
+ /******/ while (i > -1 && (!scriptUrl || !/^http(s?):/.test(scriptUrl))) scriptUrl = scripts[i--].src;
21598
+ /******/ }
21599
+ /******/ }
21600
+ /******/ }
21601
+ /******/ // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration
21602
+ /******/ // or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.
21603
+ /******/ if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser");
21604
+ /******/ scriptUrl = scriptUrl.replace(/^blob:/, "").replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/");
21605
+ /******/ __webpack_require__.p = scriptUrl;
21606
+ /******/ })();
21607
+ /******/
21608
+ /******/ /* webpack/runtime/jsonp chunk loading */
21609
+ /******/ (() => {
21610
+ /******/ // no baseURI
21611
+ /******/
21612
+ /******/ // object to store loaded and loading chunks
21613
+ /******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
21614
+ /******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
21615
+ /******/ const installedChunks = {
21616
+ /******/ 792: 0
21617
+ /******/ };
21618
+ /******/
21619
+ /******/ __webpack_require__.f.j = (chunkId, promises) => {
21620
+ /******/ // JSONP chunk loading for javascript
21621
+ /******/ let installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;
21622
+ /******/ if(installedChunkData !== 0) { // 0 means "already installed".
21623
+ /******/
21624
+ /******/ // a Promise means "currently loading".
21625
+ /******/ if(installedChunkData) {
21626
+ /******/ promises.push(installedChunkData[2]);
21627
+ /******/ } else {
21628
+ /******/ if(true) { // all chunks have JS
21629
+ /******/ // setup Promise in chunk cache
21630
+ /******/ const promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));
21631
+ /******/ promises.push(installedChunkData[2] = promise);
21632
+ /******/
21633
+ /******/ // start chunk loading
21634
+ /******/ const url = __webpack_require__.p + __webpack_require__.u(chunkId);
21635
+ /******/ // create error before stack unwound to get useful stacktrace later
21636
+ /******/ const error = new Error();
21637
+ /******/ const loadingEnded = (event) => {
21638
+ /******/ if(__webpack_require__.o(installedChunks, chunkId)) {
21639
+ /******/ installedChunkData = installedChunks[chunkId];
21640
+ /******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined;
21641
+ /******/ if(installedChunkData) {
21642
+ /******/ const errorType = event && (event.type === 'load' ? 'missing' : event.type);
21643
+ /******/ const realSrc = event && event.target && event.target.src;
21644
+ /******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
21645
+ /******/ error.name = 'ChunkLoadError';
21646
+ /******/ error.type = errorType;
21647
+ /******/ error.request = realSrc;
21648
+ /******/ error.event = event;
21649
+ /******/ installedChunkData[1](error);
21650
+ /******/ }
21651
+ /******/ }
21652
+ /******/ };
21653
+ /******/ __webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId);
21654
+ /******/ }
21655
+ /******/ }
21656
+ /******/ }
21657
+ /******/ };
21658
+ /******/
21659
+ /******/ // no prefetching
21660
+ /******/
21661
+ /******/ // no preloaded
21662
+ /******/
21663
+ /******/ // no HMR
21664
+ /******/
21665
+ /******/ // no HMR manifest
21666
+ /******/
21667
+ /******/ // no on chunks loaded
21668
+ /******/
21669
+ /******/ // install a JSONP callback for chunk loading
21670
+ /******/ const webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
21671
+ /******/ let [chunkIds, moreModules, runtime] = data;
21672
+ /******/ // add "moreModules" to the modules object,
21673
+ /******/ // then flag all "chunkIds" as loaded and fire callback
21674
+ /******/ var moduleId, chunkId, i = 0;
21675
+ /******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
21676
+ /******/ for(moduleId in moreModules) {
21677
+ /******/ if(__webpack_require__.o(moreModules, moduleId)) {
21678
+ /******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
21679
+ /******/ }
21680
+ /******/ }
21681
+ /******/ if(runtime) var result = runtime(__webpack_require__);
21682
+ /******/ }
21683
+ /******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
21684
+ /******/ for(;i < chunkIds.length; i++) {
21685
+ /******/ chunkId = chunkIds[i];
21686
+ /******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
21687
+ /******/ installedChunks[chunkId][0]();
21688
+ /******/ }
21689
+ /******/ installedChunks[chunkId] = 0;
21690
+ /******/ }
21691
+ /******/
21692
+ /******/ }
21693
+ /******/
21694
+ /******/ const chunkLoadingGlobal = self["webpackChunkastroviewer"] = self["webpackChunkastroviewer"] || [];
21695
+ /******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
21696
+ /******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
19348
21697
  /******/ })();
19349
21698
  /******/
19350
21699
  /************************************************************************/