From f75211902bde5b647e50c01235fdce8d1a92a037 Mon Sep 17 00:00:00 2001 From: Matthieu Baumann Date: Tue, 11 Feb 2025 19:04:14 +0100 Subject: [PATCH] fix #225. I set to the hips object the cached options if there are instead of erasing the Hips object given by the user with a new one with the cached options --- examples/al-cfht.html | 2 +- examples/al-cuts-fits-hips.html | 3 + examples/al-set-colormap.html | 4 - src/js/Aladin.js | 7 +- src/js/vo/Datalink.js | 535 ++++++++++++++++---------------- 5 files changed, 279 insertions(+), 272 deletions(-) diff --git a/examples/al-cfht.html b/examples/al-cfht.html index 676c78cc..6fa99a3a 100644 --- a/examples/al-cfht.html +++ b/examples/al-cfht.html @@ -10,7 +10,7 @@ import A from '../src/js/A.js'; let aladin; A.init.then(() => { - aladin = A.aladin('#aladin-lite-div', {survey: "data/hips/PanSTARRS_DR1_color-z-zg-g", fov:2.0, target: "22 35 58.39 +33 57 57.8", showSettingsControl: true, log: false}); + aladin = A.aladin('#aladin-lite-div', {samp: true, survey: "data/hips/PanSTARRS_DR1_color-z-zg-g", fov:2.0, target: "22 35 58.39 +33 57 57.8", showSettingsControl: true, log: false}); aladin.setProjection('AIT'); let cfht = aladin.createImageSurvey("CFHT", "CFHT MegaCam u+g+r", "./data/hips/CFHT", "equatorial", 10, {imgFormat: 'png'}); let jwst1 = aladin.createImageSurvey("CDS/P/JWST/Stephans-Quintet/NIRCam+MIRI", "JWST NIRCam+MIRI", "data/hips/JWST_NIRCam_MIRI", null, null, {imgFormat: 'png'}); diff --git a/examples/al-cuts-fits-hips.html b/examples/al-cuts-fits-hips.html index 3faf8f24..f7f142a8 100644 --- a/examples/al-cuts-fits-hips.html +++ b/examples/al-cuts-fits-hips.html @@ -12,10 +12,13 @@ A.init.then(() => { aladin = A.aladin('#aladin-lite-div', {projection: 'AIT', cooFrame: 'galactic', fov: 200, target: 'galactic center'}); let dss = aladin.createImageSurvey("DSS blue band", "Color DSS blue HiPS", "http://alasky.cds.unistra.fr/DSS/DSS2-blue-XJ-S/", "equatorial", 9, {imgFormat: 'fits'}) + + aladin.setBaseImageLayer(dss); aladin.getBaseImageLayer().setCuts(2, 10000); + }); diff --git a/examples/al-set-colormap.html b/examples/al-set-colormap.html index 53f1b86f..73893753 100644 --- a/examples/al-set-colormap.html +++ b/examples/al-set-colormap.html @@ -15,10 +15,6 @@ // 'rdbu', 'rdylbu', 'redtemperature', 'sinebow', 'spectral', 'summer', 'viridis', 'ylgnbu' and 'ylorbr' hips = aladin.getBaseImageLayer() hips.setColormap("cubehelix"); - - aladin.setImageSurvey('astron.nl/P/lotss_dr2_high') - - //aladin.getBaseImageLayer().setColor([1.0, 0.0, 1.0, 1.0], { tf: 'Linear'} ); }); diff --git a/src/js/Aladin.js b/src/js/Aladin.js index fcbb064e..0251bebe 100644 --- a/src/js/Aladin.js +++ b/src/js/Aladin.js @@ -1876,22 +1876,21 @@ export let Aladin = (function () { // 2/ Not in the cache, then we create the hips from this url/id and // go to the case 3 imageLayer = A.HiPS(idOrUrl); + return this.setOverlayImageLayer(imageLayer, layer); } } else { // 3/ It is an image survey. imageLayer = urlOrHiPSOrFITS; - if (imageLayer instanceof HiPS) { let cachedLayerOptions = hipsCache.get(imageLayer.id) if (!cachedLayerOptions) { hipsCache.append(imageLayer.id, imageLayer.options) } else { - // first set the options of the cached layer to the one of the user - // if it is in the cache we get it from the cache - imageLayer = A.HiPS(imageLayer.id, cachedLayerOptions) + // set the options from what is in the cache + imageLayer.setOptions(cachedLayerOptions); } } } diff --git a/src/js/vo/Datalink.js b/src/js/vo/Datalink.js index a26b5399..9c810baf 100644 --- a/src/js/vo/Datalink.js +++ b/src/js/vo/Datalink.js @@ -47,301 +47,310 @@ export let Datalink = (function() { Datalink.prototype.handleActions = function(url, obscoreRow, aladinInstance) { //const url = obscoreRow["access_url"]; - new VOTable( - url, - (rsc) => { - rsc = VOTable.parseRsc(rsc); + let success = (rsc) => { + rsc = VOTable.parseRsc(rsc); - // It is a table - if (rsc && rsc.fields && rsc.rows) { - let table = rsc; - table.fields = Catalog.parseFields(table.fields); + // It is a table + if (rsc && rsc.fields && rsc.rows) { + let table = rsc; + table.fields = Catalog.parseFields(table.fields); - // Get the fields and the rows - let measures = []; - const { fields, rows } = table; - rows.forEach(row => { - let data = {}; + // Get the fields and the rows + let measures = []; + const { fields, rows } = table; + rows.forEach(row => { + let data = {}; - for (const [_, field] of Object.entries(fields)) { - var key = field.name; - data[key] = row[field.idx]; - } + for (const [_, field] of Object.entries(fields)) { + var key = field.name; + data[key] = row[field.idx]; + } - measures.push({data: data}) - }) - let self = this; - let datalinkTable = { - name: 'Datalink:' + url, - color: 'purple', - rows: measures, - fields, - showCallback: { - content_type: (data) => { - let contentType = data['content_type']; + measures.push({data: data}) + }) + let self = this; + let datalinkTable = { + name: 'Datalink:' + url, + color: 'purple', + rows: measures, + fields, + showCallback: { + content_type: (data) => { + let contentType = data['content_type']; - if (contentType && contentType.includes('datalink')) { - return new ActionButton({ - size: 'small', - content: '🔗', - tooltip: {content: 'Datalink VOTable', aladin: aladinInstance, global: true}, - action(e) {} - }).element(); - } else { - return contentType; - } - }, - 'service_def': (data) => { - const serviceName = data['service_def']; + if (contentType && contentType.includes('datalink')) { + return new ActionButton({ + size: 'small', + content: '🔗', + tooltip: {content: 'Datalink VOTable', aladin: aladinInstance, global: true}, + action(e) {} + }).element(); + } else { + return contentType; + } + }, + 'service_def': (data) => { + const serviceName = data['service_def']; - if (data['semantics'] === "#cutout") { - return new ActionButton({ - size: 'small', - content: '📡', - tooltip: {global: true, aladin: aladinInstance, content: 'Open the cutout service form'}, - action(e) { - if (self.serviceQueryBox) { - self.serviceQueryBox.remove() - } - - self.serviceQueryBox = new ServiceQueryBox(aladinInstance); - self.serviceQueryBox._hide(); - self.serviceQueryBox.attach(self.services[serviceName]); - self.serviceQueryBox._show({ - position: { - anchor: 'center center' - } - }); + if (data['semantics'] === "#cutout") { + return new ActionButton({ + size: 'small', + content: '📡', + tooltip: {global: true, aladin: aladinInstance, content: 'Open the cutout service form'}, + action(e) { + if (self.serviceQueryBox) { + self.serviceQueryBox.remove() } - }).element(); - } else { - return serviceName || '--'; - } - }, - 'access_url': (data) => { - let url = data['access_url']; - let accessUrlEl = document.createElement('div'); - - if (url) { - let contentType = data['content_type']; - let contentQualifier = data['content_qualifier']; - - try { - // Just create a URL object to verify it is a good url - // If not, it will throw an exception - let _ = new URL(url); - accessUrlEl.classList.add('aladin-href-td-container'); - accessUrlEl.innerHTML = '' + url + ''; - - accessUrlEl.addEventListener('click', (e) => { - e.preventDefault(); - e.stopPropagation(); - - let processImageFitsClick = () => { - var successCallback = ((ra, dec, fov, _) => { - aladinInstance.gotoRaDec(ra, dec); - aladinInstance.setFoV(fov); - }); - - let image = aladinInstance.createImageFITS(url, {name: url}, successCallback); - aladinInstance.setOverlayImageLayer(image, Utils.uuidv4()) - }; - - switch (contentType) { - // A datalink response containing links to datasets or services attached to the current dataset - case 'application/x-votable+xml;content=datalink': - new Datalink().handleActions(url, obscoreRow, aladinInstance); - break; - case 'application/hips': - // Clic on a HiPS - let layer = Utils.uuidv4(); - if (contentQualifier === "cube") { - let cubeOnTheFlyUrl = url + '/'; - - HiPSProperties.fetchFromUrl(cubeOnTheFlyUrl) - .then(properties => { - let numSlices = +properties.hips_cube_depth; - let idxSlice = +properties.hips_cube_firstframe; - - let updateSlice = () => { - let colorCfg = aladinInstance.getOverlayImageLayer(layer).getColorCfg(); - let hips = aladinInstance.setOverlayImageLayer(cubeOnTheFlyUrl + idxSlice, layer) - hips.setOptions({ - opacity: colorCfg.opacity, - minCut: colorCfg.minCut, - maxCut: colorCfg.maxCut, - colormap: colorCfg.colormap, - stretch: colorCfg.stretch, - reversed: colorCfg.reversed - }) - - slicer.update({ - value: idxSlice, - tooltip: {content: (idxSlice + 1) + '/' + numSlices, position: {direction: 'bottom'}}, - }) - - cubeDisplayer.update({content: Layout.horizontal([prevBtn, nextBtn, slicer, (idxSlice + 1) + '/' + numSlices])}) - }; - - let slicer = Input.slider({ - label: "Slice", - name: "cube slicer", - ticks: [idxSlice], - tooltip: {content: (idxSlice + 1) + '/' + numSlices , position: {direction: 'bottom'}}, - min: 0, - max: numSlices - 1, - value: idxSlice, - actions: { - change: (e) => { - idxSlice = Math.round(e.target.value); - - updateSlice(); - }, - input: (e) => { - idxSlice = Math.round(e.target.value); - - slicer.update({ - value: idxSlice, - tooltip: {content: (idxSlice + 1) + '/' + numSlices, position: {direction: 'bottom'}}, - }) - } - }, - cssStyle: { - width: '300px' - } - }); - - let prevBtn = A.button({ - size: 'small', - content: '<', - action(o) { - idxSlice = Math.max(idxSlice - 1, 0); - updateSlice() - } - }) - - let nextBtn = A.button({ - size: 'small', - content: '>', - action(o) { - idxSlice = Math.min(idxSlice + 1, numSlices - 1); - updateSlice() - } - }) - - let cubeDisplayer = A.box({ - close: true, - header: { - title: 'HiPS cube player', - draggable: true, - }, - content: Layout.horizontal([prevBtn, nextBtn, slicer, (idxSlice + 1) + '/' + numSlices]), - position: {anchor: 'center top'}, - }); - aladinInstance.addUI(cubeDisplayer) - - aladinInstance.setOverlayImageLayer(cubeOnTheFlyUrl + idxSlice, layer) - }) - } else { - let survey = aladinInstance.newImageSurvey(url); - aladinInstance.setOverlayImageLayer(survey, layer) - } - - break; - // Any generic FITS file - case 'application/fits': - if (contentQualifier === "cube") { - // fits cube - console.warn("Cube not handled, only first slice downloaded") - } - - processImageFitsClick(); - break; - case 'image/fits': - if (contentQualifier === "cube") { - // fits cube - console.warn("Cube not handled, only first slice downloaded") - } - - processImageFitsClick(); - break; - default: - // When all has been done, download what's under the link - Utils.openNewTab(url); - break; + self.serviceQueryBox = new ServiceQueryBox(aladinInstance); + self.serviceQueryBox._hide(); + self.serviceQueryBox.attach(self.services[serviceName]); + self.serviceQueryBox._show({ + position: { + anchor: 'center center' } }); - } catch(e) { - accessUrlEl.innerText = '--'; } - } else { + }).element(); + } else { + return serviceName || '--'; + } + }, + 'access_url': (data) => { + let url = data['access_url']; + + let accessUrlEl = document.createElement('div'); + + if (url) { + let contentType = data['content_type']; + let contentQualifier = data['content_qualifier']; + + try { + // Just create a URL object to verify it is a good url + // If not, it will throw an exception + let _ = new URL(url); + accessUrlEl.classList.add('aladin-href-td-container'); + accessUrlEl.innerHTML = '' + url + ''; + + accessUrlEl.addEventListener('click', (e) => { + e.preventDefault(); + e.stopPropagation(); + + let processImageFitsClick = () => { + var successCallback = ((ra, dec, fov, _) => { + aladinInstance.gotoRaDec(ra, dec); + aladinInstance.setFoV(fov); + }); + + let image = aladinInstance.createImageFITS(url, {name: url}, successCallback); + aladinInstance.setOverlayImageLayer(image, Utils.uuidv4()) + }; + + switch (contentType) { + // A datalink response containing links to datasets or services attached to the current dataset + case 'application/x-votable+xml;content=datalink': + new Datalink().handleActions(url, obscoreRow, aladinInstance); + break; + case 'application/hips': + // Clic on a HiPS + let layer = Utils.uuidv4(); + if (contentQualifier === "cube") { + let cubeOnTheFlyUrl = url + '/'; + + HiPSProperties.fetchFromUrl(cubeOnTheFlyUrl) + .then(properties => { + let numSlices = +properties.hips_cube_depth; + let idxSlice = +properties.hips_cube_firstframe; + + let updateSlice = () => { + let colorCfg = aladinInstance.getOverlayImageLayer(layer).getColorCfg(); + let hips = aladinInstance.setOverlayImageLayer(cubeOnTheFlyUrl + idxSlice, layer) + hips.setOptions({ + opacity: colorCfg.opacity, + minCut: colorCfg.minCut, + maxCut: colorCfg.maxCut, + colormap: colorCfg.colormap, + stretch: colorCfg.stretch, + reversed: colorCfg.reversed + }) + + slicer.update({ + value: idxSlice, + tooltip: {content: (idxSlice + 1) + '/' + numSlices, position: {direction: 'bottom'}}, + }) + + cubeDisplayer.update({content: Layout.horizontal([prevBtn, nextBtn, slicer, (idxSlice + 1) + '/' + numSlices])}) + }; + + let slicer = Input.slider({ + label: "Slice", + name: "cube slicer", + ticks: [idxSlice], + tooltip: {content: (idxSlice + 1) + '/' + numSlices , position: {direction: 'bottom'}}, + min: 0, + max: numSlices - 1, + value: idxSlice, + actions: { + change: (e) => { + idxSlice = Math.round(e.target.value); + + updateSlice(); + }, + input: (e) => { + idxSlice = Math.round(e.target.value); + + slicer.update({ + value: idxSlice, + tooltip: {content: (idxSlice + 1) + '/' + numSlices, position: {direction: 'bottom'}}, + }) + } + }, + cssStyle: { + width: '300px' + } + }); + + let prevBtn = A.button({ + size: 'small', + content: '<', + action(o) { + idxSlice = Math.max(idxSlice - 1, 0); + updateSlice() + } + }) + + let nextBtn = A.button({ + size: 'small', + content: '>', + action(o) { + idxSlice = Math.min(idxSlice + 1, numSlices - 1); + updateSlice() + } + }) + + let cubeDisplayer = A.box({ + close: true, + header: { + title: 'HiPS cube player', + draggable: true, + }, + content: Layout.horizontal([prevBtn, nextBtn, slicer, (idxSlice + 1) + '/' + numSlices]), + position: {anchor: 'center top'}, + }); + aladinInstance.addUI(cubeDisplayer) + + aladinInstance.setOverlayImageLayer(cubeOnTheFlyUrl + idxSlice, layer) + }) + } else { + let survey = aladinInstance.newImageSurvey(url); + aladinInstance.setOverlayImageLayer(survey, layer) + } + + break; + // Any generic FITS file + case 'application/fits': + if (contentQualifier === "cube") { + // fits cube + console.warn("Cube not handled, only first slice downloaded") + } + + processImageFitsClick(); + break; + case 'image/fits': + if (contentQualifier === "cube") { + // fits cube + console.warn("Cube not handled, only first slice downloaded") + } + + processImageFitsClick(); + break; + default: + // When all has been done, download what's under the link + Utils.openNewTab(url); + break; + } + }); + } catch(e) { accessUrlEl.innerText = '--'; } - - return accessUrlEl; + } else { + accessUrlEl.innerText = '--'; } + + return accessUrlEl; } } + } - aladinInstance.measurementTable.showMeasurement([datalinkTable]); - // SODA service descriptor - } else if (rsc && rsc.baseUrl && rsc.inputParams) { - // Try to parse a SODA service descriptor resource - let serviceDesc = rsc; + aladinInstance.measurementTable.showMeasurement([datalinkTable]); + // SODA service descriptor + } else if (rsc && rsc.baseUrl && rsc.inputParams) { + // Try to parse a SODA service descriptor resource + let serviceDesc = rsc; - if (serviceDesc) { - // Try to populate the SODA form fields with obscore values - let populateSODAFields = (SODAParams) => { - for (const name in SODAParams.inputParams) { - let inputParam = SODAParams.inputParams[name]; + if (serviceDesc) { + // Try to populate the SODA form fields with obscore values + let populateSODAFields = (SODAParams) => { + for (const name in SODAParams.inputParams) { + let inputParam = SODAParams.inputParams[name]; - if (inputParam.type === "group") { - for (const param of inputParam.subInputs) { - if (param.value) { - continue; - } + if (inputParam.type === "group") { + for (const param of inputParam.subInputs) { + if (param.value) { + continue; + } - if (param.name === "ra") { - param.value = obscoreRow['s_ra']; - } else if (param.name === "dec") { - param.value = obscoreRow['s_dec']; - } else if (param.name === "fmin") { - param.value = obscoreRow['em_min']; - } else if (param.name === "fmax") { - param.value = obscoreRow['em_max']; - } else if (param.name === "rad") { - param.value = obscoreRow['s_fov'] / 2; - } + if (param.name === "ra") { + param.value = obscoreRow['s_ra']; + } else if (param.name === "dec") { + param.value = obscoreRow['s_dec']; + } else if (param.name === "fmin") { + param.value = obscoreRow['em_min']; + } else if (param.name === "fmax") { + param.value = obscoreRow['em_max']; + } else if (param.name === "rad") { + param.value = obscoreRow['s_fov'] / 2; } } } - }; + } + }; - // Request the base url of the SODA server to check if there - // is a self description VOTable - new VOTable(serviceDesc.baseUrl, (rsc) => { - const res = VOTable.parseRsc(rsc); + // Request the base url of the SODA server to check if there + // is a self description VOTable + new VOTable(serviceDesc.baseUrl, (rsc) => { + const res = VOTable.parseRsc(rsc); - if (res && res.baseUrl && res.inputParams) { - for (const name in res.inputParams) { - let inputParam = res.inputParams[name]; - if (!serviceDesc.inputParams[name]) { - serviceDesc.inputParams[name] = inputParam; - } + if (res && res.baseUrl && res.inputParams) { + for (const name in res.inputParams) { + let inputParam = res.inputParams[name]; + if (!serviceDesc.inputParams[name]) { + serviceDesc.inputParams[name] = inputParam; } } - - populateSODAFields(serviceDesc); - }, undefined, true); + } populateSODAFields(serviceDesc); + }, undefined, true); - this.services[serviceDesc.name] = serviceDesc; - } + populateSODAFields(serviceDesc); + + this.services[serviceDesc.name] = serviceDesc; } + } + }; + new VOTable( + url, + success, + () => { + new VOTable( + url, + success, + undefined, + true + ) }, - undefined, + false ) };