@holoscript/radio-astronomy-plugin 2.0.2 → 2.0.3
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/__tests__/SpectralCubeViewer.test.ts +6 -4
- package/package.json +10 -10
- package/src/components/SpectralCubeViewer.tsx +57 -32
- package/src/fits/FITSParser.ts +34 -11
- package/src/fits/FITSToGrid.ts +2 -1
- package/src/index.ts +6 -1
- package/LICENSE +0 -21
- package/dist/bridge/python-runner.d.ts +0 -24
- package/dist/bridge/python-runner.d.ts.map +0 -1
- package/dist/bridge/python-runner.js +0 -43
- package/dist/bridge/python-runner.js.map +0 -1
- package/dist/components/SpectralCubeViewer.d.ts +0 -45
- package/dist/components/SpectralCubeViewer.d.ts.map +0 -1
- package/dist/components/SpectralCubeViewer.js +0 -196
- package/dist/components/SpectralCubeViewer.js.map +0 -1
- package/dist/constants/astronomy-traits.d.ts +0 -6
- package/dist/constants/astronomy-traits.d.ts.map +0 -1
- package/dist/constants/astronomy-traits.js +0 -12
- package/dist/constants/astronomy-traits.js.map +0 -1
- package/dist/fits/FITSParser.d.ts +0 -60
- package/dist/fits/FITSParser.d.ts.map +0 -1
- package/dist/fits/FITSParser.js +0 -230
- package/dist/fits/FITSParser.js.map +0 -1
- package/dist/fits/FITSToGrid.d.ts +0 -27
- package/dist/fits/FITSToGrid.d.ts.map +0 -1
- package/dist/fits/FITSToGrid.js +0 -85
- package/dist/fits/FITSToGrid.js.map +0 -1
- package/dist/index.d.ts +0 -25
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -28
- package/dist/index.js.map +0 -1
|
@@ -33,7 +33,9 @@ describe('FITS Viewer Pipeline', () => {
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
it('parses a synthetic 3D FITS spectral cube', () => {
|
|
36
|
-
const nx = 4,
|
|
36
|
+
const nx = 4,
|
|
37
|
+
ny = 3,
|
|
38
|
+
nz = 5;
|
|
37
39
|
const data: number[] = [];
|
|
38
40
|
for (let k = 0; k < nz; k++) {
|
|
39
41
|
for (let j = 0; j < ny; j++) {
|
|
@@ -107,9 +109,9 @@ describe('FITS Viewer Pipeline', () => {
|
|
|
107
109
|
|
|
108
110
|
const fits = parseFITS(buffer);
|
|
109
111
|
// Physical value = BSCALE * raw + BZERO
|
|
110
|
-
expect(fits.data[0]).toBeCloseTo(50);
|
|
111
|
-
expect(fits.data[1]).toBeCloseTo(60);
|
|
112
|
-
expect(fits.data[3]).toBeCloseTo(80);
|
|
112
|
+
expect(fits.data[0]).toBeCloseTo(50); // 0.1 * 0 + 50
|
|
113
|
+
expect(fits.data[1]).toBeCloseTo(60); // 0.1 * 100 + 50
|
|
114
|
+
expect(fits.data[3]).toBeCloseTo(80); // 0.1 * 300 + 50
|
|
113
115
|
});
|
|
114
116
|
|
|
115
117
|
it('2D image converts to nx×ny×1 grid', () => {
|
package/package.json
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holoscript/radio-astronomy-plugin",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "Radio Astrophysics plugin for HoloScript spatial environments. Adds primitives for interferometers, pulsar analysis, and synchrotron emissions.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "vitest run",
|
|
10
|
+
"lint": "eslint src --ext .ts",
|
|
11
|
+
"clean": "rimraf dist",
|
|
12
|
+
"test:coverage": "vitest run --coverage"
|
|
13
|
+
},
|
|
7
14
|
"keywords": [
|
|
8
15
|
"holoscript",
|
|
9
16
|
"plugin",
|
|
@@ -17,17 +24,10 @@
|
|
|
17
24
|
"@holoscript/engine": "^6.1.3"
|
|
18
25
|
},
|
|
19
26
|
"peerDependencies": {
|
|
20
|
-
"@holoscript/core": "8.0.
|
|
27
|
+
"@holoscript/core": ">=8.0.0"
|
|
21
28
|
},
|
|
22
29
|
"devDependencies": {
|
|
23
30
|
"typescript": "^5.0.0",
|
|
24
31
|
"vitest": "^4.1.5"
|
|
25
|
-
},
|
|
26
|
-
"scripts": {
|
|
27
|
-
"build": "tsc",
|
|
28
|
-
"test": "vitest run",
|
|
29
|
-
"lint": "eslint src --ext .ts",
|
|
30
|
-
"clean": "rimraf dist",
|
|
31
|
-
"test:coverage": "vitest run --coverage"
|
|
32
32
|
}
|
|
33
|
-
}
|
|
33
|
+
}
|
|
@@ -121,7 +121,8 @@ export function SpectralCubeViewer({
|
|
|
121
121
|
|
|
122
122
|
// Data range for colormap normalization
|
|
123
123
|
const [min, max] = useMemo(() => {
|
|
124
|
-
let lo = Infinity,
|
|
124
|
+
let lo = Infinity,
|
|
125
|
+
hi = -Infinity;
|
|
125
126
|
for (let i = 0; i < channelData.length; i++) {
|
|
126
127
|
if (channelData[i] < lo) lo = channelData[i];
|
|
127
128
|
if (channelData[i] > hi) hi = channelData[i];
|
|
@@ -131,7 +132,12 @@ export function SpectralCubeViewer({
|
|
|
131
132
|
|
|
132
133
|
// Build geometry: flat plane with per-pixel intensity attribute
|
|
133
134
|
const geometry = useMemo(() => {
|
|
134
|
-
const geo = new THREE.PlaneGeometry(
|
|
135
|
+
const geo = new THREE.PlaneGeometry(
|
|
136
|
+
nx / Math.max(nx, ny),
|
|
137
|
+
ny / Math.max(nx, ny),
|
|
138
|
+
nx - 1,
|
|
139
|
+
ny - 1
|
|
140
|
+
);
|
|
135
141
|
const intensities = new Float32Array(nx * ny);
|
|
136
142
|
for (let j = 0; j < ny; j++) {
|
|
137
143
|
for (let i = 0; i < nx; i++) {
|
|
@@ -155,10 +161,13 @@ export function SpectralCubeViewer({
|
|
|
155
161
|
|
|
156
162
|
const fragmentShader = useMemo(() => makeFrag(colormap), [colormap]);
|
|
157
163
|
|
|
158
|
-
const uniforms = useMemo(
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
164
|
+
const uniforms = useMemo(
|
|
165
|
+
() => ({
|
|
166
|
+
uMin: { value: min },
|
|
167
|
+
uMax: { value: max },
|
|
168
|
+
}),
|
|
169
|
+
[min, max]
|
|
170
|
+
);
|
|
162
171
|
|
|
163
172
|
// Channel label from WCS
|
|
164
173
|
const channelLabel = useMemo(() => {
|
|
@@ -215,15 +224,17 @@ export function FITSViewerPanel({ fitsBuffer, onClose }: FITSViewerPanelProps) {
|
|
|
215
224
|
useEffect(() => {
|
|
216
225
|
try {
|
|
217
226
|
// Dynamic import to avoid bundling FITS parser unless needed
|
|
218
|
-
import('../fits/FITSParser')
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
+
import('../fits/FITSParser')
|
|
228
|
+
.then(({ parseFITS }) => {
|
|
229
|
+
const fits = parseFITS(fitsBuffer);
|
|
230
|
+
setFitsData({
|
|
231
|
+
data: fits.data,
|
|
232
|
+
shape: fits.shape,
|
|
233
|
+
wcs: fits.wcs,
|
|
234
|
+
object: fits.object || 'Unknown Object',
|
|
235
|
+
});
|
|
236
|
+
})
|
|
237
|
+
.catch((e) => setError(String(e)));
|
|
227
238
|
} catch (e) {
|
|
228
239
|
setError(String(e));
|
|
229
240
|
}
|
|
@@ -249,20 +260,23 @@ export function FITSViewerPanel({ fitsBuffer, onClose }: FITSViewerPanelProps) {
|
|
|
249
260
|
const is3D = fitsData.shape.length >= 3 && nz > 1;
|
|
250
261
|
|
|
251
262
|
return (
|
|
252
|
-
<div
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
263
|
+
<div
|
|
264
|
+
style={{
|
|
265
|
+
display: 'flex',
|
|
266
|
+
flexDirection: 'column',
|
|
267
|
+
gap: 8,
|
|
268
|
+
padding: 12,
|
|
269
|
+
background: '#1a1a2e',
|
|
270
|
+
borderRadius: 8,
|
|
271
|
+
border: '1px solid #2a2a3e',
|
|
272
|
+
color: '#e4e4e7',
|
|
273
|
+
fontFamily: "'Space Mono', monospace",
|
|
274
|
+
}}
|
|
275
|
+
>
|
|
258
276
|
{/* Header */}
|
|
259
277
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
260
|
-
<span style={{ fontSize: 13, fontWeight: 700, color: '#a78bfa' }}>
|
|
261
|
-
|
|
262
|
-
</span>
|
|
263
|
-
<span style={{ fontSize: 10, color: '#71717a' }}>
|
|
264
|
-
{fitsData.shape.join(' × ')} px
|
|
265
|
-
</span>
|
|
278
|
+
<span style={{ fontSize: 13, fontWeight: 700, color: '#a78bfa' }}>{fitsData.object}</span>
|
|
279
|
+
<span style={{ fontSize: 10, color: '#71717a' }}>{fitsData.shape.join(' × ')} px</span>
|
|
266
280
|
</div>
|
|
267
281
|
|
|
268
282
|
{/* Channel Slider (only for 3D cubes) */}
|
|
@@ -272,8 +286,12 @@ export function FITSViewerPanel({ fitsBuffer, onClose }: FITSViewerPanelProps) {
|
|
|
272
286
|
onClick={() => setPlaying(!playing)}
|
|
273
287
|
style={{
|
|
274
288
|
background: playing ? '#ef4444' : '#3b82f6',
|
|
275
|
-
border: 'none',
|
|
276
|
-
|
|
289
|
+
border: 'none',
|
|
290
|
+
borderRadius: 4,
|
|
291
|
+
padding: '4px 10px',
|
|
292
|
+
color: 'white',
|
|
293
|
+
fontSize: 11,
|
|
294
|
+
cursor: 'pointer',
|
|
277
295
|
}}
|
|
278
296
|
>
|
|
279
297
|
{playing ? 'Stop' : 'Play'}
|
|
@@ -283,7 +301,10 @@ export function FITSViewerPanel({ fitsBuffer, onClose }: FITSViewerPanelProps) {
|
|
|
283
301
|
min={0}
|
|
284
302
|
max={nz - 1}
|
|
285
303
|
value={channel}
|
|
286
|
-
onChange={(e) => {
|
|
304
|
+
onChange={(e) => {
|
|
305
|
+
setChannel(Number(e.target.value));
|
|
306
|
+
setPlaying(false);
|
|
307
|
+
}}
|
|
287
308
|
style={{ flex: 1 }}
|
|
288
309
|
/>
|
|
289
310
|
<span style={{ fontSize: 10, color: '#71717a', minWidth: 80, textAlign: 'right' }}>
|
|
@@ -294,14 +315,18 @@ export function FITSViewerPanel({ fitsBuffer, onClose }: FITSViewerPanelProps) {
|
|
|
294
315
|
|
|
295
316
|
{/* Data range */}
|
|
296
317
|
<div style={{ fontSize: 10, color: '#71717a' }}>
|
|
297
|
-
Range:
|
|
318
|
+
Range:{' '}
|
|
319
|
+
{dataRange(fitsData.data)
|
|
320
|
+
.map((v) => v.toExponential(2))
|
|
321
|
+
.join(' → ')}
|
|
298
322
|
</div>
|
|
299
323
|
</div>
|
|
300
324
|
);
|
|
301
325
|
}
|
|
302
326
|
|
|
303
327
|
function dataRange(data: Float32Array): [number, number] {
|
|
304
|
-
let min = Infinity,
|
|
328
|
+
let min = Infinity,
|
|
329
|
+
max = -Infinity;
|
|
305
330
|
for (let i = 0; i < data.length; i++) {
|
|
306
331
|
if (data[i] < min) min = data[i];
|
|
307
332
|
if (data[i] > max) max = data[i];
|
package/src/fits/FITSParser.ts
CHANGED
|
@@ -66,8 +66,7 @@ export function parseFITS(buffer: ArrayBuffer): FITSFile {
|
|
|
66
66
|
const headers = new Map<string, string | number | boolean>();
|
|
67
67
|
let headerEnd = 0;
|
|
68
68
|
|
|
69
|
-
outer:
|
|
70
|
-
for (let block = 0; block * BLOCK_SIZE < buffer.byteLength; block++) {
|
|
69
|
+
outer: for (let block = 0; block * BLOCK_SIZE < buffer.byteLength; block++) {
|
|
71
70
|
for (let card = 0; card < CARDS_PER_BLOCK; card++) {
|
|
72
71
|
const offset = block * BLOCK_SIZE + card * CARD_SIZE;
|
|
73
72
|
if (offset + CARD_SIZE > buffer.byteLength) break outer;
|
|
@@ -111,7 +110,9 @@ export function parseFITS(buffer: ArrayBuffer): FITSFile {
|
|
|
111
110
|
const dataOffset = headerEnd;
|
|
112
111
|
|
|
113
112
|
if (dataOffset + totalPixels * bytesPerPixel > buffer.byteLength) {
|
|
114
|
-
throw new Error(
|
|
113
|
+
throw new Error(
|
|
114
|
+
`FITS: Data section extends beyond buffer (need ${dataOffset + totalPixels * bytesPerPixel}, have ${buffer.byteLength})`
|
|
115
|
+
);
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
const data = new Float32Array(totalPixels);
|
|
@@ -148,7 +149,11 @@ export function parseFITS(buffer: ArrayBuffer): FITSFile {
|
|
|
148
149
|
let wcs: WCSInfo | null = null;
|
|
149
150
|
if (headers.has('CRVAL1')) {
|
|
150
151
|
wcs = {
|
|
151
|
-
crpix: [],
|
|
152
|
+
crpix: [],
|
|
153
|
+
crval: [],
|
|
154
|
+
cdelt: [],
|
|
155
|
+
ctype: [],
|
|
156
|
+
cunit: [],
|
|
152
157
|
};
|
|
153
158
|
for (let i = 1; i <= naxis; i++) {
|
|
154
159
|
wcs.crpix.push(getNumOr(headers, `CRPIX${i}`, 1));
|
|
@@ -225,11 +230,21 @@ export function buildFITS(opts: {
|
|
|
225
230
|
for (let i = 0; i < opts.data.length; i++) {
|
|
226
231
|
const off = i * bytesPerPixel;
|
|
227
232
|
switch (opts.bitpix) {
|
|
228
|
-
case 8:
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
case
|
|
232
|
-
|
|
233
|
+
case 8:
|
|
234
|
+
new Uint8Array(dataBytes)[off] = opts.data[i];
|
|
235
|
+
break;
|
|
236
|
+
case 16:
|
|
237
|
+
dataView.setInt16(off, opts.data[i], false);
|
|
238
|
+
break;
|
|
239
|
+
case 32:
|
|
240
|
+
dataView.setInt32(off, opts.data[i], false);
|
|
241
|
+
break;
|
|
242
|
+
case -32:
|
|
243
|
+
dataView.setFloat32(off, opts.data[i], false);
|
|
244
|
+
break;
|
|
245
|
+
case -64:
|
|
246
|
+
dataView.setFloat64(off, opts.data[i], false);
|
|
247
|
+
break;
|
|
233
248
|
}
|
|
234
249
|
}
|
|
235
250
|
|
|
@@ -264,12 +279,20 @@ function getNum(headers: Map<string, string | number | boolean>, key: string): n
|
|
|
264
279
|
return v;
|
|
265
280
|
}
|
|
266
281
|
|
|
267
|
-
function getNumOr(
|
|
282
|
+
function getNumOr(
|
|
283
|
+
headers: Map<string, string | number | boolean>,
|
|
284
|
+
key: string,
|
|
285
|
+
def: number
|
|
286
|
+
): number {
|
|
268
287
|
const v = headers.get(key);
|
|
269
288
|
return typeof v === 'number' ? v : def;
|
|
270
289
|
}
|
|
271
290
|
|
|
272
|
-
function getStrOr(
|
|
291
|
+
function getStrOr(
|
|
292
|
+
headers: Map<string, string | number | boolean>,
|
|
293
|
+
key: string,
|
|
294
|
+
def: string
|
|
295
|
+
): string {
|
|
273
296
|
const v = headers.get(key);
|
|
274
297
|
return typeof v === 'string' ? v : def;
|
|
275
298
|
}
|
package/src/fits/FITSToGrid.ts
CHANGED
|
@@ -85,7 +85,8 @@ export function extractChannel(fits: FITSFile, channel: number): Float32Array {
|
|
|
85
85
|
* Useful for colormap normalization.
|
|
86
86
|
*/
|
|
87
87
|
export function fitsDataRange(fits: FITSFile): [number, number] {
|
|
88
|
-
let min = Infinity,
|
|
88
|
+
let min = Infinity,
|
|
89
|
+
max = -Infinity;
|
|
89
90
|
for (let i = 0; i < fits.data.length; i++) {
|
|
90
91
|
const v = fits.data[i];
|
|
91
92
|
if (v < min) min = v;
|
package/src/index.ts
CHANGED
|
@@ -17,7 +17,12 @@ export { PythonAstropyBridge, type AstropyResult };
|
|
|
17
17
|
// Export FITS parsing and visualization
|
|
18
18
|
export { parseFITS, buildFITS, type FITSFile, type WCSInfo } from './fits/FITSParser';
|
|
19
19
|
export { fitsToGrid3D, extractChannel, fitsDataRange } from './fits/FITSToGrid';
|
|
20
|
-
export {
|
|
20
|
+
export {
|
|
21
|
+
SpectralCubeViewer,
|
|
22
|
+
FITSViewerPanel,
|
|
23
|
+
type SpectralCubeViewerProps,
|
|
24
|
+
type FITSViewerPanelProps,
|
|
25
|
+
} from './components/SpectralCubeViewer';
|
|
21
26
|
|
|
22
27
|
/**
|
|
23
28
|
* Metadata exposing domain capabilities to the Studio / Schema Mapper.
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025-2026 HoloScript Contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interface representing the result of a radio astronomy physics calculation.
|
|
3
|
-
*/
|
|
4
|
-
export interface AstropyResult {
|
|
5
|
-
wavelength_meters?: number;
|
|
6
|
-
frequency_hz?: number;
|
|
7
|
-
flux_density_jy?: number;
|
|
8
|
-
error?: string;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Runner that bridges HoloScript to the underlying astropy Python toolkit.
|
|
12
|
-
*/
|
|
13
|
-
export declare class PythonAstropyBridge {
|
|
14
|
-
private scriptPath;
|
|
15
|
-
constructor();
|
|
16
|
-
/**
|
|
17
|
-
* Dispatches a calculation to the Python environment.
|
|
18
|
-
* @param command The astronomical command to invoke (e.g. 'calc_synchrotron')
|
|
19
|
-
* @param params JSON payload of parameters
|
|
20
|
-
* @returns A promise resolving to the astronomical result payload
|
|
21
|
-
*/
|
|
22
|
-
executeCommand(command: string, params: Record<string, any>): Promise<AstropyResult>;
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=python-runner.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"python-runner.d.ts","sourceRoot":"","sources":["../../src/bridge/python-runner.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,UAAU,CAAS;;IAM3B;;;;;OAKG;IACU,cAAc,CACzB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC1B,OAAO,CAAC,aAAa,CAAC;CA6B1B"}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
/**
|
|
4
|
-
* Runner that bridges HoloScript to the underlying astropy Python toolkit.
|
|
5
|
-
*/
|
|
6
|
-
export class PythonAstropyBridge {
|
|
7
|
-
constructor() {
|
|
8
|
-
this.scriptPath = path.resolve(__dirname, '../../python/astropy_bridge.py');
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Dispatches a calculation to the Python environment.
|
|
12
|
-
* @param command The astronomical command to invoke (e.g. 'calc_synchrotron')
|
|
13
|
-
* @param params JSON payload of parameters
|
|
14
|
-
* @returns A promise resolving to the astronomical result payload
|
|
15
|
-
*/
|
|
16
|
-
async executeCommand(command, params) {
|
|
17
|
-
return new Promise((resolve, reject) => {
|
|
18
|
-
const process = spawn('python', [this.scriptPath, command, JSON.stringify(params)]);
|
|
19
|
-
let output = '';
|
|
20
|
-
let errorOutput = '';
|
|
21
|
-
process.stdout.on('data', (data) => {
|
|
22
|
-
output += data.toString();
|
|
23
|
-
});
|
|
24
|
-
process.stderr.on('data', (data) => {
|
|
25
|
-
errorOutput += data.toString();
|
|
26
|
-
});
|
|
27
|
-
process.on('close', (code) => {
|
|
28
|
-
if (code !== 0) {
|
|
29
|
-
return reject(new Error(`Astropy bridge exited with code ${code}: ${errorOutput}`));
|
|
30
|
-
}
|
|
31
|
-
try {
|
|
32
|
-
// Attempt to parse JSON line output from python script
|
|
33
|
-
const parsed = JSON.parse(output.trim());
|
|
34
|
-
resolve(parsed);
|
|
35
|
-
}
|
|
36
|
-
catch (_e) {
|
|
37
|
-
reject(new Error(`Failed to parse bridge output: ${output}`));
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=python-runner.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"python-runner.js","sourceRoot":"","sources":["../../src/bridge/python-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAY7B;;GAEG;AACH,MAAM,OAAO,mBAAmB;IAG9B;QACE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,gCAAgC,CAAC,CAAC;IAC9E,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,cAAc,CACzB,OAAe,EACf,MAA2B;QAE3B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAEpF,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,WAAW,GAAG,EAAE,CAAC;YAErB,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBACjC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5B,CAAC,CAAC,CAAC;YAEH,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBACjC,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjC,CAAC,CAAC,CAAC;YAEH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBAC3B,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBACf,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,mCAAmC,IAAI,KAAK,WAAW,EAAE,CAAC,CAAC,CAAC;gBACtF,CAAC;gBACD,IAAI,CAAC;oBACH,uDAAuD;oBACvD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;oBACzC,OAAO,CAAC,MAAuB,CAAC,CAAC;gBACnC,CAAC;gBAAC,OAAO,EAAE,EAAE,CAAC;oBACZ,MAAM,CAAC,IAAI,KAAK,CAAC,kCAAkC,MAAM,EAAE,CAAC,CAAC,CAAC;gBAChE,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SpectralCubeViewer — Interactive 3D viewer for FITS spectral cubes.
|
|
3
|
-
*
|
|
4
|
-
* Drop a FITS file → see the spectral cube in 3D → slide through
|
|
5
|
-
* frequency channels → play as animation. Zero code required.
|
|
6
|
-
*
|
|
7
|
-
* Works with:
|
|
8
|
-
* - 3D cubes (RA × Dec × Freq): full volumetric slice-by-slice
|
|
9
|
-
* - 2D images (RA × Dec): single-channel colormap
|
|
10
|
-
* - 1D spectra: displayed as a line in 3D space
|
|
11
|
-
*/
|
|
12
|
-
export type ColormapName = 'jet' | 'viridis' | 'turbo' | 'inferno' | 'coolwarm';
|
|
13
|
-
export interface SpectralCubeViewerProps {
|
|
14
|
-
/** Parsed FITS data array (physical values after BSCALE/BZERO) */
|
|
15
|
-
data: Float32Array;
|
|
16
|
-
/** Axis dimensions [NAXIS1, NAXIS2] or [NAXIS1, NAXIS2, NAXIS3] */
|
|
17
|
-
shape: number[];
|
|
18
|
-
/** Colormap (default: 'viridis') */
|
|
19
|
-
colormap?: ColormapName;
|
|
20
|
-
/** Auto-play through channels (default: false) */
|
|
21
|
-
autoPlay?: boolean;
|
|
22
|
-
/** Playback speed in channels per second (default: 5) */
|
|
23
|
-
playSpeed?: number;
|
|
24
|
-
/** WCS metadata for axis labels */
|
|
25
|
-
wcs?: {
|
|
26
|
-
ctype?: string[];
|
|
27
|
-
cunit?: string[];
|
|
28
|
-
crval?: number[];
|
|
29
|
-
cdelt?: number[];
|
|
30
|
-
};
|
|
31
|
-
/** Object name from FITS header */
|
|
32
|
-
objectName?: string;
|
|
33
|
-
}
|
|
34
|
-
export declare function SpectralCubeViewer({ data, shape, colormap, autoPlay, playSpeed, wcs, objectName, }: SpectralCubeViewerProps): import("react/jsx-runtime").JSX.Element;
|
|
35
|
-
export interface FITSViewerPanelProps {
|
|
36
|
-
/** Raw FITS ArrayBuffer (from file drop) */
|
|
37
|
-
fitsBuffer: ArrayBuffer;
|
|
38
|
-
onClose?: () => void;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Full FITS viewer panel: parses FITS → shows 3D → channel slider.
|
|
42
|
-
* This is the entry point for drag-and-drop FITS files.
|
|
43
|
-
*/
|
|
44
|
-
export declare function FITSViewerPanel({ fitsBuffer, onClose }: FITSViewerPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
45
|
-
//# sourceMappingURL=SpectralCubeViewer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SpectralCubeViewer.d.ts","sourceRoot":"","sources":["../../src/components/SpectralCubeViewer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;AAEhF,MAAM,WAAW,uBAAuB;IACtC,kEAAkE;IAClE,IAAI,EAAE,YAAY,CAAC;IACnB,mEAAmE;IACnE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,GAAG,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACjF,mCAAmC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA4DD,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,KAAK,EACL,QAAoB,EACpB,QAAgB,EAChB,SAAa,EACb,GAAG,EACH,UAAU,GACX,EAAE,uBAAuB,2CAsFzB;AAID,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,UAAU,EAAE,WAAW,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,oBAAoB,2CAiG5E"}
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* SpectralCubeViewer — Interactive 3D viewer for FITS spectral cubes.
|
|
4
|
-
*
|
|
5
|
-
* Drop a FITS file → see the spectral cube in 3D → slide through
|
|
6
|
-
* frequency channels → play as animation. Zero code required.
|
|
7
|
-
*
|
|
8
|
-
* Works with:
|
|
9
|
-
* - 3D cubes (RA × Dec × Freq): full volumetric slice-by-slice
|
|
10
|
-
* - 2D images (RA × Dec): single-channel colormap
|
|
11
|
-
* - 1D spectra: displayed as a line in 3D space
|
|
12
|
-
*/
|
|
13
|
-
import { useState, useMemo, useRef, useEffect } from 'react';
|
|
14
|
-
import { useFrame } from '@react-three/fiber';
|
|
15
|
-
import * as THREE from 'three';
|
|
16
|
-
// ── Colormap GLSL ────────────────────────────────────────────────────────────
|
|
17
|
-
const COLORMAPS = {
|
|
18
|
-
viridis: `
|
|
19
|
-
vec3 colormap(float t) {
|
|
20
|
-
vec3 c0 = vec3(0.267, 0.004, 0.329);
|
|
21
|
-
vec3 c4 = vec3(0.127, 0.566, 0.551);
|
|
22
|
-
vec3 c8 = vec3(0.993, 0.906, 0.144);
|
|
23
|
-
if (t < 0.5) return mix(c0, c4, t * 2.0);
|
|
24
|
-
return mix(c4, c8, (t - 0.5) * 2.0);
|
|
25
|
-
}
|
|
26
|
-
`,
|
|
27
|
-
turbo: `
|
|
28
|
-
vec3 colormap(float t) {
|
|
29
|
-
float r = 0.136 + t * (4.615 + t * (-42.66 + t * (132.13 + t * (-152.55 + t * 56.31))));
|
|
30
|
-
float g = 0.091 + t * (2.264 + t * (-14.02 + t * (32.21 + t * (-29.27 + t * 10.16))));
|
|
31
|
-
float b = 0.107 + t * (12.75 + t * (-60.58 + t * (132.75 + t * (-134.01 + t * 50.26))));
|
|
32
|
-
return clamp(vec3(r, g, b), 0.0, 1.0);
|
|
33
|
-
}
|
|
34
|
-
`,
|
|
35
|
-
inferno: `
|
|
36
|
-
vec3 colormap(float t) {
|
|
37
|
-
vec3 c0 = vec3(0.001, 0.0, 0.014);
|
|
38
|
-
vec3 c3 = vec3(0.735, 0.216, 0.329);
|
|
39
|
-
vec3 c6 = vec3(0.988, 0.999, 0.644);
|
|
40
|
-
if (t < 0.5) return mix(c0, c3, t * 2.0);
|
|
41
|
-
return mix(c3, c6, (t - 0.5) * 2.0);
|
|
42
|
-
}
|
|
43
|
-
`,
|
|
44
|
-
};
|
|
45
|
-
const VERT = /* glsl */ `
|
|
46
|
-
attribute float aIntensity;
|
|
47
|
-
uniform float uMin;
|
|
48
|
-
uniform float uMax;
|
|
49
|
-
varying float vNorm;
|
|
50
|
-
|
|
51
|
-
void main() {
|
|
52
|
-
float range = uMax - uMin;
|
|
53
|
-
vNorm = range > 0.0 ? clamp((aIntensity - uMin) / range, 0.0, 1.0) : 0.5;
|
|
54
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
55
|
-
}
|
|
56
|
-
`;
|
|
57
|
-
function makeFrag(cmName) {
|
|
58
|
-
const cm = COLORMAPS[cmName] ?? COLORMAPS.viridis;
|
|
59
|
-
return /* glsl */ `
|
|
60
|
-
varying float vNorm;
|
|
61
|
-
${cm}
|
|
62
|
-
void main() {
|
|
63
|
-
vec3 c = colormap(vNorm);
|
|
64
|
-
gl_FragColor = vec4(c, 1.0);
|
|
65
|
-
}
|
|
66
|
-
`;
|
|
67
|
-
}
|
|
68
|
-
// ── Component ────────────────────────────────────────────────────────────────
|
|
69
|
-
export function SpectralCubeViewer({ data, shape, colormap = 'viridis', autoPlay = false, playSpeed = 5, wcs, objectName, }) {
|
|
70
|
-
const nx = shape[0] ?? 1;
|
|
71
|
-
const ny = shape[1] ?? 1;
|
|
72
|
-
const nz = shape[2] ?? 1;
|
|
73
|
-
const is3D = shape.length >= 3 && nz > 1;
|
|
74
|
-
const [channel, setChannel] = useState(0);
|
|
75
|
-
const [playing, setPlaying] = useState(autoPlay);
|
|
76
|
-
const meshRef = useRef(null);
|
|
77
|
-
const timeRef = useRef(0);
|
|
78
|
-
// Extract channel slice
|
|
79
|
-
const channelData = useMemo(() => {
|
|
80
|
-
if (!is3D)
|
|
81
|
-
return data; // 2D — use entire dataset
|
|
82
|
-
const offset = channel * nx * ny;
|
|
83
|
-
return data.slice(offset, offset + nx * ny);
|
|
84
|
-
}, [data, channel, nx, ny, is3D]);
|
|
85
|
-
// Data range for colormap normalization
|
|
86
|
-
const [min, max] = useMemo(() => {
|
|
87
|
-
let lo = Infinity, hi = -Infinity;
|
|
88
|
-
for (let i = 0; i < channelData.length; i++) {
|
|
89
|
-
if (channelData[i] < lo)
|
|
90
|
-
lo = channelData[i];
|
|
91
|
-
if (channelData[i] > hi)
|
|
92
|
-
hi = channelData[i];
|
|
93
|
-
}
|
|
94
|
-
return [lo, hi];
|
|
95
|
-
}, [channelData]);
|
|
96
|
-
// Build geometry: flat plane with per-pixel intensity attribute
|
|
97
|
-
const geometry = useMemo(() => {
|
|
98
|
-
const geo = new THREE.PlaneGeometry(nx / Math.max(nx, ny), ny / Math.max(nx, ny), nx - 1, ny - 1);
|
|
99
|
-
const intensities = new Float32Array(nx * ny);
|
|
100
|
-
for (let j = 0; j < ny; j++) {
|
|
101
|
-
for (let i = 0; i < nx; i++) {
|
|
102
|
-
// PlaneGeometry vertex order: row by row, top to bottom
|
|
103
|
-
intensities[j * nx + i] = channelData[j * nx + i] ?? 0;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
geo.setAttribute('aIntensity', new THREE.BufferAttribute(intensities, 1));
|
|
107
|
-
return geo;
|
|
108
|
-
}, [nx, ny, channelData]);
|
|
109
|
-
// Auto-play animation
|
|
110
|
-
useFrame((_, delta) => {
|
|
111
|
-
if (!playing || !is3D)
|
|
112
|
-
return;
|
|
113
|
-
timeRef.current += delta * playSpeed;
|
|
114
|
-
if (timeRef.current >= 1) {
|
|
115
|
-
timeRef.current -= 1;
|
|
116
|
-
setChannel((c) => (c + 1) % nz);
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
const fragmentShader = useMemo(() => makeFrag(colormap), [colormap]);
|
|
120
|
-
const uniforms = useMemo(() => ({
|
|
121
|
-
uMin: { value: min },
|
|
122
|
-
uMax: { value: max },
|
|
123
|
-
}), [min, max]);
|
|
124
|
-
// Channel label from WCS
|
|
125
|
-
const channelLabel = useMemo(() => {
|
|
126
|
-
if (!wcs?.crval || !wcs?.cdelt || !wcs?.ctype)
|
|
127
|
-
return `Channel ${channel}/${nz}`;
|
|
128
|
-
const freqIdx = wcs.ctype.findIndex((t) => t.includes('FREQ'));
|
|
129
|
-
if (freqIdx < 0)
|
|
130
|
-
return `Channel ${channel}/${nz}`;
|
|
131
|
-
const freq = wcs.crval[freqIdx] + channel * wcs.cdelt[freqIdx];
|
|
132
|
-
const unit = wcs.cunit?.[freqIdx] ?? 'Hz';
|
|
133
|
-
if (freq >= 1e9)
|
|
134
|
-
return `${(freq / 1e9).toFixed(3)} GHz`;
|
|
135
|
-
if (freq >= 1e6)
|
|
136
|
-
return `${(freq / 1e6).toFixed(3)} MHz`;
|
|
137
|
-
return `${freq.toFixed(0)} ${unit}`;
|
|
138
|
-
}, [channel, nz, wcs]);
|
|
139
|
-
return (_jsx("group", { children: _jsx("mesh", { ref: meshRef, geometry: geometry, children: _jsx("shaderMaterial", { vertexShader: VERT, fragmentShader: fragmentShader, uniforms: uniforms, side: THREE.DoubleSide }) }) }));
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Full FITS viewer panel: parses FITS → shows 3D → channel slider.
|
|
143
|
-
* This is the entry point for drag-and-drop FITS files.
|
|
144
|
-
*/
|
|
145
|
-
export function FITSViewerPanel({ fitsBuffer, onClose }) {
|
|
146
|
-
const [fitsData, setFitsData] = useState(null);
|
|
147
|
-
const [channel, setChannel] = useState(0);
|
|
148
|
-
const [playing, setPlaying] = useState(false);
|
|
149
|
-
const [error, setError] = useState(null);
|
|
150
|
-
useEffect(() => {
|
|
151
|
-
try {
|
|
152
|
-
// Dynamic import to avoid bundling FITS parser unless needed
|
|
153
|
-
import('../fits/FITSParser').then(({ parseFITS }) => {
|
|
154
|
-
const fits = parseFITS(fitsBuffer);
|
|
155
|
-
setFitsData({
|
|
156
|
-
data: fits.data,
|
|
157
|
-
shape: fits.shape,
|
|
158
|
-
wcs: fits.wcs,
|
|
159
|
-
object: fits.object || 'Unknown Object',
|
|
160
|
-
});
|
|
161
|
-
}).catch((e) => setError(String(e)));
|
|
162
|
-
}
|
|
163
|
-
catch (e) {
|
|
164
|
-
setError(String(e));
|
|
165
|
-
}
|
|
166
|
-
}, [fitsBuffer]);
|
|
167
|
-
if (error) {
|
|
168
|
-
return (_jsxs("div", { style: { padding: 20, color: '#ef4444', fontFamily: 'monospace' }, children: ["FITS Parse Error: ", error] }));
|
|
169
|
-
}
|
|
170
|
-
if (!fitsData) {
|
|
171
|
-
return (_jsx("div", { style: { padding: 20, color: '#94a3b8', fontFamily: 'monospace' }, children: "Loading FITS data..." }));
|
|
172
|
-
}
|
|
173
|
-
const nz = fitsData.shape[2] ?? 1;
|
|
174
|
-
const is3D = fitsData.shape.length >= 3 && nz > 1;
|
|
175
|
-
return (_jsxs("div", { style: {
|
|
176
|
-
display: 'flex', flexDirection: 'column', gap: 8,
|
|
177
|
-
padding: 12, background: '#1a1a2e', borderRadius: 8,
|
|
178
|
-
border: '1px solid #2a2a3e', color: '#e4e4e7',
|
|
179
|
-
fontFamily: "'Space Mono', monospace",
|
|
180
|
-
}, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' }, children: [_jsx("span", { style: { fontSize: 13, fontWeight: 700, color: '#a78bfa' }, children: fitsData.object }), _jsxs("span", { style: { fontSize: 10, color: '#71717a' }, children: [fitsData.shape.join(' × '), " px"] })] }), is3D && (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx("button", { onClick: () => setPlaying(!playing), style: {
|
|
181
|
-
background: playing ? '#ef4444' : '#3b82f6',
|
|
182
|
-
border: 'none', borderRadius: 4, padding: '4px 10px',
|
|
183
|
-
color: 'white', fontSize: 11, cursor: 'pointer',
|
|
184
|
-
}, children: playing ? 'Stop' : 'Play' }), _jsx("input", { type: "range", min: 0, max: nz - 1, value: channel, onChange: (e) => { setChannel(Number(e.target.value)); setPlaying(false); }, style: { flex: 1 } }), _jsxs("span", { style: { fontSize: 10, color: '#71717a', minWidth: 80, textAlign: 'right' }, children: ["Ch ", channel, "/", nz - 1] })] })), _jsxs("div", { style: { fontSize: 10, color: '#71717a' }, children: ["Range: ", dataRange(fitsData.data).map((v) => v.toExponential(2)).join(' → ')] })] }));
|
|
185
|
-
}
|
|
186
|
-
function dataRange(data) {
|
|
187
|
-
let min = Infinity, max = -Infinity;
|
|
188
|
-
for (let i = 0; i < data.length; i++) {
|
|
189
|
-
if (data[i] < min)
|
|
190
|
-
min = data[i];
|
|
191
|
-
if (data[i] > max)
|
|
192
|
-
max = data[i];
|
|
193
|
-
}
|
|
194
|
-
return [min, max];
|
|
195
|
-
}
|
|
196
|
-
//# sourceMappingURL=SpectralCubeViewer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SpectralCubeViewer.js","sourceRoot":"","sources":["../../src/components/SpectralCubeViewer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Specific traits representing properties for Radio Astrophysics.
|
|
3
|
-
*/
|
|
4
|
-
export declare const RADIO_ASTRONOMY_TRAITS: readonly ["radio_emitter", "synchrotron", "interferometer", "em_wave", "pulsar_timing", "spectral_line"];
|
|
5
|
-
export type RadioAstronomyTraitName = (typeof RADIO_ASTRONOMY_TRAITS)[number];
|
|
6
|
-
//# sourceMappingURL=astronomy-traits.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"astronomy-traits.d.ts","sourceRoot":"","sources":["../../src/constants/astronomy-traits.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,sBAAsB,0GAOzB,CAAC;AAEX,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Specific traits representing properties for Radio Astrophysics.
|
|
3
|
-
*/
|
|
4
|
-
export const RADIO_ASTRONOMY_TRAITS = [
|
|
5
|
-
'radio_emitter', // Signals a 3D construct as an origin point for specific radio wavelengths
|
|
6
|
-
'synchrotron', // Determines emission behavior via magnetic fields and relativistic electrons
|
|
7
|
-
'interferometer', // Marks a multi-nodal virtual sensor
|
|
8
|
-
'em_wave', // Represents an electromagnetic wave primitive
|
|
9
|
-
'pulsar_timing', // Represents pulsar timing array signals
|
|
10
|
-
'spectral_line', // Maps to particular spectral line signals (e.g., 21cm HI line)
|
|
11
|
-
];
|
|
12
|
-
//# sourceMappingURL=astronomy-traits.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"astronomy-traits.js","sourceRoot":"","sources":["../../src/constants/astronomy-traits.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,eAAe,EAAE,2EAA2E;IAC5F,aAAa,EAAE,8EAA8E;IAC7F,gBAAgB,EAAE,qCAAqC;IACvD,SAAS,EAAE,+CAA+C;IAC1D,eAAe,EAAE,yCAAyC;IAC1D,eAAe,EAAE,gEAAgE;CACzE,CAAC"}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FITSParser — Pure JavaScript parser for FITS (Flexible Image Transport System) files.
|
|
3
|
-
*
|
|
4
|
-
* FITS is the standard data format in astronomy. Structure:
|
|
5
|
-
* - Header: 2880-byte blocks of 80-character ASCII "cards" (key=value pairs)
|
|
6
|
-
* - Data: big-endian binary arrays, padded to 2880-byte boundary
|
|
7
|
-
* - Extensions: additional HDUs (Header Data Units) with same structure
|
|
8
|
-
*
|
|
9
|
-
* Supports: BITPIX 8 (uint8), 16 (int16), 32 (int32), -32 (float32), -64 (float64)
|
|
10
|
-
* Handles: BSCALE/BZERO physical value scaling, WCS coordinate metadata
|
|
11
|
-
*
|
|
12
|
-
* @see https://fits.gsfc.nasa.gov/fits_standard.html
|
|
13
|
-
*/
|
|
14
|
-
export interface WCSInfo {
|
|
15
|
-
/** Reference pixel (1-indexed, per FITS convention) */
|
|
16
|
-
crpix: number[];
|
|
17
|
-
/** Reference value (world coordinate at reference pixel) */
|
|
18
|
-
crval: number[];
|
|
19
|
-
/** Pixel scale (coordinate increment per pixel) */
|
|
20
|
-
cdelt: number[];
|
|
21
|
-
/** Axis types (e.g., 'RA---TAN', 'DEC--TAN', 'FREQ') */
|
|
22
|
-
ctype: string[];
|
|
23
|
-
/** Axis units */
|
|
24
|
-
cunit: string[];
|
|
25
|
-
}
|
|
26
|
-
export interface FITSFile {
|
|
27
|
-
/** All header cards as key→value */
|
|
28
|
-
headers: Map<string, string | number | boolean>;
|
|
29
|
-
/** Data array (physical values after BSCALE/BZERO) */
|
|
30
|
-
data: Float32Array;
|
|
31
|
-
/** Axis dimensions [NAXIS1, NAXIS2, ...] */
|
|
32
|
-
shape: number[];
|
|
33
|
-
/** World Coordinate System info (if present) */
|
|
34
|
-
wcs: WCSInfo | null;
|
|
35
|
-
/** BITPIX from header */
|
|
36
|
-
bitpix: number;
|
|
37
|
-
/** Object name (OBJECT card) */
|
|
38
|
-
object: string;
|
|
39
|
-
/** Telescope name (TELESCOP card) */
|
|
40
|
-
telescope: string;
|
|
41
|
-
/** Observation date (DATE-OBS card) */
|
|
42
|
-
dateObs: string;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Parse a FITS file from an ArrayBuffer.
|
|
46
|
-
* Returns the primary HDU (first header + data unit).
|
|
47
|
-
*/
|
|
48
|
-
export declare function parseFITS(buffer: ArrayBuffer): FITSFile;
|
|
49
|
-
/**
|
|
50
|
-
* Build a minimal FITS file as ArrayBuffer (for testing).
|
|
51
|
-
*/
|
|
52
|
-
export declare function buildFITS(opts: {
|
|
53
|
-
bitpix: number;
|
|
54
|
-
shape: number[];
|
|
55
|
-
data: number[];
|
|
56
|
-
bscale?: number;
|
|
57
|
-
bzero?: number;
|
|
58
|
-
headers?: Record<string, string | number>;
|
|
59
|
-
}): ArrayBuffer;
|
|
60
|
-
//# sourceMappingURL=FITSParser.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FITSParser.d.ts","sourceRoot":"","sources":["../../src/fits/FITSParser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,MAAM,WAAW,OAAO;IACtB,uDAAuD;IACvD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4DAA4D;IAC5D,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,mDAAmD;IACnD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,wDAAwD;IACxD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,iBAAiB;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,oCAAoC;IACpC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAChD,sDAAsD;IACtD,IAAI,EAAE,YAAY,CAAC;IACnB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,gDAAgD;IAChD,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IACpB,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;CACjB;AAUD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,QAAQ,CA+GvD;AAID;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CAC3C,GAAG,WAAW,CAuDd"}
|
package/dist/fits/FITSParser.js
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FITSParser — Pure JavaScript parser for FITS (Flexible Image Transport System) files.
|
|
3
|
-
*
|
|
4
|
-
* FITS is the standard data format in astronomy. Structure:
|
|
5
|
-
* - Header: 2880-byte blocks of 80-character ASCII "cards" (key=value pairs)
|
|
6
|
-
* - Data: big-endian binary arrays, padded to 2880-byte boundary
|
|
7
|
-
* - Extensions: additional HDUs (Header Data Units) with same structure
|
|
8
|
-
*
|
|
9
|
-
* Supports: BITPIX 8 (uint8), 16 (int16), 32 (int32), -32 (float32), -64 (float64)
|
|
10
|
-
* Handles: BSCALE/BZERO physical value scaling, WCS coordinate metadata
|
|
11
|
-
*
|
|
12
|
-
* @see https://fits.gsfc.nasa.gov/fits_standard.html
|
|
13
|
-
*/
|
|
14
|
-
// ── Constants ────────────────────────────────────────────────────────────────
|
|
15
|
-
const BLOCK_SIZE = 2880;
|
|
16
|
-
const CARD_SIZE = 80;
|
|
17
|
-
const CARDS_PER_BLOCK = BLOCK_SIZE / CARD_SIZE; // 36
|
|
18
|
-
// ── Parser ───────────────────────────────────────────────────────────────────
|
|
19
|
-
/**
|
|
20
|
-
* Parse a FITS file from an ArrayBuffer.
|
|
21
|
-
* Returns the primary HDU (first header + data unit).
|
|
22
|
-
*/
|
|
23
|
-
export function parseFITS(buffer) {
|
|
24
|
-
const bytes = new Uint8Array(buffer);
|
|
25
|
-
const view = new DataView(buffer);
|
|
26
|
-
// ── Parse Header ─────────────────────────────────────────────────
|
|
27
|
-
const headers = new Map();
|
|
28
|
-
let headerEnd = 0;
|
|
29
|
-
outer: for (let block = 0; block * BLOCK_SIZE < buffer.byteLength; block++) {
|
|
30
|
-
for (let card = 0; card < CARDS_PER_BLOCK; card++) {
|
|
31
|
-
const offset = block * BLOCK_SIZE + card * CARD_SIZE;
|
|
32
|
-
if (offset + CARD_SIZE > buffer.byteLength)
|
|
33
|
-
break outer;
|
|
34
|
-
const cardStr = decodeASCII(bytes, offset, CARD_SIZE);
|
|
35
|
-
const keyword = cardStr.substring(0, 8).trim();
|
|
36
|
-
if (keyword === 'END') {
|
|
37
|
-
headerEnd = (block + 1) * BLOCK_SIZE; // data starts at next block boundary
|
|
38
|
-
break outer;
|
|
39
|
-
}
|
|
40
|
-
if (cardStr[8] === '=' && cardStr[9] === ' ') {
|
|
41
|
-
const valueStr = cardStr.substring(10).split('/')[0].trim();
|
|
42
|
-
headers.set(keyword, parseCardValue(valueStr));
|
|
43
|
-
}
|
|
44
|
-
else if (keyword === 'COMMENT' || keyword === 'HISTORY') {
|
|
45
|
-
// Skip comment/history cards
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
if (headerEnd === 0) {
|
|
50
|
-
throw new Error('FITS: No END card found in header');
|
|
51
|
-
}
|
|
52
|
-
// ── Extract Critical Keywords ────────────────────────────────────
|
|
53
|
-
const bitpix = getNum(headers, 'BITPIX');
|
|
54
|
-
const naxis = getNum(headers, 'NAXIS');
|
|
55
|
-
const shape = [];
|
|
56
|
-
for (let i = 1; i <= naxis; i++) {
|
|
57
|
-
shape.push(getNum(headers, `NAXIS${i}`));
|
|
58
|
-
}
|
|
59
|
-
const bscale = getNumOr(headers, 'BSCALE', 1.0);
|
|
60
|
-
const bzero = getNumOr(headers, 'BZERO', 0.0);
|
|
61
|
-
// ── Parse Data ───────────────────────────────────────────────────
|
|
62
|
-
const totalPixels = shape.reduce((a, b) => a * b, 1);
|
|
63
|
-
const bytesPerPixel = Math.abs(bitpix) / 8;
|
|
64
|
-
const dataOffset = headerEnd;
|
|
65
|
-
if (dataOffset + totalPixels * bytesPerPixel > buffer.byteLength) {
|
|
66
|
-
throw new Error(`FITS: Data section extends beyond buffer (need ${dataOffset + totalPixels * bytesPerPixel}, have ${buffer.byteLength})`);
|
|
67
|
-
}
|
|
68
|
-
const data = new Float32Array(totalPixels);
|
|
69
|
-
for (let i = 0; i < totalPixels; i++) {
|
|
70
|
-
const off = dataOffset + i * bytesPerPixel;
|
|
71
|
-
let raw;
|
|
72
|
-
switch (bitpix) {
|
|
73
|
-
case 8:
|
|
74
|
-
raw = bytes[off];
|
|
75
|
-
break;
|
|
76
|
-
case 16:
|
|
77
|
-
raw = view.getInt16(off, false); // big-endian
|
|
78
|
-
break;
|
|
79
|
-
case 32:
|
|
80
|
-
raw = view.getInt32(off, false);
|
|
81
|
-
break;
|
|
82
|
-
case -32:
|
|
83
|
-
raw = view.getFloat32(off, false);
|
|
84
|
-
break;
|
|
85
|
-
case -64:
|
|
86
|
-
raw = view.getFloat64(off, false);
|
|
87
|
-
break;
|
|
88
|
-
default:
|
|
89
|
-
throw new Error(`FITS: Unsupported BITPIX ${bitpix}`);
|
|
90
|
-
}
|
|
91
|
-
// Apply physical value transformation
|
|
92
|
-
data[i] = bscale * raw + bzero;
|
|
93
|
-
}
|
|
94
|
-
// ── Extract WCS ──────────────────────────────────────────────────
|
|
95
|
-
let wcs = null;
|
|
96
|
-
if (headers.has('CRVAL1')) {
|
|
97
|
-
wcs = {
|
|
98
|
-
crpix: [], crval: [], cdelt: [], ctype: [], cunit: [],
|
|
99
|
-
};
|
|
100
|
-
for (let i = 1; i <= naxis; i++) {
|
|
101
|
-
wcs.crpix.push(getNumOr(headers, `CRPIX${i}`, 1));
|
|
102
|
-
wcs.crval.push(getNumOr(headers, `CRVAL${i}`, 0));
|
|
103
|
-
wcs.cdelt.push(getNumOr(headers, `CDELT${i}`, 1));
|
|
104
|
-
wcs.ctype.push(getStrOr(headers, `CTYPE${i}`, ''));
|
|
105
|
-
wcs.cunit.push(getStrOr(headers, `CUNIT${i}`, ''));
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return {
|
|
109
|
-
headers,
|
|
110
|
-
data,
|
|
111
|
-
shape,
|
|
112
|
-
wcs,
|
|
113
|
-
bitpix,
|
|
114
|
-
object: getStrOr(headers, 'OBJECT', ''),
|
|
115
|
-
telescope: getStrOr(headers, 'TELESCOP', ''),
|
|
116
|
-
dateObs: getStrOr(headers, 'DATE-OBS', ''),
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
// ── FITS Builder (for tests) ─────────────────────────────────────────────────
|
|
120
|
-
/**
|
|
121
|
-
* Build a minimal FITS file as ArrayBuffer (for testing).
|
|
122
|
-
*/
|
|
123
|
-
export function buildFITS(opts) {
|
|
124
|
-
const cards = [];
|
|
125
|
-
cards.push(fmtCard('SIMPLE', true));
|
|
126
|
-
cards.push(fmtCard('BITPIX', opts.bitpix));
|
|
127
|
-
cards.push(fmtCard('NAXIS', opts.shape.length));
|
|
128
|
-
for (let i = 0; i < opts.shape.length; i++) {
|
|
129
|
-
cards.push(fmtCard(`NAXIS${i + 1}`, opts.shape[i]));
|
|
130
|
-
}
|
|
131
|
-
if (opts.bscale !== undefined)
|
|
132
|
-
cards.push(fmtCard('BSCALE', opts.bscale));
|
|
133
|
-
if (opts.bzero !== undefined)
|
|
134
|
-
cards.push(fmtCard('BZERO', opts.bzero));
|
|
135
|
-
if (opts.headers) {
|
|
136
|
-
for (const [key, val] of Object.entries(opts.headers)) {
|
|
137
|
-
cards.push(fmtCard(key, val));
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
cards.push('END'.padEnd(CARD_SIZE));
|
|
141
|
-
// Pad header to block boundary
|
|
142
|
-
while (cards.length % CARDS_PER_BLOCK !== 0) {
|
|
143
|
-
cards.push(' '.repeat(CARD_SIZE));
|
|
144
|
-
}
|
|
145
|
-
const headerBytes = new Uint8Array(cards.length * CARD_SIZE);
|
|
146
|
-
for (let i = 0; i < cards.length; i++) {
|
|
147
|
-
for (let j = 0; j < CARD_SIZE; j++) {
|
|
148
|
-
headerBytes[i * CARD_SIZE + j] = cards[i].charCodeAt(j);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
// Write data
|
|
152
|
-
const bytesPerPixel = Math.abs(opts.bitpix) / 8;
|
|
153
|
-
const dataSize = opts.data.length * bytesPerPixel;
|
|
154
|
-
const paddedDataSize = Math.ceil(dataSize / BLOCK_SIZE) * BLOCK_SIZE;
|
|
155
|
-
const dataBytes = new ArrayBuffer(paddedDataSize);
|
|
156
|
-
const dataView = new DataView(dataBytes);
|
|
157
|
-
for (let i = 0; i < opts.data.length; i++) {
|
|
158
|
-
const off = i * bytesPerPixel;
|
|
159
|
-
switch (opts.bitpix) {
|
|
160
|
-
case 8:
|
|
161
|
-
new Uint8Array(dataBytes)[off] = opts.data[i];
|
|
162
|
-
break;
|
|
163
|
-
case 16:
|
|
164
|
-
dataView.setInt16(off, opts.data[i], false);
|
|
165
|
-
break;
|
|
166
|
-
case 32:
|
|
167
|
-
dataView.setInt32(off, opts.data[i], false);
|
|
168
|
-
break;
|
|
169
|
-
case -32:
|
|
170
|
-
dataView.setFloat32(off, opts.data[i], false);
|
|
171
|
-
break;
|
|
172
|
-
case -64:
|
|
173
|
-
dataView.setFloat64(off, opts.data[i], false);
|
|
174
|
-
break;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
// Combine
|
|
178
|
-
const result = new Uint8Array(headerBytes.length + paddedDataSize);
|
|
179
|
-
result.set(headerBytes);
|
|
180
|
-
result.set(new Uint8Array(dataBytes), headerBytes.length);
|
|
181
|
-
return result.buffer;
|
|
182
|
-
}
|
|
183
|
-
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
184
|
-
function decodeASCII(bytes, offset, length) {
|
|
185
|
-
let s = '';
|
|
186
|
-
for (let i = 0; i < length; i++) {
|
|
187
|
-
s += String.fromCharCode(bytes[offset + i]);
|
|
188
|
-
}
|
|
189
|
-
return s;
|
|
190
|
-
}
|
|
191
|
-
function parseCardValue(s) {
|
|
192
|
-
if (s === 'T')
|
|
193
|
-
return true;
|
|
194
|
-
if (s === 'F')
|
|
195
|
-
return false;
|
|
196
|
-
if (s.startsWith("'"))
|
|
197
|
-
return s.replace(/^'|'$/g, '').trim();
|
|
198
|
-
const n = Number(s);
|
|
199
|
-
return Number.isNaN(n) ? s : n;
|
|
200
|
-
}
|
|
201
|
-
function getNum(headers, key) {
|
|
202
|
-
const v = headers.get(key);
|
|
203
|
-
if (typeof v !== 'number')
|
|
204
|
-
throw new Error(`FITS: Missing or non-numeric header ${key}`);
|
|
205
|
-
return v;
|
|
206
|
-
}
|
|
207
|
-
function getNumOr(headers, key, def) {
|
|
208
|
-
const v = headers.get(key);
|
|
209
|
-
return typeof v === 'number' ? v : def;
|
|
210
|
-
}
|
|
211
|
-
function getStrOr(headers, key, def) {
|
|
212
|
-
const v = headers.get(key);
|
|
213
|
-
return typeof v === 'string' ? v : def;
|
|
214
|
-
}
|
|
215
|
-
function fmtCard(keyword, value) {
|
|
216
|
-
const kw = keyword.padEnd(8);
|
|
217
|
-
let valStr;
|
|
218
|
-
if (typeof value === 'boolean') {
|
|
219
|
-
valStr = value ? 'T' : 'F';
|
|
220
|
-
valStr = valStr.padStart(20);
|
|
221
|
-
}
|
|
222
|
-
else if (typeof value === 'number') {
|
|
223
|
-
valStr = String(value).padStart(20);
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
valStr = `'${value}'`.padEnd(20);
|
|
227
|
-
}
|
|
228
|
-
return `${kw}= ${valStr}`.padEnd(CARD_SIZE);
|
|
229
|
-
}
|
|
230
|
-
//# sourceMappingURL=FITSParser.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FITSParser.js","sourceRoot":"","sources":["../../src/fits/FITSParser.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FITSToGrid — Convert parsed FITS data to HoloScript grid structures.
|
|
3
|
-
*
|
|
4
|
-
* Maps FITS spectral cubes (RA × Dec × Freq) and 2D images to
|
|
5
|
-
* RegularGrid3D for visualization via ScalarFieldOverlay or SimResultsMesh.
|
|
6
|
-
*/
|
|
7
|
-
import { RegularGrid3D } from '@holoscript/engine/simulation';
|
|
8
|
-
import type { FITSFile } from './FITSParser';
|
|
9
|
-
/**
|
|
10
|
-
* Convert a parsed FITS file to a RegularGrid3D.
|
|
11
|
-
*
|
|
12
|
-
* - 3D cubes (NAXIS=3): maps directly to grid
|
|
13
|
-
* - 2D images (NAXIS=2): creates a 1-deep grid (nx × ny × 1)
|
|
14
|
-
* - 1D spectra (NAXIS=1): creates a 1×1×n grid
|
|
15
|
-
*/
|
|
16
|
-
export declare function fitsToGrid3D(fits: FITSFile): RegularGrid3D;
|
|
17
|
-
/**
|
|
18
|
-
* Extract a single frequency channel (z-slice) from a 3D FITS cube.
|
|
19
|
-
* Returns a 2D Float32Array (nx × ny) for use as a ScalarFieldOverlay.
|
|
20
|
-
*/
|
|
21
|
-
export declare function extractChannel(fits: FITSFile, channel: number): Float32Array;
|
|
22
|
-
/**
|
|
23
|
-
* Get data range (min/max) for the FITS data.
|
|
24
|
-
* Useful for colormap normalization.
|
|
25
|
-
*/
|
|
26
|
-
export declare function fitsDataRange(fits: FITSFile): [number, number];
|
|
27
|
-
//# sourceMappingURL=FITSToGrid.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FITSToGrid.d.ts","sourceRoot":"","sources":["../../src/fits/FITSToGrid.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,aAAa,CAmC1D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CAsB5E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ9D"}
|
package/dist/fits/FITSToGrid.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FITSToGrid — Convert parsed FITS data to HoloScript grid structures.
|
|
3
|
-
*
|
|
4
|
-
* Maps FITS spectral cubes (RA × Dec × Freq) and 2D images to
|
|
5
|
-
* RegularGrid3D for visualization via ScalarFieldOverlay or SimResultsMesh.
|
|
6
|
-
*/
|
|
7
|
-
import { RegularGrid3D } from '@holoscript/engine/simulation';
|
|
8
|
-
/**
|
|
9
|
-
* Convert a parsed FITS file to a RegularGrid3D.
|
|
10
|
-
*
|
|
11
|
-
* - 3D cubes (NAXIS=3): maps directly to grid
|
|
12
|
-
* - 2D images (NAXIS=2): creates a 1-deep grid (nx × ny × 1)
|
|
13
|
-
* - 1D spectra (NAXIS=1): creates a 1×1×n grid
|
|
14
|
-
*/
|
|
15
|
-
export function fitsToGrid3D(fits) {
|
|
16
|
-
const shape = fits.shape;
|
|
17
|
-
let nx, ny, nz;
|
|
18
|
-
if (shape.length >= 3) {
|
|
19
|
-
nx = shape[0];
|
|
20
|
-
ny = shape[1];
|
|
21
|
-
nz = shape[2];
|
|
22
|
-
}
|
|
23
|
-
else if (shape.length === 2) {
|
|
24
|
-
nx = shape[0];
|
|
25
|
-
ny = shape[1];
|
|
26
|
-
nz = 1;
|
|
27
|
-
}
|
|
28
|
-
else if (shape.length === 1) {
|
|
29
|
-
nx = shape[0];
|
|
30
|
-
ny = 1;
|
|
31
|
-
nz = 1;
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
throw new Error(`FITS: Cannot convert ${shape.length}D data to grid`);
|
|
35
|
-
}
|
|
36
|
-
const grid = new RegularGrid3D([nx, ny, nz], [nx, ny, nz]);
|
|
37
|
-
// FITS stores data in FORTRAN order (column-major: NAXIS1 varies fastest)
|
|
38
|
-
// RegularGrid3D uses row-major (x varies fastest in our convention)
|
|
39
|
-
// Since NAXIS1 = x and it varies fastest in both, direct copy works
|
|
40
|
-
const data = fits.data;
|
|
41
|
-
const gridData = grid.data;
|
|
42
|
-
const len = Math.min(data.length, gridData.length);
|
|
43
|
-
for (let i = 0; i < len; i++) {
|
|
44
|
-
gridData[i] = data[i];
|
|
45
|
-
}
|
|
46
|
-
return grid;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Extract a single frequency channel (z-slice) from a 3D FITS cube.
|
|
50
|
-
* Returns a 2D Float32Array (nx × ny) for use as a ScalarFieldOverlay.
|
|
51
|
-
*/
|
|
52
|
-
export function extractChannel(fits, channel) {
|
|
53
|
-
if (fits.shape.length < 3) {
|
|
54
|
-
// 2D image — return the whole thing
|
|
55
|
-
return new Float32Array(fits.data);
|
|
56
|
-
}
|
|
57
|
-
const nx = fits.shape[0];
|
|
58
|
-
const ny = fits.shape[1];
|
|
59
|
-
const nz = fits.shape[2];
|
|
60
|
-
if (channel < 0 || channel >= nz) {
|
|
61
|
-
throw new Error(`Channel ${channel} out of range [0, ${nz - 1}]`);
|
|
62
|
-
}
|
|
63
|
-
const slice = new Float32Array(nx * ny);
|
|
64
|
-
const offset = channel * nx * ny;
|
|
65
|
-
for (let i = 0; i < nx * ny; i++) {
|
|
66
|
-
slice[i] = fits.data[offset + i];
|
|
67
|
-
}
|
|
68
|
-
return slice;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Get data range (min/max) for the FITS data.
|
|
72
|
-
* Useful for colormap normalization.
|
|
73
|
-
*/
|
|
74
|
-
export function fitsDataRange(fits) {
|
|
75
|
-
let min = Infinity, max = -Infinity;
|
|
76
|
-
for (let i = 0; i < fits.data.length; i++) {
|
|
77
|
-
const v = fits.data[i];
|
|
78
|
-
if (v < min)
|
|
79
|
-
min = v;
|
|
80
|
-
if (v > max)
|
|
81
|
-
max = v;
|
|
82
|
-
}
|
|
83
|
-
return [min, max];
|
|
84
|
-
}
|
|
85
|
-
//# sourceMappingURL=FITSToGrid.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FITSToGrid.js","sourceRoot":"","sources":["../../src/fits/FITSToGrid.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { RADIO_ASTRONOMY_TRAITS, RadioAstronomyTraitName } from './constants/astronomy-traits';
|
|
2
|
-
import { PythonAstropyBridge, AstropyResult } from './bridge/python-runner';
|
|
3
|
-
/**
|
|
4
|
-
* @holoscript/radio-astronomy-plugin
|
|
5
|
-
*
|
|
6
|
-
* Domain plugin bridging Radio Astrophysics simulation concepts into the HoloScript Universal pipeline.
|
|
7
|
-
* Extends standard traits without bloating core. Provides an astropy python bridge for logic evaluation.
|
|
8
|
-
*/
|
|
9
|
-
export { RADIO_ASTRONOMY_TRAITS, type RadioAstronomyTraitName };
|
|
10
|
-
export { PythonAstropyBridge, type AstropyResult };
|
|
11
|
-
export { parseFITS, buildFITS, type FITSFile, type WCSInfo } from './fits/FITSParser';
|
|
12
|
-
export { fitsToGrid3D, extractChannel, fitsDataRange } from './fits/FITSToGrid';
|
|
13
|
-
export { SpectralCubeViewer, FITSViewerPanel, type SpectralCubeViewerProps, type FITSViewerPanelProps } from './components/SpectralCubeViewer';
|
|
14
|
-
/**
|
|
15
|
-
* Metadata exposing domain capabilities to the Studio / Schema Mapper.
|
|
16
|
-
*/
|
|
17
|
-
export declare const DOMAIN_MANIFEST: {
|
|
18
|
-
id: string;
|
|
19
|
-
name: string;
|
|
20
|
-
version: string;
|
|
21
|
-
description: string;
|
|
22
|
-
keywords: string[];
|
|
23
|
-
traits: readonly ["radio_emitter", "synchrotron", "interferometer", "em_wave", "pulsar_timing", "spectral_line"];
|
|
24
|
-
};
|
|
25
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5E;;;;;GAKG;AAGH,OAAO,EAAE,sBAAsB,EAAE,KAAK,uBAAuB,EAAE,CAAC;AAGhE,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,CAAC;AAGnD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,KAAK,uBAAuB,EAAE,KAAK,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAE/I;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;CAO3B,CAAC"}
|
package/dist/index.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { RADIO_ASTRONOMY_TRAITS } from './constants/astronomy-traits';
|
|
2
|
-
import { PythonAstropyBridge } from './bridge/python-runner';
|
|
3
|
-
/**
|
|
4
|
-
* @holoscript/radio-astronomy-plugin
|
|
5
|
-
*
|
|
6
|
-
* Domain plugin bridging Radio Astrophysics simulation concepts into the HoloScript Universal pipeline.
|
|
7
|
-
* Extends standard traits without bloating core. Provides an astropy python bridge for logic evaluation.
|
|
8
|
-
*/
|
|
9
|
-
// Export vocabulary
|
|
10
|
-
export { RADIO_ASTRONOMY_TRAITS };
|
|
11
|
-
// Export Bridges
|
|
12
|
-
export { PythonAstropyBridge };
|
|
13
|
-
// Export FITS parsing and visualization
|
|
14
|
-
export { parseFITS, buildFITS } from './fits/FITSParser';
|
|
15
|
-
export { fitsToGrid3D, extractChannel, fitsDataRange } from './fits/FITSToGrid';
|
|
16
|
-
export { SpectralCubeViewer, FITSViewerPanel } from './components/SpectralCubeViewer';
|
|
17
|
-
/**
|
|
18
|
-
* Metadata exposing domain capabilities to the Studio / Schema Mapper.
|
|
19
|
-
*/
|
|
20
|
-
export const DOMAIN_MANIFEST = {
|
|
21
|
-
id: 'domain.science.astronomy.radio',
|
|
22
|
-
name: 'Radio Astronomy Plugin',
|
|
23
|
-
version: '1.0.0',
|
|
24
|
-
description: 'Extends HoloScript spatial environments with radio astrophysics primitives.',
|
|
25
|
-
keywords: ['interferometer', 'radio emitting', 'synchrotron radiation', 'pulsar'],
|
|
26
|
-
traits: RADIO_ASTRONOMY_TRAITS,
|
|
27
|
-
};
|
|
28
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAA2B,MAAM,8BAA8B,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAiB,MAAM,wBAAwB,CAAC;AAE5E;;;;;GAKG;AAEH,oBAAoB;AACpB,OAAO,EAAE,sBAAsB,EAAgC,CAAC;AAEhE,iBAAiB;AACjB,OAAO,EAAE,mBAAmB,EAAsB,CAAC;AAEnD,wCAAwC;AACxC,OAAO,EAAE,SAAS,EAAE,SAAS,EAA+B,MAAM,mBAAmB,CAAC;AACtF,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAA2D,MAAM,iCAAiC,CAAC;AAE/I;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,EAAE,EAAE,gCAAgC;IACpC,IAAI,EAAE,wBAAwB;IAC9B,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE,6EAA6E;IAC1F,QAAQ,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,QAAQ,CAAC;IACjF,MAAM,EAAE,sBAAsB;CAC/B,CAAC"}
|