slimfits
Version:
Package for loading data stored in FITS data format
793 lines • 38.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
// TODO: we need to incorporate RADECSYS in processing
var SphericalProjectionConverterBase = /** @class */ (function () {
function SphericalProjectionConverterBase(obj) {
this.ra2de = 180 / Math.PI;
this.de2ra = Math.PI / 180;
this.phi_0 = NaN;
this.theta_0 = NaN;
this.alpha_0 = NaN;
this.delta_0 = NaN;
this.theta_p = NaN;
this.phi_p = NaN;
this.transform_matrix = undefined;
this.inverse_transform_matrix = undefined;
if (Array.isArray(obj)) {
this.constructFromHeader(obj);
}
else {
this.constructFromDefinition(obj);
}
}
SphericalProjectionConverterBase.isLongitudal = function (type) {
for (var _i = 0, _a = SphericalProjectionConverterBase.longitudalTypes; _i < _a.length; _i++) {
var longitudalType = _a[_i];
if (longitudalType === type) {
return true;
}
}
return false;
};
SphericalProjectionConverterBase.prototype.convert = function (coords) {
var relativeCoords = this.convertToRelative(coords);
var intermediateCoords = this.convertToIntermediate(relativeCoords);
var sphericalCoords = this.convertToSpherical(intermediateCoords);
var celestialCoords = this.convertToCelestial(sphericalCoords);
return celestialCoords;
};
SphericalProjectionConverterBase.prototype.convertBack = function (coords) {
var sphericalCoords = this.convertFromCelestial(coords);
var intermediateCoords = this.convertFromSpherical(sphericalCoords);
var relativeCoords = this.convertFromIntermediate(intermediateCoords);
var plateCoords = this.convertFromRelative(relativeCoords);
return plateCoords;
};
SphericalProjectionConverterBase.prototype.multiplyMatrices = function (arr1, arr2) {
var res = [[0, 0], [0, 0]];
for (var row = 0; row < 2; row++) {
for (var col = 0; col < 2; col++) {
for (var i = 0; i < 2; i++) {
res[row][col] += arr1[row][i] * arr2[i][col];
}
}
}
return res;
};
SphericalProjectionConverterBase.prototype.convertToRelative = function (coords) {
return {
u: coords.x + 1 - this.crpixs[0],
v: coords.y + 1 - this.crpixs[1]
};
};
SphericalProjectionConverterBase.prototype.convertFromRelative = function (coords) {
return {
x: Math.round((coords.u + this.crpixs[0] - 1) * 1000) / 1000,
y: Math.round((coords.v + this.crpixs[1] - 1) * 1000) / 1000
};
};
SphericalProjectionConverterBase.prototype.convertToIntermediate = function (coords) {
var is = [];
var crds = [coords.u, coords.v];
for (var i = 0; i < this.wcslen; i += 1) {
is[i] = 0;
for (var j = 0; j < this.wcslen; j += 1) {
is[i] += this.transform_matrix[i][j] * crds[j];
}
is[i] *= this.de2ra;
}
return { x: is[0], y: is[1] };
};
SphericalProjectionConverterBase.prototype.convertFromIntermediate = function (coords) {
var is = [];
var crds = [coords.x, coords.y];
for (var i = 0; i < this.wcslen; i += 1) {
is[i] = 0;
for (var j = 0; j < this.wcslen; j += 1) {
is[i] += this.inverse_transform_matrix[i][j] * crds[j];
}
is[i] *= this.ra2de;
// is[i] += this.crpixs[i] - 1;
}
return {
u: is[0],
v: is[1] //Math.round(is[1] * 1000) / 1000
};
};
SphericalProjectionConverterBase.prototype.convertFromSpherical = function (coords) {
return {
x: coords.r * Math.sin(coords.phi),
y: -coords.r * Math.cos(coords.phi)
};
};
SphericalProjectionConverterBase.prototype.convertToCelestial = function (coords) {
var alpha = NaN;
var delta = NaN;
var coords_p = this.calculate_alphap_deltap();
if (coords_p.delta_p === Math.PI / 2) {
// SEE: http://www.aanda.org/articles/aa/pdf/2002/45/aah3860.pdf (eqn. 3)
alpha = (coords_p.alpha_p + coords.phi - this.phi_p - Math.PI) * this.ra2de;
delta = coords.theta * this.ra2de;
}
else if (coords_p.delta_p === -Math.PI / 2) {
// SEE: http://www.aanda.org/articles/aa/pdf/2002/45/aah3860.pdf (eqn. 4)
alpha = (coords_p.alpha_p - coords.phi + this.phi_p) * this.ra2de;
delta = -coords.theta * this.ra2de;
}
else {
// SEE: http://www.aanda.org/articles/aa/pdf/2002/45/aah3860.pdf (eqn. 2)
var sin_theta = Math.sin(coords.theta);
var cos_theta = Math.cos(coords.theta);
var sin_dphi = Math.sin(coords.phi - this.phi_p);
var cos_dphi = Math.cos(coords.phi - this.phi_p);
var sin_de_p = Math.sin(coords_p.delta_p);
var cos_de_p = Math.cos(coords_p.delta_p);
var xt = sin_theta * cos_de_p - cos_theta * sin_de_p * cos_dphi;
var yt = -cos_theta * sin_dphi;
var zt = sin_theta * sin_de_p + cos_theta * cos_de_p * cos_dphi;
alpha = (Math.atan2(yt, xt) + coords_p.alpha_p) * this.ra2de;
delta = Math.asin(zt) * this.ra2de;
}
alpha = (alpha + 360) % 360;
alpha /= 15;
return { alpha: alpha, delta: delta };
};
SphericalProjectionConverterBase.prototype.convertFromCelestialToAngles = function (coords) {
var phi;
var theta;
var alpha = coords.alpha * 15 * this.de2ra;
var delta = coords.delta * this.de2ra;
var coords_p = this.calculate_alphap_deltap();
if (coords_p.delta_p === Math.PI / 2) {
// SEE: http://www.aanda.org/articles/aa/pdf/2002/45/aah3860.pdf (inverted eqn. 3)
phi = alpha + Math.PI + this.phi_p - coords_p.alpha_p;
theta = delta;
}
else if (coords_p.delta_p === -Math.PI / 2) {
// SEE: http://www.aanda.org/articles/aa/pdf/2002/45/aah3860.pdf (inverted eqn. 4)
phi = coords_p.alpha_p - alpha + this.phi_p;
theta = -delta;
}
else {
// SEE: http://www.aanda.org/articles/aa/pdf/2002/45/aah3860.pdf (eqn. 5)
var sin_delta = Math.sin(delta);
var cos_delta = Math.cos(delta);
var sin_delta_p = Math.sin(coords_p.delta_p);
var cos_delta_p = Math.cos(coords_p.delta_p);
var cos_dalpha = Math.cos(alpha - coords_p.alpha_p);
var sin_dalpha = Math.sin(alpha - coords_p.alpha_p);
phi = this.phi_p + Math.atan2(sin_delta * cos_delta_p - cos_delta * sin_delta_p * cos_dalpha, -cos_delta * sin_dalpha);
theta = Math.asin(sin_delta * sin_delta_p + cos_delta * cos_delta_p * cos_dalpha);
}
return { phi: phi, theta: theta };
};
SphericalProjectionConverterBase.prototype.constructFromHeader = function (header) {
// TODO: as the construction of a converter relies on CTYPE
// most likely obtaining/defining ctypes and axis_types
// should be removed from this place to the builder.
// Moreover, axes_types shall define whether we deal with
// equatorial, galactic or ecliptic coordinates.
this.ctypes = header.filter(function (o) { return o.key.indexOf('CTYPE') === 0; })
.sort(function (a, b) { return a.key.localeCompare(b.key); })
.map(function (val) { return val.value; });
if (this.ctypes.length <= 0) {
return;
}
this.projection = this.ctypes[0].slice(5);
this.axes_types = [];
for (var _i = 0, _a = this.ctypes; _i < _a.length; _i++) {
var ctype = _a[_i];
var type = ctype.substr(0, 5).replace('-', '');
this.axes_types.push({
name: type,
isLongitudal: SphericalProjectionConverterBase.isLongitudal(type)
});
}
// TODO: WCS standard has an optional WCSAXES
this.wcslen = header.filter(function (o) { return /NAXIS\d+/.test(o.key); })
.length;
this.crpixs = header.filter(function (o) { return /CRPIX\d+/.test(o.key); })
.sort(function (a, b) { return a.key.localeCompare(b.key); })
.map(function (val) { return val.value; });
this.crvals = header.filter(function (o) { return /CRVAL\d+/.test(o.key); })
.sort(function (a, b) { return a.key.localeCompare(b.key); })
.map(function (val) { return val.value; });
this.cdelts = header.filter(function (o) { return /CDELT\d+/.test(o.key); })
.sort(function (a, b) { return a.key.localeCompare(b.key); })
.map(function (val) { return val.value; });
// TODO: currently with the below prescription we assume ra ~ x and dec ~ y
// (not to mention all the other coordinate systems).
// There must be implemented the logic describing
this.alpha_0 = this.crvals[0] * this.de2ra;
this.delta_0 = this.crvals[1] * this.de2ra;
var latpole_found = false;
var lonpole_found = false;
for (var _b = 0, header_1 = header; _b < header_1.length; _b++) {
var kw = header_1[_b];
if (kw.key === 'LATPOLE') {
this.theta_p = parseFloat(kw.value) * this.de2ra;
latpole_found = true;
}
if (kw.key === 'LONPOLE') {
this.phi_p = parseFloat(kw.value) * this.de2ra;
lonpole_found = true;
}
if (latpole_found && lonpole_found) {
break;
}
}
var phitheta = this.calculate_phi0_theta0();
this.phi_0 = phitheta.phi_0;
this.theta_0 = phitheta.theta_0;
if (isNaN(this.phi_p)) {
this.phi_p = (this.delta_0 >= this.theta_0) ? 0 : Math.PI;
}
// INFO: currently we compile down to es5 that doesn't have Array.prototype.find method.
// This should be changed to a polyfill at one point.
var find_element = function (arr, key) {
for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) {
var kw = arr_1[_i];
if (kw.key === key) {
return kw.value;
}
}
return undefined;
};
var default_for;
var rot_matrix_key_regex = /CD\d+_\d+/;
var rot_matrix_kws = header.filter(function (o) { return rot_matrix_key_regex.test(o.key); });
var rot_matrix_key_prefix = 'CD';
var rot_can_create_transform_matrix = false;
if (rot_matrix_kws != null && rot_matrix_kws.length > 0) {
// CDs are present so we use them
default_for = function (_, __) { return 0; };
// we must have at least one number given
rot_can_create_transform_matrix = rot_matrix_kws.length > 0;
}
else {
// CDs are not present. Find PC elements and CDELT elements
rot_matrix_key_regex = /PC\d+_\d+/;
rot_matrix_key_prefix = 'PC';
rot_matrix_kws = header.filter(function (o) { return rot_matrix_key_regex.test(o.key); });
default_for = function (i, j) { return (i === j) ? 1 : 0; };
// we're good to go as there is a non-zero value
rot_can_create_transform_matrix = true;
}
if (rot_can_create_transform_matrix) {
this.transform_matrix = [];
for (var i = 0; i < this.wcslen; i++) {
this.transform_matrix[i] = [];
for (var j = 0; j < this.wcslen; j++) {
var elem_default = default_for(i, j);
var loc_prefix = rot_matrix_key_prefix + (i + 1) + '_' + (j + 1);
var pc_tmp = find_element(rot_matrix_kws, loc_prefix);
this.transform_matrix[i][j] = (pc_tmp !== undefined) ? parseFloat(pc_tmp) : elem_default;
}
}
if (rot_matrix_key_prefix === 'PC' && this.cdelts.length > 0) {
this.transform_matrix = this.multiplyMatrices([[this.cdelts[0], 0], [0, this.cdelts[1]]], this.transform_matrix);
}
}
// We rely on the CD formalism, meaning our transform_matrix IS de facto CDs array.
// Thus to cover for that when a FITS file uses PC formalism we reformat [CDELTs]*[PCs]
// according to the equation below.
// SEE: http://www.aanda.org/articles/aa/pdf/2002/45/aah3860.pdf
// The translation between CD and PC formalism is:
// / CD1_1 CD1_2 \ - / CDELT1 0 \ . / PC1_1 PC1_2 \
// \ CD2_1 CD2_2 / - \ 0 CDELT2 / \ PC2_1 PC2_2 /
this.crotas = header.filter(function (o) { return /CROTA\d+/.test(o.key); })
.sort(function (a, b) { return a.key.localeCompare(b.key); })
.map(function (val) { return val.value; });
// SEE: http://www.aanda.org/articles/aa/pdf/2002/45/aah3860.pdf (section 6.1)
// we don't want to use CROTA as it's obsolete, but just in case
// the implementation is given below
// SEE: http://www.aanda.org/articles/aa/pdf/2002/45/aah3860.pdf, eqn/ 186, 187, 188 & 189
if (this.transform_matrix === undefined && this.crotas !== undefined && this.crotas.length > 0) {
this.transform_matrix = [
[this.cdelts[0] * Math.cos(this.crotas[0]), -this.cdelts[1] * Math.sin(this.crotas[1])],
[this.cdelts[0] * Math.sin(this.crotas[0]), this.cdelts[1] * Math.cos(this.crotas[1])]
];
}
this.inverse_transform_matrix = this.inverseOf(this.transform_matrix);
};
SphericalProjectionConverterBase.prototype.constructFromDefinition = function (definition) {
this.wcslen = 2;
this.crpixs = [
definition.frame_reference_point.x + 1,
definition.frame_reference_point.y + 1
];
this.alpha_0 = definition.sky_reference_point.alpha;
this.delta_0 = definition.sky_reference_point.delta;
var phitheta = this.calculate_phi0_theta0();
// TODO: check whether it is ok.
this.theta_p = definition.celestial_pole.latitude;
this.phi_p = definition.celestial_pole.longitude;
if (isNaN(this.phi_p)) {
this.phi_p = (this.delta_0 >= this.theta_0) ? 0 : Math.PI;
}
this.phi_0 = phitheta.phi_0;
this.theta_0 = phitheta.theta_0;
this.transform_matrix = [];
var dtm_length = definition.transform_matrix.length;
for (var x = 0; x < dtm_length; x++) {
this.transform_matrix[x] = [];
var dtm_sub_length = definition.transform_matrix[x].length;
for (var y = 0; y < dtm_sub_length; y++) {
this.transform_matrix[x][y] = definition.transform_matrix[x][y];
}
}
this.inverse_transform_matrix = this.inverseOf(this.transform_matrix);
};
SphericalProjectionConverterBase.prototype.inverseOf = function (arr) {
var det = arr[0][0] * arr[1][1] - arr[0][1] * arr[1][0];
var inv = [
[arr[1][1] / det, -arr[0][1] / det],
[-arr[1][0] / det, arr[0][0] / det]
];
return inv;
};
// 'RA', 'DEC' - equatorial coordinates (=> meeus.EquatorialCoordinates?)
// 'ELON', 'ELAT' - ecliptic coordinates (=> meeus.EclipticCoordinates?)
// 'GLON', 'GLAT' - galactic coordinates (=> meeus.GalacticCoordinates?)
// 'HLON', 'HLAT' - helioecliptic coordinates
// 'SLON', 'SLAT' - supergalactic coordinates
SphericalProjectionConverterBase.longitudalTypes = ['RA', 'ELON', 'GLON', 'HLON', 'SLON'];
return SphericalProjectionConverterBase;
}());
exports.SphericalProjectionConverterBase = SphericalProjectionConverterBase;
// INFO: For zenithal projections, (phi_0, theta_0) = (0, PI / 2),
// so the CRVAL elements specify the celestial coordinates
// of the native pole, i.e. (ra_0, de_0) = (ra_p, de_p)
// TODO: as written above: this only works for zenithal projections.
// It must be updated to work for all the others.
var ZenithalProjectionConverterBase = /** @class */ (function (_super) {
tslib_1.__extends(ZenithalProjectionConverterBase, _super);
function ZenithalProjectionConverterBase() {
return _super !== null && _super.apply(this, arguments) || this;
}
ZenithalProjectionConverterBase.prototype.calculate_alphap_deltap = function () {
return { alpha_p: this.alpha_0, delta_p: this.delta_0 };
};
// SEE: http://www.aanda.org/articles/aa/pdf/2002/45/aah3860.pdf, p. 1079, par 1
ZenithalProjectionConverterBase.prototype.calculate_phi0_theta0 = function () {
return { phi_0: 0, theta_0: Math.PI / 2 };
};
return ZenithalProjectionConverterBase;
}(SphericalProjectionConverterBase));
exports.ZenithalProjectionConverterBase = ZenithalProjectionConverterBase;
// INFO: For zenithal projections, (phi_0, theta_0) = (0, PI / 2),
// so the CRVAL elements specify the celestial coordinates
// of the native pole, i.e. (ra_0, de_0) = (ra_p, de_p)
// TODO: as written above: this only works for zenithal projections.
// It must be updated to work for all the others.
// See: http://www.aanda.org/articles/aa/pdf/2002/45/aah3860.pdf (eqns: 8, 9, 10)
var NonPolarProjectionConverterBase = /** @class */ (function (_super) {
tslib_1.__extends(NonPolarProjectionConverterBase, _super);
function NonPolarProjectionConverterBase() {
return _super !== null && _super.apply(this, arguments) || this;
}
NonPolarProjectionConverterBase.prototype.calculate_alphap_deltap = function () {
throw new Error('NotImplemented');
};
return NonPolarProjectionConverterBase;
}(SphericalProjectionConverterBase));
exports.NonPolarProjectionConverterBase = NonPolarProjectionConverterBase;
var GnomonicProjectionConverter = /** @class */ (function (_super) {
tslib_1.__extends(GnomonicProjectionConverter, _super);
function GnomonicProjectionConverter() {
return _super !== null && _super.apply(this, arguments) || this;
}
GnomonicProjectionConverter.prototype.convertToSpherical = function (coords) {
var r = Math.sqrt(coords.x * coords.x + coords.y * coords.y);
return {
r: r,
phi: Math.atan2(coords.x, -coords.y),
theta: Math.atan(1 / r)
};
};
GnomonicProjectionConverter.prototype.convertFromCelestial = function (coords) {
var angles = _super.prototype.convertFromCelestialToAngles.call(this, coords);
return {
r: 1.0 / Math.tan(angles.theta),
phi: angles.phi,
theta: angles.theta
};
};
return GnomonicProjectionConverter;
}(ZenithalProjectionConverterBase));
exports.GnomonicProjectionConverter = GnomonicProjectionConverter;
var TpvGnomonicProjectionConverter = /** @class */ (function (_super) {
tslib_1.__extends(TpvGnomonicProjectionConverter, _super);
function TpvGnomonicProjectionConverter() {
return _super !== null && _super.apply(this, arguments) || this;
}
TpvGnomonicProjectionConverter.prototype.convert = function (coords) {
var relativeCoords = this.convertToRelative(coords);
var intermediateCoords = this.convertToIntermediate(relativeCoords);
var distortedIntermediateCoords = this.convertToDistorted(intermediateCoords);
var sphericalCoords = this.convertToSpherical(distortedIntermediateCoords);
var celestialCoords = this.convertToCelestial(sphericalCoords);
return celestialCoords;
};
TpvGnomonicProjectionConverter.prototype.convertBack = function (coords) {
var sphericalCoords = this.convertFromCelestial(coords);
var distortedIntermediateCoords = this.convertFromSpherical(sphericalCoords);
var intermediateCoords = this.convertFromDistorted(distortedIntermediateCoords);
var relativeCoords = this.convertFromIntermediate(intermediateCoords);
var plateCoords = this.convertFromRelative(relativeCoords);
return plateCoords;
};
TpvGnomonicProjectionConverter.prototype.constructFromHeader = function (header) {
_super.prototype.constructFromHeader.call(this, header);
this.pvs = undefined;
// INFO: currently we compile down to es5 that doesn't have Array.prototype.find method.
// This should be changed to a polyfill at one point.
var find_element = function (arr, key) {
for (var _i = 0, arr_2 = arr; _i < arr_2.length; _i++) {
var kw = arr_2[_i];
if (kw.key === key) {
return kw.value;
}
}
return undefined;
};
// TPV convention: https://fits.gsfc.nasa.gov/registry/tpvwcs/tpv.html
var default_for = function (i, j) { return 0; };
var pvs_kws = header.filter(function (o) { return /PV\d+_\d+/.test(o.key); });
var pvs_prefix = 'PV';
var pvs_cnt = 0;
if (pvs_kws.length > 0) {
this.pvs = [];
for (var i = 0; i < this.wcslen; i++) {
this.pvs[i] = [];
for (var j = 0; j < 40; j++) {
var elem_default = default_for(i, j);
var loc_prefix = pvs_prefix + (i + 1) + '_' + (j);
var pv_tmp = find_element(pvs_kws, loc_prefix);
this.pvs[i][j] = (pv_tmp !== undefined) ? parseFloat(pv_tmp) : elem_default;
pvs_cnt += Math.abs(this.pvs[i][j]);
}
}
}
if (pvs_cnt === 0) {
this.pvs = undefined;
}
};
TpvGnomonicProjectionConverter.prototype.constructFromDefinition = function (definition) {
_super.prototype.constructFromDefinition.call(this, definition);
this.pvs = undefined;
if (definition.distortion_matrix === undefined) {
throw new Error('distortion_matrix is undefined');
}
this.pvs = [];
var pvc_length = definition.distortion_matrix.length;
for (var x = 0; x < pvc_length; x++) {
this.pvs[x] = [];
var pvc_sub_length = definition.distortion_matrix[x].length;
var y = 0;
for (; y < pvc_sub_length; y++) {
this.pvs[x][y] = definition.distortion_matrix[x][y];
}
for (; y < 40; y++) {
this.pvs[x][y] = 0.0;
}
}
};
TpvGnomonicProjectionConverter.prototype.convertToDistorted = function (coords) {
if (this.pvs === undefined) {
return coords;
}
var x = coords.x * this.ra2de;
var y = coords.y * this.ra2de;
var xout = this.getDistortedParam(x, y, this.pvs[0]);
var yout = this.getDistortedParam(y, x, this.pvs[1]);
return {
x: xout * this.de2ra,
y: yout * this.de2ra
};
};
TpvGnomonicProjectionConverter.prototype.getDistortedParam = function (xi, eta, pv) {
var r = Math.sqrt(xi * xi + eta * eta);
var r2 = r * r;
var r3 = r * r2;
var r4 = r * r3;
var r5 = r * r4;
var r6 = r * r5;
var r7 = r * r6;
var xi2 = xi * xi;
var xi3 = xi * xi2;
var xi4 = xi * xi3;
var xi5 = xi * xi4;
var xi6 = xi * xi5;
var xi7 = xi * xi6;
var eta2 = eta * eta;
var eta3 = eta * eta2;
var eta4 = eta * eta3;
var eta5 = eta * eta4;
var eta6 = eta * eta5;
var eta7 = eta * eta6;
return pv[0] + pv[1] * xi + pv[2] * eta + pv[3] * r +
pv[4] * xi * xi + pv[5] * xi * eta + pv[6] * eta * eta +
pv[7] * xi * xi * xi + pv[8] * xi * xi * eta + pv[9] * xi * eta * eta +
pv[10] * eta * eta * eta + pv[11] * r * r * r +
pv[12] * xi * xi * xi * xi + pv[13] * xi * xi * xi * eta +
pv[14] * xi * xi * eta * eta + pv[15] * xi * eta * eta * eta +
pv[16] * eta * eta * eta * eta +
pv[17] * xi * xi * xi * xi * xi + pv[18] * xi * xi * xi * xi * eta +
pv[19] * xi * xi * xi * eta * eta +
pv[20] * xi * xi * eta * eta * eta + pv[21] * xi * eta * eta * eta * eta +
pv[22] * eta * eta * eta * eta * eta + pv[23] * r * r * r * r * r +
pv[24] * xi * xi * xi * xi * xi * xi + pv[25] * xi * xi * xi * xi * xi * eta +
pv[26] * xi * xi * xi * xi * eta * eta + pv[27] * xi * xi * xi * eta * eta * eta +
pv[28] * xi * xi * eta * eta * eta * eta + pv[29] * xi * eta * eta * eta * eta * eta +
pv[30] * eta * eta * eta * eta * eta * eta +
pv[31] * xi * xi * xi * xi * xi * xi * xi + pv[32] * xi * xi * xi * xi * xi * xi * eta +
pv[33] * xi * xi * xi * xi * xi * eta * eta + pv[34] * xi * xi * xi * xi * eta * eta * eta +
pv[35] * xi * xi * xi * eta * eta * eta * eta + pv[36] * xi * xi * eta * eta * eta * eta * eta +
pv[37] * xi * eta * eta * eta * eta * eta * eta + pv[38] * eta * eta * eta * eta * eta * eta * eta +
pv[39] * r * r * r * r * r * r * r;
};
TpvGnomonicProjectionConverter.prototype.convertFromDistorted = function (coords) {
if (this.pvs === undefined) {
return coords;
}
throw new Error('NotImplemented');
};
return TpvGnomonicProjectionConverter;
}(GnomonicProjectionConverter));
exports.TpvGnomonicProjectionConverter = TpvGnomonicProjectionConverter;
var SipGnomonicProjectionConverter = /** @class */ (function (_super) {
tslib_1.__extends(SipGnomonicProjectionConverter, _super);
function SipGnomonicProjectionConverter() {
return _super !== null && _super.apply(this, arguments) || this;
}
SipGnomonicProjectionConverter.prototype.convert = function (coords) {
var relativeCoords = this.convertToRelative(coords);
var distortedCoords = this.convertToDistorted(relativeCoords);
var intermediateCoords = this.convertToIntermediate(distortedCoords);
var sphericalCoords = this.convertToSpherical(intermediateCoords);
var celestialCoords = this.convertToCelestial(sphericalCoords);
return celestialCoords;
};
SipGnomonicProjectionConverter.prototype.convertBack = function (coords) {
var sphericalCoords = this.convertFromCelestial(coords);
var intermediateCoords = this.convertFromSpherical(sphericalCoords);
var distortedCoords = this.convertFromIntermediate(intermediateCoords);
var relativeCoords = this.convertFromDistorted(distortedCoords);
var plateCoords = this.convertFromRelative(relativeCoords);
return plateCoords;
};
SipGnomonicProjectionConverter.prototype.constructFromHeader = function (header) {
_super.prototype.constructFromHeader.call(this, header);
this.a = undefined;
this.b = undefined;
this.ab_inv = undefined;
// INFO: currently we compile down to es5 that doesn't have Array.prototype.find method.
// This should be changed to a polyfill at one point.
var find_element = function (arr, key) {
for (var _i = 0, arr_3 = arr; _i < arr_3.length; _i++) {
var kw = arr_3[_i];
if (kw.key === key) {
return kw.value;
}
}
return undefined;
};
// SIP convention: https://fits.gsfc.nasa.gov/registry/sip.html
var default_for = function (i, j) { return 0; };
var generate_distortion_array = function (kws, order, prefix) {
var arr = [];
for (var i = 0; i <= order; i++) {
arr[i] = [];
for (var j = 0; j <= order; j++) {
var elem_default = default_for(i, j);
var loc_prefix = prefix + '_' + (i) + '_' + (j);
var tmp = find_element(kws, loc_prefix);
arr[i][j] = (tmp !== undefined) ? parseFloat(tmp) : elem_default;
}
}
return arr;
};
var a_kws = header.filter(function (o) { return /A_\d+_\d+/.test(o.key); });
this.a_order = parseInt(header.find(function (o) { return /A_ORDER/.test(o.key); }).value, 10);
if (this.a_order > 0) {
this.a = generate_distortion_array(a_kws, this.a_order, 'A');
}
var b_kws = header.filter(function (o) { return /B_\d+_\d+/.test(o.key); });
this.b_order = parseInt(header.find(function (o) { return /B_ORDER/.test(o.key); }).value, 10);
if (this.b_order > 0) {
this.b = generate_distortion_array(b_kws, this.b_order, 'B');
}
// TODO: implement the inverse transforms.
// const ap_kws: any[] = header.filter(o => /AP_\d+_\d+/.test(o.key));
// const bp_kws: any[] = header.filter(o => /BP_\d+_\d+/.test(o.key));
// const ap_order: number = header.find(o => /AP_ORDER/.test(o.key)).value;
// const bp_order: number = header.find(o => /BP_ORDER/.test(o.key)).value;
// this.inv_a_order = ap_order;
// this.inv_b_order = bp_order;
};
SipGnomonicProjectionConverter.prototype.constructFromDefinition = function (definition) {
_super.prototype.constructFromDefinition.call(this, definition);
this.a = undefined;
this.b = undefined;
throw new Error('NotImplemented');
};
SipGnomonicProjectionConverter.prototype.convertToDistorted = function (coords) {
if (this.a === undefined || this.b === undefined) {
coords;
}
return {
u: coords.u + this.getDistortedParam(coords.u, coords.v, this.a, this.a_order),
v: coords.v + this.getDistortedParam(coords.u, coords.v, this.b, this.b_order)
};
};
SipGnomonicProjectionConverter.prototype.getDistortedParam = function (u, v, arr, order) {
var par = 0;
for (var i = 0; i <= order; i++) {
for (var j = 0; j <= order; j++) {
if (arr[i][j] !== 0) {
par += arr[i][j] * Math.pow(u, i) * Math.pow(v, j);
}
}
}
return par;
};
SipGnomonicProjectionConverter.prototype.convertFromDistorted = function (coords) {
if (this.ab_inv === undefined) {
return coords;
}
throw new Error('NotImplemented');
};
return SipGnomonicProjectionConverter;
}(GnomonicProjectionConverter));
exports.SipGnomonicProjectionConverter = SipGnomonicProjectionConverter;
var SlantOrtographicProjectionConverter = /** @class */ (function (_super) {
tslib_1.__extends(SlantOrtographicProjectionConverter, _super);
function SlantOrtographicProjectionConverter() {
return _super !== null && _super.apply(this, arguments) || this;
}
SlantOrtographicProjectionConverter.prototype.convertToSpherical = function (coords) {
var r = Math.sqrt(coords.x * coords.x + coords.y * coords.y);
return {
r: r,
phi: Math.atan2(coords.x, -coords.y),
theta: Math.acos(r)
};
};
SlantOrtographicProjectionConverter.prototype.convertFromCelestial = function (coords) {
var angles = _super.prototype.convertFromCelestialToAngles.call(this, coords);
return {
r: Math.cos(angles.theta),
phi: angles.phi,
theta: angles.theta
};
};
return SlantOrtographicProjectionConverter;
}(ZenithalProjectionConverterBase));
exports.SlantOrtographicProjectionConverter = SlantOrtographicProjectionConverter;
var ZenithalEquidistantProjectionConverter = /** @class */ (function (_super) {
tslib_1.__extends(ZenithalEquidistantProjectionConverter, _super);
function ZenithalEquidistantProjectionConverter() {
return _super !== null && _super.apply(this, arguments) || this;
}
ZenithalEquidistantProjectionConverter.prototype.convertToSpherical = function (coords) {
var r = Math.sqrt(coords.x * coords.x + coords.y * coords.y);
return {
r: r,
phi: Math.atan2(coords.x, -coords.y),
theta: this.theta_0 - r
};
};
ZenithalEquidistantProjectionConverter.prototype.convertFromCelestial = function (coords) {
var angles = _super.prototype.convertFromCelestialToAngles.call(this, coords);
return {
r: this.theta_0 - angles.theta,
phi: angles.phi,
theta: angles.theta
};
};
return ZenithalEquidistantProjectionConverter;
}(ZenithalProjectionConverterBase));
exports.ZenithalEquidistantProjectionConverter = ZenithalEquidistantProjectionConverter;
var StereographicProjectionConverter = /** @class */ (function (_super) {
tslib_1.__extends(StereographicProjectionConverter, _super);
function StereographicProjectionConverter() {
return _super !== null && _super.apply(this, arguments) || this;
}
StereographicProjectionConverter.prototype.convertToSpherical = function (coords) {
var r = Math.sqrt(coords.x * coords.x + coords.y * coords.y);
return {
r: r,
phi: Math.atan2(coords.x, -coords.y),
theta: Math.PI / 2 - 2 * Math.atan(r / 2)
};
};
StereographicProjectionConverter.prototype.convertFromCelestial = function (coords) {
var angles = _super.prototype.convertFromCelestialToAngles.call(this, coords);
return {
r: 2 * Math.tan((Math.PI / 2 - angles.theta) / 2),
phi: angles.phi,
theta: angles.theta
};
};
return StereographicProjectionConverter;
}(ZenithalProjectionConverterBase));
exports.StereographicProjectionConverter = StereographicProjectionConverter;
var ZenithalEqualAreaProjectionConverter = /** @class */ (function (_super) {
tslib_1.__extends(ZenithalEqualAreaProjectionConverter, _super);
function ZenithalEqualAreaProjectionConverter() {
return _super !== null && _super.apply(this, arguments) || this;
}
ZenithalEqualAreaProjectionConverter.prototype.convertToSpherical = function (coords) {
var r = Math.sqrt(coords.x * coords.x + coords.y * coords.y);
return {
r: r,
phi: Math.atan2(coords.x, -coords.y),
theta: Math.PI / 2 - 2 * Math.asin(r / 2)
};
};
ZenithalEqualAreaProjectionConverter.prototype.convertFromCelestial = function (coords) {
var angles = _super.prototype.convertFromCelestialToAngles.call(this, coords);
return {
r: 2 * Math.sin((Math.PI / 2 - angles.theta) / 2),
phi: angles.phi,
theta: angles.theta
};
};
return ZenithalEqualAreaProjectionConverter;
}(ZenithalProjectionConverterBase));
exports.ZenithalEqualAreaProjectionConverter = ZenithalEqualAreaProjectionConverter;
var SphericalProjectionConvertersBuilder = /** @class */ (function () {
function SphericalProjectionConvertersBuilder() {
this.registeredConverters = {
'TAN': function (header) { return new GnomonicProjectionConverter(header); },
'TPV': function (header) { return new TpvGnomonicProjectionConverter(header); },
'TAN-SIP': function (header) { return new SipGnomonicProjectionConverter(header); },
'SIN': function (header) { return new SlantOrtographicProjectionConverter(header); },
'ARC': function (header) { return new ZenithalEquidistantProjectionConverter(header); },
'STG': function (header) { return new StereographicProjectionConverter(header); },
'ZEA': function (header) { return new ZenithalEqualAreaProjectionConverter(header); }
};
}
SphericalProjectionConvertersBuilder.prototype.canBuild = function (obj) {
var projection = null;
if (Array.isArray(obj)) {
projection = this.canBuildInner(obj);
}
else {
projection = obj;
}
return (projection === null) ? false : this.registeredConverters.hasOwnProperty(projection);
};
SphericalProjectionConvertersBuilder.prototype.build = function (obj) {
var projection = null;
if (Array.isArray(obj)) {
projection = this.canBuildInner(obj);
if (projection !== null) {
return this.registeredConverters[projection](obj);
}
}
else {
if (this.registeredConverters.hasOwnProperty(obj.projection)) {
return this.registeredConverters[obj.projection](obj.definition);
}
}
throw new Error('No converter for projection "' + projection + '" registered.');
};
SphericalProjectionConvertersBuilder.prototype.registerConverter = function (projection, converter) {
this.registeredConverters[projection] = converter;
};
SphericalProjectionConvertersBuilder.prototype.canBuildInner = function (header) {
var ctypes = header.filter(function (o) { return o.key.indexOf('CTYPE') === 0; })
.sort(function (a, b) { return a.key.localeCompare(b.key); })
.map(function (val) { return val.value; });
if (ctypes.length <= 0) {
return null;
}
return ctypes[0].slice(5);
};
return SphericalProjectionConvertersBuilder;
}());
exports.SphericalProjectionConvertersBuilder = SphericalProjectionConvertersBuilder;
//# sourceMappingURL=SphericalProjectionConverters.js.map