diff --git a/examples/al-displayJPG.html b/examples/al-displayJPG.html
index db635cec..08bf2b24 100644
--- a/examples/al-displayJPG.html
+++ b/examples/al-displayJPG.html
@@ -39,7 +39,9 @@ Image Opacity: "TAN" (Gnomonic projection)
+ * "STG" (Stereographic projection)
+ * "SIN" (Orthographic projection)
+ * "ZEA" (Zenital equal-area projection)
+ * "FEYE" (Fish eye projection)
+ * "AIR" (Airy projection)
+ * "ARC" (Zenital equidistant projection)
+ * "NCP" (North celestial pole projection)
+ * "MER" (Mercator projection)
+ * "CAR" (Plate Carrée projection)
+ * "CEA" (Cylindrical equal area projection)
+ * "CYP" (Cylindrical perspective projection)
+ * "AIT" (Hammer-Aitoff projection)
+ * "PAR" (Parabolic projection)
+ * "SFL" (Sanson-Flamsteed projection)
+ * "MOL" (Mollweide projection)
+ * "COD" (Conic equidistant projection)
+ * "HPX" (Healpix projection)
+ *
+ * @example
+ * // Set the projection to 'orthographic'
+ * let aladin = A.aladin('#aladin-lite-div');
+ * aladin.setProjection('SIN');
+ */
Aladin.prototype.setProjection = function (projection) {
if (!projection) {
return;
@@ -700,22 +748,43 @@ export let Aladin = (function () {
return projName;
};``
- /** return the current coordinate system: possible values are 'J2000', 'J2000d', and 'Galactic'
- * @api
+ /**
+ * Returns the current coordinate system: possible values are 'J2000', 'J2000d', and 'Galactic' .
*
+ * @memberof Aladin
+ * @returns {string} The current coordinate system: possible values are 'J2000', 'J2000d', and 'Galactic' .
+ *
+ * @example
+ * const aladin = A.aladin('#aladin-lite-div', {cooFrame: 'galactic'});
+ * let cooFrame = aladin.getFrame();
+ * assert(cooFrame, 'galactic')
*/
Aladin.prototype.getFrame = function() {
return this.view.cooFrame.label;
}
- /** point view to a given object (resolved by Sesame) or position
- * @api
+ /**
+ * Moves the Aladin instance to the specified astronomical object.
*
- * @param: target; object name or position
- * @callbackOptions: (optional) the object with key 'success' and/or 'error' containing the success and error callback functions.
+ * @memberof Aladin
+ * @param {string} targetName - The name or identifier of the astronomical object to move to.
+ * @param {Object} [callbackOptions] - Optional callback options.
+ * @param {function} [callbackOptions.success] - The callback function to execute on successful navigation.
+ * @param {function} [callbackOptions.error] - The callback function to execute on error during navigation.
*
+ * @example
+ * // Move to the astronomical object named 'M42' with callbacks
+ * const aladinInstance = A.aladin('#aladin-lite-div');
+ * aladinInstance.gotoObject('M42', {
+ * success: () => {
+ * console.log('Successfully moved to M42.');
+ * },
+ * error: (err) => {
+ * console.error('Error moving to M42:', err);
+ * }
+ * });
*/
- Aladin.prototype.gotoObject = function (targetName, callbackOptions, options) {
+ Aladin.prototype.gotoObject = function (targetName, callbackOptions) {
let successCallback = undefined;
let errorCallback = undefined;
if (typeof callbackOptions === 'object') {
@@ -740,7 +809,7 @@ export let Aladin = (function () {
coo.parse(targetName);
// Convert from view coo sys to icrs
const [ra, dec] = this.wasm.viewToICRSCooSys(coo.lon, coo.lat);
- this.view.pointTo(ra, dec, options);
+ this.view.pointTo(ra, dec);
(typeof successCallback === 'function') && successCallback(this.getRaDec());
}
@@ -758,7 +827,7 @@ export let Aladin = (function () {
function (data) { // success callback
// Location given in icrs at J2000
const coo = data.coo;
- self.view.pointTo(coo.jradeg, coo.jdedeg, options);
+ self.view.pointTo(coo.jradeg, coo.jdedeg);
(typeof successCallback === 'function') && successCallback(self.getRaDec());
},
@@ -776,7 +845,7 @@ export let Aladin = (function () {
const body = baseImageLayer.properties.hipsBody;
PlanetaryFeaturesNameResolver.resolve(targetName, body,
function (data) { // success callback
- self.view.pointTo(data.lon, data.lat, options);
+ self.view.pointTo(data.lon, data.lat);
(typeof successCallback === 'function') && successCallback(self.getRaDec());
},
@@ -793,27 +862,43 @@ export let Aladin = (function () {
}
};
-
-
- /**
- * go to a given position, expressed in the current coordinate frame
+ /**
+ * Moves the Aladin instance to the specified position.
*
- * @API
+ * @memberof Aladin
+ * @param {number} lon - longitude in degrees
+ * @param {number} lat - latitude in degrees
+ * @param {string} frame - Optional callback options.
+ *
+ * @example
+ * // Move to position
+ * const aladin = A.aladin('#aladin-lite-div');
+ * aladin.gotoPosition(20, 10, "galactic");
*/
- Aladin.prototype.gotoPosition = function (lon, lat) {
+ Aladin.prototype.gotoPosition = function (lon, lat, frame = undefined) {
var radec;
- // first, convert to J2000 if needed
- if (this.view.cooFrame == CooFrameEnum.GAL) {
- radec = CooConversion.GalacticToJ2000([lon, lat]);
+ // convert the frame from string to CooFrameEnum
+ if (frame) {
+ frame = CooFrameEnum.fromString(this.options.cooFrame, CooFrameEnum.J2000);
}
- else {
+ // both are CooFrameEnum
+ let positionGivenFrame = frame || this.view.cooFrame;
+ // First, convert to J2000 if needed
+ if (positionGivenFrame === CooFrameEnum.GAL) {
+ radec = CooConversion.GalacticToJ2000([lon, lat]);
+ } else {
radec = [lon, lat];
}
+
this.view.pointTo(radec[0], radec[1]);
};
-
+ var idTimeoutAnim;
var doAnimation = function (aladin) {
+ if (idTimeoutAnim) {
+ clearTimeout(idTimeoutAnim)
+ }
+
var params = aladin.animationParams;
if (params == null || !params['running']) {
return;
@@ -840,8 +925,7 @@ export let Aladin = (function () {
aladin.gotoRaDec(curRa, curDec);
- setTimeout(function () { doAnimation(aladin); }, 10);
-
+ idTimeoutAnim = setTimeout(function () { doAnimation(aladin); }, 10);
};
/*
@@ -985,9 +1069,14 @@ export let Aladin = (function () {
/**
- * get current [ra, dec] position of the center of the view
+ * Gets the current [Right Ascension, Declination] position of the center of the Aladin view.
*
- * @API
+ * This method returns the celestial coordinates of the center of the Aladin view in the International
+ * Celestial Reference System (ICRS) or J2000 equatorial coordinates.
+ *
+ * @memberof Aladin
+ * @returns {number[]} - An array representing the [Right Ascension, Declination] coordinates in degrees.
+ * The first element is the Right Ascension (RA), and the second element is the Declination (Dec).
*/
Aladin.prototype.getRaDec = function () {
let radec = this.wasm.getCenter(); // This is given in the frame of the view
@@ -1032,11 +1121,7 @@ export let Aladin = (function () {
return this.reticle;
};
- Aladin.prototype.removeLayers = function () {
- this.view.removeLayers();
- };
-
- // these 3 methods should be merged into a unique "add" method
+ // these 4 methods should be merged into a unique "add" method
Aladin.prototype.addCatalog = function (catalog) {
this.view.addCatalog(catalog);
@@ -1068,6 +1153,10 @@ export let Aladin = (function () {
return result[0];
}
+ Aladin.prototype.removeLayers = function () {
+ this.view.removeLayers();
+ };
+
// @API
Aladin.prototype.removeLayer = function(layer) {
this.view.removeLayer(layer);
@@ -1330,6 +1419,7 @@ export let Aladin = (function () {
Aladin.prototype.selectObjects = function(objects) {
this.view.selectObjects(objects)
};
+
// Possible values are 'rect', 'poly' and 'circle'
Aladin.prototype.select = async function (mode = 'rect', callback) {
await this.reticle.loaded;
@@ -1368,10 +1458,25 @@ export let Aladin = (function () {
};
/**
- * Change the coo grid options
- * @param {Object} options options of the coordinate grid
- * @param {Boolean} options.enable enable or disable the grid
- * @param {String} options.color color of the form 'rgba(255, 0, 255, 255)'
+ * Sets the coordinate grid options for the Aladin Lite view.
+ *
+ * This method allows you to customize the appearance of the coordinate grid in the Aladin Lite view.
+ *
+ * @memberof Aladin
+ *
+ * @param {Object} options - Options to customize the coordinate grid.
+ * @param {string} [options.color] - The color of the coordinate grid.
+ * @param {number} [options.opacity] - The opacity of the coordinate grid (value between 0 and 1).
+ * @param {number} [options.labelSize] - The size of the coordinate grid labels in pixels.
+ * @param {number} [options.thickness] - The thickness of the coordinate grid lines.
+ * @param {boolean} [options.enabled] - If true, the coordinate grid is enabled; otherwise, it is disabled.
+ *
+ * @example
+ * // Set the coordinate grid color to red
+ * aladin.setCooGrid({ color: 'red' });
+ *
+ * // Enable the coordinate grid
+ * aladin.setCooGrid({ enabled: true });
*/
Aladin.prototype.setCooGrid = function(options) {
if (options.color) {
@@ -1408,8 +1513,6 @@ export let Aladin = (function () {
return null;
};
-
-
// TODO : integrate somehow into API ?
Aladin.prototype.exportAsPNG = function (downloadFile = false) {
(async () => {
@@ -1560,96 +1663,77 @@ export let Aladin = (function () {
};
/**
- * Transform pixel coordinates to world coordinates
+ * Transform pixel coordinates to world coordinates.
*
- * Origin (0,0) of pixel coordinates is at top left corner of Aladin Lite view
+ * The origin (0,0) of pixel coordinates is at the top-left corner of the Aladin Lite view.
*
- * @API
+ * @memberof Aladin
*
- * @param x
- * @param y
- *
- * @return a [ra, dec] array with world coordinates in degrees. Returns undefined is something went wrong
+ * @param {number} x - The x-coordinate in pixel coordinates.
+ * @param {number} y - The y-coordinate in pixel coordinates.
*
+ * @returns {number[]} - An array representing the [Right Ascension, Declination] coordinates in degrees.
+ *
+ * @throws {Error} Throws an error if an issue occurs during the transformation.
*/
Aladin.prototype.pix2world = function (x, y) {
- // this might happen at early stage of initialization
- if (!this.view) {
- return undefined;
+ const [ra, dec] = this.wasm.screenToWorld(x, y);
+
+ if (ra < 0) {
+ return [ra + 360.0, dec];
}
- try {
- const [ra, dec] = this.wasm.screenToWorld(x, y);
-
- if (ra < 0) {
- return [ra + 360.0, dec];
- }
-
- return [ra, dec];
- } catch (e) {
- return undefined;
- }
+ return [ra, dec];
};
/**
- * Transform world coordinates to pixel coordinates in the view
+ * Transform world coordinates to pixel coordinates in the view.
*
- * @API
+ * @memberof Aladin
*
- * @param ra
- * @param dec
+ * @param {number} ra - The Right Ascension (RA) coordinate in degrees.
+ * @param {number} dec - The Declination (Dec) coordinate in degrees.
*
- * @return a [x, y] array with pixel coordinates in the view. Returns null if the projection failed somehow
+ * @returns {number[]} - An array representing the [x, y] coordinates in pixel coordinates in the view.
*
+ * @throws {Error} Throws an error if an issue occurs during the transformation.
*/
Aladin.prototype.world2pix = function (ra, dec) {
- // this might happen at early stage of initialization
- if (!this.view) {
- return;
- }
-
- try {
- return this.wasm.worldToScreen(ra, dec);
- } catch (e) {
- return undefined;
- }
+ return this.wasm.worldToScreen(ra, dec);
};
- /**
- * Transform world coordinates to pixel coordinates in the view
+ /**
+ * Get the angular distance in degrees between two locations
*
- * @API
+ * @memberof Aladin
*
- * @param ra
- * @param dec
+ * @param {number} x1 - The x-coordinate of the first pixel coordinates.
+ * @param {number} y1 - The y-coordinate of the first pixel coordinates.
+ * @param {number} x2 - The x-coordinate of the second pixel coordinates.
+ * @param {number} y2 - The y-coordinate of the second pixel coordinates.
*
- * @return a [x, y] array with pixel coordinates in the view. Returns null if the projection failed somehow
+ * @returns {number} - The angular distance between the two pixel coordinates in degrees
*
+ * @throws {Error} Throws an error if an issue occurs during the transformation.
*/
- Aladin.prototype.angularDist = function (x1, y1, x2, y2) {
- // this might happen at early stage of initialization
- if (!this.view) {
- return;
- }
+ Aladin.prototype.angularDist = function (x1, y1, x2, y2) {
+ const [ra1, dec1] = this.pix2world(x1, y1);
+ const [ra2, dec2] = this.pix2world(x2, y2);
- try {
- const [ra1, dec1] = this.pix2world(x1, y1);
- const [ra2, dec2] = this.pix2world(x2, y2);
-
- return this.wasm.angularDist(ra1, dec1, ra2, dec2);
- } catch (e) {
- return undefined;
- }
+ return this.wasm.angularDist(ra1, dec1, ra2, dec2);
};
/**
+ * Gets a set of points along the current Field of View (FoV) corners.
*
- * @API
+ * @memberof Aladin
*
- * @param ra
- * @param nbSteps the number of points to return along each side (the total number of points returned is 4*nbSteps)
+ * @param {number} nbSteps - The number of points to return along each side (the total number of points returned is 4 * nbSteps).
*
- * @return set of points along the current FoV with the following format: [[ra1, dec1], [ra2, dec2], ..., [ra_n, dec_n]]
+ * @returns {number[][]} - A set of positions along the current FoV with the following format: [[ra1, dec1], [ra2, dec2], ..., [ra_n, dec_n]].
+ * The positions will be given in degrees
+ *
+ * @throws {Error} Throws an error if an issue occurs during the transformation.
*
*/
Aladin.prototype.getFovCorners = function (nbSteps) {
@@ -1677,9 +1761,12 @@ export let Aladin = (function () {
};
/**
- * @API
+ * Gets the current Field of View (FoV) size in degrees as a 2-element array.
*
- * @return the current FoV size in degrees as a 2-elements array
+ * @memberof Aladin
+ *
+ * @returns {number[]} - A 2-element array representing the current FoV size in degrees. The first element is the FoV width,
+ * and the second element is the FoV height.
*/
Aladin.prototype.getFov = function () {
// can go up to 1000 deg
@@ -1697,9 +1784,12 @@ export let Aladin = (function () {
};
/**
- * @API
+ * Returns the size in pixels for the Aladin view
*
- * @return the size in pixels of the Aladin Lite view
+ * @memberof Aladin
+ *
+ * @returns {number[]} - A 2-element array representing the current Aladin view size in pixels. The first element is the width,
+ * and the second element is the height.
*/
Aladin.prototype.getSize = function () {
return [this.view.width, this.view.height];
@@ -1714,194 +1804,244 @@ export let Aladin = (function () {
return this.aladinDiv;
};
- return Aladin;
-})();
+ // @API
+ /*
+ * return a Box GUI element to insert content
+ */
+ /*Aladin.prototype.box = function (options) {
+ var box = new Box(options);
+ box.$parentDiv.appendTo(this.aladinDiv);
-// @API
-/*
- * return a Box GUI element to insert content
- */
-/*Aladin.prototype.box = function (options) {
- var box = new Box(options);
- box.$parentDiv.appendTo(this.aladinDiv);
+ return box;
+ };*/
- return box;
-};*/
+ // @API
+ /*
+ * show popup at ra, dec position with given title and content
+ *
+ * If circleRadius, the corresponding circle will also be plotted
+ */
+ Aladin.prototype.showPopup = function (ra, dec, title, content, circleRadius) {
+ this.view.catalogForPopup.removeAll();
+ this.view.overlayForPopup.removeAll();
-// @API
-/*
- * show popup at ra, dec position with given title and content
- *
- * If circleRadius, the corresponding circle will also be plotted
- */
-Aladin.prototype.showPopup = function (ra, dec, title, content, circleRadius) {
- this.view.catalogForPopup.removeAll();
- this.view.overlayForPopup.removeAll();
-
- let marker;
- if (circleRadius !== undefined) {
- this.view.overlayForPopup.add(A.circle(ra, dec, circleRadius, {fillColor: 'rgba(255, 0, 0, 0.2)'}));
- marker = A.marker(ra, dec, { popupTitle: title, popupDesc: content, useMarkerDefaultIcon: true });
- }
- else {
- marker = A.marker(ra, dec, { popupTitle: title, popupDesc: content, useMarkerDefaultIcon: false });
- }
-
- this.view.catalogForPopup.addSources(marker);
-
- this.view.overlayForPopup.show();
- this.view.catalogForPopup.show();
-
- this.view.popup.setTitle(title);
- this.view.popup.setText(content);
-
- this.view.popup.setSource(marker);
- this.view.popup.show();
-};
-
-// @API
-/*
- * hide popup
- */
-Aladin.prototype.hidePopup = function () {
- this.view.popup.hide();
-};
-
-// @API
-/*
- * return a URL allowing to share the current view
- */
-Aladin.prototype.getShareURL = function () {
- var radec = this.getRaDec();
- var coo = new Coo();
- coo.prec = 7;
- coo.lon = radec[0];
- coo.lat = radec[1];
-
- return Aladin.URL_PREVIEWER + '?target=' + encodeURIComponent(coo.format('s')) +
- '&fov=' + this.getFov()[0].toFixed(2) + '&survey=' + encodeURIComponent(this.getBaseImageLayer().id || this.getBaseImageLayer().rootUrl);
-};
-
-// @API
-/*
- * return, as a string, the HTML embed code
- */
-Aladin.prototype.getEmbedCode = function () {
- var radec = this.getRaDec();
- var coo = new Coo();
- coo.prec = 7;
- coo.lon = radec[0];
- coo.lat = radec[1];
-
- var survey = this.getBaseImageLayer().id;
- var fov = this.getFov()[0];
- let s = '';
- const NL = "\n";
- s += '
' + NL;
- s += '' + NL;
- s += '';
-
- return s;
-};
-
-// @API
-/*
- * Creates remotely a HiPS from a FITS image URL and displays it
- */
-Aladin.prototype.displayFITS = function (
- url,
- options,
- successCallback,
- errorCallback,
- layer = "base"
-) {
- successCallback = successCallback || ((ra, dec, fov, _) => {
- this.gotoRaDec(ra, dec);
- this.setFoV(fov);
- });
- const imageFits = this.createImageFITS(url, url, options, successCallback, errorCallback);
- return this.setOverlayImageLayer(imageFits, layer);
-};
-
-// @API
-/*
- * Creates remotely a HiPS from a JPEG or PNG image with astrometry info
- * and display it
- */
-Aladin.prototype.displayJPG = Aladin.prototype.displayPNG = function (url, options, successCallback, errorCallback) {
- options = options || {};
- options.color = true;
- options.label = "JPG/PNG image";
- options.outputFormat = 'png';
-
- options = options || {};
-
- var data = { url: url };
- if (options.color) {
- data.color = true;
- }
- if (options.outputFormat) {
- data.format = options.outputFormat;
- }
- if (options.order) {
- data.order = options.order;
- }
- if (options.nocache) {
- data.nocache = options.nocache;
- }
- let self = this;
-
- const request = ( url, params = {}, method = 'GET' ) => {
- let options = {
- method
- };
- if ( 'GET' === method ) {
- url += '?' + ( new URLSearchParams( params ) ).toString();
- } else {
- options.body = JSON.stringify( params );
+ let marker;
+ if (circleRadius !== undefined) {
+ this.view.overlayForPopup.add(A.circle(ra, dec, circleRadius, {fillColor: 'rgba(255, 0, 0, 0.2)'}));
+ marker = A.marker(ra, dec, { popupTitle: title, popupDesc: content, useMarkerDefaultIcon: true });
+ }
+ else {
+ marker = A.marker(ra, dec, { popupTitle: title, popupDesc: content, useMarkerDefaultIcon: false });
}
- return fetch( url, options ).then( response => response.json() );
+ this.view.catalogForPopup.addSources(marker);
+
+ this.view.overlayForPopup.show();
+ this.view.catalogForPopup.show();
+
+ this.view.popup.setTitle(title);
+ this.view.popup.setText(content);
+
+ this.view.popup.setSource(marker);
+ this.view.popup.show();
};
- const get = ( url, params ) => request( url, params, 'GET' );
- get('https://alasky.unistra.fr/cgi/fits2HiPS', data)
- .then(async (response) => {
- if (response.status != 'success') {
- console.error('An error occured: ' + response.message);
- if (errorCallback) {
- errorCallback(response.message);
- }
- return;
- }
- var label = options.label || "FITS image";
- var meta = response.data.meta;
+ // @API
+ /*
+ * hide popup
+ */
+ Aladin.prototype.hidePopup = function () {
+ this.view.popup.hide();
+ };
- const survey = self.createImageSurvey(response.data.url, label, response.data.url);
- self.setOverlayImageLayer(survey, "overlay");
+ // @API
+ /*
+ * return a URL allowing to share the current view
+ */
+ Aladin.prototype.getShareURL = function () {
+ var radec = this.getRaDec();
+ var coo = new Coo();
+ coo.prec = 7;
+ coo.lon = radec[0];
+ coo.lat = radec[1];
- var transparency = (options && options.transparency) || 1.0;
+ return Aladin.URL_PREVIEWER + '?target=' + encodeURIComponent(coo.format('s')) +
+ '&fov=' + this.getFov()[0].toFixed(2) + '&survey=' + encodeURIComponent(this.getBaseImageLayer().id || this.getBaseImageLayer().rootUrl);
+ };
- var executeDefaultSuccessAction = true;
- if (successCallback) {
- executeDefaultSuccessAction = successCallback(meta.ra, meta.dec, meta.fov);
- }
- if (executeDefaultSuccessAction === true) {
- self.wasm.setCenter(meta.ra, meta.dec);
- self.setFoV(meta.fov);
- }
+ // @API
+ /*
+ * return, as a string, the HTML embed code
+ */
+ Aladin.prototype.getEmbedCode = function () {
+ var radec = this.getRaDec();
+ var coo = new Coo();
+ coo.prec = 7;
+ coo.lon = radec[0];
+ coo.lat = radec[1];
- // TODO! set an image survey once the already loaded surveys
- // are READY! Otherwise it can lead to some congestion and avoid
- // downloading the base tiles of the other surveys loading!
- // This has to be fixed in the backend but a fast fix is just to wait
- // before setting a new image survey
+ var survey = this.getBaseImageLayer().url;
+ var fov = this.getFov()[0];
+ let s = '';
+ const NL = "\n";
+ s += '' + NL;
+ s += '' + NL;
+ s += '';
+
+ return s;
+ };
+
+/**
+ * Display a JPEG image in the Aladin Lite view.
+ *
+ * @memberof Aladin
+ *
+ * @param {string} url - The URL of the JPEG image.
+ * @param {Object} options - Options to customize the display. Can include the following properties:
+ * @param {string} options.label - A label for the displayed image.
+ * @param {number} options.order - The desired HEALPix order format.
+ * @param {boolean} options.nocache - True if you want to disable the cache
+ * @param {number} options.transparency - Opacity of the image rendered in aladin lite. Between 0 and 1.
+ * @param {Function} successCallback - The callback function to be executed on a successful display.
+ * The callback gives the ra, dec, and fov of the image;
+ * @param {Function} errorCallback - The callback function to be executed if an error occurs during display.
+ *
+ * @example
+ * aladin.displayJPG(
+ * // the JPG to transform to HiPS
+ * 'https://noirlab.edu/public/media/archives/images/large/noirlab1912a.jpg',
+ * {
+ * transparency: 0.6,
+ * label: 'NOIRLab image'
+ * },
+ * (ra, dec, fov) => {
+ * // your code here
+ * })
+ *);
+ */
+ Aladin.prototype.displayFITS = function (
+ url,
+ options,
+ successCallback,
+ errorCallback,
+ layer = "base"
+ ) {
+ successCallback = successCallback || ((ra, dec, fov, _) => {
+ this.gotoRaDec(ra, dec);
+ this.setFoV(fov);
});
-};
+ const imageFits = this.createImageFITS(url, url, options, successCallback, errorCallback);
+ return this.setOverlayImageLayer(imageFits, layer);
+ };
-Aladin.prototype.setReduceDeformations = function (reduce) {
- this.reduceDeformations = reduce;
- this.view.requestRedraw();
-}
+/**
+ * Display a JPEG image in the Aladin Lite view.
+ *
+ * @memberof Aladin
+ *
+ * @param {string} url - The URL of the JPEG image.
+ * @param {Object} options - Options to customize the display. Can include the following properties:
+ * @param {string} options.label - A label for the displayed image.
+ * @param {number} options.order - The desired HEALPix order format.
+ * @param {boolean} options.nocache - True if you want to disable the cache
+ * @param {number} options.transparency - Opacity of the image rendered in aladin lite. Between 0 and 1.
+ * @param {Function} successCallback - The callback function to be executed on a successful display.
+ * The callback gives the ra, dec, and fov of the image;
+ * @param {Function} errorCallback - The callback function to be executed if an error occurs during display.
+ *
+ * @example
+ * aladin.displayJPG(
+ * // the JPG to transform to HiPS
+ * 'https://noirlab.edu/public/media/archives/images/large/noirlab1912a.jpg',
+ * {
+ * transparency: 0.6,
+ * label: 'NOIRLab image'
+ * },
+ * (ra, dec, fov) => {
+ * // your code here
+ * })
+ *);
+ */
+ Aladin.prototype.displayJPG = Aladin.prototype.displayPNG = function (url, options, successCallback, errorCallback) {
+ options = options || {};
+ options.color = true;
+ options.label = options.label || "JPG/PNG image";
+ options.outputFormat = 'png';
+
+ options = options || {};
+
+ var data = { url };
+ if (options.color) {
+ data.color = true;
+ }
+ if (options.outputFormat) {
+ data.format = options.outputFormat;
+ }
+ if (options.order) {
+ data.order = options.order;
+ }
+ if (options.nocache) {
+ data.nocache = options.nocache;
+ }
+ let self = this;
+
+ const request = ( url, params = {}, method = 'GET' ) => {
+ let options = {
+ method
+ };
+ if ( 'GET' === method ) {
+ url += '?' + ( new URLSearchParams( params ) ).toString();
+ } else {
+ options.body = JSON.stringify( params );
+ }
+
+ return fetch( url, options ).then( response => response.json() );
+ };
+ const get = ( url, params ) => request( url, params, 'GET' );
+
+ get('https://alasky.unistra.fr/cgi/fits2HiPS', data)
+ .then(async (response) => {
+ if (response.status != 'success') {
+ console.error('An error occured: ' + response.message);
+ if (errorCallback) {
+ errorCallback(response.message);
+ }
+ return;
+ }
+ var label = options.label;
+ var meta = response.data.meta;
+
+ const survey = self.createImageSurvey(response.data.url, label, response.data.url);
+ self.setOverlayImageLayer(survey, "overlay");
+
+ var transparency = (options && options.transparency) || 1.0;
+ survey.setOpacity(transparency);
+
+ var executeDefaultSuccessAction = true;
+ if (successCallback) {
+ executeDefaultSuccessAction = successCallback(meta.ra, meta.dec, meta.fov);
+ }
+ if (executeDefaultSuccessAction === true) {
+ self.wasm.setCenter(meta.ra, meta.dec);
+ self.setFoV(meta.fov);
+ }
+
+ // TODO! set an image survey once the already loaded surveys
+ // are READY! Otherwise it can lead to some congestion and avoid
+ // downloading the base tiles of the other surveys loading!
+ // This has to be fixed in the backend but a fast fix is just to wait
+ // before setting a new image survey
+ });
+ };
+
+ /*
+ Aladin.prototype.setReduceDeformations = function (reduce) {
+ this.reduceDeformations = reduce;
+ this.view.requestRedraw();
+ }
+ */
+
+ return Aladin;
+})();
diff --git a/src/js/AladinUtils.js b/src/js/AladinUtils.js
index ef062b0d..cea2ee20 100644
--- a/src/js/AladinUtils.js
+++ b/src/js/AladinUtils.js
@@ -28,9 +28,15 @@
*
*****************************************************************************/
-export let AladinUtils = (function() {
+export let AladinUtils = {
+
+
+ HEALPix: {
+ vertices: function() {
+
+ }
+ },
- return {
/**
* passage de xy projection à xy dans la vue écran
* @param x
@@ -40,6 +46,7 @@ export let AladinUtils = (function() {
* @param largestDim largest dimension of the view
* @returns position in the view
*/
+ /*
xyToView: function(x, y, width, height, largestDim, zoomFactor, round) {
if (round==undefined) {
// we round by default
@@ -54,7 +61,7 @@ export let AladinUtils = (function() {
else {
return {vx: largestDim/2*(1+zoomFactor*x)-(largestDim-width)/2, vy: largestDim/2*(1+zoomFactor*y)-(largestDim-height)/2};
}
- },
+ },*/
/**
* passage de xy dans la vue écran à xy projection
@@ -66,9 +73,9 @@ export let AladinUtils = (function() {
* @param zoomFactor
* @returns position in xy projection
*/
- viewToXy: function(vx, vy, width, height, largestDim, zoomFactor) {
+ /*viewToXy: function(vx, vy, width, height, largestDim, zoomFactor) {
return {x: ((2*vx+(largestDim-width))/largestDim-1)/zoomFactor, y: ((2*vy+(largestDim-height))/largestDim-1)/zoomFactor};
- },
+ },*/
/**
* convert a
@@ -274,5 +281,3 @@ export let AladinUtils = (function() {
}
};
-
-})();
\ No newline at end of file
diff --git a/src/js/Catalog.js b/src/js/Catalog.js
index 2c0adf52..020c5463 100644
--- a/src/js/Catalog.js
+++ b/src/js/Catalog.js
@@ -42,7 +42,7 @@ import A from "./A.js";
* Represents a catalog with configurable options for display and interaction.
*
* @namespace
- * @typedef {Object} Aladin
+ * @typedef {Object} Catalog
*/
export let Catalog = (function() {
/**
diff --git a/src/js/ColorCfg.js b/src/js/ColorCfg.js
index a7cc25ab..964ff554 100644
--- a/src/js/ColorCfg.js
+++ b/src/js/ColorCfg.js
@@ -183,7 +183,7 @@
// @api
// Optional arguments,
- ColorCfg.prototype.setColormap = function(colormap = "native", options = {}) {
+ ColorCfg.prototype.setColormap = function(colormap = "native", options) {
/// colormap
// Make it case insensitive
let cmap = formatColormap(colormap);
diff --git a/src/js/ImageFITS.js b/src/js/ImageFITS.js
index 7d18c264..140b06ee 100644
--- a/src/js/ImageFITS.js
+++ b/src/js/ImageFITS.js
@@ -70,10 +70,6 @@ export let ImageFITS = (function () {
this.query = Promise.resolve(self);
}
- ImageFITS.prototype.isReady = function() {
- return this.added;
- }
-
// @api
ImageFITS.prototype.setOpacity = function (opacity) {
let self = this;
@@ -250,15 +246,6 @@ export let ImageFITS = (function () {
return false;
}
- // @api
- ImageFITS.prototype.focusOn = function () {
- // ensure the fits have been parsed
- if (this.added) {
- this.view.aladin.gotoRaDec(this.ra, this.dec);
- this.view.aladin.setFoV(this.fov);
- }
- };
-
// @oldapi
ImageFITS.prototype.setAlpha = ImageFITS.prototype.setOpacity;
diff --git a/src/js/ImageSurvey.js b/src/js/ImageSurvey.js
index 7aa309cb..f9fa2218 100644
--- a/src/js/ImageSurvey.js
+++ b/src/js/ImageSurvey.js
@@ -29,7 +29,6 @@
*****************************************************************************/
import { Utils } from "./Utils";
import { ALEvent } from "./events/ALEvent.js";
-import { CooFrameEnum } from "./CooFrameEnum.js"
import { ColorCfg } from "./ColorCfg.js";
import { ImageLayer } from "./ImageLayer.js";
import { HiPSProperties } from "./HiPSProperties.js";
@@ -56,11 +55,8 @@ PropertyParser.frame = function(options, properties = {}) {
frame = "ICRS";
} else if (frame == "galactic") {
frame = "GAL";
- } else if (frame === undefined) {
- frame = "ICRS";
- console.warn('No cooframe given. Coordinate systems supported: "ICRS", "ICRSd", "j2000" or "galactic". ICRS is chosen by default');
} else {
- frame = "ICRSd";
+ frame = "ICRS";
console.warn('Invalid cooframe given: ' + cooFrame + '. Coordinate systems supported: "ICRS", "ICRSd", "j2000" or "galactic". ICRS is chosen by default');
}
@@ -128,14 +124,42 @@ PropertyParser.isPlanetaryBody = function(options, properties = {}) {
return properties.hips_body !== undefined;
}
+/**
+ * @typedef {Object} ImageSurveyOptions
+ *
+ * @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.
+ * @property {number} [maxOrder] - If not given, retrieved from the properties of the survey.
+ * @property {number} [minOrder] - If not given, retrieved from the properties of the survey.
+ * @property {boolean} [longitudeReversed=false] - Set it to True for planetary survey visualization
+ * @property {string} [imgFormat] - If not given, look into the properties to see the accepted format. The format is chosen from PNG > WEBP > JPEG > FITS (in this importance order).
+ * @property {string} [cooFrame] - If not given, look into the properties. If it is a planet, then ICRS is chosen, otherwise its hips_frame key is read. If no value is found in the properties, ICRS is chosen by default.
+ */
export let ImageSurvey = (function () {
- /** Constructor
- * cooFrame and maxOrder can be set to null
- * They will be determined by reading the properties file
+ /**
+ * The object describing an image survey
*
+ * @class
+ * @constructs ImageSurvey
+ *
+ * @param {string} [id] - Optional, a uniq id for the survey. See {@link https://aladin.cds.unistra.fr/hips/list|here} for the list of IDs.
+ * Keep in mind that it is better to directly provide an url as it will not request our mocserver first to get final survey tiles retrieval url.
+ * @param {string} [name] - The name of the survey to be displayed in the UI
+ * @param {string} url - The url where the survey is located. Check the hips list {@link https://aladin.cds.unistra.fr/hips/list|here} for the valid survey urls to display.
+ * @param {ImageSurveyOptions} [options] - The option for the survey
+ *
+ * @description Prefer provide an url better than an id. If both are given, the url will be requested first for the survey data.
*/
function ImageSurvey(id, name, url, view, options) {
- // A reference to the view
this.view = view;
this.wasm = view.wasm;
this.added = false;
@@ -179,7 +203,7 @@ export let ImageSurvey = (function () {
// Request all the properties to see which mirror is the fastest
HiPSProperties.getFasterMirrorUrl(properties)
.then((url) => {
- self.setUrl(url);
+ self._setUrl(url);
})
.catch(e => {
alert(e);
@@ -373,11 +397,7 @@ export let ImageSurvey = (function () {
})();
};
- ImageSurvey.prototype.isReady = function() {
- return this.added;
- }
-
- ImageSurvey.prototype.setUrl = function (url) {
+ ImageSurvey.prototype._setUrl = function (url) {
if (this.properties.url !== url) {
console.info("Change url of ", this.id, " from ", this.properties.url, " to ", url)
@@ -389,13 +409,30 @@ export let ImageSurvey = (function () {
this.properties.url = url;
}
}
-
+ /**
+ * Checks if the ImageSurvey represents a planetary body.
+ *
+ * This method returns a boolean indicating whether the ImageSurvey corresponds to a planetary body, e.g. the earth or a celestial body.
+ *
+ * @memberof ImageSurvey
+ *
+ * @returns {boolean} Returns true if the ImageSurvey represents a planetary body; otherwise, returns false.
+ */
ImageSurvey.prototype.isPlanetaryBody = function() {
return this.properties.isPlanetaryBody;
}
- // @api
- // TODO: include imgFormat inside the ImageSurvey's meta attribute
+ /**
+ * Sets the image format for the ImageSurvey.
+ *
+ * This method updates the image format of the ImageSurvey, performs format validation, and triggers the update of metadata.
+ *
+ * @memberof ImageSurvey
+ *
+ * @param {string} format - 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 ImageSurvey.
+ */
ImageSurvey.prototype.setImageFormat = function (format) {
let self = this;
self.query
@@ -453,11 +490,24 @@ export let ImageSurvey = (function () {
})
};
+ /**
+ * Sets the opacity factor when rendering the ImageSurvey
+ *
+ * @memberof ImageSurvey
+ *
+ * @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.
+ */
ImageSurvey.prototype.getAvailableFormats = function() {
return this.properties.formats;
}
- // @api
+ /**
+ * Sets the opacity factor when rendering the ImageSurvey
+ *
+ * @memberof ImageSurvey
+ *
+ * @param {number} opacity - Opacity of the survey to set. Between 0 and 1
+ */
ImageSurvey.prototype.setOpacity = function (opacity) {
let self = this;
updateMetadata(self, () => {
@@ -465,47 +515,139 @@ export let ImageSurvey = (function () {
});
};
- // @api
+ /**
+ * Sets the blending mode when rendering the ImageSurvey
+ *
+ * @memberof ImageSurvey
+ *
+ * @param {boolean} [additive=false] -
+ *
+ * @description Two rendering modes are availables i.e. the default one and the additive one.
+ * When rendering this survey on top of the already rendered ones, the final color of the screen is computed like:
+ *
+ * opacity * this_survey_color + (1 - opacity) * already_rendered_color for the default mode
+ * opacity * this_survey_color + already_rendered_color for the additive mode
+ *
+ *
+ * Additive mode allows you to do linear survey color combination i.e. let's define 3 surveys named s1, s2, s3. Each could be associated to one color channel, i.e. s1 with red, s2 with green and s3 with the blue color channel.
+ * If the additive blending mode is enabled, then the final pixel color of your screen will be: rgb = [s1_opacity * s1_color; s2_opacity * s2_color; s3_opacity * s3_color]
+ */
ImageSurvey.prototype.setBlendingConfig = function (additive = false) {
updateMetadata(this, () => {
this.colorCfg.setBlendingConfig(additive);
});
};
- // @api
+ /**
+ * Sets the colormap when rendering the ImageSurvey.
+ *
+ * @memberof ImageSurvey
+ *
+ * @param {string} [colormap="grayscale"] - The colormap label to use. See {@link https://matplotlib.org/stable/users/explain/colors/colormaps.html|here} for more info about colormaps.
+ * Possible values are:
+ * "blues"
+ * "cividis"
+ * "cubehelix"
+ * "eosb"
+ * "grayscale"
+ * "inferno"
+ * "magma"
+ * "native"
+ * "parula"
+ * "plasma"
+ * "rainbow"
+ * "rdbu"
+ * "rdylbu"
+ * "redtemperature"
+ * "sinebow"
+ * "spectral"
+ * "summer"
+ * "viridis"
+ * "ylgnbu"
+ * "ylorbr"
+ * "red"
+ * "green"
+ * "blue"
+ * @param {Object} [options] - Options for the colormap
+ * @param {string} [options.stretch] - Stretching function of the colormap. Possible values are 'linear', 'asinh', 'log', 'sqrt', 'pow'. If no given, will not change it.
+ * @param {boolean} [options.reversed=false] - Reverse the colormap axis.
+ */
ImageSurvey.prototype.setColormap = function (colormap, options) {
updateMetadata(this, () => {
this.colorCfg.setColormap(colormap, options);
});
}
- // @api
+ /**
+ * Sets the gamma correction factor for the ImageSurvey.
+ *
+ * This method updates the gamma of the ImageSurvey.
+ *
+ * @memberof ImageSurvey
+ *
+ * @param {number} lowCut - The low cut value to set for the ImageSurvey.
+ * @param {number} highCut - The high cut value to set for the ImageSurvey.
+ */
ImageSurvey.prototype.setCuts = function (lowCut, highCut) {
updateMetadata(this, () => {
this.colorCfg.setCuts(lowCut, highCut);
});
};
- // @api
+ /**
+ * Sets the gamma correction factor for the ImageSurvey.
+ *
+ * This method updates the gamma of the ImageSurvey.
+ *
+ * @memberof ImageSurvey
+ *
+ * @param {number} gamma - The saturation value to set for the ImageSurvey. Between 0.1 and 10
+ */
ImageSurvey.prototype.setGamma = function (gamma) {
updateMetadata(this, () => {
this.colorCfg.setGamma(gamma);
});
};
- // @api
+ /**
+ * Sets the saturation for the ImageSurvey.
+ *
+ * This method updates the saturation of the ImageSurvey.
+ *
+ * @memberof ImageSurvey
+ *
+ * @param {number} saturation - The saturation value to set for the ImageSurvey. Between 0 and 1
+ */
ImageSurvey.prototype.setSaturation = function (saturation) {
updateMetadata(this, () => {
this.colorCfg.setSaturation(saturation);
});
};
+ /**
+ * Sets the brightness for the ImageSurvey.
+ *
+ * This method updates the brightness of the ImageSurvey.
+ *
+ * @memberof ImageSurvey
+ *
+ * @param {number} brightness - The brightness value to set for the ImageSurvey. Between 0 and 1
+ */
ImageSurvey.prototype.setBrightness = function (brightness) {
updateMetadata(this, () => {
this.colorCfg.setBrightness(brightness);
});
};
+ /**
+ * Sets the contrast for the ImageSurvey.
+ *
+ * This method updates the contrast of the ImageSurvey and triggers the update of metadata.
+ *
+ * @memberof ImageSurvey
+ *
+ * @param {number} contrast - The contrast value to set for the ImageSurvey. Between 0 and 1
+ */
ImageSurvey.prototype.setContrast = function (contrast) {
updateMetadata(this, () => {
this.colorCfg.setContrast(contrast);
@@ -521,7 +663,7 @@ export let ImageSurvey = (function () {
}
// Private method for updating the backend with the new meta
- var updateMetadata = function (self, callback = undefined) {
+ var updateMetadata = function (self, callback) {
if (callback) {
callback();
}
diff --git a/src/js/View.js b/src/js/View.js
index 24b04e77..4a7cb46f 100644
--- a/src/js/View.js
+++ b/src/js/View.js
@@ -490,7 +490,7 @@ export let View = (function () {
try {
const lonlat = view.wasm.screenToWorld(xymouse.x, xymouse.y);
var radec = view.wasm.viewToICRSCooSys(lonlat[0], lonlat[1]);
- view.pointTo(radec[0], radec[1], { forceAnimation: true });
+ view.pointTo(radec[0], radec[1]);
}
catch (err) {
return;
@@ -1320,17 +1320,19 @@ export let View = (function () {
}
}, a);
- a.contextMenu.attach([
- {
- label: Layout.horizontal([sampBtn, a.samp ? 'Send selection to SAMP' : 'SAMP disabled']),
- },
- {
- label: 'Remove selection',
- action(o) {
- a.view.unselectObjects();
+ if (a.contextMenu) {
+ a.contextMenu.attach([
+ {
+ label: Layout.horizontal([sampBtn, a.samp ? 'Send selection to SAMP' : 'SAMP disabled']),
+ },
+ {
+ label: 'Remove selection',
+ action(o) {
+ a.view.unselectObjects();
+ }
}
- }
- ]);
+ ]);
+ }
}
}
@@ -1342,8 +1344,7 @@ export let View = (function () {
// initialAccDelta must be consistent with fovDegrees here
View.prototype.setZoom = function (fovDegrees) {
fovDegrees = Math.min(fovDegrees, this.projection.fov);
- console.log(fovDegrees)
-
+
this.wasm.setFieldOfView(fovDegrees);
this.updateZoomState();
};
@@ -1748,8 +1749,7 @@ export let View = (function () {
* @param options
*
*/
- View.prototype.pointTo = function (ra, dec, options) {
- options = options || {};
+ View.prototype.pointTo = function (ra, dec) {
ra = parseFloat(ra);
dec = parseFloat(dec);
@@ -1775,6 +1775,7 @@ export let View = (function () {
// hide the popup if it is open
this.aladin.hidePopup();
};
+
View.prototype.makeUniqLayerName = function (name) {
if (!this.layerNameExists(name)) {
return name;