Commit 4d2d11ca authored by Moreau Nicolas's avatar Moreau Nicolas
Browse files

Merge branch 'projection'

parents e93798f3 53d07c9b
import {degToArcsec, degToRad} from "./utils.js";
import {header, product} from "./init.js";
import {SPEED_OF_LIGHT, UNIT_FACTOR, DEFAULT_OUTPUT_UNIT} from "./constants.js";
import { degToArcsec, degToRad } from "./utils.js";
import { header, product } from "./init.js";
import { SPEED_OF_LIGHT, UNIT_FACTOR, DEFAULT_OUTPUT_UNIT } from "./constants.js";
/**
* Objects containing all fields from the FITS header. Some values have been casted
......@@ -8,13 +8,13 @@ import {SPEED_OF_LIGHT, UNIT_FACTOR, DEFAULT_OUTPUT_UNIT} from "./constants.js";
*
*/
class FitsHeader{
class FitsHeader {
/**
*
* @param {object} header FITS file header
* @param {string} product Name of product
*/
constructor(header, product){
constructor(header, product) {
this.product = product;
this.object = header["OBJECT"];
this.naxis = parseInt(header["NAXIS"]);
......@@ -24,6 +24,8 @@ class FitsHeader{
this.naxis3 = parseInt(header["NAXIS3"]);
this.naxis4 = "NAXIS4" in header ? parseInt(header["NAXIS4"]) : undefined;
this.crpix1 = parseInt(header["CRPIX1"]);
this.crpix2 = parseInt(header["CRPIX2"]);
this.crpix3 = parseInt(header["CRPIX3"]);
......@@ -38,6 +40,15 @@ class FitsHeader{
this.ctype2 = "CTYPE2" in header ? header["CTYPE2"].toUpperCase().trim() : undefined;
this.ctype3 = "CTYPE3" in header ? header["CTYPE3"].toUpperCase().trim() : undefined;
if(this.ctype1 !== undefined){
this.projectionType = this.ctype1.slice(-3);
console.log(this.projectionType);
}
else{
this.projectionType = undefined;
}
this.cunit1 = "CUNIT1" in header ? header["CUNIT1"].toUpperCase().trim() : undefined;
this.cunit2 = "CUNIT2" in header ? header["CUNIT2"].toUpperCase().trim() : undefined;
......@@ -62,14 +73,17 @@ class FitsHeader{
this.restfreq = "RESTFRQ" in header ? header["RESTFRQ"] : undefined;
this.pc1_1 = 'PC1_1' in header ? header["PC1_1"] : undefined;
this.pc2_1 = 'PC2_1' in header ? header["PC2_1"] : undefined;
if ((this.isGILDAS()) && (this.ctype3 === "VRAD")) {
this.cunit3 = "M/S";
}else{
} else {
this.cunit3 = "CUNIT3" in header ? header["CUNIT3"].toUpperCase().trim() : undefined;
}
this.cdelt3prim = this.getCdelt3prim();
}
this.cdelt3prim = this.getCdelt3prim();
this.width = this.naxis1;
this.height = this.naxis2;
......@@ -79,8 +93,8 @@ class FitsHeader{
/*
* Makes sure that width and height are equals
*
*/
_setSquaredDimensions(){
*/
_setSquaredDimensions() {
if (this.width > this.height) {
this.height = this.width;
} else if (this.width < this.height) {
......@@ -92,22 +106,22 @@ class FitsHeader{
let kb = 1.380649e-23;
let bmin = degToRad(this.bmin);
let bmax = degToRad(this.bmaj);
let lambda = null;
if (this.isGILDAS()) {
lambda = SPEED_OF_LIGHT / this.restfreq;
} else {
lambda = SPEED_OF_LIGHT / this.crval3;
}
let omega = Math.PI * bmin * bmax / 4 / Math.log(2);
let step1 = 2 * kb * omega / (lambda * lambda);
let result = step1 / 1e-26;
return result;
}
}
kelvinPerJansky() {
let jperk = this.janskyPerKelvin();
......@@ -119,21 +133,21 @@ class FitsHeader{
* Returns a title to be displayed above the spectrum
* @returns {string} HTML formatted text
*/
getSpectrumTitle(){
let title = "<span>" +
Number(degToArcsec(this.bmin)).toFixed(2) + "' x " + "</span>" +
"<span>" + Number(degToArcsec(this.bmaj)).toFixed(2) + "', " + "</span>" +
"<span>" + "PA " + Number(this.bpa).toFixed(1) + "°" + "</span>";
if(!this.isSpectrumInK()){
title = title +"<span>, " + Number(this.janskyPerKelvin()).toExponential(2) + " Jy/K</span>";
getSpectrumTitle() {
let title = "<span>" +
Number(degToArcsec(this.bmin)).toFixed(2) + "' x " + "</span>" +
"<span>" + Number(degToArcsec(this.bmaj)).toFixed(2) + "', " + "</span>" +
"<span>" + "PA " + Number(this.bpa).toFixed(1) + "°" + "</span>";
if (!this.isSpectrumInK()) {
title = title + "<span>, " + Number(this.janskyPerKelvin()).toExponential(2) + " Jy/K</span>";
}
return title;
}
getVCenter(){
getVCenter() {
let vcenter = this.crval3;
if(this.ctype3 === "FREQ" || this.ctype3 === "VRAD") {
if (this.ctype3 === "FREQ" || this.ctype3 === "VRAD") {
vcenter = 0;
}
return vcenter;
......@@ -143,13 +157,13 @@ class FitsHeader{
* Returns a summary of opened fits file (product name and list of axis)
* @returns {string} HTML formatted text
*/
getFitsSummary(){
let FITSSummary = '<strong>' + this.product + '</strong> - OBJECT = <strong>'
+ this.object + '</strong> - NAXIS = <strong>'
+ this.naxis + '</strong> - NAXIS1 = <strong>'
+ this.naxis1 + '</strong> - NAXIS2 = <strong>'
+ this.naxis2 + '</strong> - NAXIS3 = <strong>'
+ this.naxis3 + '</strong>';
getFitsSummary() {
let FITSSummary = '<strong>' + this.product + '</strong> - OBJECT = <strong>' +
this.object + '</strong> - NAXIS = <strong>' +
this.naxis + '</strong> - NAXIS1 = <strong>' +
this.naxis1 + '</strong> - NAXIS2 = <strong>' +
this.naxis2 + '</strong> - NAXIS3 = <strong>' +
this.naxis3 + '</strong>';
if (this.naxis4 !== undefined) {
FITSSummary += ' - NAXIS4 = <strong>' + this.axis4 + '</strong>';
......@@ -158,8 +172,8 @@ class FitsHeader{
return FITSSummary;
}
getCdelt3prim(){
let result = 0.;
getCdelt3prim() {
let result = 0.;
if ((this.isGILDAS()) && (this.ctype3 === "VRAD")) {
//~ _cunit3 = "M/S";
result = Math.abs(this.cdelt3) * UNIT_FACTOR[this.cunit3] / UNIT_FACTOR[DEFAULT_OUTPUT_UNIT[this.ctype3]];
......@@ -184,11 +198,11 @@ class FitsHeader{
/**
* @returns {boolean} true if spectrum is in Kelvin
*/
isSpectrumInK(){
isSpectrumInK() {
if (this.bunit === "K (Ta*)")
return true;
else{
if(this.bunit.startsWith("K")){
else {
if (this.bunit.startsWith("K")) {
let error = "bunit is probably Kelvin but not recognized as such";
alert(error);
throw new Error(error);
......@@ -200,8 +214,8 @@ class FitsHeader{
/**
* Returns true if field instrume contains SITELLE
*/
isSITELLE(){
if(this.instrume === "SITELLE")
isSITELLE() {
if (this.instrume === "SITELLE")
return true;
return false;
}
......@@ -209,8 +223,8 @@ class FitsHeader{
/**
* Returns true if field instrume contains MUSE
*/
isMUSE(){
if(this.instrume === "MUSE")
isMUSE() {
if (this.instrume === "MUSE")
return true;
return false;
}
......@@ -218,8 +232,8 @@ class FitsHeader{
/**
* Returns true if field origin starts with CASA
*/
isCASA(){
if(this.origin.startsWith("CASA"))
isCASA() {
if (this.origin.startsWith("CASA"))
return true;
return false;
}
......@@ -227,9 +241,9 @@ class FitsHeader{
/**
* Returns true if field origin starts with GILDAS
*/
isGILDAS(){
isGILDAS() {
//this is the general method to check that a file comes from GILDAS
if(this.origin.startsWith("GILDAS"))
if (this.origin.startsWith("GILDAS"))
return true;
return false;
}
......@@ -248,4 +262,4 @@ class FitsHeader{
}
let FITS_HEADER = new FitsHeader(header, product);
export {FITS_HEADER}
\ No newline at end of file
export { FITS_HEADER }
\ No newline at end of file
......@@ -4,8 +4,6 @@ const relFITSFilePath = JSON.parse(document.getElementById("relFITSFilePath").te
const header = JSON.parse(document.getElementById("header").textContent);
const product = JSON.parse(document.getElementById("product").textContent);
const default_lut_index = JSON.parse(document.getElementById("defaultLutIndex").textContent);
console.log("### spectroServer");
console.log(document.getElementById("spectroServer").textContent.trim());
const URL_SPECTRO_SERVER = document.getElementById("spectroServer").textContent.trim();
/**
......@@ -13,17 +11,22 @@ const URL_SPECTRO_SERVER = document.getElementById("spectroServer").textContent.
*/
let dataPaths = {
// spectrum (top right image)
spectrum : "",
spectrum: "",
// averaged spectrum (bottom right image)
averageSpectrum : "",
averageSpectrum: "",
// slice PNG file (top left image)
relSlicePNG : "",
relSlicePNG: "",
// summed slice PNG file (bottom left image)
relSummedSlicesPNG : "",
relFITSFilePath : relFITSFilePath
}
export{
withSAMP, dataPaths, header, product, default_lut_index, URL_ROOT, URL_SPECTRO_SERVER
relSummedSlicesPNG: "",
relFITSFilePath: relFITSFilePath
}
export {
withSAMP,
dataPaths,
header,
product,
default_lut_index,
URL_ROOT,
URL_SPECTRO_SERVER
}
\ No newline at end of file
import { ShapesFactory } from "./olqv_shapes.js";
import { getProjection } from "./olqv_projections.js";
import { FITS_HEADER } from "./fitsheader.js";
import {DecDeg2DMS, DecDeg2HMS} from "./utils.js";
class AxesFactory extends ShapesFactory {
static enter(what) {
console.group(this.name + "." + what);
}
static exit() {
console.groupEnd();
}
constructor(viewer, proj_type) {
super(viewer, 'axes');
this.numeridians = 4;
this.nparallels = 4;
// number of decimals for ra/dec values on axis
this._displayed_decimals = Math.abs(FITS_HEADER.cdelt1).toExponential().split("-")[1] - 1;
//let context = this.infosBlock.getContext();
this.projection = getProjection(proj_type);
this.CDELT1 = FITS_HEADER.cdelt1 * Math.PI / 180;
this.CDELT2 = FITS_HEADER.cdelt2 * Math.PI / 180;
this.axisStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'green',
width: 2,
}),
});
}
build() {
let axes = this.getAxes();
let lineString = new ol.geom.MultiLineString(axes);
let f = new ol.Feature({ geometry: lineString.simplify(1) });
f.setStyle(this.axisStyle);
this.layer.setZIndex(10);
this.layer.getSource().addFeature(f);
for (let i = 0; i < axes.length; i++) {
this.addExtremityPoint(axes[i][0]);
this.addExtremityPoint(axes[i][axes[i].length - 1]);
}
this.layer.set('axes', "axes");
this.layer.changed();
}
/**
* Show coordinates at both axis extremity
* @param {*} coords
*/
addExtremityPoint(coords) {
let radec = this.projection.iRaiDecToRaDec(coords[0], coords[1]);
let point = new ol.geom.Point(coords);
let f2 = new ol.Feature({ geometry: point });
f2.setStyle(new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'green',
width: 10,
}),
text: new ol.style.Text({
font: '12px Calibri,sans-serif',
fill: new ol.style.Fill({ color: '#000' }),
stroke: new ol.style.Stroke({
color: '#fff',
width: 2
}),
// get the text from the feature - `this` is ol.Feature
// and show only under certain resolution
text: "RA : " + DecDeg2HMS(radec['ra']) + ", DEC : " + DecDeg2DMS(radec['dec'])
//text: "RA : " + radec['ra'].toFixed(this._displayed_decimals) + ", DEC : " + radec['dec'].toFixed(this._displayed_decimals)
})
}));
this.layer.getSource().addFeature(f2);
}
getMeridians(limits) {
// Plot the meridians
console.log("### MERIDIANS");
const dra = (limits["RA_max"] - limits["RA_min"]) / (this.numeridians - 1);
let decs = [];
for (let i = 0; i < FITS_HEADER.naxis2; i++) {
decs.push(limits["DEC_min"] + i * (limits["DEC_max"] - limits["DEC_min"]) / (FITS_HEADER.naxis2 - 1));
}
let coordinates_list = [];
for (let i = 0; i < this.numeridians; i++) {
let coordinates = [];
let ra_ = limits["RA_min"] + i * dra;
for (let j = 0; j < FITS_HEADER.naxis2; j++) {
let xy = this.projection.absToRel([ra_], [decs[j]]);
const i_xp = Math.round(FITS_HEADER.crpix1 + (xy['x'][0]) / (this.CDELT1) - 1);
const i_yp = Math.round(FITS_HEADER.crpix2 + (xy['y'][0]) / (this.CDELT2) - 1);
if (this.viewer.isInExtent(i_xp, i_yp)) {
coordinates.push([i_xp, i_yp]);
}
}
if (coordinates.length > 1)
coordinates_list.push(coordinates);
}
return coordinates_list;
}
getParallels(limits) {
const ddec = (limits["DEC_max"] - limits["DEC_min"]) / (this.nparallels);
let ras = [];
for (let i = 0; i < FITS_HEADER.naxis1; i++) {
ras.push(limits["RA_min"] + i * (limits["RA_max"] - limits["RA_min"]) / (FITS_HEADER.naxis1 - 1))
}
let coordinates_list = [];
for (let i = 0; i < this.nparallels; i++) {
let coordinates = [];
let ixpix = [];
let iypix = [];
let dec_ = limits["DEC_min"] + i * ddec;
for (let j = 0; j < FITS_HEADER.naxis1; j++) {
let xy = this.projection.absToRel([ras[j]], [dec_]);
const i_xp = Math.round(FITS_HEADER.crpix1 + (xy['x'][0]) / (this.CDELT1) - 1);
const i_yp = Math.round(FITS_HEADER.crpix2 + (xy['y'][0]) / (this.CDELT2) - 1);
ixpix.push(i_xp);
iypix.push(i_yp);
if (this.viewer.isInExtent(i_xp, i_yp)) {
coordinates.push([i_xp, i_yp]);
}
if (coordinates.length > 1)
coordinates_list.push(coordinates);
}
}
return coordinates_list;
}
getLimits() {
let result = { "RA_min": 0, "RA_max": 0, "DEC_min": 0, "DEC_max": 0 };
let x = new Array(FITS_HEADER.naxis1).fill(0); //np.zeros(shape=(NAXIS1), dtype=float)
let y = new Array(FITS_HEADER.naxis2).fill(0); //np.zeros(shape=(NAXIS2), dtype=float)
for (let i = 0; i < FITS_HEADER.naxis1; i++) {
x[i] = (i - FITS_HEADER.crpix1) * this.CDELT1;
}
for (let j = 0; j < FITS_HEADER.naxis2; j++) {
y[j] = (j - FITS_HEADER.crpix2) * this.CDELT2;
}
let ra = [];
let dec = [];
for (let i = 0; i < x.length; i++) {
ra.push([]);
dec.push([]);
for (let j = 0; j < y.length; j++) {
let raDec = this.projection.relToAbs([x[i]], [y[j]]);
ra[i].push(raDec['ra'][0]);
dec[i].push(raDec['dec'][0]);
if (i == 0 && j == 0) {
result["RA_min"] = raDec['ra'][0];
result["DEC_min"] = raDec['dec'][0];
result["RA_max"] = raDec['ra'][0];
result["DEC_max"] = raDec['dec'][0];
} else {
if (raDec['ra'][0] < result["RA_min"]) {
result["RA_min"] = raDec['ra'][0];
}
if (raDec['ra'][0] > result["RA_max"]) {
result["RA_max"] = raDec['ra'][0];
}
if (raDec['dec'][0] < result["DEC_min"]) {
result["DEC_min"] = raDec['dec'][0];
}
if (raDec['dec'][0] > result["DEC_max"]) {
result["DEC_max"] = raDec['dec'][0];
}
}
}
}
return result;
}
// End of projection determination section
getAxes() {
let limits = this.getLimits();
// Plot the meridians
let coordinates_list = this.getMeridians(limits);
let parallels = this.getParallels(limits);
coordinates_list.push.apply(coordinates_list, parallels);
//return multipoints;
return coordinates_list;
}
}
export {
AxesFactory
}
\ No newline at end of file
......@@ -94,7 +94,7 @@ class ContoursFactory extends ShapesFactory {
}
importYAFITSContours(yAFITSContours) {
ContoursFactory.enter(this.importYAFITSContours.name);
//ContoursFactory.enter(this.importYAFITSContours.name);
this.clear();
var features = new Array();
yAFITSContours.forEach((contour) => {
......@@ -114,7 +114,7 @@ class ContoursFactory extends ShapesFactory {
this.source.addFeatures(features);
this.show();
this.close();
ContoursFactory.exit()
//ContoursFactory.exit()
}
getMeasureContourPromise(feature, relFITSFilePath) {
......@@ -348,7 +348,7 @@ class ContoursFactoryGUI {
let population = histogram[0];
let bins = histogram[1];
let data = new Array(2 * population.length);
for (i = 0; i < population.length; i++) {
for (let i = 0; i < population.length; i++) {
data[i] = [bins[i], population[i]];
data[i + 1] = [bins[i + 1], population[i]];
}
......@@ -454,7 +454,7 @@ class ContoursFactoryGUI {
let cumulDist = this.viewer.getStatistics()["cumuldist"];
console.dir(cumulDist);
let data = new Array(cumulDist.length);
for (i = 0; i < data.length; i++) {
for (let i = 0; i < data.length; i++) {
data[i] = [bins[i], cumulDist[i]];
}
let mean = this.viewer.getStatistics()["mean"]
......@@ -610,8 +610,8 @@ class ContoursFactoryGUI {
resolve(resp["result"]["features"]);
}
ContoursFactoryGUI.exit();
})
})
});
})
ContoursFactoryGUI.exit();
return p;
}
......@@ -619,7 +619,6 @@ class ContoursFactoryGUI {
queryYAFITSContours(relFITSFilePath) {
ContoursFactoryGUI.enter(this.queryYAFITSContours.name);
document.getElementById('loading').style.display = "block";
let iFREQ = this.viewer.getSliceRange();
let postParams;
switch (this.contoursMethod) {
......@@ -650,7 +649,7 @@ class ContoursFactoryGUI {
default:
alert("No contours method defined");
}
if (postParams) {
var p = this.getContoursPromise(postParams);
p.then (
......
import {ShapesFactory} from "./olqv_shapes.js";
class Selector {
static enter(what) {
......
......@@ -119,6 +119,21 @@ class Viewer {
Viewer.exit();
}
isInExtent(x, y){
/*console.log(this.coordinatesFormatter.decLabelFormatter.dec0);
console.log(this.coordinatesFormatter.decLabelFormatter.dec1);
console.log(this.coordinatesFormatter.raLabelFormatter.ra0);
console.log(this.coordinatesFormatter.decLabelFormatter.ra1);*/
if(x > this.extent[0] &&
x < this.extent[2] &&
y > this.extent[1] &&
y < this.extent[3] ){
return true;
}
return false;
}
disableControls() {
Viewer.enter(this.disableControls.name);
if (this.controls) {
......
......@@ -10,7 +10,7 @@ import { displayVotable } from "./votable.js";
*/