fitsjs-ng 1.0.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/LICENSE +21 -0
- package/README.md +180 -0
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +607 -0
- package/dist/index.d.ts +607 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/package.json +108 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# fitsjs-ng
|
|
2
|
+
|
|
3
|
+
Modern TypeScript library for reading [FITS](https://fits.gsfc.nasa.gov/) (Flexible Image Transport System) astronomical files. A complete rewrite of [astrojs/fitsjs](https://github.com/astrojs/fitsjs) with Promise-based APIs, full type safety, and Node.js/browser dual support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **FITS Image Reading** — BITPIX 8, 16, 32, -32, -64 with BZERO/BSCALE scaling
|
|
8
|
+
- **Data Cubes** — Frame-by-frame reading of 3D+ image data
|
|
9
|
+
- **ASCII Tables** — Fixed-width text table parsing (A/I/F/E/D format codes)
|
|
10
|
+
- **Binary Tables** — All standard types (L/B/I/J/K/A/E/D/C/M/X), bit arrays, heap access
|
|
11
|
+
- **Compressed Images** — Rice (RICE_1) decompression with subtractive dithering
|
|
12
|
+
- **Multiple HDUs** — Sequential parsing of all Header Data Units
|
|
13
|
+
- **Modern API** — Async/await, TypeScript types, ES modules, tree-shakeable
|
|
14
|
+
- **Universal** — Works in Node.js (18+) and modern browsers
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install fitsjs-ng
|
|
20
|
+
# or
|
|
21
|
+
pnpm add fitsjs-ng
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { FITS, Image } from 'fitsjs-ng'
|
|
28
|
+
|
|
29
|
+
// From a URL
|
|
30
|
+
const fits = await FITS.fromURL('https://example.com/image.fits')
|
|
31
|
+
|
|
32
|
+
// From an ArrayBuffer
|
|
33
|
+
const fits = FITS.fromArrayBuffer(buffer)
|
|
34
|
+
|
|
35
|
+
// From a File/Blob (browser)
|
|
36
|
+
const fits = await FITS.fromBlob(file)
|
|
37
|
+
|
|
38
|
+
// From a Node.js Buffer
|
|
39
|
+
const fits = FITS.fromNodeBuffer(fs.readFileSync('image.fits'))
|
|
40
|
+
|
|
41
|
+
// Access the primary header
|
|
42
|
+
const header = fits.getHeader()
|
|
43
|
+
console.log(header.get('BITPIX')) // e.g. -32
|
|
44
|
+
console.log(header.get('NAXIS1')) // e.g. 1024
|
|
45
|
+
|
|
46
|
+
// Read image pixels
|
|
47
|
+
const image = fits.getDataUnit() as Image
|
|
48
|
+
const pixels = await image.getFrame(0)
|
|
49
|
+
const [min, max] = image.getExtent(pixels)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## API Reference
|
|
53
|
+
|
|
54
|
+
### `FITS`
|
|
55
|
+
|
|
56
|
+
Static factory methods:
|
|
57
|
+
|
|
58
|
+
| Method | Description |
|
|
59
|
+
| ------------------------------ | ----------------------------------- |
|
|
60
|
+
| `FITS.fromArrayBuffer(buffer)` | Parse from `ArrayBuffer` (sync) |
|
|
61
|
+
| `FITS.fromBlob(blob)` | Parse from `Blob`/`File` (async) |
|
|
62
|
+
| `FITS.fromURL(url)` | Fetch and parse remote file (async) |
|
|
63
|
+
| `FITS.fromNodeBuffer(buffer)` | Parse from Node.js `Buffer` (sync) |
|
|
64
|
+
|
|
65
|
+
Instance methods:
|
|
66
|
+
|
|
67
|
+
| Method | Description |
|
|
68
|
+
| --------------------- | --------------------------------------- |
|
|
69
|
+
| `getHDU(index?)` | Get an HDU by index, or first with data |
|
|
70
|
+
| `getHeader(index?)` | Get a header by HDU index |
|
|
71
|
+
| `getDataUnit(index?)` | Get a data unit by HDU index |
|
|
72
|
+
|
|
73
|
+
### `Header`
|
|
74
|
+
|
|
75
|
+
| Method | Description |
|
|
76
|
+
| --------------- | ----------------------------------------------------------------------------- |
|
|
77
|
+
| `get(key)` | Get keyword value (`null` if missing) |
|
|
78
|
+
| `contains(key)` | Check if keyword exists |
|
|
79
|
+
| `keys()` | List all keyword names |
|
|
80
|
+
| `hasDataUnit()` | Whether this header has associated data |
|
|
81
|
+
| `getDataType()` | Returns `'Image'`, `'BinaryTable'`, `'Table'`, `'CompressedImage'`, or `null` |
|
|
82
|
+
| `getComments()` | Get all COMMENT card values |
|
|
83
|
+
| `getHistory()` | Get all HISTORY card values |
|
|
84
|
+
|
|
85
|
+
### `Image`
|
|
86
|
+
|
|
87
|
+
| Method | Description |
|
|
88
|
+
| ------------------------- | --------------------------------- |
|
|
89
|
+
| `getFrame(frame?)` | Read a single frame (async) |
|
|
90
|
+
| `getFrames(start, count)` | Read multiple frames (async) |
|
|
91
|
+
| `getExtent(pixels)` | Compute `[min, max]` ignoring NaN |
|
|
92
|
+
| `getPixel(pixels, x, y)` | Get pixel at (x, y) |
|
|
93
|
+
| `isDataCube()` | Whether NAXIS > 2 |
|
|
94
|
+
|
|
95
|
+
### `Table` (ASCII)
|
|
96
|
+
|
|
97
|
+
| Method | Description |
|
|
98
|
+
| --------------------- | ------------------------------------- |
|
|
99
|
+
| `getRows(row, count)` | Read rows as `TableRow[]` (async) |
|
|
100
|
+
| `getColumn(name)` | Read all values from a column (async) |
|
|
101
|
+
|
|
102
|
+
### `BinaryTable`
|
|
103
|
+
|
|
104
|
+
Same interface as `Table`, supports types: `L` (logical), `B` (byte), `I` (int16), `J` (int32), `K` (int64), `A` (char), `E` (float32), `D` (float64), `C`/`M` (complex), `X` (bit array).
|
|
105
|
+
|
|
106
|
+
### `CompressedImage`
|
|
107
|
+
|
|
108
|
+
| Method | Description |
|
|
109
|
+
| ------------------------ | ----------------------------------- |
|
|
110
|
+
| `getFrame(frame?)` | Decompress and read a frame (async) |
|
|
111
|
+
| `getExtent(pixels)` | Compute `[min, max]` ignoring NaN |
|
|
112
|
+
| `getPixel(pixels, x, y)` | Get pixel at (x, y) |
|
|
113
|
+
|
|
114
|
+
## Data Cube Example
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
const image = fits.getDataUnit() as Image
|
|
118
|
+
|
|
119
|
+
if (image.isDataCube()) {
|
|
120
|
+
console.log(`Depth: ${image.depth} frames`)
|
|
121
|
+
for (let i = 0; i < image.depth; i++) {
|
|
122
|
+
const frame = await image.getFrame(i)
|
|
123
|
+
console.log(`Frame ${i}: ${image.getExtent(frame)}`)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Multiple HDUs
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
const fits = FITS.fromArrayBuffer(buffer)
|
|
132
|
+
|
|
133
|
+
for (let i = 0; i < fits.hdus.length; i++) {
|
|
134
|
+
const hdu = fits.hdus[i]
|
|
135
|
+
const type = hdu.header.getDataType()
|
|
136
|
+
console.log(`HDU ${i}: ${type ?? 'no data'}`)
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Project Structure
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
src/
|
|
144
|
+
├── index.ts # Public exports
|
|
145
|
+
├── types.ts # TypeScript interfaces & types
|
|
146
|
+
├── constants.ts # FITS constants
|
|
147
|
+
├── errors.ts # Custom error classes
|
|
148
|
+
├── utils.ts # Endian swap, byte utilities
|
|
149
|
+
├── fits.ts # Main FITS class
|
|
150
|
+
├── parser.ts # FITS file parser
|
|
151
|
+
├── header.ts # Header parsing
|
|
152
|
+
├── header-verify.ts # Keyword validation
|
|
153
|
+
├── hdu.ts # Header Data Unit
|
|
154
|
+
├── data-unit.ts # Base data unit
|
|
155
|
+
├── image.ts # Image data unit
|
|
156
|
+
├── image-utils.ts # getExtent, getPixel
|
|
157
|
+
├── tabular.ts # Abstract tabular base
|
|
158
|
+
├── table.ts # ASCII table
|
|
159
|
+
├── binary-table.ts # Binary table
|
|
160
|
+
├── compressed-image.ts # Compressed image (Rice)
|
|
161
|
+
└── decompress.ts # Decompression algorithms
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Development
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
pnpm install
|
|
168
|
+
pnpm test # Run tests
|
|
169
|
+
pnpm build # Build library
|
|
170
|
+
pnpm typecheck # Type check
|
|
171
|
+
pnpm lint # Lint
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Credits
|
|
175
|
+
|
|
176
|
+
Based on [astrojs/fitsjs](https://github.com/astrojs/fitsjs) by Amit Kapadia / Zooniverse.
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
[MIT](LICENSE)
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
'use strict';// fitsjs-ng v1.0.0 | MIT License
|
|
2
|
+
var P=80,x=2880,he=36,se=600,ne=-2147483647,ie=-2147483646,N=1e4,me="1.0.0";var D=class extends Error{constructor(e){super(e),this.name="FITSError";}},B=class extends D{constructor(e){super(e),this.name="HeaderError";}},G=class extends D{constructor(e){super(e),this.name="DataError";}},R=class extends D{constructor(e){super(e),this.name="DecompressionError";}};function O(s,e,t){t!==s.cardIndex&&s.warn(`${e} should appear at index ${t} in the FITS header`);}function X(s,e,t,r){if(e<t||e>r)throw new B(`The ${s} value of ${e} is not between ${t} and ${r}`)}function Y(s){return s==="T"}var K={SIMPLE(s,e){return s.primary=true,O(s,"SIMPLE",0),Y(e)},XTENSION(s,e){return s.extension=true,s.extensionType=e,O(s,"XTENSION",0),s.extensionType},BITPIX(s,e){let t=parseInt(String(e),10);if(O(s,"BITPIX",1),![8,16,32,-32,-64].includes(t))throw new B(`BITPIX value ${t} is not permitted`);return t},NAXIS(s,e,t){let r=parseInt(String(e),10);if(!t&&(O(s,"NAXIS",2),X("NAXIS",r,0,999),s.isExtension()&&(s.extensionType==="TABLE"||s.extensionType==="BINTABLE")&&r!==2))throw new B("NAXIS must be 2 for TABLE and BINTABLE extensions");return r},PCOUNT(s,e){let t=parseInt(String(e),10),n=3+s.get("NAXIS");if(O(s,"PCOUNT",n),s.isExtension()&&(s.extensionType==="IMAGE"||s.extensionType==="TABLE")&&t!==0)throw new B(`PCOUNT must be 0 for the ${s.extensionType} extensions`);return t},GCOUNT(s,e){let t=parseInt(String(e),10),n=3+s.get("NAXIS")+1;if(O(s,"GCOUNT",n),s.isExtension()&&(s.extensionType==="IMAGE"||s.extensionType==="TABLE"||s.extensionType==="BINTABLE")&&t!==1)throw new B(`GCOUNT must be 1 for the ${s.extensionType} extensions`);return t},EXTEND(s,e){if(!s.isPrimary())throw new B("EXTEND must only appear in the primary header");return Y(e)},BSCALE(s,e){return parseFloat(String(e))},BZERO(s,e){return parseFloat(String(e))},BLANK(s,e){let t=s.get("BITPIX");return t<=0&&s.warn(`BLANK is not to be used for BITPIX = ${t}`),parseInt(String(e),10)},DATAMIN(s,e){return parseFloat(String(e))},DATAMAX(s,e){return parseFloat(String(e))},EXTVER(s,e){return parseInt(String(e),10)},EXTLEVEL(s,e){return parseInt(String(e),10)},TFIELDS(s,e){let t=parseInt(String(e),10);return X("TFIELDS",t,0,999),t},TBCOL(s,e,t,r){let n=s.get("TFIELDS");return r!==void 0&&X("TBCOL",parseInt(r,10),0,n),e},ZIMAGE(s,e){return Y(e)},ZCMPTYPE(s,e){let t=String(e);if(!["GZIP_1","RICE_1","PLIO_1","HCOMPRESS_1"].includes(t))throw new B(`ZCMPTYPE value ${t} is not permitted`);if(!["RICE_1"].includes(t))throw new B(`Compress type ${t} is not yet implemented`);return t},ZBITPIX(s,e){let t=parseInt(String(e),10);if(![8,16,32,64,-32,-64].includes(t))throw new B(`ZBITPIX value ${t} is not permitted`);return t},ZNAXIS(s,e,t){let r=parseInt(String(e),10);return t||X("ZNAXIS",r,0,999),r},ZTILE(s,e){return parseInt(String(e),10)},ZSIMPLE(s,e){return e==="T"},ZPCOUNT(s,e){return parseInt(String(e),10)},ZGCOUNT(s,e){return parseInt(String(e),10)},ZDITHER0(s,e){return parseInt(String(e),10)}};var U=class s{static ARRAY_PATTERN=/(\D+)(\d+)/;primary=false;extension=false;extensionType;cards=new Map;comments=[];history=[];cardIndex=0;warn;maxLines;block;constructor(e,t=600,r){this.maxLines=t,this.warn=r??console.warn,this.block=e,this.readBlock(e);}get(e){return this.contains(e)?this.cards.get(e).value:null}getNumber(e,t){let r=this.get(e);if(r===null)return t??0;if(typeof r=="number")return r;throw new B(`Expected number for keyword ${e}, got ${typeof r}`)}getString(e,t){let r=this.get(e);if(r===null)return t??"";if(typeof r=="string")return r;throw new B(`Expected string for keyword ${e}, got ${typeof r}`)}getBoolean(e,t){let r=this.get(e);if(r===null)return t??false;if(typeof r=="boolean")return r;throw new B(`Expected boolean for keyword ${e}, got ${typeof r}`)}set(e,t,r=""){this.cards.set(e,{index:this.cardIndex,value:t,comment:r}),this.cardIndex+=1;}contains(e){return this.cards.has(e)}getComments(){return this.comments}getHistory(){return this.history}keys(){return Array.from(this.cards.keys())}hasDataUnit(){let e=this.getNumber("NAXIS");if(e===0)return false;for(let t=1;t<=e;t++)if(this.getNumber(`NAXIS${t}`)!==0)return true;return false}getDataLength(){if(!this.hasDataUnit())return 0;let e=this.getNumber("NAXIS"),t=[];for(let i=1;i<=e;i++)t.push(this.getNumber(`NAXIS${i}`));let r=this.getNumber("BITPIX"),n=t.reduce((i,o)=>i*o,1)*Math.abs(r)/8;return n+=this.getNumber("PCOUNT"),n}getDataType(){switch(this.extensionType){case "BINTABLE":return this.contains("ZIMAGE")?"CompressedImage":"BinaryTable";case "TABLE":return "Table";case "IMAGE":return this.hasDataUnit()?"Image":null;default:return this.hasDataUnit()?"Image":null}}isPrimary(){return this.primary}isExtension(){return this.extension}readBlock(e){let r=e.length/80,n=Math.min(r,this.maxLines);for(let i=0;i<n;i++){let o=e.slice(i*80,(i+1)*80);this.readLine(o);}}readLine(e){let t=e.slice(0,8).trim();if(t==="")return;let r=e.slice(8,10),n=e.slice(10);if(r!=="= "){let a=e.slice(8).trim();t==="COMMENT"?this.comments.push(a):t==="HISTORY"&&this.history.push(a);return}let i,o;if(n.trimStart().startsWith("'")){let a=n.indexOf("'"),u=-1,m=a+1;for(;m<n.length;){let c=n.indexOf("'",m);if(c===-1)break;if(c+1<n.length&&n[c+1]==="'"){m=c+2;continue}u=c;break}if(u!==-1){let c=n.slice(u+1),f=c.indexOf(" /");f!==-1?(i=n.slice(0,u+1).trim(),o=c.slice(f+2).trim()):(i=n.slice(0,u+1).trim(),o="");}else i=n.trim(),o="";}else {let a=n.indexOf(" /");a!==-1?(i=n.slice(0,a).trim(),o=n.slice(a+2).trim()):(i=n.trim(),o="");}let l;i.startsWith("'")?l=i.slice(1,-1).replaceAll("''","'").trim():i==="T"||i==="F"?l=i:l=parseFloat(i),l=this.validate(t,l),this.set(t,l,o);}validate(e,t){let r=e,n=false,i,o=s.ARRAY_PATTERN.exec(e);return o&&(n=true,r=o[1],i=o[2]),r in K&&(t=K[r](this,t,n,i)),t}};var _=class{header;data;constructor(e,t){this.header=e,this.data=t;}hasData(){return this.data!==void 0}};var oe=s=>s,ae=s=>(s&255)<<8|s>>8&255,ce=s=>(s&255)<<24|(s&65280)<<8|s>>8&65280|s>>24&255,$={8:oe,B:oe,16:ae,I:ae,32:ce,J:ce},pe=new TextDecoder("ascii");function H(s){return pe.decode(s)}function q(s){return (2880-s%2880)%2880}function le(s){let e=[],t=128;for(;t>=1;)e.push(s&t?1:0),t>>=1;return e}var C=class{buffer;blob;static swapEndian=$;constructor(e){e instanceof ArrayBuffer?this.buffer=e:typeof Blob<"u"&&e instanceof Blob&&(this.blob=e);}};function M(s){let e=s.length,t,r,n=0;for(;n<e;n++){let i=s[n];if(!isNaN(i)){t=r=i,n++;break}}if(t===void 0||r===void 0)return [NaN,NaN];for(;n<e;n++){let i=s[n];isNaN(i)||(i<t?t=i:i>r&&(r=i));}return [t,r]}function k(s,e,t,r){let n=t*r+e;return n<0||n>=s.length?NaN:s[n]}var z=class s extends C{bitpix;naxis;width;height;depth;bzero;bscale;bytes;length;frameLength;frameOffsets;constructor(e,t){super(t);let r=e.getNumber("NAXIS");this.bitpix=e.getNumber("BITPIX"),this.naxis=[];for(let n=1;n<=r;n++)this.naxis.push(e.getNumber(`NAXIS${n}`));this.width=e.getNumber("NAXIS1"),this.height=e.getNumber("NAXIS2",1),this.depth=e.getNumber("NAXIS3",1),this.bzero=e.getNumber("BZERO"),this.bscale=e.getNumber("BSCALE",1),this.bytes=Math.abs(this.bitpix)/8,this.length=this.naxis.reduce((n,i)=>n*i,1)*Math.abs(this.bitpix)/8,this.frameOffsets=[],this.frameLength=this.bytes*this.width*this.height;for(let n=0;n<this.depth;n++){let i=n*this.frameLength,o={begin:i};this.buffer&&(o.buffers=[this.buffer.slice(i,i+this.frameLength)]),this.frameOffsets.push(o);}}static computeFrame(e,t,r,n){let i=Math.abs(t)/8,o=e.byteLength/i,l=r===0&&n===1,a=new DataView(e),u=!(Number.isInteger(r)&&Number.isInteger(n));if(t===8){if(l)return new Uint8Array(e.slice(0));let c=u?new Float32Array(o):new Int32Array(o);for(let f=0;f<o;f++)c[f]=r+n*a.getUint8(f);return c}if(t===16){if(l){let f=new Int16Array(o);for(let h=0;h<o;h++)f[h]=a.getInt16(h*2,false);return f}let c=u?new Float32Array(o):new Int32Array(o);for(let f=0;f<o;f++)c[f]=r+n*a.getInt16(f*2,false);return c}if(t===32){if(l){let f=new Int32Array(o);for(let h=0;h<o;h++)f[h]=a.getInt32(h*4,false);return f}let c=new Float64Array(o);for(let f=0;f<o;f++)c[f]=r+n*a.getInt32(f*4,false);return c}if(t===-32){let c=new Float32Array(o);if(l)for(let f=0;f<o;f++)c[f]=a.getFloat32(f*4,false);else for(let f=0;f<o;f++)c[f]=r+n*a.getFloat32(f*4,false);return c}let m=new Float64Array(o);if(l)for(let c=0;c<o;c++)m[c]=a.getFloat64(c*8,false);else for(let c=0;c<o;c++)m[c]=r+n*a.getFloat64(c*8,false);return m}async getFrame(e=0){let t=this.frameOffsets[e];if(t.buffers&&t.buffers.length>0)return s.computeFrame(t.buffers[0],this.bitpix,this.bzero,this.bscale);if(!this.blob)throw new Error("No data source available for this image frame");let r=t.begin,i=await this.blob.slice(r,r+this.frameLength).arrayBuffer();return t.buffers=[i],s.computeFrame(i,this.bitpix,this.bzero,this.bscale)}async getFrames(e,t){let r=Array.from({length:t},(n,i)=>e+i);return Promise.all(r.map(n=>this.getFrame(n)))}isDataCube(){return this.naxis.length>2}async*[Symbol.asyncIterator](){for(let e=0;e<this.depth;e++)yield this.getFrame(e);}getExtent(e){return M(e)}getPixel(e,t,r){return k(e,t,r,this.width)}};var Q={L:1,B:1,I:2,J:4,K:8,A:1,E:4,D:8,C:8,M:16},v={B:Uint8Array,I:Int16Array,J:Int32Array,E:Float32Array,D:Float64Array,1:Uint8Array,2:Int16Array,4:Int32Array};var F=class extends C{maxMemory=1048576;rowByteSize;rows;cols;length;heapLength;columns;accessors=[];descriptors=[];elementByteLengths=[];columnTypes=[];heap;typedArray=v;firstRowInBuffer=0;lastRowInBuffer=0;nRowsInBuffer=0;cachedBuffer;constructor(e,t){super(t),this.rowByteSize=e.getNumber("NAXIS1"),this.rows=e.getNumber("NAXIS2"),this.cols=e.getNumber("TFIELDS"),this.length=this.rowByteSize*this.rows,this.heapLength=e.getNumber("PCOUNT"),this.columns=this.getColumns(e),this.buffer?this.heap=this.buffer.slice(this.length,this.length+this.heapLength):(this.firstRowInBuffer=0,this.lastRowInBuffer=0,this.nRowsInBuffer=Math.floor(this.maxMemory/this.rowByteSize));}initAccessors(e){this.resetAccessors(),this.setAccessors(e);}resetAccessors(){this.accessors=[],this.descriptors=[],this.elementByteLengths=[],this.columnTypes=[];}rowsInMemory(e,t){return this.buffer&&!this.blob?true:this.cachedBuffer?!(e<this.firstRowInBuffer||t>this.lastRowInBuffer):false}getColumns(e){let t=[];for(let r=1;r<=this.cols;r++){let n=`TTYPE${r}`;if(!e.contains(n))return null;t.push(e.getString(n));}return t}async getRows(e,t){if(this.rowsInMemory(e,e+t)){let a;if(this.cachedBuffer){let u=(e-this.firstRowInBuffer)*this.rowByteSize;a=this.cachedBuffer.slice(u,u+t*this.rowByteSize);}else if(this.buffer){let u=e*this.rowByteSize,m=u+t*this.rowByteSize;a=this.buffer.slice(u,m);}else throw new Error("No data source available");return this._getRows(a,t)}if(!this.blob)throw new Error("No data source available");let r=e*this.rowByteSize,n=Math.max(this.nRowsInBuffer,t),i=r+n*this.rowByteSize,l=await this.blob.slice(r,i).arrayBuffer();return this.cachedBuffer=l,this.firstRowInBuffer=e,this.lastRowInBuffer=e+n,this._getRows(l,t)}async getTableBuffer(e,t){let r=Math.min(this.rows-e,t),n=e*this.rowByteSize,i=n+r*this.rowByteSize;if(this.buffer)return this.buffer.slice(n,i);if(!this.blob)throw new Error("No data source available");return this.blob.slice(n,i).arrayBuffer()}async getColumn(e){if(!this.columns)throw new Error("Column names not available");let t=this.columns.indexOf(e);if(t===-1)throw new Error(`Column "${e}" not found`);if(this.buffer&&!this.blob)return (await this.getRows(0,this.rows)).map(y=>y[e]);let r=this.descriptors[t],n=this.accessors[t],i=this.elementByteLengths.slice(0,t).reduce((h,y)=>h+y,0),o=r&&this.typedArray[r]?this.typedArray[r]:null,l=o?Array.from(new o(this.rows)):new Array(this.rows),a=Math.min(Math.max(1,Math.floor(this.maxMemory/this.rowByteSize)),this.rows),u=this.rows/a,m=Math.floor(u)===u?u:Math.floor(u)+1,c=0,f=0;for(;m>0;){let h=f*a,y=await this.getTableBuffer(h,a),A=y.byteLength/this.rowByteSize,b=new DataView(y),g=i;for(let p=0;p<A;p++)l[c]=n(b,g)[0],c++,g+=this.rowByteSize;m--,f++;}return l}};var ye={A:s=>s.trim(),I:s=>parseInt(s,10),F:s=>parseFloat(s),E:s=>parseFloat(s),D:s=>parseFloat(s)},Z=class extends F{asciiAccessors=[];colStarts=[];colWidths=[];hasTBCOL=false;constructor(e,t){super(e,t),this.initAccessors(e);}setAccessors(e){this.asciiAccessors=[],this.colStarts=[],this.colWidths=[],this.hasTBCOL=false;let t=/([AIFED])(\d+)\.*(\d+)*/;for(let r=1;r<=this.cols;r++)if(e.contains(`TBCOL${r}`)){this.hasTBCOL=true;break}for(let r=1;r<=this.cols;r++){let n=e.getString(`TFORM${r}`),i=t.exec(n);if(!i){this.asciiAccessors.push(m=>m.trim()),this.colStarts.push(0),this.colWidths.push(0);continue}let o=i[1],l=parseInt(i[2],10),a=ye[o]??(m=>m.trim());this.asciiAccessors.push(a);let u=e.contains(`TBCOL${r}`)?e.getNumber(`TBCOL${r}`)-1:0;this.colStarts.push(u),this.colWidths.push(l);}}_getRows(e,t){let r=e.byteLength/this.rowByteSize,n=new Uint8Array(e),i=[],o=this.asciiAccessors??[];for(let l=0;l<r;l++){let a=l*this.rowByteSize,u=a+this.rowByteSize,m=n.subarray(a,u),c=H(m),f={};if(this.hasTBCOL)for(let h=0;h<o.length;h++){let y=this.colStarts[h],A=this.colWidths[h],b=c.substring(y,y+A).trim();this.columns&&(f[this.columns[h]]=o[h](b));}else {let h=c.trim().split(/\s+/);for(let y=0;y<o.length;y++){let A=h[y]??"";this.columns&&(f[this.columns[y]]=o[y](A));}}i.push(f);}return i}};var ue={L(s,e){return [s.getInt8(e)===84,e+1]},B(s,e){return [s.getUint8(e),e+1]},I(s,e){return [s.getInt16(e,false),e+2]},J(s,e){return [s.getInt32(e,false),e+4]},K(s,e){let t=s.getBigInt64(e,false);return [Number(t),e+8]},A(s,e){return [String.fromCharCode(s.getUint8(e)),e+1]},E(s,e){return [s.getFloat32(e,false),e+4]},D(s,e){return [s.getFloat64(e,false),e+8]},C(s,e){let t=s.getFloat32(e,false),r=s.getFloat32(e+4,false);return [[t,r],e+8]},M(s,e){let t=s.getFloat64(e,false),r=s.getFloat64(e+8,false);return [[t,r],e+16]}},L=class extends F{constructor(e,t){super(e,t),this.initAccessors(e);}setAccessors(e){let t=/(\d*)([PQ]*)([LXBIJKAEDCM])$/;for(let r=1;r<=this.cols;r++){let n=e.getString(`TFORM${r}`),i=e.getString(`TTYPE${r}`),o=t.exec(n);if(!o)throw new Error(`Unsupported or invalid TFORM${r} value: '${n}'`);let l=parseInt(o[1],10)||1,a=o[2],u=o[3];this.descriptors.push(u),this.columnTypes.push(i),this.elementByteLengths.push((Q[u]??1)*l),a?this.setupArrayAccessor(u,i):l===1?this.setupSingleAccessor(u):u==="X"?this.setupBitArrayAccessor(l):u==="A"?this.setupCharArrayAccessor(l):this.setupMultiAccessor(u,l);}}getFromHeap(e,t,r){let n=e.getInt32(t,false);t+=4;let i=e.getInt32(t,false);if(t+=4,!this.heap)throw new Error("Heap not available");let o=Q[r]??1,l=this.heap.slice(i,i+n*o),a=v[r];if(!a)throw new Error(`No typed array constructor for descriptor: ${r}`);let u=new a(l),m=$[r];if(m&&r!=="B")for(let c=0;c<u.length;c++)u[c]=m(u[c]);return [u,t]}setupArrayAccessor(e,t){if(t==="COMPRESSED_DATA"){let r=(n,i)=>{let[o,l]=this.getFromHeap(n,i,e);return [o,l]};this.accessors.push(r);}else if(t==="GZIP_COMPRESSED_DATA"){let r=(n,i)=>{throw new R("GZIP decompression is not yet implemented")};this.accessors.push(r);}else {let r=(n,i)=>this.getFromHeap(n,i,e);this.accessors.push(r);}}setupSingleAccessor(e){let t=ue[e];if(!t)throw new Error(`Unknown binary table type code: ${e}`);let r=(n,i)=>t(n,i);this.accessors.push(r);}setupBitArrayAccessor(e){let t=Math.ceil(e/8),r=(n,i)=>{let o=n.buffer.slice(i,i+t),l=new Uint8Array(o),a=[];for(let u=0;u<l.length;u++)a=a.concat(le(l[u]));return [a.slice(0,e),i+t]};this.accessors.push(r);}setupCharArrayAccessor(e){let t=(r,n)=>{let i=r.buffer.slice(n,n+e),o=new Uint8Array(i),l="";for(let a=0;a<o.length;a++)l+=String.fromCharCode(o[a]);return [l.trim(),n+e]};this.accessors.push(t);}setupMultiAccessor(e,t){let r=ue[e];if(!r)throw new Error(`Unknown binary table type code: ${e}`);let n=(i,o)=>{let l=[],a=o;for(let u=0;u<t;u++){let[m,c]=r(i,a);l.push(m),a=c;}return [l,a]};this.accessors.push(n);}_getRows(e,t){let r=new DataView(e),n=0,i=[];for(let o=0;o<t;o++){let l={};for(let a=0;a<this.accessors.length;a++){let[u,m]=this.accessors[a](r,n);n=m,this.columns&&(l[this.columns[a]]=u);}i.push(l);}return i}};var W={1(s){return [3,6,s[0],1]},2(s){let n=0;return n=n|s[0]<<8,n=n|s[1],[4,14,n,2]},4(s){let n=0;return n=n|s[0]<<24,n=n|s[1]<<16,n=n|s[2]<<8,n=n|s[3],[5,25,n,4]}};function J(s,e,t,r,n,i=W){let o=i[t];if(!o)throw new Error(`Unsupported bytepix value: ${t}`);let[l,a,u,m]=o(s),c=u,f=m,h=1<<l,y=new Uint8Array(256),A=8,b=128,g=255;for(;g>=0;){for(;g>=b;)y[g]=A,g--;b=b/2,A--;}y[0]=0;let p=s[f++],d=8,w=0;for(;w<n;){for(d-=l;d<0;)p=p<<8|s[f++],d+=8;let E=(p>>d)-1;p&=(1<<d)-1;let S=w+e;if(S>n&&(S=n),E<0)for(;w<S;)r[w]=c,w++;else if(E===a)for(;w<S;){b=h-d;let T=p<<b;for(b-=8;b>=0;)p=s[f++],T|=p<<b,b-=8;d>0?(p=s[f++],T|=p>>-b,p&=(1<<d)-1):p=0,(T&1)===0?T=T>>1:T=~(T>>1),r[w]=T+c,c=r[w],w++;}else for(;w<S;){for(;p===0;)d+=8,p=s[f++];for(A=d-y[p],d-=A+1,p^=1<<d,d-=E;d<0;)p=p<<8|s[f++],d+=8;let T=A<<E|p>>d;p&=(1<<d)-1,(T&1)===0?T=T>>1:T=~(T>>1),r[w]=T+c,c=r[w],w++;}}return r}function be(){let t=1,r=new Float32Array(1e4);for(let n=0;n<1e4;n++){let i=16807*t;t=i-2147483647*Math.floor(i/2147483647),r[n]=t/2147483647;}return r}var j=be(),V=class extends L{zcmptype;zbitpix;znaxis;zblank;blank;zdither;ztile;width;height;bzero;bscale;algorithmParameters;zquantiz;constructor(e,t){super(e,t),this.zcmptype=e.getString("ZCMPTYPE"),this.zbitpix=e.getNumber("ZBITPIX"),this.znaxis=e.getNumber("ZNAXIS"),this.zblank=e.contains("ZBLANK")?e.getNumber("ZBLANK"):null,this.blank=e.contains("BLANK")?e.getNumber("BLANK"):null,this.zdither=e.getNumber("ZDITHER0"),this.ztile=[];for(let n=1;n<=this.znaxis;n++){let i=e.contains(`ZTILE${n}`)?e.getNumber(`ZTILE${n}`):n===1?e.getNumber("ZNAXIS1"):1;this.ztile.push(i);}this.width=e.getNumber("ZNAXIS1"),this.height=e.getNumber("ZNAXIS2",1),this.algorithmParameters={},this.zcmptype==="RICE_1"&&(this.algorithmParameters.BLOCKSIZE=32,this.algorithmParameters.BYTEPIX=4);let r=1;for(;e.contains(`ZNAME${r}`);){let n=e.getString(`ZNAME${r}`),i=e.getNumber(`ZVAL${r}`);this.algorithmParameters[n]=i,r++;}this.zquantiz=e.getString("ZQUANTIZ","LINEAR_SCALING"),this.bzero=e.getNumber("BZERO"),this.bscale=e.getNumber("BSCALE",1),this.initAccessors(e);}setAccessors(e){super.setAccessors(e);for(let t=0;t<this.columnTypes.length;t++){let r=this.columnTypes[t],n=this.descriptors[t];r==="COMPRESSED_DATA"?this.accessors[t]=(i,o)=>{let[l,a]=this.getFromHeap(i,o,n),u=this.algorithmParameters.BYTEPIX??4,m=this.algorithmParameters.BLOCKSIZE??32,c=v[u];if(!c)throw new Error(`No typed array for bytepix: ${u}`);let f=this.ztile[0]??this.width,h=new c(f);return J(l,m,u,h,f,W),[h,a]}:r==="GZIP_COMPRESSED_DATA"&&(this.accessors[t]=(i,o)=>{throw new R("GZIP decompression is not yet implemented")});}}_getRows(e,t){let r=new DataView(e),n=0,i=new Float32Array(this.width*this.height),o=0,l=t;for(;l--;){o++;let a={};for(let b=0;b<this.accessors.length;b++){let[g,p]=this.accessors[b](r,n);n=p,this.columns&&(a[this.columns[b]]=g);}let u=a.COMPRESSED_DATA||a.UNCOMPRESSED_DATA||a.GZIP_COMPRESSED_DATA,m=a.ZSCALE||this.bscale,c=a.ZZERO||this.bzero,f=o,h=this.zquantiz==="SUBTRACTIVE_DITHER_1"||this.zquantiz==="SUBTRACTIVE_DITHER_2",y=0,A=0;if(h){let g=(f+this.zdither-1-1)%1e4;A=g<0?g+1e4:g,y=Math.floor(j[A]*500);}for(let b=0;b<u.length;b++){let g=(f-1)*this.width+b,p=u[b];if(p===-2147483647)i[g]=NaN;else if(p===-2147483646)i[g]=0;else if(h){let d=j[y];i[g]=(p-d+.5)*m+c;}else i[g]=p*m+c;h&&(y++,y===1e4&&(A=(A+1)%1e4,y=Math.floor(j[A]*500)));}}return i}async getFrame(e=0){if(this.heap)return await this.getRows(0,this.rows);if(!this.blob)throw new Error("No data source available");let t=this.blob.slice(this.length,this.length+this.heapLength);return this.heap=await t.arrayBuffer(),this.getFrame(e)}getExtent(e){return M(e)}getPixel(e,t,r){return k(e,t,r,this.width)}};function fe(s,e){let t=s.getDataType();if(t)switch(t){case "Image":return new z(s,e);case "BinaryTable":return new L(s,e);case "Table":return new Z(s,e);case "CompressedImage":return new V(s,e);default:return}}function ee(s,e){let t=[],r=s.byteLength,n=0;for(;n<r;){let i=0,o=new Uint8Array(0),l=false;for(;!l&&n+i*2880+2880<=r;){let a=n+i*2880,u=new Uint8Array(s,a,2880),m=new Uint8Array(o.length+2880);m.set(o,0),m.set(u,o.length),o=m;let c=2880/80;for(let p=c-1;p>=0;p--){let d=p*80,w=u[d];if(w!==32){if(w===69&&u[d+1]===78&&u[d+2]===68&&u[d+3]===32){l=true;break}break}}if(i++,!l)continue;let f=H(o),h=new U(f,e?.maxHeaderLines,e?.onWarning),y=n+i*2880,A=h.getDataLength(),b=s.slice(y,y+A),g;if(h.hasDataUnit()&&(g=fe(h,b)),t.push(new _(h,g)),n=y+A+q(A),n>=r)break}if(!l)break}return t}async function te(s,e){let t=[],r=s.size,n=0;for(;n<r;){let i=0,o=[],l=false;for(;!l&&n+i*2880+2880<=r;){let a=n+i*2880,m=await s.slice(a,a+2880).arrayBuffer(),c=new Uint8Array(m);o.push(c);let f=2880/80;for(let E=f-1;E>=0;E--){let S=E*80,T=c[S];if(T!==32){if(T===69&&c[S+1]===78&&c[S+2]===68&&c[S+3]===32){l=true;break}break}}if(i++,!l)continue;let h=o.reduce((E,S)=>E+S.length,0),y=new Uint8Array(h),A=0;for(let E of o)y.set(E,A),A+=E.length;let b=H(y),g=new U(b,e?.maxHeaderLines,e?.onWarning),p=n+i*2880,d=g.getDataLength(),w;if(g.hasDataUnit()){let E=s.slice(p,p+d);w=fe(g,E);}if(t.push(new _(g,w)),n=p+d+q(d),n>=r)break}if(!l)break}return t}var re=class s{hdus;constructor(e){this.hdus=e;}static fromArrayBuffer(e,t){let r=ee(e,t);return new s(r)}static async fromBlob(e,t){let r=await te(e,t);return new s(r)}static async fromURL(e,t){let r=await fetch(e,t?.requestInit);if(!r.ok)throw new Error(`Failed to fetch FITS file: ${r.status} ${r.statusText}`);let n=await r.arrayBuffer();return s.fromArrayBuffer(n,t)}static fromNodeBuffer(e,t){let r=e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength);return s.fromArrayBuffer(r,t)}getHDU(e){if(e!==void 0)return e>=0&&e<this.hdus.length?this.hdus[e]:void 0;for(let t of this.hdus)if(t.hasData())return t}getHeader(e){return this.getHDU(e)?.header}getDataUnit(e){return this.getHDU(e)?.data}};exports.BLOCK_LENGTH=x;exports.BinaryTable=L;exports.CompressedImage=V;exports.DEFAULT_MAX_HEADER_LINES=se;exports.DataError=G;exports.DataUnit=C;exports.DecompressionError=R;exports.FITS=re;exports.FITSError=D;exports.HDU=_;exports.Header=U;exports.HeaderError=B;exports.Image=z;exports.LINES_PER_BLOCK=he;exports.LINE_WIDTH=P;exports.NULL_VALUE=ne;exports.N_RANDOM=N;exports.RiceSetup=W;exports.Table=Z;exports.VERSION=me;exports.ZERO_VALUE=ie;exports.getExtent=M;exports.getPixel=k;exports.parseBlob=te;exports.parseBuffer=ee;exports.riceDecompress=J;//# sourceMappingURL=index.cjs.map
|
|
3
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/errors.ts","../src/header-verify.ts","../src/header.ts","../src/hdu.ts","../src/utils.ts","../src/data-unit.ts","../src/image-utils.ts","../src/image.ts","../src/types.ts","../src/tabular.ts","../src/table.ts","../src/binary-table.ts","../src/decompress.ts","../src/compressed-image.ts","../src/parser.ts","../src/fits.ts"],"names":["LINE_WIDTH","BLOCK_LENGTH","LINES_PER_BLOCK","DEFAULT_MAX_HEADER_LINES","NULL_VALUE","ZERO_VALUE","N_RANDOM","VERSION","FITSError","message","HeaderError","DataError","DecompressionError","verifyOrder","ctx","keyword","order","verifyBetween","value","lower","upper","verifyBoolean","VerifyFns","v","isArray","_ctx","bitpix","_isArray","index","tfields","Header","_Header","block","maxLines","onWarning","key","fallback","comment","naxis","i","naxisValues","length","a","b","nLinesRaw","nLines","line","indicator","rawValue","fullValue","valueStr","openQuote","closeQuote","pos","q","afterQuote","slashIdx","baseKey","match","HDU","header","data","swap8","swap16","swap32","swapEndian","textDecoder","uint8ArrayToString","arr","excessBytes","toBits","byte","DataUnit","getExtent","len","min","max","getPixel","x","y","width","Image","_Image","naxisCount","begin","info","buffer","bzero","bscale","bytes","nPixels","identity","view","needFloat","result","frame","frameInfo","arrayBuffer","startFrame","count","indices","_","BINARY_TYPE_BYTE_SIZES","TYPED_ARRAY_CONSTRUCTORS","Tabular","firstRow","lastRow","columns","row","number_","buf","offsetInCache","end","readRows","actualRows","name","colIndex","d","descriptor","accessor","elementByteOffset","TypedArrayCtor","column","rowsPerIteration","factor","iterations","chunkIndex","startRow","nRows","offset","r","ASCII_ACCESSORS","Table","pattern","form","fn","tbcol","_nRows","rows","accessors","subarray","j","start","fields","DATA_ACCESSORS","val","val1","val2","BinaryTable","type","heapOffset","bytesPerElement","heapSlice","Ctor","swapFn","newOffset","_view","_offset","dataAccessor","nBytes","bits","s","c","off","newOff","RiceSetup","array","lastpix","riceDecompress","blocksize","bytepix","pixels","nx","setup","setupFn","fsbits","fsmax","initialLastpix","initialPointer","pointer","bbits","nonzeroCount","nzero","k","idx","nbits","fs","imax","diff","generateRandomSequence","seed","random","temp","RANDOM_SEQUENCE","CompressedImage","ztile","paramIdx","tileSize","tileIndex","rowsRemaining","scale","zero","nTile","useDither","rIndex","seed1","seed1Initial","pixelIndex","_nFrame","heapBlob","createDataUnit","parseBuffer","options","hdus","totalLength","blockCount","headerStorage","headerFound","blockStart","blockBytes","newStorage","rowIndex","headerString","headerEnd","dataLength","dataSlice","dataunit","parseBlob","blob","headerChunks","blockBuffer","totalHeaderBytes","sum","chunk","dataBlob","FITS","_FITS","url","response","nodeBuffer","hdu"],"mappings":"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","file":"index.cjs","sourcesContent":["/** Width of a single FITS header card in bytes (characters). */\nexport const LINE_WIDTH = 80\n\n/** Size of a FITS block in bytes. All FITS structures are padded to this boundary. */\nexport const BLOCK_LENGTH = 2880\n\n/** Number of header card lines per FITS block. */\nexport const LINES_PER_BLOCK = BLOCK_LENGTH / LINE_WIDTH // 36\n\n/** Default maximum number of header lines to parse. */\nexport const DEFAULT_MAX_HEADER_LINES = 600\n\n/** FITS special integer value representing a NULL pixel in compressed images. */\nexport const NULL_VALUE = -2147483647\n\n/** FITS special integer value representing a 0.0 pixel in compressed images. */\nexport const ZERO_VALUE = -2147483646\n\n/** Number of random values in the dithering sequence. */\nexport const N_RANDOM = 10000\n\n/** Library version. */\nexport const VERSION = __VERSION__\n","/**\n * Base error class for all FITS-related errors.\n */\nexport class FITSError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'FITSError'\n }\n}\n\n/**\n * Error thrown during header parsing or validation.\n */\nexport class HeaderError extends FITSError {\n constructor(message: string) {\n super(message)\n this.name = 'HeaderError'\n }\n}\n\n/**\n * Error thrown during data unit reading or interpretation.\n */\nexport class DataError extends FITSError {\n constructor(message: string) {\n super(message)\n this.name = 'DataError'\n }\n}\n\n/**\n * Error thrown when decompression fails.\n */\nexport class DecompressionError extends FITSError {\n constructor(message: string) {\n super(message)\n this.name = 'DecompressionError'\n }\n}\n","import type { CardValue, ExtensionType, WarningCallback } from './types'\nimport { HeaderError } from './errors'\n\n/**\n * Context interface for verification functions — represents the header state\n * during parsing so verification functions can access current parse state.\n */\nexport interface VerifyContext {\n cardIndex: number\n primary: boolean\n extension: boolean\n extensionType?: ExtensionType\n warn: WarningCallback\n get(key: string): CardValue\n isPrimary(): boolean\n isExtension(): boolean\n}\n\nfunction verifyOrder(ctx: VerifyContext, keyword: string, order: number): void {\n if (order !== ctx.cardIndex) {\n ctx.warn(`${keyword} should appear at index ${order} in the FITS header`)\n }\n}\n\nfunction verifyBetween(keyword: string, value: number, lower: number, upper: number): void {\n if (value < lower || value > upper) {\n throw new HeaderError(`The ${keyword} value of ${value} is not between ${lower} and ${upper}`)\n }\n}\n\nfunction verifyBoolean(value: CardValue): boolean {\n return value === 'T' ? true : false\n}\n\n/**\n * Verification functions for reserved FITS header keywords.\n * Each function receives (ctx, value, isArray, index?) and returns the validated value.\n */\nexport const VerifyFns: Record<\n string,\n (ctx: VerifyContext, value: CardValue, isArray: boolean, index?: string) => CardValue\n> = {\n SIMPLE(ctx, value) {\n ctx.primary = true\n verifyOrder(ctx, 'SIMPLE', 0)\n return verifyBoolean(value)\n },\n\n XTENSION(ctx, value) {\n ctx.extension = true\n ctx.extensionType = value as ExtensionType\n verifyOrder(ctx, 'XTENSION', 0)\n return ctx.extensionType\n },\n\n BITPIX(ctx, value) {\n const v = parseInt(String(value), 10)\n verifyOrder(ctx, 'BITPIX', 1)\n if (![8, 16, 32, -32, -64].includes(v)) {\n throw new HeaderError(`BITPIX value ${v} is not permitted`)\n }\n return v\n },\n\n NAXIS(ctx, value, isArray) {\n const v = parseInt(String(value), 10)\n if (!isArray) {\n verifyOrder(ctx, 'NAXIS', 2)\n verifyBetween('NAXIS', v, 0, 999)\n if (ctx.isExtension()) {\n if (ctx.extensionType === 'TABLE' || ctx.extensionType === 'BINTABLE') {\n if (v !== 2) {\n throw new HeaderError(`NAXIS must be 2 for TABLE and BINTABLE extensions`)\n }\n }\n }\n }\n return v\n },\n\n PCOUNT(ctx, value) {\n const v = parseInt(String(value), 10)\n const naxis = ctx.get('NAXIS') as number\n const order = 1 + 1 + 1 + naxis\n verifyOrder(ctx, 'PCOUNT', order)\n if (ctx.isExtension()) {\n if (ctx.extensionType === 'IMAGE' || ctx.extensionType === 'TABLE') {\n if (v !== 0) {\n throw new HeaderError(`PCOUNT must be 0 for the ${ctx.extensionType} extensions`)\n }\n }\n }\n return v\n },\n\n GCOUNT(ctx, value) {\n const v = parseInt(String(value), 10)\n const naxis = ctx.get('NAXIS') as number\n const order = 1 + 1 + 1 + naxis + 1\n verifyOrder(ctx, 'GCOUNT', order)\n if (ctx.isExtension()) {\n if (\n ctx.extensionType === 'IMAGE' ||\n ctx.extensionType === 'TABLE' ||\n ctx.extensionType === 'BINTABLE'\n ) {\n if (v !== 1) {\n throw new HeaderError(`GCOUNT must be 1 for the ${ctx.extensionType} extensions`)\n }\n }\n }\n return v\n },\n\n EXTEND(ctx, value) {\n if (!ctx.isPrimary()) {\n throw new HeaderError('EXTEND must only appear in the primary header')\n }\n return verifyBoolean(value)\n },\n\n BSCALE(_ctx, value) {\n return parseFloat(String(value))\n },\n\n BZERO(_ctx, value) {\n return parseFloat(String(value))\n },\n\n BLANK(ctx, value) {\n const bitpix = ctx.get('BITPIX') as number\n if (bitpix <= 0) {\n ctx.warn(`BLANK is not to be used for BITPIX = ${bitpix}`)\n }\n return parseInt(String(value), 10)\n },\n\n DATAMIN(_ctx, value) {\n return parseFloat(String(value))\n },\n\n DATAMAX(_ctx, value) {\n return parseFloat(String(value))\n },\n\n EXTVER(_ctx, value) {\n return parseInt(String(value), 10)\n },\n\n EXTLEVEL(_ctx, value) {\n return parseInt(String(value), 10)\n },\n\n TFIELDS(_ctx, value) {\n const v = parseInt(String(value), 10)\n verifyBetween('TFIELDS', v, 0, 999)\n return v\n },\n\n TBCOL(ctx, value, _isArray, index) {\n const tfields = ctx.get('TFIELDS') as number\n if (index !== undefined) {\n verifyBetween('TBCOL', parseInt(index, 10), 0, tfields)\n }\n return value\n },\n\n ZIMAGE(_ctx, value) {\n return verifyBoolean(value)\n },\n\n ZCMPTYPE(_ctx, value) {\n const v = String(value)\n if (!['GZIP_1', 'RICE_1', 'PLIO_1', 'HCOMPRESS_1'].includes(v)) {\n throw new HeaderError(`ZCMPTYPE value ${v} is not permitted`)\n }\n if (!['RICE_1'].includes(v)) {\n throw new HeaderError(`Compress type ${v} is not yet implemented`)\n }\n return v\n },\n\n ZBITPIX(_ctx, value) {\n const v = parseInt(String(value), 10)\n if (![8, 16, 32, 64, -32, -64].includes(v)) {\n throw new HeaderError(`ZBITPIX value ${v} is not permitted`)\n }\n return v\n },\n\n ZNAXIS(_ctx, value, isArray) {\n const v = parseInt(String(value), 10)\n if (!isArray) {\n verifyBetween('ZNAXIS', v, 0, 999)\n }\n return v\n },\n\n ZTILE(_ctx, value) {\n return parseInt(String(value), 10)\n },\n\n ZSIMPLE(_ctx, value) {\n return value === 'T' ? true : false\n },\n\n ZPCOUNT(_ctx, value) {\n return parseInt(String(value), 10)\n },\n\n ZGCOUNT(_ctx, value) {\n return parseInt(String(value), 10)\n },\n\n ZDITHER0(_ctx, value) {\n return parseInt(String(value), 10)\n },\n}\n","import type { CardValue, HeaderCard, DataUnitType, ExtensionType, WarningCallback } from './types'\nimport { DEFAULT_MAX_HEADER_LINES } from './constants'\nimport { HeaderError } from './errors'\nimport { VerifyFns, type VerifyContext } from './header-verify'\n\n/**\n * Represents a parsed FITS header.\n *\n * A FITS header consists of 80-character card images containing\n * keyword = value / comment triplets.\n */\nexport class Header implements VerifyContext {\n private static readonly ARRAY_PATTERN = /(\\D+)(\\d+)/\n\n /** Whether this is a primary header (contains SIMPLE keyword). */\n primary = false\n /** Whether this is an extension header (contains XTENSION keyword). */\n extension = false\n /** The extension type if this is an extension header. */\n extensionType?: ExtensionType\n\n /** Storage for parsed header cards, keyed by keyword. */\n private cards: Map<string, HeaderCard> = new Map()\n /** Storage for COMMENT cards. */\n private comments: string[] = []\n /** Storage for HISTORY cards. */\n private history: string[] = []\n /** Running index of the current card being parsed. */\n cardIndex = 0\n\n /** Warning callback for non-fatal issues during parsing. */\n warn: WarningCallback\n\n /** Maximum number of header lines to parse. */\n private maxLines: number\n\n /** The raw header block string, preserved for reference. */\n readonly block: string\n\n constructor(\n block: string,\n maxLines: number = DEFAULT_MAX_HEADER_LINES,\n onWarning?: WarningCallback,\n ) {\n this.maxLines = maxLines\n this.warn = onWarning ?? console.warn\n this.block = block\n this.readBlock(block)\n }\n\n /**\n * Get the value for a header keyword.\n * Returns `null` if the keyword is not present.\n */\n get(key: string): CardValue {\n if (this.contains(key)) {\n return this.cards.get(key)!.value\n }\n return null\n }\n\n /**\n * Get a numeric value for a header keyword.\n * Returns the `fallback` (default `0`) if the keyword is missing.\n * Throws `HeaderError` if the value is present but not a number.\n */\n getNumber(key: string, fallback?: number): number {\n const value = this.get(key)\n if (value === null) return fallback ?? 0\n if (typeof value === 'number') return value\n throw new HeaderError(`Expected number for keyword ${key}, got ${typeof value}`)\n }\n\n /**\n * Get a string value for a header keyword.\n * Returns the `fallback` (default `''`) if the keyword is missing.\n * Throws `HeaderError` if the value is present but not a string.\n */\n getString(key: string, fallback?: string): string {\n const value = this.get(key)\n if (value === null) return fallback ?? ''\n if (typeof value === 'string') return value\n throw new HeaderError(`Expected string for keyword ${key}, got ${typeof value}`)\n }\n\n /**\n * Get a boolean value for a header keyword.\n * Returns the `fallback` (default `false`) if the keyword is missing.\n * Throws `HeaderError` if the value is present but not a boolean.\n */\n getBoolean(key: string, fallback?: boolean): boolean {\n const value = this.get(key)\n if (value === null) return fallback ?? false\n if (typeof value === 'boolean') return value\n throw new HeaderError(`Expected boolean for keyword ${key}, got ${typeof value}`)\n }\n\n /**\n * Set a keyword with a value and optional comment.\n */\n set(key: string, value: CardValue, comment: string = ''): void {\n this.cards.set(key, {\n index: this.cardIndex,\n value,\n comment,\n })\n this.cardIndex += 1\n }\n\n /**\n * Check if the header contains a specific keyword.\n */\n contains(key: string): boolean {\n return this.cards.has(key)\n }\n\n /**\n * Get all COMMENT card values.\n */\n getComments(): string[] {\n return this.comments\n }\n\n /**\n * Get all HISTORY card values.\n */\n getHistory(): string[] {\n return this.history\n }\n\n /**\n * Returns all keyword names in insertion order.\n */\n keys(): string[] {\n return Array.from(this.cards.keys())\n }\n\n /**\n * Determine if this header has an associated data unit based on NAXIS.\n */\n hasDataUnit(): boolean {\n const naxis = this.getNumber('NAXIS')\n if (naxis === 0) return false\n for (let i = 1; i <= naxis; i++) {\n if (this.getNumber(`NAXIS${i}`) !== 0) return true\n }\n return false\n }\n\n /**\n * Calculate the byte length of the associated data unit.\n */\n getDataLength(): number {\n if (!this.hasDataUnit()) {\n return 0\n }\n\n const naxis = this.getNumber('NAXIS')\n const naxisValues: number[] = []\n for (let i = 1; i <= naxis; i++) {\n naxisValues.push(this.getNumber(`NAXIS${i}`))\n }\n\n const bitpix = this.getNumber('BITPIX')\n let length = (naxisValues.reduce((a, b) => a * b, 1) * Math.abs(bitpix)) / 8\n length += this.getNumber('PCOUNT')\n\n return length\n }\n\n /**\n * Determine the data unit type from header keywords.\n */\n getDataType(): DataUnitType | null {\n switch (this.extensionType) {\n case 'BINTABLE':\n if (this.contains('ZIMAGE')) return 'CompressedImage'\n return 'BinaryTable'\n case 'TABLE':\n return 'Table'\n case 'IMAGE':\n if (this.hasDataUnit()) return 'Image'\n return null\n default:\n if (this.hasDataUnit()) return 'Image'\n return null\n }\n }\n\n /** Check if this is a primary header. */\n isPrimary(): boolean {\n return this.primary\n }\n\n /** Check if this is an extension header. */\n isExtension(): boolean {\n return this.extension\n }\n\n // --- Private parsing methods ---\n\n private readBlock(block: string): void {\n const lineWidth = 80\n const nLinesRaw = block.length / lineWidth\n const nLines = Math.min(nLinesRaw, this.maxLines)\n\n for (let i = 0; i < nLines; i++) {\n const line = block.slice(i * lineWidth, (i + 1) * lineWidth)\n this.readLine(line)\n }\n }\n\n private readLine(line: string): void {\n // Check bytes 1 to 8 for key or whitespace\n const key = line.slice(0, 8).trim()\n if (key === '') return\n\n // Get indicator and value portion\n const indicator = line.slice(8, 10)\n const rawValue = line.slice(10)\n\n // Check the indicator\n if (indicator !== '= ') {\n // Key will be either COMMENT, HISTORY, or END\n // For COMMENT/HISTORY, the value is everything after the keyword (pos 8)\n const fullValue = line.slice(8).trim()\n if (key === 'COMMENT') {\n this.comments.push(fullValue)\n } else if (key === 'HISTORY') {\n this.history.push(fullValue)\n }\n return\n }\n\n // Split value from comment (comment starts with ' /')\n // Must not match ' /' inside quoted string values\n let valueStr: string\n let comment: string\n if (rawValue.trimStart().startsWith(\"'\")) {\n // String value — find closing quote, skipping escaped quotes ('')\n const openQuote = rawValue.indexOf(\"'\")\n let closeQuote = -1\n let pos = openQuote + 1\n while (pos < rawValue.length) {\n const q = rawValue.indexOf(\"'\", pos)\n if (q === -1) break\n // Check if this is an escaped quote (followed by another quote)\n if (q + 1 < rawValue.length && rawValue[q + 1] === \"'\") {\n pos = q + 2 // Skip the escaped pair\n continue\n }\n closeQuote = q\n break\n }\n if (closeQuote !== -1) {\n const afterQuote = rawValue.slice(closeQuote + 1)\n const slashIdx = afterQuote.indexOf(' /')\n if (slashIdx !== -1) {\n valueStr = rawValue.slice(0, closeQuote + 1).trim()\n comment = afterQuote.slice(slashIdx + 2).trim()\n } else {\n valueStr = rawValue.slice(0, closeQuote + 1).trim()\n comment = ''\n }\n } else {\n valueStr = rawValue.trim()\n comment = ''\n }\n } else {\n const slashIdx = rawValue.indexOf(' /')\n if (slashIdx !== -1) {\n valueStr = rawValue.slice(0, slashIdx).trim()\n comment = rawValue.slice(slashIdx + 2).trim()\n } else {\n valueStr = rawValue.trim()\n comment = ''\n }\n }\n\n // Parse the value\n let value: CardValue\n if (valueStr.startsWith(\"'\")) {\n // String data type — strip surrounding quotes and unescape doubled quotes\n value = valueStr.slice(1, -1).replaceAll(\"''\", \"'\").trim()\n } else if (valueStr === 'T' || valueStr === 'F') {\n // Boolean — leave as string for verification functions to handle\n value = valueStr\n } else {\n // Numeric\n value = parseFloat(valueStr)\n }\n\n // Validate against reserved keyword rules\n value = this.validate(key, value)\n\n this.set(key, value, comment)\n }\n\n private validate(key: string, value: CardValue): CardValue {\n let baseKey = key\n let isArray = false\n let index: string | undefined\n\n const match = Header.ARRAY_PATTERN.exec(key)\n if (match) {\n isArray = true\n baseKey = match[1]!\n index = match[2]\n }\n\n if (baseKey in VerifyFns) {\n value = VerifyFns[baseKey]!(this, value, isArray, index)\n }\n\n return value\n }\n}\n","import type { Header } from './header'\nimport type { DataUnit } from './data-unit'\n\n/**\n * Header Data Unit — the fundamental building block of a FITS file.\n *\n * Each HDU contains a header and an optional data unit. The header\n * describes the structure and metadata of the data unit.\n */\nexport class HDU {\n readonly header: Header\n readonly data?: DataUnit\n\n constructor(header: Header, data?: DataUnit) {\n this.header = header\n this.data = data\n }\n\n /**\n * Check if this HDU has an associated data unit.\n */\n hasData(): boolean {\n return this.data !== undefined\n }\n}\n","import { BLOCK_LENGTH } from './constants'\n\n/**\n * Endian swap functions for converting big-endian data to host byte order.\n * FITS data is always stored in big-endian format.\n */\n/** 8-bit: no swap needed */\nconst swap8 = (value: number): number => value\n/** 16-bit endian swap */\nconst swap16 = (value: number): number => ((value & 0xff) << 8) | ((value >> 8) & 0xff)\n/** 32-bit endian swap */\nconst swap32 = (value: number): number =>\n ((value & 0xff) << 24) |\n ((value & 0xff00) << 8) |\n ((value >> 8) & 0xff00) |\n ((value >> 24) & 0xff)\n\nexport const swapEndian = {\n 8: swap8,\n B: swap8,\n 16: swap16,\n I: swap16,\n 32: swap32,\n J: swap32,\n} as Record<string | number, (value: number) => number>\n\n/** Shared TextDecoder instance for ASCII decoding. */\nconst textDecoder = new TextDecoder('ascii')\n\n/**\n * Convert a Uint8Array to a string (ASCII decoding).\n */\nexport function uint8ArrayToString(arr: Uint8Array): string {\n return textDecoder.decode(arr)\n}\n\n/**\n * Calculate the number of excess (padding) bytes needed to reach a FITS block boundary.\n */\nexport function excessBytes(length: number): number {\n return (BLOCK_LENGTH - (length % BLOCK_LENGTH)) % BLOCK_LENGTH\n}\n\n/**\n * Convert a byte to an array of 8 bits (MSB first).\n */\nexport function toBits(byte: number): number[] {\n const arr: number[] = []\n let i = 128\n while (i >= 1) {\n arr.push(byte & i ? 1 : 0)\n i >>= 1\n }\n return arr\n}\n","import { swapEndian } from './utils'\n\n/**\n * Base class for FITS data units (Image, BinaryTable, Table, CompressedImage).\n *\n * FITS data is always stored in big-endian format. This base class provides\n * shared infrastructure for endian swapping and buffer management.\n */\nexport class DataUnit {\n /** The ArrayBuffer containing raw data (available when loaded from buffer). */\n buffer?: ArrayBuffer\n /** The Blob containing raw data (available when loaded from file). */\n blob?: Blob\n\n /** Static endian swap functions keyed by type code or byte size. */\n static readonly swapEndian = swapEndian\n\n constructor(data: ArrayBuffer | Blob) {\n if (data instanceof ArrayBuffer) {\n this.buffer = data\n } else if (typeof Blob !== 'undefined' && data instanceof Blob) {\n this.blob = data\n }\n }\n}\n","import type { TypedArray } from './types'\n\n/**\n * Compute the minimum and maximum pixel values in a typed array,\n * ignoring NaN values.\n *\n * @returns A tuple [min, max], or [NaN, NaN] if all values are NaN.\n */\nexport function getExtent(arr: TypedArray | Float32Array): [number, number] {\n const len = arr.length\n let min: number | undefined\n let max: number | undefined\n let i = 0\n\n // Find first non-NaN value\n for (; i < len; i++) {\n const value = arr[i]!\n if (!isNaN(value)) {\n min = max = value\n i++\n break\n }\n }\n\n if (min === undefined || max === undefined) {\n return [NaN, NaN]\n }\n\n // Continue forward loop to find extent\n for (; i < len; i++) {\n const value = arr[i]!\n if (isNaN(value)) continue\n if (value < min) min = value\n else if (value > max) max = value\n }\n\n return [min, max]\n}\n\n/**\n * Get a single pixel value from a flat array given x, y coordinates and image width.\n */\nexport function getPixel(\n arr: TypedArray | Float32Array,\n x: number,\n y: number,\n width: number,\n): number {\n const index = y * width + x\n if (index < 0 || index >= arr.length) {\n return NaN\n }\n return arr[index]!\n}\n","import { DataUnit } from './data-unit'\nimport { getExtent, getPixel } from './image-utils'\nimport type { Header } from './header'\nimport type { TypedArray } from './types'\n\ninterface FrameOffset {\n begin: number\n buffers?: ArrayBuffer[]\n}\n\n/**\n * Represents a standard FITS image stored in the data unit of a FITS file.\n * Supports BITPIX values: 8, 16, 32, -32, -64\n * Supports data cubes (NAXIS > 2) with frame-by-frame reading.\n */\nexport class Image extends DataUnit {\n readonly bitpix: number\n readonly naxis: number[]\n readonly width: number\n readonly height: number\n readonly depth: number\n readonly bzero: number\n readonly bscale: number\n readonly bytes: number\n readonly length: number\n readonly frameLength: number\n readonly frameOffsets: FrameOffset[]\n\n constructor(header: Header, data: ArrayBuffer | Blob) {\n super(data)\n\n const naxisCount = header.getNumber('NAXIS')\n this.bitpix = header.getNumber('BITPIX')\n\n this.naxis = []\n for (let i = 1; i <= naxisCount; i++) {\n this.naxis.push(header.getNumber(`NAXIS${i}`))\n }\n\n this.width = header.getNumber('NAXIS1')\n this.height = header.getNumber('NAXIS2', 1)\n this.depth = header.getNumber('NAXIS3', 1)\n this.bzero = header.getNumber('BZERO')\n this.bscale = header.getNumber('BSCALE', 1)\n this.bytes = Math.abs(this.bitpix) / 8\n this.length = (this.naxis.reduce((a, b) => a * b, 1) * Math.abs(this.bitpix)) / 8\n\n this.frameOffsets = []\n this.frameLength = this.bytes * this.width * this.height\n\n for (let i = 0; i < this.depth; i++) {\n const begin = i * this.frameLength\n const info: FrameOffset = { begin }\n if (this.buffer) {\n info.buffers = [this.buffer.slice(begin, begin + this.frameLength)]\n }\n this.frameOffsets.push(info)\n }\n }\n\n /**\n * Convert raw buffer bytes into pixel values with endian handling and BZERO/BSCALE.\n */\n static computeFrame(\n buffer: ArrayBuffer,\n bitpix: number,\n bzero: number,\n bscale: number,\n ): TypedArray {\n const bytes = Math.abs(bitpix) / 8\n const nPixels = buffer.byteLength / bytes\n const identity = bzero === 0 && bscale === 1\n const view = new DataView(buffer)\n const needFloat = !(Number.isInteger(bzero) && Number.isInteger(bscale))\n\n if (bitpix === 8) {\n if (identity) return new Uint8Array(buffer.slice(0))\n const result = needFloat ? new Float32Array(nPixels) : new Int32Array(nPixels)\n for (let i = 0; i < nPixels; i++) {\n result[i] = bzero + bscale * view.getUint8(i)\n }\n return result\n }\n\n if (bitpix === 16) {\n if (identity) {\n const result = new Int16Array(nPixels)\n for (let i = 0; i < nPixels; i++) result[i] = view.getInt16(i * 2, false)\n return result\n }\n const result = needFloat ? new Float32Array(nPixels) : new Int32Array(nPixels)\n for (let i = 0; i < nPixels; i++) {\n result[i] = bzero + bscale * view.getInt16(i * 2, false)\n }\n return result\n }\n\n if (bitpix === 32) {\n if (identity) {\n const result = new Int32Array(nPixels)\n for (let i = 0; i < nPixels; i++) result[i] = view.getInt32(i * 4, false)\n return result\n }\n const result = new Float64Array(nPixels)\n for (let i = 0; i < nPixels; i++) {\n result[i] = bzero + bscale * view.getInt32(i * 4, false)\n }\n return result\n }\n\n if (bitpix === -32) {\n const result = new Float32Array(nPixels)\n if (identity) {\n for (let i = 0; i < nPixels; i++) result[i] = view.getFloat32(i * 4, false)\n } else {\n for (let i = 0; i < nPixels; i++) {\n result[i] = bzero + bscale * view.getFloat32(i * 4, false)\n }\n }\n return result\n }\n\n // bitpix === -64\n const result = new Float64Array(nPixels)\n if (identity) {\n for (let i = 0; i < nPixels; i++) result[i] = view.getFloat64(i * 8, false)\n } else {\n for (let i = 0; i < nPixels; i++) {\n result[i] = bzero + bscale * view.getFloat64(i * 8, false)\n }\n }\n return result\n }\n\n /**\n * Read a single frame from the image. For 2D images, frame is always 0.\n * For data cubes, frame selects the z-slice.\n *\n * @returns Promise resolving to pixel data as a typed array.\n */\n async getFrame(frame: number = 0): Promise<TypedArray> {\n const frameInfo = this.frameOffsets[frame]!\n\n if (frameInfo.buffers && frameInfo.buffers.length > 0) {\n return Image.computeFrame(frameInfo.buffers[0]!, this.bitpix, this.bzero, this.bscale)\n }\n\n // Read from blob\n if (!this.blob) {\n throw new Error('No data source available for this image frame')\n }\n\n const begin = frameInfo.begin\n const blobFrame = this.blob.slice(begin, begin + this.frameLength)\n const arrayBuffer = await blobFrame.arrayBuffer()\n\n // Cache the buffer for future access\n frameInfo.buffers = [arrayBuffer]\n\n return Image.computeFrame(arrayBuffer, this.bitpix, this.bzero, this.bscale)\n }\n\n /**\n * Read multiple sequential frames from a data cube.\n *\n * @param startFrame - First frame index to read.\n * @param count - Number of frames to read.\n * @returns Promise resolving to an array of typed arrays, one per frame.\n */\n async getFrames(startFrame: number, count: number): Promise<TypedArray[]> {\n const indices = Array.from({ length: count }, (_, i) => startFrame + i)\n return Promise.all(indices.map((i) => this.getFrame(i)))\n }\n\n /** Check if the image is a data cube (more than 2 axes). */\n isDataCube(): boolean {\n return this.naxis.length > 2\n }\n\n /**\n * Async iterator for frame-by-frame reading of data cubes.\n * Yields each frame sequentially from index 0 to depth-1.\n */\n async *[Symbol.asyncIterator](): AsyncIterableIterator<TypedArray> {\n for (let i = 0; i < this.depth; i++) {\n yield this.getFrame(i)\n }\n }\n\n /** Compute min/max pixel values of an array, ignoring NaN. */\n getExtent(arr: TypedArray): [number, number] {\n return getExtent(arr)\n }\n\n /** Get a single pixel value at (x, y) from a pixel array. */\n getPixel(arr: TypedArray, x: number, y: number): number {\n return getPixel(arr, x, y, this.width)\n }\n}\n","/**\n * FITS standard BITPIX values representing data types in image arrays.\n * Positive values are integer types, negative values are floating point.\n */\nexport type BitPix = 8 | 16 | 32 | -32 | -64\n\n/**\n * Extended BITPIX values used in compressed images (ZBITPIX).\n */\nexport type ZBitPix = 8 | 16 | 32 | 64 | -32 | -64\n\n/**\n * Possible value types stored in a FITS header card.\n */\nexport type CardValue = string | number | boolean | null\n\n/**\n * A single header card entry with its positional index, value, and optional comment.\n */\nexport interface HeaderCard {\n index: number\n value: CardValue\n comment: string\n}\n\n/**\n * Types of FITS data units.\n */\nexport type DataUnitType = 'Image' | 'BinaryTable' | 'Table' | 'CompressedImage'\n\n/**\n * FITS extension types as stored in the XTENSION keyword.\n */\nexport type ExtensionType = 'IMAGE' | 'BINTABLE' | 'TABLE'\n\n/**\n * Compression algorithms supported by the FITS tiled image convention.\n */\nexport type CompressionType = 'GZIP_1' | 'RICE_1' | 'PLIO_1' | 'HCOMPRESS_1'\n\n/**\n * Quantization methods for compressed images.\n */\nexport type QuantizationType = 'LINEAR_SCALING' | 'SUBTRACTIVE_DITHER_1' | 'SUBTRACTIVE_DITHER_2'\n\n/**\n * Binary table format type codes (single character descriptors).\n */\nexport type BinaryTableTypeCode =\n | 'L' // Logical\n | 'B' // Unsigned byte\n | 'I' // 16-bit integer\n | 'J' // 32-bit integer\n | 'K' // 64-bit integer\n | 'A' // Character\n | 'E' // Single-precision float\n | 'D' // Double-precision float\n | 'C' // Single-precision complex\n | 'M' // Double-precision complex\n | 'X' // Bit\n\n/**\n * ASCII table format type codes.\n */\nexport type AsciiTableTypeCode = 'A' | 'I' | 'F' | 'E' | 'D'\n\n/**\n * Byte sizes for each binary table type code.\n */\nexport const BINARY_TYPE_BYTE_SIZES: Record<string, number> = {\n L: 1,\n B: 1,\n I: 2,\n J: 4,\n K: 8,\n A: 1,\n E: 4,\n D: 8,\n C: 8,\n M: 16,\n}\n\n/**\n * A binary table accessor function reads a value from a DataView at the given offset\n * and returns the value plus the new offset.\n */\nexport type BinaryAccessor = (view: DataView, offset: number) => [value: unknown, newOffset: number]\n\n/**\n * An ASCII table accessor transforms a string value into the appropriate type.\n */\nexport type AsciiAccessor = (value: string) => CardValue\n\n/**\n * Typed array constructors mapped by binary type codes.\n */\nexport const TYPED_ARRAY_CONSTRUCTORS: Record<string, TypedArrayConstructor> = {\n B: Uint8Array,\n I: Int16Array,\n J: Int32Array,\n E: Float32Array,\n D: Float64Array,\n 1: Uint8Array,\n 2: Int16Array,\n 4: Int32Array,\n}\n\nexport type TypedArrayConstructor =\n | Uint8ArrayConstructor\n | Int8ArrayConstructor\n | Uint16ArrayConstructor\n | Int16ArrayConstructor\n | Uint32ArrayConstructor\n | Int32ArrayConstructor\n | Float32ArrayConstructor\n | Float64ArrayConstructor\n\nexport type TypedArray =\n | Uint8Array\n | Int8Array\n | Uint16Array\n | Int16Array\n | Uint32Array\n | Int32Array\n | Float32Array\n | Float64Array\n\n/**\n * Warning callback type for non-fatal issues during parsing.\n */\nexport type WarningCallback = (message: string) => void\n\n/**\n * Options for reading FITS data.\n */\nexport interface ReadOptions {\n /** Maximum number of header lines to parse (default: 600) */\n maxHeaderLines?: number\n /** Callback for non-fatal warnings during parsing (default: console.warn) */\n onWarning?: WarningCallback\n}\n\n/**\n * Options for fetching remote FITS files.\n */\nexport interface FetchOptions extends ReadOptions {\n /** Additional fetch options (headers, signal, etc.) */\n requestInit?: RequestInit\n}\n\n/**\n * Row data from a table, keyed by column name.\n */\nexport type TableRow = Record<string, unknown>\n\n/**\n * Compression algorithm parameters (e.g., BLOCKSIZE, BYTEPIX).\n */\nexport type AlgorithmParameters = Record<string, number>\n","import { DataUnit } from './data-unit'\nimport type { Header } from './header'\nimport type { BinaryAccessor, TableRow, TypedArray } from './types'\nimport { TYPED_ARRAY_CONSTRUCTORS } from './types'\n\n/**\n * Abstract base class for tabular FITS extensions (TABLE and BINTABLE).\n *\n * Handles shared logic for row/column access, buffer management,\n * and accessor setup. Derived classes must implement `setAccessors` and `_getRows`.\n */\nexport abstract class Tabular extends DataUnit {\n /** Maximum memory (bytes) to hold when reading from blob. */\n protected maxMemory = 1048576\n\n readonly rowByteSize: number\n readonly rows: number\n readonly cols: number\n readonly length: number\n readonly heapLength: number\n readonly columns: string[] | null\n\n /** Accessor functions for each column. */\n protected accessors: BinaryAccessor[] = []\n /** Type descriptor for each column. */\n protected descriptors: string[] = []\n /** Byte length of each column element. */\n protected elementByteLengths: number[] = []\n /** TTYPE values for each column (used by subclasses to identify column roles). */\n protected columnTypes: string[] = []\n\n /** Heap data for variable-length arrays. */\n heap?: ArrayBuffer\n\n /** Typed array constructor map (used by BinaryTable). */\n protected typedArray: Record<string, new (length: number | ArrayBuffer) => TypedArray> =\n TYPED_ARRAY_CONSTRUCTORS as Record<string, new (length: number | ArrayBuffer) => TypedArray>\n\n // For blob-based reading\n private firstRowInBuffer = 0\n private lastRowInBuffer = 0\n private nRowsInBuffer = 0\n private cachedBuffer?: ArrayBuffer\n\n constructor(header: Header, data: ArrayBuffer | Blob) {\n super(data)\n\n this.rowByteSize = header.getNumber('NAXIS1')\n this.rows = header.getNumber('NAXIS2')\n this.cols = header.getNumber('TFIELDS')\n\n this.length = this.rowByteSize * this.rows\n this.heapLength = header.getNumber('PCOUNT')\n this.columns = this.getColumns(header)\n\n if (this.buffer) {\n // Keep separate buffer for heap\n this.heap = this.buffer.slice(this.length, this.length + this.heapLength)\n } else {\n this.firstRowInBuffer = 0\n this.lastRowInBuffer = 0\n this.nRowsInBuffer = Math.floor(this.maxMemory / this.rowByteSize)\n }\n\n // NOTE: Do NOT call setAccessors here.\n // Subclass field initializers run after super() returns,\n // which would overwrite values set by setAccessors.\n // Subclasses must call this.initAccessors(header) at the end of their own constructor.\n }\n\n /**\n * Subclasses must call this at the end of their constructor.\n */\n protected initAccessors(header: Header): void {\n this.resetAccessors()\n this.setAccessors(header)\n }\n\n /**\n * Clear all accessor arrays before re-initialization.\n */\n private resetAccessors(): void {\n this.accessors = []\n this.descriptors = []\n this.elementByteLengths = []\n this.columnTypes = []\n }\n\n /**\n * Derived classes must set up accessor functions for each column.\n */\n protected abstract setAccessors(header: Header): void\n\n /**\n * Derived classes must implement row parsing from a buffer.\n */\n protected abstract _getRows(buffer: ArrayBuffer, nRows: number): TableRow[] | Float32Array\n\n /**\n * Check if the specified row range is currently in memory.\n */\n private rowsInMemory(firstRow: number, lastRow: number): boolean {\n if (this.buffer && !this.blob) return true\n if (this.cachedBuffer) {\n if (firstRow < this.firstRowInBuffer) return false\n if (lastRow > this.lastRowInBuffer) return false\n return true\n }\n return false\n }\n\n /**\n * Get column names from the header.\n */\n private getColumns(header: Header): string[] | null {\n const columns: string[] = []\n for (let i = 1; i <= this.cols; i++) {\n const key = `TTYPE${i}`\n if (!header.contains(key)) return null\n columns.push(header.getString(key))\n }\n return columns\n }\n\n /**\n * Read a range of rows from the table.\n *\n * @param row - Starting row index (0-based).\n * @param number_ - Number of rows to read.\n */\n async getRows(\n row: number,\n number_: number,\n ): Promise<TableRow[] | Float32Array | ArrayLike<number>> {\n if (this.rowsInMemory(row, row + number_)) {\n let buf: ArrayBuffer\n if (this.cachedBuffer) {\n const offsetInCache = (row - this.firstRowInBuffer) * this.rowByteSize\n buf = this.cachedBuffer.slice(offsetInCache, offsetInCache + number_ * this.rowByteSize)\n } else if (this.buffer) {\n const begin = row * this.rowByteSize\n const end = begin + number_ * this.rowByteSize\n buf = this.buffer.slice(begin, end)\n } else {\n throw new Error('No data source available')\n }\n return this._getRows(buf, number_) as TableRow[] | Float32Array\n }\n\n // Read from blob\n if (!this.blob) {\n throw new Error('No data source available')\n }\n\n const begin = row * this.rowByteSize\n const readRows = Math.max(this.nRowsInBuffer, number_)\n const end = begin + readRows * this.rowByteSize\n const blobSlice = this.blob.slice(begin, end)\n const arrayBuffer = await blobSlice.arrayBuffer()\n\n this.cachedBuffer = arrayBuffer\n this.firstRowInBuffer = row\n this.lastRowInBuffer = row + readRows\n\n return this._getRows(arrayBuffer, number_) as TableRow[] | Float32Array\n }\n\n /**\n * Read a table buffer for a range of rows.\n * Used internally for column-based reading from blob.\n */\n private async getTableBuffer(row: number, number_: number): Promise<ArrayBuffer> {\n const actualRows = Math.min(this.rows - row, number_)\n const begin = row * this.rowByteSize\n const end = begin + actualRows * this.rowByteSize\n\n if (this.buffer) {\n return this.buffer.slice(begin, end)\n }\n\n if (!this.blob) {\n throw new Error('No data source available')\n }\n\n const blobSlice = this.blob.slice(begin, end)\n return blobSlice.arrayBuffer()\n }\n\n /**\n * Read all values from a single column.\n *\n * @param name - Column name.\n * @returns Array of column values.\n */\n async getColumn(name: string): Promise<unknown[]> {\n if (!this.columns) {\n throw new Error('Column names not available')\n }\n\n const colIndex = this.columns.indexOf(name)\n if (colIndex === -1) {\n throw new Error(`Column \"${name}\" not found`)\n }\n\n if (this.buffer && !this.blob) {\n // Table already in memory — use getRows\n const rows = (await this.getRows(0, this.rows)) as TableRow[]\n return rows.map((d) => d[name])\n }\n\n // Read column from blob in chunks\n const descriptor = this.descriptors[colIndex]\n const accessor = this.accessors[colIndex]!\n const elementByteOffset = this.elementByteLengths.slice(0, colIndex).reduce((a, b) => a + b, 0)\n\n const TypedArrayCtor =\n descriptor && this.typedArray[descriptor] ? this.typedArray[descriptor]! : null\n\n const column: unknown[] = TypedArrayCtor\n ? Array.from(new TypedArrayCtor(this.rows))\n : new Array(this.rows)\n\n const rowsPerIteration = Math.min(\n Math.max(1, Math.floor(this.maxMemory / this.rowByteSize)),\n this.rows,\n )\n\n const factor = this.rows / rowsPerIteration\n let iterations = Math.floor(factor) === factor ? factor : Math.floor(factor) + 1\n let i = 0\n let chunkIndex = 0\n\n while (iterations > 0) {\n const startRow = chunkIndex * rowsPerIteration\n const buffer = await this.getTableBuffer(startRow, rowsPerIteration)\n const nRows = buffer.byteLength / this.rowByteSize\n const view = new DataView(buffer)\n let offset = elementByteOffset\n\n for (let r = 0; r < nRows; r++) {\n column[i] = accessor(view, offset)[0]\n i++\n offset += this.rowByteSize\n }\n\n iterations--\n chunkIndex++\n }\n\n return column\n }\n}\n","import { Tabular } from './tabular'\nimport type { Header } from './header'\nimport type { TableRow } from './types'\nimport { uint8ArrayToString } from './utils'\n\n/**\n * ASCII table accessor functions keyed by format code.\n */\nconst ASCII_ACCESSORS: Record<string, (value: string) => string | number> = {\n A: (value: string) => value.trim(),\n I: (value: string) => parseInt(value, 10),\n F: (value: string) => parseFloat(value),\n E: (value: string) => parseFloat(value),\n D: (value: string) => parseFloat(value),\n}\n\n/**\n * Reads ASCII tables from FITS files (XTENSION = 'TABLE').\n *\n * ASCII tables store data as fixed-width text fields where each row\n * is a sequence of ASCII characters.\n */\nexport class Table extends Tabular {\n private asciiAccessors: ((value: string) => string | number)[] = []\n /** 0-based start positions for each column within a row. */\n private colStarts: number[] = []\n /** Character widths for each column. */\n private colWidths: number[] = []\n /** Whether TBCOL keywords were found in the header. */\n private hasTBCOL = false\n\n constructor(header: Header, data: ArrayBuffer | Blob) {\n super(header, data)\n this.initAccessors(header)\n }\n\n protected setAccessors(header: Header): void {\n this.asciiAccessors = []\n this.colStarts = []\n this.colWidths = []\n this.hasTBCOL = false\n const pattern = /([AIFED])(\\d+)\\.*(\\d+)*/\n\n // First pass: check if any TBCOL keywords exist\n for (let i = 1; i <= this.cols; i++) {\n if (header.contains(`TBCOL${i}`)) {\n this.hasTBCOL = true\n break\n }\n }\n\n for (let i = 1; i <= this.cols; i++) {\n const form = header.getString(`TFORM${i}`)\n const match = pattern.exec(form)\n if (!match) {\n this.asciiAccessors.push((v: string) => v.trim())\n this.colStarts.push(0)\n this.colWidths.push(0)\n continue\n }\n\n const descriptor = match[1]!\n const width = parseInt(match[2]!, 10)\n const fn = ASCII_ACCESSORS[descriptor] ?? ((v: string) => v.trim())\n this.asciiAccessors.push(fn)\n\n // TBCOL is 1-based per FITS standard\n const tbcol = header.contains(`TBCOL${i}`) ? header.getNumber(`TBCOL${i}`) - 1 : 0\n this.colStarts.push(tbcol)\n this.colWidths.push(width)\n }\n }\n\n protected override _getRows(buffer: ArrayBuffer, _nRows?: number): TableRow[] {\n const nRows = buffer.byteLength / this.rowByteSize\n const arr = new Uint8Array(buffer)\n const rows: TableRow[] = []\n const accessors = this.asciiAccessors ?? []\n\n for (let i = 0; i < nRows; i++) {\n const begin = i * this.rowByteSize\n const end = begin + this.rowByteSize\n const subarray = arr.subarray(begin, end)\n const line = uint8ArrayToString(subarray)\n\n const row: TableRow = {}\n if (this.hasTBCOL) {\n // Fixed-width extraction using TBCOL positions\n for (let j = 0; j < accessors.length; j++) {\n const start = this.colStarts[j]!\n const width = this.colWidths[j]!\n const value = line.substring(start, start + width).trim()\n if (this.columns) {\n row[this.columns[j]!] = accessors[j]!(value)\n }\n }\n } else {\n // Fallback: whitespace splitting (when TBCOL is not available)\n const fields = line.trim().split(/\\s+/)\n for (let j = 0; j < accessors.length; j++) {\n const value = fields[j] ?? ''\n if (this.columns) {\n row[this.columns[j]!] = accessors[j]!(value)\n }\n }\n }\n rows.push(row)\n }\n\n return rows\n }\n}\n","import { Tabular } from './tabular'\nimport { DecompressionError } from './errors'\nimport type { Header } from './header'\nimport type { BinaryAccessor, TableRow, TypedArray } from './types'\nimport { BINARY_TYPE_BYTE_SIZES, TYPED_ARRAY_CONSTRUCTORS } from './types'\nimport { swapEndian, toBits } from './utils'\n\n/**\n * Binary table data accessor functions keyed by type code.\n * Each returns [value, newOffset].\n */\nconst DATA_ACCESSORS: Record<string, (view: DataView, offset: number) => [unknown, number]> = {\n L(view, offset) {\n const x = view.getInt8(offset)\n return [x === 84, offset + 1]\n },\n B(view, offset) {\n return [view.getUint8(offset), offset + 1]\n },\n I(view, offset) {\n return [view.getInt16(offset, false), offset + 2]\n },\n J(view, offset) {\n return [view.getInt32(offset, false), offset + 4]\n },\n K(view, offset) {\n const val = view.getBigInt64(offset, false)\n return [Number(val), offset + 8]\n },\n A(view, offset) {\n const val = String.fromCharCode(view.getUint8(offset))\n return [val, offset + 1]\n },\n E(view, offset) {\n return [view.getFloat32(offset, false), offset + 4]\n },\n D(view, offset) {\n return [view.getFloat64(offset, false), offset + 8]\n },\n C(view, offset) {\n const val1 = view.getFloat32(offset, false)\n const val2 = view.getFloat32(offset + 4, false)\n return [[val1, val2], offset + 8]\n },\n M(view, offset) {\n const val1 = view.getFloat64(offset, false)\n const val2 = view.getFloat64(offset + 8, false)\n return [[val1, val2], offset + 16]\n },\n}\n\n/**\n * Reads binary tables from FITS files (XTENSION = 'BINTABLE').\n *\n * Binary tables support a rich set of data types including logical,\n * integer, float, complex, character, bit arrays, and variable-length\n * array descriptors pointing to a heap area.\n */\nexport class BinaryTable extends Tabular {\n constructor(header: Header, data: ArrayBuffer | Blob) {\n super(header, data)\n this.initAccessors(header)\n }\n\n protected setAccessors(header: Header): void {\n const pattern = /(\\d*)([PQ]*)([LXBIJKAEDCM])$/\n\n for (let i = 1; i <= this.cols; i++) {\n const form = header.getString(`TFORM${i}`)\n const type = header.getString(`TTYPE${i}`)\n const match = pattern.exec(form)\n if (!match) {\n throw new Error(`Unsupported or invalid TFORM${i} value: '${form}'`)\n }\n\n const count = parseInt(match[1]!, 10) || 1\n const isArray = match[2]!\n const descriptor = match[3]!\n\n this.descriptors.push(descriptor)\n this.columnTypes.push(type)\n this.elementByteLengths.push((BINARY_TYPE_BYTE_SIZES[descriptor] ?? 1) * count)\n\n if (isArray) {\n this.setupArrayAccessor(descriptor, type)\n } else if (count === 1) {\n this.setupSingleAccessor(descriptor)\n } else if (descriptor === 'X') {\n this.setupBitArrayAccessor(count)\n } else if (descriptor === 'A') {\n this.setupCharArrayAccessor(count)\n } else {\n this.setupMultiAccessor(descriptor, count)\n }\n }\n }\n\n /**\n * Read data from the heap area following the main table data.\n */\n protected getFromHeap(view: DataView, offset: number, descriptor: string): [TypedArray, number] {\n const length = view.getInt32(offset, false)\n offset += 4\n const heapOffset = view.getInt32(offset, false)\n offset += 4\n\n if (!this.heap) {\n throw new Error('Heap not available')\n }\n\n const bytesPerElement = BINARY_TYPE_BYTE_SIZES[descriptor] ?? 1\n const heapSlice = this.heap.slice(heapOffset, heapOffset + length * bytesPerElement)\n const Ctor = TYPED_ARRAY_CONSTRUCTORS[descriptor]\n if (!Ctor) {\n throw new Error(`No typed array constructor for descriptor: ${descriptor}`)\n }\n\n const arr = new Ctor(heapSlice) as TypedArray\n\n // Endian swap (byte arrays don't need swapping)\n const swapFn = swapEndian[descriptor]\n if (swapFn && descriptor !== 'B') {\n for (let j = 0; j < arr.length; j++) {\n ;(arr as Int32Array)[j] = swapFn(arr[j]!) as number\n }\n }\n\n return [arr, offset]\n }\n\n private setupArrayAccessor(descriptor: string, type: string): void {\n if (type === 'COMPRESSED_DATA') {\n const accessor: BinaryAccessor = (view, offset) => {\n const [arr, newOffset] = this.getFromHeap(view, offset, descriptor)\n // Rice decompression is handled by CompressedImage subclass\n return [arr, newOffset]\n }\n this.accessors.push(accessor)\n } else if (type === 'GZIP_COMPRESSED_DATA') {\n const accessor: BinaryAccessor = (_view, _offset) => {\n throw new DecompressionError('GZIP decompression is not yet implemented')\n }\n this.accessors.push(accessor)\n } else {\n const accessor: BinaryAccessor = (view, offset) => {\n return this.getFromHeap(view, offset, descriptor)\n }\n this.accessors.push(accessor)\n }\n }\n\n private setupSingleAccessor(descriptor: string): void {\n const dataAccessor = DATA_ACCESSORS[descriptor]\n if (!dataAccessor) {\n throw new Error(`Unknown binary table type code: ${descriptor}`)\n }\n const accessor: BinaryAccessor = (view, offset) => {\n return dataAccessor(view, offset)\n }\n this.accessors.push(accessor)\n }\n\n private setupBitArrayAccessor(count: number): void {\n const nBytes = Math.ceil(count / 8)\n const accessor: BinaryAccessor = (view, offset) => {\n const buffer = view.buffer.slice(offset, offset + nBytes)\n const bytes = new Uint8Array(buffer)\n let bits: number[] = []\n for (let b = 0; b < bytes.length; b++) {\n bits = bits.concat(toBits(bytes[b]!))\n }\n return [bits.slice(0, count), offset + nBytes]\n }\n this.accessors.push(accessor)\n }\n\n private setupCharArrayAccessor(count: number): void {\n const accessor: BinaryAccessor = (view, offset) => {\n const buffer = view.buffer.slice(offset, offset + count)\n const arr = new Uint8Array(buffer)\n let s = ''\n for (let c = 0; c < arr.length; c++) {\n s += String.fromCharCode(arr[c]!)\n }\n return [s.trim(), offset + count]\n }\n this.accessors.push(accessor)\n }\n\n private setupMultiAccessor(descriptor: string, count: number): void {\n const dataAccessor = DATA_ACCESSORS[descriptor]\n if (!dataAccessor) {\n throw new Error(`Unknown binary table type code: ${descriptor}`)\n }\n const accessor: BinaryAccessor = (view, offset) => {\n const data: unknown[] = []\n let off = offset\n for (let c = 0; c < count; c++) {\n const [value, newOff] = dataAccessor(view, off)\n data.push(value)\n off = newOff\n }\n return [data, off]\n }\n this.accessors.push(accessor)\n }\n\n protected override _getRows(buffer: ArrayBuffer, nRows: number): TableRow[] | Float32Array {\n const view = new DataView(buffer)\n let offset = 0\n const rows: TableRow[] = []\n\n for (let r = 0; r < nRows; r++) {\n const row: TableRow = {}\n for (let c = 0; c < this.accessors.length; c++) {\n const [value, newOffset] = this.accessors[c]!(view, offset)\n offset = newOffset\n if (this.columns) {\n row[this.columns[c]!] = value\n }\n }\n rows.push(row)\n }\n\n return rows\n }\n}\n\nexport { DATA_ACCESSORS }\n","import type { TypedArray } from './types'\n\n/**\n * Setup functions for Rice decompression, keyed by bytepix (1, 2, or 4).\n * Each returns [fsbits, fsmax, lastpix, pointer].\n */\nexport const RiceSetup: Record<number, (array: Uint8Array) => [number, number, number, number]> = {\n 1(array) {\n const pointer = 1\n const fsbits = 3\n const fsmax = 6\n const lastpix = array[0]!\n return [fsbits, fsmax, lastpix, pointer]\n },\n\n 2(array) {\n const pointer = 2\n const fsbits = 4\n const fsmax = 14\n let lastpix = 0\n lastpix = lastpix | (array[0]! << 8)\n lastpix = lastpix | array[1]!\n return [fsbits, fsmax, lastpix, pointer]\n },\n\n 4(array) {\n const pointer = 4\n const fsbits = 5\n const fsmax = 25\n let lastpix = 0\n lastpix = lastpix | (array[0]! << 24)\n lastpix = lastpix | (array[1]! << 16)\n lastpix = lastpix | (array[2]! << 8)\n lastpix = lastpix | array[3]!\n return [fsbits, fsmax, lastpix, pointer]\n },\n}\n\n/**\n * Rice decompression algorithm.\n *\n * Decompresses a byte array that was compressed using the Rice algorithm,\n * as defined in the FITS tiled image compression convention.\n *\n * @param array - Compressed byte array.\n * @param blocksize - Number of pixels encoded in a block.\n * @param bytepix - Number of bytes per original pixel (1, 2, or 4).\n * @param pixels - Output array to fill with decompressed values.\n * @param nx - Number of output pixels (tile length).\n * @param setup - Setup function map (default: RiceSetup).\n * @returns The filled pixels array.\n */\nexport function riceDecompress(\n array: Uint8Array,\n blocksize: number,\n bytepix: number,\n pixels: TypedArray,\n nx: number,\n setup: Record<number, (array: Uint8Array) => [number, number, number, number]> = RiceSetup,\n): TypedArray {\n const setupFn = setup[bytepix]\n if (!setupFn) {\n throw new Error(`Unsupported bytepix value: ${bytepix}`)\n }\n\n const [fsbits, fsmax, initialLastpix, initialPointer] = setupFn(array)\n let lastpix = initialLastpix\n let pointer = initialPointer\n\n const bbits = 1 << fsbits\n\n // Build non-zero count lookup table\n const nonzeroCount = new Uint8Array(256)\n let nzero = 8\n let k = 128\n let idx = 255\n while (idx >= 0) {\n while (idx >= k) {\n nonzeroCount[idx] = nzero\n idx--\n }\n k = k / 2\n nzero--\n }\n nonzeroCount[0] = 0\n\n // Bit buffer\n let b = array[pointer++]!\n let nbits = 8\n\n let i = 0\n while (i < nx) {\n nbits -= fsbits\n\n while (nbits < 0) {\n b = (b << 8) | array[pointer++]!\n nbits += 8\n }\n\n const fs = (b >> nbits) - 1\n b &= (1 << nbits) - 1\n\n let imax = i + blocksize\n if (imax > nx) imax = nx\n\n if (fs < 0) {\n // All pixels in block have same value\n while (i < imax) {\n ;(pixels as Int32Array)[i] = lastpix\n i++\n }\n } else if (fs === fsmax) {\n // Uncompressed block\n while (i < imax) {\n k = bbits - nbits\n let diff = b << k\n k -= 8\n while (k >= 0) {\n b = array[pointer++]!\n diff |= b << k\n k -= 8\n }\n if (nbits > 0) {\n b = array[pointer++]!\n diff |= b >> -k\n b &= (1 << nbits) - 1\n } else {\n b = 0\n }\n if ((diff & 1) === 0) {\n diff = diff >> 1\n } else {\n diff = ~(diff >> 1)\n }\n ;(pixels as Int32Array)[i] = diff + lastpix\n lastpix = (pixels as Int32Array)[i]!\n i++\n }\n } else {\n // Normal compressed block\n while (i < imax) {\n while (b === 0) {\n nbits += 8\n b = array[pointer++]!\n }\n nzero = nbits - nonzeroCount[b]!\n nbits -= nzero + 1\n b ^= 1 << nbits\n nbits -= fs\n while (nbits < 0) {\n b = (b << 8) | array[pointer++]!\n nbits += 8\n }\n let diff = (nzero << fs) | (b >> nbits)\n b &= (1 << nbits) - 1\n if ((diff & 1) === 0) {\n diff = diff >> 1\n } else {\n diff = ~(diff >> 1)\n }\n ;(pixels as Int32Array)[i] = diff + lastpix\n lastpix = (pixels as Int32Array)[i]!\n i++\n }\n }\n }\n\n return pixels\n}\n","import { BinaryTable } from './binary-table'\nimport { getExtent, getPixel } from './image-utils'\nimport { riceDecompress, RiceSetup } from './decompress'\nimport { N_RANDOM, NULL_VALUE, ZERO_VALUE } from './constants'\nimport { DecompressionError } from './errors'\nimport { TYPED_ARRAY_CONSTRUCTORS } from './types'\nimport type { Header } from './header'\nimport type { TableRow, TypedArray, AlgorithmParameters } from './types'\n\n/**\n * Predefined random number generator from the FITS tiled image compression standard.\n * This is the same method used by fpack when dithering images during compression.\n * See: http://arxiv.org/pdf/1201.1336v1.pdf\n */\nfunction generateRandomSequence(): Float32Array {\n const a = 16807\n const m = 2147483647\n let seed = 1\n\n const random = new Float32Array(N_RANDOM)\n for (let i = 0; i < N_RANDOM; i++) {\n const temp = a * seed\n seed = temp - m * Math.floor(temp / m)\n random[i] = seed / m\n }\n return random\n}\n\n/** Pre-computed random dithering sequence. */\nconst RANDOM_SEQUENCE = generateRandomSequence()\n\n/**\n * Reads Rice-compressed FITS images stored as binary tables.\n *\n * Compressed images are stored in BINTABLE extensions with ZIMAGE=T.\n * Each row in the table represents one tile of the image.\n * This class decompresses tiles and reconstructs the full image,\n * applying subtractive dithering when appropriate.\n */\nexport class CompressedImage extends BinaryTable {\n readonly zcmptype: string\n readonly zbitpix: number\n readonly znaxis: number\n readonly zblank: number | null\n readonly blank: number | null\n readonly zdither: number\n readonly ztile: number[]\n readonly width: number\n readonly height: number\n readonly bzero: number\n readonly bscale: number\n readonly algorithmParameters: AlgorithmParameters\n readonly zquantiz: string\n\n constructor(header: Header, data: ArrayBuffer | Blob) {\n super(header, data)\n\n this.zcmptype = header.getString('ZCMPTYPE')\n this.zbitpix = header.getNumber('ZBITPIX')\n this.znaxis = header.getNumber('ZNAXIS')\n this.zblank = header.contains('ZBLANK') ? header.getNumber('ZBLANK') : null\n this.blank = header.contains('BLANK') ? header.getNumber('BLANK') : null\n this.zdither = header.getNumber('ZDITHER0')\n\n this.ztile = []\n for (let i = 1; i <= this.znaxis; i++) {\n const ztile = header.contains(`ZTILE${i}`)\n ? header.getNumber(`ZTILE${i}`)\n : i === 1\n ? header.getNumber('ZNAXIS1')\n : 1\n this.ztile.push(ztile)\n }\n\n this.width = header.getNumber('ZNAXIS1')\n this.height = header.getNumber('ZNAXIS2', 1)\n\n // Set default compression parameters\n this.algorithmParameters = {}\n if (this.zcmptype === 'RICE_1') {\n this.algorithmParameters['BLOCKSIZE'] = 32\n this.algorithmParameters['BYTEPIX'] = 4\n }\n\n // Override with header-specified parameters\n let paramIdx = 1\n while (header.contains(`ZNAME${paramIdx}`)) {\n const name = header.getString(`ZNAME${paramIdx}`)\n const value = header.getNumber(`ZVAL${paramIdx}`)\n this.algorithmParameters[name] = value\n paramIdx++\n }\n\n this.zquantiz = header.getString('ZQUANTIZ', 'LINEAR_SCALING')\n this.bzero = header.getNumber('BZERO')\n this.bscale = header.getNumber('BSCALE', 1)\n\n // Re-initialize accessors now that CompressedImage fields are set.\n // BinaryTable.constructor already called initAccessors, but CompressedImage\n // overrides setAccessors and needs its own fields (width, algorithmParameters, etc.)\n // to be initialized first.\n this.initAccessors(header)\n }\n\n /**\n * Override setAccessors to replace compressed data column accessors\n * with decompression-aware versions. Delegates base TFORM parsing to BinaryTable.\n */\n protected override setAccessors(header: Header): void {\n // Let BinaryTable handle all the TFORM parsing and standard accessor setup\n super.setAccessors(header)\n\n // Now replace accessors for compressed columns\n for (let c = 0; c < this.columnTypes.length; c++) {\n const type = this.columnTypes[c]\n const descriptor = this.descriptors[c]!\n\n if (type === 'COMPRESSED_DATA') {\n this.accessors[c] = (view, offset) => {\n const [arr, newOffset] = this.getFromHeap(view, offset, descriptor)\n\n // Rice decompression\n const bytepix = this.algorithmParameters['BYTEPIX'] ?? 4\n const blocksize = this.algorithmParameters['BLOCKSIZE'] ?? 32\n const Ctor = TYPED_ARRAY_CONSTRUCTORS[bytepix]\n if (!Ctor) {\n throw new Error(`No typed array for bytepix: ${bytepix}`)\n }\n const tileSize = this.ztile[0] ?? this.width\n const pixels = new Ctor(tileSize) as TypedArray\n riceDecompress(arr as Uint8Array, blocksize, bytepix, pixels, tileSize, RiceSetup)\n return [pixels, newOffset]\n }\n } else if (type === 'GZIP_COMPRESSED_DATA') {\n this.accessors[c] = (_view, _offset) => {\n throw new DecompressionError('GZIP decompression is not yet implemented')\n }\n }\n }\n }\n\n /**\n * Override _getRows to handle compressed image tile decompression\n * and subtractive dithering.\n */\n protected override _getRows(buffer: ArrayBuffer, nRows: number): Float32Array {\n const view = new DataView(buffer)\n let offset = 0\n const arr = new Float32Array(this.width * this.height)\n\n let tileIndex = 0\n let rowsRemaining = nRows\n while (rowsRemaining--) {\n tileIndex++\n const row: TableRow = {}\n for (let c = 0; c < this.accessors.length; c++) {\n const [value, newOffset] = this.accessors[c]!(view, offset)\n offset = newOffset\n if (this.columns) {\n row[this.columns[c]!] = value\n }\n }\n\n // Get compressed data and scaling parameters\n const data = (row['COMPRESSED_DATA'] ||\n row['UNCOMPRESSED_DATA'] ||\n row['GZIP_COMPRESSED_DATA']) as Int32Array | Float32Array\n const scale = (row['ZSCALE'] as number) || this.bscale\n const zero = (row['ZZERO'] as number) || this.bzero\n\n // Tile number (1-based)\n const nTile = tileIndex\n\n // Dequantize each pixel in the tile\n const useDither =\n this.zquantiz === 'SUBTRACTIVE_DITHER_1' || this.zquantiz === 'SUBTRACTIVE_DITHER_2'\n\n // Subtractive dithering setup (only when dithering is enabled)\n let rIndex = 0\n let seed1 = 0\n if (useDither) {\n const seed0 = nTile + this.zdither - 1\n const seed1Initial = (seed0 - 1) % N_RANDOM\n seed1 = seed1Initial < 0 ? seed1Initial + N_RANDOM : seed1Initial\n rIndex = Math.floor(RANDOM_SEQUENCE[seed1]! * 500)\n }\n\n for (let idx = 0; idx < data.length; idx++) {\n const pixelIndex = (nTile - 1) * this.width + idx\n const value = data[idx]!\n\n if (value === NULL_VALUE) {\n arr[pixelIndex] = NaN\n } else if (value === ZERO_VALUE) {\n arr[pixelIndex] = 0\n } else if (useDither) {\n const r = RANDOM_SEQUENCE[rIndex]!\n arr[pixelIndex] = (value - r + 0.5) * scale + zero\n } else {\n arr[pixelIndex] = value * scale + zero\n }\n\n // Update random index (only when dithering)\n if (useDither) {\n rIndex++\n if (rIndex === N_RANDOM) {\n seed1 = (seed1 + 1) % N_RANDOM\n rIndex = Math.floor(RANDOM_SEQUENCE[seed1]! * 500)\n }\n }\n }\n }\n\n return arr\n }\n\n /**\n * Read a frame from the compressed image.\n * Exposes the same API as Image.getFrame() for consistency.\n */\n async getFrame(_nFrame: number = 0): Promise<Float32Array> {\n if (this.heap) {\n const result = await this.getRows(0, this.rows)\n return result as Float32Array\n }\n\n // Need to read heap from blob first\n if (!this.blob) {\n throw new Error('No data source available')\n }\n\n const heapBlob = this.blob.slice(this.length, this.length + this.heapLength)\n this.heap = await heapBlob.arrayBuffer()\n\n return this.getFrame(_nFrame)\n }\n\n /** Compute min/max pixel values, ignoring NaN. */\n getExtent(arr: Float32Array): [number, number] {\n return getExtent(arr)\n }\n\n /** Get a single pixel value at (x, y). */\n getPixel(arr: Float32Array, x: number, y: number): number {\n return getPixel(arr, x, y, this.width)\n }\n}\n","import { BLOCK_LENGTH, LINE_WIDTH } from './constants'\nimport { Header } from './header'\nimport { HDU } from './hdu'\nimport { Image } from './image'\nimport { Table } from './table'\nimport { BinaryTable } from './binary-table'\nimport { CompressedImage } from './compressed-image'\nimport { excessBytes, uint8ArrayToString } from './utils'\nimport type { DataUnit } from './data-unit'\nimport type { DataUnitType, ReadOptions } from './types'\n\n/**\n * Data unit factory: creates the appropriate data unit subclass based on header info.\n */\nfunction createDataUnit(header: Header, data: ArrayBuffer | Blob): DataUnit | undefined {\n const type: DataUnitType | null = header.getDataType()\n if (!type) return undefined\n\n switch (type) {\n case 'Image':\n return new Image(header, data)\n case 'BinaryTable':\n return new BinaryTable(header, data)\n case 'Table':\n return new Table(header, data)\n case 'CompressedImage':\n return new CompressedImage(header, data)\n default:\n return undefined\n }\n}\n\n/**\n * Parse a FITS file from an ArrayBuffer.\n *\n * Reads 2880-byte blocks sequentially, looking for the END keyword\n * to delimit headers. After each header, the corresponding data unit\n * is sliced from the buffer and an HDU is created.\n *\n * @param buffer - The complete FITS file as an ArrayBuffer.\n * @returns Array of parsed HDUs.\n */\nexport function parseBuffer(buffer: ArrayBuffer, options?: ReadOptions): HDU[] {\n const hdus: HDU[] = []\n const totalLength = buffer.byteLength\n let offset = 0\n\n while (offset < totalLength) {\n // --- Read header blocks ---\n let blockCount = 0\n let headerStorage = new Uint8Array(0)\n let headerFound = false\n\n while (!headerFound && offset + blockCount * BLOCK_LENGTH + BLOCK_LENGTH <= totalLength) {\n const blockStart = offset + blockCount * BLOCK_LENGTH\n const blockBytes = new Uint8Array(buffer, blockStart, BLOCK_LENGTH)\n\n // Expand header storage\n const newStorage = new Uint8Array(headerStorage.length + BLOCK_LENGTH)\n newStorage.set(headerStorage, 0)\n newStorage.set(blockBytes, headerStorage.length)\n headerStorage = newStorage\n\n // Check block for END keyword (scanning rows bottom-up)\n const rows = BLOCK_LENGTH / LINE_WIDTH\n for (let row = rows - 1; row >= 0; row--) {\n const rowIndex = row * LINE_WIDTH\n const b = blockBytes[rowIndex]!\n\n // Skip whitespace rows\n if (b === 32) continue\n\n // Check for 'E' 'N' 'D' ' ' (69, 78, 68, 32)\n if (\n b === 69 &&\n blockBytes[rowIndex + 1] === 78 &&\n blockBytes[rowIndex + 2] === 68 &&\n blockBytes[rowIndex + 3] === 32\n ) {\n headerFound = true\n break\n }\n\n // If we hit a non-whitespace, non-END row, stop checking this block\n break\n }\n\n blockCount++\n\n if (!headerFound) {\n continue\n }\n\n // Parse header string\n const headerString = uint8ArrayToString(headerStorage)\n const header = new Header(headerString, options?.maxHeaderLines, options?.onWarning)\n\n // Calculate data unit position\n const headerEnd = offset + blockCount * BLOCK_LENGTH\n const dataLength = header.getDataLength()\n\n // Slice data unit bytes\n const dataSlice = buffer.slice(headerEnd, headerEnd + dataLength)\n\n // Create data unit if header indicates one\n let dataunit: DataUnit | undefined\n if (header.hasDataUnit()) {\n dataunit = createDataUnit(header, dataSlice)\n }\n\n // Store HDU\n hdus.push(new HDU(header, dataunit))\n\n // Advance offset past header + data + padding\n offset = headerEnd + dataLength + excessBytes(dataLength)\n\n // If we've reached the end of the file, stop\n if (offset >= totalLength) {\n break\n }\n }\n\n // Safety: if header was not found, break to avoid infinite loop\n if (!headerFound) {\n break\n }\n }\n\n return hdus\n}\n\n/**\n * Parse a FITS file from a Blob (File object) using streaming block reads.\n *\n * Reads header blocks incrementally (2880 bytes at a time) without loading\n * the entire file into memory. Data units are kept as Blob slices for\n * lazy on-demand reading, significantly reducing memory usage for large files.\n *\n * @param blob - The FITS file as a Blob or File object.\n * @returns Promise resolving to an array of parsed HDUs.\n */\nexport async function parseBlob(blob: Blob, options?: ReadOptions): Promise<HDU[]> {\n const hdus: HDU[] = []\n const totalLength = blob.size\n let offset = 0\n\n while (offset < totalLength) {\n // --- Read header blocks incrementally ---\n let blockCount = 0\n const headerChunks: Uint8Array[] = []\n let headerFound = false\n\n while (!headerFound && offset + blockCount * BLOCK_LENGTH + BLOCK_LENGTH <= totalLength) {\n const blockStart = offset + blockCount * BLOCK_LENGTH\n const blockBlob = blob.slice(blockStart, blockStart + BLOCK_LENGTH)\n const blockBuffer = await blockBlob.arrayBuffer()\n const blockBytes = new Uint8Array(blockBuffer)\n\n headerChunks.push(blockBytes)\n\n // Check block for END keyword (scanning rows bottom-up)\n const rows = BLOCK_LENGTH / LINE_WIDTH\n for (let row = rows - 1; row >= 0; row--) {\n const rowIndex = row * LINE_WIDTH\n const b = blockBytes[rowIndex]!\n\n if (b === 32) continue\n\n if (\n b === 69 &&\n blockBytes[rowIndex + 1] === 78 &&\n blockBytes[rowIndex + 2] === 68 &&\n blockBytes[rowIndex + 3] === 32\n ) {\n headerFound = true\n break\n }\n\n break\n }\n\n blockCount++\n\n if (!headerFound) {\n continue\n }\n\n // Assemble header string from chunks\n const totalHeaderBytes = headerChunks.reduce((sum, c) => sum + c.length, 0)\n const headerStorage = new Uint8Array(totalHeaderBytes)\n let pos = 0\n for (const chunk of headerChunks) {\n headerStorage.set(chunk, pos)\n pos += chunk.length\n }\n const headerString = uint8ArrayToString(headerStorage)\n const header = new Header(headerString, options?.maxHeaderLines, options?.onWarning)\n\n // Calculate data unit position\n const headerEnd = offset + blockCount * BLOCK_LENGTH\n const dataLength = header.getDataLength()\n\n // Create data unit using Blob slice (lazy — no data loaded yet)\n let dataunit: DataUnit | undefined\n if (header.hasDataUnit()) {\n const dataBlob = blob.slice(headerEnd, headerEnd + dataLength)\n dataunit = createDataUnit(header, dataBlob)\n }\n\n hdus.push(new HDU(header, dataunit))\n\n // Advance past header + data + padding\n offset = headerEnd + dataLength + excessBytes(dataLength)\n\n if (offset >= totalLength) {\n break\n }\n }\n\n if (!headerFound) {\n break\n }\n }\n\n return hdus\n}\n","import { parseBuffer, parseBlob } from './parser'\nimport { HDU } from './hdu'\nimport type { Header } from './header'\nimport type { DataUnit } from './data-unit'\nimport type { ReadOptions, FetchOptions } from './types'\n\n/**\n * Main FITS class — the primary entry point for reading FITS files.\n *\n * Provides static factory methods for creating FITS instances from\n * various data sources (ArrayBuffer, Blob/File, URL, Node.js Buffer).\n *\n * @example\n * ```ts\n * // From URL (browser)\n * const fits = await FITS.fromURL('https://example.com/image.fits');\n *\n * // From ArrayBuffer\n * const fits = FITS.fromArrayBuffer(buffer);\n *\n * // From File object (browser)\n * const fits = await FITS.fromBlob(fileInput.files[0]);\n *\n * // Access data\n * const header = fits.getHeader();\n * const image = fits.getDataUnit();\n * ```\n */\nexport class FITS {\n /** All Header Data Units in this FITS file. */\n readonly hdus: HDU[]\n\n private constructor(hdus: HDU[]) {\n this.hdus = hdus\n }\n\n // --- Static factory methods ---\n\n /**\n * Parse a FITS file from an ArrayBuffer (synchronous).\n */\n static fromArrayBuffer(buffer: ArrayBuffer, options?: ReadOptions): FITS {\n const hdus = parseBuffer(buffer, options)\n return new FITS(hdus)\n }\n\n /**\n * Parse a FITS file from a Blob or File object (async).\n */\n static async fromBlob(blob: Blob, options?: ReadOptions): Promise<FITS> {\n const hdus = await parseBlob(blob, options)\n return new FITS(hdus)\n }\n\n /**\n * Fetch a remote FITS file and parse it (async, browser or Node 18+).\n *\n * @param url - URL of the FITS file.\n * @param init - Optional fetch RequestInit (headers, signal, etc.).\n */\n static async fromURL(url: string, options?: FetchOptions): Promise<FITS> {\n const response = await fetch(url, options?.requestInit)\n if (!response.ok) {\n throw new Error(`Failed to fetch FITS file: ${response.status} ${response.statusText}`)\n }\n const buffer = await response.arrayBuffer()\n return FITS.fromArrayBuffer(buffer, options)\n }\n\n /**\n * Parse a FITS file from a Node.js Buffer.\n * The buffer is converted to an ArrayBuffer internally.\n */\n static fromNodeBuffer(\n nodeBuffer: { buffer: ArrayBuffer; byteOffset: number; byteLength: number },\n options?: ReadOptions,\n ): FITS {\n const arrayBuffer = nodeBuffer.buffer.slice(\n nodeBuffer.byteOffset,\n nodeBuffer.byteOffset + nodeBuffer.byteLength,\n )\n return FITS.fromArrayBuffer(arrayBuffer, options)\n }\n\n // --- Public API ---\n\n /**\n * Returns the first HDU containing a data unit.\n * If `index` is provided, returns that specific HDU.\n */\n getHDU(index?: number): HDU | undefined {\n if (index !== undefined) {\n return index >= 0 && index < this.hdus.length ? this.hdus[index] : undefined\n }\n for (const hdu of this.hdus) {\n if (hdu.hasData()) return hdu\n }\n return undefined\n }\n\n /**\n * Returns the header associated with the first HDU containing a data unit.\n * If `index` is provided, returns the header of that specific HDU.\n */\n getHeader(index?: number): Header | undefined {\n return this.getHDU(index)?.header\n }\n\n /**\n * Returns the data unit associated with the first HDU containing a data unit.\n * If `index` is provided, returns the data unit of that specific HDU.\n */\n getDataUnit(index?: number): DataUnit | undefined {\n return this.getHDU(index)?.data\n }\n}\n"]}
|