wcslight
Version:
WCS Javascript library.
302 lines (299 loc) • 16.1 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
/**
* Summary. (bla bla bla)
*
* Description. (bla bla bla)
*
* @link github https://github.com/fab77/wcslight
* @author Fabrizio Giordano <fabriziogiordano77@gmail.com>
*/
import { AbstractProjection } from './AbstractProjection.js';
import { FITSParser } from 'jsfitsio';
import { FITSHeader } from 'jsfitsio';
import { FITSHeaderItem } from 'jsfitsio';
import { ParseUtils } from 'jsfitsio';
export class GnomonicProjection extends AbstractProjection {
constructor(infile) {
super("'RA---TAN'", "'DEC--TAN'");
if (infile) {
this._inflie = infile;
}
}
get fitsUsed() {
throw new Error('Method not implemented.');
}
initFromFile(infile) {
const _super = Object.create(null, {
naxis1: { get: () => super.naxis1, set: v => super.naxis1 = v },
naxis2: { get: () => super.naxis2, set: v => super.naxis2 = v }
});
return __awaiter(this, void 0, void 0, function* () {
let fp = new FITSParser(infile);
let promise = fp.loadFITS().then(fits => {
// console.log(fits.header);
this._pxvalues.set(0, fits.data);
this._fitsheader[0] = fits.header;
_super.naxis1 = fits.header.get("NAXIS1");
_super.naxis2 = fits.header.get("NAXIS2");
this._craDeg = fits.header.getItemListOf("CRVAL1")[0].value;
this._cdecDeg = fits.header.getItemListOf("CRVAL2")[0].value;
// TODO CDELT could not be present. In this is the case,
// there should be CDi_ja, but I am not handling them atm
// [Ref. Representation of celestial coordinates in FITS - equation (1)]
this._pxsize1 = this._fitsheader[0].getItemListOf("CDELT1")[0].value;
this._pxsize2 = this._fitsheader[0].getItemListOf("CDELT2")[0].value;
this._minra = this._craDeg - this._pxsize1 * _super.naxis1 / 2;
if (this._minra < 0) {
this._minra += 360;
}
this._mindec = this._cdecDeg - this._pxsize2 * _super.naxis2 / 2;
return fits;
});
yield promise;
return promise;
});
}
extractPhysicalValues(fits) {
let bzero = fits.header.get("BZERO");
let bscale = fits.header.get("BSCALE");
let naxis1 = fits.header.get("NAXIS1");
let naxis2 = fits.header.get("NAXIS2");
let bitpix = fits.header.get("BITPIX");
let bytesXelem = Math.abs(bitpix / 8);
let blankBytes = ParseUtils.convertBlankToBytes(fits.header.get("BLANK"), bytesXelem); // TODO => ??????? Im not using it. it should be used!
// let physicalvalues = new Array[naxis2][naxis1];
let physicalvalues = new Array(naxis2);
for (let n2 = 0; n2 < naxis2; n2++) {
physicalvalues[n2] = new Array(naxis1);
for (let n1 = 0; n1 < naxis1; n1++) {
let pixval = ParseUtils.extractPixelValue(0, fits.data[n2].slice(n1 * bytesXelem, (n1 + 1) * bytesXelem), bitpix);
let physicalVal = bzero + bscale * pixval;
physicalvalues[n2][n1] = physicalVal;
}
}
return physicalvalues;
}
prepareFITSHeader(fitsHeaderParams) {
this._fitsheader[0] = new FITSHeader();
this._fitsheader[0].addItemAtTheBeginning(new FITSHeaderItem("BITPIX", fitsHeaderParams.get("BITPIX")));
this._fitsheader[0].addItemAtTheBeginning(new FITSHeaderItem("SIMPLE", fitsHeaderParams.get("SIMPLE")));
if (fitsHeaderParams.get("BLANK") !== undefined) {
this._fitsheader[0].addItem(new FITSHeaderItem("BLANK", fitsHeaderParams.get("BLANK")));
}
let bscale = 1.0;
if (fitsHeaderParams.get("BSCALE") !== undefined) {
bscale = fitsHeaderParams.get("BSCALE");
}
this._fitsheader[0].addItem(new FITSHeaderItem("BSCALE", bscale));
let bzero = 0.0;
if (fitsHeaderParams.get("BZERO") !== undefined) {
bzero = fitsHeaderParams.get("BZERO");
}
this._fitsheader[0].addItem(new FITSHeaderItem("BZERO", bzero));
this._fitsheader[0].addItem(new FITSHeaderItem("NAXIS", 2));
this._fitsheader[0].addItem(new FITSHeaderItem("NAXIS1", super.naxis1));
this._fitsheader[0].addItem(new FITSHeaderItem("NAXIS2", super.naxis2));
this._fitsheader[0].addItem(new FITSHeaderItem("CTYPE1", super.ctype1));
this._fitsheader[0].addItem(new FITSHeaderItem("CTYPE2", super.ctype2));
this._fitsheader[0].addItem(new FITSHeaderItem("CDELT1", super.pxsize)); // ??? Pixel spacing along axis 1 ???
this._fitsheader[0].addItem(new FITSHeaderItem("CDELT2", super.pxsize)); // ??? Pixel spacing along axis 2 ???
this._fitsheader[0].addItem(new FITSHeaderItem("CRPIX1", super.naxis1 / 2)); // central/reference pixel i along naxis1
this._fitsheader[0].addItem(new FITSHeaderItem("CRPIX2", super.naxis2 / 2)); // central/reference pixel j along naxis2
this._fitsheader[0].addItem(new FITSHeaderItem("CRVAL1", this._craDeg)); // central/reference pixel RA
this._fitsheader[0].addItem(new FITSHeaderItem("CRVAL2", this._cdecDeg)); // central/reference pixel Dec
let min = bzero + bscale * this._minphysicalval;
let max = bzero + bscale * this._maxphysicalval;
this._fitsheader[0].addItem(new FITSHeaderItem("DATAMIN", min)); // min data value
this._fitsheader[0].addItem(new FITSHeaderItem("DATAMAX", max)); // max data value
this._fitsheader[0].addItem(new FITSHeaderItem("ORIGIN", "WCSLight v.0.x"));
this._fitsheader[0].addItem(new FITSHeaderItem("COMMENT", "WCSLight v0.x developed by F.Giordano and Y.Ascasibar"));
this._fitsheader[0].addItem(new FITSHeaderItem("END"));
return this._fitsheader;
}
getFITSHeader() {
return this._fitsheader;
}
getCommonFitsHeaderParams() {
let header = new FITSHeader();
for (const [key, value] of this._fitsheader[0]) {
// I could add a list of used NPIXs to be included in the comment of the output FITS
if (["SIMPLE", "BITPIX", "BSCALE", "BZERO", "BLANK", "ORDER",].includes(key)) {
// header.set(key, value);
header.addItem(new FITSHeaderItem(key, value));
}
}
return header;
}
getPixValues(inputPixelsList) {
const _super = Object.create(null, {
naxis2: { get: () => super.naxis2 },
naxis1: { get: () => super.naxis1 }
});
return __awaiter(this, void 0, void 0, function* () {
let promise = new Promise((resolve, reject) => {
try {
let bytesXelem = Math.abs(this._fitsheader[0].get("BITPIX") / 8);
let blankBytes = ParseUtils.convertBlankToBytes(this._fitsheader[0].get("BLANK"), bytesXelem);
let pixcount = inputPixelsList.length;
let values = new Uint8Array(pixcount * bytesXelem);
for (let p = 0; p < pixcount; p++) {
let imgpx = inputPixelsList[p];
// TODO check when input is undefined. atm it puts 0 bur it should be BLANK
// TODO why I am getting negative i and j? check world2pix!!!
if ((imgpx._j) < 0 || (imgpx._j) >= _super.naxis2 ||
(imgpx._i) < 0 || (imgpx._i) >= _super.naxis1) {
for (let b = 0; b < bytesXelem; b++) {
values[p * bytesXelem + b] = blankBytes[b];
}
}
else {
for (let b = 0; b < bytesXelem; b++) {
values[p * bytesXelem + b] = (this._pxvalues.get(0))[imgpx._j][(imgpx._i) * bytesXelem + b];
}
}
}
resolve(values);
}
catch (err) {
reject("[MercatorProjection] ERROR: " + err);
}
});
return promise;
});
}
setPxsValue(values, fitsHeaderParams) {
// let bytesXelem = Math.abs(fitsHeaderParams.get("BITPIX") / 8);
// let minpixb = ParseUtils.extractPixelValue(0, values.slice(0, bytesXelem), fitsHeaderParams.get("BITPIX"));
// let maxpixb = minpixb;
// let bscale = (fitsHeaderParams.get("BSCALE") !== undefined) ? fitsHeaderParams.get("BSCALE") : 1.0;
// let bzero = (fitsHeaderParams.get("BZERO") !== undefined) ? fitsHeaderParams.get("BZERO") : 0.0;
// this._minphysicalval = bzero + bscale * minpixb;
// this._maxphysicalval = bzero + bscale * maxpixb;
// this._pxvalues = new Array(this._naxis2);
// for (let r = 0; r < this._naxis2; r++) {
// this._pxvalues[r] = new Uint8Array(this._naxis1 * bytesXelem);
// }
// TODO ...
return null;
}
getImageRADecList(center, radius, pxsize) {
// let promise = new Promise((resolve, reject) => {
// this.computeSquaredNaxes(2 * radius, pxsize); // compute naxis[1, 2]
// this._pxsize = pxsize;
// this._minra = center.ra - radius;
// if (this._minra < 0) {
// this._minra += 360;
// }
// this._mindec = center.dec - radius;
// let radeclist = [];
// let pra, pdec;
// TODO ...
/*
basing on naxis1 and naxis2 call pix2world!!!
*/
/*
mindec = center.dec - radius;
maxdec = center.dec + radius;
below pixel size should depend on the distance from the center
let l = 0;
let factor = 1;
for (let d = mindec; d < maxdec; d+=pxsize) { <--ERROR the external loop must be over RA
factor = 1 + 2**l;
rapxsize = pxsize/factor;
for (let r = 0; r < 360; r+=rapxsize) {
radeclist.push(r, d);
}
l++;
}
*/
// let cidx = (this._naxis2 / 2 - 1) * this._naxis1 + this._naxis1 / 2;
// this._cra = radeclist[cidx][0];
// this._cdec = radeclist[cidx][1];
// resolve(radeclist);
// });
// return promise;
return null;
}
pix2world(i, j) {
// TODO ...
let x, y;
let CDELT1 = this._fitsheader[0].getItemListOf("CDELT1")[0];
let CDELT2 = this._fitsheader[0].getItemListOf("CDELT2")[0];
let PC1_1 = this._fitsheader[0].getItemListOf("PC1_1")[0];
let PC1_2 = this._fitsheader[0].getItemListOf("PC1_2")[0];
let PC2_1 = this._fitsheader[0].getItemListOf("PC2_1")[0];
let PC2_2 = this._fitsheader[0].getItemListOf("PC2_2")[0];
let CD1_1 = this._fitsheader[0].getItemListOf("CD1_1")[0];
let CD1_2 = this._fitsheader[0].getItemListOf("CD1_2")[0];
let CD2_1 = this._fitsheader[0].getItemListOf("CD2_1")[0];
let CD2_2 = this._fitsheader[0].getItemListOf("CD2_2")[0];
let CRPIX1 = this._fitsheader[0].getItemListOf("CRPIX1")[0];
let CRPIX2 = this._fitsheader[0].getItemListOf("CRPIX2")[0];
if (CDELT1 !== undefined && CDELT2 !== undefined &&
PC1_1 !== undefined && PC1_2 !== undefined &&
PC2_1 !== undefined && PC2_2 !== undefined) { // if CDELTia and PCi_ja notation
x = CDELT1 * (PC1_1 * (i - CRPIX1) + PC1_2 * (j - CRPIX2));
y = CDELT2 * (PC2_1 * (i - CRPIX1) + PC2_2 * (j - CRPIX2));
}
else { // else CDi_ja notation
x = CD1_1 * (i - CRPIX1) + CD1_2 * (j - CRPIX2);
y = CD2_1 * (i - CRPIX1) + CD2_2 * (j - CRPIX2);
}
// let phi = math.arg(-y / x);
// let R_theta = Math.sqrt(x * x + y * y);
// let theta = Math.atan2(180 / (Math.PI * R_theta));
// let ra, dec;
// ra = phi;
// dec = theta;
// // TODO check if phi, theta match with ra, dec or they need to be (linearly) converted
// return [ra, dec];
return null;
}
world2pix(radeclist) {
let imgpxlist = [];
let CDELT1 = (this._fitsheader[0].getItemListOf("CDELT1").length > 0) ? this._fitsheader[0].getItemListOf("CDELT1")[0] : undefined;
let CDELT2 = (this._fitsheader[0].getItemListOf("CDELT2").length > 0) ? this._fitsheader[0].getItemListOf("CDELT2")[0] : undefined;
let PC1_1 = (this._fitsheader[0].getItemListOf("PC1_1").length > 0) ? this._fitsheader[0].getItemListOf("PC1_1")[0] : undefined;
let PC1_2 = (this._fitsheader[0].getItemListOf("PC1_2").length > 0) ? this._fitsheader[0].getItemListOf("PC1_2")[0] : undefined;
let PC2_1 = (this._fitsheader[0].getItemListOf("PC2_1").length > 0) ? this._fitsheader[0].getItemListOf("PC2_1")[0] : undefined;
let PC2_2 = (this._fitsheader[0].getItemListOf("PC2_2").length > 0) ? this._fitsheader[0].getItemListOf("PC2_2")[0] : undefined;
let CD1_1 = (this._fitsheader[0].getItemListOf("CD1_1").length > 0) ? this._fitsheader[0].getItemListOf("CD1_1")[0] : undefined;
let CD1_2 = (this._fitsheader[0].getItemListOf("CD1_2").length > 0) ? this._fitsheader[0].getItemListOf("CD1_2")[0] : undefined;
let CD2_1 = (this._fitsheader[0].getItemListOf("CD2_1").length > 0) ? this._fitsheader[0].getItemListOf("CD2_1")[0] : undefined;
let CD2_2 = (this._fitsheader[0].getItemListOf("CD2_2").length > 0) ? this._fitsheader[0].getItemListOf("CD2_2")[0] : undefined;
let CRPIX1 = (this._fitsheader[0].getItemListOf("CRPIX1").length > 0) ? this._fitsheader[0].getItemListOf("CRPIX1")[0] : undefined;
let CRPIX2 = (this._fitsheader[0].getItemListOf("CRPIX2").length > 0) ? this._fitsheader[0].getItemListOf("CRPIX2")[0] : undefined;
radeclist.forEach(([ra, dec]) => {
// TODO ...
// let i, j;
// // (linearly) convert ra, dec into phi, theta
// let theta = dec;
// let phi = ra;
// let R_theta = (180 / Math.PI) * math.cot(theta);
// let x = R_theta * Math.sin(phi);
// let y = - R_theta * Math.cos(phi);
// if (CDELT1 !== undefined && CDELT2 !== undefined &&
// PC1_1 !== undefined && PC1_2 !== undefined &&
// PC2_1 !== undefined && PC2_2 !== undefined
// ) { // if CDELTia and PCi_ja notation
// j = y * CDELT1 * PC1_1 / (CDELT1 * CDELT2 * (PC1_1 * PC2_2 - PC2_1 * PC1_2)) + PC1_1 * CRPIX2 * (PC2_2 - PC2_1) / (PC1_1 * PC2_2 - PC2_1 * PC1_2);
// i = x / (CDELT1 * PC1_1) + CRPIX1 - j * PC1_2 / PC1_1 + CRPIX2 * PC1_2 / PC1_1;
// } else { // else CDi_ja notation
// j = y * CD1_1 / (CD1_1 * CD2_2 - CD1_2 * CD2_1) + CRPIX2 * CD1_1 * (CD2_2 - CD2_1) / (CD1_1 * CD2_2 - CD1_2 * CD2_1);
// i = (x + CD1_1 * CRPIX1 - CD1_2 * j + CD1_2 * CRPIX2) / CD1_1;
// }
// imgpxlist.push(new ImagePixel(i, j));
});
return imgpxlist;
}
}
//# sourceMappingURL=GnomonicProjection.js.map