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.
- package/dist/64.astroviewer.cjs +37 -0
- package/dist/64.astroviewer.cjs.map +1 -0
- package/dist/64.astroviewer.js +41 -0
- package/dist/64.astroviewer.js.map +1 -0
- package/dist/64.astroviewer.min.js +2 -0
- package/dist/64.astroviewer.min.js.map +1 -0
- package/dist/911.astroviewer.cjs +4047 -0
- package/dist/911.astroviewer.cjs.map +1 -0
- package/dist/911.astroviewer.js +735 -0
- package/dist/911.astroviewer.js.map +1 -0
- package/dist/911.astroviewer.min.js +2 -0
- package/dist/911.astroviewer.min.js.map +1 -0
- package/dist/astroviewer.cjs +2704 -510
- package/dist/astroviewer.cjs.map +1 -1
- package/dist/astroviewer.js +2861 -512
- package/dist/astroviewer.js.map +1 -1
- package/dist/astroviewer.min.js +1 -1
- package/dist/astroviewer.min.js.map +1 -1
- package/lib-esm/AstroSphere.d.ts +1 -1
- package/lib-esm/AstroSphere.d.ts.map +1 -1
- package/lib-esm/AstroSphere.js +15 -25
- package/lib-esm/AstroSphere.js.map +1 -1
- package/lib-esm/AstroViewer.d.ts +25 -23
- package/lib-esm/AstroViewer.d.ts.map +1 -1
- package/lib-esm/AstroViewer.js +97 -67
- package/lib-esm/AstroViewer.js.map +1 -1
- package/lib-esm/model/hips/AllSky.d.ts +7 -3
- package/lib-esm/model/hips/AllSky.d.ts.map +1 -1
- package/lib-esm/model/hips/AllSky.js +93 -28
- package/lib-esm/model/hips/AllSky.js.map +1 -1
- package/lib-esm/model/hips/AncestorTile.d.ts +7 -4
- package/lib-esm/model/hips/AncestorTile.d.ts.map +1 -1
- package/lib-esm/model/hips/AncestorTile.js +91 -52
- package/lib-esm/model/hips/AncestorTile.js.map +1 -1
- package/lib-esm/model/hips/FitsTileLoader.d.ts +9 -0
- package/lib-esm/model/hips/FitsTileLoader.d.ts.map +1 -0
- package/lib-esm/model/hips/FitsTileLoader.js +65 -0
- package/lib-esm/model/hips/FitsTileLoader.js.map +1 -0
- package/lib-esm/model/hips/HiPS.d.ts +9 -5
- package/lib-esm/model/hips/HiPS.d.ts.map +1 -1
- package/lib-esm/model/hips/HiPS.js +120 -72
- package/lib-esm/model/hips/HiPS.js.map +1 -1
- package/lib-esm/model/hips/HiPSCoverage.d.ts +15 -0
- package/lib-esm/model/hips/HiPSCoverage.d.ts.map +1 -0
- package/lib-esm/model/hips/HiPSCoverage.js +148 -0
- package/lib-esm/model/hips/HiPSCoverage.js.map +1 -0
- package/lib-esm/model/hips/Tile.d.ts +8 -4
- package/lib-esm/model/hips/Tile.d.ts.map +1 -1
- package/lib-esm/model/hips/Tile.js +111 -55
- package/lib-esm/model/hips/Tile.js.map +1 -1
- package/lib-esm/model/hips/TileBuffer.d.ts +13 -4
- package/lib-esm/model/hips/TileBuffer.d.ts.map +1 -1
- package/lib-esm/model/hips/TileBuffer.js +46 -11
- package/lib-esm/model/hips/TileBuffer.js.map +1 -1
- package/lib-esm/model/hips/VisibleTilesManager.d.ts +5 -5
- package/lib-esm/model/hips/VisibleTilesManager.d.ts.map +1 -1
- package/lib-esm/model/hips/VisibleTilesManager.js +6 -20
- package/lib-esm/model/hips/VisibleTilesManager.js.map +1 -1
- package/lib-esm/shader/HiPSShaderProgram.d.ts +9 -2
- package/lib-esm/shader/HiPSShaderProgram.d.ts.map +1 -1
- package/lib-esm/shader/HiPSShaderProgram.js +91 -53
- package/lib-esm/shader/HiPSShaderProgram.js.map +1 -1
- package/lib-esm/shader/ShaderManager.d.ts +2 -0
- package/lib-esm/shader/ShaderManager.d.ts.map +1 -1
- package/lib-esm/shader/ShaderManager.js +193 -94
- package/lib-esm/shader/ShaderManager.js.map +1 -1
- package/package.json +3 -3
package/dist/astroviewer.cjs
CHANGED
|
@@ -3980,9 +3980,15 @@ class AstroSphere {
|
|
|
3980
3980
|
document.body.style.cursor = "grab";
|
|
3981
3981
|
const dragDirection = Global_js_1.default.insideSphere ? -1 : 1;
|
|
3982
3982
|
const dragSpeed = Global_js_1.default.insideSphere ? 10.0 : 1;
|
|
3983
|
-
const deltaX = (dragDirection *
|
|
3983
|
+
const deltaX = (dragDirection *
|
|
3984
|
+
dragSpeed *
|
|
3985
|
+
(newX - (this.lastMouseX ?? newX)) *
|
|
3986
|
+
Math.PI) /
|
|
3984
3987
|
canvas.width;
|
|
3985
|
-
const deltaY = (dragDirection *
|
|
3988
|
+
const deltaY = (dragDirection *
|
|
3989
|
+
dragSpeed *
|
|
3990
|
+
(newY - (this.lastMouseY ?? newY)) *
|
|
3991
|
+
Math.PI) /
|
|
3986
3992
|
canvas.height;
|
|
3987
3993
|
const filteredDelta = this.filterRotationDeltaByAstroLocks(deltaX, deltaY);
|
|
3988
3994
|
this.inertiaX += 0.1 * filteredDelta.deltaX;
|
|
@@ -4117,24 +4123,16 @@ class AstroSphere {
|
|
|
4117
4123
|
const pickerPoint = RayPickingUtils_js_1.default.getIntersectionPointWithSingleModel(maxX / 2, maxY / 2, this._healpixGrid, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
4118
4124
|
return (0, Utils_js_1.cartesianToSpherical)(pickerPoint);
|
|
4119
4125
|
}
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
const height = rect.height;
|
|
4124
|
-
const samples = [];
|
|
4125
|
-
for (let ix = 0; ix < sampleCount; ix++) {
|
|
4126
|
-
const x = sampleCount === 1 ? width / 2 : (ix / (sampleCount - 1)) * width;
|
|
4127
|
-
for (let iy = 0; iy < sampleCount; iy++) {
|
|
4128
|
-
const y = sampleCount === 1 ? height / 2 : (iy / (sampleCount - 1)) * height;
|
|
4129
|
-
const hit = RayPickingUtils_js_1.default.getIntersectionPointWithSingleModel(x, y, this._healpixGrid, this._webgl, this._camera, this._perspectiveMatrixManager.pMatrix);
|
|
4130
|
-
if (hit && hit.length > 0) {
|
|
4131
|
-
samples.push((0, Utils_js_1.cartesianToSpherical)(hit));
|
|
4132
|
-
}
|
|
4133
|
-
}
|
|
4126
|
+
changeHiPSFormat(format) {
|
|
4127
|
+
if (!this._activeHiPS) {
|
|
4128
|
+
throw new Error("No active HiPS.");
|
|
4134
4129
|
}
|
|
4135
|
-
|
|
4130
|
+
this._activeHiPS.changeFormat(format);
|
|
4136
4131
|
}
|
|
4137
4132
|
activateHiPS(hipsDescriptor) {
|
|
4133
|
+
if (this._activeHiPS) {
|
|
4134
|
+
this._healpixGrid.visibleTilesManager.tileBuffer.removeHiPS(this._activeHiPS);
|
|
4135
|
+
}
|
|
4138
4136
|
this._activeHiPS = new HiPS_js_1.HiPS(1, [0.0, 0.0, 0.0], 0, 0, hipsDescriptor, this._webgl, this._healpixGrid);
|
|
4139
4137
|
this._activeBaseLayer = "hips";
|
|
4140
4138
|
}
|
|
@@ -4544,14 +4542,6 @@ class AstroSphere {
|
|
|
4544
4542
|
Math.abs(this.inertiaX) > 0.02 ||
|
|
4545
4543
|
Math.abs(this.inertiaY) > 0.02 ||
|
|
4546
4544
|
nowForGrid - this.lastCameraMotionAt < 220;
|
|
4547
|
-
// const skyEntityDrawInput: SkyEntityDrawInput = {
|
|
4548
|
-
// fovDeg: this._healpixGrid.getMinFoV(),
|
|
4549
|
-
// camera: this._camera,
|
|
4550
|
-
// pMatrix: this._perspectiveMatrixManager.pMatrix,
|
|
4551
|
-
// centerSphericalDeg: this.updateCentralPoint().sphericalDeg,
|
|
4552
|
-
// fovPolygon: this._activeBaseLayer === 'xyz' ? this.getFoVPolygon() : undefined,
|
|
4553
|
-
// viewportSphericalSamples: this._activeBaseLayer === 'xyz' ? this.collectViewportSphericalSamples(7) : undefined,
|
|
4554
|
-
// }
|
|
4555
4545
|
const skyEntityDrawInput = {
|
|
4556
4546
|
fovDeg: stableFovDeg,
|
|
4557
4547
|
camera: this._camera,
|
|
@@ -4703,7 +4693,7 @@ class AstroViewer {
|
|
|
4703
4693
|
webglContextList = new Map();
|
|
4704
4694
|
viewfinderEl = null;
|
|
4705
4695
|
viewfinderVisible = Config_js_1.bootSetup.showViewfinder;
|
|
4706
|
-
viewfinderColor =
|
|
4696
|
+
viewfinderColor = "rgba(75,148,226,0.68)";
|
|
4707
4697
|
options = {};
|
|
4708
4698
|
// API
|
|
4709
4699
|
run() {
|
|
@@ -4841,7 +4831,7 @@ class AstroViewer {
|
|
|
4841
4831
|
this.astroSphere.activateXYZ(config);
|
|
4842
4832
|
}
|
|
4843
4833
|
activateXYZ2(config) {
|
|
4844
|
-
const descriptor = new XYZMapDescriptor_js_1.XYZMapDescriptor(config.name ??
|
|
4834
|
+
const descriptor = new XYZMapDescriptor_js_1.XYZMapDescriptor(config.name ?? "XYZ Earth2 Layer", config.urlTemplate, config.minZoom ?? 0, config.maxZoom ?? 8, config.segmentsPerSide ?? 48, config.maxCachedTiles ?? 384, 8, config.urlResolver);
|
|
4845
4835
|
this.astroSphere.activateXYZ2(descriptor);
|
|
4846
4836
|
}
|
|
4847
4837
|
activateWMTS(config) {
|
|
@@ -4866,8 +4856,8 @@ class AstroViewer {
|
|
|
4866
4856
|
return this.astroSphere.getMeshHiPSDebugStats();
|
|
4867
4857
|
}
|
|
4868
4858
|
async loadHiPS(baseUrl) {
|
|
4869
|
-
const hipsUrl = baseUrl.endsWith(
|
|
4870
|
-
const resp = await fetch(hipsUrl +
|
|
4859
|
+
const hipsUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
|
|
4860
|
+
const resp = await fetch(hipsUrl + "properties");
|
|
4871
4861
|
if (!resp.ok)
|
|
4872
4862
|
throw new Error(`HTTP ${resp.status} fetching properties`);
|
|
4873
4863
|
const propsText = await resp.text();
|
|
@@ -4877,20 +4867,20 @@ class AstroViewer {
|
|
|
4877
4867
|
// this.activateHiPS(desc);
|
|
4878
4868
|
}
|
|
4879
4869
|
async loadMeshHiPS(baseUrl, config = {}) {
|
|
4880
|
-
const meshHiPSUrl = baseUrl.endsWith(
|
|
4881
|
-
let propsText =
|
|
4882
|
-
const resp = await fetch(meshHiPSUrl +
|
|
4870
|
+
const meshHiPSUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
|
|
4871
|
+
let propsText = "";
|
|
4872
|
+
const resp = await fetch(meshHiPSUrl + "properties");
|
|
4883
4873
|
if (resp.ok) {
|
|
4884
4874
|
propsText = await resp.text();
|
|
4885
4875
|
}
|
|
4886
4876
|
else {
|
|
4887
|
-
const jsonResp = await fetch(meshHiPSUrl +
|
|
4877
|
+
const jsonResp = await fetch(meshHiPSUrl + "properties.json");
|
|
4888
4878
|
if (!jsonResp.ok)
|
|
4889
4879
|
throw new Error(`HTTP ${jsonResp.status} fetching MeshHiPS properties`);
|
|
4890
4880
|
const json = await jsonResp.json();
|
|
4891
4881
|
propsText = Object.entries(json)
|
|
4892
4882
|
.map(([key, value]) => `${key}=${String(value)}`)
|
|
4893
|
-
.join(
|
|
4883
|
+
.join("\n");
|
|
4894
4884
|
}
|
|
4895
4885
|
const desc = new MeshHiPSDescriptor_js_1.MeshHiPSDescriptor({ ...config, baseUrl: meshHiPSUrl }, propsText);
|
|
4896
4886
|
this.astroSphere.activateMeshHiPS(desc);
|
|
@@ -4908,6 +4898,12 @@ class AstroViewer {
|
|
|
4908
4898
|
getActiveHiPS() {
|
|
4909
4899
|
return this.astroSphere.activeHiPS;
|
|
4910
4900
|
}
|
|
4901
|
+
changeHiPSFormat(format) {
|
|
4902
|
+
this.astroSphere.changeHiPSFormat(format);
|
|
4903
|
+
}
|
|
4904
|
+
getActiveHiPSFormats() {
|
|
4905
|
+
return this.astroSphere.activeHiPS?.availableFormats ?? [];
|
|
4906
|
+
}
|
|
4911
4907
|
getActiveXYZ() {
|
|
4912
4908
|
return this.astroSphere.activeXYZ;
|
|
4913
4909
|
}
|
|
@@ -4995,13 +4991,13 @@ class AstroViewer {
|
|
|
4995
4991
|
return this.astroSphere.getFoVPolygon();
|
|
4996
4992
|
}
|
|
4997
4993
|
changeFoV(deg) {
|
|
4998
|
-
this, this.astroSphere.changeFoV(deg);
|
|
4994
|
+
(this, this.astroSphere.changeFoV(deg));
|
|
4999
4995
|
}
|
|
5000
4996
|
changeFoV2(deg) {
|
|
5001
|
-
this, this.astroSphere.changeFoV2(deg);
|
|
4997
|
+
(this, this.astroSphere.changeFoV2(deg));
|
|
5002
4998
|
}
|
|
5003
4999
|
changeFoV3(deg) {
|
|
5004
|
-
this, this.astroSphere.changeFoV3(deg);
|
|
5000
|
+
(this, this.astroSphere.changeFoV3(deg));
|
|
5005
5001
|
}
|
|
5006
5002
|
getInsideSphere() {
|
|
5007
5003
|
return this.astroSphere.getInsideSphere();
|
|
@@ -5047,13 +5043,13 @@ class AstroViewer {
|
|
|
5047
5043
|
this.webglContextList = new Map();
|
|
5048
5044
|
}
|
|
5049
5045
|
init(canvasEl) {
|
|
5050
|
-
console.log(
|
|
5046
|
+
console.log("init webgl");
|
|
5051
5047
|
this.canvas = canvasEl;
|
|
5052
5048
|
this.initViewfinder();
|
|
5053
|
-
const gl = this.canvas.getContext(
|
|
5049
|
+
const gl = this.canvas.getContext("webgl2", { alpha: false });
|
|
5054
5050
|
if (!gl) {
|
|
5055
|
-
alert(
|
|
5056
|
-
throw new Error(
|
|
5051
|
+
alert("Could not initialise WebGL, sorry :-(");
|
|
5052
|
+
throw new Error("WebGL2 not available");
|
|
5057
5053
|
}
|
|
5058
5054
|
// Extend with custom fields used elsewhere
|
|
5059
5055
|
this.webgl = gl;
|
|
@@ -5064,7 +5060,7 @@ class AstroViewer {
|
|
|
5064
5060
|
this.webgl.clearColor(0 * 0.00392156862, 16 * 0.00392156862, 50 * 0.00392156862, 0.7);
|
|
5065
5061
|
}
|
|
5066
5062
|
catch (e) {
|
|
5067
|
-
console.log(
|
|
5063
|
+
console.log("Error instantiating WebGL context");
|
|
5068
5064
|
}
|
|
5069
5065
|
this.initListeners();
|
|
5070
5066
|
// ; (global as any).gl = this.webgl
|
|
@@ -5076,40 +5072,64 @@ class AstroViewer {
|
|
|
5076
5072
|
const parent = this.canvas.parentElement;
|
|
5077
5073
|
if (!parent)
|
|
5078
5074
|
return;
|
|
5079
|
-
if (window.getComputedStyle(parent).position ===
|
|
5080
|
-
parent.style.position =
|
|
5081
|
-
}
|
|
5082
|
-
const viewfinder = document.createElement(
|
|
5083
|
-
viewfinder.setAttribute(
|
|
5084
|
-
viewfinder.setAttribute(
|
|
5085
|
-
viewfinder.style.position =
|
|
5086
|
-
viewfinder.style.left =
|
|
5087
|
-
viewfinder.style.top =
|
|
5088
|
-
viewfinder.style.width =
|
|
5089
|
-
viewfinder.style.height =
|
|
5090
|
-
viewfinder.style.transform =
|
|
5091
|
-
viewfinder.style.pointerEvents =
|
|
5092
|
-
viewfinder.style.zIndex =
|
|
5093
|
-
viewfinder.style.boxSizing =
|
|
5075
|
+
if (window.getComputedStyle(parent).position === "static") {
|
|
5076
|
+
parent.style.position = "relative";
|
|
5077
|
+
}
|
|
5078
|
+
const viewfinder = document.createElement("div");
|
|
5079
|
+
viewfinder.setAttribute("data-astro-viewfinder", "true");
|
|
5080
|
+
viewfinder.setAttribute("aria-hidden", "true");
|
|
5081
|
+
viewfinder.style.position = "absolute";
|
|
5082
|
+
viewfinder.style.left = "50%";
|
|
5083
|
+
viewfinder.style.top = "50%";
|
|
5084
|
+
viewfinder.style.width = "44px";
|
|
5085
|
+
viewfinder.style.height = "44px";
|
|
5086
|
+
viewfinder.style.transform = "translate(-50%, -50%)";
|
|
5087
|
+
viewfinder.style.pointerEvents = "none";
|
|
5088
|
+
viewfinder.style.zIndex = "1";
|
|
5089
|
+
viewfinder.style.boxSizing = "border-box";
|
|
5094
5090
|
const segments = [
|
|
5095
|
-
{
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5091
|
+
{
|
|
5092
|
+
left: "50%",
|
|
5093
|
+
top: "7px",
|
|
5094
|
+
width: "1px",
|
|
5095
|
+
height: "11px",
|
|
5096
|
+
transform: "translateX(-50%)",
|
|
5097
|
+
},
|
|
5098
|
+
{
|
|
5099
|
+
left: "50%",
|
|
5100
|
+
bottom: "7px",
|
|
5101
|
+
width: "1px",
|
|
5102
|
+
height: "11px",
|
|
5103
|
+
transform: "translateX(-50%)",
|
|
5104
|
+
},
|
|
5105
|
+
{
|
|
5106
|
+
left: "7px",
|
|
5107
|
+
top: "50%",
|
|
5108
|
+
width: "11px",
|
|
5109
|
+
height: "1px",
|
|
5110
|
+
transform: "translateY(-50%)",
|
|
5111
|
+
},
|
|
5112
|
+
{
|
|
5113
|
+
right: "7px",
|
|
5114
|
+
top: "50%",
|
|
5115
|
+
width: "11px",
|
|
5116
|
+
height: "1px",
|
|
5117
|
+
transform: "translateY(-50%)",
|
|
5118
|
+
},
|
|
5099
5119
|
];
|
|
5100
5120
|
for (const segmentDef of segments) {
|
|
5101
|
-
const segment = document.createElement(
|
|
5102
|
-
segment.style.position =
|
|
5103
|
-
segment.style.left = segmentDef.left ??
|
|
5104
|
-
segment.style.right = segmentDef.right ??
|
|
5105
|
-
segment.style.top = segmentDef.top ??
|
|
5106
|
-
segment.style.bottom = segmentDef.bottom ??
|
|
5121
|
+
const segment = document.createElement("div");
|
|
5122
|
+
segment.style.position = "absolute";
|
|
5123
|
+
segment.style.left = segmentDef.left ?? "auto";
|
|
5124
|
+
segment.style.right = segmentDef.right ?? "auto";
|
|
5125
|
+
segment.style.top = segmentDef.top ?? "auto";
|
|
5126
|
+
segment.style.bottom = segmentDef.bottom ?? "auto";
|
|
5107
5127
|
segment.style.width = segmentDef.width;
|
|
5108
5128
|
segment.style.height = segmentDef.height;
|
|
5109
5129
|
segment.style.transform = segmentDef.transform;
|
|
5110
|
-
segment.style.background =
|
|
5111
|
-
segment.style.borderRadius =
|
|
5112
|
-
segment.style.boxShadow =
|
|
5130
|
+
segment.style.background = "currentColor";
|
|
5131
|
+
segment.style.borderRadius = "999px";
|
|
5132
|
+
segment.style.boxShadow = "0 0 0 1px rgba(0, 0, 0, 0.14)";
|
|
5113
5133
|
viewfinder.appendChild(segment);
|
|
5114
5134
|
}
|
|
5115
5135
|
parent.appendChild(viewfinder);
|
|
@@ -5120,7 +5140,7 @@ class AstroViewer {
|
|
|
5120
5140
|
syncViewfinderVisibility() {
|
|
5121
5141
|
if (!this.viewfinderEl)
|
|
5122
5142
|
return;
|
|
5123
|
-
this.viewfinderEl.style.display = this.viewfinderVisible ?
|
|
5143
|
+
this.viewfinderEl.style.display = this.viewfinderVisible ? "block" : "none";
|
|
5124
5144
|
}
|
|
5125
5145
|
syncViewfinderColor() {
|
|
5126
5146
|
if (!this.viewfinderEl)
|
|
@@ -5128,9 +5148,9 @@ class AstroViewer {
|
|
|
5128
5148
|
this.viewfinderEl.style.color = this.viewfinderColor;
|
|
5129
5149
|
}
|
|
5130
5150
|
initListeners() {
|
|
5131
|
-
console.log(
|
|
5151
|
+
console.log("inside initListeners");
|
|
5132
5152
|
const resizeCanvas = () => {
|
|
5133
|
-
console.log(
|
|
5153
|
+
console.log("[resizeCanvas]");
|
|
5134
5154
|
const rect = this.canvas.getBoundingClientRect();
|
|
5135
5155
|
const dpr = window.devicePixelRatio || 1;
|
|
5136
5156
|
const newWidth = Math.max(1, Math.floor(rect.width * dpr));
|
|
@@ -5144,7 +5164,7 @@ class AstroViewer {
|
|
|
5144
5164
|
}
|
|
5145
5165
|
};
|
|
5146
5166
|
const handleContextLost = (event) => {
|
|
5147
|
-
console.log(
|
|
5167
|
+
console.log("[handleContextLost]");
|
|
5148
5168
|
event.preventDefault();
|
|
5149
5169
|
if (this.rafId !== null) {
|
|
5150
5170
|
cancelAnimationFrame(this.rafId);
|
|
@@ -5152,7 +5172,7 @@ class AstroViewer {
|
|
|
5152
5172
|
}
|
|
5153
5173
|
};
|
|
5154
5174
|
const handleContextRestored = (_event) => {
|
|
5155
|
-
console.log(
|
|
5175
|
+
console.log("[handleContextRestored]");
|
|
5156
5176
|
// this.webgl.viewportWidth = this.canvas.width
|
|
5157
5177
|
// this.webgl.viewportHeight = this.canvas.height
|
|
5158
5178
|
this.webgl.clearColor(0 * 0.00392156862, 16 * 0.00392156862, 50 * 0.00392156862, 0.7);
|
|
@@ -5160,16 +5180,16 @@ class AstroViewer {
|
|
|
5160
5180
|
this.rafId = requestAnimationFrame(() => this.tick());
|
|
5161
5181
|
};
|
|
5162
5182
|
// 🔥 ResizeObserver per pannelli / split / layout dinamici
|
|
5163
|
-
if (
|
|
5183
|
+
if ("ResizeObserver" in window) {
|
|
5164
5184
|
const ro = new ResizeObserver(() => {
|
|
5165
5185
|
resizeCanvas();
|
|
5166
5186
|
});
|
|
5167
5187
|
// Osserva il canvas o il suo parent (a tua scelta)
|
|
5168
5188
|
ro.observe(this.canvas);
|
|
5169
5189
|
}
|
|
5170
|
-
window.addEventListener(
|
|
5171
|
-
this.canvas.addEventListener(
|
|
5172
|
-
this.canvas.addEventListener(
|
|
5190
|
+
window.addEventListener("resize", resizeCanvas);
|
|
5191
|
+
this.canvas.addEventListener("webglcontextlost", handleContextLost, false);
|
|
5192
|
+
this.canvas.addEventListener("webglcontextrestored", handleContextRestored, false);
|
|
5173
5193
|
resizeCanvas();
|
|
5174
5194
|
}
|
|
5175
5195
|
tick() {
|
|
@@ -11887,6 +11907,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
11887
11907
|
};
|
|
11888
11908
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
11889
11909
|
const Global_js_1 = __importDefault(__webpack_require__(4382));
|
|
11910
|
+
const FitsTileLoader_js_1 = __webpack_require__(1399);
|
|
11890
11911
|
class AllSky {
|
|
11891
11912
|
_ready = false;
|
|
11892
11913
|
_hips;
|
|
@@ -11899,6 +11920,7 @@ class AllSky {
|
|
|
11899
11920
|
_texture = null;
|
|
11900
11921
|
_image;
|
|
11901
11922
|
_texurl;
|
|
11923
|
+
_fitsTile;
|
|
11902
11924
|
_textureLoaded = false;
|
|
11903
11925
|
_maxTiles = 0;
|
|
11904
11926
|
_numFacesXTile = 0;
|
|
@@ -11921,15 +11943,34 @@ class AllSky {
|
|
|
11921
11943
|
this.initImage();
|
|
11922
11944
|
}
|
|
11923
11945
|
initImage() {
|
|
11924
|
-
this._image = new Image();
|
|
11925
11946
|
this._texurl = `${this._baseurl}/Norder3/Allsky.${this._format}`;
|
|
11947
|
+
if (this._format === "fits") {
|
|
11948
|
+
void this.loadFits();
|
|
11949
|
+
return;
|
|
11950
|
+
}
|
|
11951
|
+
this.loadImage();
|
|
11952
|
+
}
|
|
11953
|
+
loadImage() {
|
|
11954
|
+
this._image = new Image();
|
|
11926
11955
|
this._image.onload = () => this.imageLoaded();
|
|
11927
11956
|
this._image.onerror = () => {
|
|
11928
|
-
console.error(
|
|
11957
|
+
console.error("File not found? %s", this._texurl);
|
|
11929
11958
|
};
|
|
11930
|
-
this._image.setAttribute(
|
|
11959
|
+
this._image.setAttribute("crossorigin", "anonymous");
|
|
11931
11960
|
this._image.src = this._texurl;
|
|
11932
11961
|
}
|
|
11962
|
+
async loadFits() {
|
|
11963
|
+
try {
|
|
11964
|
+
this._fitsTile = await (0, FitsTileLoader_js_1.loadFitsTile)(this._texurl);
|
|
11965
|
+
this.textureLoaded();
|
|
11966
|
+
this.initModelBuffer();
|
|
11967
|
+
this._textureLoaded = true;
|
|
11968
|
+
this._ready = true;
|
|
11969
|
+
}
|
|
11970
|
+
catch (error) {
|
|
11971
|
+
console.error(`[AllSky] Unable to load FITS atlas ${this._texurl}`, error);
|
|
11972
|
+
}
|
|
11973
|
+
}
|
|
11933
11974
|
imageLoaded() {
|
|
11934
11975
|
this.textureLoaded();
|
|
11935
11976
|
this.initModelBuffer();
|
|
@@ -11937,31 +11978,58 @@ class AllSky {
|
|
|
11937
11978
|
this._ready = true;
|
|
11938
11979
|
}
|
|
11939
11980
|
textureLoaded() {
|
|
11940
|
-
// hipsShaderProgram.enableProgram()
|
|
11941
11981
|
this._hipsShaderProgram.enableProgram();
|
|
11942
11982
|
const gl = this._webgl;
|
|
11943
11983
|
this._texture = gl.createTexture();
|
|
11944
11984
|
gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
|
|
11945
|
-
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,
|
|
11985
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._format !== "fits");
|
|
11946
11986
|
gl.bindTexture(gl.TEXTURE_2D, this._texture);
|
|
11947
|
-
|
|
11948
|
-
|
|
11949
|
-
|
|
11987
|
+
if (this._format === "fits") {
|
|
11988
|
+
const fits = this._fitsTile;
|
|
11989
|
+
if (!fits) {
|
|
11990
|
+
throw new Error(`FITS AllSky data not loaded: ${this._texurl}`);
|
|
11991
|
+
}
|
|
11992
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, fits.width, fits.height, 0, gl.RED, gl.FLOAT, fits.pixels);
|
|
11993
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
11994
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
11995
|
+
}
|
|
11996
|
+
else {
|
|
11997
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
|
|
11998
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
|
|
11999
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
12000
|
+
gl.generateMipmap(gl.TEXTURE_2D);
|
|
11950
12001
|
}
|
|
11951
|
-
gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
|
|
11952
|
-
gl.bindTexture(gl.TEXTURE_2D, this._texture);
|
|
11953
|
-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
|
|
11954
12002
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
11955
12003
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
11956
|
-
|
|
11957
|
-
|
|
11958
|
-
|
|
11959
|
-
|
|
11960
|
-
|
|
11961
|
-
|
|
11962
|
-
|
|
11963
|
-
|
|
11964
|
-
|
|
12004
|
+
if (!gl.isTexture(this._texture)) {
|
|
12005
|
+
console.log("error in texture");
|
|
12006
|
+
}
|
|
12007
|
+
}
|
|
12008
|
+
getFitsDataRange() {
|
|
12009
|
+
const hipsRange = this._hips.dataRange;
|
|
12010
|
+
if (hipsRange.min !== undefined &&
|
|
12011
|
+
hipsRange.max !== undefined &&
|
|
12012
|
+
Number.isFinite(hipsRange.min) &&
|
|
12013
|
+
Number.isFinite(hipsRange.max) &&
|
|
12014
|
+
hipsRange.max > hipsRange.min) {
|
|
12015
|
+
return {
|
|
12016
|
+
min: hipsRange.min,
|
|
12017
|
+
max: hipsRange.max,
|
|
12018
|
+
};
|
|
12019
|
+
}
|
|
12020
|
+
const fits = this._fitsTile;
|
|
12021
|
+
if (fits &&
|
|
12022
|
+
fits.dataMin !== null &&
|
|
12023
|
+
fits.dataMax !== null &&
|
|
12024
|
+
Number.isFinite(fits.dataMin) &&
|
|
12025
|
+
Number.isFinite(fits.dataMax) &&
|
|
12026
|
+
fits.dataMax > fits.dataMin) {
|
|
12027
|
+
return {
|
|
12028
|
+
min: fits.dataMin,
|
|
12029
|
+
max: fits.dataMax,
|
|
12030
|
+
};
|
|
12031
|
+
}
|
|
12032
|
+
return null;
|
|
11965
12033
|
}
|
|
11966
12034
|
initModelBuffer() {
|
|
11967
12035
|
const gl = this._webgl;
|
|
@@ -12026,13 +12094,16 @@ class AllSky {
|
|
|
12026
12094
|
this.vertexPosition[20 * this.vidx] = facesVec3Array[0].x;
|
|
12027
12095
|
this.vertexPosition[20 * this.vidx + 1] = facesVec3Array[0].y;
|
|
12028
12096
|
this.vertexPosition[20 * this.vidx + 2] = facesVec3Array[0].z;
|
|
12029
|
-
this.vertexPosition[20 * this.vidx + 3] =
|
|
12030
|
-
|
|
12097
|
+
this.vertexPosition[20 * this.vidx + 3] =
|
|
12098
|
+
s_step + base_s - s_pixel_size;
|
|
12099
|
+
this.vertexPosition[20 * this.vidx + 4] =
|
|
12100
|
+
1 - (t_step + base_t) + t_pixel_size;
|
|
12031
12101
|
// top right
|
|
12032
12102
|
this.vertexPosition[20 * this.vidx + 5] = facesVec3Array[1].x;
|
|
12033
12103
|
this.vertexPosition[20 * this.vidx + 6] = facesVec3Array[1].y;
|
|
12034
12104
|
this.vertexPosition[20 * this.vidx + 7] = facesVec3Array[1].z;
|
|
12035
|
-
this.vertexPosition[20 * this.vidx + 8] =
|
|
12105
|
+
this.vertexPosition[20 * this.vidx + 8] =
|
|
12106
|
+
s_step + base_s - s_pixel_size;
|
|
12036
12107
|
this.vertexPosition[20 * this.vidx + 9] = 1 - base_t - t_pixel_size;
|
|
12037
12108
|
// top left
|
|
12038
12109
|
this.vertexPosition[20 * this.vidx + 10] = facesVec3Array[2].x;
|
|
@@ -12045,7 +12116,8 @@ class AllSky {
|
|
|
12045
12116
|
this.vertexPosition[20 * this.vidx + 16] = facesVec3Array[3].y;
|
|
12046
12117
|
this.vertexPosition[20 * this.vidx + 17] = facesVec3Array[3].z;
|
|
12047
12118
|
this.vertexPosition[20 * this.vidx + 18] = base_s + s_pixel_size;
|
|
12048
|
-
this.vertexPosition[20 * this.vidx + 19] =
|
|
12119
|
+
this.vertexPosition[20 * this.vidx + 19] =
|
|
12120
|
+
1 - (t_step + base_t) + t_pixel_size;
|
|
12049
12121
|
this.vidx++;
|
|
12050
12122
|
}
|
|
12051
12123
|
}
|
|
@@ -12065,6 +12137,17 @@ class AllSky {
|
|
|
12065
12137
|
}
|
|
12066
12138
|
const gl = this._webgl;
|
|
12067
12139
|
this._hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx);
|
|
12140
|
+
if (this._format === "fits") {
|
|
12141
|
+
const range = this.getFitsDataRange();
|
|
12142
|
+
if (!range) {
|
|
12143
|
+
console.error(`[AllSky] No display range available for FITS atlas ${this._texurl}`);
|
|
12144
|
+
return false;
|
|
12145
|
+
}
|
|
12146
|
+
this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max);
|
|
12147
|
+
}
|
|
12148
|
+
else {
|
|
12149
|
+
this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, false);
|
|
12150
|
+
}
|
|
12068
12151
|
gl.enableVertexAttribArray(this._hipsShaderProgram.locations.vertexPositionAttribute);
|
|
12069
12152
|
gl.enableVertexAttribArray(this._hipsShaderProgram.locations.textureCoordAttribute);
|
|
12070
12153
|
// hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx)
|
|
@@ -12072,8 +12155,10 @@ class AllSky {
|
|
|
12072
12155
|
// gl.enableVertexAttribArray((hipsShaderProgram as any).locations.textureCoordAttribute)
|
|
12073
12156
|
gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
|
|
12074
12157
|
gl.bindTexture(gl.TEXTURE_2D, this._texture);
|
|
12075
|
-
|
|
12076
|
-
|
|
12158
|
+
const factorLocation = this._hipsShaderProgram.locations.textureAlpha[this._hipsShaderIndex];
|
|
12159
|
+
if (factorLocation) {
|
|
12160
|
+
gl.uniform1f(factorLocation, this.opacity);
|
|
12161
|
+
}
|
|
12077
12162
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBuffer);
|
|
12078
12163
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
|
|
12079
12164
|
gl.vertexAttribPointer(
|
|
@@ -12141,6 +12226,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12141
12226
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
12142
12227
|
const Global_js_1 = __importDefault(__webpack_require__(4382));
|
|
12143
12228
|
const FoVHelper_js_1 = __webpack_require__(229);
|
|
12229
|
+
const FitsTileLoader_js_1 = __webpack_require__(1399);
|
|
12144
12230
|
class AncestorTile {
|
|
12145
12231
|
_hips;
|
|
12146
12232
|
_tileno;
|
|
@@ -12154,7 +12240,8 @@ class AncestorTile {
|
|
|
12154
12240
|
_pixels = [];
|
|
12155
12241
|
_texture = null;
|
|
12156
12242
|
_image;
|
|
12157
|
-
_texurl =
|
|
12243
|
+
_texurl = "";
|
|
12244
|
+
_fitsTile;
|
|
12158
12245
|
vertexPosition;
|
|
12159
12246
|
vertexPositionBuffer;
|
|
12160
12247
|
vertexIndices;
|
|
@@ -12180,14 +12267,41 @@ class AncestorTile {
|
|
|
12180
12267
|
}
|
|
12181
12268
|
initImage() {
|
|
12182
12269
|
const dirnumber = Math.floor(this._tileno / 10000) * 10000;
|
|
12183
|
-
this._texurl =
|
|
12270
|
+
this._texurl =
|
|
12271
|
+
`${this._baseurl}/Norder${this._order}/Dir${dirnumber}` +
|
|
12272
|
+
`/Npix${this._tileno}.${this._format}`;
|
|
12273
|
+
if (this._format === "fits") {
|
|
12274
|
+
void this.loadFits();
|
|
12275
|
+
return;
|
|
12276
|
+
}
|
|
12277
|
+
this.loadImage();
|
|
12278
|
+
}
|
|
12279
|
+
async loadFits() {
|
|
12280
|
+
try {
|
|
12281
|
+
this._fitsTile = await (0, FitsTileLoader_js_1.loadFitsTile)(this._texurl);
|
|
12282
|
+
this.textureLoaded();
|
|
12283
|
+
const fits = this._fitsTile;
|
|
12284
|
+
if (!fits) {
|
|
12285
|
+
throw new Error(`FITS tile data not loaded: ${this._texurl}`);
|
|
12286
|
+
}
|
|
12287
|
+
const gl = this._webgl;
|
|
12288
|
+
gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
|
|
12289
|
+
gl.bindTexture(gl.TEXTURE_2D, this._texture);
|
|
12290
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, fits.width, fits.height, 0, gl.RED, gl.FLOAT, fits.pixels);
|
|
12291
|
+
this.initModelBuffer();
|
|
12292
|
+
this._ready = true;
|
|
12293
|
+
}
|
|
12294
|
+
catch (error) {
|
|
12295
|
+
console.error(`[AncestorTile] Unable to load FITS tile ${this._texurl}`, error);
|
|
12296
|
+
}
|
|
12297
|
+
}
|
|
12298
|
+
loadImage() {
|
|
12184
12299
|
this._image = new Image();
|
|
12185
12300
|
this._image.onload = () => this.imageLoaded();
|
|
12186
12301
|
this._image.onerror = () => {
|
|
12187
|
-
console.error(
|
|
12302
|
+
console.error("File not found? %s", this._texurl);
|
|
12188
12303
|
};
|
|
12189
|
-
this._image.crossOrigin =
|
|
12190
|
-
// If you ever need FITS handling, call this.loadImage() instead.
|
|
12304
|
+
this._image.crossOrigin = "anonymous";
|
|
12191
12305
|
this._image.src = this._texurl;
|
|
12192
12306
|
}
|
|
12193
12307
|
imageLoaded() {
|
|
@@ -12205,15 +12319,47 @@ class AncestorTile {
|
|
|
12205
12319
|
const gl = this._webgl;
|
|
12206
12320
|
this._texture = gl.createTexture();
|
|
12207
12321
|
gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
|
|
12208
|
-
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,
|
|
12322
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._format !== "fits");
|
|
12209
12323
|
gl.bindTexture(gl.TEXTURE_2D, this._texture);
|
|
12210
12324
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
12211
12325
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
12212
|
-
|
|
12213
|
-
|
|
12326
|
+
if (this._format === "fits") {
|
|
12327
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
12328
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
12329
|
+
}
|
|
12330
|
+
else {
|
|
12331
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
12332
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
12333
|
+
}
|
|
12214
12334
|
if (!gl.isTexture(this._texture)) {
|
|
12215
|
-
console.log(
|
|
12335
|
+
console.log("error in texture");
|
|
12336
|
+
}
|
|
12337
|
+
}
|
|
12338
|
+
getFitsDataRange() {
|
|
12339
|
+
const hipsRange = this._hips.dataRange;
|
|
12340
|
+
if (hipsRange.min !== undefined &&
|
|
12341
|
+
hipsRange.max !== undefined &&
|
|
12342
|
+
Number.isFinite(hipsRange.min) &&
|
|
12343
|
+
Number.isFinite(hipsRange.max) &&
|
|
12344
|
+
hipsRange.max > hipsRange.min) {
|
|
12345
|
+
return {
|
|
12346
|
+
min: hipsRange.min,
|
|
12347
|
+
max: hipsRange.max,
|
|
12348
|
+
};
|
|
12349
|
+
}
|
|
12350
|
+
const fits = this._fitsTile;
|
|
12351
|
+
if (fits &&
|
|
12352
|
+
fits.dataMin !== null &&
|
|
12353
|
+
fits.dataMax !== null &&
|
|
12354
|
+
Number.isFinite(fits.dataMin) &&
|
|
12355
|
+
Number.isFinite(fits.dataMax) &&
|
|
12356
|
+
fits.dataMax > fits.dataMin) {
|
|
12357
|
+
return {
|
|
12358
|
+
min: fits.dataMin,
|
|
12359
|
+
max: fits.dataMax,
|
|
12360
|
+
};
|
|
12216
12361
|
}
|
|
12362
|
+
return null;
|
|
12217
12363
|
}
|
|
12218
12364
|
initModelBuffer() {
|
|
12219
12365
|
const gl = this._webgl;
|
|
@@ -12256,43 +12402,6 @@ class AncestorTile {
|
|
|
12256
12402
|
}
|
|
12257
12403
|
return vertexIndices;
|
|
12258
12404
|
}
|
|
12259
|
-
// Version that uses getPointsForXyfNoStep (kept for reference; not used in this class)
|
|
12260
|
-
setupPositionAndTexture4Quadrant2(dxmin, dxmax, dymin, dymax, qidx, healpix, orderjump, origxyf) {
|
|
12261
|
-
this.vertexPosition[qidx] = new Float32Array(20 * (dxmax - dxmin) * (dymax - dymin));
|
|
12262
|
-
const step = 1 / (1 << orderjump);
|
|
12263
|
-
let p = 0;
|
|
12264
|
-
for (let dx = dxmin; dx < dxmax; dx++) {
|
|
12265
|
-
for (let dy = dymin; dy < dymax; dy++) {
|
|
12266
|
-
const facesVec3Array = healpix.getPointsForXyfNoStep(dx, dy, origxyf.face);
|
|
12267
|
-
const uindex = dy - (origxyf.iy << orderjump);
|
|
12268
|
-
const vindex = dx - (origxyf.ix << orderjump);
|
|
12269
|
-
this.vertexPosition[qidx][20 * p] = facesVec3Array[0].x;
|
|
12270
|
-
this.vertexPosition[qidx][20 * p + 1] = facesVec3Array[0].y;
|
|
12271
|
-
this.vertexPosition[qidx][20 * p + 2] = facesVec3Array[0].z;
|
|
12272
|
-
this.vertexPosition[qidx][20 * p + 3] = step + step * uindex;
|
|
12273
|
-
this.vertexPosition[qidx][20 * p + 4] = 1 - (step + step * vindex);
|
|
12274
|
-
this.vertexPosition[qidx][20 * p + 5] = facesVec3Array[1].x;
|
|
12275
|
-
this.vertexPosition[qidx][20 * p + 6] = facesVec3Array[1].y;
|
|
12276
|
-
this.vertexPosition[qidx][20 * p + 7] = facesVec3Array[1].z;
|
|
12277
|
-
this.vertexPosition[qidx][20 * p + 8] = step + step * uindex;
|
|
12278
|
-
this.vertexPosition[qidx][20 * p + 9] = 1 - step * vindex;
|
|
12279
|
-
this.vertexPosition[qidx][20 * p + 10] = facesVec3Array[2].x;
|
|
12280
|
-
this.vertexPosition[qidx][20 * p + 11] = facesVec3Array[2].y;
|
|
12281
|
-
this.vertexPosition[qidx][20 * p + 12] = facesVec3Array[2].z;
|
|
12282
|
-
this.vertexPosition[qidx][20 * p + 13] = step * uindex;
|
|
12283
|
-
this.vertexPosition[qidx][20 * p + 14] = 1 - step * vindex;
|
|
12284
|
-
this.vertexPosition[qidx][20 * p + 15] = facesVec3Array[3].x;
|
|
12285
|
-
this.vertexPosition[qidx][20 * p + 16] = facesVec3Array[3].y;
|
|
12286
|
-
this.vertexPosition[qidx][20 * p + 17] = facesVec3Array[3].z;
|
|
12287
|
-
this.vertexPosition[qidx][20 * p + 18] = step * uindex;
|
|
12288
|
-
this.vertexPosition[qidx][20 * p + 19] = 1 - (step + step * vindex);
|
|
12289
|
-
p++;
|
|
12290
|
-
}
|
|
12291
|
-
}
|
|
12292
|
-
this.vertexPositionBuffer[qidx] = this._webgl.createBuffer();
|
|
12293
|
-
this._webgl.bindBuffer(this._webgl.ARRAY_BUFFER, this.vertexPositionBuffer[qidx]);
|
|
12294
|
-
this._webgl.bufferData(this._webgl.ARRAY_BUFFER, this.vertexPosition[qidx], this._webgl.STATIC_DRAW);
|
|
12295
|
-
}
|
|
12296
12405
|
// Version used by the original JS, collecting _pixels via xyf2nest + getBoundaries
|
|
12297
12406
|
setupPositionAndTexture4Quadrant(dxmin, dxmax, dymin, dymax, qidx, healpix, orderjump, origxyf) {
|
|
12298
12407
|
const gl = this._webgl;
|
|
@@ -12344,12 +12453,26 @@ class AncestorTile {
|
|
|
12344
12453
|
quadrantsToDraw = q;
|
|
12345
12454
|
}
|
|
12346
12455
|
this._hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx);
|
|
12456
|
+
if (this._format === "fits") {
|
|
12457
|
+
const range = this.getFitsDataRange();
|
|
12458
|
+
if (!range) {
|
|
12459
|
+
console.error(`[AncestorTile] No display range available for FITS tile ${this._texurl}`);
|
|
12460
|
+
return false;
|
|
12461
|
+
}
|
|
12462
|
+
this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max);
|
|
12463
|
+
}
|
|
12464
|
+
else {
|
|
12465
|
+
this._hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, false);
|
|
12466
|
+
}
|
|
12347
12467
|
const gl = this._webgl;
|
|
12348
12468
|
gl.enableVertexAttribArray(this._hipsShaderProgram.locations.vertexPositionAttribute);
|
|
12349
12469
|
gl.enableVertexAttribArray(this._hipsShaderProgram.locations.textureCoordAttribute);
|
|
12350
12470
|
gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
|
|
12351
12471
|
gl.bindTexture(gl.TEXTURE_2D, this._texture);
|
|
12352
|
-
|
|
12472
|
+
const factorLocation = this._hipsShaderProgram.locations.textureAlpha[this._hipsShaderIndex];
|
|
12473
|
+
if (factorLocation) {
|
|
12474
|
+
gl.uniform1f(factorLocation, this.opacity);
|
|
12475
|
+
}
|
|
12353
12476
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
|
|
12354
12477
|
const elemno = this.vertexIndices.length;
|
|
12355
12478
|
quadrantsToDraw.forEach((qidx) => {
|
|
@@ -12376,8 +12499,9 @@ class AncestorTile {
|
|
|
12376
12499
|
: this._tileBuffer.getTile(childTileNo, childrenOrder, this._hips);
|
|
12377
12500
|
// childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx)
|
|
12378
12501
|
childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx, this._hipsShaderProgram);
|
|
12379
|
-
if (childTile.
|
|
12380
|
-
quadrantsToDraw.delete(
|
|
12502
|
+
if (childTile.getReadyState()) {
|
|
12503
|
+
quadrantsToDraw.delete(c);
|
|
12504
|
+
// quadrantsToDraw.delete((childTile as any)._tileno - (this._tileno << 2))
|
|
12381
12505
|
}
|
|
12382
12506
|
}
|
|
12383
12507
|
}
|
|
@@ -12387,6 +12511,81 @@ class AncestorTile {
|
|
|
12387
12511
|
exports["default"] = AncestorTile;
|
|
12388
12512
|
|
|
12389
12513
|
|
|
12514
|
+
/***/ },
|
|
12515
|
+
|
|
12516
|
+
/***/ 1399
|
|
12517
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
12518
|
+
|
|
12519
|
+
var __webpack_unused_export__;
|
|
12520
|
+
|
|
12521
|
+
/*
|
|
12522
|
+
* AstroViewer
|
|
12523
|
+
* Copyright (C) Fabrizio Giordano
|
|
12524
|
+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-AstroViewer-Commercial
|
|
12525
|
+
*
|
|
12526
|
+
* AstroViewer is dual-licensed under the GNU Affero General Public License
|
|
12527
|
+
* version 3 and a separate commercial license.
|
|
12528
|
+
*
|
|
12529
|
+
* See LICENSE.md, LICENSE-AGPL.md, and LICENSE-COMMERCIAL.md for details.
|
|
12530
|
+
*/
|
|
12531
|
+
__webpack_unused_export__ = ({ value: true });
|
|
12532
|
+
exports.loadFitsTile = loadFitsTile;
|
|
12533
|
+
const jsfitsio_1 = __webpack_require__(4971);
|
|
12534
|
+
async function loadFitsTile(url) {
|
|
12535
|
+
const fitsFile = await jsfitsio_1.FITSParser.loadFITSFile(url);
|
|
12536
|
+
if (!fitsFile?.primaryHDU) {
|
|
12537
|
+
throw new Error(`Unable to load FITS tile: ${url}`);
|
|
12538
|
+
}
|
|
12539
|
+
const image = fitsFile.primaryHDU;
|
|
12540
|
+
if (image.naxis !== 2) {
|
|
12541
|
+
throw new Error(`Expected a 2D FITS tile, got NAXIS=${image.naxis}: ${url}`);
|
|
12542
|
+
}
|
|
12543
|
+
const [width, height] = image.shape;
|
|
12544
|
+
if (!Number.isInteger(width) ||
|
|
12545
|
+
!Number.isInteger(height) ||
|
|
12546
|
+
width <= 0 ||
|
|
12547
|
+
height <= 0) {
|
|
12548
|
+
throw new Error(`Invalid FITS tile dimensions: ${url}`);
|
|
12549
|
+
}
|
|
12550
|
+
const data = image.typedData;
|
|
12551
|
+
if (!data || data.length !== width * height) {
|
|
12552
|
+
throw new Error(`Invalid FITS tile payload: ${url}`);
|
|
12553
|
+
}
|
|
12554
|
+
if (data instanceof BigInt64Array) {
|
|
12555
|
+
throw new Error(`BITPIX=64 FITS tiles are not supported for HiPS rendering: ${url}`);
|
|
12556
|
+
}
|
|
12557
|
+
const bscale = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.BSCALE) ?? 1;
|
|
12558
|
+
const bzero = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.BZERO) ?? 0;
|
|
12559
|
+
const blank = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.BLANK);
|
|
12560
|
+
const dataMin = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.DATAMIN);
|
|
12561
|
+
const dataMax = getNumericHeaderValue(image.header, jsfitsio_1.FITSHeaderManager.DATAMAX);
|
|
12562
|
+
const pixels = new Float32Array(data.length);
|
|
12563
|
+
for (let i = 0; i < data.length; i++) {
|
|
12564
|
+
const rawValue = data[i];
|
|
12565
|
+
if (!Number.isFinite(rawValue) || (blank !== null && rawValue === blank)) {
|
|
12566
|
+
pixels[i] = Number.NaN;
|
|
12567
|
+
continue;
|
|
12568
|
+
}
|
|
12569
|
+
pixels[i] = rawValue * bscale + bzero;
|
|
12570
|
+
}
|
|
12571
|
+
return {
|
|
12572
|
+
width,
|
|
12573
|
+
height,
|
|
12574
|
+
pixels,
|
|
12575
|
+
dataMin,
|
|
12576
|
+
dataMax,
|
|
12577
|
+
};
|
|
12578
|
+
}
|
|
12579
|
+
function getNumericHeaderValue(header, key) {
|
|
12580
|
+
const item = header.findById(key);
|
|
12581
|
+
if (!item) {
|
|
12582
|
+
return null;
|
|
12583
|
+
}
|
|
12584
|
+
const value = Number(item.value);
|
|
12585
|
+
return Number.isFinite(value) ? value : null;
|
|
12586
|
+
}
|
|
12587
|
+
|
|
12588
|
+
|
|
12390
12589
|
/***/ },
|
|
12391
12590
|
|
|
12392
12591
|
/***/ 229
|
|
@@ -12591,30 +12790,47 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
|
|
|
12591
12790
|
_allSky = true;
|
|
12592
12791
|
samplerIdx = 0;
|
|
12593
12792
|
colorMapIdx = 0;
|
|
12594
|
-
colorMap = ColorMaps_js_1.default[
|
|
12793
|
+
colorMap = ColorMaps_js_1.default["native"];
|
|
12595
12794
|
_healpixGrid;
|
|
12596
12795
|
// exposed read-only helpers
|
|
12597
|
-
get maxOrder() {
|
|
12598
|
-
|
|
12599
|
-
|
|
12600
|
-
get
|
|
12601
|
-
|
|
12602
|
-
|
|
12796
|
+
get maxOrder() {
|
|
12797
|
+
return this._maxorder;
|
|
12798
|
+
}
|
|
12799
|
+
get minOrder() {
|
|
12800
|
+
return this._minorder;
|
|
12801
|
+
}
|
|
12802
|
+
get baseURL() {
|
|
12803
|
+
return this._baseurl;
|
|
12804
|
+
}
|
|
12805
|
+
get format() {
|
|
12806
|
+
return this._format;
|
|
12807
|
+
}
|
|
12808
|
+
get propertiesRawText() {
|
|
12809
|
+
return this._descriptor.propertiesRawText;
|
|
12810
|
+
}
|
|
12811
|
+
get properties() {
|
|
12812
|
+
return this._descriptor.properties;
|
|
12813
|
+
}
|
|
12603
12814
|
constructor(radius, position, xrad, yrad, descriptor, webgl, healpixGrid) {
|
|
12604
12815
|
super(radius, position, xrad, yrad, descriptor.surveyName, webgl, descriptor.isGalactic);
|
|
12605
12816
|
this._descriptor = descriptor;
|
|
12606
12817
|
this.initGL(webgl);
|
|
12607
12818
|
this._healpixGrid = healpixGrid;
|
|
12608
|
-
this.
|
|
12609
|
-
// DEBUG logs kept from JS (optional)
|
|
12610
|
-
// eslint-disable-next-line no-console
|
|
12611
|
-
console.log('HiPS frame ' + descriptor.hipsFrame);
|
|
12612
|
-
// eslint-disable-next-line no-console
|
|
12613
|
-
console.log('HiPS minOrder ' + descriptor.minOrder);
|
|
12614
|
-
this._format = descriptor.imgFormats[0];
|
|
12819
|
+
this._format = this.selectDefaultFormat(descriptor.imgFormats);
|
|
12615
12820
|
this._baseurl = descriptor.url;
|
|
12616
12821
|
this._maxorder = descriptor.maxOrder;
|
|
12617
12822
|
this._minorder = descriptor.minOrder;
|
|
12823
|
+
if (this.isGalacticHips) {
|
|
12824
|
+
this._healpixGrid.visibleTilesManager.tileBuffer.addGalHiPS(this);
|
|
12825
|
+
}
|
|
12826
|
+
else {
|
|
12827
|
+
this._healpixGrid.visibleTilesManager.tileBuffer.addHiPS(this);
|
|
12828
|
+
}
|
|
12829
|
+
// DEBUG logs kept from JS (optional)
|
|
12830
|
+
// eslint-disable-next-line no-console
|
|
12831
|
+
console.log("HiPS frame " + descriptor.hipsFrame);
|
|
12832
|
+
// eslint-disable-next-line no-console
|
|
12833
|
+
console.log("HiPS minOrder " + descriptor.minOrder);
|
|
12618
12834
|
this.initShaders();
|
|
12619
12835
|
// pick initial order from a starting FoV
|
|
12620
12836
|
const fov = 180;
|
|
@@ -12624,39 +12840,52 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
|
|
|
12624
12840
|
this._allSkyTile = null;
|
|
12625
12841
|
// auto-detect all-sky: original code forces true
|
|
12626
12842
|
this._allSky = true;
|
|
12843
|
+
this.initBaseTiles();
|
|
12844
|
+
}
|
|
12845
|
+
initBaseTiles() {
|
|
12846
|
+
this._ancestorTiles = [];
|
|
12847
|
+
this._allSkyTile = null;
|
|
12627
12848
|
if (this._allSky) {
|
|
12628
12849
|
this._allSkyTile = new AllSky_js_1.default(this, this._webgl, this._healpixGrid.visibleTilesManager.tileBuffer, super.hipsShaderProgram);
|
|
12850
|
+
return;
|
|
12629
12851
|
}
|
|
12630
|
-
|
|
12631
|
-
|
|
12632
|
-
this._ancestorTiles.push(new AncestorTile_js_1.default(t, 0, this, this._healpixGrid.visibleTilesManager.tileBuffer, super.hipsShaderProgram, this._webgl));
|
|
12633
|
-
}
|
|
12852
|
+
for (let t = 0; t < 12; t++) {
|
|
12853
|
+
this._ancestorTiles.push(new AncestorTile_js_1.default(t, 0, this, this._healpixGrid.visibleTilesManager.tileBuffer, super.hipsShaderProgram, this._webgl));
|
|
12634
12854
|
}
|
|
12635
12855
|
}
|
|
12636
12856
|
getProperty(key) {
|
|
12637
12857
|
return this._descriptor.getProperty(key);
|
|
12638
12858
|
}
|
|
12639
12859
|
changeFormat(format) {
|
|
12640
|
-
|
|
12641
|
-
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
if (this.
|
|
12646
|
-
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
|
|
12654
|
-
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
|
|
12860
|
+
const normalizedFormat = format.toLowerCase();
|
|
12861
|
+
if (!this._descriptor.imgFormats.includes(normalizedFormat)) {
|
|
12862
|
+
throw new Error(`HiPS format "${format}" is not supported. ` +
|
|
12863
|
+
`Available formats: ${this._descriptor.imgFormats.join(", ")}`);
|
|
12864
|
+
}
|
|
12865
|
+
if (normalizedFormat === this._format.toLowerCase()) {
|
|
12866
|
+
return;
|
|
12867
|
+
}
|
|
12868
|
+
const tileBuffer = this._healpixGrid.visibleTilesManager.tileBuffer;
|
|
12869
|
+
/*
|
|
12870
|
+
* Remove Tile instances created using the previous format.
|
|
12871
|
+
*
|
|
12872
|
+
* TileBuffer invalidates by HiPS identity/base URL rather than by the
|
|
12873
|
+
* current format, so both active and cached resources are discarded.
|
|
12874
|
+
*/
|
|
12875
|
+
tileBuffer.invalidateHiPS(this);
|
|
12876
|
+
/*
|
|
12877
|
+
* Change format before recreating AllSky/AncestorTile because their
|
|
12878
|
+
* constructors read hips.format.
|
|
12879
|
+
*/
|
|
12880
|
+
this._format = normalizedFormat;
|
|
12881
|
+
/*
|
|
12882
|
+
* AllSky and AncestorTile also keep the format they were constructed
|
|
12883
|
+
* with, so they must be recreated.
|
|
12884
|
+
*/
|
|
12885
|
+
this.initBaseTiles();
|
|
12886
|
+
}
|
|
12887
|
+
get availableFormats() {
|
|
12888
|
+
return this._descriptor.imgFormats;
|
|
12660
12889
|
}
|
|
12661
12890
|
/**
|
|
12662
12891
|
* Shader colormap switcher
|
|
@@ -12669,60 +12898,60 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
|
|
|
12669
12898
|
* 6 -> cubehelix
|
|
12670
12899
|
*/
|
|
12671
12900
|
changeColorMap(colorMap) {
|
|
12672
|
-
console.log(
|
|
12901
|
+
console.log("HiPS.changeColorMap -> shaderProgram", super.hipsShaderProgram.shaderProgram);
|
|
12673
12902
|
this.colorMap = colorMap;
|
|
12674
12903
|
switch (colorMap.name) {
|
|
12675
|
-
case
|
|
12904
|
+
case "grayscale":
|
|
12676
12905
|
this.colorMapIdx = 1;
|
|
12677
12906
|
// hipsShaderProgram.setGrayscaleShader()
|
|
12678
|
-
this.colorMap = ColorMaps_js_1.default[
|
|
12907
|
+
this.colorMap = ColorMaps_js_1.default["grayscale"];
|
|
12679
12908
|
super.hipsShaderProgram.setGrayscaleShader();
|
|
12680
12909
|
break;
|
|
12681
|
-
case
|
|
12910
|
+
case "planck":
|
|
12682
12911
|
this.colorMapIdx = 2;
|
|
12683
|
-
this.colorMap = ColorMaps_js_1.default[
|
|
12912
|
+
this.colorMap = ColorMaps_js_1.default["planck"];
|
|
12684
12913
|
// hipsShaderProgram.setColorMapShader()
|
|
12685
12914
|
super.hipsShaderProgram.setColorMapShader();
|
|
12686
12915
|
break;
|
|
12687
|
-
case
|
|
12916
|
+
case "cmb":
|
|
12688
12917
|
this.colorMapIdx = 3;
|
|
12689
|
-
this.colorMap = ColorMaps_js_1.default[
|
|
12918
|
+
this.colorMap = ColorMaps_js_1.default["cmb"];
|
|
12690
12919
|
// hipsShaderProgram.setColorMapShader()
|
|
12691
12920
|
super.hipsShaderProgram.setColorMapShader();
|
|
12692
12921
|
break;
|
|
12693
|
-
case
|
|
12922
|
+
case "rainbow":
|
|
12694
12923
|
this.colorMapIdx = 4;
|
|
12695
|
-
this.colorMap = ColorMaps_js_1.default[
|
|
12924
|
+
this.colorMap = ColorMaps_js_1.default["rainbow"];
|
|
12696
12925
|
// hipsShaderProgram.setColorMapShader()
|
|
12697
12926
|
super.hipsShaderProgram.setColorMapShader();
|
|
12698
12927
|
break;
|
|
12699
|
-
case
|
|
12928
|
+
case "eosb":
|
|
12700
12929
|
this.colorMapIdx = 5;
|
|
12701
|
-
this.colorMap = ColorMaps_js_1.default[
|
|
12930
|
+
this.colorMap = ColorMaps_js_1.default["eosb"];
|
|
12702
12931
|
super.hipsShaderProgram.setColorMapShader();
|
|
12703
12932
|
// hipsShaderProgram.setColorMapShader()
|
|
12704
12933
|
break;
|
|
12705
|
-
case
|
|
12934
|
+
case "cubehelix":
|
|
12706
12935
|
this.colorMapIdx = 6;
|
|
12707
|
-
this.colorMap = ColorMaps_js_1.default[
|
|
12936
|
+
this.colorMap = ColorMaps_js_1.default["cubehelix"];
|
|
12708
12937
|
super.hipsShaderProgram.setColorMapShader();
|
|
12709
12938
|
// hipsShaderProgram.setColorMapShader()
|
|
12710
12939
|
break;
|
|
12711
|
-
case
|
|
12940
|
+
case "hot":
|
|
12712
12941
|
this.colorMapIdx = 7;
|
|
12713
|
-
this.colorMap = ColorMaps_js_1.default[
|
|
12942
|
+
this.colorMap = ColorMaps_js_1.default["hot"];
|
|
12714
12943
|
super.hipsShaderProgram.setColorMapShader();
|
|
12715
12944
|
// hipsShaderProgram.setColorMapShader()
|
|
12716
12945
|
break;
|
|
12717
|
-
case
|
|
12946
|
+
case "gray":
|
|
12718
12947
|
this.colorMapIdx = 8;
|
|
12719
|
-
this.colorMap = ColorMaps_js_1.default[
|
|
12948
|
+
this.colorMap = ColorMaps_js_1.default["gray"];
|
|
12720
12949
|
super.hipsShaderProgram.setColorMapShader();
|
|
12721
12950
|
// hipsShaderProgram.setColorMapShader()
|
|
12722
12951
|
break;
|
|
12723
|
-
case
|
|
12952
|
+
case "native":
|
|
12724
12953
|
this.colorMapIdx = 0;
|
|
12725
|
-
this.colorMap = ColorMaps_js_1.default[
|
|
12954
|
+
this.colorMap = ColorMaps_js_1.default["native"];
|
|
12726
12955
|
super.hipsShaderProgram.setNativeShader();
|
|
12727
12956
|
break;
|
|
12728
12957
|
default:
|
|
@@ -12737,6 +12966,30 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
|
|
|
12737
12966
|
// this.shaderProgram = super.hipsShaderProgram.shaderProgram
|
|
12738
12967
|
// this.shaderProgram = hipsShaderProgram.shaderProgram
|
|
12739
12968
|
}
|
|
12969
|
+
// private selectDefaultFormat(formats: string[]): string {
|
|
12970
|
+
// if (formats.includes("fits")) return "fits";
|
|
12971
|
+
// if (formats.includes("png")) return "png";
|
|
12972
|
+
// if (formats.includes("jpg")) return "jpg";
|
|
12973
|
+
// if (formats.length > 0) {
|
|
12974
|
+
// return formats[0];
|
|
12975
|
+
// }
|
|
12976
|
+
// throw new Error("HiPS descriptor does not define a tile format");
|
|
12977
|
+
// }
|
|
12978
|
+
selectDefaultFormat(formats) {
|
|
12979
|
+
if (formats.includes("png"))
|
|
12980
|
+
return "png";
|
|
12981
|
+
if (formats.includes("jpg"))
|
|
12982
|
+
return "jpg";
|
|
12983
|
+
if (formats.includes("fits"))
|
|
12984
|
+
return "fits";
|
|
12985
|
+
if (formats.length > 0) {
|
|
12986
|
+
return formats[0];
|
|
12987
|
+
}
|
|
12988
|
+
throw new Error("HiPS descriptor does not define a tile format");
|
|
12989
|
+
}
|
|
12990
|
+
get dataRange() {
|
|
12991
|
+
return this._descriptor.dataRange;
|
|
12992
|
+
}
|
|
12740
12993
|
getCurrentHealpixOrder() {
|
|
12741
12994
|
return this._visibleorder;
|
|
12742
12995
|
}
|
|
@@ -12746,7 +12999,7 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
|
|
|
12746
12999
|
? this._healpixGrid.visibleTilesManager.galVisibleTilesByOrder
|
|
12747
13000
|
: this._healpixGrid.visibleTilesManager.visibleTilesByOrder;
|
|
12748
13001
|
return {
|
|
12749
|
-
activeBaseLayer:
|
|
13002
|
+
activeBaseLayer: "hips",
|
|
12750
13003
|
hipsName: this._descriptor.surveyName,
|
|
12751
13004
|
hipsUrl: this._baseurl,
|
|
12752
13005
|
isGalactic: this.isGalacticHips,
|
|
@@ -12778,16 +13031,10 @@ class HiPS extends AbstractSkyEntity_js_1.AbstractSkyEntity {
|
|
|
12778
13031
|
super.hipsShaderProgram.setRuntimeColorMap(this.colorMap);
|
|
12779
13032
|
if (this._allSky && this._allSkyTile) {
|
|
12780
13033
|
if (this.isGalacticHips) {
|
|
12781
|
-
this._allSkyTile.draw(this._healpixGrid.visibleTilesManager.galVisibleTilesByOrder.order, this._healpixGrid.visibleTilesManager.galAncestorsMap,
|
|
12782
|
-
// visibleTilesManager.galVisibleTilesByOrder.order,
|
|
12783
|
-
// visibleTilesManager.galAncestorsMap,
|
|
12784
|
-
pMatrix, vMatrix, mMatrix, this.colorMapIdx);
|
|
13034
|
+
this._allSkyTile.draw(this._healpixGrid.visibleTilesManager.galVisibleTilesByOrder.order, this._healpixGrid.visibleTilesManager.galAncestorsMap, pMatrix, vMatrix, mMatrix, this.colorMapIdx);
|
|
12785
13035
|
}
|
|
12786
13036
|
else {
|
|
12787
|
-
this._allSkyTile.draw(this._healpixGrid.visibleTilesManager.visibleTilesByOrder.order, this._healpixGrid.visibleTilesManager.ancestorsMap,
|
|
12788
|
-
// visibleTilesManager.visibleTilesByOrder.order,
|
|
12789
|
-
// visibleTilesManager.ancestorsMap,
|
|
12790
|
-
pMatrix, vMatrix, mMatrix, this.colorMapIdx);
|
|
13037
|
+
this._allSkyTile.draw(this._healpixGrid.visibleTilesManager.visibleTilesByOrder.order, this._healpixGrid.visibleTilesManager.ancestorsMap, pMatrix, vMatrix, mMatrix, this.colorMapIdx);
|
|
12791
13038
|
}
|
|
12792
13039
|
return;
|
|
12793
13040
|
}
|
|
@@ -12980,6 +13227,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
12980
13227
|
// Tile.ts
|
|
12981
13228
|
const Global_js_1 = __importDefault(__webpack_require__(4382));
|
|
12982
13229
|
const FoVHelper_js_1 = __webpack_require__(229);
|
|
13230
|
+
const FitsTileLoader_js_1 = __webpack_require__(1399);
|
|
12983
13231
|
// ------------------------------------------------------------------------
|
|
12984
13232
|
class Tile {
|
|
12985
13233
|
_hips;
|
|
@@ -12994,8 +13242,9 @@ class Tile {
|
|
|
12994
13242
|
_image;
|
|
12995
13243
|
_textureLoaded = false;
|
|
12996
13244
|
_texture;
|
|
12997
|
-
_texurl =
|
|
13245
|
+
_texurl = "";
|
|
12998
13246
|
_hipsShaderIndex = 0;
|
|
13247
|
+
_fitsTile;
|
|
12999
13248
|
_cacheTime0;
|
|
13000
13249
|
_inView = true;
|
|
13001
13250
|
_amIStillInFoV_requsetID;
|
|
@@ -13052,50 +13301,66 @@ class Tile {
|
|
|
13052
13301
|
console.warn(`[Tile] Skipping tile request above max order: requested order ${this._order}, max order ${this._maxorder}, url ${this._baseurl}`);
|
|
13053
13302
|
return;
|
|
13054
13303
|
}
|
|
13055
|
-
this._image = new Image();
|
|
13056
13304
|
const dirnumber = Math.floor(this._tileno / 10000) * 10000;
|
|
13057
13305
|
this._texurl = `${this._baseurl}/Norder${this._order}/Dir${dirnumber}/Npix${this._tileno}.${this._format}`;
|
|
13306
|
+
if (this._format === "fits") {
|
|
13307
|
+
void this.loadFits();
|
|
13308
|
+
return;
|
|
13309
|
+
}
|
|
13310
|
+
this.loadImage();
|
|
13311
|
+
}
|
|
13312
|
+
loadImage() {
|
|
13313
|
+
this._image = new Image();
|
|
13058
13314
|
this._image.onload = () => this.imageLoaded();
|
|
13059
13315
|
this._image.onerror = () => {
|
|
13060
|
-
// console.error('File not found?', this._texurl)
|
|
13061
13316
|
this._ready = false;
|
|
13062
13317
|
this._abort = true;
|
|
13063
13318
|
this.destroyIntervals();
|
|
13064
13319
|
};
|
|
13065
|
-
this._image.crossOrigin =
|
|
13320
|
+
this._image.crossOrigin = "anonymous";
|
|
13066
13321
|
this._image.src = this._texurl;
|
|
13067
13322
|
}
|
|
13323
|
+
async loadFits() {
|
|
13324
|
+
try {
|
|
13325
|
+
this._fitsTile = await (0, FitsTileLoader_js_1.loadFitsTile)(this._texurl);
|
|
13326
|
+
this._ready = true;
|
|
13327
|
+
}
|
|
13328
|
+
catch (error) {
|
|
13329
|
+
console.error(`[Tile] Unable to load FITS tile ${this._texurl}`, error);
|
|
13330
|
+
this._ready = false;
|
|
13331
|
+
this._abort = true;
|
|
13332
|
+
this.destroyIntervals();
|
|
13333
|
+
}
|
|
13334
|
+
}
|
|
13068
13335
|
imageLoaded() {
|
|
13069
13336
|
// this.textureLoaded()
|
|
13070
13337
|
// this.initModelBuffer()
|
|
13071
13338
|
// this._textureLoaded = true
|
|
13072
13339
|
this._ready = true;
|
|
13073
13340
|
}
|
|
13074
|
-
// private textureLoaded(): void {
|
|
13075
13341
|
textureLoaded(hipsShaderProgram) {
|
|
13076
|
-
// this._hipsShaderProgram.enableProgram()
|
|
13077
13342
|
hipsShaderProgram.enableProgram();
|
|
13078
13343
|
const gl = this._webgl;
|
|
13079
13344
|
this._texture = gl.createTexture();
|
|
13080
13345
|
gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
|
|
13081
|
-
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,
|
|
13346
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, this._format !== "fits");
|
|
13082
13347
|
gl.bindTexture(gl.TEXTURE_2D, this._texture);
|
|
13083
|
-
if (
|
|
13084
|
-
|
|
13348
|
+
if (this._format === "fits") {
|
|
13349
|
+
const fits = this._fitsTile;
|
|
13350
|
+
if (!fits) {
|
|
13351
|
+
throw new Error(`FITS tile data not loaded: ${this._texurl}`);
|
|
13352
|
+
}
|
|
13353
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, fits.width, fits.height, 0, gl.RED, gl.FLOAT, fits.pixels);
|
|
13354
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
13355
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
13356
|
+
}
|
|
13357
|
+
else {
|
|
13358
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
|
|
13359
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
13360
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
13085
13361
|
}
|
|
13086
|
-
gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
|
|
13087
|
-
gl.bindTexture(gl.TEXTURE_2D, this._texture);
|
|
13088
|
-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
|
|
13089
13362
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
13090
13363
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
13091
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
13092
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
13093
|
-
// FIX: use the sampler location we fetched in enableShaders()
|
|
13094
|
-
// gl.uniform1i((this._hipsShaderProgram.locations as ShaderLocations).sampler, this._hipsShaderIndex)
|
|
13095
|
-
// gl.uniform1i((hipsShaderProgram.locations as ShaderLocations).sampler, this._hipsShaderIndex)
|
|
13096
|
-
if (!gl.isTexture(this._texture)) {
|
|
13097
|
-
console.warn('Texture creation failed');
|
|
13098
|
-
}
|
|
13099
13364
|
this.initModelBuffer();
|
|
13100
13365
|
this._textureLoaded = true;
|
|
13101
13366
|
}
|
|
@@ -13162,26 +13427,32 @@ class Tile {
|
|
|
13162
13427
|
this.vertexPosition[qidx][20 * p] = facesVec3Array[0].x;
|
|
13163
13428
|
this.vertexPosition[qidx][20 * p + 1] = facesVec3Array[0].y;
|
|
13164
13429
|
this.vertexPosition[qidx][20 * p + 2] = facesVec3Array[0].z;
|
|
13165
|
-
this.vertexPosition[qidx][20 * p + 3] =
|
|
13166
|
-
|
|
13430
|
+
this.vertexPosition[qidx][20 * p + 3] =
|
|
13431
|
+
step + step * uindex + s_pixel_size;
|
|
13432
|
+
this.vertexPosition[qidx][20 * p + 4] =
|
|
13433
|
+
1 - (step + step * vindex) - t_pixel_size;
|
|
13167
13434
|
// v1
|
|
13168
13435
|
this.vertexPosition[qidx][20 * p + 5] = facesVec3Array[1].x;
|
|
13169
13436
|
this.vertexPosition[qidx][20 * p + 6] = facesVec3Array[1].y;
|
|
13170
13437
|
this.vertexPosition[qidx][20 * p + 7] = facesVec3Array[1].z;
|
|
13171
|
-
this.vertexPosition[qidx][20 * p + 8] =
|
|
13172
|
-
|
|
13438
|
+
this.vertexPosition[qidx][20 * p + 8] =
|
|
13439
|
+
step + step * uindex + s_pixel_size;
|
|
13440
|
+
this.vertexPosition[qidx][20 * p + 9] =
|
|
13441
|
+
1 - step * vindex + t_pixel_size;
|
|
13173
13442
|
// v2
|
|
13174
13443
|
this.vertexPosition[qidx][20 * p + 10] = facesVec3Array[2].x;
|
|
13175
13444
|
this.vertexPosition[qidx][20 * p + 11] = facesVec3Array[2].y;
|
|
13176
13445
|
this.vertexPosition[qidx][20 * p + 12] = facesVec3Array[2].z;
|
|
13177
13446
|
this.vertexPosition[qidx][20 * p + 13] = step * uindex - s_pixel_size;
|
|
13178
|
-
this.vertexPosition[qidx][20 * p + 14] =
|
|
13447
|
+
this.vertexPosition[qidx][20 * p + 14] =
|
|
13448
|
+
1 - step * vindex + t_pixel_size;
|
|
13179
13449
|
// v3
|
|
13180
13450
|
this.vertexPosition[qidx][20 * p + 15] = facesVec3Array[3].x;
|
|
13181
13451
|
this.vertexPosition[qidx][20 * p + 16] = facesVec3Array[3].y;
|
|
13182
13452
|
this.vertexPosition[qidx][20 * p + 17] = facesVec3Array[3].z;
|
|
13183
13453
|
this.vertexPosition[qidx][20 * p + 18] = step * uindex - s_pixel_size;
|
|
13184
|
-
this.vertexPosition[qidx][20 * p + 19] =
|
|
13454
|
+
this.vertexPosition[qidx][20 * p + 19] =
|
|
13455
|
+
1 - (step + step * vindex) - t_pixel_size;
|
|
13185
13456
|
p++;
|
|
13186
13457
|
}
|
|
13187
13458
|
}
|
|
@@ -13189,6 +13460,32 @@ class Tile {
|
|
|
13189
13460
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBuffer[qidx]);
|
|
13190
13461
|
gl.bufferData(gl.ARRAY_BUFFER, this.vertexPosition[qidx], gl.STATIC_DRAW);
|
|
13191
13462
|
}
|
|
13463
|
+
getFitsDataRange() {
|
|
13464
|
+
const hipsRange = this._hips.dataRange;
|
|
13465
|
+
if (hipsRange.min !== undefined &&
|
|
13466
|
+
hipsRange.max !== undefined &&
|
|
13467
|
+
Number.isFinite(hipsRange.min) &&
|
|
13468
|
+
Number.isFinite(hipsRange.max) &&
|
|
13469
|
+
hipsRange.max > hipsRange.min) {
|
|
13470
|
+
return {
|
|
13471
|
+
min: hipsRange.min,
|
|
13472
|
+
max: hipsRange.max,
|
|
13473
|
+
};
|
|
13474
|
+
}
|
|
13475
|
+
const fits = this._fitsTile;
|
|
13476
|
+
if (fits &&
|
|
13477
|
+
fits.dataMin !== null &&
|
|
13478
|
+
fits.dataMax !== null &&
|
|
13479
|
+
Number.isFinite(fits.dataMin) &&
|
|
13480
|
+
Number.isFinite(fits.dataMax) &&
|
|
13481
|
+
fits.dataMax > fits.dataMin) {
|
|
13482
|
+
return {
|
|
13483
|
+
min: fits.dataMin,
|
|
13484
|
+
max: fits.dataMax,
|
|
13485
|
+
};
|
|
13486
|
+
}
|
|
13487
|
+
return null;
|
|
13488
|
+
}
|
|
13192
13489
|
get inView() {
|
|
13193
13490
|
return this._inView;
|
|
13194
13491
|
}
|
|
@@ -13203,7 +13500,9 @@ class Tile {
|
|
|
13203
13500
|
this._ready = true;
|
|
13204
13501
|
if (this._isGalacticHips) {
|
|
13205
13502
|
if (this._visibleTileManager.galAncestorsMap.has(this._order)) {
|
|
13206
|
-
if (!this._visibleTileManager.galAncestorsMap
|
|
13503
|
+
if (!this._visibleTileManager.galAncestorsMap
|
|
13504
|
+
.get(this._order)
|
|
13505
|
+
.includes(this._tileno)) {
|
|
13207
13506
|
this.moveToCache();
|
|
13208
13507
|
}
|
|
13209
13508
|
else {
|
|
@@ -13235,7 +13534,9 @@ class Tile {
|
|
|
13235
13534
|
}
|
|
13236
13535
|
else {
|
|
13237
13536
|
if (this._visibleTileManager.ancestorsMap.has(this._order)) {
|
|
13238
|
-
if (!this._visibleTileManager.ancestorsMap
|
|
13537
|
+
if (!this._visibleTileManager.ancestorsMap
|
|
13538
|
+
.get(this._order)
|
|
13539
|
+
.includes(this._tileno)) {
|
|
13239
13540
|
this.moveToCache();
|
|
13240
13541
|
}
|
|
13241
13542
|
else {
|
|
@@ -13281,33 +13582,39 @@ class Tile {
|
|
|
13281
13582
|
}
|
|
13282
13583
|
const gl = this._webgl;
|
|
13283
13584
|
hipsShaderProgram.enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx);
|
|
13284
|
-
|
|
13285
|
-
|
|
13286
|
-
|
|
13287
|
-
|
|
13288
|
-
|
|
13289
|
-
|
|
13585
|
+
if (this._format === "fits") {
|
|
13586
|
+
const range = this.getFitsDataRange();
|
|
13587
|
+
if (!range) {
|
|
13588
|
+
console.error(`[Tile] No display range available for FITS tile ${this._texurl}`);
|
|
13589
|
+
return;
|
|
13590
|
+
}
|
|
13591
|
+
hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, true, range.min, range.max);
|
|
13592
|
+
}
|
|
13593
|
+
else {
|
|
13594
|
+
hipsShaderProgram.setTextureDataMode(this._hipsShaderIndex, false);
|
|
13595
|
+
}
|
|
13596
|
+
const locations = hipsShaderProgram.locations;
|
|
13597
|
+
gl.enableVertexAttribArray(locations.vertexPositionAttribute);
|
|
13598
|
+
gl.enableVertexAttribArray(locations.textureCoordAttribute);
|
|
13290
13599
|
gl.activeTexture(gl.TEXTURE0 + this._hipsShaderIndex);
|
|
13291
13600
|
gl.bindTexture(gl.TEXTURE_2D, this._texture);
|
|
13292
|
-
|
|
13293
|
-
|
|
13601
|
+
const factorLocation = locations.textureAlpha[this._hipsShaderIndex];
|
|
13602
|
+
if (factorLocation) {
|
|
13603
|
+
gl.uniform1f(factorLocation, this.opacity);
|
|
13604
|
+
}
|
|
13294
13605
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.vertexIndexBuffer);
|
|
13295
13606
|
const elemno = this.vertexIndices.length;
|
|
13296
|
-
const indexType = this.vertexIndices instanceof Uint32Array
|
|
13607
|
+
const indexType = this.vertexIndices instanceof Uint32Array
|
|
13608
|
+
? gl.UNSIGNED_INT
|
|
13609
|
+
: gl.UNSIGNED_SHORT;
|
|
13297
13610
|
quadrantsToDraw.forEach((qidx) => {
|
|
13298
13611
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexPositionBuffer[qidx]);
|
|
13299
|
-
gl.vertexAttribPointer(
|
|
13300
|
-
|
|
13301
|
-
hipsShaderProgram.locations.vertexPositionAttribute, 3, gl.FLOAT, false, 5 * 4, 0);
|
|
13302
|
-
gl.vertexAttribPointer(
|
|
13303
|
-
// this._hipsShaderProgram.locations.textureCoordAttribute,
|
|
13304
|
-
hipsShaderProgram.locations.textureCoordAttribute, 2, gl.FLOAT, false, 5 * 4, 3 * 4);
|
|
13612
|
+
gl.vertexAttribPointer(locations.vertexPositionAttribute, 3, gl.FLOAT, false, 5 * 4, 0);
|
|
13613
|
+
gl.vertexAttribPointer(locations.textureCoordAttribute, 2, gl.FLOAT, false, 5 * 4, 3 * 4);
|
|
13305
13614
|
gl.drawElements(gl.TRIANGLES, elemno, indexType, 0);
|
|
13306
13615
|
});
|
|
13307
|
-
|
|
13308
|
-
|
|
13309
|
-
gl.disableVertexAttribArray(hipsShaderProgram.locations.vertexPositionAttribute);
|
|
13310
|
-
gl.disableVertexAttribArray(hipsShaderProgram.locations.textureCoordAttribute);
|
|
13616
|
+
gl.disableVertexAttribArray(locations.vertexPositionAttribute);
|
|
13617
|
+
gl.disableVertexAttribArray(locations.textureCoordAttribute);
|
|
13311
13618
|
}
|
|
13312
13619
|
drawChildren(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx, hipsShaderProgram) {
|
|
13313
13620
|
const quadrantsToDraw = new Set([0, 1, 2, 3]);
|
|
@@ -13321,13 +13628,9 @@ class Tile {
|
|
|
13321
13628
|
const childTile = this._isGalacticHips
|
|
13322
13629
|
? this._tileBuffer.getGalTile(childTileNo, childrenOrder, this._hips)
|
|
13323
13630
|
: this._tileBuffer.getTile(childTileNo, childrenOrder, this._hips);
|
|
13324
|
-
// const childTile = this._isGalacticHips
|
|
13325
|
-
// ? newTileBuffer.getGalTile(childTileNo, childrenOrder, this._hips)
|
|
13326
|
-
// : newTileBuffer.getTile(childTileNo, childrenOrder, this._hips)
|
|
13327
|
-
// childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx)
|
|
13328
13631
|
childTile.draw(visibleOrder, visibleTilesMap, pMatrix, vMatrix, mMatrix, colorMapIdx, hipsShaderProgram);
|
|
13329
|
-
if (childTile.
|
|
13330
|
-
quadrantsToDraw.delete(
|
|
13632
|
+
if (childTile.getReadyState()) {
|
|
13633
|
+
quadrantsToDraw.delete(c);
|
|
13331
13634
|
}
|
|
13332
13635
|
}
|
|
13333
13636
|
}
|
|
@@ -13393,7 +13696,7 @@ class TileBuffer {
|
|
|
13393
13696
|
/** Register an equatorial HiPS into the buffer. */
|
|
13394
13697
|
addHiPS(hips) {
|
|
13395
13698
|
if (this._activeHiPS.has(hips)) {
|
|
13396
|
-
console.error(
|
|
13699
|
+
console.error("HiPS already present in TileBuffer");
|
|
13397
13700
|
return;
|
|
13398
13701
|
}
|
|
13399
13702
|
this._activeHiPS.set(hips, new Map());
|
|
@@ -13401,7 +13704,7 @@ class TileBuffer {
|
|
|
13401
13704
|
/** Register a galactic HiPS into the buffer. */
|
|
13402
13705
|
addGalHiPS(hips) {
|
|
13403
13706
|
if (this._galActiveHiPS.has(hips)) {
|
|
13404
|
-
console.error(
|
|
13707
|
+
console.error("HiPS already present in TileBuffer");
|
|
13405
13708
|
return;
|
|
13406
13709
|
}
|
|
13407
13710
|
this._galActiveHiPS.set(hips, new Map());
|
|
@@ -13426,7 +13729,7 @@ class TileBuffer {
|
|
|
13426
13729
|
}
|
|
13427
13730
|
/** Fetch (or create) an equatorial tile, reviving from cache if present. */
|
|
13428
13731
|
getTile(tileno, order, hips) {
|
|
13429
|
-
const tileKey = this.key(order, tileno, hips
|
|
13732
|
+
const tileKey = this.key(order, tileno, hips);
|
|
13430
13733
|
if (!this._tiles.has(tileKey)) {
|
|
13431
13734
|
if (this._cachedTiles.has(tileKey)) {
|
|
13432
13735
|
const tile = this._cachedTiles.get(tileKey);
|
|
@@ -13444,7 +13747,7 @@ class TileBuffer {
|
|
|
13444
13747
|
}
|
|
13445
13748
|
/** Fetch (or create) a galactic tile, reviving from cache if present. */
|
|
13446
13749
|
getGalTile(tileno, order, hips) {
|
|
13447
|
-
const tileKey = this.key(order, tileno, hips
|
|
13750
|
+
const tileKey = this.key(order, tileno, hips);
|
|
13448
13751
|
if (!this._galTiles.has(tileKey)) {
|
|
13449
13752
|
if (this._galCachedTiles.has(tileKey)) {
|
|
13450
13753
|
const tile = this._galCachedTiles.get(tileKey);
|
|
@@ -13462,7 +13765,7 @@ class TileBuffer {
|
|
|
13462
13765
|
}
|
|
13463
13766
|
/** Move a tile (equatorial or galactic) into cache. */
|
|
13464
13767
|
moveTileToCache(tileno, order, hips) {
|
|
13465
|
-
const tileKey = this.key(order, tileno, hips
|
|
13768
|
+
const tileKey = this.key(order, tileno, hips);
|
|
13466
13769
|
if (this._tiles.has(tileKey)) {
|
|
13467
13770
|
const tile = this._tiles.get(tileKey);
|
|
13468
13771
|
tile.setCacheTime0();
|
|
@@ -13481,29 +13784,64 @@ class TileBuffer {
|
|
|
13481
13784
|
const now = Date.now();
|
|
13482
13785
|
for (const [tileKey, tile] of this._cachedTiles) {
|
|
13483
13786
|
const t0 = tile.cacheTime0;
|
|
13484
|
-
if (!tile.inView &&
|
|
13787
|
+
if (!tile.inView &&
|
|
13788
|
+
t0 !== undefined &&
|
|
13789
|
+
now - t0 > this._cacheAliveMilliSeconds) {
|
|
13485
13790
|
tile.destroyIntervals();
|
|
13486
13791
|
this._cachedTiles.delete(tileKey);
|
|
13487
13792
|
}
|
|
13488
13793
|
}
|
|
13489
13794
|
for (const [tileKey, tile] of this._galCachedTiles) {
|
|
13490
13795
|
const t0 = tile.cacheTime0;
|
|
13491
|
-
if (!tile.inView &&
|
|
13796
|
+
if (!tile.inView &&
|
|
13797
|
+
t0 !== undefined &&
|
|
13798
|
+
now - t0 > this._cacheAliveMilliSeconds) {
|
|
13492
13799
|
tile.destroyIntervals();
|
|
13493
13800
|
this._galCachedTiles.delete(tileKey);
|
|
13494
13801
|
}
|
|
13495
13802
|
}
|
|
13496
13803
|
}
|
|
13497
13804
|
/** Compose a stable key for maps. */
|
|
13498
|
-
key(order, tileno,
|
|
13499
|
-
return `${order}#${tileno}#${baseURL}`;
|
|
13805
|
+
key(order, tileno, hips) {
|
|
13806
|
+
return `${order}#${tileno}#${hips.baseURL}#${hips.format}`;
|
|
13807
|
+
}
|
|
13808
|
+
removeHiPS(hips) {
|
|
13809
|
+
this.invalidateHiPS(hips);
|
|
13810
|
+
this._activeHiPS.delete(hips);
|
|
13811
|
+
this._galActiveHiPS.delete(hips);
|
|
13812
|
+
}
|
|
13813
|
+
/**
|
|
13814
|
+
* Remove all active and cached tiles belonging to a specific HiPS.
|
|
13815
|
+
*
|
|
13816
|
+
* Tile keys contain the HiPS base URL and format. We intentionally
|
|
13817
|
+
* ignore the format here so that a format change removes resources
|
|
13818
|
+
* created with the previous format as well.
|
|
13819
|
+
*/
|
|
13820
|
+
invalidateHiPS(hips) {
|
|
13821
|
+
const belongsToHiPS = (tileKey) => tileKey.includes(`#${hips.baseURL}#`);
|
|
13822
|
+
const clearTiles = (tiles) => {
|
|
13823
|
+
for (const [tileKey, tile] of tiles) {
|
|
13824
|
+
if (!belongsToHiPS(tileKey)) {
|
|
13825
|
+
continue;
|
|
13826
|
+
}
|
|
13827
|
+
tile.destroyIntervals();
|
|
13828
|
+
tiles.delete(tileKey);
|
|
13829
|
+
}
|
|
13830
|
+
};
|
|
13831
|
+
clearTiles(this._tiles);
|
|
13832
|
+
clearTiles(this._cachedTiles);
|
|
13833
|
+
clearTiles(this._galTiles);
|
|
13834
|
+
clearTiles(this._galCachedTiles);
|
|
13500
13835
|
}
|
|
13501
13836
|
/** Optional: call to stop internal timers if you dispose this buffer. */
|
|
13502
13837
|
dispose() {
|
|
13503
13838
|
window.clearInterval(this._cleanerId);
|
|
13504
13839
|
}
|
|
13505
13840
|
get size() {
|
|
13506
|
-
return this._tiles.size +
|
|
13841
|
+
return (this._tiles.size +
|
|
13842
|
+
this._cachedTiles.size +
|
|
13843
|
+
this._galTiles.size +
|
|
13844
|
+
this._galCachedTiles.size);
|
|
13507
13845
|
}
|
|
13508
13846
|
get activeTileCount() {
|
|
13509
13847
|
return this._tiles.size + this._galTiles.size;
|
|
@@ -13581,11 +13919,8 @@ exports.VisibleTilesManager = void 0;
|
|
|
13581
13919
|
const Global_js_1 = __importDefault(__webpack_require__(4382));
|
|
13582
13920
|
const healpix_1 = __webpack_require__(4851);
|
|
13583
13921
|
const RayPickingUtils_js_1 = __importDefault(__webpack_require__(4639));
|
|
13584
|
-
// import { newTileBuffer } from './TileBuffer.js';
|
|
13585
13922
|
const TileBuffer_js_1 = __webpack_require__(4006);
|
|
13586
13923
|
const gl_matrix_1 = __webpack_require__(3890);
|
|
13587
|
-
// import healpixGridSingleton from '../grid/HealpixGridSingleton.js';
|
|
13588
|
-
// import {HealpixGridSingleton} from '../grid/HealpixGridSingleton.js';
|
|
13589
13924
|
const Config_js_1 = __webpack_require__(2919);
|
|
13590
13925
|
class VisibleTilesManager {
|
|
13591
13926
|
_visibleTilesByOrder;
|
|
@@ -13625,18 +13960,13 @@ class VisibleTilesManager {
|
|
|
13625
13960
|
init(insideSphere) {
|
|
13626
13961
|
this.initialised = true;
|
|
13627
13962
|
this.insideSphere = insideSphere;
|
|
13628
|
-
// this.computeVisiblePixels();
|
|
13629
|
-
// setInterval(() => this.computeVisiblePixels(), 500);
|
|
13630
13963
|
}
|
|
13631
13964
|
getVisibleOrder() {
|
|
13632
|
-
// return healpixGridSingleton.visibleorder;
|
|
13633
13965
|
return this._healpixGrid.visibleorder;
|
|
13634
13966
|
}
|
|
13635
|
-
// computeVisiblePixels(): void {
|
|
13636
13967
|
computeVisiblePixels(order, webgl, camera, pMatrix) {
|
|
13637
13968
|
if (!this.initialised)
|
|
13638
13969
|
return;
|
|
13639
|
-
// let order = healpixGridSingleton.visibleorder;
|
|
13640
13970
|
if (Global_js_1.default.insideSphere && order < 3) {
|
|
13641
13971
|
order = 3;
|
|
13642
13972
|
}
|
|
@@ -13656,8 +13986,6 @@ class VisibleTilesManager {
|
|
|
13656
13986
|
}
|
|
13657
13987
|
else {
|
|
13658
13988
|
const geomhealpix = Global_js_1.default.getHealpix(order);
|
|
13659
|
-
// const maxX = (global.gl as GL).canvas.width;
|
|
13660
|
-
// const maxY = (global.gl as GL).canvas.height;
|
|
13661
13989
|
const maxX = webgl.canvas.width;
|
|
13662
13990
|
const maxY = webgl.canvas.height;
|
|
13663
13991
|
// Sample a grid of screen points, project to the sphere, then to galactic
|
|
@@ -13677,13 +14005,11 @@ class VisibleTilesManager {
|
|
|
13677
14005
|
if (!pixels.includes(currPixNo)) {
|
|
13678
14006
|
pixels.push(currPixNo);
|
|
13679
14007
|
this._ancestorsMap.get(order).push(currPixNo);
|
|
13680
|
-
// newTileBuffer.addTile(order, currPixNo);
|
|
13681
14008
|
this._tileBuffer.addTile(order, currPixNo);
|
|
13682
14009
|
}
|
|
13683
14010
|
if (!galTiles.includes(galTileNo)) {
|
|
13684
14011
|
galTiles.push(galTileNo);
|
|
13685
14012
|
this._galAncestorsMap.get(order).push(galTileNo);
|
|
13686
|
-
// newTileBuffer.addGalTile(order, galTileNo);
|
|
13687
14013
|
this._tileBuffer.addGalTile(order, galTileNo);
|
|
13688
14014
|
}
|
|
13689
14015
|
}
|
|
@@ -13701,7 +14027,6 @@ class VisibleTilesManager {
|
|
|
13701
14027
|
const parent = pixels[p] >> (2 * o);
|
|
13702
14028
|
if (!list.includes(parent)) {
|
|
13703
14029
|
list.push(parent);
|
|
13704
|
-
// newTileBuffer.addTile(tgtOrder, parent);
|
|
13705
14030
|
this._tileBuffer.addTile(tgtOrder, parent);
|
|
13706
14031
|
}
|
|
13707
14032
|
}
|
|
@@ -13714,7 +14039,6 @@ class VisibleTilesManager {
|
|
|
13714
14039
|
const parent = galTiles[p] >> (2 * o);
|
|
13715
14040
|
if (!list.includes(parent)) {
|
|
13716
14041
|
list.push(parent);
|
|
13717
|
-
// newTileBuffer.addGalTile(tgtOrder, parent);
|
|
13718
14042
|
this._tileBuffer.addGalTile(tgtOrder, parent);
|
|
13719
14043
|
}
|
|
13720
14044
|
}
|
|
@@ -16078,7 +16402,7 @@ class HiPSShaderProgram {
|
|
|
16078
16402
|
_UBO_colorMapVariableInfo = {
|
|
16079
16403
|
r_palette: { index: 0, offset: 0 },
|
|
16080
16404
|
g_palette: { index: 0, offset: 0 },
|
|
16081
|
-
b_palette: { index: 0, offset: 0 }
|
|
16405
|
+
b_palette: { index: 0, offset: 0 },
|
|
16082
16406
|
};
|
|
16083
16407
|
gl_uniforms;
|
|
16084
16408
|
gl_attributes;
|
|
@@ -16087,54 +16411,60 @@ class HiPSShaderProgram {
|
|
|
16087
16411
|
constructor(webgl) {
|
|
16088
16412
|
this._webgl = webgl;
|
|
16089
16413
|
this.gl_uniforms = {
|
|
16090
|
-
sampler:
|
|
16091
|
-
factor:
|
|
16092
|
-
m_perspective:
|
|
16093
|
-
m_model:
|
|
16094
|
-
m_view:
|
|
16095
|
-
colormapIdx:
|
|
16096
|
-
colormap_red:
|
|
16097
|
-
colormap_green:
|
|
16098
|
-
colormap_blue:
|
|
16414
|
+
sampler: "uSampler0",
|
|
16415
|
+
factor: "uFactor0",
|
|
16416
|
+
m_perspective: "uPMatrix",
|
|
16417
|
+
m_model: "uMMatrix",
|
|
16418
|
+
m_view: "uVMatrix",
|
|
16419
|
+
colormapIdx: "cmapIdx",
|
|
16420
|
+
colormap_red: "r",
|
|
16421
|
+
colormap_green: "g",
|
|
16422
|
+
colormap_blue: "b",
|
|
16423
|
+
textureMode: "uTextureMode",
|
|
16424
|
+
dataMin: "uDataMin",
|
|
16425
|
+
dataMax: "uDataMax",
|
|
16099
16426
|
};
|
|
16100
16427
|
this.gl_attributes = {
|
|
16101
|
-
vertex_pos:
|
|
16102
|
-
text_coords:
|
|
16428
|
+
vertex_pos: "aVertexPosition",
|
|
16429
|
+
text_coords: "aTextureCoord",
|
|
16103
16430
|
};
|
|
16104
16431
|
this.locations = {
|
|
16105
16432
|
pMatrix: null,
|
|
16106
16433
|
mMatrix: null,
|
|
16107
16434
|
vMatrix: null,
|
|
16108
|
-
|
|
16109
|
-
textureAlpha: null,
|
|
16435
|
+
samplers: new Array(8).fill(null),
|
|
16436
|
+
textureAlpha: new Array(8).fill(null),
|
|
16437
|
+
textureMode: new Array(8).fill(null),
|
|
16438
|
+
dataMin: new Array(8).fill(null),
|
|
16439
|
+
dataMax: new Array(8).fill(null),
|
|
16110
16440
|
clorMapIdx: null,
|
|
16111
16441
|
vertexPositionAttribute: -1,
|
|
16112
|
-
textureCoordAttribute: -1
|
|
16442
|
+
textureCoordAttribute: -1,
|
|
16113
16443
|
};
|
|
16114
16444
|
}
|
|
16115
16445
|
get shaderProgram() {
|
|
16116
16446
|
const gl = this._webgl;
|
|
16117
16447
|
if (!this._shaderProgram) {
|
|
16118
|
-
|
|
16119
|
-
this._shaderProgram =
|
|
16120
|
-
this.initShaders();
|
|
16448
|
+
const program = gl.createProgram();
|
|
16449
|
+
this._shaderProgram = program;
|
|
16450
|
+
this.initShaders(program);
|
|
16121
16451
|
}
|
|
16122
|
-
;
|
|
16123
16452
|
gl.useProgram(this._shaderProgram);
|
|
16124
16453
|
return this._shaderProgram;
|
|
16125
16454
|
}
|
|
16126
16455
|
setRuntimeColorMap(colorMap) {
|
|
16127
16456
|
this._runtimeColorMap = colorMap;
|
|
16128
16457
|
}
|
|
16129
|
-
initShaders() {
|
|
16130
|
-
// const gl = global.gl
|
|
16458
|
+
initShaders(program) {
|
|
16459
|
+
// const gl = global.gl
|
|
16131
16460
|
const gl = this._webgl;
|
|
16132
16461
|
const fragmentShaderStr = ShaderManager_js_1.default.hipsNativeFS();
|
|
16133
16462
|
this._fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
|
|
16134
16463
|
gl.shaderSource(this._fragmentShader, fragmentShaderStr);
|
|
16135
16464
|
gl.compileShader(this._fragmentShader);
|
|
16136
16465
|
if (!gl.getShaderParameter(this._fragmentShader, gl.COMPILE_STATUS)) {
|
|
16137
|
-
alert(gl.getShaderInfoLog(this._fragmentShader) ||
|
|
16466
|
+
alert(gl.getShaderInfoLog(this._fragmentShader) ||
|
|
16467
|
+
"Fragment shader compile error");
|
|
16138
16468
|
return;
|
|
16139
16469
|
}
|
|
16140
16470
|
const vertexShaderStr = ShaderManager_js_1.default.hipsVS();
|
|
@@ -16142,43 +16472,44 @@ class HiPSShaderProgram {
|
|
|
16142
16472
|
gl.shaderSource(this._vertexShader, vertexShaderStr);
|
|
16143
16473
|
gl.compileShader(this._vertexShader);
|
|
16144
16474
|
if (!gl.getShaderParameter(this._vertexShader, gl.COMPILE_STATUS)) {
|
|
16145
|
-
alert(gl.getShaderInfoLog(this._vertexShader) ||
|
|
16475
|
+
alert(gl.getShaderInfoLog(this._vertexShader) ||
|
|
16476
|
+
"Vertex shader compile error");
|
|
16146
16477
|
return;
|
|
16147
16478
|
}
|
|
16148
|
-
gl.attachShader(
|
|
16149
|
-
gl.attachShader(
|
|
16150
|
-
gl.linkProgram(
|
|
16151
|
-
if (!gl.getProgramParameter(
|
|
16152
|
-
alert(
|
|
16479
|
+
gl.attachShader(program, this._vertexShader);
|
|
16480
|
+
gl.attachShader(program, this._fragmentShader);
|
|
16481
|
+
gl.linkProgram(program);
|
|
16482
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
16483
|
+
alert("Could not initialise shaders");
|
|
16153
16484
|
}
|
|
16154
16485
|
}
|
|
16155
16486
|
enableProgram() {
|
|
16156
|
-
// (global.gl
|
|
16487
|
+
// (global.gl).useProgram(this._shaderProgram)
|
|
16157
16488
|
this._webgl.useProgram(this.shaderProgram);
|
|
16158
16489
|
}
|
|
16159
16490
|
setGrayscaleShader() {
|
|
16160
|
-
// const gl = global.gl
|
|
16491
|
+
// const gl = global.gl
|
|
16161
16492
|
const gl = this._webgl;
|
|
16162
16493
|
gl.detachShader(this.shaderProgram, this._fragmentShader);
|
|
16163
16494
|
const fragmentShaderStr = ShaderManager_js_1.default.hipsGrayscaleFS();
|
|
16164
16495
|
this.changeFSShader(fragmentShaderStr);
|
|
16165
16496
|
}
|
|
16166
16497
|
setNativeShader() {
|
|
16167
|
-
// const gl = global.gl
|
|
16498
|
+
// const gl = global.gl
|
|
16168
16499
|
const gl = this._webgl;
|
|
16169
16500
|
gl.detachShader(this.shaderProgram, this._fragmentShader);
|
|
16170
16501
|
const fragmentShaderStr = ShaderManager_js_1.default.hipsNativeFS();
|
|
16171
16502
|
this.changeFSShader(fragmentShaderStr);
|
|
16172
16503
|
}
|
|
16173
16504
|
setColorMapShader() {
|
|
16174
|
-
// const gl = global.gl
|
|
16505
|
+
// const gl = global.gl
|
|
16175
16506
|
const gl = this._webgl;
|
|
16176
16507
|
// Swap fragment shader
|
|
16177
16508
|
gl.detachShader(this.shaderProgram, this._fragmentShader);
|
|
16178
16509
|
const fragmentShaderStr = ShaderManager_js_1.default.hipsColorMapFS();
|
|
16179
16510
|
this.changeFSShader(fragmentShaderStr);
|
|
16180
16511
|
// UBO discovery for the "colormap" block
|
|
16181
|
-
const blockIndex = gl.getUniformBlockIndex(this.shaderProgram,
|
|
16512
|
+
const blockIndex = gl.getUniformBlockIndex(this.shaderProgram, "colormap");
|
|
16182
16513
|
// INVALID_INDEX == 0xFFFFFFFF in WebGL2
|
|
16183
16514
|
if (blockIndex === gl.INVALID_INDEX) {
|
|
16184
16515
|
console.warn('HiPSShaderProgram: uniform block "colormap" not found in hipsColorMapFS()');
|
|
@@ -16188,11 +16519,11 @@ class HiPSShaderProgram {
|
|
|
16188
16519
|
}
|
|
16189
16520
|
this._colorMapBlockIndex = blockIndex;
|
|
16190
16521
|
// const blockSize = gl.getActiveUniformBlockParameter(
|
|
16191
|
-
// this.shaderProgram
|
|
16522
|
+
// this.shaderProgram,
|
|
16192
16523
|
// blockIndex,
|
|
16193
16524
|
// gl.UNIFORM_BLOCK_DATA_SIZE
|
|
16194
16525
|
// ) as number
|
|
16195
|
-
const uboVariableNames = [
|
|
16526
|
+
const uboVariableNames = ["r_palette", "g_palette", "b_palette"];
|
|
16196
16527
|
const uboVariableIndices = gl.getUniformIndices(this.shaderProgram, uboVariableNames);
|
|
16197
16528
|
const uboVariableOffsets = gl.getActiveUniforms(this.shaderProgram, uboVariableIndices, gl.UNIFORM_OFFSET);
|
|
16198
16529
|
// Create buffer only once
|
|
@@ -16209,49 +16540,80 @@ class HiPSShaderProgram {
|
|
|
16209
16540
|
uboVariableNames.forEach((name, index) => {
|
|
16210
16541
|
this._UBO_colorMapVariableInfo[name] = {
|
|
16211
16542
|
index: uboVariableIndices[index],
|
|
16212
|
-
offset: uboVariableOffsets[index]
|
|
16543
|
+
offset: uboVariableOffsets[index],
|
|
16213
16544
|
};
|
|
16214
16545
|
});
|
|
16215
16546
|
}
|
|
16216
16547
|
changeFSShader(fragmentShaderStr) {
|
|
16217
|
-
// const gl = global.gl
|
|
16548
|
+
// const gl = global.gl
|
|
16218
16549
|
const gl = this._webgl;
|
|
16219
16550
|
this._fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
|
|
16220
16551
|
gl.shaderSource(this._fragmentShader, fragmentShaderStr);
|
|
16221
16552
|
gl.compileShader(this._fragmentShader);
|
|
16222
16553
|
if (!gl.getShaderParameter(this._fragmentShader, gl.COMPILE_STATUS)) {
|
|
16223
|
-
alert(gl.getShaderInfoLog(this._fragmentShader) ||
|
|
16554
|
+
alert(gl.getShaderInfoLog(this._fragmentShader) ||
|
|
16555
|
+
"Fragment shader compile error");
|
|
16224
16556
|
return;
|
|
16225
16557
|
}
|
|
16226
16558
|
gl.attachShader(this.shaderProgram, this._fragmentShader);
|
|
16227
16559
|
gl.linkProgram(this.shaderProgram);
|
|
16228
16560
|
if (!gl.getProgramParameter(this.shaderProgram, gl.LINK_STATUS)) {
|
|
16229
|
-
alert(
|
|
16561
|
+
alert("Could not initialise shaders");
|
|
16230
16562
|
}
|
|
16231
16563
|
gl.useProgram(this.shaderProgram);
|
|
16232
16564
|
}
|
|
16565
|
+
setTextureDataMode(samplerIndex, fits, min, max) {
|
|
16566
|
+
if (samplerIndex < 0 || samplerIndex >= 8) {
|
|
16567
|
+
throw new Error(`Invalid HiPS sampler index: ${samplerIndex}`);
|
|
16568
|
+
}
|
|
16569
|
+
const gl = this._webgl;
|
|
16570
|
+
const modeLocation = this.locations.textureMode[samplerIndex];
|
|
16571
|
+
if (modeLocation) {
|
|
16572
|
+
gl.uniform1i(modeLocation, fits ? 1 : 0);
|
|
16573
|
+
}
|
|
16574
|
+
if (!fits) {
|
|
16575
|
+
return;
|
|
16576
|
+
}
|
|
16577
|
+
if (min === undefined ||
|
|
16578
|
+
max === undefined ||
|
|
16579
|
+
!Number.isFinite(min) ||
|
|
16580
|
+
!Number.isFinite(max) ||
|
|
16581
|
+
max <= min) {
|
|
16582
|
+
throw new Error("Invalid FITS display range.");
|
|
16583
|
+
}
|
|
16584
|
+
const minLocation = this.locations.dataMin[samplerIndex];
|
|
16585
|
+
const maxLocation = this.locations.dataMax[samplerIndex];
|
|
16586
|
+
if (minLocation) {
|
|
16587
|
+
gl.uniform1f(minLocation, min);
|
|
16588
|
+
}
|
|
16589
|
+
if (maxLocation) {
|
|
16590
|
+
gl.uniform1f(maxLocation, max);
|
|
16591
|
+
}
|
|
16592
|
+
}
|
|
16233
16593
|
enableShaders(pMatrix, vMatrix, mMatrix, colorMapIdx) {
|
|
16234
|
-
// const gl = global.gl
|
|
16594
|
+
// const gl = global.gl
|
|
16235
16595
|
const gl = this._webgl;
|
|
16236
16596
|
gl.useProgram(this.shaderProgram);
|
|
16237
16597
|
this.locations.pMatrix = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.m_perspective);
|
|
16238
16598
|
this.locations.mMatrix = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.m_model);
|
|
16239
16599
|
this.locations.vMatrix = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.m_view);
|
|
16240
|
-
this.locations.sampler = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.sampler);
|
|
16241
|
-
this.locations.textureAlpha = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.factor);
|
|
16242
16600
|
this.locations.clorMapIdx = gl.getUniformLocation(this.shaderProgram, this.gl_uniforms.colormapIdx);
|
|
16243
|
-
|
|
16244
|
-
|
|
16245
|
-
|
|
16246
|
-
|
|
16247
|
-
|
|
16248
|
-
|
|
16249
|
-
|
|
16601
|
+
for (let i = 0; i < 8; i++) {
|
|
16602
|
+
this.locations.samplers[i] = gl.getUniformLocation(this.shaderProgram, `uSampler${i}`);
|
|
16603
|
+
this.locations.textureAlpha[i] = gl.getUniformLocation(this.shaderProgram, `uFactor${i}`);
|
|
16604
|
+
this.locations.textureMode[i] = gl.getUniformLocation(this.shaderProgram, `uTextureMode${i}`);
|
|
16605
|
+
this.locations.dataMin[i] = gl.getUniformLocation(this.shaderProgram, `uDataMin${i}`);
|
|
16606
|
+
this.locations.dataMax[i] = gl.getUniformLocation(this.shaderProgram, `uDataMax${i}`);
|
|
16607
|
+
if (this.locations.samplers[i]) {
|
|
16608
|
+
gl.uniform1i(this.locations.samplers[i], i);
|
|
16609
|
+
}
|
|
16250
16610
|
}
|
|
16251
|
-
|
|
16611
|
+
gl.uniform1i(this.locations.clorMapIdx, colorMapIdx);
|
|
16252
16612
|
this.locations.vertexPositionAttribute = gl.getAttribLocation(this.shaderProgram, this.gl_attributes.vertex_pos);
|
|
16253
16613
|
this.locations.textureCoordAttribute = gl.getAttribLocation(this.shaderProgram, this.gl_attributes.text_coords);
|
|
16254
|
-
if (colorMapIdx >= 2 &&
|
|
16614
|
+
if (colorMapIdx >= 2 &&
|
|
16615
|
+
this._UBO_colorMapBuffer &&
|
|
16616
|
+
this._colorMapBlockIndex !== null) {
|
|
16255
16617
|
gl.uniformBlockBinding(this.shaderProgram, this._colorMapBlockIndex, 0);
|
|
16256
16618
|
gl.bindBuffer(gl.UNIFORM_BUFFER, this._UBO_colorMapBuffer);
|
|
16257
16619
|
let currentColorMap;
|
|
@@ -16624,15 +16986,6 @@ class ShaderManager {
|
|
|
16624
16986
|
|
|
16625
16987
|
in vec2 vTextureCoord;
|
|
16626
16988
|
|
|
16627
|
-
uniform sampler2D uSampler0;
|
|
16628
|
-
uniform sampler2D uSampler1;
|
|
16629
|
-
uniform sampler2D uSampler2;
|
|
16630
|
-
uniform sampler2D uSampler3;
|
|
16631
|
-
uniform sampler2D uSampler4;
|
|
16632
|
-
uniform sampler2D uSampler5;
|
|
16633
|
-
uniform sampler2D uSampler6;
|
|
16634
|
-
uniform sampler2D uSampler7;
|
|
16635
|
-
|
|
16636
16989
|
uniform float uFactor0;
|
|
16637
16990
|
uniform float uFactor1;
|
|
16638
16991
|
uniform float uFactor2;
|
|
@@ -16642,23 +16995,53 @@ class ShaderManager {
|
|
|
16642
16995
|
uniform float uFactor6;
|
|
16643
16996
|
uniform float uFactor7;
|
|
16644
16997
|
|
|
16998
|
+
${ShaderManager.hipsSamplersGLSL()}
|
|
16999
|
+
|
|
16645
17000
|
out vec4 fragColor;
|
|
16646
17001
|
|
|
16647
17002
|
void main() {
|
|
16648
17003
|
vec3 finalColor = vec3(0.0);
|
|
16649
17004
|
|
|
16650
|
-
if (uFactor0 >= 0.0){
|
|
16651
|
-
|
|
16652
|
-
|
|
16653
|
-
|
|
16654
|
-
|
|
16655
|
-
|
|
16656
|
-
|
|
16657
|
-
|
|
16658
|
-
|
|
16659
|
-
|
|
16660
|
-
|
|
17005
|
+
if (uFactor0 >= 0.0) {
|
|
17006
|
+
finalColor +=
|
|
17007
|
+
sampleHiPSTexture0(vTextureCoord).rgb * uFactor0;
|
|
17008
|
+
}
|
|
17009
|
+
|
|
17010
|
+
if (uFactor1 >= 0.0) {
|
|
17011
|
+
finalColor +=
|
|
17012
|
+
sampleHiPSTexture1(vTextureCoord).rgb * uFactor1;
|
|
17013
|
+
}
|
|
17014
|
+
|
|
17015
|
+
if (uFactor2 >= 0.0) {
|
|
17016
|
+
finalColor +=
|
|
17017
|
+
sampleHiPSTexture2(vTextureCoord).rgb * uFactor2;
|
|
16661
17018
|
}
|
|
17019
|
+
|
|
17020
|
+
if (uFactor3 >= 0.0) {
|
|
17021
|
+
finalColor +=
|
|
17022
|
+
sampleHiPSTexture3(vTextureCoord).rgb * uFactor3;
|
|
17023
|
+
}
|
|
17024
|
+
|
|
17025
|
+
if (uFactor4 >= 0.0) {
|
|
17026
|
+
finalColor +=
|
|
17027
|
+
sampleHiPSTexture4(vTextureCoord).rgb * uFactor4;
|
|
17028
|
+
}
|
|
17029
|
+
|
|
17030
|
+
if (uFactor5 >= 0.0) {
|
|
17031
|
+
finalColor +=
|
|
17032
|
+
sampleHiPSTexture5(vTextureCoord).rgb * uFactor5;
|
|
17033
|
+
}
|
|
17034
|
+
|
|
17035
|
+
if (uFactor6 >= 0.0) {
|
|
17036
|
+
finalColor +=
|
|
17037
|
+
sampleHiPSTexture6(vTextureCoord).rgb * uFactor6;
|
|
17038
|
+
}
|
|
17039
|
+
|
|
17040
|
+
if (uFactor7 >= 0.0) {
|
|
17041
|
+
finalColor +=
|
|
17042
|
+
sampleHiPSTexture7(vTextureCoord).rgb * uFactor7;
|
|
17043
|
+
}
|
|
17044
|
+
|
|
16662
17045
|
fragColor = vec4(finalColor, 1.0);
|
|
16663
17046
|
}`;
|
|
16664
17047
|
}
|
|
@@ -16668,15 +17051,6 @@ class ShaderManager {
|
|
|
16668
17051
|
|
|
16669
17052
|
in vec2 vTextureCoord;
|
|
16670
17053
|
|
|
16671
|
-
uniform sampler2D uSampler0;
|
|
16672
|
-
uniform sampler2D uSampler1;
|
|
16673
|
-
uniform sampler2D uSampler2;
|
|
16674
|
-
uniform sampler2D uSampler3;
|
|
16675
|
-
uniform sampler2D uSampler4;
|
|
16676
|
-
uniform sampler2D uSampler5;
|
|
16677
|
-
uniform sampler2D uSampler6;
|
|
16678
|
-
uniform sampler2D uSampler7;
|
|
16679
|
-
|
|
16680
17054
|
uniform float uFactor0;
|
|
16681
17055
|
uniform float uFactor1;
|
|
16682
17056
|
uniform float uFactor2;
|
|
@@ -16686,76 +17060,61 @@ class ShaderManager {
|
|
|
16686
17060
|
uniform float uFactor6;
|
|
16687
17061
|
uniform float uFactor7;
|
|
16688
17062
|
|
|
17063
|
+
${ShaderManager.hipsSamplersGLSL()}
|
|
17064
|
+
|
|
16689
17065
|
out vec4 fragColor;
|
|
16690
17066
|
|
|
16691
17067
|
void main() {
|
|
16692
17068
|
vec3 finalColor = vec3(0.0);
|
|
16693
17069
|
|
|
16694
|
-
if (uFactor0 >= 0.0){
|
|
16695
|
-
|
|
16696
|
-
|
|
16697
|
-
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
17070
|
+
if (uFactor0 >= 0.0) {
|
|
17071
|
+
vec4 color0 = sampleHiPSTexture0(vTextureCoord);
|
|
17072
|
+
|
|
17073
|
+
float gray =
|
|
17074
|
+
0.21 * color0.r +
|
|
17075
|
+
0.71 * color0.g +
|
|
17076
|
+
0.07 * color0.b;
|
|
17077
|
+
|
|
17078
|
+
finalColor =
|
|
17079
|
+
color0.rgb * (1.0 - uFactor0) +
|
|
17080
|
+
vec3(gray) * uFactor0;
|
|
16702
17081
|
}
|
|
16703
|
-
|
|
16704
|
-
|
|
16705
|
-
|
|
16706
|
-
#else
|
|
16707
|
-
vec4 color1 = texture2D(uSampler1, vTextureCoord);
|
|
16708
|
-
#endif
|
|
17082
|
+
|
|
17083
|
+
if (uFactor1 >= 0.0) {
|
|
17084
|
+
vec4 color1 = sampleHiPSTexture1(vTextureCoord);
|
|
16709
17085
|
finalColor += color1.rgb * uFactor1;
|
|
16710
17086
|
}
|
|
16711
|
-
|
|
16712
|
-
|
|
16713
|
-
|
|
16714
|
-
#else
|
|
16715
|
-
vec4 color2 = texture2D(uSampler2, vTextureCoord);
|
|
16716
|
-
#endif
|
|
17087
|
+
|
|
17088
|
+
if (uFactor2 >= 0.0) {
|
|
17089
|
+
vec4 color2 = sampleHiPSTexture2(vTextureCoord);
|
|
16717
17090
|
finalColor += color2.rgb * uFactor2;
|
|
16718
17091
|
}
|
|
16719
|
-
|
|
16720
|
-
|
|
16721
|
-
|
|
16722
|
-
#else
|
|
16723
|
-
vec4 color3 = texture2D(uSampler3, vTextureCoord);
|
|
16724
|
-
#endif
|
|
17092
|
+
|
|
17093
|
+
if (uFactor3 >= 0.0) {
|
|
17094
|
+
vec4 color3 = sampleHiPSTexture3(vTextureCoord);
|
|
16725
17095
|
finalColor += color3.rgb * uFactor3;
|
|
16726
17096
|
}
|
|
16727
|
-
|
|
16728
|
-
|
|
16729
|
-
|
|
16730
|
-
#else
|
|
16731
|
-
vec4 color4 = texture2D(uSampler4, vTextureCoord);
|
|
16732
|
-
#endif
|
|
17097
|
+
|
|
17098
|
+
if (uFactor4 >= 0.0) {
|
|
17099
|
+
vec4 color4 = sampleHiPSTexture4(vTextureCoord);
|
|
16733
17100
|
finalColor += color4.rgb * uFactor4;
|
|
16734
17101
|
}
|
|
16735
|
-
|
|
16736
|
-
|
|
16737
|
-
|
|
16738
|
-
#else
|
|
16739
|
-
vec4 color5 = texture2D(uSampler5, vTextureCoord);
|
|
16740
|
-
#endif
|
|
17102
|
+
|
|
17103
|
+
if (uFactor5 >= 0.0) {
|
|
17104
|
+
vec4 color5 = sampleHiPSTexture5(vTextureCoord);
|
|
16741
17105
|
finalColor += color5.rgb * uFactor5;
|
|
16742
17106
|
}
|
|
16743
|
-
|
|
16744
|
-
|
|
16745
|
-
|
|
16746
|
-
#else
|
|
16747
|
-
vec4 color6 = texture2D(uSampler6, vTextureCoord);
|
|
16748
|
-
#endif
|
|
17107
|
+
|
|
17108
|
+
if (uFactor6 >= 0.0) {
|
|
17109
|
+
vec4 color6 = sampleHiPSTexture6(vTextureCoord);
|
|
16749
17110
|
finalColor += color6.rgb * uFactor6;
|
|
16750
17111
|
}
|
|
16751
|
-
|
|
16752
|
-
|
|
16753
|
-
|
|
16754
|
-
#else
|
|
16755
|
-
vec4 color7 = texture2D(uSampler7, vTextureCoord);
|
|
16756
|
-
#endif
|
|
17112
|
+
|
|
17113
|
+
if (uFactor7 >= 0.0) {
|
|
17114
|
+
vec4 color7 = sampleHiPSTexture7(vTextureCoord);
|
|
16757
17115
|
finalColor += color7.rgb * uFactor7;
|
|
16758
17116
|
}
|
|
17117
|
+
|
|
16759
17118
|
fragColor = vec4(finalColor, 1.0);
|
|
16760
17119
|
}`;
|
|
16761
17120
|
}
|
|
@@ -16765,38 +17124,140 @@ class ShaderManager {
|
|
|
16765
17124
|
|
|
16766
17125
|
in vec2 vTextureCoord;
|
|
16767
17126
|
|
|
16768
|
-
// UBO
|
|
16769
17127
|
layout (std140) uniform colormap {
|
|
16770
17128
|
float r_palette[256];
|
|
16771
17129
|
float g_palette[256];
|
|
16772
17130
|
float b_palette[256];
|
|
16773
17131
|
};
|
|
16774
17132
|
|
|
16775
|
-
uniform sampler2D uSampler0;
|
|
16776
17133
|
uniform float uFactor0;
|
|
17134
|
+
uniform float uFactor1;
|
|
17135
|
+
uniform float uFactor2;
|
|
17136
|
+
uniform float uFactor3;
|
|
17137
|
+
uniform float uFactor4;
|
|
17138
|
+
uniform float uFactor5;
|
|
17139
|
+
uniform float uFactor6;
|
|
17140
|
+
uniform float uFactor7;
|
|
17141
|
+
|
|
17142
|
+
${ShaderManager.hipsSamplersGLSL()}
|
|
16777
17143
|
|
|
16778
17144
|
out vec4 fragColor;
|
|
16779
17145
|
|
|
16780
|
-
|
|
16781
|
-
|
|
16782
|
-
|
|
16783
|
-
|
|
16784
|
-
vec4 color0 = texture2D(uSampler0, vTextureCoord);
|
|
16785
|
-
#endif
|
|
17146
|
+
vec3 applyColorMap(vec4 color) {
|
|
17147
|
+
int x = int(clamp(color.r, 0.0, 1.0) * 255.0);
|
|
17148
|
+
int y = int(clamp(color.g, 0.0, 1.0) * 255.0);
|
|
17149
|
+
int z = int(clamp(color.b, 0.0, 1.0) * 255.0);
|
|
16786
17150
|
|
|
16787
|
-
int x = int(color0.r * 255.0);
|
|
16788
17151
|
float px = r_palette[x] / 256.0;
|
|
16789
|
-
|
|
16790
|
-
int y = int(color0.g * 255.0);
|
|
16791
17152
|
float py = g_palette[y] / 256.0;
|
|
16792
|
-
|
|
16793
|
-
int z = int(color0.b * 255.0);
|
|
16794
17153
|
float pz = b_palette[z] / 256.0;
|
|
16795
17154
|
|
|
16796
|
-
|
|
16797
|
-
|
|
17155
|
+
return vec3(px, py, pz);
|
|
17156
|
+
}
|
|
17157
|
+
|
|
17158
|
+
void main() {
|
|
17159
|
+
vec3 finalColor = vec3(0.0);
|
|
17160
|
+
|
|
17161
|
+
if (uFactor0 >= 0.0) {
|
|
17162
|
+
finalColor +=
|
|
17163
|
+
applyColorMap(
|
|
17164
|
+
sampleHiPSTexture0(vTextureCoord)
|
|
17165
|
+
) * uFactor0;
|
|
17166
|
+
}
|
|
17167
|
+
|
|
17168
|
+
if (uFactor1 >= 0.0) {
|
|
17169
|
+
finalColor +=
|
|
17170
|
+
applyColorMap(
|
|
17171
|
+
sampleHiPSTexture1(vTextureCoord)
|
|
17172
|
+
) * uFactor1;
|
|
17173
|
+
}
|
|
17174
|
+
|
|
17175
|
+
if (uFactor2 >= 0.0) {
|
|
17176
|
+
finalColor +=
|
|
17177
|
+
applyColorMap(
|
|
17178
|
+
sampleHiPSTexture2(vTextureCoord)
|
|
17179
|
+
) * uFactor2;
|
|
17180
|
+
}
|
|
17181
|
+
|
|
17182
|
+
if (uFactor3 >= 0.0) {
|
|
17183
|
+
finalColor +=
|
|
17184
|
+
applyColorMap(
|
|
17185
|
+
sampleHiPSTexture3(vTextureCoord)
|
|
17186
|
+
) * uFactor3;
|
|
17187
|
+
}
|
|
17188
|
+
|
|
17189
|
+
if (uFactor4 >= 0.0) {
|
|
17190
|
+
finalColor +=
|
|
17191
|
+
applyColorMap(
|
|
17192
|
+
sampleHiPSTexture4(vTextureCoord)
|
|
17193
|
+
) * uFactor4;
|
|
17194
|
+
}
|
|
17195
|
+
|
|
17196
|
+
if (uFactor5 >= 0.0) {
|
|
17197
|
+
finalColor +=
|
|
17198
|
+
applyColorMap(
|
|
17199
|
+
sampleHiPSTexture5(vTextureCoord)
|
|
17200
|
+
) * uFactor5;
|
|
17201
|
+
}
|
|
17202
|
+
|
|
17203
|
+
if (uFactor6 >= 0.0) {
|
|
17204
|
+
finalColor +=
|
|
17205
|
+
applyColorMap(
|
|
17206
|
+
sampleHiPSTexture6(vTextureCoord)
|
|
17207
|
+
) * uFactor6;
|
|
17208
|
+
}
|
|
17209
|
+
|
|
17210
|
+
if (uFactor7 >= 0.0) {
|
|
17211
|
+
finalColor +=
|
|
17212
|
+
applyColorMap(
|
|
17213
|
+
sampleHiPSTexture7(vTextureCoord)
|
|
17214
|
+
) * uFactor7;
|
|
17215
|
+
}
|
|
17216
|
+
|
|
17217
|
+
fragColor = vec4(finalColor, 1.0);
|
|
16798
17218
|
}`;
|
|
16799
17219
|
}
|
|
17220
|
+
static hipsSamplerGLSL(index) {
|
|
17221
|
+
return `
|
|
17222
|
+
uniform sampler2D uSampler${index};
|
|
17223
|
+
uniform int uTextureMode${index};
|
|
17224
|
+
uniform float uDataMin${index};
|
|
17225
|
+
uniform float uDataMax${index};
|
|
17226
|
+
|
|
17227
|
+
vec4 sampleHiPSTexture${index}(vec2 uv) {
|
|
17228
|
+
vec4 color = texture(uSampler${index}, uv);
|
|
17229
|
+
|
|
17230
|
+
// JPG / PNG
|
|
17231
|
+
if (uTextureMode${index} == 0) {
|
|
17232
|
+
return color;
|
|
17233
|
+
}
|
|
17234
|
+
|
|
17235
|
+
// FITS physical value stored in red channel
|
|
17236
|
+
float value = color.r;
|
|
17237
|
+
|
|
17238
|
+
if (isnan(value)) {
|
|
17239
|
+
discard;
|
|
17240
|
+
}
|
|
17241
|
+
|
|
17242
|
+
float normalized = clamp(
|
|
17243
|
+
(value - uDataMin${index}) /
|
|
17244
|
+
(uDataMax${index} - uDataMin${index}),
|
|
17245
|
+
0.0,
|
|
17246
|
+
1.0
|
|
17247
|
+
);
|
|
17248
|
+
|
|
17249
|
+
return vec4(
|
|
17250
|
+
normalized,
|
|
17251
|
+
normalized,
|
|
17252
|
+
normalized,
|
|
17253
|
+
1.0
|
|
17254
|
+
);
|
|
17255
|
+
}
|
|
17256
|
+
`;
|
|
17257
|
+
}
|
|
17258
|
+
static hipsSamplersGLSL() {
|
|
17259
|
+
return Array.from({ length: 8 }, (_, index) => ShaderManager.hipsSamplerGLSL(index)).join("\n");
|
|
17260
|
+
}
|
|
16800
17261
|
}
|
|
16801
17262
|
exports["default"] = ShaderManager;
|
|
16802
17263
|
|
|
@@ -18467,6 +18928,55 @@ class XYZRayPickingUtils {
|
|
|
18467
18928
|
exports["default"] = XYZRayPickingUtils;
|
|
18468
18929
|
|
|
18469
18930
|
|
|
18931
|
+
/***/ },
|
|
18932
|
+
|
|
18933
|
+
/***/ 8611
|
|
18934
|
+
(module) {
|
|
18935
|
+
|
|
18936
|
+
module.exports = require("http");
|
|
18937
|
+
|
|
18938
|
+
/***/ },
|
|
18939
|
+
|
|
18940
|
+
/***/ 5692
|
|
18941
|
+
(module) {
|
|
18942
|
+
|
|
18943
|
+
module.exports = require("https");
|
|
18944
|
+
|
|
18945
|
+
/***/ },
|
|
18946
|
+
|
|
18947
|
+
/***/ 1455
|
|
18948
|
+
(module) {
|
|
18949
|
+
|
|
18950
|
+
module.exports = require("node:fs/promises");
|
|
18951
|
+
|
|
18952
|
+
/***/ },
|
|
18953
|
+
|
|
18954
|
+
/***/ 4876
|
|
18955
|
+
(module) {
|
|
18956
|
+
|
|
18957
|
+
module.exports = require("punycode");
|
|
18958
|
+
|
|
18959
|
+
/***/ },
|
|
18960
|
+
|
|
18961
|
+
/***/ 2203
|
|
18962
|
+
(module) {
|
|
18963
|
+
|
|
18964
|
+
module.exports = require("stream");
|
|
18965
|
+
|
|
18966
|
+
/***/ },
|
|
18967
|
+
|
|
18968
|
+
/***/ 7016
|
|
18969
|
+
(module) {
|
|
18970
|
+
|
|
18971
|
+
module.exports = require("url");
|
|
18972
|
+
|
|
18973
|
+
/***/ },
|
|
18974
|
+
|
|
18975
|
+
/***/ 3106
|
|
18976
|
+
(module) {
|
|
18977
|
+
|
|
18978
|
+
module.exports = require("zlib");
|
|
18979
|
+
|
|
18470
18980
|
/***/ },
|
|
18471
18981
|
|
|
18472
18982
|
/***/ 4851
|
|
@@ -19265,76 +19775,1760 @@ function findCircleThroughTwoPoints(points, q1, q2) {
|
|
|
19265
19775
|
|
|
19266
19776
|
|
|
19267
19777
|
|
|
19268
|
-
/***/ }
|
|
19778
|
+
/***/ },
|
|
19269
19779
|
|
|
19270
|
-
|
|
19271
|
-
|
|
19272
|
-
|
|
19273
|
-
|
|
19274
|
-
|
|
19275
|
-
|
|
19276
|
-
|
|
19277
|
-
|
|
19278
|
-
|
|
19279
|
-
|
|
19280
|
-
|
|
19281
|
-
|
|
19282
|
-
|
|
19283
|
-
|
|
19284
|
-
|
|
19285
|
-
|
|
19286
|
-
|
|
19287
|
-
|
|
19288
|
-
|
|
19289
|
-
|
|
19290
|
-
|
|
19291
|
-
|
|
19292
|
-
|
|
19293
|
-
|
|
19294
|
-
|
|
19295
|
-
|
|
19296
|
-
|
|
19297
|
-
|
|
19298
|
-
|
|
19299
|
-
|
|
19300
|
-
|
|
19301
|
-
|
|
19302
|
-
|
|
19303
|
-
|
|
19304
|
-
|
|
19305
|
-
|
|
19306
|
-
|
|
19307
|
-
|
|
19308
|
-
|
|
19309
|
-
|
|
19310
|
-
|
|
19311
|
-
|
|
19312
|
-
|
|
19313
|
-
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
|
|
19318
|
-
|
|
19319
|
-
|
|
19320
|
-
|
|
19321
|
-
|
|
19322
|
-
|
|
19323
|
-
|
|
19324
|
-
|
|
19325
|
-
|
|
19326
|
-
|
|
19327
|
-
|
|
19328
|
-
|
|
19329
|
-
|
|
19330
|
-
|
|
19331
|
-
|
|
19332
|
-
|
|
19333
|
-
|
|
19334
|
-
|
|
19335
|
-
|
|
19336
|
-
|
|
19780
|
+
/***/ 4971
|
|
19781
|
+
(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
19782
|
+
|
|
19783
|
+
|
|
19784
|
+
// EXPORTS
|
|
19785
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
19786
|
+
FITSHeaderManager: () => (/* reexport */ FITSHeaderManager),
|
|
19787
|
+
FITSParser: () => (/* reexport */ FITSParser)
|
|
19788
|
+
});
|
|
19789
|
+
|
|
19790
|
+
// UNUSED EXPORTS: AsciiTableHDU, BinaryTableHDU, FITSFile, FITSHDU, FITSHeaderItem, FITSWriter, ImageHDU, ParseHeader, ParsePayload, PrimaryHDU
|
|
19791
|
+
|
|
19792
|
+
;// ./node_modules/jsfitsio/lib-esm/model/FITSHeaderItem.js
|
|
19793
|
+
/**
|
|
19794
|
+
* Summary. (bla bla bla)
|
|
19795
|
+
*
|
|
19796
|
+
* Description. (bla bla bla)
|
|
19797
|
+
*
|
|
19798
|
+
* @link github https://github.com/fab77/FITSParser
|
|
19799
|
+
* @author Fabrizio Giordano <fabriziogiordano77@gmail.com>
|
|
19800
|
+
*/
|
|
19801
|
+
class FITSHeaderItem {
|
|
19802
|
+
_key = "";
|
|
19803
|
+
_value = "";
|
|
19804
|
+
_comment = "";
|
|
19805
|
+
constructor(key, value, comment) {
|
|
19806
|
+
this._key = key;
|
|
19807
|
+
this._value = value;
|
|
19808
|
+
this._comment = comment;
|
|
19809
|
+
}
|
|
19810
|
+
get key() {
|
|
19811
|
+
return this._key;
|
|
19812
|
+
}
|
|
19813
|
+
get comment() {
|
|
19814
|
+
return this._comment;
|
|
19815
|
+
}
|
|
19816
|
+
get value() {
|
|
19817
|
+
return this._value;
|
|
19818
|
+
}
|
|
19819
|
+
}
|
|
19820
|
+
//# sourceMappingURL=FITSHeaderItem.js.map
|
|
19821
|
+
;// ./node_modules/jsfitsio/lib-esm/model/FITSHeaderManager.js
|
|
19822
|
+
|
|
19823
|
+
class FITSHeaderManager {
|
|
19824
|
+
static SIMPLE = "SIMPLE";
|
|
19825
|
+
static BITPIX = "BITPIX";
|
|
19826
|
+
static BZERO = "BZERO";
|
|
19827
|
+
static BSCALE = "BSCALE";
|
|
19828
|
+
static BLANK = "BLANK";
|
|
19829
|
+
static NAXIS = "NAXIS";
|
|
19830
|
+
static NAXIS1 = "NAXIS1";
|
|
19831
|
+
static NAXIS2 = "NAXIS2";
|
|
19832
|
+
static DATAMIN = "DATAMIN";
|
|
19833
|
+
static DATAMAX = "DATAMAX";
|
|
19834
|
+
static CRVAL1 = "CRVAL1";
|
|
19835
|
+
static CRVAL2 = "CRVAL2";
|
|
19836
|
+
static CTYPE1 = "CTYPE1";
|
|
19837
|
+
static CTYPE2 = "CTYPE2";
|
|
19838
|
+
static CRPIX1 = "CRPIX1";
|
|
19839
|
+
static CRPIX2 = "CRPIX2";
|
|
19840
|
+
static ORIGIN = "ORIGIN";
|
|
19841
|
+
static COMMENT = "COMMENT";
|
|
19842
|
+
static XTENSION = "XTENSION";
|
|
19843
|
+
static PCOUNT = "PCOUNT";
|
|
19844
|
+
static GCOUNT = "GCOUNT";
|
|
19845
|
+
static TFIELDS = "TFIELDS";
|
|
19846
|
+
static TFORM = "TFORM";
|
|
19847
|
+
static TTYPE = "TTYPE";
|
|
19848
|
+
static TUNIT = "TUNIT";
|
|
19849
|
+
static TSCAL = "TSCAL";
|
|
19850
|
+
static TZERO = "TZERO";
|
|
19851
|
+
static TNULL = "TNULL";
|
|
19852
|
+
static TBCOL = "TBCOL";
|
|
19853
|
+
items = [];
|
|
19854
|
+
constructor(initializeDefaults = true) {
|
|
19855
|
+
if (!initializeDefaults) {
|
|
19856
|
+
return;
|
|
19857
|
+
}
|
|
19858
|
+
this.items[0] = new FITSHeaderItem(FITSHeaderManager.SIMPLE, "T", "");
|
|
19859
|
+
this.items[1] = new FITSHeaderItem(FITSHeaderManager.BITPIX, "", "");
|
|
19860
|
+
this.items[2] = new FITSHeaderItem(FITSHeaderManager.NAXIS, 2, "");
|
|
19861
|
+
this.items[3] = new FITSHeaderItem(FITSHeaderManager.NAXIS1, "", "");
|
|
19862
|
+
this.items[4] = new FITSHeaderItem(FITSHeaderManager.NAXIS2, "", "");
|
|
19863
|
+
}
|
|
19864
|
+
// insert(item: FITSHeaderItem, position?: number): void {
|
|
19865
|
+
insert(item) {
|
|
19866
|
+
if (item.key === FITSHeaderManager.SIMPLE) {
|
|
19867
|
+
// this.items.splice(0, 0, item);
|
|
19868
|
+
this.items[0] = item;
|
|
19869
|
+
}
|
|
19870
|
+
else if (item.key === FITSHeaderManager.BITPIX) {
|
|
19871
|
+
// this.items.splice(1, 0, item);
|
|
19872
|
+
this.items[1] = item;
|
|
19873
|
+
}
|
|
19874
|
+
else if (item.key === FITSHeaderManager.NAXIS) {
|
|
19875
|
+
// this.items.splice(2, 0, item);
|
|
19876
|
+
this.items[2] = item;
|
|
19877
|
+
}
|
|
19878
|
+
else if (item.key === FITSHeaderManager.NAXIS1) {
|
|
19879
|
+
// this.items.splice(3, 0, item);
|
|
19880
|
+
this.items[3] = item;
|
|
19881
|
+
}
|
|
19882
|
+
else if (item.key === FITSHeaderManager.NAXIS2) {
|
|
19883
|
+
// this.items.splice(4, 0, item);
|
|
19884
|
+
this.items[4] = item;
|
|
19885
|
+
}
|
|
19886
|
+
else {
|
|
19887
|
+
this.items.push(item);
|
|
19888
|
+
}
|
|
19889
|
+
// if (position !== undefined && position >= 0 && position <= this.items.length) {
|
|
19890
|
+
// this.items.splice(position, 0, item);
|
|
19891
|
+
// } else {
|
|
19892
|
+
// this.items.push(item);
|
|
19893
|
+
// }
|
|
19894
|
+
}
|
|
19895
|
+
getItems() {
|
|
19896
|
+
return this.items;
|
|
19897
|
+
}
|
|
19898
|
+
remove(key) {
|
|
19899
|
+
this.items = this.items.filter((item) => item.key !== key);
|
|
19900
|
+
}
|
|
19901
|
+
findById(key) {
|
|
19902
|
+
const item = this.items.find((item) => item.key === key);
|
|
19903
|
+
if (!item) {
|
|
19904
|
+
return null;
|
|
19905
|
+
}
|
|
19906
|
+
return item;
|
|
19907
|
+
}
|
|
19908
|
+
static tableFieldKey(prefix, index) {
|
|
19909
|
+
if (!Number.isInteger(index) || index < 1) {
|
|
19910
|
+
throw new RangeError(`FITS table field index must be >= 1, received ${index}.`);
|
|
19911
|
+
}
|
|
19912
|
+
return `${prefix}${index}`;
|
|
19913
|
+
}
|
|
19914
|
+
static naxisKey(axis) {
|
|
19915
|
+
if (!Number.isInteger(axis) || axis < 1) {
|
|
19916
|
+
throw new RangeError(`FITS axis must be a positive integer, received ${axis}.`);
|
|
19917
|
+
}
|
|
19918
|
+
return `NAXIS${axis}`;
|
|
19919
|
+
}
|
|
19920
|
+
static getFITSItemStringValue(header, key) {
|
|
19921
|
+
const item = header.findById(key);
|
|
19922
|
+
if (!item) {
|
|
19923
|
+
return null;
|
|
19924
|
+
}
|
|
19925
|
+
return String(item.value).trim().replace(/^'/, "").replace(/'$/, "").trim();
|
|
19926
|
+
}
|
|
19927
|
+
}
|
|
19928
|
+
//# sourceMappingURL=FITSHeaderManager.js.map
|
|
19929
|
+
;// external "fs"
|
|
19930
|
+
const external_fs_namespaceObject = require("fs");
|
|
19931
|
+
;// ./node_modules/jsfitsio/lib-esm/FITSHeaderWriter.js
|
|
19932
|
+
class FITSHeaderWriter {
|
|
19933
|
+
static BLOCK_SIZE = 2880;
|
|
19934
|
+
static CARD_SIZE = 80;
|
|
19935
|
+
static INTEGER_KEYWORDS = new Set([
|
|
19936
|
+
"BITPIX",
|
|
19937
|
+
"NAXIS",
|
|
19938
|
+
"PCOUNT",
|
|
19939
|
+
"GCOUNT",
|
|
19940
|
+
]);
|
|
19941
|
+
static LOGICAL_KEYWORDS = new Set(["SIMPLE", "EXTEND"]);
|
|
19942
|
+
static serialize(header, primary) {
|
|
19943
|
+
const items = header.getItems();
|
|
19944
|
+
const map = new Map(items.map((item) => [item.key.toUpperCase(), item]));
|
|
19945
|
+
const cards = [];
|
|
19946
|
+
FITSHeaderWriter.appendMandatoryCards(cards, map, primary);
|
|
19947
|
+
FITSHeaderWriter.appendRemainingCards(cards, items);
|
|
19948
|
+
cards.push(FITSHeaderWriter.card80("END"));
|
|
19949
|
+
return FITSHeaderWriter.encodeAndPad(cards);
|
|
19950
|
+
}
|
|
19951
|
+
static appendMandatoryCards(cards, map, primary) {
|
|
19952
|
+
if (primary) {
|
|
19953
|
+
const simple = map.get("SIMPLE");
|
|
19954
|
+
if (!simple) {
|
|
19955
|
+
throw new Error("Missing mandatory SIMPLE card in Primary HDU");
|
|
19956
|
+
}
|
|
19957
|
+
cards.push(...FITSHeaderWriter.makeKeywordWithComment("SIMPLE", simple.value, simple.comment));
|
|
19958
|
+
}
|
|
19959
|
+
else {
|
|
19960
|
+
const xtension = map.get("XTENSION");
|
|
19961
|
+
if (!xtension) {
|
|
19962
|
+
throw new Error("Missing mandatory XTENSION card in extension HDU");
|
|
19963
|
+
}
|
|
19964
|
+
cards.push(...FITSHeaderWriter.makeKeywordWithComment("XTENSION", xtension.value, xtension.comment));
|
|
19965
|
+
}
|
|
19966
|
+
const bitpix = map.get("BITPIX");
|
|
19967
|
+
if (!bitpix) {
|
|
19968
|
+
throw new Error("Missing mandatory BITPIX card");
|
|
19969
|
+
}
|
|
19970
|
+
cards.push(...FITSHeaderWriter.makeKeywordWithComment("BITPIX", bitpix.value, bitpix.comment));
|
|
19971
|
+
const naxis = map.get("NAXIS");
|
|
19972
|
+
if (!naxis) {
|
|
19973
|
+
throw new Error("Missing mandatory NAXIS card");
|
|
19974
|
+
}
|
|
19975
|
+
const nAxes = Number(naxis.value);
|
|
19976
|
+
if (!Number.isInteger(nAxes) || nAxes < 0) {
|
|
19977
|
+
throw new Error(`Invalid NAXIS value: ${naxis.value}`);
|
|
19978
|
+
}
|
|
19979
|
+
cards.push(...FITSHeaderWriter.makeKeywordWithComment("NAXIS", nAxes, naxis.comment));
|
|
19980
|
+
for (let axis = 1; axis <= nAxes; axis++) {
|
|
19981
|
+
const key = `NAXIS${axis}`;
|
|
19982
|
+
const item = map.get(key);
|
|
19983
|
+
if (!item) {
|
|
19984
|
+
throw new Error(`Missing mandatory ${key} card`);
|
|
19985
|
+
}
|
|
19986
|
+
cards.push(...FITSHeaderWriter.makeKeywordWithComment(key, item.value, item.comment));
|
|
19987
|
+
}
|
|
19988
|
+
if (!primary) {
|
|
19989
|
+
const pcount = map.get("PCOUNT");
|
|
19990
|
+
const gcount = map.get("GCOUNT");
|
|
19991
|
+
if (!pcount) {
|
|
19992
|
+
throw new Error("Missing mandatory PCOUNT card in extension HDU");
|
|
19993
|
+
}
|
|
19994
|
+
if (!gcount) {
|
|
19995
|
+
throw new Error("Missing mandatory GCOUNT card in extension HDU");
|
|
19996
|
+
}
|
|
19997
|
+
cards.push(...FITSHeaderWriter.makeKeywordWithComment("PCOUNT", pcount.value, pcount.comment));
|
|
19998
|
+
cards.push(...FITSHeaderWriter.makeKeywordWithComment("GCOUNT", gcount.value, gcount.comment));
|
|
19999
|
+
}
|
|
20000
|
+
if (primary) {
|
|
20001
|
+
const extend = map.get("EXTEND");
|
|
20002
|
+
if (extend) {
|
|
20003
|
+
cards.push(...FITSHeaderWriter.makeKeywordWithComment("EXTEND", extend.value, extend.comment));
|
|
20004
|
+
}
|
|
20005
|
+
}
|
|
20006
|
+
}
|
|
20007
|
+
static appendRemainingCards(cards, items) {
|
|
20008
|
+
for (const item of items) {
|
|
20009
|
+
const key = item.key.toUpperCase();
|
|
20010
|
+
if (key === "SIMPLE" ||
|
|
20011
|
+
key === "XTENSION" ||
|
|
20012
|
+
key === "BITPIX" ||
|
|
20013
|
+
key === "NAXIS" ||
|
|
20014
|
+
/^NAXIS\d+$/.test(key) ||
|
|
20015
|
+
key === "PCOUNT" ||
|
|
20016
|
+
key === "GCOUNT" ||
|
|
20017
|
+
key === "EXTEND" ||
|
|
20018
|
+
key === "END") {
|
|
20019
|
+
continue;
|
|
20020
|
+
}
|
|
20021
|
+
cards.push(...FITSHeaderWriter.makeKeywordWithComment(item.key, item.value, item.comment));
|
|
20022
|
+
}
|
|
20023
|
+
}
|
|
20024
|
+
static makeKeywordWithComment(key, value, comment) {
|
|
20025
|
+
const normalized = key.toUpperCase();
|
|
20026
|
+
if (normalized === "END") {
|
|
20027
|
+
return [FITSHeaderWriter.card80("END")];
|
|
20028
|
+
}
|
|
20029
|
+
if (normalized === "COMMENT" || normalized === "HISTORY") {
|
|
20030
|
+
return FITSHeaderWriter.makeCommentCards(normalized, String(value ?? comment ?? ""));
|
|
20031
|
+
}
|
|
20032
|
+
let base = FITSHeaderWriter.keyword(normalized) +
|
|
20033
|
+
FITSHeaderWriter.valueField20(normalized, value);
|
|
20034
|
+
if (!comment || comment.length === 0) {
|
|
20035
|
+
return [FITSHeaderWriter.card80(base)];
|
|
20036
|
+
}
|
|
20037
|
+
const addition = ` / ${comment}`;
|
|
20038
|
+
const spaceLeft = FITSHeaderWriter.CARD_SIZE - base.length;
|
|
20039
|
+
if (spaceLeft <= 0) {
|
|
20040
|
+
return [
|
|
20041
|
+
FITSHeaderWriter.card80(base),
|
|
20042
|
+
...FITSHeaderWriter.makeCommentCards("COMMENT", comment),
|
|
20043
|
+
];
|
|
20044
|
+
}
|
|
20045
|
+
base += addition.slice(0, spaceLeft);
|
|
20046
|
+
const overflow = addition.slice(spaceLeft).replace(/^\s*\/\s*/, "");
|
|
20047
|
+
if (overflow.length === 0) {
|
|
20048
|
+
return [FITSHeaderWriter.card80(base)];
|
|
20049
|
+
}
|
|
20050
|
+
return [
|
|
20051
|
+
FITSHeaderWriter.card80(base),
|
|
20052
|
+
...FITSHeaderWriter.makeCommentCards("COMMENT", overflow),
|
|
20053
|
+
];
|
|
20054
|
+
}
|
|
20055
|
+
static makeCommentCards(kind, text) {
|
|
20056
|
+
const prefix = FITSHeaderWriter.keyword(kind);
|
|
20057
|
+
const width = FITSHeaderWriter.CARD_SIZE - prefix.length;
|
|
20058
|
+
const value = String(text ?? "");
|
|
20059
|
+
if (value.length === 0) {
|
|
20060
|
+
return [FITSHeaderWriter.card80(prefix)];
|
|
20061
|
+
}
|
|
20062
|
+
const cards = [];
|
|
20063
|
+
for (let offset = 0; offset < value.length; offset += width) {
|
|
20064
|
+
cards.push(FITSHeaderWriter.card80(prefix + value.slice(offset, offset + width)));
|
|
20065
|
+
}
|
|
20066
|
+
return cards;
|
|
20067
|
+
}
|
|
20068
|
+
static valueField20(key, value) {
|
|
20069
|
+
if (FITSHeaderWriter.LOGICAL_KEYWORDS.has(key)) {
|
|
20070
|
+
const logical = value === true || value === "T" || value === "t" ? "T" : "F";
|
|
20071
|
+
return `= ${logical.padStart(20, " ")}`;
|
|
20072
|
+
}
|
|
20073
|
+
if (FITSHeaderWriter.INTEGER_KEYWORDS.has(key) || /^NAXIS\d+$/.test(key)) {
|
|
20074
|
+
const number = Number(value);
|
|
20075
|
+
if (!Number.isFinite(number) || !Number.isInteger(number)) {
|
|
20076
|
+
throw new Error(`FITS header: ${key} must be an integer, got ${value}`);
|
|
20077
|
+
}
|
|
20078
|
+
return `= ${String(number).padStart(20, " ")}`;
|
|
20079
|
+
}
|
|
20080
|
+
if (typeof value === "number") {
|
|
20081
|
+
let encoded = Number.isInteger(value)
|
|
20082
|
+
? String(value)
|
|
20083
|
+
: value.toExponential(10).replace("e", "E");
|
|
20084
|
+
if (encoded.length > 20) {
|
|
20085
|
+
encoded = value.toExponential(8).replace("e", "E");
|
|
20086
|
+
}
|
|
20087
|
+
return `= ${encoded.padStart(20, " ")}`;
|
|
20088
|
+
}
|
|
20089
|
+
if (typeof value === "string") {
|
|
20090
|
+
return `= ${FITSHeaderWriter.quoteFitsString(value)}`;
|
|
20091
|
+
}
|
|
20092
|
+
return "";
|
|
20093
|
+
}
|
|
20094
|
+
static quoteFitsString(value) {
|
|
20095
|
+
const unquoted = value.replace(/^'+|'+$/g, "");
|
|
20096
|
+
const escaped = unquoted.replace(/'/g, "''");
|
|
20097
|
+
return `'${escaped}'`;
|
|
20098
|
+
}
|
|
20099
|
+
static keyword(value) {
|
|
20100
|
+
return (value ?? "").toUpperCase().padEnd(8, " ").slice(0, 8);
|
|
20101
|
+
}
|
|
20102
|
+
static card80(value) {
|
|
20103
|
+
if (value.length >= FITSHeaderWriter.CARD_SIZE) {
|
|
20104
|
+
return value.slice(0, FITSHeaderWriter.CARD_SIZE);
|
|
20105
|
+
}
|
|
20106
|
+
return value.padEnd(FITSHeaderWriter.CARD_SIZE, " ");
|
|
20107
|
+
}
|
|
20108
|
+
static encodeAndPad(cards) {
|
|
20109
|
+
let header = cards.join("");
|
|
20110
|
+
const remainder = header.length % FITSHeaderWriter.BLOCK_SIZE;
|
|
20111
|
+
if (remainder !== 0) {
|
|
20112
|
+
header += " ".repeat(FITSHeaderWriter.BLOCK_SIZE - remainder);
|
|
20113
|
+
}
|
|
20114
|
+
return new TextEncoder().encode(header);
|
|
20115
|
+
}
|
|
20116
|
+
}
|
|
20117
|
+
//# sourceMappingURL=FITSHeaderWriter.js.map
|
|
20118
|
+
;// ./node_modules/jsfitsio/lib-esm/FITSWriter.js
|
|
20119
|
+
/**
|
|
20120
|
+
* FITS serialization and file writing support.
|
|
20121
|
+
*
|
|
20122
|
+
* FITSWriter provides two serialization APIs:
|
|
20123
|
+
*
|
|
20124
|
+
* - The jsfitsio 3.x API serializes the FITSFile/HDU data model,
|
|
20125
|
+
* including PrimaryHDU, ImageHDU, BinaryTableHDU and AsciiTableHDU.
|
|
20126
|
+
*
|
|
20127
|
+
* - The legacy API serializes the former FITSParsed representation
|
|
20128
|
+
* and is retained for backward compatibility with jsfitsio 2.x
|
|
20129
|
+
* consumers.
|
|
20130
|
+
*
|
|
20131
|
+
* FITS headers are serialized according to the FITS 80-character
|
|
20132
|
+
* card format and padded to 2880-byte FITS logical blocks.
|
|
20133
|
+
* HDU payloads are likewise padded to 2880-byte boundaries.
|
|
20134
|
+
*
|
|
20135
|
+
* New code should use FITSFile together with createFITSFile() and
|
|
20136
|
+
* writeFITSFileModel().
|
|
20137
|
+
*
|
|
20138
|
+
* @see https://fits.gsfc.nasa.gov/
|
|
20139
|
+
*/
|
|
20140
|
+
|
|
20141
|
+
|
|
20142
|
+
class FITSWriter {
|
|
20143
|
+
/**
|
|
20144
|
+
* Serializes the legacy FITSParsed representation.
|
|
20145
|
+
*
|
|
20146
|
+
* @deprecated Use createFITSFile() with the FITSFile/HDU model.
|
|
20147
|
+
* This method is retained for backward compatibility with jsfitsio 2.x.
|
|
20148
|
+
*/
|
|
20149
|
+
static createFITS(fitsParsed) {
|
|
20150
|
+
const headerBytes = FITSHeaderWriter.serialize(fitsParsed.header, true);
|
|
20151
|
+
const dataBytes = this.createData(fitsParsed.data, fitsParsed.header);
|
|
20152
|
+
const fitsFile = new Uint8Array(headerBytes.length + dataBytes.length);
|
|
20153
|
+
fitsFile.set(headerBytes, 0);
|
|
20154
|
+
fitsFile.set(dataBytes, headerBytes.length);
|
|
20155
|
+
return fitsFile;
|
|
20156
|
+
}
|
|
20157
|
+
static createHDU(hdu, primary) {
|
|
20158
|
+
const headerBytes = FITSHeaderWriter.serialize(hdu.header, primary);
|
|
20159
|
+
const rawData = hdu.rawData ?? new Uint8Array(0);
|
|
20160
|
+
if (rawData.byteLength !== hdu.dataByteLength) {
|
|
20161
|
+
throw new Error(`HDU payload length mismatch: ` +
|
|
20162
|
+
`rawData contains ${rawData.byteLength} bytes, ` +
|
|
20163
|
+
`but dataByteLength=${hdu.dataByteLength}.`);
|
|
20164
|
+
}
|
|
20165
|
+
const dataBytes = FITSWriter.padData(rawData);
|
|
20166
|
+
const result = new Uint8Array(headerBytes.byteLength + dataBytes.byteLength);
|
|
20167
|
+
result.set(headerBytes, 0);
|
|
20168
|
+
result.set(dataBytes, headerBytes.byteLength);
|
|
20169
|
+
return result;
|
|
20170
|
+
}
|
|
20171
|
+
static padData(data) {
|
|
20172
|
+
const BLOCK = 2880;
|
|
20173
|
+
if (data.byteLength === 0) {
|
|
20174
|
+
return new Uint8Array(0);
|
|
20175
|
+
}
|
|
20176
|
+
const remainder = data.byteLength % BLOCK;
|
|
20177
|
+
if (remainder === 0) {
|
|
20178
|
+
return data.slice();
|
|
20179
|
+
}
|
|
20180
|
+
const padded = new Uint8Array(data.byteLength + (BLOCK - remainder));
|
|
20181
|
+
padded.set(data);
|
|
20182
|
+
return padded;
|
|
20183
|
+
}
|
|
20184
|
+
static createData(data, header) {
|
|
20185
|
+
// concat
|
|
20186
|
+
const totalLength = data.reduce((s, c) => s + c.length, 0);
|
|
20187
|
+
// OPTIONAL: verify size from BITPIX/NAXIS
|
|
20188
|
+
const bitpix = Math.abs(Number(header.findById("BITPIX")?.value ?? 0));
|
|
20189
|
+
const naxis = Number(header.findById("NAXIS")?.value ?? 0);
|
|
20190
|
+
let elems = 1;
|
|
20191
|
+
for (let k = 1; k <= naxis; k++) {
|
|
20192
|
+
elems *= Number(header.findById(`NAXIS${k}`)?.value ?? 0);
|
|
20193
|
+
}
|
|
20194
|
+
const bytesPerElem = bitpix / 8;
|
|
20195
|
+
const expectedUnpadded = naxis > 0 ? elems * bytesPerElem : 0;
|
|
20196
|
+
if (expectedUnpadded && expectedUnpadded !== totalLength) {
|
|
20197
|
+
throw new Error(`Data length ${totalLength} does not match header expectation ${expectedUnpadded} (BITPIX=${bitpix}, NAXIS=${naxis})`);
|
|
20198
|
+
}
|
|
20199
|
+
// build and pad
|
|
20200
|
+
let dataBytes = new Uint8Array(totalLength);
|
|
20201
|
+
let off = 0;
|
|
20202
|
+
for (const chunk of data) {
|
|
20203
|
+
dataBytes.set(chunk, off);
|
|
20204
|
+
off += chunk.length;
|
|
20205
|
+
}
|
|
20206
|
+
return FITSWriter.padData(dataBytes);
|
|
20207
|
+
}
|
|
20208
|
+
/**
|
|
20209
|
+
* Serializes a jsfitsio 3.x FITSFile, including all contained HDUs.
|
|
20210
|
+
*/
|
|
20211
|
+
static createFITSFile(fitsFile) {
|
|
20212
|
+
if (fitsFile.length === 0) {
|
|
20213
|
+
throw new Error("Cannot write an empty FITSFile.");
|
|
20214
|
+
}
|
|
20215
|
+
if (fitsFile.primaryHDU === null) {
|
|
20216
|
+
throw new Error("FITSFile must start with a PrimaryHDU.");
|
|
20217
|
+
}
|
|
20218
|
+
const serializedHDUs = fitsFile.hdus.map((hdu, index) => FITSWriter.createHDU(hdu, index === 0));
|
|
20219
|
+
const totalLength = serializedHDUs.reduce((sum, hdu) => sum + hdu.byteLength, 0);
|
|
20220
|
+
const result = new Uint8Array(totalLength);
|
|
20221
|
+
let offset = 0;
|
|
20222
|
+
for (const hdu of serializedHDUs) {
|
|
20223
|
+
result.set(hdu, offset);
|
|
20224
|
+
offset += hdu.byteLength;
|
|
20225
|
+
}
|
|
20226
|
+
return result;
|
|
20227
|
+
}
|
|
20228
|
+
/**
|
|
20229
|
+
* Serializes a jsfitsio 3.x FITSFile and writes it to the local filesystem.
|
|
20230
|
+
*/
|
|
20231
|
+
static writeFITSFileModel(fitsFile, filePath) {
|
|
20232
|
+
const data = FITSWriter.createFITSFile(fitsFile);
|
|
20233
|
+
external_fs_namespaceObject.writeFileSync(filePath, data);
|
|
20234
|
+
}
|
|
20235
|
+
/**
|
|
20236
|
+
* Writes the legacy FITSParsed representation to a local file.
|
|
20237
|
+
*
|
|
20238
|
+
* @deprecated Use writeFITSFileModel() with FITSFile instead.
|
|
20239
|
+
* This method is retained for backward compatibility with jsfitsio 2.x.
|
|
20240
|
+
*/
|
|
20241
|
+
static writeFITSFile(fitsParsed, filePath) {
|
|
20242
|
+
const fitsFile = FITSWriter.createFITS(fitsParsed);
|
|
20243
|
+
external_fs_namespaceObject.writeFileSync(filePath, fitsFile);
|
|
20244
|
+
}
|
|
20245
|
+
}
|
|
20246
|
+
//# sourceMappingURL=FITSWriter.js.map
|
|
20247
|
+
;// ./node_modules/jsfitsio/lib-esm/ParseHeader.js
|
|
20248
|
+
// import { FITSHeader } from "./model/FITSHeader.js";
|
|
20249
|
+
|
|
20250
|
+
|
|
20251
|
+
/**
|
|
20252
|
+
* Summary. (bla bla bla)
|
|
20253
|
+
*
|
|
20254
|
+
* Description. (bla bla bla)
|
|
20255
|
+
*
|
|
20256
|
+
* @link github https://github.com/fab77/FITSParser
|
|
20257
|
+
* @author Fabrizio Giordano <fabriziogiordano77@gmail.com>
|
|
20258
|
+
*/
|
|
20259
|
+
class ParseHeader {
|
|
20260
|
+
static CARD_SIZE = 80;
|
|
20261
|
+
static BLOCK_SIZE = 2880;
|
|
20262
|
+
static getFITSItemStringValue(header, key) {
|
|
20263
|
+
const item = header.findById(key);
|
|
20264
|
+
if (!item) {
|
|
20265
|
+
return null;
|
|
20266
|
+
}
|
|
20267
|
+
return String(item.value).trim().replace(/^'/, "").replace(/'$/, "").trim();
|
|
20268
|
+
}
|
|
20269
|
+
static getFITSItemValue(header, key) {
|
|
20270
|
+
const item = header.findById(key);
|
|
20271
|
+
if (!item) {
|
|
20272
|
+
return null;
|
|
20273
|
+
}
|
|
20274
|
+
const value = Number(item.value);
|
|
20275
|
+
return Number.isNaN(value) ? null : value;
|
|
20276
|
+
}
|
|
20277
|
+
/**
|
|
20278
|
+
* Returns the complete FITS header size, including padding
|
|
20279
|
+
* up to the next 2880-byte boundary.
|
|
20280
|
+
*/
|
|
20281
|
+
static getHeaderByteLength(rawData, startOffset = 0) {
|
|
20282
|
+
const decoder = new TextDecoder("ascii");
|
|
20283
|
+
for (let offset = startOffset; offset + ParseHeader.CARD_SIZE <= rawData.byteLength; offset += ParseHeader.CARD_SIZE) {
|
|
20284
|
+
const key = decoder.decode(rawData.subarray(offset, offset + 8)).trim();
|
|
20285
|
+
if (key === "END") {
|
|
20286
|
+
const consumed = offset + ParseHeader.CARD_SIZE - startOffset;
|
|
20287
|
+
return (Math.ceil(consumed / ParseHeader.BLOCK_SIZE) * ParseHeader.BLOCK_SIZE);
|
|
20288
|
+
}
|
|
20289
|
+
}
|
|
20290
|
+
throw new Error("Invalid FITS header: END card not found.");
|
|
20291
|
+
}
|
|
20292
|
+
static parse(rawData, startOffset = 0) {
|
|
20293
|
+
const decoder = new TextDecoder("ascii");
|
|
20294
|
+
const headerLength = ParseHeader.getHeaderByteLength(rawData, startOffset);
|
|
20295
|
+
const header = new FITSHeaderManager(false);
|
|
20296
|
+
for (let offset = startOffset; offset < startOffset + headerLength; offset += ParseHeader.CARD_SIZE) {
|
|
20297
|
+
const line = decoder.decode(rawData.subarray(offset, offset + ParseHeader.CARD_SIZE));
|
|
20298
|
+
const key = line.slice(0, 8).trim();
|
|
20299
|
+
if (key === "END") {
|
|
20300
|
+
break;
|
|
20301
|
+
}
|
|
20302
|
+
if (!key) {
|
|
20303
|
+
continue;
|
|
20304
|
+
}
|
|
20305
|
+
let value;
|
|
20306
|
+
let comment = "";
|
|
20307
|
+
const rawValue = line.slice(10).trim().split("/")[0].trim();
|
|
20308
|
+
if (Number.isNaN(Number(rawValue))) {
|
|
20309
|
+
value = rawValue;
|
|
20310
|
+
}
|
|
20311
|
+
else {
|
|
20312
|
+
value = Number(rawValue);
|
|
20313
|
+
}
|
|
20314
|
+
if (line.includes("/")) {
|
|
20315
|
+
comment = line.slice(10).trim().split("/")[1]?.trim() ?? "";
|
|
20316
|
+
}
|
|
20317
|
+
header.insert(new FITSHeaderItem(key, value, comment));
|
|
20318
|
+
}
|
|
20319
|
+
return header;
|
|
20320
|
+
}
|
|
20321
|
+
}
|
|
20322
|
+
//# sourceMappingURL=ParseHeader.js.map
|
|
20323
|
+
;// ./node_modules/jsfitsio/lib-esm/FITSImageUtils.js
|
|
20324
|
+
|
|
20325
|
+
|
|
20326
|
+
class FITSImageUtils {
|
|
20327
|
+
static getShape(header) {
|
|
20328
|
+
const naxis = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS);
|
|
20329
|
+
if (naxis === null) {
|
|
20330
|
+
throw new Error("NAXIS not defined.");
|
|
20331
|
+
}
|
|
20332
|
+
if (!Number.isInteger(naxis) || naxis < 0) {
|
|
20333
|
+
throw new Error(`Invalid FITS NAXIS value: ${naxis}`);
|
|
20334
|
+
}
|
|
20335
|
+
const shape = [];
|
|
20336
|
+
for (let axis = 1; axis <= naxis; axis++) {
|
|
20337
|
+
const size = ParseHeader.getFITSItemValue(header, FITSHeaderManager.naxisKey(axis));
|
|
20338
|
+
if (size === null) {
|
|
20339
|
+
throw new Error(`NAXIS${axis} not defined.`);
|
|
20340
|
+
}
|
|
20341
|
+
shape.push(size);
|
|
20342
|
+
}
|
|
20343
|
+
return shape;
|
|
20344
|
+
}
|
|
20345
|
+
static getElementCount(shape) {
|
|
20346
|
+
if (shape.length === 0) {
|
|
20347
|
+
return 0;
|
|
20348
|
+
}
|
|
20349
|
+
return shape.reduce((total, dimension) => total * dimension, 1);
|
|
20350
|
+
}
|
|
20351
|
+
}
|
|
20352
|
+
//# sourceMappingURL=FITSImageUtils.js.map
|
|
20353
|
+
;// ./node_modules/jsfitsio/lib-esm/ParsePayload.js
|
|
20354
|
+
// "use strict";
|
|
20355
|
+
/**
|
|
20356
|
+
* Summary. (bla bla bla)
|
|
20357
|
+
*
|
|
20358
|
+
* Description. (bla bla bla)
|
|
20359
|
+
*
|
|
20360
|
+
* @link github https://github.com/fab77/FITSParser
|
|
20361
|
+
* @author Fabrizio Giordano <fabriziogiordano77@gmail.com>
|
|
20362
|
+
*/
|
|
20363
|
+
|
|
20364
|
+
|
|
20365
|
+
|
|
20366
|
+
|
|
20367
|
+
class ParsePayload {
|
|
20368
|
+
static SUPPORTED_BITPIX = new Set([8, 16, 32, 64, -32, -64]);
|
|
20369
|
+
static assertSupportedBITPIX(bitpix) {
|
|
20370
|
+
if (!ParsePayload.SUPPORTED_BITPIX.has(bitpix)) {
|
|
20371
|
+
throw new Error(`Unsupported FITS BITPIX value: ${bitpix}`);
|
|
20372
|
+
}
|
|
20373
|
+
}
|
|
20374
|
+
static extractPixelFromView(view, offset, bitpix) {
|
|
20375
|
+
switch (bitpix) {
|
|
20376
|
+
case 8:
|
|
20377
|
+
return view.getUint8(offset);
|
|
20378
|
+
case 16:
|
|
20379
|
+
return view.getInt16(offset, false);
|
|
20380
|
+
case 32:
|
|
20381
|
+
return view.getInt32(offset, false);
|
|
20382
|
+
case -32:
|
|
20383
|
+
return view.getFloat32(offset, false);
|
|
20384
|
+
case -64:
|
|
20385
|
+
return view.getFloat64(offset, false);
|
|
20386
|
+
case 64: {
|
|
20387
|
+
const value = view.getBigInt64(offset, false);
|
|
20388
|
+
const numeric = Number(value);
|
|
20389
|
+
if (!Number.isSafeInteger(numeric)) {
|
|
20390
|
+
throw new RangeError(`BITPIX=64 value ${value} cannot be represented ` +
|
|
20391
|
+
`exactly as a JavaScript number.`);
|
|
20392
|
+
}
|
|
20393
|
+
return numeric;
|
|
20394
|
+
}
|
|
20395
|
+
default:
|
|
20396
|
+
throw new Error(`Unsupported FITS BITPIX value: ${bitpix}`);
|
|
20397
|
+
}
|
|
20398
|
+
}
|
|
20399
|
+
static computePhysicalMinAndMax(header, payload) {
|
|
20400
|
+
const bitpix = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BITPIX);
|
|
20401
|
+
if (bitpix === null) {
|
|
20402
|
+
return null;
|
|
20403
|
+
}
|
|
20404
|
+
ParsePayload.assertSupportedBITPIX(bitpix);
|
|
20405
|
+
const shape = FITSImageUtils.getShape(header);
|
|
20406
|
+
/*
|
|
20407
|
+
* NAXIS=0 is a valid FITS HDU.
|
|
20408
|
+
*/
|
|
20409
|
+
if (shape.length === 0 || payload.byteLength === 0) {
|
|
20410
|
+
return header;
|
|
20411
|
+
}
|
|
20412
|
+
const dataMinItem = header.findById(FITSHeaderManager.DATAMIN);
|
|
20413
|
+
const dataMaxItem = header.findById(FITSHeaderManager.DATAMAX);
|
|
20414
|
+
if (dataMinItem === null || dataMaxItem === null) {
|
|
20415
|
+
try {
|
|
20416
|
+
const [min, max] = ParsePayload.computePhysicalValues(payload, header);
|
|
20417
|
+
if (dataMinItem === null && min !== null) {
|
|
20418
|
+
header.insert(new FITSHeaderItem(FITSHeaderManager.DATAMIN, min, "computed by jsfitsio"));
|
|
20419
|
+
}
|
|
20420
|
+
if (dataMaxItem === null && max !== null) {
|
|
20421
|
+
header.insert(new FITSHeaderItem(FITSHeaderManager.DATAMAX, max, "computed by jsfitsio"));
|
|
20422
|
+
}
|
|
20423
|
+
}
|
|
20424
|
+
catch (error) {
|
|
20425
|
+
if (bitpix === 64 && error instanceof RangeError) {
|
|
20426
|
+
return header;
|
|
20427
|
+
}
|
|
20428
|
+
throw error;
|
|
20429
|
+
}
|
|
20430
|
+
}
|
|
20431
|
+
return header;
|
|
20432
|
+
}
|
|
20433
|
+
static createTypedArray(rawData, bitpix) {
|
|
20434
|
+
ParsePayload.assertSupportedBITPIX(bitpix);
|
|
20435
|
+
const bytesPerElement = Math.abs(bitpix) / 8;
|
|
20436
|
+
if (rawData.byteLength % bytesPerElement !== 0) {
|
|
20437
|
+
throw new Error(`Payload byte length ${rawData.byteLength} ` +
|
|
20438
|
+
`is not aligned with BITPIX=${bitpix}.`);
|
|
20439
|
+
}
|
|
20440
|
+
const count = rawData.byteLength / bytesPerElement;
|
|
20441
|
+
const view = new DataView(rawData.buffer, rawData.byteOffset, rawData.byteLength);
|
|
20442
|
+
switch (bitpix) {
|
|
20443
|
+
case 8: {
|
|
20444
|
+
/*
|
|
20445
|
+
* For 8-bit FITS, byte order is irrelevant.
|
|
20446
|
+
*
|
|
20447
|
+
* Use slice() so typedData has its own correctly
|
|
20448
|
+
* sized backing store.
|
|
20449
|
+
*/
|
|
20450
|
+
return rawData.slice();
|
|
20451
|
+
}
|
|
20452
|
+
case 16: {
|
|
20453
|
+
const result = new Int16Array(count);
|
|
20454
|
+
for (let i = 0; i < count; i++) {
|
|
20455
|
+
result[i] = view.getInt16(i * 2, false);
|
|
20456
|
+
}
|
|
20457
|
+
return result;
|
|
20458
|
+
}
|
|
20459
|
+
case 32: {
|
|
20460
|
+
const result = new Int32Array(count);
|
|
20461
|
+
for (let i = 0; i < count; i++) {
|
|
20462
|
+
result[i] = view.getInt32(i * 4, false);
|
|
20463
|
+
}
|
|
20464
|
+
return result;
|
|
20465
|
+
}
|
|
20466
|
+
case 64: {
|
|
20467
|
+
const result = new BigInt64Array(count);
|
|
20468
|
+
for (let i = 0; i < count; i++) {
|
|
20469
|
+
result[i] = view.getBigInt64(i * 8, false);
|
|
20470
|
+
}
|
|
20471
|
+
return result;
|
|
20472
|
+
}
|
|
20473
|
+
case -32: {
|
|
20474
|
+
const result = new Float32Array(count);
|
|
20475
|
+
for (let i = 0; i < count; i++) {
|
|
20476
|
+
result[i] = view.getFloat32(i * 4, false);
|
|
20477
|
+
}
|
|
20478
|
+
return result;
|
|
20479
|
+
}
|
|
20480
|
+
case -64: {
|
|
20481
|
+
const result = new Float64Array(count);
|
|
20482
|
+
for (let i = 0; i < count; i++) {
|
|
20483
|
+
result[i] = view.getFloat64(i * 8, false);
|
|
20484
|
+
}
|
|
20485
|
+
return result;
|
|
20486
|
+
}
|
|
20487
|
+
default:
|
|
20488
|
+
throw new Error(`Unsupported FITS BITPIX value: ${bitpix}`);
|
|
20489
|
+
}
|
|
20490
|
+
}
|
|
20491
|
+
static computePhysicalValues(rawData, header) {
|
|
20492
|
+
const bitpix = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BITPIX);
|
|
20493
|
+
if (bitpix === null) {
|
|
20494
|
+
return [null, null];
|
|
20495
|
+
}
|
|
20496
|
+
ParsePayload.assertSupportedBITPIX(bitpix);
|
|
20497
|
+
const shape = FITSImageUtils.getShape(header);
|
|
20498
|
+
const pixelCount = FITSImageUtils.getElementCount(shape);
|
|
20499
|
+
if (pixelCount === 0) {
|
|
20500
|
+
return [null, null];
|
|
20501
|
+
}
|
|
20502
|
+
const blank = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BLANK);
|
|
20503
|
+
const bzero = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BZERO) ?? 0;
|
|
20504
|
+
const bscale = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BSCALE) ?? 1;
|
|
20505
|
+
const bytesPerElement = Math.abs(bitpix) / 8;
|
|
20506
|
+
const requiredBytes = pixelCount * bytesPerElement;
|
|
20507
|
+
if (rawData.byteLength < requiredBytes) {
|
|
20508
|
+
throw new Error(`FITS payload is too short: expected ${requiredBytes} bytes, ` +
|
|
20509
|
+
`received ${rawData.byteLength}.`);
|
|
20510
|
+
}
|
|
20511
|
+
const view = new DataView(rawData.buffer, rawData.byteOffset, rawData.byteLength);
|
|
20512
|
+
let min = null;
|
|
20513
|
+
let max = null;
|
|
20514
|
+
for (let i = 0; i < pixelCount; i++) {
|
|
20515
|
+
const rawValue = ParsePayload.extractPixelFromView(view, i * bytesPerElement, bitpix);
|
|
20516
|
+
// BLANK applies to integer FITS image data.
|
|
20517
|
+
if (bitpix > 0 && blank !== null && rawValue === blank) {
|
|
20518
|
+
continue;
|
|
20519
|
+
}
|
|
20520
|
+
const physicalValue = ParsePayload.pixel2physicalValue(rawValue, bscale, bzero);
|
|
20521
|
+
// Floating-point FITS images may contain NaN.
|
|
20522
|
+
if (Number.isNaN(physicalValue)) {
|
|
20523
|
+
continue;
|
|
20524
|
+
}
|
|
20525
|
+
if (min === null || physicalValue < min) {
|
|
20526
|
+
min = physicalValue;
|
|
20527
|
+
}
|
|
20528
|
+
if (max === null || physicalValue > max) {
|
|
20529
|
+
max = physicalValue;
|
|
20530
|
+
}
|
|
20531
|
+
}
|
|
20532
|
+
return [min, max];
|
|
20533
|
+
}
|
|
20534
|
+
static pixel2physicalValue(pxval, BSCALE, BZERO) {
|
|
20535
|
+
if (BZERO === null || BSCALE === null) {
|
|
20536
|
+
throw new Error("Either BZERO or BSCALE is null");
|
|
20537
|
+
}
|
|
20538
|
+
return BZERO + BSCALE * pxval;
|
|
20539
|
+
}
|
|
20540
|
+
static extractPixelValue(rawData, offset, bitpix) {
|
|
20541
|
+
ParsePayload.assertSupportedBITPIX(bitpix);
|
|
20542
|
+
const view = new DataView(rawData.buffer, rawData.byteOffset, rawData.byteLength);
|
|
20543
|
+
return ParsePayload.extractPixelFromView(view, offset, bitpix);
|
|
20544
|
+
}
|
|
20545
|
+
}
|
|
20546
|
+
//# sourceMappingURL=ParsePayload.js.map
|
|
20547
|
+
;// ./node_modules/jsfitsio/lib-esm/model/FITSHDU.js
|
|
20548
|
+
class FITSHDU {
|
|
20549
|
+
header;
|
|
20550
|
+
rawData;
|
|
20551
|
+
dataOffset;
|
|
20552
|
+
dataByteLength;
|
|
20553
|
+
constructor(header, rawData, dataOffset, dataByteLength) {
|
|
20554
|
+
this.header = header;
|
|
20555
|
+
this.rawData = rawData;
|
|
20556
|
+
this.dataOffset = dataOffset;
|
|
20557
|
+
this.dataByteLength = dataByteLength;
|
|
20558
|
+
}
|
|
20559
|
+
}
|
|
20560
|
+
//# sourceMappingURL=FITSHDU.js.map
|
|
20561
|
+
;// ./node_modules/jsfitsio/lib-esm/model/ImageHDU.js
|
|
20562
|
+
|
|
20563
|
+
class ImageHDU extends FITSHDU {
|
|
20564
|
+
bitpix;
|
|
20565
|
+
shape;
|
|
20566
|
+
typedData;
|
|
20567
|
+
type = "IMAGE";
|
|
20568
|
+
constructor(header, rawData, dataOffset, dataByteLength, bitpix, shape, typedData) {
|
|
20569
|
+
super(header, rawData, dataOffset, dataByteLength);
|
|
20570
|
+
this.bitpix = bitpix;
|
|
20571
|
+
this.shape = shape;
|
|
20572
|
+
this.typedData = typedData;
|
|
20573
|
+
}
|
|
20574
|
+
get naxis() {
|
|
20575
|
+
return this.shape.length;
|
|
20576
|
+
}
|
|
20577
|
+
get elementCount() {
|
|
20578
|
+
if (this.shape.length === 0) {
|
|
20579
|
+
return 0;
|
|
20580
|
+
}
|
|
20581
|
+
return this.shape.reduce((accumulator, dimension) => accumulator * dimension, 1);
|
|
20582
|
+
}
|
|
20583
|
+
}
|
|
20584
|
+
//# sourceMappingURL=ImageHDU.js.map
|
|
20585
|
+
;// ./node_modules/jsfitsio/lib-esm/model/PrimaryHDU.js
|
|
20586
|
+
|
|
20587
|
+
class PrimaryHDU extends ImageHDU {
|
|
20588
|
+
type = "PRIMARY";
|
|
20589
|
+
constructor(header, rawData, dataOffset, dataByteLength, bitpix, shape, typedData) {
|
|
20590
|
+
super(header, rawData, dataOffset, dataByteLength, bitpix, shape, typedData);
|
|
20591
|
+
}
|
|
20592
|
+
}
|
|
20593
|
+
//# sourceMappingURL=PrimaryHDU.js.map
|
|
20594
|
+
;// ./node_modules/jsfitsio/lib-esm/model/FITSFile.js
|
|
20595
|
+
|
|
20596
|
+
class FITSFile {
|
|
20597
|
+
_hdus;
|
|
20598
|
+
constructor(hdus = []) {
|
|
20599
|
+
this._hdus = [...hdus];
|
|
20600
|
+
}
|
|
20601
|
+
get hdus() {
|
|
20602
|
+
return this._hdus;
|
|
20603
|
+
}
|
|
20604
|
+
get length() {
|
|
20605
|
+
return this._hdus.length;
|
|
20606
|
+
}
|
|
20607
|
+
get primaryHDU() {
|
|
20608
|
+
const hdu = this._hdus[0];
|
|
20609
|
+
if (hdu instanceof PrimaryHDU) {
|
|
20610
|
+
return hdu;
|
|
20611
|
+
}
|
|
20612
|
+
return null;
|
|
20613
|
+
}
|
|
20614
|
+
getHDU(index) {
|
|
20615
|
+
return this._hdus[index] ?? null;
|
|
20616
|
+
}
|
|
20617
|
+
addHDU(hdu) {
|
|
20618
|
+
this._hdus.push(hdu);
|
|
20619
|
+
}
|
|
20620
|
+
}
|
|
20621
|
+
//# sourceMappingURL=FITSFile.js.map
|
|
20622
|
+
;// ./node_modules/jsfitsio/lib-esm/model/BinaryTableHDU.js
|
|
20623
|
+
|
|
20624
|
+
class BinaryTableHDU extends FITSHDU {
|
|
20625
|
+
rowByteLength;
|
|
20626
|
+
rowCount;
|
|
20627
|
+
columns;
|
|
20628
|
+
type = "BINTABLE";
|
|
20629
|
+
constructor(header, rawData, dataOffset, dataByteLength, rowByteLength, rowCount, columns) {
|
|
20630
|
+
super(header, rawData, dataOffset, dataByteLength);
|
|
20631
|
+
this.rowByteLength = rowByteLength;
|
|
20632
|
+
this.rowCount = rowCount;
|
|
20633
|
+
this.columns = columns;
|
|
20634
|
+
}
|
|
20635
|
+
get columnCount() {
|
|
20636
|
+
return this.columns.length;
|
|
20637
|
+
}
|
|
20638
|
+
getRowView(rowIndex) {
|
|
20639
|
+
if (rowIndex < 0 || rowIndex >= this.rowCount) {
|
|
20640
|
+
throw new RangeError(`Invalid row index ${rowIndex}.`);
|
|
20641
|
+
}
|
|
20642
|
+
const offset = rowIndex * this.rowByteLength;
|
|
20643
|
+
return new DataView(this.rawData.buffer, this.rawData.byteOffset + offset, this.rowByteLength);
|
|
20644
|
+
}
|
|
20645
|
+
getRow(rowIndex) {
|
|
20646
|
+
return this.columns.map((_, columnIndex) => this.getCell(rowIndex, columnIndex));
|
|
20647
|
+
}
|
|
20648
|
+
getCell(rowIndex, column) {
|
|
20649
|
+
const columnDefinition = this.resolveColumn(column);
|
|
20650
|
+
const row = this.getRowView(rowIndex);
|
|
20651
|
+
const offset = columnDefinition.byteOffset;
|
|
20652
|
+
const repeat = columnDefinition.repeat;
|
|
20653
|
+
switch (columnDefinition.type) {
|
|
20654
|
+
case "CHAR": {
|
|
20655
|
+
const bytes = new Uint8Array(row.buffer, row.byteOffset + offset, columnDefinition.byteWidth);
|
|
20656
|
+
return new TextDecoder("ascii").decode(bytes).replace(/\s+$/, "");
|
|
20657
|
+
}
|
|
20658
|
+
case "LOGICAL": {
|
|
20659
|
+
const values = [];
|
|
20660
|
+
for (let i = 0; i < repeat; i++) {
|
|
20661
|
+
const value = String.fromCharCode(row.getUint8(offset + i));
|
|
20662
|
+
values.push(value === "T");
|
|
20663
|
+
}
|
|
20664
|
+
return repeat === 1 ? values[0] : values;
|
|
20665
|
+
}
|
|
20666
|
+
case "UINT8": {
|
|
20667
|
+
const values = [];
|
|
20668
|
+
for (let i = 0; i < repeat; i++) {
|
|
20669
|
+
const raw = row.getUint8(offset + i);
|
|
20670
|
+
values.push(this.applyNumericScaling(raw, columnDefinition.scale, columnDefinition.zero));
|
|
20671
|
+
}
|
|
20672
|
+
return repeat === 1 ? values[0] : values;
|
|
20673
|
+
}
|
|
20674
|
+
case "INT16":
|
|
20675
|
+
return this.readNumericColumn(row, offset, repeat, 2, (view, position) => view.getInt16(position, false), columnDefinition.scale, columnDefinition.zero, columnDefinition.nullValue);
|
|
20676
|
+
case "INT32":
|
|
20677
|
+
return this.readNumericColumn(row, offset, repeat, 4, (view, position) => view.getInt32(position, false), columnDefinition.scale, columnDefinition.zero, columnDefinition.nullValue);
|
|
20678
|
+
case "INT64": {
|
|
20679
|
+
const values = [];
|
|
20680
|
+
for (let i = 0; i < repeat; i++) {
|
|
20681
|
+
const raw = row.getBigInt64(offset + i * 8, false);
|
|
20682
|
+
/*
|
|
20683
|
+
* Preserve exact 64-bit integers.
|
|
20684
|
+
*
|
|
20685
|
+
* Do not silently convert bigint to number.
|
|
20686
|
+
*/
|
|
20687
|
+
values.push(raw);
|
|
20688
|
+
}
|
|
20689
|
+
return repeat === 1 ? values[0] : values;
|
|
20690
|
+
}
|
|
20691
|
+
case "FLOAT32":
|
|
20692
|
+
return this.readNumericColumn(row, offset, repeat, 4, (view, position) => view.getFloat32(position, false), columnDefinition.scale, columnDefinition.zero, null);
|
|
20693
|
+
case "FLOAT64":
|
|
20694
|
+
return this.readNumericColumn(row, offset, repeat, 8, (view, position) => view.getFloat64(position, false), columnDefinition.scale, columnDefinition.zero, null);
|
|
20695
|
+
case "COMPLEX64": {
|
|
20696
|
+
const values = [];
|
|
20697
|
+
for (let i = 0; i < repeat; i++) {
|
|
20698
|
+
const position = offset + i * 8;
|
|
20699
|
+
values.push({
|
|
20700
|
+
real: row.getFloat32(position, false),
|
|
20701
|
+
imaginary: row.getFloat32(position + 4, false),
|
|
20702
|
+
});
|
|
20703
|
+
}
|
|
20704
|
+
return repeat === 1 ? values[0] : values;
|
|
20705
|
+
}
|
|
20706
|
+
case "COMPLEX128": {
|
|
20707
|
+
const values = [];
|
|
20708
|
+
for (let i = 0; i < repeat; i++) {
|
|
20709
|
+
const position = offset + i * 16;
|
|
20710
|
+
values.push({
|
|
20711
|
+
real: row.getFloat64(position, false),
|
|
20712
|
+
imaginary: row.getFloat64(position + 8, false),
|
|
20713
|
+
});
|
|
20714
|
+
}
|
|
20715
|
+
return repeat === 1 ? values[0] : values;
|
|
20716
|
+
}
|
|
20717
|
+
case "BIT":
|
|
20718
|
+
/*
|
|
20719
|
+
* I'd defer bit-array decoding for the moment.
|
|
20720
|
+
* The raw bytes remain available.
|
|
20721
|
+
*/
|
|
20722
|
+
return new Uint8Array(row.buffer, row.byteOffset + offset, columnDefinition.byteWidth).slice();
|
|
20723
|
+
default:
|
|
20724
|
+
throw new Error(`Unsupported BINTABLE column type: ${columnDefinition.type}`);
|
|
20725
|
+
}
|
|
20726
|
+
}
|
|
20727
|
+
readNumericColumn(view, offset, repeat, bytesPerElement, reader, scale, zero, nullValue) {
|
|
20728
|
+
const values = [];
|
|
20729
|
+
for (let i = 0; i < repeat; i++) {
|
|
20730
|
+
const raw = reader(view, offset + i * bytesPerElement);
|
|
20731
|
+
if (nullValue !== null && raw === nullValue) {
|
|
20732
|
+
values.push(null);
|
|
20733
|
+
continue;
|
|
20734
|
+
}
|
|
20735
|
+
values.push(this.applyNumericScaling(raw, scale, zero));
|
|
20736
|
+
}
|
|
20737
|
+
if (repeat === 1) {
|
|
20738
|
+
return values[0];
|
|
20739
|
+
}
|
|
20740
|
+
/*
|
|
20741
|
+
* Because repeated integer fields may contain NULL,
|
|
20742
|
+
* we cannot represent every case as number[].
|
|
20743
|
+
*
|
|
20744
|
+
* For now return a generic value array.
|
|
20745
|
+
*/
|
|
20746
|
+
return values;
|
|
20747
|
+
}
|
|
20748
|
+
applyNumericScaling(raw, scale, zero) {
|
|
20749
|
+
return zero + scale * raw;
|
|
20750
|
+
}
|
|
20751
|
+
resolveColumn(column) {
|
|
20752
|
+
if (typeof column === "number") {
|
|
20753
|
+
if (!Number.isInteger(column) ||
|
|
20754
|
+
column < 0 ||
|
|
20755
|
+
column >= this.columns.length) {
|
|
20756
|
+
throw new RangeError(`Invalid column index ${column}.`);
|
|
20757
|
+
}
|
|
20758
|
+
return this.columns[column];
|
|
20759
|
+
}
|
|
20760
|
+
const found = this.columns.find((candidate) => candidate.name === column);
|
|
20761
|
+
if (!found) {
|
|
20762
|
+
throw new Error(`BINTABLE column '${column}' not found.`);
|
|
20763
|
+
}
|
|
20764
|
+
return found;
|
|
20765
|
+
}
|
|
20766
|
+
}
|
|
20767
|
+
//# sourceMappingURL=BinaryTableHDU.js.map
|
|
20768
|
+
;// ./node_modules/jsfitsio/lib-esm/FITSBinaryTableUtils.js
|
|
20769
|
+
class FITSBinaryTableUtils {
|
|
20770
|
+
static parseTFORM(format) {
|
|
20771
|
+
const normalized = format
|
|
20772
|
+
.trim()
|
|
20773
|
+
.replace(/^'/, "")
|
|
20774
|
+
.replace(/'$/, "")
|
|
20775
|
+
.trim()
|
|
20776
|
+
.toUpperCase();
|
|
20777
|
+
const match = normalized.match(/^(\d*)([LXBIJKAEDCM])$/);
|
|
20778
|
+
if (!match) {
|
|
20779
|
+
throw new Error(`Unsupported FITS TFORM value: ${format}`);
|
|
20780
|
+
}
|
|
20781
|
+
const repeat = match[1] ? Number(match[1]) : 1;
|
|
20782
|
+
const code = match[2];
|
|
20783
|
+
const bytesPerElement = FITSBinaryTableUtils.bytesPerType(code);
|
|
20784
|
+
return {
|
|
20785
|
+
repeat,
|
|
20786
|
+
code,
|
|
20787
|
+
byteWidth: code === "X" ? Math.ceil(repeat / 8) : repeat * bytesPerElement,
|
|
20788
|
+
};
|
|
20789
|
+
}
|
|
20790
|
+
static bytesPerType(code) {
|
|
20791
|
+
switch (code) {
|
|
20792
|
+
case "L":
|
|
20793
|
+
case "B":
|
|
20794
|
+
case "A":
|
|
20795
|
+
return 1;
|
|
20796
|
+
case "I":
|
|
20797
|
+
return 2;
|
|
20798
|
+
case "J":
|
|
20799
|
+
case "E":
|
|
20800
|
+
return 4;
|
|
20801
|
+
case "K":
|
|
20802
|
+
case "D":
|
|
20803
|
+
return 8;
|
|
20804
|
+
case "C":
|
|
20805
|
+
return 8;
|
|
20806
|
+
case "M":
|
|
20807
|
+
return 16;
|
|
20808
|
+
case "X":
|
|
20809
|
+
return 0;
|
|
20810
|
+
default:
|
|
20811
|
+
throw new Error(`Unsupported FITS binary table type: ${code}`);
|
|
20812
|
+
}
|
|
20813
|
+
}
|
|
20814
|
+
}
|
|
20815
|
+
//# sourceMappingURL=FITSBinaryTableUtils.js.map
|
|
20816
|
+
;// ./node_modules/jsfitsio/lib-esm/model/AsciiTableHDU.js
|
|
20817
|
+
|
|
20818
|
+
class AsciiTableHDU extends FITSHDU {
|
|
20819
|
+
rowByteLength;
|
|
20820
|
+
rowCount;
|
|
20821
|
+
columns;
|
|
20822
|
+
type = "TABLE";
|
|
20823
|
+
constructor(header, rawData, dataOffset, dataByteLength, rowByteLength, rowCount, columns) {
|
|
20824
|
+
super(header, rawData, dataOffset, dataByteLength);
|
|
20825
|
+
this.rowByteLength = rowByteLength;
|
|
20826
|
+
this.rowCount = rowCount;
|
|
20827
|
+
this.columns = columns;
|
|
20828
|
+
}
|
|
20829
|
+
get columnCount() {
|
|
20830
|
+
return this.columns.length;
|
|
20831
|
+
}
|
|
20832
|
+
getRowView(rowIndex) {
|
|
20833
|
+
if (!Number.isInteger(rowIndex) ||
|
|
20834
|
+
rowIndex < 0 ||
|
|
20835
|
+
rowIndex >= this.rowCount) {
|
|
20836
|
+
throw new RangeError(`Invalid row index ${rowIndex}.`);
|
|
20837
|
+
}
|
|
20838
|
+
const start = rowIndex * this.rowByteLength;
|
|
20839
|
+
return this.rawData.subarray(start, start + this.rowByteLength);
|
|
20840
|
+
}
|
|
20841
|
+
getRowText(rowIndex) {
|
|
20842
|
+
return new TextDecoder("ascii").decode(this.getRowView(rowIndex));
|
|
20843
|
+
}
|
|
20844
|
+
resolveColumn(column) {
|
|
20845
|
+
if (typeof column === "number") {
|
|
20846
|
+
if (!Number.isInteger(column) ||
|
|
20847
|
+
column < 0 ||
|
|
20848
|
+
column >= this.columns.length) {
|
|
20849
|
+
throw new RangeError(`Invalid column index ${column}.`);
|
|
20850
|
+
}
|
|
20851
|
+
return this.columns[column];
|
|
20852
|
+
}
|
|
20853
|
+
const found = this.columns.find((candidate) => candidate.name === column);
|
|
20854
|
+
if (!found) {
|
|
20855
|
+
throw new Error(`ASCII TABLE column '${column}' not found.`);
|
|
20856
|
+
}
|
|
20857
|
+
return found;
|
|
20858
|
+
}
|
|
20859
|
+
getCell(rowIndex, column) {
|
|
20860
|
+
const definition = this.resolveColumn(column);
|
|
20861
|
+
const row = this.getRowView(rowIndex);
|
|
20862
|
+
const bytes = row.subarray(definition.byteOffset, definition.byteOffset + definition.width);
|
|
20863
|
+
const raw = new TextDecoder("ascii").decode(bytes);
|
|
20864
|
+
const trimmed = raw.trim();
|
|
20865
|
+
/*
|
|
20866
|
+
* Blank numeric fields are treated as null.
|
|
20867
|
+
*/
|
|
20868
|
+
if (trimmed.length === 0) {
|
|
20869
|
+
return definition.type === "CHAR" ? "" : null;
|
|
20870
|
+
}
|
|
20871
|
+
switch (definition.type) {
|
|
20872
|
+
case "CHAR":
|
|
20873
|
+
return raw.replace(/\s+$/, "");
|
|
20874
|
+
case "INTEGER": {
|
|
20875
|
+
const value = Number.parseInt(trimmed, 10);
|
|
20876
|
+
if (Number.isNaN(value)) {
|
|
20877
|
+
return null;
|
|
20878
|
+
}
|
|
20879
|
+
return value;
|
|
20880
|
+
}
|
|
20881
|
+
case "FLOAT":
|
|
20882
|
+
case "EXPONENTIAL":
|
|
20883
|
+
case "DOUBLE": {
|
|
20884
|
+
/*
|
|
20885
|
+
* FITS ASCII tables may use D exponent notation.
|
|
20886
|
+
* JavaScript expects E.
|
|
20887
|
+
*/
|
|
20888
|
+
const normalized = trimmed.replace(/[dD]/, "E");
|
|
20889
|
+
const value = Number.parseFloat(normalized);
|
|
20890
|
+
if (Number.isNaN(value)) {
|
|
20891
|
+
return null;
|
|
20892
|
+
}
|
|
20893
|
+
return value;
|
|
20894
|
+
}
|
|
20895
|
+
default:
|
|
20896
|
+
throw new Error(`Unsupported ASCII TABLE column type: ${definition.type}`);
|
|
20897
|
+
}
|
|
20898
|
+
}
|
|
20899
|
+
getRow(rowIndex) {
|
|
20900
|
+
return this.columns.map((_, columnIndex) => this.getCell(rowIndex, columnIndex));
|
|
20901
|
+
}
|
|
20902
|
+
}
|
|
20903
|
+
//# sourceMappingURL=AsciiTableHDU.js.map
|
|
20904
|
+
;// ./node_modules/jsfitsio/lib-esm/FITSAsciiTableUtils.js
|
|
20905
|
+
class FITSAsciiTableUtils {
|
|
20906
|
+
static parseTFORM(format) {
|
|
20907
|
+
const normalized = format
|
|
20908
|
+
.trim()
|
|
20909
|
+
.replace(/^'/, "")
|
|
20910
|
+
.replace(/'$/, "")
|
|
20911
|
+
.trim()
|
|
20912
|
+
.toUpperCase();
|
|
20913
|
+
/*
|
|
20914
|
+
* FITS ASCII table formats:
|
|
20915
|
+
*
|
|
20916
|
+
* Aw
|
|
20917
|
+
* Iw
|
|
20918
|
+
* Fw.d
|
|
20919
|
+
* Ew.d
|
|
20920
|
+
* Dw.d
|
|
20921
|
+
*/
|
|
20922
|
+
const match = normalized.match(/^([AIFED])(\d+)(?:\.(\d+))?$/);
|
|
20923
|
+
if (!match) {
|
|
20924
|
+
throw new Error(`Unsupported FITS ASCII table TFORM value: ${format}`);
|
|
20925
|
+
}
|
|
20926
|
+
const code = match[1];
|
|
20927
|
+
const width = Number(match[2]);
|
|
20928
|
+
const decimals = match[3] !== undefined
|
|
20929
|
+
? Number(match[3])
|
|
20930
|
+
: null;
|
|
20931
|
+
if (!Number.isInteger(width) ||
|
|
20932
|
+
width <= 0) {
|
|
20933
|
+
throw new Error(`Invalid FITS ASCII table field width: ${width}`);
|
|
20934
|
+
}
|
|
20935
|
+
if (code === "A" ||
|
|
20936
|
+
code === "I") {
|
|
20937
|
+
if (decimals !== null) {
|
|
20938
|
+
throw new Error(`TFORM ${format} must not specify decimal places.`);
|
|
20939
|
+
}
|
|
20940
|
+
}
|
|
20941
|
+
else if (decimals === null) {
|
|
20942
|
+
throw new Error(`TFORM ${format} requires decimal places.`);
|
|
20943
|
+
}
|
|
20944
|
+
return {
|
|
20945
|
+
code,
|
|
20946
|
+
width,
|
|
20947
|
+
decimals,
|
|
20948
|
+
};
|
|
20949
|
+
}
|
|
20950
|
+
}
|
|
20951
|
+
//# sourceMappingURL=FITSAsciiTableUtils.js.map
|
|
20952
|
+
;// ./node_modules/jsfitsio/lib-esm/FITSParser.js
|
|
20953
|
+
|
|
20954
|
+
|
|
20955
|
+
|
|
20956
|
+
|
|
20957
|
+
|
|
20958
|
+
|
|
20959
|
+
|
|
20960
|
+
|
|
20961
|
+
|
|
20962
|
+
|
|
20963
|
+
|
|
20964
|
+
|
|
20965
|
+
class FITSParser {
|
|
20966
|
+
/**
|
|
20967
|
+
* @deprecated Use loadFITSFile() instead.
|
|
20968
|
+
*
|
|
20969
|
+
* This legacy API supports only 2-dimensional image FITS files
|
|
20970
|
+
* and returns the former FITSParsed structure.
|
|
20971
|
+
*/
|
|
20972
|
+
static async loadFITS(path, options = {}) {
|
|
20973
|
+
const fitsFile = await FITSParser.loadFITSFile(path, options);
|
|
20974
|
+
if (fitsFile === null) {
|
|
20975
|
+
return null;
|
|
20976
|
+
}
|
|
20977
|
+
const primary = fitsFile.primaryHDU;
|
|
20978
|
+
if (primary === null || primary.rawData === null) {
|
|
20979
|
+
return null;
|
|
20980
|
+
}
|
|
20981
|
+
const shape = FITSImageUtils.getShape(primary.header);
|
|
20982
|
+
if (shape.length !== 2) {
|
|
20983
|
+
throw new Error("Legacy loadFITS() supports only 2D FITS images. " +
|
|
20984
|
+
"Use loadFITSFile() for N-dimensional images.");
|
|
20985
|
+
}
|
|
20986
|
+
return {
|
|
20987
|
+
header: primary.header,
|
|
20988
|
+
data: FITSParser.createMatrix(primary.rawData, primary.header),
|
|
20989
|
+
};
|
|
20990
|
+
}
|
|
20991
|
+
static async loadFITSFile(path, options = {}) {
|
|
20992
|
+
const rawData = await FITSParser.getFile(path);
|
|
20993
|
+
if (rawData.byteLength === 0) {
|
|
20994
|
+
return null;
|
|
20995
|
+
}
|
|
20996
|
+
return FITSParser.processFITSFile(rawData, options);
|
|
20997
|
+
}
|
|
20998
|
+
static processFITSFile(rawData, options) {
|
|
20999
|
+
const fitsFile = new FITSFile();
|
|
21000
|
+
let offset = 0;
|
|
21001
|
+
let hduIndex = 0;
|
|
21002
|
+
while (offset < rawData.byteLength) {
|
|
21003
|
+
/*
|
|
21004
|
+
* Ignore trailing zero/space padding.
|
|
21005
|
+
*/
|
|
21006
|
+
if (FITSParser.isPaddingOnly(rawData, offset)) {
|
|
21007
|
+
break;
|
|
21008
|
+
}
|
|
21009
|
+
const header = ParseHeader.parse(rawData, offset);
|
|
21010
|
+
const headerByteLength = ParseHeader.getHeaderByteLength(rawData, offset);
|
|
21011
|
+
const dataOffset = offset + headerByteLength;
|
|
21012
|
+
const hduType = FITSParser.getHDUType(header, hduIndex);
|
|
21013
|
+
switch (hduType) {
|
|
21014
|
+
case "PRIMARY":
|
|
21015
|
+
case "IMAGE": {
|
|
21016
|
+
const dataByteLength = FITSParser.getImagePayloadByteLength(header);
|
|
21017
|
+
if (dataOffset + dataByteLength > rawData.byteLength) {
|
|
21018
|
+
throw new Error(`Invalid FITS HDU ${hduIndex}: ` +
|
|
21019
|
+
`expected ${dataByteLength} payload bytes ` +
|
|
21020
|
+
`at offset ${dataOffset}, but only ` +
|
|
21021
|
+
`${rawData.byteLength - dataOffset} remain.`);
|
|
21022
|
+
}
|
|
21023
|
+
const rawPayload = rawData.subarray(dataOffset, dataOffset + dataByteLength);
|
|
21024
|
+
const hdu = FITSParser.createImageHDU(header, rawPayload, dataOffset, dataByteLength, hduIndex === 0, options);
|
|
21025
|
+
fitsFile.addHDU(hdu);
|
|
21026
|
+
const paddedPayloadLength = FITSParser.getPaddedByteLength(dataByteLength);
|
|
21027
|
+
offset = dataOffset + paddedPayloadLength;
|
|
21028
|
+
break;
|
|
21029
|
+
}
|
|
21030
|
+
case "BINTABLE": {
|
|
21031
|
+
const dataByteLength = FITSParser.getBinaryTablePayloadByteLength(header);
|
|
21032
|
+
if (dataOffset + dataByteLength > rawData.byteLength) {
|
|
21033
|
+
throw new Error(`Invalid BINTABLE HDU ${hduIndex}.`);
|
|
21034
|
+
}
|
|
21035
|
+
const rawPayload = rawData.subarray(dataOffset, dataOffset + dataByteLength);
|
|
21036
|
+
const hdu = FITSParser.createBinaryTableHDU(header, rawPayload, dataOffset, dataByteLength);
|
|
21037
|
+
fitsFile.addHDU(hdu);
|
|
21038
|
+
offset = dataOffset + FITSParser.getPaddedByteLength(dataByteLength);
|
|
21039
|
+
break;
|
|
21040
|
+
}
|
|
21041
|
+
case "TABLE": {
|
|
21042
|
+
const dataByteLength = FITSParser.getAsciiTablePayloadByteLength(header);
|
|
21043
|
+
if (dataOffset + dataByteLength > rawData.byteLength) {
|
|
21044
|
+
throw new Error(`Invalid ASCII TABLE HDU ${hduIndex}: ` +
|
|
21045
|
+
`expected ${dataByteLength} payload bytes ` +
|
|
21046
|
+
`at offset ${dataOffset}, but only ` +
|
|
21047
|
+
`${rawData.byteLength - dataOffset} remain.`);
|
|
21048
|
+
}
|
|
21049
|
+
const rawPayload = rawData.subarray(dataOffset, dataOffset + dataByteLength);
|
|
21050
|
+
const hdu = FITSParser.createAsciiTableHDU(header, rawPayload, dataOffset, dataByteLength);
|
|
21051
|
+
fitsFile.addHDU(hdu);
|
|
21052
|
+
offset = dataOffset + FITSParser.getPaddedByteLength(dataByteLength);
|
|
21053
|
+
break;
|
|
21054
|
+
}
|
|
21055
|
+
default:
|
|
21056
|
+
throw new Error(`Unsupported FITS HDU type at index ${hduIndex}.`);
|
|
21057
|
+
}
|
|
21058
|
+
hduIndex++;
|
|
21059
|
+
}
|
|
21060
|
+
return fitsFile;
|
|
21061
|
+
}
|
|
21062
|
+
static getPaddedByteLength(byteLength) {
|
|
21063
|
+
if (byteLength === 0) {
|
|
21064
|
+
return 0;
|
|
21065
|
+
}
|
|
21066
|
+
return (Math.ceil(byteLength / ParseHeader.BLOCK_SIZE) * ParseHeader.BLOCK_SIZE);
|
|
21067
|
+
}
|
|
21068
|
+
static isPaddingOnly(rawData, offset) {
|
|
21069
|
+
for (let i = offset; i < rawData.byteLength; i++) {
|
|
21070
|
+
const value = rawData[i];
|
|
21071
|
+
if (value !== 0x00 && value !== 0x20) {
|
|
21072
|
+
return false;
|
|
21073
|
+
}
|
|
21074
|
+
}
|
|
21075
|
+
return true;
|
|
21076
|
+
}
|
|
21077
|
+
static getHDUType(header, index) {
|
|
21078
|
+
if (index === 0) {
|
|
21079
|
+
return "PRIMARY";
|
|
21080
|
+
}
|
|
21081
|
+
const xtension = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.XTENSION);
|
|
21082
|
+
if (xtension === null) {
|
|
21083
|
+
return "UNKNOWN";
|
|
21084
|
+
}
|
|
21085
|
+
switch (xtension.toUpperCase()) {
|
|
21086
|
+
case "IMAGE":
|
|
21087
|
+
return "IMAGE";
|
|
21088
|
+
case "BINTABLE":
|
|
21089
|
+
return "BINTABLE";
|
|
21090
|
+
case "TABLE":
|
|
21091
|
+
return "TABLE";
|
|
21092
|
+
default:
|
|
21093
|
+
return "UNKNOWN";
|
|
21094
|
+
}
|
|
21095
|
+
}
|
|
21096
|
+
static createImageHDU(header, rawPayload, dataOffset, dataByteLength, primary, options) {
|
|
21097
|
+
const finalHeader = options.computeDataMinMax
|
|
21098
|
+
? (ParsePayload.computePhysicalMinAndMax(header, rawPayload) ?? header)
|
|
21099
|
+
: header;
|
|
21100
|
+
const bitpix = ParseHeader.getFITSItemValue(finalHeader, FITSHeaderManager.BITPIX);
|
|
21101
|
+
if (bitpix === null) {
|
|
21102
|
+
throw new Error("BITPIX not defined.");
|
|
21103
|
+
}
|
|
21104
|
+
const shape = FITSImageUtils.getShape(finalHeader);
|
|
21105
|
+
const typedData = ParsePayload.createTypedArray(rawPayload, bitpix);
|
|
21106
|
+
if (primary) {
|
|
21107
|
+
return new PrimaryHDU(finalHeader, rawPayload, dataOffset, dataByteLength, bitpix, shape, typedData);
|
|
21108
|
+
}
|
|
21109
|
+
return new ImageHDU(finalHeader, rawPayload, dataOffset, dataByteLength, bitpix, shape, typedData);
|
|
21110
|
+
}
|
|
21111
|
+
static getImagePayloadByteLength(header) {
|
|
21112
|
+
const bitpix = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BITPIX);
|
|
21113
|
+
if (bitpix === null) {
|
|
21114
|
+
throw new Error("BITPIX not defined.");
|
|
21115
|
+
}
|
|
21116
|
+
ParsePayload.assertSupportedBITPIX(bitpix);
|
|
21117
|
+
const shape = FITSImageUtils.getShape(header);
|
|
21118
|
+
if (shape.length === 0) {
|
|
21119
|
+
return 0;
|
|
21120
|
+
}
|
|
21121
|
+
const elementCount = shape.reduce((total, dimension) => total * dimension, 1);
|
|
21122
|
+
const bytesPerElement = Math.abs(bitpix) / 8;
|
|
21123
|
+
return elementCount * bytesPerElement;
|
|
21124
|
+
}
|
|
21125
|
+
static getBinaryTablePayloadByteLength(header) {
|
|
21126
|
+
const rowByteLength = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
|
|
21127
|
+
const rowCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
|
|
21128
|
+
const pcount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.PCOUNT) ?? 0;
|
|
21129
|
+
if (rowByteLength === null || rowCount === null) {
|
|
21130
|
+
throw new Error("BINTABLE requires NAXIS1 and NAXIS2.");
|
|
21131
|
+
}
|
|
21132
|
+
return rowByteLength * rowCount + pcount;
|
|
21133
|
+
}
|
|
21134
|
+
static getBinaryTableColumns(header) {
|
|
21135
|
+
const fieldCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.TFIELDS);
|
|
21136
|
+
if (fieldCount === null) {
|
|
21137
|
+
throw new Error("BINTABLE requires TFIELDS.");
|
|
21138
|
+
}
|
|
21139
|
+
const columns = [];
|
|
21140
|
+
let byteOffset = 0;
|
|
21141
|
+
for (let index = 1; index <= fieldCount; index++) {
|
|
21142
|
+
const tform = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TFORM", index));
|
|
21143
|
+
if (tform === null) {
|
|
21144
|
+
throw new Error(`Missing TFORM${index}.`);
|
|
21145
|
+
}
|
|
21146
|
+
const parsed = FITSBinaryTableUtils.parseTFORM(tform);
|
|
21147
|
+
const name = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TTYPE", index));
|
|
21148
|
+
const unit = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TUNIT", index));
|
|
21149
|
+
columns.push({
|
|
21150
|
+
index,
|
|
21151
|
+
name,
|
|
21152
|
+
format: tform,
|
|
21153
|
+
type: FITSParser.mapBinaryType(parsed.code),
|
|
21154
|
+
repeat: parsed.repeat,
|
|
21155
|
+
byteOffset,
|
|
21156
|
+
byteWidth: parsed.byteWidth,
|
|
21157
|
+
unit,
|
|
21158
|
+
scale: ParseHeader.getFITSItemValue(header, FITSHeaderManager.tableFieldKey("TSCAL", index)) ?? 1,
|
|
21159
|
+
zero: ParseHeader.getFITSItemValue(header, FITSHeaderManager.tableFieldKey("TZERO", index)) ?? 0,
|
|
21160
|
+
nullValue: ParseHeader.getFITSItemValue(header, FITSHeaderManager.tableFieldKey("TNULL", index)),
|
|
21161
|
+
});
|
|
21162
|
+
byteOffset += parsed.byteWidth;
|
|
21163
|
+
}
|
|
21164
|
+
return columns;
|
|
21165
|
+
}
|
|
21166
|
+
static mapBinaryType(code) {
|
|
21167
|
+
switch (code.toUpperCase()) {
|
|
21168
|
+
case "L":
|
|
21169
|
+
return "LOGICAL";
|
|
21170
|
+
case "X":
|
|
21171
|
+
return "BIT";
|
|
21172
|
+
case "B":
|
|
21173
|
+
return "UINT8";
|
|
21174
|
+
case "I":
|
|
21175
|
+
return "INT16";
|
|
21176
|
+
case "J":
|
|
21177
|
+
return "INT32";
|
|
21178
|
+
case "K":
|
|
21179
|
+
return "INT64";
|
|
21180
|
+
case "A":
|
|
21181
|
+
return "CHAR";
|
|
21182
|
+
case "E":
|
|
21183
|
+
return "FLOAT32";
|
|
21184
|
+
case "D":
|
|
21185
|
+
return "FLOAT64";
|
|
21186
|
+
case "C":
|
|
21187
|
+
return "COMPLEX64";
|
|
21188
|
+
case "M":
|
|
21189
|
+
return "COMPLEX128";
|
|
21190
|
+
default:
|
|
21191
|
+
return "UNKNOWN";
|
|
21192
|
+
}
|
|
21193
|
+
}
|
|
21194
|
+
static createBinaryTableHDU(header, rawPayload, dataOffset, dataByteLength) {
|
|
21195
|
+
const rowByteLength = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
|
|
21196
|
+
const rowCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
|
|
21197
|
+
if (rowByteLength === null || rowCount === null) {
|
|
21198
|
+
throw new Error("Invalid BINTABLE header.");
|
|
21199
|
+
}
|
|
21200
|
+
const columns = FITSParser.getBinaryTableColumns(header);
|
|
21201
|
+
const columnsByteWidth = columns.reduce((sum, column) => sum + column.byteWidth, 0);
|
|
21202
|
+
if (columnsByteWidth !== rowByteLength) {
|
|
21203
|
+
throw new Error(`BINTABLE columns occupy ${columnsByteWidth} bytes per row, ` +
|
|
21204
|
+
`but NAXIS1=${rowByteLength}.`);
|
|
21205
|
+
}
|
|
21206
|
+
return new BinaryTableHDU(header, rawPayload, dataOffset, dataByteLength, rowByteLength, rowCount, columns);
|
|
21207
|
+
}
|
|
21208
|
+
static getAsciiTablePayloadByteLength(header) {
|
|
21209
|
+
const rowByteLength = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
|
|
21210
|
+
const rowCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
|
|
21211
|
+
if (rowByteLength === null || rowCount === null) {
|
|
21212
|
+
throw new Error("ASCII TABLE requires NAXIS1 and NAXIS2.");
|
|
21213
|
+
}
|
|
21214
|
+
if (!Number.isInteger(rowByteLength) || rowByteLength < 0) {
|
|
21215
|
+
throw new Error(`Invalid ASCII TABLE NAXIS1=${rowByteLength}.`);
|
|
21216
|
+
}
|
|
21217
|
+
if (!Number.isInteger(rowCount) || rowCount < 0) {
|
|
21218
|
+
throw new Error(`Invalid ASCII TABLE NAXIS2=${rowCount}.`);
|
|
21219
|
+
}
|
|
21220
|
+
const pcount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.PCOUNT) ?? 0;
|
|
21221
|
+
if (pcount !== 0) {
|
|
21222
|
+
throw new Error(`ASCII TABLE requires PCOUNT=0, received ${pcount}.`);
|
|
21223
|
+
}
|
|
21224
|
+
return rowByteLength * rowCount;
|
|
21225
|
+
}
|
|
21226
|
+
static mapAsciiType(code) {
|
|
21227
|
+
switch (code.toUpperCase()) {
|
|
21228
|
+
case "A":
|
|
21229
|
+
return "CHAR";
|
|
21230
|
+
case "I":
|
|
21231
|
+
return "INTEGER";
|
|
21232
|
+
case "F":
|
|
21233
|
+
return "FLOAT";
|
|
21234
|
+
case "E":
|
|
21235
|
+
return "EXPONENTIAL";
|
|
21236
|
+
case "D":
|
|
21237
|
+
return "DOUBLE";
|
|
21238
|
+
default:
|
|
21239
|
+
return "UNKNOWN";
|
|
21240
|
+
}
|
|
21241
|
+
}
|
|
21242
|
+
static getAsciiTableColumns(header) {
|
|
21243
|
+
const fieldCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.TFIELDS);
|
|
21244
|
+
if (fieldCount === null) {
|
|
21245
|
+
throw new Error("ASCII TABLE requires TFIELDS.");
|
|
21246
|
+
}
|
|
21247
|
+
if (!Number.isInteger(fieldCount) || fieldCount < 0) {
|
|
21248
|
+
throw new Error(`Invalid ASCII TABLE TFIELDS=${fieldCount}.`);
|
|
21249
|
+
}
|
|
21250
|
+
const columns = [];
|
|
21251
|
+
for (let index = 1; index <= fieldCount; index++) {
|
|
21252
|
+
const tform = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TFORM", index));
|
|
21253
|
+
if (tform === null) {
|
|
21254
|
+
throw new Error(`Missing TFORM${index}.`);
|
|
21255
|
+
}
|
|
21256
|
+
const tbcol = ParseHeader.getFITSItemValue(header, FITSHeaderManager.tableFieldKey("TBCOL", index));
|
|
21257
|
+
if (tbcol === null) {
|
|
21258
|
+
throw new Error(`Missing TBCOL${index}.`);
|
|
21259
|
+
}
|
|
21260
|
+
if (!Number.isInteger(tbcol) || tbcol < 1) {
|
|
21261
|
+
throw new Error(`Invalid TBCOL${index}=${tbcol}.`);
|
|
21262
|
+
}
|
|
21263
|
+
const parsed = FITSAsciiTableUtils.parseTFORM(tform);
|
|
21264
|
+
const name = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TTYPE", index));
|
|
21265
|
+
const unit = ParseHeader.getFITSItemStringValue(header, FITSHeaderManager.tableFieldKey("TUNIT", index));
|
|
21266
|
+
columns.push({
|
|
21267
|
+
index,
|
|
21268
|
+
name,
|
|
21269
|
+
format: tform,
|
|
21270
|
+
type: FITSParser.mapAsciiType(parsed.code),
|
|
21271
|
+
startColumn: tbcol,
|
|
21272
|
+
/*
|
|
21273
|
+
* FITS TBCOL is 1-based.
|
|
21274
|
+
* JavaScript offsets are 0-based.
|
|
21275
|
+
*/
|
|
21276
|
+
byteOffset: tbcol - 1,
|
|
21277
|
+
width: parsed.width,
|
|
21278
|
+
decimals: parsed.decimals,
|
|
21279
|
+
unit,
|
|
21280
|
+
});
|
|
21281
|
+
}
|
|
21282
|
+
return columns;
|
|
21283
|
+
}
|
|
21284
|
+
static validateAsciiTableColumns(columns, rowByteLength) {
|
|
21285
|
+
for (const column of columns) {
|
|
21286
|
+
const endOffset = column.byteOffset + column.width;
|
|
21287
|
+
if (endOffset > rowByteLength) {
|
|
21288
|
+
throw new Error(`ASCII TABLE column ${column.index} ` +
|
|
21289
|
+
`extends to byte ${endOffset}, ` +
|
|
21290
|
+
`but NAXIS1=${rowByteLength}.`);
|
|
21291
|
+
}
|
|
21292
|
+
}
|
|
21293
|
+
}
|
|
21294
|
+
static createAsciiTableHDU(header, rawPayload, dataOffset, dataByteLength) {
|
|
21295
|
+
const rowByteLength = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
|
|
21296
|
+
const rowCount = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
|
|
21297
|
+
if (rowByteLength === null || rowCount === null) {
|
|
21298
|
+
throw new Error("Invalid ASCII TABLE header.");
|
|
21299
|
+
}
|
|
21300
|
+
const columns = FITSParser.getAsciiTableColumns(header);
|
|
21301
|
+
FITSParser.validateAsciiTableColumns(columns, rowByteLength);
|
|
21302
|
+
return new AsciiTableHDU(header, rawPayload, dataOffset, dataByteLength, rowByteLength, rowCount, columns);
|
|
21303
|
+
}
|
|
21304
|
+
static createMatrix(payload, header) {
|
|
21305
|
+
const NAXIS1 = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS1);
|
|
21306
|
+
if (NAXIS1 === null) {
|
|
21307
|
+
throw new Error("NAXIS1 not defined.");
|
|
21308
|
+
}
|
|
21309
|
+
const NAXIS2 = ParseHeader.getFITSItemValue(header, FITSHeaderManager.NAXIS2);
|
|
21310
|
+
if (NAXIS2 === null) {
|
|
21311
|
+
throw new Error("NAXIS2 not defined.");
|
|
21312
|
+
}
|
|
21313
|
+
const BITPIX = ParseHeader.getFITSItemValue(header, FITSHeaderManager.BITPIX);
|
|
21314
|
+
if (BITPIX === null) {
|
|
21315
|
+
throw new Error("BITPIX not defined.");
|
|
21316
|
+
}
|
|
21317
|
+
const bytesXelem = Math.abs(BITPIX / 8);
|
|
21318
|
+
// if (payload.length !== NAXIS1 * NAXIS2 * bytesXelem) {
|
|
21319
|
+
// throw new Error("Payload size does not match the expected matrix dimensions.");
|
|
21320
|
+
// }
|
|
21321
|
+
// const matrix: Array<Uint8Array> = [];
|
|
21322
|
+
const matrix = [];
|
|
21323
|
+
for (let i = 0; i < NAXIS2; i++) {
|
|
21324
|
+
matrix.push(payload.slice(i * NAXIS1 * bytesXelem, (i + 1) * NAXIS1 * bytesXelem));
|
|
21325
|
+
}
|
|
21326
|
+
return matrix;
|
|
21327
|
+
}
|
|
21328
|
+
/**
|
|
21329
|
+
* @deprecated Legacy FITSParsed writer API.
|
|
21330
|
+
*/
|
|
21331
|
+
static saveFITSLocally(fitsParsed, path) {
|
|
21332
|
+
return FITSWriter.writeFITSFile(fitsParsed, path);
|
|
21333
|
+
}
|
|
21334
|
+
static async getFile(uri) {
|
|
21335
|
+
if (!uri.substring(0, 5).toLowerCase().includes("http")) {
|
|
21336
|
+
const p = await __webpack_require__.e(/* import() */ 64).then(__webpack_require__.bind(__webpack_require__, 7064));
|
|
21337
|
+
const rawData = await p.getLocalFile(uri);
|
|
21338
|
+
if (rawData?.length) {
|
|
21339
|
+
const uint8 = new Uint8Array(rawData);
|
|
21340
|
+
return uint8;
|
|
21341
|
+
}
|
|
21342
|
+
return new Uint8Array(0);
|
|
21343
|
+
}
|
|
21344
|
+
else {
|
|
21345
|
+
const p = await __webpack_require__.e(/* import() */ 911).then(__webpack_require__.bind(__webpack_require__, 1911));
|
|
21346
|
+
const rawData = await p.getFile(uri);
|
|
21347
|
+
if (rawData?.byteLength) {
|
|
21348
|
+
const uint8 = new Uint8Array(rawData);
|
|
21349
|
+
return uint8;
|
|
21350
|
+
}
|
|
21351
|
+
return new Uint8Array(0);
|
|
21352
|
+
}
|
|
21353
|
+
}
|
|
21354
|
+
}
|
|
21355
|
+
// const url = "http://skies.esac.esa.int/Herschel/normalized/PACS_hips160//Norder8/Dir40000/Npix47180.fits"
|
|
21356
|
+
// FITSParser.loadFITS(url).then((fits) => {
|
|
21357
|
+
// if (fits == null) {
|
|
21358
|
+
// return null
|
|
21359
|
+
// }
|
|
21360
|
+
// const path = "./fitsTest1.fits"
|
|
21361
|
+
// console.log(fits.header)
|
|
21362
|
+
// FITSParser.saveFITSLocally(fits, path)
|
|
21363
|
+
// console.log("finished")
|
|
21364
|
+
// })
|
|
21365
|
+
// // const file = "/Users/fabriziogiordano/Desktop/PhD/code/new/FITSParser/tests/inputs/empty.fits"
|
|
21366
|
+
// const file = "/Users/fabriziogiordano/Desktop/PhD/code/new/FITSParser/tests/inputs/Npix43348.fits"
|
|
21367
|
+
// FITSParser.loadFITS(file).then((fits) => {
|
|
21368
|
+
// if (fits == null) {
|
|
21369
|
+
// return null
|
|
21370
|
+
// }
|
|
21371
|
+
// const path = "./fitsTest2.fits"
|
|
21372
|
+
// console.log(fits.header)
|
|
21373
|
+
// FITSParser.saveFITSLocally(fits, path)
|
|
21374
|
+
// console.log("finished")
|
|
21375
|
+
// })
|
|
21376
|
+
//# sourceMappingURL=FITSParser.js.map
|
|
21377
|
+
;// ./node_modules/jsfitsio/lib-esm/index.js
|
|
21378
|
+
|
|
21379
|
+
|
|
21380
|
+
|
|
21381
|
+
|
|
21382
|
+
|
|
21383
|
+
|
|
21384
|
+
|
|
21385
|
+
|
|
21386
|
+
|
|
21387
|
+
|
|
21388
|
+
|
|
21389
|
+
|
|
21390
|
+
//# sourceMappingURL=index.js.map
|
|
21391
|
+
|
|
21392
|
+
/***/ }
|
|
21393
|
+
|
|
21394
|
+
/******/ });
|
|
21395
|
+
/************************************************************************/
|
|
21396
|
+
/******/ // The module cache
|
|
21397
|
+
/******/ const __webpack_module_cache__ = {};
|
|
21398
|
+
/******/
|
|
21399
|
+
/******/ // The require function
|
|
21400
|
+
/******/ function __webpack_require__(moduleId) {
|
|
21401
|
+
/******/ // Check if module is in cache
|
|
21402
|
+
/******/ const cachedModule = __webpack_module_cache__[moduleId];
|
|
21403
|
+
/******/ if (cachedModule !== undefined) {
|
|
21404
|
+
/******/ return cachedModule.exports;
|
|
21405
|
+
/******/ }
|
|
21406
|
+
/******/ // Create a new module (and put it into the cache)
|
|
21407
|
+
/******/ const module = __webpack_module_cache__[moduleId] = {
|
|
21408
|
+
/******/ // no module.id needed
|
|
21409
|
+
/******/ // no module.loaded needed
|
|
21410
|
+
/******/ exports: {}
|
|
21411
|
+
/******/ };
|
|
21412
|
+
/******/
|
|
21413
|
+
/******/ // Execute the module function
|
|
21414
|
+
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
21415
|
+
/******/
|
|
21416
|
+
/******/ // Return the exports of the module
|
|
21417
|
+
/******/ return module.exports;
|
|
21418
|
+
/******/ }
|
|
21419
|
+
/******/
|
|
21420
|
+
/******/ // expose the modules object (__webpack_modules__)
|
|
21421
|
+
/******/ __webpack_require__.m = __webpack_modules__;
|
|
21422
|
+
/******/
|
|
21423
|
+
/************************************************************************/
|
|
21424
|
+
/******/ /* webpack/runtime/define property getters */
|
|
21425
|
+
/******/ (() => {
|
|
21426
|
+
/******/ // define getter/value functions for harmony exports
|
|
21427
|
+
/******/ __webpack_require__.d = (exports, definition) => {
|
|
21428
|
+
/******/ if(Array.isArray(definition)) {
|
|
21429
|
+
/******/ var i = 0;
|
|
21430
|
+
/******/ while(i < definition.length) {
|
|
21431
|
+
/******/ var key = definition[i++];
|
|
21432
|
+
/******/ var binding = definition[i++];
|
|
21433
|
+
/******/ if(!__webpack_require__.o(exports, key)) {
|
|
21434
|
+
/******/ if(binding === 0) {
|
|
21435
|
+
/******/ Object.defineProperty(exports, key, { enumerable: true, value: definition[i++] });
|
|
21436
|
+
/******/ } else {
|
|
21437
|
+
/******/ Object.defineProperty(exports, key, { enumerable: true, get: binding });
|
|
21438
|
+
/******/ }
|
|
21439
|
+
/******/ } else if(binding === 0) { i++; }
|
|
21440
|
+
/******/ }
|
|
21441
|
+
/******/ } else {
|
|
21442
|
+
/******/ for(var key in definition) {
|
|
21443
|
+
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
21444
|
+
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
21445
|
+
/******/ }
|
|
21446
|
+
/******/ }
|
|
21447
|
+
/******/ }
|
|
21448
|
+
/******/ };
|
|
21449
|
+
/******/ })();
|
|
21450
|
+
/******/
|
|
21451
|
+
/******/ /* webpack/runtime/ensure chunk */
|
|
21452
|
+
/******/ (() => {
|
|
21453
|
+
/******/ __webpack_require__.f = {};
|
|
21454
|
+
/******/ // This file contains only the entry chunk.
|
|
21455
|
+
/******/ // The chunk loading function for additional chunks
|
|
21456
|
+
/******/ __webpack_require__.e = (chunkId) => {
|
|
21457
|
+
/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
|
|
21458
|
+
/******/ __webpack_require__.f[key](chunkId, promises);
|
|
21459
|
+
/******/ return promises;
|
|
21460
|
+
/******/ }, []));
|
|
21461
|
+
/******/ };
|
|
21462
|
+
/******/ })();
|
|
21463
|
+
/******/
|
|
21464
|
+
/******/ /* webpack/runtime/get javascript chunk filename */
|
|
21465
|
+
/******/ (() => {
|
|
21466
|
+
/******/ // This function allow to reference async chunks
|
|
21467
|
+
/******/ __webpack_require__.u = (chunkId) => {
|
|
21468
|
+
/******/ // return url for filenames based on template
|
|
21469
|
+
/******/ return "" + chunkId + ".astroviewer.cjs";
|
|
21470
|
+
/******/ };
|
|
21471
|
+
/******/ })();
|
|
21472
|
+
/******/
|
|
21473
|
+
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
21474
|
+
/******/ (() => {
|
|
21475
|
+
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
|
21476
|
+
/******/ })();
|
|
21477
|
+
/******/
|
|
21478
|
+
/******/ /* webpack/runtime/make namespace object */
|
|
21479
|
+
/******/ (() => {
|
|
21480
|
+
/******/ // define __esModule on exports
|
|
21481
|
+
/******/ __webpack_require__.r = (exports) => {
|
|
21482
|
+
/******/ if(Symbol.toStringTag) {
|
|
21483
|
+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
21484
|
+
/******/ }
|
|
21485
|
+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
21486
|
+
/******/ };
|
|
21487
|
+
/******/ })();
|
|
21488
|
+
/******/
|
|
21489
|
+
/******/ /* webpack/runtime/require chunk loading */
|
|
21490
|
+
/******/ (() => {
|
|
21491
|
+
/******/ // no baseURI
|
|
21492
|
+
/******/
|
|
21493
|
+
/******/ // object to store loaded chunks
|
|
21494
|
+
/******/ // "1" means "loaded", otherwise not loaded yet
|
|
21495
|
+
/******/ const installedChunks = {
|
|
21496
|
+
/******/ 792: 1
|
|
21497
|
+
/******/ };
|
|
21498
|
+
/******/
|
|
21499
|
+
/******/ // no on chunks loaded
|
|
21500
|
+
/******/
|
|
21501
|
+
/******/ const installChunk = (chunk) => {
|
|
21502
|
+
/******/ const moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime;
|
|
21503
|
+
/******/ for(var moduleId in moreModules) {
|
|
21504
|
+
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
|
|
21505
|
+
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
|
|
21506
|
+
/******/ }
|
|
21507
|
+
/******/ }
|
|
21508
|
+
/******/ if(runtime) runtime(__webpack_require__);
|
|
21509
|
+
/******/ for(var i = 0; i < chunkIds.length; i++)
|
|
21510
|
+
/******/ installedChunks[chunkIds[i]] = 1;
|
|
21511
|
+
/******/
|
|
21512
|
+
/******/ };
|
|
21513
|
+
/******/
|
|
21514
|
+
/******/ // require() chunk loading for javascript
|
|
21515
|
+
/******/ __webpack_require__.f.require = (chunkId, promises) => {
|
|
21516
|
+
/******/ // "1" is the signal for "already loaded"
|
|
21517
|
+
/******/ if(!installedChunks[chunkId]) {
|
|
21518
|
+
/******/ if(true) { // all chunks have JS
|
|
21519
|
+
/******/ const installedChunk = require("./" + __webpack_require__.u(chunkId));
|
|
21520
|
+
/******/ if (!installedChunks[chunkId]) {
|
|
21521
|
+
/******/ installChunk(installedChunk);
|
|
21522
|
+
/******/ }
|
|
21523
|
+
/******/ } else installedChunks[chunkId] = 1;
|
|
21524
|
+
/******/ }
|
|
19337
21525
|
/******/ };
|
|
21526
|
+
/******/
|
|
21527
|
+
/******/ // no external install chunk
|
|
21528
|
+
/******/
|
|
21529
|
+
/******/ // no HMR
|
|
21530
|
+
/******/
|
|
21531
|
+
/******/ // no HMR manifest
|
|
19338
21532
|
/******/ })();
|
|
19339
21533
|
/******/
|
|
19340
21534
|
/************************************************************************/
|