mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2025-12-12 15:49:18 -08:00
rename ImageSurvey in ImageHiPS, add a global cache for HiPS and FITS
This commit is contained in:
@@ -1024,10 +1024,10 @@ impl App {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn add_image_survey(&mut self, hips_cfg: HiPSCfg) -> Result<(), JsValue> {
|
||||
pub(crate) fn add_image_hips(&mut self, hips_cfg: HiPSCfg) -> Result<(), JsValue> {
|
||||
let hips =
|
||||
self.layers
|
||||
.add_image_survey(&self.gl, hips_cfg, &mut self.camera, &self.projection)?;
|
||||
.add_image_hips(&self.gl, hips_cfg, &mut self.camera, &self.projection)?;
|
||||
self.tile_fetcher
|
||||
.launch_starting_hips_requests(hips, &mut self.downloader);
|
||||
|
||||
|
||||
@@ -364,11 +364,11 @@ impl WebClient {
|
||||
/// * If the number of surveys is greater than 4. For the moment, due to the limitations
|
||||
/// of WebGL2 texture units on some architectures, the total number of surveys rendered is
|
||||
/// limited to 4.
|
||||
#[wasm_bindgen(js_name = addImageSurvey)]
|
||||
pub fn add_image_survey(&mut self, hips: JsValue) -> Result<(), JsValue> {
|
||||
#[wasm_bindgen(js_name = addImageHiPS)]
|
||||
pub fn add_image_hips(&mut self, hips: JsValue) -> Result<(), JsValue> {
|
||||
// Deserialize the survey objects that compose the survey
|
||||
let hips = serde_wasm_bindgen::from_value(hips)?;
|
||||
self.app.add_image_survey(hips)?;
|
||||
self.app.add_image_hips(hips)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ impl Layers {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_image_survey(
|
||||
pub fn add_image_hips(
|
||||
&mut self,
|
||||
gl: &WebGlContext,
|
||||
hips: HiPSCfg,
|
||||
|
||||
@@ -109,8 +109,8 @@ A.aladin = function (divSelector, options) {
|
||||
* @param {string} id - Mandatory unique identifier for the survey.
|
||||
* @param {string} url - Can be an `url` that refers to a HiPS.
|
||||
* Or it can be a "CDS ID" pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}.
|
||||
* @param {ImageSurveyOptions} [options] - Options describing the survey
|
||||
* @returns {ImageSurvey} - A HiPS image object
|
||||
* @param {ImageHiPSOptions} [options] - Options describing the survey
|
||||
* @returns {ImageHiPS} - A HiPS image object
|
||||
*/
|
||||
A.imageHiPS = function (id, url, options) {
|
||||
return Aladin.createImageSurvey(
|
||||
@@ -131,7 +131,7 @@ A.imageHiPS = function (id, url, options) {
|
||||
* @memberof A
|
||||
* @param {string} url - Options describing the fits file. An url is mandatory
|
||||
* @param {ImageFITSOptions} [options] - Options describing the fits file. An url is mandatory
|
||||
* @returns {ImageSurvey} - A HiPS image object
|
||||
* @returns {ImageFITS} - A HiPS image object
|
||||
* @example
|
||||
* const sourceObj = A.source(180.0, 30.0, data, options);
|
||||
*/
|
||||
|
||||
@@ -37,10 +37,10 @@ import { Sesame } from "./Sesame.js";
|
||||
import { PlanetaryFeaturesNameResolver } from "./PlanetaryFeaturesNameResolver.js";
|
||||
import { CooFrameEnum } from "./CooFrameEnum.js";
|
||||
import { MeasurementTable } from "./MeasurementTable.js";
|
||||
import { ImageSurvey } from "./ImageSurvey.js";
|
||||
import { ImageHiPS } from "./ImageHiPS.js";
|
||||
import { Coo } from "./libs/astro/coo.js";
|
||||
import { CooConversion } from "./CooConversion.js";
|
||||
import { MocServer } from './MocServer';
|
||||
import { HiPSCache } from './DefaultHiPSCache';
|
||||
|
||||
import { ProjectionEnum } from "./ProjectionEnum.js";
|
||||
|
||||
@@ -382,9 +382,9 @@ export let Aladin = (function () {
|
||||
}
|
||||
i++;
|
||||
});
|
||||
} else if (options.survey === ImageSurvey.DEFAULT_SURVEY_ID) {
|
||||
// DSS is cached inside ImageSurvey class, no need to provide any further information
|
||||
const survey = this.createImageSurvey(ImageSurvey.DEFAULT_SURVEY_ID);
|
||||
} else if (options.survey === ImageHiPS.DEFAULT_SURVEY_ID) {
|
||||
// DSS is cached inside ImageHiPS class, no need to provide any further information
|
||||
const survey = this.createImageSurvey(ImageHiPS.DEFAULT_SURVEY_ID);
|
||||
|
||||
this.setBaseImageLayer(survey);
|
||||
} else {
|
||||
@@ -468,11 +468,9 @@ export let Aladin = (function () {
|
||||
// at least id or url is defined
|
||||
let key = id || url;
|
||||
|
||||
//if (!(key in ImageSurvey.cache)) {
|
||||
// Merge what is already in the cache for that HiPS with new properties
|
||||
// coming from the MOCServer
|
||||
ImageSurvey.cache[key] = {...ImageSurvey.cache[key], ...cachedSurvey}
|
||||
//}
|
||||
HiPSCache.append(key, {...HiPSCache.get(key), ...cachedSurvey})
|
||||
}
|
||||
|
||||
ALEvent.HIPS_LIST_UPDATED.dispatchedTo(this.aladinDiv);
|
||||
@@ -664,9 +662,9 @@ export let Aladin = (function () {
|
||||
// access to WASM libraries
|
||||
Aladin.wasmLibs = {};
|
||||
Aladin.DEFAULT_OPTIONS = {
|
||||
survey: ImageSurvey.DEFAULT_SURVEY_ID,
|
||||
survey: ImageHiPS.DEFAULT_SURVEY_ID,
|
||||
// surveys suggestion list
|
||||
hipsList: ImageSurvey.DEFAULT_HIPS_LIST,
|
||||
hipsList: HiPSCache.DEFAULT_HIPS_LIST,
|
||||
//surveyUrl: ["https://alaskybis.unistra.fr/DSS/DSSColor", "https://alasky.unistra.fr/DSS/DSSColor"],
|
||||
target: "0 +0",
|
||||
cooFrame: "J2000",
|
||||
@@ -792,7 +790,7 @@ export let Aladin = (function () {
|
||||
options.frame = requestedFrame;
|
||||
}
|
||||
var requestedSurveyId = Utils.urlParam('survey');
|
||||
if (requestedSurveyId && ImageSurvey.getSurveyInfoFromId(requestedSurveyId)) {
|
||||
if (requestedSurveyId && ImageHiPS.getSurveyInfoFromId(requestedSurveyId)) {
|
||||
options.survey = requestedSurveyId;
|
||||
}
|
||||
var requestedZoom = Utils.urlParam('zoom');
|
||||
@@ -1412,11 +1410,11 @@ export let Aladin = (function () {
|
||||
* </ul>
|
||||
* @param {string} [cooFrame] - Values accepted: 'equatorial', 'icrs', 'icrsd', 'j2000', 'gal', 'galactic'
|
||||
* @param {number} [maxOrder] - The maximum HEALPix order of the HiPS, i.e the HEALPix order of the most refined tile images of the HiPS.
|
||||
* @param {ImageSurveyOptions} [options] - Options describing the survey
|
||||
* @returns {ImageSurvey} A HiPS image object.
|
||||
* @param {ImageOptions} [options] - Options describing the survey
|
||||
* @returns {ImageHiPS} A HiPS image object.
|
||||
*/
|
||||
Aladin.prototype.createImageSurvey = function(id, name, url, cooFrame, maxOrder, options) {
|
||||
let surveyOptions = ImageSurvey.cache[id];
|
||||
let surveyOptions = HiPSCache.get(id);
|
||||
|
||||
if (!surveyOptions) {
|
||||
surveyOptions = {name, maxOrder, cooFrame, ...options};
|
||||
@@ -1428,10 +1426,10 @@ export let Aladin = (function () {
|
||||
surveyOptions.url = url;
|
||||
}
|
||||
|
||||
ImageSurvey.cache[id] = surveyOptions;
|
||||
HiPSCache.append(id, surveyOptions);
|
||||
}
|
||||
|
||||
return new ImageSurvey(id, surveyOptions.url, surveyOptions);
|
||||
return new ImageHiPS(id, surveyOptions.url, surveyOptions);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1451,8 +1449,8 @@ export let Aladin = (function () {
|
||||
* </ul>
|
||||
* @param {string} [cooFrame] - Values accepted: 'equatorial', 'icrs', 'icrsd', 'j2000', 'gal', 'galactic'
|
||||
* @param {number} [maxOrder] - The maximum HEALPix order of the HiPS, i.e the HEALPix order of the most refined tile images of the HiPS.
|
||||
* @param {ImageSurveyOptions} [options] - Options describing the survey
|
||||
* @returns {ImageSurvey} A HiPS image object.
|
||||
* @param {ImageOptions} [options] - Options describing the survey
|
||||
* @returns {ImageHiPS} A HiPS image object.
|
||||
*/
|
||||
Aladin.createImageSurvey = Aladin.prototype.createImageSurvey;
|
||||
|
||||
@@ -1471,10 +1469,11 @@ export let Aladin = (function () {
|
||||
// Do not use proxy with CORS headers until we solve that: https://github.com/MattiasBuelens/wasm-streams/issues/20
|
||||
//url = Utils.handleCORSNotSameOrigin(url);
|
||||
|
||||
let image = ImageSurvey.cache[url];
|
||||
let image = HiPSCache.get(url);
|
||||
if (!image) {
|
||||
image = new ImageFITS(url, name, options, successCallback, errorCallback)
|
||||
ImageSurvey.cache[url] = image;
|
||||
options = { name, successCallback, errorCallback, ...options };
|
||||
image = new ImageFITS(url, options);
|
||||
HiPSCache.append(url, image);
|
||||
}
|
||||
|
||||
return image;
|
||||
@@ -1488,10 +1487,10 @@ export let Aladin = (function () {
|
||||
* @static
|
||||
* @param {string} url - The url of the fits.
|
||||
* @param {string} [name] - The url of the fits.
|
||||
* @param {ImageSurveyOptions} [options] - Options for rendering the image
|
||||
* @param {ImageOptions} [options] - Options for rendering the image
|
||||
* @param {function} [success] - A success callback
|
||||
* @param {function} [error] - A success callback
|
||||
* @returns {ImageSurvey} A FITS image object.
|
||||
* @returns {ImageFITS} A FITS image object.
|
||||
*/
|
||||
Aladin.createImageFITS = Aladin.prototype.createImageFITS;
|
||||
|
||||
@@ -1508,10 +1507,10 @@ export let Aladin = (function () {
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>Or it can be a "CDS ID" that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* </ul>
|
||||
* @param {ImageSurveyOptions} [options] - Options for rendering the image
|
||||
* @param {ImageHiPSOptions} [options] - Options for rendering the image
|
||||
* @param {function} [success] - A success callback
|
||||
* @param {function} [error] - A success callback
|
||||
* @returns {ImageSurvey} A FITS image object.
|
||||
* @returns {ImageHiPS} A FITS image object.
|
||||
*/
|
||||
Aladin.prototype.newImageSurvey = function(url, options) {
|
||||
const id = url;
|
||||
@@ -1523,30 +1522,30 @@ export let Aladin = (function () {
|
||||
* Add a new HiPS layer to the view on top of the others
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string|ImageSurvey} [survey="CDS/P/DSS2/color"] - Can be:
|
||||
* @param {string|ImageHiPS} [survey="CDS/P/DSS2/color"] - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>2. Or it can be a CDS ID that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>3. It can also be an {@link ImageSurvey} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>3. It can also be an {@link ImageHiPS} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* </ul>
|
||||
* By default, the {@link https://alasky.cds.unistra.fr/DSS/DSSColor/|Digital Sky Survey 2} survey will be displayed
|
||||
*/
|
||||
Aladin.prototype.addNewImageLayer = function(survey="CDS/P/DSS2/color") {
|
||||
let layerName = Utils.uuidv4();
|
||||
this.setOverlayImageLayer(survey, layerName);
|
||||
return this.setOverlayImageLayer(survey, layerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the base layer of the view
|
||||
*
|
||||
* It internally calls {@link Aladin#setBaseImageLayer|Aladin.setBaseImageLayer} with the url/{@link ImageSurvey}/{@link ImageFITS} given
|
||||
* It internally calls {@link Aladin#setBaseImageLayer|Aladin.setBaseImageLayer} with the url/{@link ImageHiPS}/{@link ImageFITS} given
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string|ImageSurvey|ImageFITS} urlOrHiPSOrFITS - Can be:
|
||||
* @param {string|ImageHiPS|ImageFITS} urlOrHiPSOrFITS - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>2. Or it can be a CDS identifier that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>3. A {@link ImageSurvey} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>3. A {@link ImageHiPS} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>4. A {@link ImageFITS} FITS image object</li>
|
||||
* </ul>
|
||||
*/
|
||||
@@ -1557,14 +1556,14 @@ export let Aladin = (function () {
|
||||
/**
|
||||
* Change the base layer of the view
|
||||
*
|
||||
* It internally calls {@link Aladin#setBaseImageLayer|Aladin.setBaseImageLayer} with the url/{@link ImageSurvey}/{@link ImageFITS} given
|
||||
* It internally calls {@link Aladin#setBaseImageLayer|Aladin.setBaseImageLayer} with the url/{@link ImageHiPS}/{@link ImageFITS} given
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string|ImageSurvey|ImageFITS} urlOrHiPSOrFITS - Can be:
|
||||
* @param {string|ImageHiPS|ImageFITS} urlOrHiPSOrFITS - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>2. Or it can be a CDS ID that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>3. A {@link ImageSurvey} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>3. A {@link ImageHiPS} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>4. A {@link ImageFITS} FITS image object</li>
|
||||
* </ul>
|
||||
*/
|
||||
@@ -1598,11 +1597,11 @@ export let Aladin = (function () {
|
||||
* Change the base layer of the view
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string|ImageSurvey|ImageFITS} urlOrHiPSOrFITS - Can be:
|
||||
* @param {string|ImageHiPS|ImageFITS} urlOrHiPSOrFITS - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>2. Or it can be a CDS ID that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>3. A {@link ImageSurvey} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>3. A {@link ImageHiPS} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>4. A {@link ImageFITS} FITS image object</li>
|
||||
* </ul>
|
||||
*/
|
||||
@@ -1619,11 +1618,11 @@ export let Aladin = (function () {
|
||||
* Add a new HiPS/FITS image layer in the view
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string|ImageSurvey|ImageFITS} urlOrHiPSOrFITS - Can be:
|
||||
* @param {string|ImageHiPS|ImageFITS} urlOrHiPSOrFITS - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>2. Or it can be a CDS ID that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>3. A {@link ImageSurvey} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>3. A {@link ImageHiPS} HiPS object created from {@link A.imageHiPS}</li>
|
||||
* <li>4. A {@link ImageFITS} FITS image object</li>
|
||||
* </ul>
|
||||
* @param {string} [layer="overlay"] - A layer name. By default 'overlay' is chosen and it is destined to be plot
|
||||
|
||||
252
src/js/DefaultHiPSCache.js
Normal file
252
src/js/DefaultHiPSCache.js
Normal file
@@ -0,0 +1,252 @@
|
||||
// Copyright 2013 - 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.
|
||||
//
|
||||
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
*
|
||||
* File ImageHiPS
|
||||
*
|
||||
* Authors: Thomas Boch & Matthieu Baumann [CDS]
|
||||
*
|
||||
*****************************************************************************/
|
||||
import { ALEvent } from "./events/ALEvent.js";
|
||||
|
||||
export let HiPSCache = (function () {
|
||||
function HiPSCache() {}
|
||||
|
||||
HiPSCache.append = function (key, image) {
|
||||
HiPSCache.cache[key] = image;
|
||||
|
||||
ALEvent.HIPS_LIST_UPDATED.dispatchedTo(document.body);
|
||||
};
|
||||
|
||||
HiPSCache.delete = function (key) {
|
||||
delete HiPSCache.cache[key];
|
||||
|
||||
ALEvent.HIPS_LIST_UPDATED.dispatchedTo(document.body);
|
||||
};
|
||||
|
||||
HiPSCache.get = function (key) {
|
||||
return HiPSCache.cache[key];
|
||||
};
|
||||
|
||||
// A cache storing directly surveys important information to not query for the properties each time
|
||||
HiPSCache.cache = {};
|
||||
|
||||
HiPSCache.DEFAULT_HIPS_LIST = [
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/DSS2/color",
|
||||
name: "DSS colored",
|
||||
id: "CDS/P/DSS2/color",
|
||||
maxOrder: 9,
|
||||
tileSize: 512,
|
||||
imgFormat: "jpeg",
|
||||
cooFrame: "ICRS",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/2MASS/color",
|
||||
name: "2MASS colored",
|
||||
id: "CDS/P/2MASS/color",
|
||||
maxOrder: 9,
|
||||
tileSize: 512,
|
||||
imgFormat: "jpeg",
|
||||
cooFrame: "ICRS",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/DSS2/red",
|
||||
name: "DSS2 Red (F+R)",
|
||||
id: "CDS/P/DSS2/red",
|
||||
maxOrder: 9,
|
||||
tileSize: 512,
|
||||
imgFormat: "fits",
|
||||
cooFrame: "ICRS",
|
||||
numBitsPerPixel: 16,
|
||||
// options
|
||||
minCut: 1000.0,
|
||||
maxCut: 10000.0,
|
||||
colormap: "magma",
|
||||
stretch: "Linear",
|
||||
imgFormat: "fits",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/DM/I/350/gaiaedr3",
|
||||
name: "Density map for Gaia EDR3 (I/350/gaiaedr3)",
|
||||
id: "CDS/P/DM/I/350/gaiaedr3",
|
||||
maxOrder: 7,
|
||||
tileSize: 512,
|
||||
numBitsPerPixel: -32,
|
||||
cooFrame: "ICRS",
|
||||
minCut: 0,
|
||||
maxCut: 12000,
|
||||
stretch: "asinh",
|
||||
colormap: "rdylbu",
|
||||
imgFormat: "fits",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/PanSTARRS/DR1/g",
|
||||
name: "PanSTARRS DR1 g",
|
||||
id: "CDS/P/PanSTARRS/DR1/g",
|
||||
maxOrder: 11,
|
||||
tileSize: 512,
|
||||
imgFormat: "fits",
|
||||
cooFrame: "ICRS",
|
||||
numBitsPerPixel: -32,
|
||||
// options
|
||||
minCut: -34,
|
||||
maxCut: 7000,
|
||||
stretch: "asinh",
|
||||
colormap: "redtemperature",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/PanSTARRS/DR1/color-z-zg-g",
|
||||
name: "PanSTARRS DR1 color",
|
||||
id: "CDS/P/PanSTARRS/DR1/color-z-zg-g",
|
||||
maxOrder: 11,
|
||||
tileSize: 512,
|
||||
imgFormat: "jpeg",
|
||||
cooFrame: "ICRS",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/DECaPS/DR2/color",
|
||||
name: "DECaPS DR2 color",
|
||||
id: "CDS/P/DECaPS/DR2/color",
|
||||
maxOrder: 11,
|
||||
cooFrame: "equatorial",
|
||||
tileSize: 512,
|
||||
imgFormat: "png",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/Fermi/color",
|
||||
name: "Fermi color",
|
||||
id: "CDS/P/Fermi/color",
|
||||
maxOrder: 3,
|
||||
imgFormat: "jpeg",
|
||||
tileSize: 512,
|
||||
cooFrame: "equatorial",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/GALEXGR6_7/NUV",
|
||||
id: "P/GALEXGR6_7/NUV",
|
||||
name: "GALEXGR6_7 NUV",
|
||||
maxOrder: 8,
|
||||
imgFormat: "png",
|
||||
tileSize: 512,
|
||||
cooFrame: "equatorial",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/IRIS/color",
|
||||
id: "CDS/P/IRIS/color",
|
||||
name: "IRIS colored",
|
||||
maxOrder: 3,
|
||||
tileSize: 256,
|
||||
imgFormat: "jpeg",
|
||||
cooFrame: "galactic",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/Mellinger/color",
|
||||
id: "CDS/P/Mellinger/color",
|
||||
name: "Mellinger colored",
|
||||
maxOrder: 4,
|
||||
tileSize: 512,
|
||||
imgFormat: "jpeg",
|
||||
cooFrame: "galactic",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/SDSS9/color",
|
||||
id: "CDS/P/SDSS9/color",
|
||||
name: "SDSS9 colored",
|
||||
maxOrder: 10,
|
||||
tileSize: 512,
|
||||
imgFormat: "jpeg",
|
||||
cooFrame: "equatorial",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/SPITZER/color",
|
||||
id: "CDS/P/SPITZER/color",
|
||||
name: "IRAC color I1,I2,I4 - (GLIMPSE, SAGE, SAGE-SMC, SINGS)",
|
||||
maxOrder: 9,
|
||||
tileSize: 512,
|
||||
imgFormat: "jpeg",
|
||||
cooFrame: "galactic",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/allWISE/color",
|
||||
id: "CDS/P/allWISE/color",
|
||||
name: "AllWISE color",
|
||||
maxOrder: 8,
|
||||
tileSize: 512,
|
||||
imgFormat: "jpeg",
|
||||
cooFrame: "equatorial",
|
||||
},
|
||||
{
|
||||
creatorDid: "ivo://CDS/P/SDSS9/g",
|
||||
id: "CDS/P/SDSS9/g",
|
||||
name: "SDSS9 band-g",
|
||||
maxOrder: 10,
|
||||
tileSize: 512,
|
||||
numBitsPerPixel: 16,
|
||||
imgFormat: "fits",
|
||||
cooFrame: "equatorial",
|
||||
minCut: 0,
|
||||
maxCut: 1.8,
|
||||
stretch: "linear",
|
||||
colormap: "redtemperature",
|
||||
},
|
||||
{
|
||||
id: "CDS/P/Finkbeiner",
|
||||
name: "Halpha",
|
||||
maxOrder: 3,
|
||||
minCut: -10,
|
||||
maxCut: 800,
|
||||
colormap: "rdbu",
|
||||
imgFormat: "fits",
|
||||
},
|
||||
{
|
||||
id: "CDS/P/VTSS/Ha",
|
||||
name: "VTSS-Ha",
|
||||
maxOrder: 3,
|
||||
minCut: -10.0,
|
||||
maxCut: 100.0,
|
||||
colormap: "grayscale",
|
||||
imgFormat: "fits",
|
||||
},
|
||||
{
|
||||
id: "xcatdb/P/XMM/PN/color",
|
||||
name: "XMM PN colored",
|
||||
maxOrder: 7,
|
||||
},
|
||||
{
|
||||
id: "CDS/P/allWISE/color",
|
||||
name: "AllWISE color",
|
||||
maxOrder: 8,
|
||||
},
|
||||
/*{
|
||||
id: "CDS/P/GLIMPSE360",
|
||||
name: "GLIMPSE360",
|
||||
// This domain is not giving the CORS headers
|
||||
// We need to query by with a proxy equipped with CORS header.
|
||||
//url: "https://alasky.cds.unistra.fr/cgi/JSONProxy?url=https://www.spitzer.caltech.edu/glimpse360/aladin/data",
|
||||
maxOrder: 9,
|
||||
imgFormat: "jpeg",
|
||||
minOrder: 3,
|
||||
}*/
|
||||
];
|
||||
|
||||
return HiPSCache;
|
||||
})();
|
||||
@@ -1,130 +0,0 @@
|
||||
import A from "./A.js";
|
||||
|
||||
export let DiscoveryTree = (function () {
|
||||
// Constructor
|
||||
var DiscoveryTree = function (aladin) {
|
||||
// activate Vue on the <div> that contains the component
|
||||
new Vue({
|
||||
el: '#ui',
|
||||
methods: {
|
||||
// Define the methods for the discovery-tree component
|
||||
// to interact with the aladin viewer
|
||||
getFovCorners() {
|
||||
return aladin.getFovCorners();
|
||||
},
|
||||
getCenter() {
|
||||
return aladin.getRaDec();
|
||||
},
|
||||
// Called when the user add a image survey
|
||||
addImage(metadata) {
|
||||
const order = (+metadata.hips_order);
|
||||
const hipsTileFormat = metadata.hips_tile_format.split(' ');
|
||||
|
||||
let tileFormat;
|
||||
let color;
|
||||
if (hipsTileFormat.indexOf('fits') >= 0) {
|
||||
tileFormat = {
|
||||
FITSImage: {
|
||||
bitpix: parseInt(metadata.hips_pixel_bitpix)
|
||||
}
|
||||
};
|
||||
color = {
|
||||
Grayscale2Color: {
|
||||
color: [1.0, 1.0, 1.0],
|
||||
k: 1.0,
|
||||
transfer: "asinh"
|
||||
}
|
||||
};
|
||||
} else {
|
||||
color = "Color";
|
||||
|
||||
if (hipsTileFormat.indexOf('png') >= 0) {
|
||||
tileFormat = {
|
||||
Image: {
|
||||
format: "png"
|
||||
}
|
||||
};
|
||||
} else {
|
||||
tileFormat = {
|
||||
Image: {
|
||||
format: "jpeg"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let cuts = [undefined, undefined];
|
||||
if (metadata.hips_pixel_cut) {
|
||||
cuts = metadata.hips_pixel_cut.split(" ");
|
||||
}
|
||||
let tileSize = 512;
|
||||
// Verify the validity of the tile width
|
||||
if (metadata.hips_tile_width) {
|
||||
let hipsTileWidth = parseInt(metadata.hips_tile_width);
|
||||
let isPowerOfTwo = hipsTileWidth && !(hipsTileWidth & (hipsTileWidth - 1));
|
||||
|
||||
if (isPowerOfTwo === true) {
|
||||
tileSize = hipsTileWidth;
|
||||
}
|
||||
}
|
||||
let url = metadata.hips_service_url;
|
||||
if (url.startsWith('http://alasky')) {
|
||||
// From alasky one can directly use the https access
|
||||
url = url.replace('http', 'https');
|
||||
} else {
|
||||
// Pass by a proxy for extern http urls
|
||||
url = 'https://alasky.u-strasbg.fr/cgi/JSONProxy?url=' + url;
|
||||
}
|
||||
let survey = {
|
||||
properties: {
|
||||
url: url,
|
||||
maxOrder: parseInt(metadata.hips_order),
|
||||
frame: {
|
||||
label: "J2000",
|
||||
system: "J2000"
|
||||
},
|
||||
tileSize: tileSize,
|
||||
format: tileFormat,
|
||||
minCutout: parseFloat(cuts[0]),
|
||||
maxCutout: parseFloat(cuts[1]),
|
||||
},
|
||||
color: color
|
||||
};
|
||||
|
||||
aladin.setImageSurveysLayer([survey], "base");
|
||||
},
|
||||
// Called when the user add a catalog survey
|
||||
addCatalog(metadata, center, radius) {
|
||||
if (metadata.hips_service_url) {
|
||||
const hips = A.catalogHiPS(metadata.hips_service_url, {
|
||||
onClick: 'showTable',
|
||||
name: metadata.ID,
|
||||
});
|
||||
aladin.addCatalog(hips);
|
||||
} else {
|
||||
console.log(metadata.obs_id, "center, ", center, " radius, ", radius)
|
||||
const catalog = A.catalogFromVizieR(
|
||||
metadata.obs_id,
|
||||
{
|
||||
ra: center[0],
|
||||
dec: center[1]
|
||||
},
|
||||
radius, {
|
||||
onClick: 'showTable',
|
||||
limit: 1000,
|
||||
}
|
||||
);
|
||||
aladin.addCatalog(catalog);
|
||||
}
|
||||
},
|
||||
// Called when the user add a HEALPix coverage
|
||||
addCoverage(metadata) {
|
||||
const moc = A.MOCFromURL(metadata.moc_access_url);
|
||||
aladin.addMOC(moc);
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return DiscoveryTree;
|
||||
})();
|
||||
@@ -17,25 +17,50 @@
|
||||
// along with Aladin Lite.
|
||||
//
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
*
|
||||
*
|
||||
* File ImageFITS
|
||||
*
|
||||
*
|
||||
* Authors: Matthieu Baumann [CDS]
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
import { ALEvent } from "./events/ALEvent.js";
|
||||
import { ColorCfg } from "./ColorCfg.js";
|
||||
import { Utils } from "./Utils";
|
||||
import { ImageSurvey } from "./ImageSurvey.js";
|
||||
import { HiPSCache } from "./DefaultHiPSCache";
|
||||
|
||||
/**
|
||||
* @typedef {Object} ImageFITSOptions
|
||||
*
|
||||
* @property {string} [name] - A human-readable name for the FITS image
|
||||
* @property {Function} [successCallback] - A callback executed when the FITS has been loaded
|
||||
* @property {Function} [errorCallback] - A callback executed when the FITS could not be loaded
|
||||
* @property {number} [opacity=1.0] - Opacity of the survey or image (value between 0 and 1).
|
||||
* @property {string} [colormap="native"] - The colormap configuration for the survey or image.
|
||||
* @property {string} [stretch="linear"] - The stretch configuration for the survey or image.
|
||||
* @property {boolean} [reversed=false] - If true, the colormap is reversed; otherwise, it is not reversed.
|
||||
* @property {number} [minCut] - The minimum cut value for the color configuration. If not given, 0.0 for JPEG/PNG surveys, the value of the property file for FITS surveys
|
||||
* @property {number} [maxCut] - The maximum cut value for the color configuration. If not given, 1.0 for JPEG/PNG surveys, the value of the property file for FITS surveys
|
||||
* @property {boolean} [additive=false] - If true, additive blending is applied; otherwise, it is not applied.
|
||||
* @property {number} [gamma=1.0] - The gamma correction value for the color configuration.
|
||||
* @property {number} [saturation=0.0] - The saturation value for the color configuration.
|
||||
* @property {number} [brightness=0.0] - The brightness value for the color configuration.
|
||||
* @property {number} [contrast=0.0] - The contrast value for the color configuration.
|
||||
*/
|
||||
|
||||
export let ImageFITS = (function () {
|
||||
|
||||
function ImageFITS(url, name, options, successCallback = undefined, errorCallback = undefined) {
|
||||
/**
|
||||
* The object describing a FITS image
|
||||
*
|
||||
* @class
|
||||
* @constructs ImageFITS
|
||||
*
|
||||
* @param {string} url - Mandatory unique identifier for the layer. Can be an arbitrary name
|
||||
* @param {ImageFITSOptions} [options] - The option for the survey
|
||||
*
|
||||
*/
|
||||
function ImageFITS(url, options) {
|
||||
// Name of the layer
|
||||
this.layer = null;
|
||||
this.added = false;
|
||||
@@ -43,13 +68,13 @@ export let ImageFITS = (function () {
|
||||
// Set it to a default value
|
||||
this.url = url;
|
||||
this.id = url;
|
||||
this.name = name || this.url;
|
||||
this.name = (options && options.name) || this.url;
|
||||
|
||||
this.imgFormat = "fits";
|
||||
this.formats = ["fits"]
|
||||
this.formats = ["fits"];
|
||||
// callbacks
|
||||
this.successCallback = successCallback;
|
||||
this.errorCallback = errorCallback;
|
||||
this.successCallback = options && options.successCallback;
|
||||
this.errorCallback = options && options.errorCallback;
|
||||
// initialize the color meta data here
|
||||
// set a asinh stretch by default if there is none
|
||||
/*if (options) {
|
||||
@@ -60,37 +85,27 @@ export let ImageFITS = (function () {
|
||||
let self = this;
|
||||
|
||||
this.query = Promise.resolve(self);
|
||||
this._saveInCache();
|
||||
}
|
||||
|
||||
ImageFITS.prototype._saveInCache = function() {
|
||||
let self = this;
|
||||
|
||||
let colorOpt = Object.fromEntries(Object.entries(this.colorCfg));
|
||||
let fitsOpt = {
|
||||
id: self.id,
|
||||
name: self.name,
|
||||
url: self.url,
|
||||
imgFormat: self.imgFormat,
|
||||
...colorOpt
|
||||
}
|
||||
|
||||
ImageSurvey.cache[self.id] = self;
|
||||
|
||||
//console.log('new CACHE', ImageSurvey.cache, self.id, surveyOpt, ImageSurvey.cache[self.id], ImageSurvey.cache["CSIRO/P/RACS/mid/I"])
|
||||
ImageFITS.prototype._saveInCache = function () {
|
||||
/*ImageHiPS.cache[this.id] = this;
|
||||
|
||||
// Tell that the HiPS List has been updated
|
||||
if (this.view) {
|
||||
ALEvent.HIPS_LIST_UPDATED.dispatchedTo(this.view.aladin.aladinDiv);
|
||||
}
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
HiPSCache.append(this.id, this);
|
||||
};
|
||||
|
||||
// A cache storing directly the images to not query for the properties each time
|
||||
//ImageFITS.cache = {};
|
||||
|
||||
ImageFITS.prototype.setView = function(view) {
|
||||
ImageFITS.prototype.setView = function (view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
this._saveInCache();
|
||||
};
|
||||
|
||||
// @api
|
||||
ImageFITS.prototype.setOpacity = function (opacity) {
|
||||
@@ -112,7 +127,7 @@ export let ImageFITS = (function () {
|
||||
this._updateMetadata(() => {
|
||||
this.colorCfg.setColormap(colormap, options);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// @api
|
||||
ImageFITS.prototype.setCuts = function (lowCut, highCut) {
|
||||
@@ -159,95 +174,105 @@ export let ImageFITS = (function () {
|
||||
this.view.wasm.setImageMetadata(this.layer, {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: false,
|
||||
imgFormat: this.imgFormat
|
||||
imgFormat: this.imgFormat,
|
||||
});
|
||||
ALEvent.HIPS_LAYER_CHANGED.dispatchedTo(this.view.aladinDiv, {
|
||||
layer: this,
|
||||
});
|
||||
ALEvent.HIPS_LAYER_CHANGED.dispatchedTo(this.view.aladinDiv, { layer: this });
|
||||
}
|
||||
|
||||
// save it in the JS HiPS cache
|
||||
this._saveInCache()
|
||||
this._saveInCache();
|
||||
} catch (e) {
|
||||
// Display the error message
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ImageFITS.prototype.add = function (layer) {
|
||||
this.layer = layer;
|
||||
|
||||
let self = this;
|
||||
|
||||
const promise = self.view.wasm.addImageFITS({
|
||||
layer: self.layer,
|
||||
url: self.url,
|
||||
meta: {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: false,
|
||||
imgFormat: this.imgFormat
|
||||
}
|
||||
}).then((imagesParams) => {
|
||||
// There is at least one entry in imageParams
|
||||
self.added = true;
|
||||
const promise = self.view.wasm
|
||||
.addImageFITS({
|
||||
layer: self.layer,
|
||||
url: self.url,
|
||||
meta: {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: false,
|
||||
imgFormat: this.imgFormat,
|
||||
},
|
||||
})
|
||||
.then((imagesParams) => {
|
||||
// There is at least one entry in imageParams
|
||||
self.added = true;
|
||||
|
||||
self.children = [];
|
||||
self.children = [];
|
||||
|
||||
let hduIdx = 0;
|
||||
imagesParams.forEach((imageParams) => {
|
||||
// This fits has HDU extensions
|
||||
let image = new ImageFITS(
|
||||
imageParams.url,
|
||||
self.name + "_ext_" + hduIdx.toString(),
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
let hduIdx = 0;
|
||||
imagesParams.forEach((imageParams) => {
|
||||
// This fits has HDU extensions
|
||||
let image = new ImageFITS(imageParams.url, {
|
||||
name: self.name + "_ext_" + hduIdx.toString(),
|
||||
});
|
||||
|
||||
// Set the layer corresponding to the onein the backend
|
||||
image.layer = imageParams.layer;
|
||||
image.added = true;
|
||||
image.setView(self.view);
|
||||
// deep copy of the color object of self
|
||||
image.colorCfg = Utils.deepCopy(self.colorCfg);
|
||||
// Set the automatic computed cuts
|
||||
image.setCuts(imageParams.automatic_min_cut, imageParams.automatic_max_cut);
|
||||
// Set the layer corresponding to the onein the backend
|
||||
image.layer = imageParams.layer;
|
||||
image.added = true;
|
||||
image.setView(self.view);
|
||||
// deep copy of the color object of self
|
||||
image.colorCfg = Utils.deepCopy(self.colorCfg);
|
||||
// Set the automatic computed cuts
|
||||
image.setCuts(
|
||||
imageParams.automatic_min_cut,
|
||||
imageParams.automatic_max_cut
|
||||
);
|
||||
|
||||
image.ra = imageParams.centered_fov.ra;
|
||||
image.dec = imageParams.centered_fov.dec;
|
||||
image.fov = imageParams.centered_fov.fov;
|
||||
image.ra = imageParams.centered_fov.ra;
|
||||
image.dec = imageParams.centered_fov.dec;
|
||||
image.fov = imageParams.centered_fov.fov;
|
||||
|
||||
if (!self.ra) { self.ra = image.ra; }
|
||||
if (!self.dec) { self.dec = image.dec; }
|
||||
if (!self.fov) { self.fov = image.fov; }
|
||||
if (!self.ra) {
|
||||
self.ra = image.ra;
|
||||
}
|
||||
if (!self.dec) {
|
||||
self.dec = image.dec;
|
||||
}
|
||||
if (!self.fov) {
|
||||
self.fov = image.fov;
|
||||
}
|
||||
|
||||
self.children.push(image)
|
||||
self.children.push(image);
|
||||
|
||||
hduIdx += 1;
|
||||
hduIdx += 1;
|
||||
});
|
||||
|
||||
// Call the success callback on the first HDU image parsed
|
||||
if (self.successCallback) {
|
||||
self.successCallback(
|
||||
self.children[0].ra,
|
||||
self.children[0].dec,
|
||||
self.children[0].fov,
|
||||
self.children[0]
|
||||
);
|
||||
}
|
||||
|
||||
return self;
|
||||
})
|
||||
.catch((e) => {
|
||||
if (self.errorCallback) {
|
||||
self.errorCallback();
|
||||
}
|
||||
|
||||
// This error result from a promise
|
||||
// If I throw it, it will not be catched because
|
||||
// it is run async
|
||||
self.view.removeImageLayer(layer);
|
||||
|
||||
return Promise.reject(e);
|
||||
});
|
||||
|
||||
// Call the success callback on the first HDU image parsed
|
||||
if (self.successCallback) {
|
||||
self.successCallback(
|
||||
self.children[0].ra,
|
||||
self.children[0].dec,
|
||||
self.children[0].fov,
|
||||
self.children[0]
|
||||
);
|
||||
}
|
||||
|
||||
return self;
|
||||
}).catch((e) => {
|
||||
if (self.errorCallback) {
|
||||
self.errorCallback()
|
||||
}
|
||||
|
||||
// This error result from a promise
|
||||
// If I throw it, it will not be catched because
|
||||
// it is run async
|
||||
self.view.removeImageLayer(layer)
|
||||
|
||||
return Promise.reject(e);
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
@@ -261,9 +286,9 @@ export let ImageFITS = (function () {
|
||||
};
|
||||
|
||||
// FITS images does not mean to be used for storing planetary data
|
||||
ImageFITS.prototype.isPlanetaryBody = function() {
|
||||
ImageFITS.prototype.isPlanetaryBody = function () {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// @api
|
||||
ImageFITS.prototype.focusOn = function () {
|
||||
@@ -307,4 +332,3 @@ export let ImageFITS = (function () {
|
||||
|
||||
return ImageFITS;
|
||||
})();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -50,8 +50,7 @@ import { ObsCore } from "./vo/ObsCore.js";
|
||||
import { DefaultActionsForContextMenu } from "./DefaultActionsForContextMenu.js";
|
||||
import { Layout } from "./gui/Layout.js";
|
||||
import { SAMPActionButton } from "./gui/Button/SAMP.js";
|
||||
import { ImageSurvey } from "./ImageSurvey.js";
|
||||
import { ImageFITS } from "./ImageFITS.js";
|
||||
import { HiPSCache } from "./DefaultHiPSCache.js";
|
||||
|
||||
export let View = (function () {
|
||||
|
||||
@@ -1613,7 +1612,7 @@ export let View = (function () {
|
||||
Promise.allSettled(this.promises)
|
||||
.then(() => imageLayerPromise)
|
||||
// The promise is resolved and we now have access
|
||||
// to the image layer objet (whether it is an ImageSurvey or an ImageFITS)
|
||||
// to the image layer objet (whether it is an ImageHiPS or an ImageFITS)
|
||||
.then((imageLayer) => {
|
||||
// Add to the backend
|
||||
const promise = imageLayer.add(layer);
|
||||
@@ -1642,8 +1641,7 @@ export let View = (function () {
|
||||
})
|
||||
.catch((e) => {
|
||||
// remove it from the cache
|
||||
delete ImageSurvey.cache[imageLayer.id]
|
||||
ALEvent.HIPS_LIST_UPDATED.dispatchedTo(this.aladin.aladinDiv);
|
||||
HiPSCache.delete(imageLayer.id)
|
||||
|
||||
throw e;
|
||||
})
|
||||
@@ -1662,7 +1660,7 @@ export let View = (function () {
|
||||
if (noMoreLayersToWaitFor) {
|
||||
if (self.empty) {
|
||||
// no promises to launch!
|
||||
//self.aladin.setBaseImageLayer(self.aladin.createImageSurvey(ImageSurvey.DEFAULT_SURVEY_ID));
|
||||
//self.aladin.setBaseImageLayer(self.aladin.createImageSurvey(ImageHiPS.DEFAULT_SURVEY_ID));
|
||||
} else {
|
||||
// there is surveys that have been queried
|
||||
// rename the first overlay layer to "base"
|
||||
|
||||
@@ -47,11 +47,12 @@ import filterOffUrl from "../../../../assets/icons/filter-off.svg";
|
||||
import searchIconImg from "../../../../assets/icons/search.svg";
|
||||
import { TogglerActionButton } from "../Button/Toggler.js";
|
||||
import { Icon } from "../Widgets/Icon.js";
|
||||
import { ImageSurvey } from "../../ImageSurvey.js";
|
||||
import { ImageHiPS } from "../../ImageHiPS.js";
|
||||
import { Box } from "../Widgets/Box.js";
|
||||
import { CtxMenuActionButtonOpener } from "../Button/CtxMenuOpener.js";
|
||||
import { Input } from "../Widgets/Input.js";
|
||||
import { ImageFITS } from "../../ImageFITS.js";
|
||||
import { HiPSCache } from "../../DefaultHiPSCache.js";
|
||||
|
||||
export class OverlayStackBox extends Box {
|
||||
/*static previewImagesUrl = {
|
||||
@@ -783,11 +784,12 @@ export class OverlayStackBox extends Box {
|
||||
updateOverlayList();
|
||||
|
||||
// Add a listener for HiPS list changes
|
||||
ALEvent.HIPS_LIST_UPDATED.listenedBy(this.aladin.aladinDiv, () => {
|
||||
ALEvent.HIPS_LIST_UPDATED.listenedBy(document.body, () => {
|
||||
self.cachedHiPS = {};
|
||||
|
||||
for (var key in ImageSurvey.cache) {
|
||||
let HiPS = ImageSurvey.cache[key];
|
||||
for (var key in HiPSCache.cache) {
|
||||
|
||||
let HiPS = HiPSCache.cache[key];
|
||||
|
||||
self.cachedHiPS[HiPS.name] = HiPS;
|
||||
}
|
||||
@@ -805,8 +807,8 @@ export class OverlayStackBox extends Box {
|
||||
/*ALEvent.HIPS_LIST_UPDATED.listenedBy(this.aladin.aladinDiv, () => {
|
||||
// Recompute the autocompletion as the cache has changed
|
||||
HiPSSearch.HiPSList = {};
|
||||
for (var key in ImageSurvey.cache) {
|
||||
let HiPS = ImageSurvey.cache[key];
|
||||
for (var key in ImageHiPS.cache) {
|
||||
let HiPS = ImageHiPS.cache[key];
|
||||
|
||||
// apply filtering
|
||||
if (
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
import { CtxMenuActionButtonOpener } from "./CtxMenuOpener";
|
||||
import stackOverlayIconUrl from './../../../../assets/icons/stack.svg';
|
||||
import { OverlayStack } from "../CtxMenu/OverlayStack";
|
||||
import { OverlayStackBox } from "../Box/StackBox";
|
||||
import { TogglerActionButton } from "./Toggler";
|
||||
/******************************************************************************
|
||||
|
||||
@@ -1,817 +0,0 @@
|
||||
// Copyright 2013 - 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.
|
||||
//
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
*
|
||||
* File gui/Stack/Menu.js
|
||||
*
|
||||
*
|
||||
* Author: Matthieu Baumann [CDS, matthieu.baumann@astro.unistra.fr]
|
||||
*
|
||||
*****************************************************************************/
|
||||
import { CatalogQueryBox } from "../Box/CatalogQueryBox.js";
|
||||
import { ALEvent } from "../../events/ALEvent.js";
|
||||
import { Layout } from "../Layout.js";
|
||||
import { ContextMenu } from "../Widgets/ContextMenu.js";
|
||||
import { ActionButton } from "../Widgets/ActionButton.js";
|
||||
import A from "../../A.js";
|
||||
import { Utils } from "../../../js/Utils";
|
||||
import { View } from "../../View.js";
|
||||
import { HiPSSettingsBox } from "../Box/HiPSSettingsBox.js";
|
||||
import { HiPSSelectorBox } from "../Box/HiPSSelectorBox.js";
|
||||
import searchIconUrl from '../../../../assets/icons/search.svg';
|
||||
import showIconUrl from '../../../../assets/icons/show.svg';
|
||||
import hideIconUrl from '../../../../assets/icons/hide.svg';
|
||||
import removeIconUrl from '../../../../assets/icons/remove.svg';
|
||||
import settingsIconUrl from '../../../../assets/icons/settings.svg';
|
||||
import { ImageFITS } from "../../ImageFITS.js";
|
||||
import searchIconImg from '../../../../assets/icons/search.svg';
|
||||
import { TogglerActionButton } from "../Button/Toggler.js";
|
||||
import { Icon } from "../Widgets/Icon.js";
|
||||
import { ImageSurvey } from "../../ImageSurvey.js";
|
||||
|
||||
export class OverlayStack extends ContextMenu {
|
||||
static previewImagesUrl = {
|
||||
'AllWISE color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_allWISE_color.jpg',
|
||||
'DSS colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_DSS2_color.jpg',
|
||||
'DSS2 Red (F+R)': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_DSS2_red.jpg',
|
||||
'Fermi color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_Fermi_color.jpg',
|
||||
'GALEXGR6_7 NUV': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_GALEXGR6_7_color.jpg',
|
||||
'GLIMPSE360': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_GLIMPSE360.jpg',
|
||||
'Halpha': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_VTSS_Ha.jpg',
|
||||
'IRAC color I1,I2,I4 - (GLIMPSE, SAGE, SAGE-SMC, SINGS)': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_SPITZER_color.jpg',
|
||||
'IRIS colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_IRIS_color.jpg',
|
||||
'Mellinger colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_Mellinger_color.jpg',
|
||||
'PanSTARRS DR1 color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_PanSTARRS_DR1_color-z-zg-g.jpg',
|
||||
'2MASS colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_2MASS_color.jpg',
|
||||
'AKARI colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_AKARI_FIS_Color.jpg',
|
||||
'SWIFT': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_SWIFT_BAT_FLUX.jpg',
|
||||
'VTSS-Ha': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_Finkbeiner.jpg',
|
||||
'XMM PN colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_XMM_PN_color.jpg',
|
||||
'SDSS9 colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_SDSS9_color.jpg',
|
||||
};
|
||||
static predefinedCats = {
|
||||
simbad: {url: 'https://axel.u-strasbg.fr/HiPSCatService/SIMBAD', options: {id: 'simbad', name: 'SIMBAD', shape: 'circle', sourceSize: 8, color: '#318d80', onClick: 'showTable'}},
|
||||
gaia: {url: 'https://axel.u-strasbg.fr/HiPSCatService/I/355/gaiadr3', options: {id: 'gaia-dr3', name: 'Gaia DR3', shape: 'square', sourceSize: 8, color: '#6baed6', onClick: 'showTable'}},
|
||||
twomass: {url: 'https://axel.u-strasbg.fr/HiPSCatService/II/246/out', options: {id: '2mass', name: '2MASS', shape: 'plus', sourceSize: 8, color: '#dd2233', onClick: 'showTable'}}
|
||||
};
|
||||
// Constructor
|
||||
constructor(aladin) {
|
||||
let self;
|
||||
super(aladin, {hideOnClick: (e) => {
|
||||
// only hide the stack ctx menu but not the windows
|
||||
super._hide();
|
||||
}});
|
||||
self = this;
|
||||
this.aladin = aladin;
|
||||
|
||||
this.mode = 'stack';
|
||||
|
||||
this._addListeners();
|
||||
|
||||
this.mocHiPSUrls = {}
|
||||
}
|
||||
|
||||
_addListeners() {
|
||||
let self = this;
|
||||
|
||||
let updateOverlayList = () => {
|
||||
// If it is shown, update it
|
||||
if (!self.isHidden) {
|
||||
// show will update the content of the stack
|
||||
self.attach();
|
||||
self.show();
|
||||
}
|
||||
};
|
||||
|
||||
ALEvent.GRAPHIC_OVERLAY_LAYER_ADDED.listenedBy(this.aladin.aladinDiv, function (e) {
|
||||
updateOverlayList();
|
||||
});
|
||||
|
||||
ALEvent.GRAPHIC_OVERLAY_LAYER_REMOVED.listenedBy(this.aladin.aladinDiv, function (e) {
|
||||
updateOverlayList();
|
||||
});
|
||||
|
||||
ALEvent.GRAPHIC_OVERLAY_LAYER_CHANGED.listenedBy(this.aladin.aladinDiv, function (e) {
|
||||
updateOverlayList();
|
||||
});
|
||||
|
||||
ALEvent.HIPS_LAYER_ADDED.listenedBy(this.aladin.aladinDiv, function (e) {
|
||||
updateOverlayList();
|
||||
});
|
||||
|
||||
ALEvent.HIPS_LAYER_RENAMED.listenedBy(this.aladin.aladinDiv, function (e) {
|
||||
updateOverlayList();
|
||||
});
|
||||
|
||||
ALEvent.HIPS_LAYER_SWAP.listenedBy(this.aladin.aladinDiv, function (e) {
|
||||
updateOverlayList();
|
||||
});
|
||||
|
||||
ALEvent.HIPS_LAYER_REMOVED.listenedBy(this.aladin.aladinDiv, function (e) {
|
||||
updateOverlayList();
|
||||
});
|
||||
|
||||
updateOverlayList();
|
||||
}
|
||||
|
||||
attach() {
|
||||
let self = this;
|
||||
|
||||
const overlays = Array.from(this.aladin.getOverlays()).reverse().map((overlay) => {
|
||||
return overlay;
|
||||
});
|
||||
const layers = Array.from(self.aladin.getImageOverlays()).reverse().map((name) => {
|
||||
let overlay = self.aladin.getOverlayImageLayer(name);
|
||||
return overlay;
|
||||
});
|
||||
|
||||
|
||||
let layout = [{
|
||||
label: 'Add overlay',
|
||||
subMenu: [
|
||||
{
|
||||
label: 'Catalogue',
|
||||
subMenu: [
|
||||
{
|
||||
label: {
|
||||
icon: {
|
||||
url: 'https://aladin.cds.unistra.fr/AladinLite/logos/SIMBAD.svg',
|
||||
cssStyle: {
|
||||
width: '3rem',
|
||||
height: '3rem',
|
||||
cursor: 'help',
|
||||
},
|
||||
action(o) {
|
||||
window.open('https://simbad.cds.unistra.fr/simbad/')
|
||||
}
|
||||
},
|
||||
content: 'database',
|
||||
tooltip: {content: 'Click to go to the SIMBAD database', position: {direction: 'bottom'}},
|
||||
|
||||
},
|
||||
action(o) {
|
||||
o.stopPropagation();
|
||||
o.preventDefault();
|
||||
|
||||
self._hide();
|
||||
|
||||
const simbadHiPS = A.catalogHiPS(OverlayStack.predefinedCats.simbad.url, OverlayStack.predefinedCats.simbad.options);
|
||||
self.aladin.addCatalog(simbadHiPS);
|
||||
|
||||
self.mode = 'stack';
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Gaia DR3',
|
||||
action(o) {
|
||||
o.stopPropagation();
|
||||
o.preventDefault();
|
||||
|
||||
self._hide();
|
||||
|
||||
const simbadHiPS = A.catalogHiPS(OverlayStack.predefinedCats.gaia.url, OverlayStack.predefinedCats.gaia.options);
|
||||
self.aladin.addCatalog(simbadHiPS);
|
||||
|
||||
self.mode = 'stack';
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '2MASS',
|
||||
action(o) {
|
||||
o.stopPropagation();
|
||||
o.preventDefault();
|
||||
|
||||
self._hide();
|
||||
|
||||
const simbadHiPS = A.catalogHiPS(OverlayStack.predefinedCats.twomass.url, OverlayStack.predefinedCats.twomass.options);
|
||||
self.aladin.addCatalog(simbadHiPS);
|
||||
|
||||
self.mode = 'stack';
|
||||
}
|
||||
},
|
||||
ContextMenu.fileLoaderItem({
|
||||
label: 'From a VOTable File',
|
||||
accept: '.xml,.vot',
|
||||
action(file) {
|
||||
let url = URL.createObjectURL(file);
|
||||
|
||||
A.catalogFromURL(
|
||||
url,
|
||||
{onClick: 'showTable'},
|
||||
(catalog) => {
|
||||
self.aladin.addCatalog(catalog)
|
||||
},
|
||||
e => alert(e)
|
||||
);
|
||||
}
|
||||
}),
|
||||
{
|
||||
label: {
|
||||
icon: {
|
||||
url: searchIconImg,
|
||||
monochrome: true,
|
||||
tooltip: {content: 'Find a specific catalogue <br /> in our database...', position: { direction: 'top' }},
|
||||
cssStyle: {
|
||||
cursor: 'help',
|
||||
},
|
||||
},
|
||||
content: 'More...'
|
||||
},
|
||||
action(o) {
|
||||
o.stopPropagation();
|
||||
o.preventDefault();
|
||||
|
||||
self._hide();
|
||||
|
||||
self.catBox = new CatalogQueryBox(self.aladin);
|
||||
self.catBox._show({position: self.position});
|
||||
|
||||
self.mode = 'search';
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: {
|
||||
icon: {
|
||||
url: Icon.dataURLFromSVG({svg: Icon.SVG_ICONS.MOC}),
|
||||
size: 'small',
|
||||
tooltip: {content: 'Define a selection coverage', position: {direction: 'bottom'}},
|
||||
monochrome: true,
|
||||
cssStyle: {
|
||||
cursor: 'pointer',
|
||||
},
|
||||
},
|
||||
content: 'MOC'
|
||||
},
|
||||
subMenu: [
|
||||
ContextMenu.fileLoaderItem({
|
||||
label: 'FITS File',
|
||||
accept: '.fits',
|
||||
action(file) {
|
||||
let url = URL.createObjectURL(file);
|
||||
|
||||
let moc = A.MOCFromURL(
|
||||
url,
|
||||
{name: file.name, lineWidth: 3.0},
|
||||
);
|
||||
self.aladin.addMOC(moc)
|
||||
}
|
||||
}),
|
||||
{
|
||||
label: 'From selection',
|
||||
subMenu: [
|
||||
{
|
||||
label: '◌ Circle',
|
||||
disabled: self.aladin.view.mode !== View.PAN ? {
|
||||
reason: 'Exit your current mode<br/>(e.g. disable the SIMBAD pointer mode)'
|
||||
} : false,
|
||||
action(o) {
|
||||
o.preventDefault();
|
||||
o.stopPropagation();
|
||||
|
||||
self._hide();
|
||||
|
||||
self.aladin.select('circle', c => {
|
||||
try {
|
||||
let [ra, dec] = self.aladin.pix2world(c.x, c.y, 'j2000');
|
||||
let radius = self.aladin.angularDist(c.x, c.y, c.x + c.r, c.y);
|
||||
|
||||
// the moc needs a
|
||||
let moc = A.MOCFromCone(
|
||||
{ra, dec, radius},
|
||||
{name: 'cone', lineWidth: 3.0},
|
||||
);
|
||||
self.aladin.addMOC(moc)
|
||||
} catch {
|
||||
console.error('Circle out of projection. Selection canceled')
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '⬚ Rect',
|
||||
disabled: self.aladin.view.mode !== View.PAN ? {
|
||||
reason: 'Exit your current mode<br/>(e.g. disable the SIMBAD pointer mode)'
|
||||
} : false,
|
||||
action(o) {
|
||||
o.stopPropagation();
|
||||
o.preventDefault();
|
||||
|
||||
self._hide();
|
||||
|
||||
self.aladin.select('rect', r => {
|
||||
try {
|
||||
let [ra1, dec1] = self.aladin.pix2world(r.x, r.y, 'j2000');
|
||||
let [ra2, dec2] = self.aladin.pix2world(r.x + r.w, r.y, 'j2000');
|
||||
let [ra3, dec3] = self.aladin.pix2world(r.x + r.w, r.y + r.h, 'j2000');
|
||||
let [ra4, dec4] = self.aladin.pix2world(r.x, r.y + r.h, 'j2000');
|
||||
|
||||
let moc = A.MOCFromPolygon(
|
||||
{
|
||||
ra: [ra1, ra2, ra3, ra4],
|
||||
dec: [dec1, dec2, dec3, dec4]
|
||||
},
|
||||
{name: 'rect', lineWidth: 3.0},
|
||||
);
|
||||
self.aladin.addMOC(moc)
|
||||
} catch(_) {
|
||||
alert('Selection covers a region out of the projection definition domain.');
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '⛉ Polygon',
|
||||
disabled: self.aladin.view.mode !== View.PAN ? {
|
||||
reason: 'Exit your current mode<br/>(e.g. disable the SIMBAD pointer mode)'
|
||||
} : false,
|
||||
action(o) {
|
||||
o.stopPropagation();
|
||||
o.preventDefault();
|
||||
|
||||
self._hide();
|
||||
|
||||
self.aladin.select('poly', p => {
|
||||
try {
|
||||
let ra = []
|
||||
let dec = []
|
||||
for (const v of p.vertices) {
|
||||
let [lon, lat] = self.aladin.pix2world(v.x, v.y, 'j2000');
|
||||
ra.push(lon)
|
||||
dec.push(lat)
|
||||
}
|
||||
|
||||
let moc = A.MOCFromPolygon(
|
||||
{ra, dec},
|
||||
{name: 'poly', lineWidth: 3.0},
|
||||
);
|
||||
self.aladin.addMOC(moc)
|
||||
|
||||
} catch(_) {
|
||||
alert('Selection covers a region out of the projection definition domain.');
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}];
|
||||
|
||||
for(const overlay of overlays) {
|
||||
const name = overlay.name;
|
||||
let cssStyle = {
|
||||
height: 'fit-content',
|
||||
};
|
||||
let showBtn = new ActionButton({
|
||||
size: 'small',
|
||||
icon: {
|
||||
url: overlay.isShowing ? showIconUrl : hideIconUrl,
|
||||
monochrome: true,
|
||||
},
|
||||
cssStyle: {
|
||||
visibility: Utils.hasTouchScreen() ? 'visible' : 'hidden',
|
||||
},
|
||||
tooltip: {content: overlay.isShowing ? 'Hide' : 'Show', position: {direction: 'bottom'}},
|
||||
action(e, btn) {
|
||||
if (overlay.isShowing) {
|
||||
overlay.hide()
|
||||
btn.update({icon: {monochrome: true, url: hideIconUrl}, tooltip: {content: 'Show'}});
|
||||
} else {
|
||||
overlay.show()
|
||||
btn.update({icon: {monochrome: true, url: showIconUrl}, tooltip: {content: 'Hide'}});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let deleteBtn = new ActionButton({
|
||||
icon: {
|
||||
url: removeIconUrl,
|
||||
monochrome: true,
|
||||
},
|
||||
size: 'small',
|
||||
cssStyle: {
|
||||
visibility: Utils.hasTouchScreen() ? 'visible' : 'hidden',
|
||||
},
|
||||
tooltip: {
|
||||
content: 'Remove',
|
||||
position: {direction: 'bottom'}
|
||||
},
|
||||
action(e) {
|
||||
self.aladin.removeLayer(overlay)
|
||||
}
|
||||
});
|
||||
|
||||
let item = Layout.horizontal({
|
||||
layout: [
|
||||
this._addOverlayIcon(overlay),
|
||||
'<div style="background-color: rgba(0, 0, 0, 0.6); padding: 3px; border-radius: 3px; word-break: break-word;">' + name + '</div>',
|
||||
Layout.horizontal({layout: [showBtn, deleteBtn]})
|
||||
],
|
||||
cssStyle: {
|
||||
textAlign: 'center',
|
||||
}
|
||||
});
|
||||
|
||||
if(!Utils.hasTouchScreen()) {
|
||||
layout.push({
|
||||
label: item,
|
||||
cssStyle,
|
||||
hover(e) {
|
||||
showBtn.el.style.visibility = 'visible'
|
||||
deleteBtn.el.style.visibility = 'visible'
|
||||
},
|
||||
unhover(e) {
|
||||
showBtn.el.style.visibility = 'hidden'
|
||||
deleteBtn.el.style.visibility = 'hidden'
|
||||
},
|
||||
})
|
||||
} else {
|
||||
layout.push({
|
||||
label: item,
|
||||
cssStyle
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// survey list
|
||||
let selectedLayer = self.aladin.getSelectedLayer();
|
||||
|
||||
/*if (!layers) {
|
||||
super.attach(layout);
|
||||
return;
|
||||
}*/
|
||||
|
||||
const defaultLayers = Object.entries(ImageSurvey.cache).sort(function (e1, e2) {
|
||||
let a = e1[1]
|
||||
let b = e2[1]
|
||||
|
||||
if (!a.order) {
|
||||
return a.name > b.name ? 1 : -1;
|
||||
}
|
||||
|
||||
return a.maxOrder && a.maxOrder > b.maxOrder ? 1 : -1;
|
||||
});
|
||||
|
||||
for(const layer of layers) {
|
||||
let backgroundUrl = layer.url + '/preview.jpg';
|
||||
let cssStyle = {
|
||||
height: 'fit-content',
|
||||
};
|
||||
|
||||
if (backgroundUrl) {
|
||||
cssStyle = {
|
||||
backgroundSize: '100%',
|
||||
backgroundImage: 'url(' + backgroundUrl + ')',
|
||||
...cssStyle
|
||||
}
|
||||
}
|
||||
|
||||
let showBtn = ActionButton.createSmallSizedIconBtn({
|
||||
icon: {
|
||||
url: layer.getOpacity() === 0.0 ? hideIconUrl : showIconUrl,
|
||||
monochrome: true,
|
||||
},
|
||||
cssStyle: {
|
||||
visibility: Utils.hasTouchScreen() ? 'visible' : 'hidden',
|
||||
},
|
||||
tooltip: {content: layer.getOpacity() === 0.0 ? 'Show' : 'Hide', position: {direction: 'bottom'}},
|
||||
action(e, btn) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
let opacity = layer.getOpacity();
|
||||
if (opacity === 0.0) {
|
||||
layer.setOpacity(1.0);
|
||||
btn.update({icon: {monochrome: true, url: showIconUrl}, tooltip: {content: 'Hide'}});
|
||||
} else {
|
||||
layer.setOpacity(0.0);
|
||||
btn.update({icon: {monochrome: true, url: hideIconUrl}, tooltip: {content: 'Show'}});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let deleteBtn = ActionButton.createSmallSizedIconBtn({
|
||||
icon: {url: removeIconUrl, monochrome: true},
|
||||
cssStyle: {
|
||||
visibility: Utils.hasTouchScreen() ? 'visible' : 'hidden',
|
||||
},
|
||||
disable: layer.layer === 'base',
|
||||
tooltip: {content: 'Remove', position: {direction: 'bottom'}},
|
||||
action(e) {
|
||||
self.aladin.removeImageLayer(layer.layer);
|
||||
}
|
||||
});
|
||||
|
||||
let editBtn = ActionButton.createSmallSizedIconBtn({
|
||||
icon: {url: settingsIconUrl, monochrome: true},
|
||||
cssStyle: {
|
||||
visibility: Utils.hasTouchScreen() ? 'visible' : 'hidden',
|
||||
},
|
||||
tooltip: {content: 'Settings', position: {direction: 'bottom'}},
|
||||
action: (e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
self._hide();
|
||||
|
||||
//self.aladin.selectLayer(layer.layer);
|
||||
//self.attach()
|
||||
|
||||
self.editBox = new LayerEditBox(self.aladin);
|
||||
self.editBox.update({layer})
|
||||
self.editBox._show({position: self.position});
|
||||
|
||||
self.mode = 'edit';
|
||||
}
|
||||
});
|
||||
|
||||
let loadMOCBtn = new TogglerActionButton({
|
||||
size: 'small',
|
||||
cssStyle: {
|
||||
visibility: Utils.hasTouchScreen() ? 'visible' : 'hidden',
|
||||
},
|
||||
icon: {url: Icon.dataURLFromSVG({svg: Icon.SVG_ICONS.MOC}), monochrome: true},
|
||||
tooltip: {content: 'Add coverage', position: {direction: 'bottom'}},
|
||||
toggled: (() => {
|
||||
let overlays = self.aladin.getOverlays();
|
||||
let found = overlays.find((o) => o.type === "moc" && o.name === layer.name);
|
||||
return found !== undefined;
|
||||
})(),
|
||||
actionOn: (e) => {
|
||||
let moc = A.MOCFromURL(layer.url + '/Moc.fits', {lineWidth: 3, name: layer.name});
|
||||
self.aladin.addMOC(moc);
|
||||
|
||||
self.mocHiPSUrls[layer.url] = moc;
|
||||
loadMOCBtn.update({tooltip: {content: 'Remove coverage', position: {direction: 'bottom'}}})
|
||||
|
||||
if (self.aladin.statusBar) {
|
||||
self.aladin.statusBar.appendMessage({
|
||||
message: 'Coverage of ' + layer.name + ' loaded',
|
||||
duration: 2000,
|
||||
type: 'info'
|
||||
})
|
||||
}
|
||||
},
|
||||
actionOff: (e) => {
|
||||
let moc = self.mocHiPSUrls[layer.url];
|
||||
self.aladin.removeLayer(moc)
|
||||
|
||||
delete self.mocHiPSUrls[layer.url];
|
||||
|
||||
loadMOCBtn.update({tooltip: {content: 'Add coverage', position: {direction: 'bottom'}}})
|
||||
|
||||
if (self.aladin.statusBar) {
|
||||
self.aladin.statusBar.appendMessage({
|
||||
message: 'Coverage of ' + layer.name + ' removed',
|
||||
duration: 2000,
|
||||
type: 'info'
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let layerClassName = 'a' + layer.layer.replace(/[.\/ ]/g, '')
|
||||
|
||||
let btns = [showBtn, editBtn];
|
||||
|
||||
if (layer.subtype !== 'fits') {
|
||||
btns.push(loadMOCBtn)
|
||||
}
|
||||
btns.push(deleteBtn)
|
||||
|
||||
let item = Layout.horizontal({
|
||||
layout: [
|
||||
'<div class="' + layerClassName + '" style="background-color: rgba(0, 0, 0, 0.6); line-height: 1rem; padding: 3px; border-radius: 3px; word-break: break-word;' + (selectedLayer === layer.layer ? 'border: 1px solid white;' : '') + '">' + (layer.name) + '</div>',
|
||||
Layout.horizontal(btns)
|
||||
],
|
||||
/*cssStyle: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
listStyle: 'none',
|
||||
justifyContent: 'space-between',
|
||||
width: '100%',
|
||||
}*/
|
||||
});
|
||||
|
||||
let l = {
|
||||
label: item,
|
||||
classList: 'surveyItem',
|
||||
cssStyle,
|
||||
hover(e) {
|
||||
showBtn.el.style.visibility = 'visible'
|
||||
editBtn.el.style.visibility = 'visible'
|
||||
deleteBtn.el.style.visibility = 'visible'
|
||||
loadMOCBtn.el.style.visibility = 'visible'
|
||||
},
|
||||
unhover(e) {
|
||||
showBtn.el.style.visibility = 'hidden'
|
||||
editBtn.el.style.visibility = 'hidden'
|
||||
deleteBtn.el.style.visibility = 'hidden'
|
||||
loadMOCBtn.el.style.visibility = 'hidden'
|
||||
}
|
||||
};
|
||||
|
||||
l.subMenu = [];
|
||||
l.subMenu.push({
|
||||
label: {
|
||||
icon: {
|
||||
url: searchIconImg,
|
||||
monochrome: true,
|
||||
tooltip: {content: 'Find a specific survey <br /> in our database...', position: { direction: 'bottom' }},
|
||||
cssStyle: {
|
||||
cursor: 'help',
|
||||
},
|
||||
},
|
||||
content: 'More...'
|
||||
},
|
||||
action(o) {
|
||||
o.stopPropagation();
|
||||
o.preventDefault();
|
||||
|
||||
self._hide();
|
||||
|
||||
self.hipsBox = new HiPSSelectorBox(self.aladin)
|
||||
|
||||
self.hipsBox.attach((HiPSId) => {
|
||||
self.aladin.setOverlayImageLayer(HiPSId, layer.layer);
|
||||
self.show();
|
||||
});
|
||||
|
||||
self.hipsBox._show({
|
||||
position: self.position,
|
||||
})
|
||||
|
||||
self.mode = 'hips';
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
for(const [id, ll] of defaultLayers) {
|
||||
backgroundUrl = OverlayStack.previewImagesUrl[ll.name];
|
||||
if (!backgroundUrl) {
|
||||
backgroundUrl = ll.url + '/preview.jpg'
|
||||
}
|
||||
let cssStyle = {
|
||||
height: '2.5em',
|
||||
};
|
||||
if (backgroundUrl) {
|
||||
cssStyle = {
|
||||
backgroundSize: '100%',
|
||||
backgroundImage: 'url(' + backgroundUrl + ')',
|
||||
...cssStyle
|
||||
}
|
||||
}
|
||||
|
||||
l.subMenu.push({
|
||||
//selected: layer.name === aladin.getBaseImageLayer().name,
|
||||
label: '<div style="background-color: rgba(0, 0, 0, 0.6); line-height: 1rem; padding: 3px; border-radius: 3px">' + ll.name + '</div>',
|
||||
cssStyle,
|
||||
action(e) {
|
||||
self.aladin.setOverlayImageLayer(id, layer.layer);
|
||||
},
|
||||
hover(e, item) {
|
||||
item.style.filter = 'brightness(1.5)';
|
||||
},
|
||||
unhover(e, item) {
|
||||
item.style.filter = 'brightness(1.0)';
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
l.action = (o) => {
|
||||
let oldLayerClassName = 'a' + self.aladin.getSelectedLayer().replace(/[.\/ ]/g, '')
|
||||
self.el.querySelector('.' + oldLayerClassName).style.removeProperty('border')
|
||||
self.aladin.selectLayer(layer.layer);
|
||||
self.el.querySelector('.' + layerClassName).style.border = '1px solid white';
|
||||
}
|
||||
|
||||
layout.push(l);
|
||||
}
|
||||
|
||||
super.attach(layout);
|
||||
}
|
||||
|
||||
_findPreviewImageUrl(layer) {
|
||||
if (layer instanceof ImageFITS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!layer.creatorDid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const creatorDid = layer.creatorDid;
|
||||
|
||||
for (const key in Stack.previewImagesUrl) {
|
||||
if (creatorDid.includes(key)) {
|
||||
return Stack.previewImagesUrl[key];
|
||||
}
|
||||
}
|
||||
// if not found
|
||||
return layer.url + '/preview.jpg'
|
||||
}
|
||||
|
||||
_addOverlayIcon(overlay) {
|
||||
var tooltipText;
|
||||
var svg = '';
|
||||
if (overlay.type == 'catalog' || overlay.type == 'progressivecat') {
|
||||
var nbSources = overlay.getSources().length;
|
||||
tooltipText = nbSources + ' source' + (nbSources > 1 ? 's' : '');
|
||||
|
||||
svg = Icon.SVG_ICONS.CATALOG;
|
||||
}
|
||||
else if (overlay.type == 'moc') {
|
||||
tooltipText = 'Coverage: ' + (100 * overlay.skyFraction()).toFixed(2) + ' % of sky';
|
||||
|
||||
svg = Icon.SVG_ICONS.MOC;
|
||||
}
|
||||
else if (overlay.type == 'overlay') {
|
||||
svg = Icon.SVG_ICONS.OVERLAY;
|
||||
}
|
||||
|
||||
let tooltip;
|
||||
if (tooltipText) {
|
||||
tooltip = { content: tooltipText, position: {direction: 'bottom'} }
|
||||
}
|
||||
|
||||
// retrieve SVG icon, and apply the layer color
|
||||
return new Icon({
|
||||
size: 'small',
|
||||
url: Icon.dataURLFromSVG({svg, color: overlay.color}),
|
||||
tooltip
|
||||
});
|
||||
}
|
||||
|
||||
show(options) {
|
||||
if (this.mode !== 'stack') {
|
||||
if(this.hipsSelectorBox) {
|
||||
this.hipsSelectorBox.remove()
|
||||
}
|
||||
|
||||
if(this.catBox) {
|
||||
this.catBox.remove()
|
||||
}
|
||||
|
||||
if(this.hipsBox) {
|
||||
this.hipsBox.remove()
|
||||
}
|
||||
|
||||
if(this.editBox) {
|
||||
this.editBox.remove()
|
||||
}
|
||||
}
|
||||
|
||||
self.mode = 'stack';
|
||||
|
||||
this.attach();
|
||||
|
||||
this.position = (options && options.position) || this.position || { anchor: 'center center'};
|
||||
this.position.aladin = this.aladin;
|
||||
super.show({
|
||||
...options,
|
||||
...{position: this.position},
|
||||
cssStyle: {
|
||||
maxWidth: '17rem',
|
||||
}
|
||||
})
|
||||
|
||||
const innerHeight = this.aladin.aladinDiv.offsetHeight;
|
||||
this.element().querySelectorAll(".surveyItem")
|
||||
.forEach((surveyItem) => {
|
||||
surveyItem.querySelectorAll(".aladin-context-sub-menu")
|
||||
// skip the first menu
|
||||
.forEach((subMenu) => {
|
||||
subMenu.style.display = 'block'
|
||||
|
||||
let Y = innerHeight - (subMenu.getBoundingClientRect().y - this.aladin.aladinDiv.getBoundingClientRect().y);
|
||||
subMenu.style.display = 'none'
|
||||
|
||||
subMenu.style.maxHeight = Y + 'px';
|
||||
subMenu.style.overflowY = 'scroll';
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user