From b68358f6b25780ea27d43b9ed53619f5f9cbff6d Mon Sep 17 00:00:00 2001 From: Matthieu Baumann Date: Thu, 4 Apr 2024 17:41:11 +0200 Subject: [PATCH] add proper motion example --- examples/al-cat-proper-motion.html | 99 +++++++++++++++++++++++------ examples/al-catalog-hips-shape.html | 5 +- examples/al-obscore.html | 2 +- examples/al-soda-ska.html | 2 +- src/js/A.js | 27 ++++---- src/js/Catalog.js | 60 +++++++++-------- src/js/Ellipse.js | 10 ++- src/js/Footprint.js | 19 +++--- src/js/Line.js | 5 ++ src/js/Polyline.js | 2 +- src/js/ProgressiveCat.js | 9 +-- src/js/Utils.ts | 25 +++++--- 12 files changed, 180 insertions(+), 85 deletions(-) diff --git a/examples/al-cat-proper-motion.html b/examples/al-cat-proper-motion.html index bc1f42e6..38c1c612 100644 --- a/examples/al-cat-proper-motion.html +++ b/examples/al-cat-proper-motion.html @@ -22,27 +22,90 @@ samp: true, }); - aladin.addCatalog(A.catalogFromSimbad("LMC", 10, { - limit: 10000, - onClick: 'showTable', - orderBy: 'nb_ref', - color: 'yellow', - hoverColor: 'yellow', - shape: (s) => { - let pmra = +s.data.pmra; - let pmdec = +s.data.pmdec; + let pmraMean = null, pmdecMean = null; + //aladin.addCatalog(A.catalogFromSimbad('LMC', 2.5, { + //aladin.addCatalog(A.catalogFromVizieR('J/A+A/663/A107/table5', 'LMC', 5, { + + const pmCat = A.catalogFromURL('./data/proper_motion.xml', { + onClick: 'showTable', + name: 'mean pm over HPX cells around LMC from GaiaDR2', + hoverColor: 'yellow', + // Footprint associated to sources + shape: (s) => { + // compute the mean of pm over the catalog sources + if (!pmraMean || !pmdecMean) { + pmraMean = 0, pmdecMean = 0; + for (var s of pmCat.getSources()) { + pmraMean += +s.data.pmra; + pmdecMean += +s.data.pmdec; + } - let mag2 = pmra * pmra + pmdec * pmdec; - if (mag2 > 1000) { - return; + const numSources = pmCat.getSources().length; + + pmraMean /= numSources + pmdecMean /= numSources + } + + let dra = +s.data.pmra - pmraMean; + let ddec = +s.data.pmdec - pmdecMean; + + let mag = Math.sqrt(dra * dra + ddec * ddec); + // discard drawing a vector for big pm + if (mag > 1) { + return; + } + + let color = rainbowColorMap(mag * 2) + + return A.line( + s.ra, + s.dec, + s.ra + dra, + s.dec + ddec, + null, + {lineWidth: 3, arrow: true, color} + ) } - - let mag = Math.sqrt(mag2) - - return A.line(+s.ra, +s.dec, +s.ra + (0.5 * pmra / mag), +s.dec + (0.5 * pmdec / mag), null, {lineWidth: 3, arrow: true, color: +s.data.rvz_radvel < 0 ? 'blue' : 'red'}) - } - })); + }, + ); + aladin.addCatalog(pmCat); }); + + function rainbowColorMap(value) { + // Ensure value is within range [0, 1] + value = Math.max(0, Math.min(1, value)); + + // Convert value to hue + var hue = (1 - value) * 240; // 240 is the maximum hue value for blue + + // Convert HSV to RGB + var chroma = 1; + var x = chroma * (1 - Math.abs((hue / 60) % 2 - 1)); + var r1, g1, b1; + + if (hue >= 0 && hue < 60) { + [r1, g1, b1] = [chroma, x, 0]; + } else if (hue >= 60 && hue < 120) { + [r1, g1, b1] = [x, chroma, 0]; + } else if (hue >= 120 && hue < 180) { + [r1, g1, b1] = [0, chroma, x]; + } else if (hue >= 180 && hue < 240) { + [r1, g1, b1] = [0, x, chroma]; + } + + var m = 1 - chroma; + var r = r1 + m; + var g = g1 + m; + var b = b1 + m; + + // Convert RGB to HEX + r = Math.round(r * 255); + g = Math.round(g * 255); + b = Math.round(b * 255); + var colorHex = "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); + + return colorHex; + } diff --git a/examples/al-catalog-hips-shape.html b/examples/al-catalog-hips-shape.html index a1549acc..53338161 100644 --- a/examples/al-catalog-hips-shape.html +++ b/examples/al-catalog-hips-shape.html @@ -35,12 +35,11 @@ let a = +s.data.size_maj; let b = +s.data.size_min; - if (a < 0.1 || b < 0.1) { + if (a < 0.1 || b < 0.1) return; - } let angle = +s.data.size_angle || 0.0; - return A.ellipse(s.ra, s.dec, a / 60, b / 60, angle, {lineWidth: 3, color: 'cyan'}); + return A.ellipse(s.ra, s.dec, a / 60, b / 60, angle, {color: 'cyan'}); }; var hips = A.catalogHiPS('https://axel.u-strasbg.fr/HiPSCatService/Simbad', {onClick: 'showTable', name: 'Simbad', color: 'cyan', hoverColor: 'red', shape: drawFunctionFootprint}); diff --git a/examples/al-obscore.html b/examples/al-obscore.html index 3a5f88e3..25d0a3cb 100644 --- a/examples/al-obscore.html +++ b/examples/al-obscore.html @@ -16,7 +16,7 @@ aladin.addCatalog(catalog) }); - aladin.addCatalog(A.catalogFromVizieR("B/assocdata/obscore", "0 +0", 20, {limit: 1000})) + aladin.addCatalog(A.catalogFromVizieR("B/assocdata/obscore", "0 +0", 20, {onClick: 'showTable', hoverColor: 'yellow', limit: 1000})) }); diff --git a/examples/al-soda-ska.html b/examples/al-soda-ska.html index d9d23b62..a315254b 100644 --- a/examples/al-soda-ska.html +++ b/examples/al-soda-ska.html @@ -12,7 +12,7 @@ A.init.then(() => { aladin = A.aladin('#aladin-lite-div', {fullScreen: true, target: "Abell 194", fov: 180, projection: 'AIT', showContextMenu: true}); aladin.setImageSurvey('astron.nl/P/lotss_dr2_high') - A.catalogFromSKAORucio("Abell 194", 90, {onClick: 'showTable'}, (cat) => { + A.catalogFromSKAORucio("Abell 194", 90, {onClick: 'showTable', hoverColor: 'yellow'}, (cat) => { aladin.addCatalog(cat); }); diff --git a/src/js/A.js b/src/js/A.js index 6f03944c..8547364e 100644 --- a/src/js/A.js +++ b/src/js/A.js @@ -523,18 +523,24 @@ A.catalogFromURL = function (url, options, successCallback, errorCallback, usePr options.url = url; var catalog = A.catalog(options); const processVOTable = function (table) { - let {sources, footprints, fields, type} = table; + let {sources, fields} = table; catalog.setFields(fields); - - if (catalog.type === 'ObsCore') { - // The fields corresponds to obscore ones - // Set the name of the catalog to be ObsCore: - catalog.name = "ObsCore:" + url; - } - - catalog.addFootprints(footprints) catalog.addSources(sources); + if ('s_region' in fields && typeof catalog.shape !== 'function') { + // set the shape + catalog.setShape((s) => { + if (!s.data.s_region) + return; + + const shapes = A.footprintsFromSTCS(s.data.s_region, options) + let fp = new Footprint(shapes, s); + fp.setColor(catalog.color); + + return fp; + }) + } + if (successCallback) { successCallback(catalog); } @@ -646,7 +652,7 @@ A.catalogFromSimbad = function (target, radius, options, successCallback, errorC }).then((coo) => { const url = URLBuilder.buildSimbadCSURL(coo.lon, coo.lat, radius, options) const processVOTable = function (table) { - let {sources, footprints, fields, type} = table; + let {sources, fields} = table; cat.setFields(fields); if (cat.type === 'ObsCore') { @@ -655,7 +661,6 @@ A.catalogFromSimbad = function (target, radius, options, successCallback, errorC cat.name = "ObsCore:" + url; } - cat.addFootprints(footprints) cat.addSources(sources); if (successCallback) { diff --git a/src/js/Catalog.js b/src/js/Catalog.js index d0402570..fcb996c5 100644 --- a/src/js/Catalog.js +++ b/src/js/Catalog.js @@ -293,14 +293,14 @@ export let Catalog = (function() { var name = field.name || field.ID || ''; name = name.toLowerCase(); - if ( ! raFieldIdx) { - if (name.indexOf('ra')==0 || name.indexOf('_ra')==0 || name.indexOf('ra(icrs)')==0 || name.indexOf('_ra')==0 || name.indexOf('alpha')==0) { + if (raFieldIdx === null) { + if (name.indexOf('ra')==0 || name.indexOf('_ra')==0 || name.indexOf('ra(icrs)')==0 || name.indexOf('alpha')==0) { raFieldIdx = l; continue; } } - if ( ! decFieldIdx) { + if (decFieldIdx === null) { if (name.indexOf('dej2000')==0 || name.indexOf('_dej2000')==0 || name.indexOf('de')==0 || name.indexOf('de(icrs)')==0 || name.indexOf('_de')==0 || name.indexOf('delta')==0) { decFieldIdx = l; continue; @@ -323,7 +323,6 @@ export let Catalog = (function() { Catalog.parseFields = function(fields, raField, decField) { // This votable is not an obscore one let [raFieldIdx, decFieldIdx] = findRADecFields(fields, raField, decField); - let parsedFields = {}; let fieldIdx = 0; fields.forEach((field) => { @@ -366,19 +365,16 @@ export let Catalog = (function() { } let { fields, rows } = table; - let type; try { fields = ObsCore.parseFields(fields); //fields.subtype = "ObsCore"; - type = 'ObsCore'; } catch(e) { // It is not an ObsCore table fields = Catalog.parseFields(fields, raField, decField); - type = 'sources'; } let sources = []; - let footprints = []; + //let footprints = []; var coo = new Coo(); @@ -408,22 +404,23 @@ export let Catalog = (function() { dec = coo.lat; } - source = new Source(ra, dec, mesures); + source = new Source(parseFloat(ra), parseFloat(dec), mesures); source.rowIdx = rowIdx; } - let footprint = null; - if (region) { + //let footprint = null; + /*if (region) { let shapes = A.footprintsFromSTCS(region, {lineWidth: 2}) footprint = new Footprint(shapes, source); - } + }*/ - if (footprint) { + /*if (footprint) { footprints.push(footprint); if (maxNbSources && footprints.length == maxNbSources) { return false; } - } else if(source) { + } else */ + if (source) { sources.push(source); if (maxNbSources && sources.length == maxNbSources) { return false; @@ -437,9 +434,8 @@ export let Catalog = (function() { if (successCallback) { successCallback({ sources, - footprints, + //footprints, fields, - type }); } }, @@ -489,7 +485,7 @@ export let Catalog = (function() { return; } - if(!this.fields) { + if (!this.fields) { // Case where we create a catalog from scratch // We have to define its fields by looking at the source data let fields = []; @@ -501,9 +497,9 @@ export let Catalog = (function() { this.setFields(fields); } - let footprints = this.parseFootprintsFromSources(sources); - sources = sources.filter((s) => s.hasFootprint !== true); - this.addFootprints(footprints); + //let footprints = this.parseFootprintsFromSources(sources); + //sources = sources.filter((s) => s.hasFootprint !== true); + //this.addFootprints(footprints); this.sources = this.sources.concat(sources); for (var k=0, len=sources.length; k { - f.setCatalog(instance); - }) - sources = sources.filter((s) => s.hasFootprint !== true); - + let footprints = instance.computeFootprints(sources); return [sources, footprints]; }; @@ -648,7 +643,7 @@ export let ProgressiveCat = (function() { } }, - parseFootprintsFromSources: Catalog.prototype.parseFootprintsFromSources, + computeFootprints: Catalog.prototype.computeFootprints, reportChange: function() { // TODO: to be shared with Catalog this.view && this.view.requestRedraw(); diff --git a/src/js/Utils.ts b/src/js/Utils.ts index f999b8cf..f7680ac7 100644 --- a/src/js/Utils.ts +++ b/src/js/Utils.ts @@ -310,17 +310,24 @@ Utils.getAjaxObject = function (url, method, dataType, useProxy) { */ Utils.fetch = function(params) { - let url = new URL(params.url); - if (params.useProxy === true) { - url = Utils.handleCORSNotSameOrigin(url) - } - - if (params.data) { - // add the search params to the url object - for (const key in params.data) { - url.searchParams.append(key, params.data[key]); + let url; + try { + url = new URL(params.url); + if (params.useProxy === true) { + url = Utils.handleCORSNotSameOrigin(url) } + + if (params.data) { + // add the search params to the url object + for (const key in params.data) { + url.searchParams.append(key, params.data[key]); + } + } + } catch(e) { + // localhost url + url = params.url; } + let request = new Request(url, { method: params.method || 'GET',