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