add proper motion example

This commit is contained in:
Matthieu Baumann
2024-04-04 17:41:11 +02:00
committed by Matthieu Baumann
parent 9109c69fc3
commit b68358f6b2
12 changed files with 180 additions and 85 deletions

View File

@@ -22,27 +22,90 @@
samp: true, samp: true,
}); });
aladin.addCatalog(A.catalogFromSimbad("LMC", 10, { let pmraMean = null, pmdecMean = null;
limit: 10000, //aladin.addCatalog(A.catalogFromSimbad('LMC', 2.5, {
onClick: 'showTable', //aladin.addCatalog(A.catalogFromVizieR('J/A+A/663/A107/table5', 'LMC', 5, {
orderBy: 'nb_ref',
color: 'yellow', const pmCat = A.catalogFromURL('./data/proper_motion.xml', {
hoverColor: 'yellow', onClick: 'showTable',
shape: (s) => { name: 'mean pm over HPX cells around LMC from GaiaDR2',
let pmra = +s.data.pmra; hoverColor: 'yellow',
let pmdec = +s.data.pmdec; // 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; const numSources = pmCat.getSources().length;
if (mag2 > 1000) {
return; 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) );
aladin.addCatalog(pmCat);
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'})
}
}));
}); });
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;
}
</script> </script>
</body> </body>

View File

@@ -35,12 +35,11 @@
let a = +s.data.size_maj; let a = +s.data.size_maj;
let b = +s.data.size_min; let b = +s.data.size_min;
if (a < 0.1 || b < 0.1) { if (a < 0.1 || b < 0.1)
return; return;
}
let angle = +s.data.size_angle || 0.0; 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}); var hips = A.catalogHiPS('https://axel.u-strasbg.fr/HiPSCatService/Simbad', {onClick: 'showTable', name: 'Simbad', color: 'cyan', hoverColor: 'red', shape: drawFunctionFootprint});

View File

@@ -16,7 +16,7 @@
aladin.addCatalog(catalog) 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}))
}); });
</script> </script>
</body> </body>

View File

@@ -12,7 +12,7 @@
A.init.then(() => { A.init.then(() => {
aladin = A.aladin('#aladin-lite-div', {fullScreen: true, target: "Abell 194", fov: 180, projection: 'AIT', showContextMenu: true}); 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') 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); aladin.addCatalog(cat);
}); });

View File

