mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2025-12-12 07:40:26 -08:00
Reverse the longitude axis globally
This method does add: * reverseLongitude method on aladin object * add a longitudeReversed flag in AladinOptions, when creating the aladin view to reverse the longitude axis globally at start. * BREAKS the HiPS options API by removing the longitudeReversed option at the HiPS level, replacing it by a global flag on the aladin lite view * fix: when adding two times the same survey, we could not change its hips options This commit also impl #191
This commit is contained in:
committed by
Matthieu Baumann
parent
645bab7cd9
commit
945672a846
@@ -10,6 +10,8 @@ import A from '../src/js/A.js';
|
||||
A.init.then(() => {
|
||||
let aladin = A.aladin('#aladin-lite-div', {projection: "TAN", survey: "P/HSC/DR2/deep/g", target: '02 21 36.529 -05 31 20.16', fov: 0.1});
|
||||
|
||||
aladin.reverseLongitude(true)
|
||||
|
||||
let hscGreenSurvey = aladin.getBaseImageLayer();
|
||||
hscGreenSurvey.setImageFormat("fits");
|
||||
hscGreenSurvey.setColormap("green", { stretch: "asinh" });
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
|
||||
let stephansNIRCamMIRI
|
||||
async function s11() {
|
||||
stephansNIRCamMIRI = aladin.createImageSurvey('CDS/P/JWST/Stephans-Quintet/NIRCam+MIRI', "stephansMIRI", null, null, null)
|
||||
stephansNIRCamMIRI = aladin.createImageSurvey('CDS/P/JWST/Stephans-Quintet/NIRCam-MIRI', "stephansNircamMIRI", null, null, null)
|
||||
stephansNIRCamMIRI.setOpacity(0.0)
|
||||
aladin.setOverlayImageLayer(stephansNIRCamMIRI, 'stephansNIRCamMIRI')
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
<script src="https://code.jquery.com/jquery-1.10.1.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
let aladin;
|
||||
let longitudeReversed = false;
|
||||
</script>
|
||||
<div id="aladin-lite-div" style="width:100vw;height:100vh;">
|
||||
<div id="calibCircle" style="display: none;"></div>
|
||||
@@ -37,8 +38,8 @@
|
||||
<!-- fin temporaire gestion cercle -->
|
||||
|
||||
<b>Orientation</b><br>
|
||||
<button id="hips-coronelli" class="pure-button" name="ref-hips" onclick="aladin.setImageSurvey('Coronelli')">Normal</button><br>
|
||||
<button id="hips-illenoroc" class="pure-button" name="ref-hips" onclick="aladin.setImageSurvey('illenoroC')">Inversé</button>
|
||||
<button id="hips-coronelli" class="pure-button" name="ref-hips" onclick="longitudeReversed = false; aladin.reverseLongitude(longitudeReversed)">Normal</button><br>
|
||||
<button id="hips-illenoroc" class="pure-button" name="ref-hips" onclick="longitudeReversed = true; aladin.reverseLongitude(longitudeReversed)">Inversé</button>
|
||||
<br><br>
|
||||
|
||||
<b>Constellations</b>
|
||||
@@ -232,8 +233,7 @@
|
||||
A.init.then(() => {
|
||||
var hipsDir="http://alasky.u-strasbg.fr/CDS_P_Coronelli";
|
||||
aladin = A.aladin("#aladin-lite-div", {showSimbadPointerControl: true, expandLayersControl: true, realFullscreen: true, fov: 100, allowFullZoomout: true, showReticle: false });
|
||||
aladin.createImageSurvey('illenoroC', 'illenoroC', hipsDir, 'equatorial', 4, {imgFormat: 'jpg', longitudeReversed: false});
|
||||
aladin.createImageSurvey('Coronelli', 'Coronelli', hipsDir, 'equatorial', 4, {imgFormat: 'jpg', longitudeReversed: true});
|
||||
aladin.createImageSurvey('Coronelli', 'Coronelli', hipsDir, 'equatorial', 4, {imgFormat: 'jpg'});
|
||||
aladin.setImageSurvey('Coronelli');
|
||||
|
||||
$('#layersControlLeft').show();
|
||||
|
||||
23
examples/al-flip-longitude-axis.html
Normal file
23
examples/al-flip-longitude-axis.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div id="aladin-lite-div" style="width: 1024px; height: 768px"></div>
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
|
||||
A.init.then(() => {
|
||||
let aladin = A.aladin('#aladin-lite-div', {longitudeReversed: true, showCooGrid: true, cooFrame: 'galactic', target: '0 0', fov: 100});
|
||||
//aladin.reverseLongitude(true)
|
||||
|
||||
setTimeout(
|
||||
() => {
|
||||
aladin.reverseLongitude(false)
|
||||
},
|
||||
5000
|
||||
)
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,16 +5,16 @@
|
||||
<body>
|
||||
<div>
|
||||
<div id="offset" style="display: inline-block; width: 200px; height: 100px"></div>
|
||||
<div id="aladin-lite-div" style="display: inline-block; width: 50%"></div>
|
||||
<div id="aladin-lite-div" style="width: 500px; height: 500px"></div>
|
||||
</div>
|
||||
<!--<script type="text/javascript" src="https://aladin.cds.unistra.fr/AladinLite/api/v3/latest/aladin.js" charset="utf-8"></script>-->
|
||||
|
||||
|
||||
<script>let aladin, hips</script>
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {projection: 'TAN', cooFrame: 'galactic', showSettingsControl: true, showSimbadPointerControl: true, showContextMenu: true, target: 'galactic center', survey: 'P/Finkbeiner'});
|
||||
aladin = A.aladin('#aladin-lite-div', {projection: 'TAN', cooFrame: 'galactic', showSettingsControl: true, showSimbadPointerControl: true, showContextMenu: true, target: 'galactic center'});
|
||||
// possible values are 'blues', 'cividis', 'cubehelix', 'eosb', 'grayscale', 'inferno', 'magma', 'native', 'parula', 'plasma', 'rainbow',
|
||||
// 'rdbu', 'rdylbu', 'redtemperature', 'sinebow', 'spectral', 'summer', 'viridis', 'ylgnbu' and 'ylorbr'
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import A from '../src/js/A.js';
|
||||
let aladin;
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {survey: 'http://alasky.cds.unistra.fr/ancillary/GaiaDR2/hips-density-map/', showProjectionControl: true, showContextMenu: true, showStatusBar: true, fullScreen: true, target: 'galactic center'});
|
||||
aladin = A.aladin('#aladin-lite-div', {survey: 'http://alasky.cds.unistra.fr/ancillary/GaiaDR2/hips-density-map/', showProjectionControl: true, showContextMenu: true, showStatusBar: true, fullScreen: true, target: 'galactic center', expandLayersControl: true});
|
||||
|
||||
const fluxMap = aladin.createImageSurvey('gdr3-color-flux-map', 'Gaia DR3 flux map', 'https://alasky.u-strasbg.fr/ancillary/GaiaEDR3/color-Rp-G-Bp-flux-map', 'equatorial', 7);
|
||||
const densityMap = aladin.createImageSurvey('gdr3-density-map', 'Gaia DR3 density map', 'sdfsg', 'equatorial', 7, {formats: ['fits']});
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {projection: 'MOL', fullScreen: true, fov: 360, survey: ['P/DM/vizMine', 'P/HST/GOODS/color', 'P/MATLAS/g'], target: '0 0', showProjectionControl: false, showSettingsControl: false, showLayersControl: false, showCooGrid: false, showFrame: false, showCooLocation: false});
|
||||
aladin = A.aladin('#aladin-lite-div', {projection: 'MOL', fullScreen: true, fov: 360, survey: ['P/DM/vizMine', 'P/HST/GOODS/color', 'P/MATLAS/g'], target: '0 0', showProjectionControl: false, showSettingsControl: false, showLayersControl: true, showCooGrid: false, showFrame: false, showCooLocation: false});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ A.init.then(() => {
|
||||
let aladin = A.aladin('#aladin-lite-div', {fov: 70,projection: "AIT"});
|
||||
|
||||
aladin.setOverlayImageLayer(A.imageHiPS(
|
||||
'Fermi',
|
||||
"https://alasky.cds.unistra.fr/Fermi/Color",
|
||||
{
|
||||
name: "Fermi color",
|
||||
|
||||
@@ -15,16 +15,17 @@
|
||||
let survey1 = aladin.getBaseImageLayer();
|
||||
survey1.setColormap('magma', {stretch: 'linear'});
|
||||
|
||||
let survey2 = aladin.newImageSurvey("CSIRO/P/RACS/low/I");
|
||||
aladin.setImageLayer(survey2)
|
||||
let survey2 = aladin.newImageSurvey("CSIRO/P/RACS/low/I", {name: 'racs low'});
|
||||
survey2.setColormap('rdbu', {stretch: 'linear'});
|
||||
|
||||
aladin.setImageLayer(survey2)
|
||||
|
||||
|
||||
let survey3 = aladin.newImageSurvey("CSIRO/P/RACS/mid/I");
|
||||
aladin.setImageLayer(survey3)
|
||||
survey3.setColormap('cubehelix', {stretch: 'asinh'});
|
||||
|
||||
aladin.setImageLayer(survey2);
|
||||
|
||||
setTimeout(() => {
|
||||
aladin.removeHiPSFromFavorites(survey3)
|
||||
}, 5000);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
<body>
|
||||
<div id="aladin-lite-div" style="width: 1024px; height: 768px"></div>
|
||||
|
||||
<div id='aladin-statsDiv'></div>
|
||||
<script>let aladin, hips</script>
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
|
||||
@@ -223,16 +223,10 @@ pub struct ImageMetadata {
|
||||
pub blend_cfg: BlendCfg,
|
||||
#[serde(default = "default_opacity")]
|
||||
pub opacity: f32,
|
||||
#[serde(default = "default_longitude_reversed")]
|
||||
pub longitude_reversed: bool,
|
||||
/// the current format chosen
|
||||
pub img_format: ImageExt,
|
||||
}
|
||||
|
||||
fn default_longitude_reversed() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn default_opacity() -> f32 {
|
||||
1.0
|
||||
}
|
||||
|
||||
@@ -1323,6 +1323,10 @@ impl App {
|
||||
self.camera.get_longitude_reversed()
|
||||
}
|
||||
|
||||
pub(crate) fn set_longitude_reversed(&mut self, longitude_reversed: bool) {
|
||||
self.camera.set_longitude_reversed(longitude_reversed, &self.projection);
|
||||
}
|
||||
|
||||
pub(crate) fn add_catalog(&mut self, _name: String, table: JsValue, _colormap: String) {
|
||||
//let mut exec_ref = self.exec.borrow_mut();
|
||||
let _table = table;
|
||||
|
||||
@@ -566,6 +566,12 @@ impl WebClient {
|
||||
self.app.get_longitude_reversed()
|
||||
}
|
||||
|
||||
/// Set the longitude axis reversed globally
|
||||
#[wasm_bindgen(js_name = setLongitudeReversed)]
|
||||
pub fn set_longitude_reversed(&mut self, longitude_reversed: bool) {
|
||||
self.app.set_longitude_reversed(longitude_reversed);
|
||||
}
|
||||
|
||||
/// Get the field of view angle value when the view is zoomed out to its maximum
|
||||
///
|
||||
/// This method is dependent of the projection currently set.
|
||||
|
||||
@@ -308,12 +308,6 @@ impl Layers {
|
||||
.ok_or(err_layer_not_found)?;
|
||||
self.layers.remove(id_layer);
|
||||
|
||||
// Loop over all the meta for its longitude reversed property
|
||||
// and set the camera to it if there is at least one
|
||||
let longitude_reversed = self.meta.values().any(|meta| meta.longitude_reversed);
|
||||
|
||||
camera.set_longitude_reversed(longitude_reversed, proj);
|
||||
|
||||
// Check if the url is still used
|
||||
let id_still_used = self.ids.values().any(|rem_id| rem_id == &id);
|
||||
if id_still_used {
|
||||
@@ -421,11 +415,6 @@ impl Layers {
|
||||
|
||||
// 2. Add the meta information of the layer
|
||||
self.meta.insert(layer.clone(), meta);
|
||||
// Loop over all the meta for its longitude reversed property
|
||||
// and set the camera to it if there is at least one
|
||||
let longitude_reversed = self.meta.values().any(|meta| meta.longitude_reversed);
|
||||
|
||||
camera.set_longitude_reversed(longitude_reversed, proj);
|
||||
|
||||
// 3. Add the image hips
|
||||
let creator_did = String::from(properties.get_creator_did());
|
||||
@@ -500,11 +489,6 @@ impl Layers {
|
||||
|
||||
// 2. Add the meta information of the layer
|
||||
self.meta.insert(layer.clone(), meta);
|
||||
// Loop over all the meta for its longitude reversed property
|
||||
// and set the camera to it if there is at least one
|
||||
let longitude_reversed = self.meta.values().any(|meta| meta.longitude_reversed);
|
||||
|
||||
camera.set_longitude_reversed(longitude_reversed, proj);
|
||||
|
||||
// 3. Add the fits image
|
||||
// The layer does not already exist
|
||||
|
||||
@@ -143,7 +143,8 @@ import { Polyline } from "./shapes/Polyline";
|
||||
* @property {number} [gridOptions.labelSize=15] - The font size of the labels.
|
||||
*
|
||||
* @property {string} [projection="SIN"] - Projection type. Can be 'SIN' for orthographic, 'MOL' for mollweide, 'AIT' for hammer-aitoff, 'ZEA' for zenital equal-area or 'MER' for mercator
|
||||
* @property {boolean} [log=true] - Whether to log events.
|
||||
* @property {boolean} [longitudeReversed=false] - Longitude reverse axis flag. Set to true to reverse the longitude axis. This is especially needed for planetary survey visualization. Default is set to false.
|
||||
* @property {boolean} [log=true] - Whether to log events.
|
||||
* @property {boolean} [samp=false] - Whether to enable SAMP (Simple Application Messaging Protocol).
|
||||
* @property {boolean} [realFullscreen=false] - Whether to use real fullscreen mode.
|
||||
* @property {boolean} [pixelateCanvas=true] - Whether to pixelate the canvas.
|
||||
@@ -518,6 +519,10 @@ export let Aladin = (function () {
|
||||
if (options.northPoleOrientation) {
|
||||
this.setRotation(options.northPoleOrientation);
|
||||
}
|
||||
|
||||
if (options.longitudeReversed !== undefined && options.longitudeReversed !== null) {
|
||||
this.reverseLongitude(options.longitudeReversed)
|
||||
}
|
||||
};
|
||||
|
||||
Aladin.prototype._setupUI = function (options) {
|
||||
@@ -700,6 +705,8 @@ export let Aladin = (function () {
|
||||
projection: "SIN",
|
||||
log: true,
|
||||
samp: false,
|
||||
// Longitude reversed flag
|
||||
longitudeReversed: false,
|
||||
realFullscreen: false,
|
||||
pixelateCanvas: true,
|
||||
manualSelection: false
|
||||
@@ -898,7 +905,7 @@ export let Aladin = (function () {
|
||||
* Sets the coordinate frame of the Aladin instance to the specified frame.
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string} frame - The name of the coordinate frame. Possible values: 'j2000d', 'j2000', 'gal', 'icrs'. The given string is case insensitive.
|
||||
* @param {string} frame - The name of the coordinate frame. Possible values: 'j2000d', 'j2000', 'gal', 'icrs', 'equatorial'. The given string is case insensitive.
|
||||
*
|
||||
* @example
|
||||
* // Set the coordinate frame to 'J2000'
|
||||
@@ -1785,6 +1792,16 @@ export let Aladin = (function () {
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverse the longitude axis of the view globally
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {Boolean} [longitudeReversed] - Reverse the longitude axis
|
||||
*/
|
||||
Aladin.prototype.reverseLongitude = function (longitudeReversed) {
|
||||
this.view.reverseLongitude(longitudeReversed)
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a new HiPS layer to the view on top of the others
|
||||
*
|
||||
@@ -1959,8 +1976,8 @@ export let Aladin = (function () {
|
||||
if (!cachedLayerOptions) {
|
||||
hipsCache.append(imageLayer.id, imageLayer.options)
|
||||
} else {
|
||||
// Set the options from what is in the cache
|
||||
imageLayer.setOptions(cachedLayerOptions);
|
||||
// Set the image layer object with the options from the cache.
|
||||
imageLayer.setOptions(cachedLayerOptions)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1968,8 +1985,6 @@ export let Aladin = (function () {
|
||||
// Add it to the hipsList if it is not there yet
|
||||
this.addHiPSToFavorites(imageLayer)
|
||||
|
||||
imageLayer.layer = layer;
|
||||
|
||||
return this.view.setOverlayImageLayer(imageLayer, layer);
|
||||
};
|
||||
|
||||
@@ -2186,7 +2201,7 @@ export let Aladin = (function () {
|
||||
aladin.on("layerChanged", (layer, layerName, state) => {
|
||||
console.log("layerChanged", layer, layerName, state)
|
||||
})
|
||||
*/
|
||||
*/
|
||||
Aladin.prototype.on = function (what, myFunction) {
|
||||
if (Aladin.AVAILABLE_CALLBACKS.indexOf(what) < 0) {
|
||||
return;
|
||||
|
||||
@@ -41,17 +41,31 @@
|
||||
this.stretch = (options && options.stretch) || "linear";
|
||||
this.stretch = this.stretch.toLowerCase();
|
||||
this.reversed = false;
|
||||
// Keep the image tile format because we want the cuts
|
||||
this.imgFormat = options.imgFormat || 'png';
|
||||
|
||||
if (options && options.reversed === true) {
|
||||
this.reversed = true;
|
||||
}
|
||||
|
||||
this.minCut = {
|
||||
webp: 0.0,
|
||||
jpeg: 0.0,
|
||||
png: 0.0,
|
||||
fits: undefined // wait the default value coming from the properties
|
||||
};
|
||||
if (options && Number.isFinite(options.minCut)) {
|
||||
this.minCut = options.minCut;
|
||||
this.minCut[this.imgFormat] = options.minCut;
|
||||
}
|
||||
|
||||
this.maxCut = {
|
||||
webp: 1.0,
|
||||
jpeg: 1.0,
|
||||
png: 1.0,
|
||||
fits: undefined // wait the default value coming from the properties
|
||||
};
|
||||
if (options && Number.isFinite(options.maxCut)) {
|
||||
this.maxCut = options.maxCut;
|
||||
this.maxCut[this.imgFormat] = options.maxCut;
|
||||
}
|
||||
|
||||
this.additiveBlending = options && options.additive;
|
||||
@@ -93,8 +107,8 @@
|
||||
kContrast: this.kContrast,
|
||||
|
||||
stretch: this.stretch,
|
||||
minCut: this.minCut,
|
||||
maxCut: this.maxCut,
|
||||
minCut: this.minCut[this.imgFormat],
|
||||
maxCut: this.maxCut[this.imgFormat],
|
||||
reversed: this.reversed,
|
||||
cmapName: this.colormap,
|
||||
}
|
||||
@@ -102,6 +116,9 @@
|
||||
}
|
||||
|
||||
ColorCfg.prototype.setOptions = function(options) {
|
||||
// Update the imgFormat
|
||||
this.imgFormat = options.imgFormat || this.imgFormat;
|
||||
|
||||
this.setColormap(options.colormap, options)
|
||||
|
||||
this.setCuts(options.minCut, options.maxCut)
|
||||
@@ -231,18 +248,28 @@
|
||||
return this.reversed;
|
||||
};
|
||||
|
||||
// @api
|
||||
// Sets the cuts for the current image format
|
||||
ColorCfg.prototype.setCuts = function(minCut, maxCut) {
|
||||
if (minCut === null || minCut === undefined || maxCut === null || maxCut === undefined) {
|
||||
return;
|
||||
if (minCut instanceof Object) {
|
||||
// Mincut is given in the form of an javascript object with all the formats
|
||||
this.minCut = minCut
|
||||
} else if (minCut !== null && minCut !== undefined) {
|
||||
this.minCut[this.imgFormat] = minCut;
|
||||
}
|
||||
|
||||
this.minCut = minCut;
|
||||
this.maxCut = maxCut;
|
||||
if (maxCut instanceof Object) {
|
||||
this.maxCut = maxCut;
|
||||
} else if (maxCut !== null && maxCut !== undefined) {
|
||||
this.maxCut[this.imgFormat] = maxCut;
|
||||
}
|
||||
};
|
||||
|
||||
// Returns the cuts for the current image format
|
||||
ColorCfg.prototype.getCuts = function() {
|
||||
return [this.minCut, this.maxCut];
|
||||
return [
|
||||
this.minCut[this.imgFormat],
|
||||
this.maxCut[this.imgFormat]
|
||||
];
|
||||
};
|
||||
|
||||
return ColorCfg;
|
||||
|
||||
@@ -49,7 +49,7 @@ export let CooFrameEnum = (function() {
|
||||
if (str.indexOf('j2000d')==0 || str.indexOf('icrsd')==0) {
|
||||
return CooFrameEnum.ICRSd;
|
||||
}
|
||||
else if (str.indexOf('j2000')==0 || str.indexOf('icrs')==0) {
|
||||
else if (str.indexOf('j2000')==0 || str.indexOf('icrs')==0 || str.indexOf('equatorial')==0) {
|
||||
return CooFrameEnum.ICRS;
|
||||
}
|
||||
else if (str.indexOf('gal')==0) {
|
||||
|
||||
545
src/js/HiPS.js
545
src/js/HiPS.js
@@ -76,12 +76,12 @@ PropertyParser.minOrder = function (properties) {
|
||||
return minOrder;
|
||||
};
|
||||
|
||||
PropertyParser.formats = function (properties) {
|
||||
let formats = (properties && properties.hips_tile_format) || "jpeg";
|
||||
PropertyParser.acceptedFormats = function (properties) {
|
||||
let acceptedFormats = (properties && properties.hips_tile_format) || "jpeg";
|
||||
|
||||
formats = formats.split(" ").map((fmt) => fmt.toLowerCase());
|
||||
acceptedFormats = acceptedFormats.split(" ").map((fmt) => fmt.toLowerCase());
|
||||
|
||||
return formats;
|
||||
return acceptedFormats;
|
||||
};
|
||||
|
||||
PropertyParser.initialFov = function (properties) {
|
||||
@@ -143,20 +143,18 @@ PropertyParser.isPlanetaryBody = function (properties) {
|
||||
* <li>The coordinate frame of the HiPS</li>
|
||||
* </ul>
|
||||
*
|
||||
* @deprecated The longitudeReversed property is now deprecated from version 3.6.1. This property will be removed from version 3.7.0 and replaced with a method flipping the longitude axis directly on the {@link Aladin} view object and not at the HiPS level.
|
||||
*
|
||||
* @typedef {Object} HiPSOptions
|
||||
* @property {string} [name] - The name of the survey to be displayed in the UI
|
||||
* @property {Function} [successCallback] - A callback executed when the HiPS has been loaded
|
||||
* @property {Function} [errorCallback] - A callback executed when the HiPS could not be loaded
|
||||
* @property {string} [imgFormat] - Formats accepted 'webp', 'png', 'jpeg' or 'fits'. Will raise an error if the HiPS does not contain tiles in this format
|
||||
* @property {CooFrame} [cooFrame="ICRS"] - Coordinate frame of the survey tiles
|
||||
* @property {CooFrame} [cooFrame] - Coordinate frame of the survey tiles. If not given, the one from the parsed properties file will be retrieved.
|
||||
* @property {number} [maxOrder] - The maximum HEALPix order of the HiPS, i.e the HEALPix order of the most refined tile images of the HiPS.
|
||||
* @property {number} [numBitsPerPixel] - Useful if you want to display the FITS tiles of a HiPS. It specifies the number of bits per pixel. Possible values are:
|
||||
* -64: double, -32: float, 8: unsigned byte, 16: short, 32: integer 32 bits, 64: integer 64 bits
|
||||
* @property {number} [tileSize] - The width of the HEALPix tile images. Mostly 512 pixels but can be 256, 128, 64, 32
|
||||
* @property {number} [minOrder] - If not given, retrieved from the properties of the survey.
|
||||
* @property {boolean} [longitudeReversed=false] - Deprecated since 3.6.1: Set it to True for planetary survey visualization
|
||||
* @property {boolean} [longitudeReversed] - Deprecated The longitudeReversed property is now deprecated since version 3.6.1. This property has been removed since version 3.7.0 and replaced with {@link Aladin#reverseLongitude} set directly on the {@link Aladin} view object and not at the HiPS level.
|
||||
* @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.
|
||||
@@ -257,12 +255,8 @@ export let HiPS = (function () {
|
||||
this.cooFrame = CooFrameEnum.fromString(options.cooFrame, null);
|
||||
this.tileSize = options.tileSize;
|
||||
this.skyFraction = options.skyFraction;
|
||||
this.longitudeReversed =
|
||||
options.longitudeReversed === undefined
|
||||
? false
|
||||
: options.longitudeReversed;
|
||||
this.imgFormat = options.imgFormat;
|
||||
this.formats = options.formats;
|
||||
this.acceptedFormats = options.formats;
|
||||
this.defaultFitsMinCut = options.defaultFitsMinCut;
|
||||
this.defaultFitsMaxCut = options.defaultFitsMaxCut;
|
||||
this.numBitsPerPixel = options.numBitsPerPixel;
|
||||
@@ -271,6 +265,127 @@ export let HiPS = (function () {
|
||||
this.successCallback = options.successCallback;
|
||||
|
||||
this.colorCfg = new ColorCfg(options);
|
||||
|
||||
let self = this;
|
||||
|
||||
if (this.localFiles) {
|
||||
// Fetch the properties file
|
||||
this.query = new Promise(async (resolve, reject) => {
|
||||
// look for the properties file
|
||||
await HiPSProperties.fetchFromFile(self.localFiles["properties"])
|
||||
.then((p) => {
|
||||
self._parseProperties(p);
|
||||
|
||||
self.url = "local";
|
||||
|
||||
delete self.localFiles["properties"]
|
||||
})
|
||||
.catch((_) => reject("HiPS " + self.id + " error: " + self.localFiles["properties"] + " does not point towards a local HiPS."))
|
||||
|
||||
resolve(self);
|
||||
});
|
||||
} else {
|
||||
let isIncompleteOptions = true;
|
||||
|
||||
let isID = Utils.isUrl(this.url) === undefined;
|
||||
|
||||
if (this.imgFormat === "fits") {
|
||||
// a fits is given
|
||||
isIncompleteOptions = !(
|
||||
this.maxOrder &&
|
||||
(!isID && this.url) &&
|
||||
this.imgFormat &&
|
||||
this.tileSize &&
|
||||
this.cooFrame &&
|
||||
this.numBitsPerPixel
|
||||
);
|
||||
} else {
|
||||
isIncompleteOptions = !(
|
||||
this.maxOrder &&
|
||||
(!isID && this.url) &&
|
||||
this.imgFormat &&
|
||||
this.tileSize &&
|
||||
this.cooFrame
|
||||
);
|
||||
}
|
||||
|
||||
this.query = new Promise(async (resolve, reject) => {
|
||||
if (isIncompleteOptions) {
|
||||
// ID typed url
|
||||
if (self.startUrl && isID) {
|
||||
// First download the properties from the start url
|
||||
await HiPSProperties.fetchFromUrl(self.startUrl)
|
||||
.then((p) => {
|
||||
self._parseProperties(p);
|
||||
})
|
||||
.catch((_) => reject("HiPS " + self.id + " error: starting url " + self.startUrl + " given does not points to a HiPS location"))
|
||||
|
||||
// the url stores a "CDS ID" we take it prioritaly
|
||||
// if the url is null, take the id, this is for some tests
|
||||
// to pass because some users might just give null as url param and a "CDS ID" as id param
|
||||
let id = self.url || self.id;
|
||||
|
||||
self.url = self.startUrl;
|
||||
|
||||
setTimeout(
|
||||
() => {
|
||||
if (!self.added)
|
||||
return;
|
||||
|
||||
HiPSProperties.fetchFromID(id)
|
||||
.then((p) => {
|
||||
self._fetchFasterUrlFromProperties(p);
|
||||
})
|
||||
.catch((_) => reject("HiPS " + self.id + " error: CDS ID " + id + " is not found"));
|
||||
},
|
||||
1000
|
||||
);
|
||||
} else if (!self.startUrl && isID) {
|
||||
// the url stores a "CDS ID" we take it prioritaly
|
||||
// if the url is null, take the id, this is for some tests
|
||||
// to pass because some users might just give null as url param and a "CDS ID" as id param
|
||||
let id = self.url || self.id;
|
||||
|
||||
await HiPSProperties.fetchFromID(id)
|
||||
.then((p) => {
|
||||
self.url = p.hips_service_url;
|
||||
|
||||
self._parseProperties(p);
|
||||
self._fetchFasterUrlFromProperties(p);
|
||||
})
|
||||
.catch(() => {
|
||||
// If no ID has been found then it may actually be a path
|
||||
// url pointing to a local HiPS
|
||||
return HiPSProperties.fetchFromUrl(id)
|
||||
.then((p) => {
|
||||
self._parseProperties(p);
|
||||
})
|
||||
.catch((_) => reject("HiPS " + self.id + " error: " + id + " does not refer to a found CDS ID nor a local path pointing towards a HiPS"))
|
||||
})
|
||||
} else {
|
||||
await HiPSProperties.fetchFromUrl(self.url)
|
||||
.then((p) => {
|
||||
self._parseProperties(p);
|
||||
})
|
||||
.catch((_) => reject("HiPS " + self.id + " error: HiPS not found at url " + self.url))
|
||||
}
|
||||
} else {
|
||||
self._parseProperties({
|
||||
hips_order: self.maxOrder,
|
||||
hips_service_url: self.url,
|
||||
hips_tile_width: self.tileSize,
|
||||
hips_frame: self.cooFrame.label
|
||||
})
|
||||
}
|
||||
|
||||
if (self.updateHiPSCache) {
|
||||
self._saveInCache();
|
||||
self.updateHiPSCache = false;
|
||||
}
|
||||
|
||||
resolve(self);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
HiPS.prototype._fetchFasterUrlFromProperties = function(properties) {
|
||||
@@ -287,7 +402,6 @@ export let HiPS = (function () {
|
||||
);
|
||||
|
||||
self.url = url;
|
||||
|
||||
// If added to the backend, then we need to tell it the url has changed
|
||||
if (self.added) {
|
||||
self.view.wasm.setHiPSUrl(
|
||||
@@ -322,8 +436,8 @@ export let HiPS = (function () {
|
||||
PropertyParser.tileSize(properties) || self.tileSize;
|
||||
|
||||
// Tile formats
|
||||
self.formats =
|
||||
PropertyParser.formats(properties) || self.formats;
|
||||
self.acceptedFormats =
|
||||
PropertyParser.acceptedFormats(properties) || self.acceptedFormats;
|
||||
|
||||
// Min order
|
||||
const minOrder = PropertyParser.minOrder(properties)
|
||||
@@ -354,8 +468,8 @@ export let HiPS = (function () {
|
||||
|
||||
// Cutouts
|
||||
const cutoutFromProperties = PropertyParser.cutouts(properties);
|
||||
self.defaultFitsMinCut = cutoutFromProperties[0];
|
||||
self.defaultFitsMaxCut = cutoutFromProperties[1];
|
||||
self.defaultFitsMinCut = cutoutFromProperties[0] || 0.0;
|
||||
self.defaultFitsMaxCut = cutoutFromProperties[1] || 1.0;
|
||||
|
||||
// Bitpix
|
||||
self.numBitsPerPixel =
|
||||
@@ -364,9 +478,8 @@ export let HiPS = (function () {
|
||||
// HiPS body
|
||||
if (properties.hips_body) {
|
||||
self.hipsBody = properties.hips_body;
|
||||
// Use the property to define and check some user given infos
|
||||
// Longitude reversed
|
||||
self.longitudeReversed = true;
|
||||
// The HiPS is a planetary one, so we reverse the longitude axis globally
|
||||
self.view.aladin.reverseLongitude(true)
|
||||
}
|
||||
|
||||
// Give a better name if we have the HiPS metadata
|
||||
@@ -377,81 +490,40 @@ export let HiPS = (function () {
|
||||
|
||||
self.creatorDid = self.creatorDid || self.id || self.url;
|
||||
|
||||
// Image format
|
||||
if (self.imgFormat) {
|
||||
// transform to lower case
|
||||
self.imgFormat = self.imgFormat.toLowerCase();
|
||||
// convert JPG -> JPEG
|
||||
if (self.imgFormat === "jpg") {
|
||||
self.imgFormat = "jpeg";
|
||||
}
|
||||
|
||||
// user wants a fits but the properties tells this format is not available
|
||||
if (
|
||||
self.imgFormat === "fits" &&
|
||||
self.formats &&
|
||||
self.formats.indexOf("fits") < 0
|
||||
) {
|
||||
throw self.name + " does not provide fits tiles";
|
||||
}
|
||||
|
||||
if (
|
||||
self.imgFormat === "webp" &&
|
||||
self.formats &&
|
||||
self.formats.indexOf("webp") < 0
|
||||
) {
|
||||
throw self.name + " does not provide webp tiles";
|
||||
}
|
||||
|
||||
if (
|
||||
self.imgFormat === "png" &&
|
||||
self.formats &&
|
||||
self.formats.indexOf("png") < 0
|
||||
) {
|
||||
throw self.name + " does not provide png tiles";
|
||||
}
|
||||
|
||||
if (
|
||||
self.imgFormat === "jpeg" &&
|
||||
self.formats &&
|
||||
self.formats.indexOf("jpeg") < 0
|
||||
) {
|
||||
throw self.name + " does not provide jpeg tiles";
|
||||
}
|
||||
} else {
|
||||
// user wants nothing then we choose one from the properties
|
||||
if (self.formats.indexOf("webp") >= 0) {
|
||||
self.imgFormat = "webp";
|
||||
} else if (self.formats.indexOf("png") >= 0) {
|
||||
self.imgFormat = "png";
|
||||
} else if (self.formats.indexOf("jpeg") >= 0) {
|
||||
self.imgFormat = "jpeg";
|
||||
} else if (self.formats.indexOf("fits") >= 0) {
|
||||
self.imgFormat = "fits";
|
||||
// check the imgFormat with respect to the formats accepted image format
|
||||
const chooseTileFormat = (acceptedFormats) => {
|
||||
if (acceptedFormats.indexOf("webp") >= 0) {
|
||||
return "webp";
|
||||
} else if (acceptedFormats.indexOf("png") >= 0) {
|
||||
return "png";
|
||||
} else if (acceptedFormats.indexOf("jpeg") >= 0) {
|
||||
return "jpeg";
|
||||
} else if (acceptedFormats.indexOf("fits") >= 0) {
|
||||
return "fits";
|
||||
} else {
|
||||
throw (
|
||||
"Unsupported format(s) found in the properties: " +
|
||||
self.formats
|
||||
acceptedFormats
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Set an image format with respect to the ones available for that HiPS if:
|
||||
// * the format is unknown
|
||||
// * the format is known but is not available for that HiPS
|
||||
if (!self.imgFormat || !self.acceptedFormats.includes(self.imgFormat)) {
|
||||
// Switch automatically to a available format
|
||||
let imgFormat = chooseTileFormat(self.acceptedFormats);
|
||||
self.setImageFormat(imgFormat)
|
||||
|
||||
console.info(self.id + " tile format chosen: " + self.imgFormat)
|
||||
}
|
||||
|
||||
// Cutouts
|
||||
let minCut, maxCut;
|
||||
if (self.imgFormat === "fits") {
|
||||
// Take into account the default cuts given by the property file (this is true especially for FITS HiPSes)
|
||||
minCut = self.colorCfg.minCut || self.defaultFitsMinCut || 0.0;
|
||||
maxCut = self.colorCfg.maxCut || self.defaultFitsMaxCut || 1.0;
|
||||
} else {
|
||||
minCut = self.colorCfg.minCut || 0.0;
|
||||
maxCut = self.colorCfg.maxCut || 1.0;
|
||||
// Set a cuts for fits formats if no cuts has been yet given
|
||||
let [minCut, maxCut] = self.getCuts();
|
||||
if (self.imgFormat === "fits" && minCut === undefined && maxCut === undefined) {
|
||||
self.setCuts(self.defaultFitsMinCut, self.defaultFitsMaxCut);
|
||||
}
|
||||
|
||||
self.setOptions({minCut, maxCut});
|
||||
|
||||
self.formats = self.formats || [self.imgFormat];
|
||||
|
||||
self._saveInCache();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -474,99 +546,23 @@ export let HiPS = (function () {
|
||||
*
|
||||
* @memberof HiPS
|
||||
*
|
||||
* @param {string} format - The desired image format. Should be one of ["fits", "png", "jpg", "webp"].
|
||||
* @param {string} imgFormat - The desired image format. Should be one of ["fits", "png", "jpg", "webp"].
|
||||
*
|
||||
* @throws {string} Throws an error if the provided format is not one of the supported formats or if the format is not available for the specific HiPS.
|
||||
*/
|
||||
HiPS.prototype.setImageFormat = function (format) {
|
||||
let self = this;
|
||||
self.query.then(() => {
|
||||
let imgFormat = format.toLowerCase();
|
||||
|
||||
if (
|
||||
imgFormat !== "fits" &&
|
||||
imgFormat !== "png" &&
|
||||
imgFormat !== "jpg" &&
|
||||
imgFormat !== "jpeg" &&
|
||||
imgFormat !== "webp"
|
||||
) {
|
||||
throw 'Formats must lie in ["fits", "png", "jpg", "webp"]';
|
||||
}
|
||||
|
||||
if (imgFormat === "jpg") {
|
||||
imgFormat = "jpeg";
|
||||
}
|
||||
|
||||
// Passed the check, we erase the image format with the new one
|
||||
// We do nothing if the imgFormat is the same
|
||||
if (self.imgFormat === imgFormat) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the properties to see if the given format is available among the list
|
||||
// If the properties have not been retrieved yet, it will be tested afterwards
|
||||
const availableFormats = self.formats;
|
||||
// user wants a fits but the metadata tells this format is not available
|
||||
if (
|
||||
imgFormat === "fits" &&
|
||||
availableFormats.indexOf("fits") < 0
|
||||
) {
|
||||
throw self.id + " does not provide fits tiles";
|
||||
}
|
||||
|
||||
if (
|
||||
imgFormat === "webp" &&
|
||||
availableFormats.indexOf("webp") < 0
|
||||
) {
|
||||
throw self.id + " does not provide webp tiles";
|
||||
}
|
||||
|
||||
if (
|
||||
imgFormat === "png" &&
|
||||
availableFormats.indexOf("png") < 0
|
||||
) {
|
||||
throw self.id + " does not provide png tiles";
|
||||
}
|
||||
|
||||
if (
|
||||
imgFormat === "jpeg" &&
|
||||
availableFormats.indexOf("jpeg") < 0
|
||||
) {
|
||||
throw self.id + " does not provide jpeg tiles";
|
||||
}
|
||||
|
||||
// Switch from png/webp/jpeg to fits
|
||||
if (
|
||||
(self.imgFormat === "png" ||
|
||||
self.imgFormat === "webp" ||
|
||||
self.imgFormat === "jpeg") &&
|
||||
imgFormat === "fits"
|
||||
) {
|
||||
if (Number.isFinite(self.defaultFitsMinCut) && Number.isFinite(self.defaultFitsMaxCut)) {
|
||||
// reset cuts to those given from the properties
|
||||
self.setCuts(self.defaultFitsMinCut, self.defaultFitsMaxCut);
|
||||
}
|
||||
// Switch from fits to png/webp/jpeg
|
||||
} else if (self.imgFormat === "fits") {
|
||||
self.setCuts(0.0, 1.0);
|
||||
}
|
||||
|
||||
// Check if it is a fits
|
||||
self.imgFormat = imgFormat;
|
||||
|
||||
self._updateMetadata();
|
||||
});
|
||||
HiPS.prototype.setImageFormat = function (imgFormat) {
|
||||
this.setOptions({imgFormat});
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the opacity factor when rendering the HiPS
|
||||
* Get the list of accepted tile format for that HiPS
|
||||
*
|
||||
* @memberof HiPS
|
||||
*
|
||||
* @returns {string[]} Returns the formats accepted for the survey, i.e. the formats of tiles that are availables. Could be PNG, WEBP, JPG and FITS.
|
||||
*/
|
||||
HiPS.prototype.getAvailableFormats = function () {
|
||||
return this.formats;
|
||||
return this.acceptedFormats;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -634,6 +630,8 @@ export let HiPS = (function () {
|
||||
* @param {boolean} [options.reversed=false] - Reverse the colormap axis.
|
||||
*/
|
||||
HiPS.prototype.setColormap = function (colormap, options) {
|
||||
colormap = colormap || this.options.colormap;
|
||||
|
||||
this.setOptions({colormap, ...options})
|
||||
};
|
||||
|
||||
@@ -728,17 +726,16 @@ export let HiPS = (function () {
|
||||
if (this.added) {
|
||||
this.view.wasm.setImageMetadata(this.layer, {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: this.longitudeReversed,
|
||||
imgFormat: this.imgFormat,
|
||||
});
|
||||
// once the meta have been well parsed, we can set the meta
|
||||
ALEvent.HIPS_LAYER_CHANGED.dispatchedTo(this.view.aladinDiv, {
|
||||
layer: this,
|
||||
});
|
||||
|
||||
// Save it in the JS HiPS cache
|
||||
this._saveInCache();
|
||||
}
|
||||
|
||||
// Save it in the JS HiPS cache
|
||||
this._saveInCache();
|
||||
} catch (e) {
|
||||
// Display the error message
|
||||
console.error(e);
|
||||
@@ -746,11 +743,13 @@ export let HiPS = (function () {
|
||||
};
|
||||
|
||||
/**
|
||||
* Set color options generic method for changing colormap, opacity, ... of the HiPS
|
||||
* Set color options generic method for changing colormap, opacity, ... of the HiPS
|
||||
*
|
||||
* @memberof HiPS
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {number} [options.imgFormat] - Image format of the HiPS tiles. Possible values are "jpeg", "png", "webp" or "fits".
|
||||
* Some formats might not be handled depending on the survey simply because tiles of that format have not been generated.
|
||||
* @param {number} [options.opacity=1.0] - Opacity of the survey or image (value between 0 and 1).
|
||||
* @param {string} [options.colormap="native"] - The colormap configuration for the survey or image.
|
||||
* @param {string} [options.stretch="linear"] - The stretch configuration for the survey or image.
|
||||
@@ -766,12 +765,44 @@ export let HiPS = (function () {
|
||||
HiPS.prototype.setOptions = function(options) {
|
||||
this.colorCfg.setOptions(options);
|
||||
|
||||
// FIXME, change api of setColormap to take an option object having a name field
|
||||
if (options.colormap == null || options.colormap == undefined) {
|
||||
delete options.colormap;
|
||||
/// Set image format
|
||||
if (options.imgFormat) {
|
||||
let imgFormat = options.imgFormat.toLowerCase();
|
||||
|
||||
if (imgFormat === "jpg") {
|
||||
imgFormat = "jpeg";
|
||||
}
|
||||
|
||||
if (!["fits", "png", "jpeg", "webp"].includes(imgFormat)) {
|
||||
console.warn('Formats must lie in ["fits", "png", "jpg", "webp"]. imgFormat option property ignored');
|
||||
} else {
|
||||
// Passed the check, we erase the image format with the new one
|
||||
// We do nothing if the imgFormat is the same
|
||||
|
||||
// Check the properties to see if the given format is available among the list
|
||||
// If the properties have not been retrieved yet, it will be tested afterwards
|
||||
const availableFormats = this.acceptedFormats;
|
||||
// user wants a fits but the metadata tells this format is not available
|
||||
if (!availableFormats || (availableFormats && availableFormats.indexOf(imgFormat) >= 0)) {
|
||||
this.imgFormat = imgFormat;
|
||||
|
||||
let [minCut, maxCut] = this.getCuts();
|
||||
if (minCut === undefined && maxCut === undefined && imgFormat === "fits") {
|
||||
// sets the default cuts parsed from the properties
|
||||
this.setCuts(this.defaultFitsMinCut, this.defaultFitsMaxCut)
|
||||
}
|
||||
} else {
|
||||
console.warn(this.id + " does not provide " + imgFormat + " tiles")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.options = {...this.options, ...options};
|
||||
this.options = {
|
||||
...this.options,
|
||||
...options,
|
||||
minCut: this.colorCfg.minCut,
|
||||
maxCut: this.colorCfg.maxCut
|
||||
};
|
||||
|
||||
this._updateMetadata();
|
||||
};
|
||||
@@ -831,146 +862,16 @@ export let HiPS = (function () {
|
||||
};
|
||||
|
||||
HiPS.prototype._setView = function (view) {
|
||||
let self = this;
|
||||
|
||||
// do not allow to call setView multiple times otherwise
|
||||
// the querying to the properties and the search to the best
|
||||
// HiPS node will be done again for the same hiPS
|
||||
if (this.view) {
|
||||
return;
|
||||
}
|
||||
this.view = view;
|
||||
|
||||
if (this.localFiles) {
|
||||
// Fetch the properties file
|
||||
self.query = (async () => {
|
||||
// look for the properties file
|
||||
await HiPSProperties.fetchFromFile(self.localFiles["properties"])
|
||||
.then((p) => {
|
||||
self._parseProperties(p);
|
||||
|
||||
self.url = "local";
|
||||
|
||||
delete self.localFiles["properties"]
|
||||
})
|
||||
|
||||
return self;
|
||||
})();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let isIncompleteOptions = true;
|
||||
|
||||
let isID = Utils.isUrl(this.url) === undefined;
|
||||
|
||||
if (this.imgFormat === "fits") {
|
||||
// a fits is given
|
||||
isIncompleteOptions = !(
|
||||
this.maxOrder &&
|
||||
(!isID && this.url) &&
|
||||
this.imgFormat &&
|
||||
this.tileSize &&
|
||||
this.cooFrame &&
|
||||
this.numBitsPerPixel
|
||||
);
|
||||
} else {
|
||||
isIncompleteOptions = !(
|
||||
this.maxOrder &&
|
||||
(!isID && this.url) &&
|
||||
this.imgFormat &&
|
||||
this.tileSize &&
|
||||
this.cooFrame
|
||||
);
|
||||
}
|
||||
|
||||
self.query = (async () => {
|
||||
if (isIncompleteOptions) {
|
||||
// ID typed url
|
||||
if (self.startUrl && isID) {
|
||||
// First download the properties from the start url
|
||||
await HiPSProperties.fetchFromUrl(self.startUrl)
|
||||
.then((p) => {
|
||||
self._parseProperties(p);
|
||||
})
|
||||
|
||||
try {
|
||||
// the url stores a "CDS ID" we take it prioritaly
|
||||
// if the url is null, take the id, this is for some tests
|
||||
// to pass because some users might just give null as url param and a "CDS ID" as id param
|
||||
let id = self.url || self.id;
|
||||
|
||||
self.url = self.startUrl;
|
||||
|
||||
setTimeout(
|
||||
() => {
|
||||
if (!self.added)
|
||||
return;
|
||||
|
||||
HiPSProperties.fetchFromID(id)
|
||||
.then((p) => {
|
||||
self._fetchFasterUrlFromProperties(p);
|
||||
})
|
||||
.catch(() => {
|
||||
// If no ID has been found then it may actually be a path
|
||||
// url pointing to a local HiPS
|
||||
return HiPSProperties.fetchFromUrl(id)
|
||||
.then((p) => {
|
||||
self._parseProperties(p);
|
||||
})
|
||||
})
|
||||
},
|
||||
1000
|
||||
);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
} else if (!this.startUrl && isID) {
|
||||
try {
|
||||
// the url stores a "CDS ID" we take it prioritaly
|
||||
// if the url is null, take the id, this is for some tests
|
||||
// to pass because some users might just give null as url param and a "CDS ID" as id param
|
||||
let id = self.url || self.id;
|
||||
|
||||
await HiPSProperties.fetchFromID(id)
|
||||
.then((p) => {
|
||||
self.url = p.hips_service_url;
|
||||
|
||||
self._parseProperties(p);
|
||||
self._fetchFasterUrlFromProperties(p);
|
||||
})
|
||||
.catch(() => {
|
||||
// If no ID has been found then it may actually be a path
|
||||
// url pointing to a local HiPS
|
||||
return HiPSProperties.fetchFromUrl(id)
|
||||
.then((p) => {
|
||||
self._parseProperties(p);
|
||||
})
|
||||
})
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
await HiPSProperties.fetchFromUrl(self.url)
|
||||
.then((p) => {
|
||||
self._parseProperties(p);
|
||||
})
|
||||
}
|
||||
} else {
|
||||
self._parseProperties({
|
||||
hips_order: this.maxOrder,
|
||||
hips_service_url: this.url,
|
||||
hips_tile_width: this.tileSize,
|
||||
hips_frame: this.cooFrame.label
|
||||
})
|
||||
}
|
||||
|
||||
return self;
|
||||
})()
|
||||
};
|
||||
|
||||
/* Precondition: view is attached */
|
||||
HiPS.prototype._saveInCache = function () {
|
||||
if (!this.view) {
|
||||
this.updateHiPSCache = true;
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
let hipsCache = this.view.aladin.hipsCache;
|
||||
|
||||
@@ -979,7 +880,7 @@ export let HiPS = (function () {
|
||||
}
|
||||
};
|
||||
|
||||
HiPS.prototype._add = function (layer) {
|
||||
HiPS.prototype._add2View = function (layer) {
|
||||
this.layer = layer;
|
||||
let self = this;
|
||||
|
||||
@@ -991,7 +892,7 @@ export let HiPS = (function () {
|
||||
maxOrder: self.maxOrder,
|
||||
cooFrame: self.cooFrame.system,
|
||||
tileSize: self.tileSize,
|
||||
formats: self.formats,
|
||||
formats: self.acceptedFormats,
|
||||
bitpix: self.numBitsPerPixel,
|
||||
skyFraction: self.skyFraction,
|
||||
minOrder: self.minOrder,
|
||||
@@ -1004,7 +905,6 @@ export let HiPS = (function () {
|
||||
},
|
||||
meta: {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: this.longitudeReversed,
|
||||
imgFormat: this.imgFormat,
|
||||
}
|
||||
};
|
||||
@@ -1040,16 +940,13 @@ export let HiPS = (function () {
|
||||
localFiles
|
||||
);
|
||||
|
||||
return Promise.resolve(this)
|
||||
.then((hips) => {
|
||||
this.added = true;
|
||||
this.added = true;
|
||||
|
||||
if (hips.successCallback) {
|
||||
hips.successCallback(hips)
|
||||
}
|
||||
if (this.successCallback) {
|
||||
this.successCallback(this)
|
||||
}
|
||||
|
||||
return hips
|
||||
});
|
||||
return this
|
||||
};
|
||||
|
||||
HiPS.DEFAULT_SURVEY_ID = "P/DSS2/color";
|
||||
|
||||
@@ -136,13 +136,12 @@ export let Image = (function () {
|
||||
this.id = url;
|
||||
this.name = (options && options.name) || this.url;
|
||||
this.imgFormat = options && options.imgFormat;
|
||||
//this.formats = [this.imgFormat];
|
||||
this.acceptedFormats = [this.imgFormat];
|
||||
|
||||
// callbacks
|
||||
this.successCallback = options && options.successCallback;
|
||||
this.errorCallback = options && options.errorCallback;
|
||||
|
||||
this.longitudeReversed = false;
|
||||
|
||||
this.colorCfg = new ColorCfg(options);
|
||||
this.options = options || {};
|
||||
|
||||
@@ -329,11 +328,18 @@ export let Image = (function () {
|
||||
*/
|
||||
Image.prototype.readPixel = HiPS.prototype.readPixel;
|
||||
|
||||
|
||||
/** PRIVATE METHODS **/
|
||||
/**
|
||||
* Get the list of accepted tile format for that HiPS
|
||||
*
|
||||
* @memberof Image
|
||||
*
|
||||
* @returns {string[]} Returns the formats accepted for the survey, i.e. the formats of tiles that are availables. Could be PNG, WEBP, JPG and FITS.
|
||||
*/
|
||||
Image.prototype.getAvailableFormats = HiPS.prototype.getAvailableFormats;
|
||||
|
||||
|
||||
Image.prototype._setView = function (view) {
|
||||
this.view = view;
|
||||
this._saveInCache();
|
||||
};
|
||||
|
||||
// FITS images does not mean to be used for storing planetary data
|
||||
@@ -356,7 +362,7 @@ export let Image = (function () {
|
||||
// Private method for updating the view with the new meta
|
||||
Image.prototype._updateMetadata = HiPS.prototype._updateMetadata;
|
||||
|
||||
Image.prototype._add = function (layer) {
|
||||
Image.prototype._add2View = function (layer) {
|
||||
this.layer = layer;
|
||||
|
||||
let self = this;
|
||||
@@ -388,11 +394,10 @@ export let Image = (function () {
|
||||
}
|
||||
|
||||
promise = promise.then((imageParams) => {
|
||||
self.formats = [self.imgFormat];
|
||||
self.acceptedFormats = [self.imgFormat];
|
||||
|
||||
// There is at least one entry in imageParams
|
||||
self.added = true;
|
||||
self._setView(self.view);
|
||||
|
||||
// Set the automatic computed cuts
|
||||
let [minCut, maxCut] = self.getCuts();
|
||||
@@ -442,7 +447,6 @@ export let Image = (function () {
|
||||
stream,
|
||||
{
|
||||
...self.colorCfg.get(),
|
||||
longitudeReversed: this.longitudeReversed,
|
||||
imgFormat: 'fits',
|
||||
},
|
||||
layer
|
||||
@@ -460,7 +464,6 @@ export let Image = (function () {
|
||||
stream,
|
||||
{
|
||||
...self.colorCfg.get(),
|
||||
longitudeReversed: this.longitudeReversed,
|
||||
imgFormat: 'fits',
|
||||
},
|
||||
layer
|
||||
@@ -470,7 +473,8 @@ export let Image = (function () {
|
||||
}
|
||||
})
|
||||
.then((imageParams) => {
|
||||
self.imgFormat = 'fits';
|
||||
self.imgFormat = 'fits'
|
||||
self.colorCfg.setOptions({imgFormat: 'fits'});
|
||||
|
||||
return Promise.resolve(imageParams);
|
||||
})
|
||||
@@ -562,14 +566,14 @@ export let Image = (function () {
|
||||
wcs,
|
||||
{
|
||||
...self.colorCfg.get(),
|
||||
longitudeReversed: this.longitudeReversed,
|
||||
imgFormat: 'jpeg',
|
||||
},
|
||||
layer
|
||||
)
|
||||
})
|
||||
.then((imageParams) => {
|
||||
self.imgFormat = 'jpeg';
|
||||
self.imgFormat = 'jpeg'
|
||||
self.colorCfg.setOptions({imgFormat: 'jpeg'});
|
||||
return Promise.resolve(imageParams);
|
||||
})
|
||||
.finally(() => {
|
||||
|
||||
@@ -717,9 +717,7 @@ export let View = (function () {
|
||||
// Take as start cut values what is inside the properties
|
||||
// If the cuts are not defined in the metadata of the survey
|
||||
// then we take what has been defined by the user
|
||||
cutMinInit = imageLayer.getColorCfg().minCut || 0.0;
|
||||
cutMaxInit = imageLayer.getColorCfg().maxCut || 1.0;
|
||||
|
||||
[cutMinInit, cutMaxInit] = imageLayer.getCuts();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1188,7 +1186,6 @@ export let View = (function () {
|
||||
view.throttledTouchPadZoom = () => {
|
||||
const factor = Utils.detectTrackPad(e) ? 1.04 : 1.2;
|
||||
const currZoomFactor = view.zoom.isZooming ? view.zoom.finalZoom : view.zoomFactor;
|
||||
//const currZoomFactor = view.wasm.getZoomFactor();
|
||||
let newZoomFactor = view.delta > 0 ? currZoomFactor * factor : currZoomFactor / factor;
|
||||
|
||||
// inside case
|
||||
@@ -1394,6 +1391,10 @@ export let View = (function () {
|
||||
}
|
||||
};
|
||||
|
||||
View.prototype.reverseLongitude = function(longitudeReversed) {
|
||||
this.wasm.setLongitudeReversed(longitudeReversed);
|
||||
}
|
||||
|
||||
View.prototype.refreshProgressiveCats = function () {
|
||||
if (!this.catalogs) {
|
||||
return;
|
||||
@@ -1607,6 +1608,7 @@ export let View = (function () {
|
||||
View.prototype.setOverlayImageLayer = function (imageLayer, layer = "overlay") {
|
||||
// set the view to the image layer object
|
||||
// do the properties query if needed
|
||||
imageLayer.layer = layer;
|
||||
imageLayer._setView(this);
|
||||
|
||||
// register its promise
|
||||
@@ -1617,7 +1619,9 @@ export let View = (function () {
|
||||
return imageLayer;
|
||||
};
|
||||
|
||||
// Insert a layer object (Image/HiPS) at a specific index in the stack
|
||||
View.prototype._addLayer = function(imageLayer) {
|
||||
// Keep the JS frontend in-line with the wasm state
|
||||
const layerName = imageLayer.layer;
|
||||
// Check whether this layer already exist
|
||||
const idxOverlayLayer = this.overlayLayers.findIndex(overlayLayer => overlayLayer == layerName);
|
||||
@@ -1628,12 +1632,16 @@ export let View = (function () {
|
||||
} else {
|
||||
// it exists
|
||||
alreadyPresentImageLayer = this.imageLayers.get(layerName);
|
||||
alreadyPresentImageLayer.added = false;
|
||||
// Notify that this image layer has been replaced by the wasm part
|
||||
if (alreadyPresentImageLayer && alreadyPresentImageLayer.added === true) {
|
||||
ALEvent.HIPS_LAYER_REMOVED.dispatchedTo(this.aladinDiv, { layer: alreadyPresentImageLayer });
|
||||
}
|
||||
|
||||
alreadyPresentImageLayer.added = false;
|
||||
this.imageLayers.delete(layerName);
|
||||
}
|
||||
|
||||
//imageLayer.added = true;
|
||||
imageLayer.added = true;
|
||||
|
||||
this.imageLayers.set(layerName, imageLayer);
|
||||
|
||||
@@ -1641,11 +1649,6 @@ export let View = (function () {
|
||||
if (idxOverlayLayer == -1) {
|
||||
this.selectLayer(layerName);
|
||||
}
|
||||
|
||||
// Notify that this image layer has been replaced by the wasm part
|
||||
if (alreadyPresentImageLayer) {
|
||||
ALEvent.HIPS_LAYER_REMOVED.dispatchedTo(this.aladinDiv, { layer: alreadyPresentImageLayer });
|
||||
}
|
||||
|
||||
ALEvent.HIPS_LAYER_ADDED.dispatchedTo(this.aladinDiv, { layer: imageLayer });
|
||||
}
|
||||
@@ -1655,6 +1658,7 @@ export let View = (function () {
|
||||
// start the query
|
||||
const imageLayerPromise = imageLayer.query;
|
||||
|
||||
let idx = this.promises.length;
|
||||
this.promises.push(imageLayerPromise);
|
||||
|
||||
// All image layer promises must be completed (fullfilled or rejected)
|
||||
@@ -1662,25 +1666,21 @@ export let View = (function () {
|
||||
message: 'Load layer: ' + imageLayer.name,
|
||||
id: Utils.uuidv4(),
|
||||
}
|
||||
Promise.allSettled(this.promises)
|
||||
.then(() => imageLayerPromise)
|
||||
// The promise is resolved and we now have access
|
||||
// to the image layer objet (whether it is an HiPS or an Image)
|
||||
// Ensure all the properties for HiPSes have been seeked
|
||||
ALEvent.FETCH.dispatchedTo(document, {task});
|
||||
// All the remaining promises must be terminated and the current one must be resolved
|
||||
// so that we can add it to the view (call of _add2View)
|
||||
Promise.all([Promise.allSettled(this.promises), imageLayerPromise])
|
||||
// Then we add the layer to the view
|
||||
.then((_) => imageLayer._add2View(layer))
|
||||
// Then we keep a track of the layer in the JS front
|
||||
.then((imageLayer) => {
|
||||
// Add to the backend
|
||||
imageLayer._setView(this)
|
||||
const promise = imageLayer._add(layer);
|
||||
ALEvent.FETCH.dispatchedTo(document, {task});
|
||||
this._addLayer(imageLayer);
|
||||
|
||||
return promise;
|
||||
})
|
||||
.then((imageLayer) => {
|
||||
// If the image layer has successfuly been added
|
||||
this.empty = false;
|
||||
|
||||
this._addLayer(imageLayer);
|
||||
|
||||
// change the view frame in case we have a planetary hips loaded
|
||||
// Change the view frame in case we have a planetary hips loaded
|
||||
if (imageLayer.hipsBody) {
|
||||
if (this.options.showFrame) {
|
||||
this.aladin.setFrame('J2000d');
|
||||
@@ -1704,7 +1704,6 @@ export let View = (function () {
|
||||
self.imageLayersBeingQueried.delete(layer);
|
||||
|
||||
// Remove the settled promise
|
||||
let idx = this.promises.findIndex(p => p == imageLayerPromise);
|
||||
this.promises.splice(idx, 1);
|
||||
|
||||
const noMoreLayersToWaitFor = this.promises.length === 0;
|
||||
|
||||
@@ -310,7 +310,8 @@ import { Form } from "../Widgets/Form.js";
|
||||
let fmtInput = this.pixelSettingsContent.getInput('fmt')
|
||||
|
||||
fmtInput.innerHTML = '';
|
||||
for (const option of layer.formats) {
|
||||
|
||||
for (const option of layer.getAvailableFormats()) {
|
||||
fmtInput.innerHTML += "<option>" + option + "</option>";
|
||||
}
|
||||
fmtInput.value = layer.imgFormat;
|
||||
|
||||
@@ -85,7 +85,7 @@ export class OverlayStackBox extends Box {
|
||||
hoverColor: 'red',
|
||||
onClick: "showTable",
|
||||
shape: (s) => {
|
||||
let galaxy = ["Seyfert","Seyfert_1", "Seyfert_2","LSB_G","PartofG","RadioG","Gin","GinPair","HII_G","LensedG","BClG","BlueCompG","EmG","GinCl","GinGroup","StarburstG","LINER","AGN","Galaxy"].some((n) => s.data.main_type.indexOf(n) >= 0);
|
||||
let galaxy = ["Seyfert","Seyfert_1", "Seyfert_2","LSB_G","PartofG","RadioG","Gin","GinPair","HII_G","LensedG","BClG","BlueCompG","EmG","GinCl","GinGroup","StarburstG","LINER","AGN", "Galaxy", "GtowardsGroup", "GtowardsCl", "BrightestCG"].some((n) => s.data.main_type.indexOf(n) >= 0);
|
||||
if (!galaxy) return;
|
||||
|
||||
let a = +s.data.size_maj;
|
||||
@@ -710,6 +710,7 @@ export class OverlayStackBox extends Box {
|
||||
// Add a listener for HiPS list changes
|
||||
ALEvent.FAVORITE_HIPS_LIST_UPDATED.listenedBy(document.body, (event) => {
|
||||
let favoritesHips = event.detail;
|
||||
|
||||
self.cachedHiPS = {};
|
||||
|
||||
for (var hips of favoritesHips) {
|
||||
|
||||
Reference in New Issue
Block a user