mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2026-04-28 11:53:18 -07:00
add button to change unit
This commit is contained in:
committed by
Matthieu Baumann
parent
6cab5f9efd
commit
b35f79ad0a
@@ -28,11 +28,12 @@
|
||||
}
|
||||
);
|
||||
|
||||
hips = aladin.newImageSurvey("http://alasky.cds.unistra.fr/LGLBSHI", {
|
||||
hips = aladin.newImageSurvey("https://alasky.cds.unistra.fr/test-compression-cubes/DHIGLS/", {
|
||||
successCallback: (hips) => {
|
||||
hips.setFrequency({value: 0.21101690259115785, unit: "m"}) // GALFA
|
||||
}
|
||||
});
|
||||
// compressed https://alasky.cds.unistra.fr/test-compression-cubes/DHIGLS/
|
||||
//hips = aladin.newImageSurvey("http://alasky.cds.unistra.fr/DHIGLS");
|
||||
//hips = aladin.newImageSurvey("https://alasky.cds.unistra.fr/MUSE3D");
|
||||
// http://alasky.cds.unistra.fr/LGLBSHI
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
.aladin-lite-spectra-displayer .aladin-spectra-unit-selector {
|
||||
position: absolute;
|
||||
bottom: 3rem;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.aladin-imageCanvas {
|
||||
position: absolute;
|
||||
|
||||
@@ -499,7 +499,7 @@ export let HiPS = (function () {
|
||||
// HiPS3D special keywords
|
||||
self.hipsOrderFreq = properties && properties.hips_order_freq && +properties.hips_order_freq;
|
||||
self.hipsTileDepth = properties && properties.hips_tile_depth && +properties.hips_tile_depth;
|
||||
|
||||
self.obsRestFreq = properties && properties.obs_restfreq && +properties.obs_restfreq;
|
||||
|
||||
// Max order
|
||||
const maxOrder = PropertyParser.maxOrder(properties)
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
// along with Aladin Lite.
|
||||
//
|
||||
|
||||
import { Input } from "./gui/Widgets/Input";
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
@@ -29,17 +31,97 @@
|
||||
*****************************************************************************/
|
||||
|
||||
export class SpectraDisplayer {
|
||||
static UNIT = {
|
||||
FREQUENCY: {
|
||||
label: "f",
|
||||
units: [
|
||||
{ unit: "THz", factor: 1e12 },
|
||||
{ unit: "GHz", factor: 1e9 },
|
||||
{ unit: "MHz", factor: 1e6 },
|
||||
{ unit: "kHz", factor: 1e3 },
|
||||
{ unit: "Hz", factor: 1 }
|
||||
]
|
||||
},
|
||||
WAVELENGTH: {
|
||||
label: "λ",
|
||||
units: [
|
||||
{ unit: "km", factor: 1e3 },
|
||||
{ unit: "m", factor: 1 },
|
||||
{ unit: "mm", factor: 1e-3 },
|
||||
{ unit: "μm", factor: 1e-6 },
|
||||
{ unit: "nm", factor: 1e-9 },
|
||||
{ unit: "Å", factor: 1e-10 },
|
||||
{ unit: "pm", factor: 1e-12 },
|
||||
]
|
||||
},
|
||||
VELOCITY: {
|
||||
label: "v",
|
||||
units: [
|
||||
{ unit: "km/s", factor: 1e3 },
|
||||
{ unit: "m/s", factor: 1 },
|
||||
{ unit: "mm/s", factor: 1e-3 },
|
||||
{ unit: "μm/s", factor: 1e-6 },
|
||||
{ unit: "nm/s", factor: 1e-9 },
|
||||
{ unit: "pm/s", factor: 1e-12 },
|
||||
]
|
||||
},
|
||||
convertFrequency: function(freq, options) {
|
||||
const SPEED_OF_LIGHT = 299792458.0;
|
||||
|
||||
let unit = options && options.unit;
|
||||
|
||||
let value;
|
||||
if (unit === SpectraDisplayer.UNIT.WAVELENGTH) {
|
||||
value = SPEED_OF_LIGHT / freq;
|
||||
} else if (unit === SpectraDisplayer.UNIT.VELOCITY) {
|
||||
// A velocity is given in "m/s"
|
||||
const restFreq = options && options.restFreq;
|
||||
if (!restFreq) {
|
||||
throw 'When giving a velocity, a rest frequency must be given as well for computing the frequency to query the HiPS'
|
||||
}
|
||||
|
||||
value = SPEED_OF_LIGHT * (1.0 - freq / restFreq)
|
||||
} else {
|
||||
// unit is "Hz"
|
||||
value = freq;
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
convertPrecisionFrequency: function(prec, freq, options) {
|
||||
const SPEED_OF_LIGHT = 299792458.0;
|
||||
|
||||
let unit = options && options.unit;
|
||||
|
||||
let value;
|
||||
if (unit === SpectraDisplayer.UNIT.WAVELENGTH) {
|
||||
value = SPEED_OF_LIGHT * prec / (freq * freq);
|
||||
} else if (unit === SpectraDisplayer.UNIT.VELOCITY) {
|
||||
// A velocity is given in "m/s"
|
||||
const restFreq = options && options.restFreq;
|
||||
if (!restFreq) {
|
||||
throw 'When giving a velocity, a rest frequency must be given as well for computing the frequency to query the HiPS'
|
||||
}
|
||||
|
||||
value = prec * SPEED_OF_LIGHT / restFreq
|
||||
} else {
|
||||
// unit is "Hz"
|
||||
value = prec;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
constructor(hips, options) {
|
||||
let createPlotCanvas = (name) => {
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.classList.add(name);
|
||||
canvas.width = this.width;
|
||||
canvas.height = this.height;
|
||||
//canvas.style.pointerEvents = "none";
|
||||
canvas.style.position = "absolute";
|
||||
canvas.style.left = "50%";
|
||||
canvas.style.transform = "translateX(-50%)";
|
||||
canvas.style.bottom = "2px";
|
||||
canvas.style.position = "absolute"
|
||||
canvas.style.top = 0;
|
||||
canvas.style.left = 0;
|
||||
|
||||
this.view.aladinDiv.appendChild(canvas);
|
||||
return canvas;
|
||||
@@ -52,8 +134,8 @@ export class SpectraDisplayer {
|
||||
this.scaleY = undefined;
|
||||
this.height = options && options.height || 300;
|
||||
this.width = options && options.width || 600;
|
||||
this.minY = {};
|
||||
this.maxY = {};
|
||||
this.minY = undefined;
|
||||
this.maxY = undefined;
|
||||
this.mouseFreq = undefined;
|
||||
|
||||
// One canvas for the spectra
|
||||
@@ -68,11 +150,49 @@ export class SpectraDisplayer {
|
||||
canvasLabels.style.pointerEvents = "none"
|
||||
this.ctxLabels = canvasLabels.getContext("2d");
|
||||
|
||||
let self = this;
|
||||
// a selector for choosing the unit
|
||||
let unitSelector = new Input({
|
||||
label: "Unit:",
|
||||
name: "unit selector",
|
||||
value: "f",
|
||||
type: 'select',
|
||||
classList: ['aladin-spectra-unit-selector'],
|
||||
options: [
|
||||
SpectraDisplayer.UNIT.FREQUENCY.label,
|
||||
SpectraDisplayer.UNIT.WAVELENGTH.label,
|
||||
SpectraDisplayer.UNIT.VELOCITY.label,
|
||||
],
|
||||
change: (e) => {
|
||||
let label = e.target.value;
|
||||
|
||||
if (label === SpectraDisplayer.UNIT.FREQUENCY.label) {
|
||||
self.unit = SpectraDisplayer.UNIT.FREQUENCY
|
||||
} else if (label === SpectraDisplayer.UNIT.WAVELENGTH.label) {
|
||||
self.unit = SpectraDisplayer.UNIT.WAVELENGTH
|
||||
} else {
|
||||
self.unit = SpectraDisplayer.UNIT.VELOCITY
|
||||
}
|
||||
|
||||
self._redrawLabels();
|
||||
},
|
||||
})
|
||||
|
||||
this.unit = SpectraDisplayer.UNIT.FREQUENCY;
|
||||
|
||||
let divNode = document.createElement("div");
|
||||
divNode.style.position = "absolute";
|
||||
divNode.style.left = "50%";
|
||||
divNode.style.transform = "translateX(-50%)";
|
||||
divNode.style.bottom = "2px";
|
||||
divNode.style.width = this.width + "px";
|
||||
divNode.style.height = this.height + "px";
|
||||
divNode.classList.add("aladin-lite-spectra-displayer")
|
||||
|
||||
divNode.appendChild(this.canvas)
|
||||
divNode.appendChild(canvasCursor)
|
||||
divNode.appendChild(canvasLabels)
|
||||
divNode.appendChild(unitSelector.element())
|
||||
|
||||
this.divNode = divNode;
|
||||
|
||||
@@ -97,9 +217,8 @@ export class SpectraDisplayer {
|
||||
let v = this.data.values[Math.round(mx / this.scaleX)]
|
||||
|
||||
let len = this.data.values.length;
|
||||
let fOrder = this.data.fOrder;
|
||||
|
||||
v = this.height - (v - this.minY[fOrder]) * this.scaleY
|
||||
v = this.height - (v - this.minY) * this.scaleY
|
||||
if (my >= v) {
|
||||
isDragging = true;
|
||||
lastMouse = { x: mx, y: my };
|
||||
@@ -109,7 +228,7 @@ export class SpectraDisplayer {
|
||||
// Draw the vertical line that can be grabed to move the slice
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(this.scaleX * len / 2, this.height);
|
||||
this.ctx.lineTo(this.scaleX * len / 2, this.height - (this.maxY[fOrder] - this.minY[fOrder]) * this.scaleY);
|
||||
this.ctx.lineTo(this.scaleX * len / 2, this.height - (this.maxY - this.minY) * this.scaleY);
|
||||
this.ctx.strokeStyle = "red";
|
||||
this.ctx.lineWidth = 10;
|
||||
|
||||
@@ -150,7 +269,7 @@ export class SpectraDisplayer {
|
||||
|
||||
let fOrder = this.data.fOrder;
|
||||
|
||||
v = this.height - (v - this.minY[fOrder]) * this.scaleY
|
||||
v = this.height - (v - this.minY) * this.scaleY
|
||||
canvas.style.cursor = 'default';
|
||||
|
||||
this.ctxCursor.clearRect(0, 0, this.width, this.height);
|
||||
@@ -180,7 +299,7 @@ export class SpectraDisplayer {
|
||||
// Draw the vertical line that can be grabed to move the slice
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(this.scaleX * len / 2, this.height);
|
||||
this.ctx.lineTo(this.scaleX * len / 2, this.height - (this.maxY[fOrder] - this.minY[fOrder]) * this.scaleY);
|
||||
this.ctx.lineTo(this.scaleX * len / 2, this.height - (this.maxY - this.minY) * this.scaleY);
|
||||
this.ctx.strokeStyle = "red";
|
||||
this.ctx.lineWidth = 10;
|
||||
|
||||
@@ -290,26 +409,26 @@ export class SpectraDisplayer {
|
||||
|
||||
const fOrder = this.data.fOrder;
|
||||
|
||||
if (Number.isFinite(this.minY[fOrder])) {
|
||||
this.minY[fOrder] = Math.min(...valuesWithNoNans, this.minY[fOrder])
|
||||
if (Number.isFinite(this.minY)) {
|
||||
this.minY = Math.min(...valuesWithNoNans, this.minY)
|
||||
} else {
|
||||
this.minY[fOrder] = Math.min(...valuesWithNoNans)
|
||||
this.minY = Math.min(...valuesWithNoNans)
|
||||
}
|
||||
if (Number.isFinite(this.maxY[fOrder])) {
|
||||
this.maxY[fOrder] = Math.max(...valuesWithNoNans, this.maxY[fOrder])
|
||||
if (Number.isFinite(this.maxY)) {
|
||||
this.maxY = Math.max(...valuesWithNoNans, this.maxY)
|
||||
} else {
|
||||
this.maxY[fOrder] = Math.max(...valuesWithNoNans)
|
||||
this.maxY = Math.max(...valuesWithNoNans)
|
||||
}
|
||||
|
||||
this.scaleX = this.width / (len - 1);
|
||||
this.scaleY = (this.maxY[fOrder] - this.minY[fOrder] === 0) ? 1 : this.height / (this.maxY[fOrder] - this.minY[fOrder]);
|
||||
this.scaleY = (this.maxY - this.minY === 0) ? 1 : this.height / (this.maxY - this.minY);
|
||||
|
||||
this._redrawSpectra(values)
|
||||
|
||||
// Draw the vertical line that can be grabed to move the slice
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(this.scaleX * len / 2, this.height);
|
||||
this.ctx.lineTo(this.scaleX * len / 2, this.height - (this.maxY[fOrder] - this.minY[fOrder]) * this.scaleY);
|
||||
this.ctx.lineTo(this.scaleX * len / 2, this.height - (this.maxY - this.minY) * this.scaleY);
|
||||
this.ctx.strokeStyle = "red";
|
||||
this.ctx.lineWidth = 2;
|
||||
this.ctx.stroke();
|
||||
@@ -318,20 +437,32 @@ export class SpectraDisplayer {
|
||||
}
|
||||
|
||||
_redrawLabels() {
|
||||
function freq2String(frequencyHz, precisionHz) {
|
||||
const units = [
|
||||
{ unit: "THz", factor: 1e12 },
|
||||
{ unit: "GHz", factor: 1e9 },
|
||||
{ unit: "MHz", factor: 1e6 },
|
||||
{ unit: "kHz", factor: 1e3 },
|
||||
{ unit: "Hz", factor: 1 }
|
||||
];
|
||||
|
||||
let self = this;
|
||||
function spectraValue2String(freq, precision) {
|
||||
let units = self.unit.units;
|
||||
|
||||
let x = SpectraDisplayer.UNIT.convertFrequency(
|
||||
freq,
|
||||
{
|
||||
unit: self.unit,
|
||||
restFreq: self.hips.obsRestFreq
|
||||
}
|
||||
)
|
||||
|
||||
let dx = SpectraDisplayer.UNIT.convertPrecisionFrequency(
|
||||
precision,
|
||||
freq,
|
||||
{
|
||||
unit: self.unit,
|
||||
restFreq: self.hips.obsRestFreq
|
||||
}
|
||||
)
|
||||
|
||||
for (const { unit, factor } of units) {
|
||||
const value = frequencyHz / factor;
|
||||
const precisionInUnit = precisionHz / factor;
|
||||
const value = x / factor;
|
||||
const precisionInUnit = dx / factor;
|
||||
|
||||
if (value >= 1 || unit === "Hz") {
|
||||
if (Math.abs(value) >= 1 || unit === units[units.length - 1].unit) {
|
||||
// Calculate number of decimal places needed to show the given precision
|
||||
const decimals = Math.max(0, Math.ceil(-Math.log10(precisionInUnit)));
|
||||
return value.toFixed(decimals) + " " + unit;
|
||||
@@ -349,20 +480,20 @@ export class SpectraDisplayer {
|
||||
|
||||
// min window freq
|
||||
this.ctxLabels.textAlign = "left"; // Horizontally centered
|
||||
this.ctxLabels.fillText(freq2String(this.data.freqMin, this.data.freqStep), 0, this.height - 20);
|
||||
this.ctxLabels.fillText(spectraValue2String(this.data.freqMin, this.data.freqStep), 0, this.height - 20);
|
||||
|
||||
// max window freq
|
||||
this.ctxLabels.textAlign = "right"; // Horizontally centered
|
||||
this.ctxLabels.fillText(freq2String(this.data.freqMax, this.data.freqStep), this.width, this.height - 20);
|
||||
this.ctxLabels.fillText(spectraValue2String(this.data.freqMax, this.data.freqStep), this.width, this.height - 20);
|
||||
|
||||
// current window freq
|
||||
this.ctxLabels.textAlign = "center"; // Horizontally centered
|
||||
let fStr;
|
||||
if (this.mouseFreq) {
|
||||
this.ctxLabels.fillStyle = "yellow";
|
||||
fStr = freq2String(this.mouseFreq, this.data.freqStep);
|
||||
fStr = spectraValue2String(this.mouseFreq, this.data.freqStep);
|
||||
} else {
|
||||
fStr = freq2String(this.data.freq, this.data.freqStep);
|
||||
fStr = spectraValue2String(this.data.freq, this.data.freqStep);
|
||||
}
|
||||
this.ctxLabels.fillText(fStr, this.width / 2, this.height - 20);
|
||||
}
|
||||
@@ -417,7 +548,7 @@ export class SpectraDisplayer {
|
||||
this.ctx.moveTo(x - this.scaleX, prevY)
|
||||
}
|
||||
|
||||
y = this.height - (array[i] - this.minY[fOrder]) * this.scaleY;
|
||||
y = this.height - (array[i] - this.minY) * this.scaleY;
|
||||
if (i === 0) {
|
||||
this.ctx.moveTo(x, y);
|
||||
} else {
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
// Copyright 2023 - UDS/CNRS
|
||||
// The Aladin Lite program is distributed under the terms
|
||||
// of the GNU General Public License version 3.
|
||||
//
|
||||
// This file is part of Aladin Lite.
|
||||
//
|
||||
// Aladin Lite is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 3 of the License.
|
||||
//
|
||||
// Aladin Lite is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// The GNU General Public License is available in COPYING file
|
||||
// along with Aladin Lite.
|
||||
//
|
||||
|
||||
import { SelectorButton } from "../Widgets/Selector";
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
*
|
||||
* File gui/Form.js
|
||||
*
|
||||
* A context menu that shows when the user right clicks, or long touch on touch device
|
||||
*
|
||||
*
|
||||
* Author: Matthieu Baumann[CDS]
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
Exemple of layout object
|
||||
{
|
||||
{
|
||||
label: "ID",
|
||||
type: "text",
|
||||
value: "the placeholder value...",
|
||||
},
|
||||
*/
|
||||
|
||||
/*
|
||||
options = {cmap1: {imgUrl, change}, cmap2: imgUrl, selected: cmap1}
|
||||
*/
|
||||
export class CmapSelector extends SelectorButton {
|
||||
/**
|
||||
* Create a layout
|
||||
* @param {{layout: {type: String, name: String, value: Number | String, placeholder: Number | String, change: Function } | {type: String, name: String, checked: Boolean, change: Function } | { type: String, name: String, value: String, options: Array.<String>, change: Function }, cssStyle: Object}} options - Represents the structure of the Tabs
|
||||
* @param {DOMElement} target - The parent element.
|
||||
* @param {String} position - The position of the tabs layout relative to the target.
|
||||
* For the list of possibilities, see https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML
|
||||
*/
|
||||
constructor(options, aladin, target, position = 'beforeend') {
|
||||
for (const cmap in options) {
|
||||
if (cmap === 'selected') {
|
||||
continue;
|
||||
}
|
||||
|
||||
options[cmap] = {
|
||||
...options[cmap],
|
||||
cssStyle: {
|
||||
//border: 'none',
|
||||
//borderRadius: '0',
|
||||
//backgroundColor: 'black',
|
||||
color: 'black',
|
||||
width: '4rem',
|
||||
overflow: 'hidden',
|
||||
'font-family': 'monospace',
|
||||
},
|
||||
content: cmap,
|
||||
tooltip: {content: cmap, position: {direction: 'left'}},
|
||||
}
|
||||
}
|
||||
super(options, aladin, target, position)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user