@@ -523,18 +523,24 @@ A.catalogFromURL = function (url, options, successCallback, errorCallback, usePr
options.url = url; options.url = url;
var catalog = A.catalog(options); var catalog = A.catalog(options);
const processVOTable = function (table) { const processVOTable = function (table) {
let {sources, footprints, fields, type} = table; let {sources, fields} = table;
catalog.setFields(fields); catalog.setFields(fields);
if (catalog.type === 'ObsCore') {
// The fields corresponds to obscore ones
// Set the name of the catalog to be ObsCore:<catalog name>
catalog.name = "ObsCore:" + url;
}
catalog.addFootprints(footprints)
catalog.addSources(sources); 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) { if (successCallback) {
successCallback(catalog); successCallback(catalog);
} }
@@ -646,7 +652,7 @@ A.catalogFromSimbad = function (target, radius, options, successCallback, errorC
}).then((coo) => { }).then((coo) => {
const url = URLBuilder.buildSimbadCSURL(coo.lon, coo.lat, radius, options) const url = URLBuilder.buildSimbadCSURL(coo.lon, coo.lat, radius, options)
const processVOTable = function (table) { const processVOTable = function (table) {
let {sources, footprints, fields, type} = table; let {sources, fields} = table;
cat.setFields(fields); cat.setFields(fields);
if (cat.type === 'ObsCore') { if (cat.type === 'ObsCore') {
@@ -655,7 +661,6 @@ A.catalogFromSimbad = function (target, radius, options, successCallback, errorC
cat.name = "ObsCore:" + url; cat.name = "ObsCore:" + url;
} }
cat.addFootprints(footprints)
cat.addSources(sources); cat.addSources(sources);
if (successCallback) { if (successCallback) {

View File

@@ -293,14 +293,14 @@ export let Catalog = (function() {
var name = field.name || field.ID || ''; var name = field.name || field.ID || '';
name = name.toLowerCase(); name = name.toLowerCase();
if ( ! raFieldIdx) { if (raFieldIdx === null) {
if (name.indexOf('ra')==0 || name.indexOf('_ra')==0 || name.indexOf('ra(icrs)')==0 || name.indexOf('_ra')==0 || name.indexOf('alpha')==0) { if (name.indexOf('ra')==0 || name.indexOf('_ra')==0 || name.indexOf('ra(icrs)')==0 || name.indexOf('alpha')==0) {
raFieldIdx = l; raFieldIdx = l;
continue; 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) { 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; decFieldIdx = l;
continue; continue;
@@ -323,7 +323,6 @@ export let Catalog = (function() {
Catalog.parseFields = function(fields, raField, decField) { Catalog.parseFields = function(fields, raField, decField) {
// This votable is not an obscore one // This votable is not an obscore one
let [raFieldIdx, decFieldIdx] = findRADecFields(fields, raField, decField); let [raFieldIdx, decFieldIdx] = findRADecFields(fields, raField, decField);
let parsedFields = {}; let parsedFields = {};
let fieldIdx = 0; let fieldIdx = 0;
fields.forEach((field) => { fields.forEach((field) => {
@@ -366,19 +365,16 @@ export let Catalog = (function() {
} }
let { fields, rows } = table; let { fields, rows } = table;
let type;
try { try {
fields = ObsCore.parseFields(fields); fields = ObsCore.parseFields(fields);
//fields.subtype = "ObsCore"; //fields.subtype = "ObsCore";
type = 'ObsCore';
} catch(e) { } catch(e) {
// It is not an ObsCore table // It is not an ObsCore table
fields = Catalog.parseFields(fields, raField, decField); fields = Catalog.parseFields(fields, raField, decField);
type = 'sources';
} }
let sources = []; let sources = [];
let footprints = []; //let footprints = [];
var coo = new Coo(); var coo = new Coo();
@@ -408,22 +404,23 @@ export let Catalog = (function() {
dec = coo.lat; dec = coo.lat;
} }
source = new Source(ra, dec, mesures); source = new Source(parseFloat(ra), parseFloat(dec), mesures);
source.rowIdx = rowIdx; source.rowIdx = rowIdx;
} }
let footprint = null; //let footprint = null;
if (region) { /*if (region) {
let shapes = A.footprintsFromSTCS(region, {lineWidth: 2}) let shapes = A.footprintsFromSTCS(region, {lineWidth: 2})
footprint = new Footprint(shapes, source); footprint = new Footprint(shapes, source);
} }*/
if (footprint) { /*if (footprint) {
footprints.push(footprint); footprints.push(footprint);
if (maxNbSources && footprints.length == maxNbSources) { if (maxNbSources && footprints.length == maxNbSources) {
return false; return false;
} }
} else if(source) { } else */
if (source) {
sources.push(source); sources.push(source);
if (maxNbSources && sources.length == maxNbSources) { if (maxNbSources && sources.length == maxNbSources) {
return false; return false;
@@ -437,9 +434,8 @@ export let Catalog = (function() {
if (successCallback) { if (successCallback) {
successCallback({ successCallback({
sources, sources,
footprints, //footprints,
fields, fields,
type
}); });
} }
}, },
@@ -489,7 +485,7 @@ export let Catalog = (function() {
return; return;
} }
if(!this.fields) { if (!this.fields) {
// Case where we create a catalog from scratch // Case where we create a catalog from scratch
// We have to define its fields by looking at the source data // We have to define its fields by looking at the source data
let fields = []; let fields = [];
@@ -501,9 +497,9 @@ export let Catalog = (function() {
this.setFields(fields); this.setFields(fields);
} }
let footprints = this.parseFootprintsFromSources(sources); //let footprints = this.parseFootprintsFromSources(sources);
sources = sources.filter((s) => s.hasFootprint !== true); //sources = sources.filter((s) => s.hasFootprint !== true);
this.addFootprints(footprints); //this.addFootprints(footprints);
this.sources = this.sources.concat(sources); this.sources = this.sources.concat(sources);
for (var k=0, len=sources.length; k<len; k++) { for (var k=0, len=sources.length; k<len; k++) {
@@ -514,10 +510,12 @@ export let Catalog = (function() {
this.dec.push(sources[k].dec); this.dec.push(sources[k].dec);
} }
this.recomputeFootprints = true;
this.reportChange(); this.reportChange();
}; };
Catalog.prototype.addFootprints = function(footprintsToAdd) { /*Catalog.prototype.addFootprints = function(footprintsToAdd) {
footprintsToAdd = [].concat(footprintsToAdd); // make sure we have an array and not an individual footprints footprintsToAdd = [].concat(footprintsToAdd); // make sure we have an array and not an individual footprints
this.footprints = this.footprints.concat(footprintsToAdd); this.footprints = this.footprints.concat(footprintsToAdd);
@@ -526,23 +524,28 @@ export let Catalog = (function() {
}) })
this.reportChange(); this.reportChange();
}; };*/
Catalog.prototype.parseFootprintsFromSources = function(sources) { Catalog.prototype.computeFootprints = function(sources) {
let footprints = []; let footprints = [];
if (this._shapeIsFunction) { if (this._shapeIsFunction) {
for(const source of sources) { for(const source of sources) {
try { try {
let shape = this.shape(source) let shape = this.shape(source)
// convert simple shapes to footprints // convert simple shapes to footprints
if (shape instanceof Circle || shape instanceof Polyline || shape instanceof Ellipse || shape instanceof Line) { if (shape instanceof Circle || shape instanceof Polyline || shape instanceof Ellipse || shape instanceof Line) {
shape = new Footprint(shape, source); shape = new Footprint(shape, source);
} }
if (shape instanceof Footprint) { if (shape instanceof Footprint) {
let footprint = shape;
this._shapeIsFootprintFunction = true; this._shapeIsFootprintFunction = true;
footprint.setCatalog(this);
// store the footprints // store the footprints
footprints.push(shape); footprints.push(footprint);
} }
} catch(e) { } catch(e) {
// do not create the footprint // do not create the footprint
@@ -696,6 +699,8 @@ export let Catalog = (function() {
this.ra.splice(idx, 1); this.ra.splice(idx, 1);
this.dec.splice(idx, 1); this.dec.splice(idx, 1);
this.recomputeFootprints = true;
this.reportChange(); this.reportChange();
}; };
@@ -712,7 +717,7 @@ export let Catalog = (function() {
return; return;
} }
// tracé simple // tracé simple
ctx.strokeStyle= this.color; ctx.strokeStyle = this.color;
// Draw the footprints // Draw the footprints
this.drawFootprints(ctx); this.drawFootprints(ctx);
@@ -811,6 +816,11 @@ export let Catalog = (function() {
}; };
Catalog.prototype.drawFootprints = function(ctx) { Catalog.prototype.drawFootprints = function(ctx) {
if (this.recomputeFootprints) {
this.footprints = this.computeFootprints(this.sources);
this.recomputeFootprints = false;
}
for(let k = 0; k < this.footprints.length; k++) { for(let k = 0; k < this.footprints.length; k++) {
this.footprints[k].draw(ctx, this.view) this.footprints[k].draw(ctx, this.view)
}; };

View File

@@ -200,10 +200,18 @@ export let Ellipse = (function() {
// TODO // TODO
Ellipse.prototype.draw = function(ctx, view, noStroke) { Ellipse.prototype.draw = function(ctx, view, noStroke) {
if (! this.isShowing) { if (! this.isShowing) {
return; return;
} }
let px_per_deg = view.width / view.fov;
/*if (this.a * 2 * px_per_deg < this.lineWidth || this.b * 2 * px_per_deg < this.lineWidth) {
return;
}*/
var originScreen = view.aladin.world2pix(this.centerRaDec[0], this.centerRaDec[1]); var originScreen = view.aladin.world2pix(this.centerRaDec[0], this.centerRaDec[1]);
if (!originScreen) { if (!originScreen) {
// the center goes out of the projection // the center goes out of the projection
@@ -290,7 +298,7 @@ export let Ellipse = (function() {
ctx.lineWidth = this.lineWidth; ctx.lineWidth = this.lineWidth;
ctx.beginPath(); ctx.beginPath();
let px_per_deg = view.width / view.fov;
ctx.ellipse(originScreen[0], originScreen[1], px_per_deg * this.a, px_per_deg * this.b, theta, 0, 2*Math.PI, false); ctx.ellipse(originScreen[0], originScreen[1], px_per_deg * this.a, px_per_deg * this.b, theta, 0, 2*Math.PI, false);
if (!noStroke) { if (!noStroke) {
if (this.fillColor) { if (this.fillColor) {

View File

@@ -58,14 +58,17 @@ export let Footprint= (function() {
if (this.source) { if (this.source) {
this.source.setCatalog(catalog); this.source.setCatalog(catalog);
/* for (var s of this.shapes) {
// Take the color properties of the catalog if (!s.color) {
if (this.color === undefined) { s.setColor(catalog.color);
this.setColor(catalog.color); }
}*/ if (!s.selectionColor) {
s.setSelectionColor(catalog.selectionColor);
this.setSelectionColor(catalog.selectionColor); }
this.setHoverColor(catalog.hoverColor); if (!s.hoverColor) {
s.setHoverColor(catalog.hoverColor);
}
}
} }
}; };

View File

@@ -61,6 +61,11 @@ export let Line = (function() {
}; };
Line.prototype = { Line.prototype = {
setToPosition: function(ra2, dec2) {
this.ra2 = ra2;
this.dec2 = dec2;
},
setOverlay: Polyline.prototype.setOverlay, setOverlay: Polyline.prototype.setOverlay,
isFootprint: Polyline.prototype.isFootprint, isFootprint: Polyline.prototype.isFootprint,
show: Polyline.prototype.show, show: Polyline.prototype.show,

View File

@@ -249,7 +249,7 @@ export let Polyline = (function() {
} }
if (!this.lineWidth) { if (!this.lineWidth) {
this.lineWidth = this.overlay.lineWidth || 2; this.lineWidth = (this.overlay && this.overlay.lineWidth) || 2;
} }
if (this.isSelected) { if (this.isSelected) {

View File

@@ -210,12 +210,7 @@ export let ProgressiveCat = (function() {
newSource.setCatalog(instance); newSource.setCatalog(instance);
} }
let footprints = instance.parseFootprintsFromSources(sources); let footprints = instance.computeFootprints(sources);
footprints.forEach(f => {
f.setCatalog(instance);
})
sources = sources.filter((s) => s.hasFootprint !== true);
return [sources, footprints]; 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 reportChange: function() { // TODO: to be shared with Catalog
this.view && this.view.requestRedraw(); this.view && this.view.requestRedraw();

View File

@@ -310,17 +310,24 @@ Utils.getAjaxObject = function (url, method, dataType, useProxy) {
*/ */
Utils.fetch = function(params) { Utils.fetch = function(params) {
let url = new URL(params.url); let url;
if (params.useProxy === true) { try {
url = Utils.handleCORSNotSameOrigin(url) 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]);
} }
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, { let request = new Request(url, {
method: params.method || 'GET', method: params.method || 'GET',