mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2025-12-25 12:25:52 -08:00
Compare commits
17 Commits
3.5.1-beta
...
hips_cube
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60339e529a | ||
|
|
9bccdefcc5 | ||
|
|
16f978810f | ||
|
|
424c3cebba | ||
|
|
66326b59e4 | ||
|
|
7b80efa324 | ||
|
|
fd9a7b0de2 | ||
|
|
72d7e4e6bb | ||
|
|
186e634a86 | ||
|
|
5fd6bedeb9 | ||
|
|
6dd8ee2b85 | ||
|
|
a8c07137a4 | ||
|
|
7dc4a737ac | ||
|
|
a1b7b255bd | ||
|
|
1c3d6e90c9 | ||
|
|
ebb2172833 | ||
|
|
256e440ac5 |
@@ -1,14 +1,11 @@
|
||||
# Changelogs
|
||||
|
||||
## 3.5.1-beta
|
||||
## [Unreleased]
|
||||
|
||||
* [feat] Add support for name removing in `removeOverlay` method
|
||||
* [test] Add support of playwright. Instructions in the readme for running the test matching snapshots [PR #176]
|
||||
* [fix] Order of overlays in the stack now matches the addMOC/addCatalog/addOverlay calls ordering
|
||||
* [fixed] Order of overlays in the stack now matches the addMOC/addCatalog/addOverlay calls ordering
|
||||
* [doc] Expose the API of Coo class
|
||||
* [fix] Insert aladin css inside the aladin lite so that it should be compliant with the use of shadow DOMs [cds-astro/ipyaladin#113], [marimo-team/marimo#2106]
|
||||
* [feat] Add possibility of giving a local JS FileList to load a locally-stored HiPS without starting an HTTP server [cds-astro/aladin-lite#103]
|
||||
* [fix] removeOverlayByName
|
||||
|
||||
## 3.5.0-beta
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
"dateModified": "2023-01-31",
|
||||
"issueTracker": "https://github.com/cds-astro/aladin-lite/issues",
|
||||
"name": "Aladin Lite",
|
||||
"version": "3.5.1-beta",
|
||||
"softwareVersion": "3.5.1-beta",
|
||||
"version": "3.5.0-beta",
|
||||
"softwareVersion": "3.5.0-beta",
|
||||
"description": "An astronomical HiPS visualizer in the browser.",
|
||||
"identifier": "10.5281/zenodo.7638833",
|
||||
"applicationCategory": "Astronomy, Visualization",
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="shadow-host"></div>
|
||||
|
||||
<script type="text/javascript" src="./../dist/aladin.umd.cjs" charset="utf-8"></script>
|
||||
<script type="text/javascript">
|
||||
const shadowEl = document.querySelector(".shadow-host");
|
||||
const shadow = shadowEl.attachShadow({mode: 'open'});
|
||||
|
||||
let aladinLiteEl = document.createElement('div');
|
||||
aladinLiteEl.id = "aladin-lite-div"
|
||||
aladinLiteEl.style = "width: 768px; height: 512px";
|
||||
shadow.appendChild(aladinLiteEl)
|
||||
|
||||
A.init.then(() => {
|
||||
let aladin = A.aladin(
|
||||
aladinLiteEl,
|
||||
{
|
||||
survey: 'P/allWISE/color', // set initial image survey
|
||||
projection: 'AIT', // set a projection
|
||||
fov: 1.5, // initial field of view in degrees
|
||||
target: 'orion', // initial target
|
||||
}
|
||||
);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -13,7 +13,6 @@
|
||||
aladin = A.aladin(
|
||||
'#aladin-lite-div',
|
||||
{
|
||||
showSimbadPointerControl: true,
|
||||
survey: 'P/allWISE/color', // set initial image survey
|
||||
projection: 'AIT', // set a projection
|
||||
fov: 1.5, // initial field of view in degrees
|
||||
@@ -31,14 +30,7 @@
|
||||
}
|
||||
);
|
||||
|
||||
/*let id;
|
||||
aladin.on("zoomChanged", () => {
|
||||
if (id)
|
||||
clearTimeout(id);
|
||||
id = setTimeout(() => {
|
||||
console.log("wheel stopped, new cone search here")
|
||||
}, 500);
|
||||
})*/
|
||||
//aladin.removeHiPSFromFavorites('CDS/P/allWISE/color')
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
|
||||
@@ -11,17 +11,10 @@
|
||||
|
||||
A.init.then(() => {
|
||||
let vertices = A.Utils.HEALPix.vertices(Math.pow(2, 3), BigInt(276))
|
||||
let lonlat = A.Utils.HEALPix.pix2ang(8, 0n)
|
||||
let ipix = A.Utils.HEALPix.ang2pix(8, 0.1, 0.4)
|
||||
console.log("vertices", vertices, lonlat, ipix)
|
||||
|
||||
A.Utils.Sesame.resolveAstronomicalName("M101", (o) => {
|
||||
console.log("object found", o)
|
||||
},
|
||||
(err) => {
|
||||
console.error("errr", err)
|
||||
}
|
||||
)
|
||||
//let lonlat = A.Utils.HEALPix.pix2ang(8, 0n)
|
||||
//let ipix = A.Utils.HEALPix.ang2pix(8, 0.1, 0.4)
|
||||
//console.log("vertices", vertices, lonlat, ipix)
|
||||
console.log(vertices)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
"module": "./dist/aladin.js",
|
||||
"main": "./dist/aladin.js",
|
||||
"files": [
|
||||
"dist/aladin.js"
|
||||
"dist/aladin.js",
|
||||
"dist/aladin.umd.cjs",
|
||||
"dist/index.html"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
@@ -34,8 +36,8 @@
|
||||
"wasm:dbg": "wasm-pack build --dev ./src/core --target web --out-name core -- --features=webgl2,dbg -Z build-std=panic_abort,std -Z build-std-features=panic_immediate_abort ",
|
||||
"predeploy": "npm run build && rm -rf aladin-lite*.tgz && npm pack",
|
||||
"deploy": "python3 deploy/deploy.py",
|
||||
"build": "npm run wasm && vite build",
|
||||
"build:dbg": "npm run wasm:dbg && vite build",
|
||||
"build": "npm run wasm && vite build && cp examples/index.html dist/index.html",
|
||||
"build:dbg": "npm run wasm:dbg && vite build && cp examples/index.html dist/index.html",
|
||||
"dev": "npm run build && vite",
|
||||
"dev:dbg": "npm run build:dbg && vite",
|
||||
"serve": "npm run dev",
|
||||
@@ -51,6 +53,7 @@
|
||||
"@playwright/test": "^1.47.0",
|
||||
"jsdoc": "^4.0.2",
|
||||
"vite": "^4.3.8",
|
||||
"vite-plugin-css-injected-by-js": "^3.1.1",
|
||||
"vite-plugin-glsl": "^1.1.2",
|
||||
"vite-plugin-top-level-await": "^1.4.1",
|
||||
"vite-plugin-wasm": "^3.2.2",
|
||||
|
||||
@@ -3,7 +3,7 @@ name = "aladin-lite"
|
||||
description = "Aladin Lite v3 introduces a new graphical engine written in Rust with the use of WebGL"
|
||||
license = "BSD-3-Clause"
|
||||
repository = "https://github.com/cds-astro/aladin-lite"
|
||||
version = "3.5.1-beta"
|
||||
version = "3.5.0-beta"
|
||||
authors = [ "baumannmatthieu0@gmail.com", "matthieu.baumann@astro.unistra.fr",]
|
||||
edition = "2018"
|
||||
|
||||
@@ -70,7 +70,7 @@ path = "./al-api"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "*"
|
||||
features = [ "console", "CssStyleDeclaration", "Document", "Element", "HtmlCollection", "HtmlElement", "HtmlImageElement", "HtmlCanvasElement", "Blob", "ImageBitmap", "ImageData", "CanvasRenderingContext2d", "WebGlBuffer", "WebGlContextAttributes", "WebGlFramebuffer", "WebGlProgram", "WebGlShader", "WebGlUniformLocation", "WebGlTexture", "WebGlActiveInfo", "Headers", "Window", "Request", "RequestInit", "RequestMode", "Response", "XmlHttpRequest", "XmlHttpRequestResponseType", "PerformanceTiming", "Performance", "Url", "ReadableStream", "File", "FileList",]
|
||||
features = [ "console", "CssStyleDeclaration", "Document", "Element", "HtmlCollection", "HtmlElement", "HtmlImageElement", "HtmlCanvasElement", "Blob", "ImageBitmap", "ImageData", "CanvasRenderingContext2d", "WebGlBuffer", "WebGlContextAttributes", "WebGlFramebuffer", "WebGlProgram", "WebGlShader", "WebGlUniformLocation", "WebGlTexture", "WebGlActiveInfo", "Headers", "Window", "Request", "RequestInit", "RequestMode", "Response", "XmlHttpRequest", "XmlHttpRequestResponseType", "PerformanceTiming", "Performance", "Url", "ReadableStream",]
|
||||
|
||||
[dev-dependencies.image-decoder]
|
||||
package = "image"
|
||||
|
||||
@@ -61,8 +61,6 @@ features = [
|
||||
'PerformanceTiming',
|
||||
'Performance',
|
||||
'Url',
|
||||
'File',
|
||||
'FileList'
|
||||
]
|
||||
|
||||
[profile.dev]
|
||||
|
||||
@@ -73,8 +73,6 @@ features = [
|
||||
'PerformanceTiming',
|
||||
'Performance',
|
||||
'Url',
|
||||
'File',
|
||||
'FileList'
|
||||
]
|
||||
|
||||
[profile.dev]
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::renderable::ImageLayer;
|
||||
use crate::tile_fetcher::HiPSLocalFiles;
|
||||
use crate::{
|
||||
//async_task::{BuildCatalogIndex, ParseTableTask, TaskExecutor, TaskResult, TaskType},
|
||||
camera::CameraViewPort,
|
||||
@@ -303,6 +302,16 @@ impl App {
|
||||
ancestors.insert(ancestor_tile_cell);
|
||||
}
|
||||
}
|
||||
//let ancestor_next_tile_cell = next_tile_cell.ancestor(3);
|
||||
//if !survey.contains_tile(&ancestor_tile_cell) {
|
||||
//self.tile_fetcher.append(
|
||||
// query::Tile::new(&ancestor_tile_cell, hips_url.clone(), format),
|
||||
// &mut self.downloader,
|
||||
//);
|
||||
//}
|
||||
//if ancestor_tile_cell != ancestor_next_tile_cell {
|
||||
|
||||
//}
|
||||
}
|
||||
}
|
||||
// Request for ancestor
|
||||
@@ -796,12 +805,8 @@ impl App {
|
||||
// Check for async retrieval
|
||||
if let Ok(img) = self.img_recv.try_recv() {
|
||||
let params = img.get_params();
|
||||
self.layers.add_image(
|
||||
img,
|
||||
&mut self.camera,
|
||||
&self.projection,
|
||||
&mut self.tile_fetcher,
|
||||
)?;
|
||||
self.layers
|
||||
.add_image(img, &mut self.camera, &self.projection)?;
|
||||
self.request_redraw = true;
|
||||
|
||||
// Send the ack to the js promise so that she finished
|
||||
@@ -953,12 +958,8 @@ impl App {
|
||||
}
|
||||
|
||||
pub(crate) fn remove_layer(&mut self, layer: &str) -> Result<(), JsValue> {
|
||||
self.layers.remove_layer(
|
||||
layer,
|
||||
&mut self.camera,
|
||||
&self.projection,
|
||||
&mut self.tile_fetcher,
|
||||
)?;
|
||||
self.layers
|
||||
.remove_layer(layer, &mut self.camera, &self.projection)?;
|
||||
|
||||
self.request_redraw = true;
|
||||
|
||||
@@ -981,31 +982,17 @@ impl App {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn add_image_hips(
|
||||
&mut self,
|
||||
hips_cfg: HiPSCfg,
|
||||
local_files: Option<HiPSLocalFiles>,
|
||||
) -> Result<(), JsValue> {
|
||||
let cdid = hips_cfg.properties.get_creator_did().to_string();
|
||||
|
||||
let hips = self.layers.add_image_hips(
|
||||
&self.gl,
|
||||
hips_cfg,
|
||||
&mut self.camera,
|
||||
&self.projection,
|
||||
&mut self.tile_fetcher,
|
||||
)?;
|
||||
|
||||
if let Some(local_files) = local_files {
|
||||
self.tile_fetcher.insert_hips_local_files(cdid, local_files);
|
||||
}
|
||||
|
||||
pub(crate) fn add_image_hips(&mut self, hips_cfg: HiPSCfg) -> Result<(), JsValue> {
|
||||
let hips =
|
||||
self.layers
|
||||
.add_image_hips(&self.gl, hips_cfg, &mut self.camera, &self.projection)?;
|
||||
self.tile_fetcher
|
||||
.launch_starting_hips_requests(hips, self.downloader.clone());
|
||||
|
||||
// Once its added, request the tiles in the view (unless the viewer is at depth 0)
|
||||
self.request_for_new_tiles = true;
|
||||
self.request_redraw = true;
|
||||
//self.grid.update(&self.camera, &self.projection);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -87,7 +87,6 @@ use math::projection::*;
|
||||
|
||||
use moclib::moc::RangeMOCIntoIterator;
|
||||
//use votable::votable::VOTableWrapper;
|
||||
use crate::tile_fetcher::HiPSLocalFiles;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use web_sys::HtmlElement;
|
||||
|
||||
@@ -161,7 +160,11 @@ impl WebClient {
|
||||
/// * `shaders` - The list of shader objects containing the GLSL code source
|
||||
/// * `resources` - Image resource files
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(aladin_div: &HtmlElement, resources: JsValue) -> Result<WebClient, JsValue> {
|
||||
pub fn new(
|
||||
aladin_div: &HtmlElement,
|
||||
//_shaders: JsValue,
|
||||
resources: JsValue,
|
||||
) -> Result<WebClient, JsValue> {
|
||||
#[cfg(feature = "dbg")]
|
||||
panic::set_hook(Box::new(console_error_panic_hook::hook));
|
||||
|
||||
@@ -368,14 +371,10 @@ impl WebClient {
|
||||
/// of WebGL2 texture units on some architectures, the total number of surveys rendered is
|
||||
/// limited to 4.
|
||||
#[wasm_bindgen(js_name = addHiPS)]
|
||||
pub fn add_image_hips(
|
||||
&mut self,
|
||||
hips: JsValue,
|
||||
files: Option<HiPSLocalFiles>,
|
||||
) -> Result<(), JsValue> {
|
||||
pub fn add_image_hips(&mut self, hips: JsValue) -> Result<(), JsValue> {
|
||||
// Deserialize the survey objects that compose the survey
|
||||
let hips = serde_wasm_bindgen::from_value(hips)?;
|
||||
self.app.add_image_hips(hips, files)?;
|
||||
self.app.add_image_hips(hips)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1033,7 +1032,7 @@ impl WebClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = addFITSMOC)]
|
||||
#[wasm_bindgen(js_name = addFITSMoc)]
|
||||
pub fn add_fits_moc(&mut self, params: &al_api::moc::MOC, data: &[u8]) -> Result<(), JsValue> {
|
||||
//let bytes = js_sys::Uint8Array::new(array_buffer).to_vec();
|
||||
let moc = match fits::from_fits_ivoa_custom(Cursor::new(&data[..]), false)
|
||||
|
||||
@@ -10,7 +10,6 @@ pub mod text;
|
||||
pub mod utils;
|
||||
|
||||
use crate::renderable::image::Image;
|
||||
use crate::tile_fetcher::TileFetcherQueue;
|
||||
|
||||
use al_core::image::format::ChannelType;
|
||||
|
||||
@@ -317,7 +316,6 @@ impl Layers {
|
||||
layer: &str,
|
||||
camera: &mut CameraViewPort,
|
||||
proj: &ProjectionType,
|
||||
tile_fetcher: &mut TileFetcherQueue,
|
||||
) -> Result<usize, JsValue> {
|
||||
let err_layer_not_found = JsValue::from_str(&format!(
|
||||
"Layer {:?} not found, so cannot be removed.",
|
||||
@@ -353,9 +351,6 @@ impl Layers {
|
||||
// remove the frame
|
||||
camera.unregister_view_frame(hips_frame, proj);
|
||||
|
||||
// remove the local files access from the tile fetcher
|
||||
tile_fetcher.delete_hips_local_files(s.get_config().get_creator_did());
|
||||
|
||||
Ok(id_layer)
|
||||
} else if let Some(_) = self.images.remove(&id) {
|
||||
// A FITS image has been found and removed
|
||||
@@ -423,7 +418,6 @@ impl Layers {
|
||||
hips: HiPSCfg,
|
||||
camera: &mut CameraViewPort,
|
||||
proj: &ProjectionType,
|
||||
tile_fetcher: &mut TileFetcherQueue,
|
||||
) -> Result<&HiPS, JsValue> {
|
||||
let HiPSCfg {
|
||||
layer,
|
||||
@@ -437,7 +431,7 @@ impl Layers {
|
||||
let layer_already_found = self.layers.iter().any(|l| l == &layer);
|
||||
|
||||
let idx = if layer_already_found {
|
||||
let idx = self.remove_layer(&layer, camera, proj, tile_fetcher)?;
|
||||
let idx = self.remove_layer(&layer, camera, proj)?;
|
||||
idx
|
||||
} else {
|
||||
self.layers.len()
|
||||
@@ -498,7 +492,6 @@ impl Layers {
|
||||
image: ImageLayer,
|
||||
camera: &mut CameraViewPort,
|
||||
proj: &ProjectionType,
|
||||
tile_fetcher: &mut TileFetcherQueue,
|
||||
) -> Result<&[Image], JsValue> {
|
||||
let ImageLayer {
|
||||
layer,
|
||||
@@ -511,7 +504,7 @@ impl Layers {
|
||||
let layer_already_found = self.layers.iter().any(|s| s == &layer);
|
||||
|
||||
let idx = if layer_already_found {
|
||||
let idx = self.remove_layer(&layer, camera, proj, tile_fetcher)?;
|
||||
let idx = self.remove_layer(&layer, camera, proj)?;
|
||||
idx
|
||||
} else {
|
||||
self.layers.len()
|
||||
|
||||
@@ -27,7 +27,6 @@ impl<const N: usize> BitVector<N> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::BitVector;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::time::{DeltaTime, Time};
|
||||
use crate::Abort;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
|
||||
const MAX_NUM_TILE_FETCHING: usize = 8;
|
||||
@@ -16,68 +16,25 @@ pub struct TileFetcherQueue {
|
||||
base_tile_queries: Vec<query::Tile>,
|
||||
tiles_fetched_time: Time,
|
||||
num_tiles_fetched: usize,
|
||||
|
||||
hips_local_files: HashMap<CreatorDid, HiPSLocalFiles>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[wasm_bindgen]
|
||||
pub struct HiPSLocalFiles {
|
||||
paths: Box<[HashMap<u64, web_sys::File>]>,
|
||||
}
|
||||
|
||||
use crate::tile_fetcher::query::Tile;
|
||||
use crate::HEALPixCell;
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl HiPSLocalFiles {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
let paths = vec![HashMap::new(); 30].into_boxed_slice();
|
||||
|
||||
Self { paths }
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, depth: u8, ipix: u64, file: web_sys::File) {
|
||||
self.paths[depth as usize].insert(ipix, file);
|
||||
}
|
||||
|
||||
fn get(&self, cell: &HEALPixCell) -> Option<&web_sys::File> {
|
||||
let d = cell.depth() as usize;
|
||||
let i = cell.idx();
|
||||
|
||||
return self.paths[d].get(&i);
|
||||
}
|
||||
}
|
||||
use crate::renderable::CreatorDid;
|
||||
impl TileFetcherQueue {
|
||||
pub fn new() -> Self {
|
||||
let queries = VecDeque::new();
|
||||
let base_tile_queries = Vec::new();
|
||||
let tiles_fetched_time = Time::now();
|
||||
let num_tiles_fetched = 0;
|
||||
|
||||
Self {
|
||||
queries,
|
||||
base_tile_queries,
|
||||
tiles_fetched_time,
|
||||
num_tiles_fetched,
|
||||
hips_local_files: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_hips_local_files(&mut self, id: CreatorDid, local_files: HiPSLocalFiles) {
|
||||
self.hips_local_files.insert(id, local_files);
|
||||
}
|
||||
|
||||
pub fn delete_hips_local_files(&mut self, id: &str) {
|
||||
self.hips_local_files.remove(id);
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.queries.clear();
|
||||
//self.query_set.clear();
|
||||
}
|
||||
|
||||
pub fn append(&mut self, query: query::Tile) {
|
||||
@@ -115,41 +72,23 @@ impl TileFetcherQueue {
|
||||
self.num_tiles_fetched
|
||||
}
|
||||
|
||||
fn check_in_file_list(&self, mut query: Tile) -> Result<Tile, JsValue> {
|
||||
if let Some(files) = self.hips_local_files.get(&query.hips_cdid) {
|
||||
if let Some(file) = files.get(&query.cell) {
|
||||
if let Ok(url) = web_sys::Url::create_object_url_with_blob(file.as_ref()) {
|
||||
// rewrite the url
|
||||
query.url = url;
|
||||
Ok(query)
|
||||
} else {
|
||||
Err(JsValue::from_str("could not create an url from the tile"))
|
||||
}
|
||||
} else {
|
||||
Ok(query)
|
||||
}
|
||||
} else {
|
||||
Ok(query)
|
||||
}
|
||||
}
|
||||
|
||||
fn fetch(&mut self, downloader: Rc<RefCell<Downloader>>) {
|
||||
// Fetch the base tiles with higher priority
|
||||
while let Some(query) = self.base_tile_queries.pop() {
|
||||
if let Ok(query) = self.check_in_file_list(query) {
|
||||
downloader.borrow_mut().fetch(query);
|
||||
}
|
||||
//if downloader.fetch(query) {
|
||||
// The fetch has succeded
|
||||
//self.num_tiles_fetched += 1;
|
||||
//}
|
||||
downloader.borrow_mut().fetch(query);
|
||||
}
|
||||
|
||||
let mut num_fetched_tile = 0;
|
||||
while num_fetched_tile < MAX_NUM_TILE_FETCHING && !self.queries.is_empty() {
|
||||
let query = self.queries.pop_back().unwrap_abort();
|
||||
|
||||
if let Ok(query) = self.check_in_file_list(query) {
|
||||
if downloader.borrow_mut().fetch(query) {
|
||||
// The fetch has succeded
|
||||
num_fetched_tile += 1;
|
||||
}
|
||||
if downloader.borrow_mut().fetch(query) {
|
||||
// The fetch has succeded
|
||||
num_fetched_tile += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,23 +124,20 @@ impl TileFetcherQueue {
|
||||
let hips_fmt = cfg.get_format();
|
||||
let min_order = cfg.get_min_depth_texture();
|
||||
|
||||
for tile_cell in crate::healpix::cell::ALLSKY_HPX_CELLS_D0 {
|
||||
if let Ok(query) = self.check_in_file_list(query::Tile::new(
|
||||
tile_cell,
|
||||
hips_cdid.clone(),
|
||||
hips_url.clone(),
|
||||
hips_fmt,
|
||||
)) {
|
||||
let dl = downloader.clone();
|
||||
|
||||
crate::utils::set_timeout(
|
||||
move || {
|
||||
dl.borrow_mut().fetch(query);
|
||||
},
|
||||
2_000,
|
||||
);
|
||||
}
|
||||
}
|
||||
let dl = downloader.clone();
|
||||
crate::utils::set_timeout(
|
||||
move || {
|
||||
for tile_cell in crate::healpix::cell::ALLSKY_HPX_CELLS_D0 {
|
||||
dl.borrow_mut().fetch(query::Tile::new(
|
||||
tile_cell,
|
||||
hips_cdid.clone(),
|
||||
hips_url.clone(),
|
||||
hips_fmt,
|
||||
));
|
||||
}
|
||||
},
|
||||
2_000,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
57
src/js/A.js
57
src/js/A.js
@@ -51,7 +51,8 @@ import { Sesame } from "./Sesame.js";
|
||||
import init, * as module from './../core/pkg';
|
||||
|
||||
// Import aladin css inside the project
|
||||
import aladinCSS from './../css/aladin.css?inline';
|
||||
import './../css/aladin.css';
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
/////// Aladin Lite API ///////
|
||||
@@ -96,32 +97,17 @@ A.aladin = function (divSelector, options) {
|
||||
} else {
|
||||
divElement = divSelector;
|
||||
}
|
||||
|
||||
// Associate the CSS inside the div
|
||||
var cssStyleSheet = document.createElement('style')
|
||||
cssStyleSheet.classList.add("aladin-css");
|
||||
cssStyleSheet.innerHTML = aladinCSS;
|
||||
divElement.appendChild(cssStyleSheet)
|
||||
|
||||
return new Aladin(divElement, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a HiPS image object
|
||||
*
|
||||
* @function
|
||||
* @name A.HiPS
|
||||
* @name A.imageHiPS
|
||||
* @memberof A
|
||||
* @param {string|FileList|Object} id - Can be: <br/>
|
||||
* - an http url <br/>
|
||||
* - a relative path to your HiPS <br/>
|
||||
* - a special ID pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here} <br/>
|
||||
* - a dict storing a local HiPS files. This object contains a tile file: hips[order][ipix] = File and refers to the properties file like so: hips["properties"] = File. <br/>
|
||||
* A javascript FileList pointing to the opened webkit directory is also accepted.
|
||||
* @param {HiPSOptions} [options] - Options describing the survey
|
||||
* @returns {HiPS} - A HiPS image object
|
||||
* @deprecated
|
||||
* Old method name, use {@link A.HiPS} instead.
|
||||
*/
|
||||
A.HiPS = function (id, options) {
|
||||
A.imageHiPS = function (id, options) {
|
||||
let url = id;
|
||||
return Aladin.createImageSurvey(
|
||||
id,
|
||||
@@ -134,13 +120,17 @@ A.HiPS = function (id, options) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a HiPS image object
|
||||
*
|
||||
* @function
|
||||
* @name A.imageHiPS
|
||||
* @name A.HiPS
|
||||
* @memberof A
|
||||
* @deprecated
|
||||
* Old method name, use {@link A.HiPS} instead.
|
||||
* @param {string} id - Can be either an `url` that refers to a HiPS.
|
||||
* Or it can be a "CDS ID" pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}.
|
||||
* @param {HiPSOptions} [options] - Options describing the survey
|
||||
* @returns {HiPS} - A HiPS image object
|
||||
*/
|
||||
A.imageHiPS = A.HiPS;
|
||||
A.HiPS = A.imageHiPS;
|
||||
|
||||
/**
|
||||
* Creates a celestial source object with the given coordinates.
|
||||
@@ -453,19 +443,17 @@ A.MOCFromURL = function (url, options, successCallback, errorCallback) {
|
||||
* @returns {MOC} Returns a new MOC object
|
||||
*
|
||||
* @example
|
||||
* var json = {
|
||||
* "3": [517],
|
||||
* "4": [2065,2066,2067,2112,2344,2346,2432],
|
||||
* "5": [8221,8257,8258,8259,8293,8304,8305,8307,8308,8452,8456,9346,9352,9354,9736],
|
||||
* "6": [32861,32862,32863,32881,32882,32883,32892,32893,33025,33026,33027,33157,33168,33169,33171,
|
||||
* var json = {"3":[517],
|
||||
* "4":[2065,2066,2067,2112,2344,2346,2432],
|
||||
* "5":[8221,8257,8258,8259,8293,8304,8305,8307,8308,8452,8456,9346,9352,9354,9736],
|
||||
* "6":[32861,32862,32863,32881,32882,32883,32892,32893,33025,33026,33027,33157,33168,33169,33171,
|
||||
* 33181,33224,33225,33227,33236,33240,33812,33816,33828,33832,37377,37378,37379,37382,37388,
|
||||
* 37390,37412,37414,37420,37422,37562,38928,38930,38936,38948,38952],
|
||||
* "7": [131423,131439,131443,131523,131556,131557,131580,131581,132099,132612,132613,132624,132625,132627,132637,
|
||||
* "7":[131423,131439,131443,131523,131556,131557,131580,131581,132099,132612,132613,132624,132625,132627,132637,
|
||||
* 132680,132681,132683,132709,132720,132721,132904,132905,132948,132952,132964,132968,133008,133009,133012,135252,135256,135268,135316,135320,135332,135336,148143,148152,148154,149507,149520
|
||||
* ,149522,149523,149652,149654,149660,149662,149684,149686,149692,149694,149695,150120,150122,150208,150210,150216,150218,150240,150242,150243,155748,155752,155796,155800,155812,155816]
|
||||
* };
|
||||
* ,149522,149523,149652,149654,149660,149662,149684,149686,149692,149694,149695,150120,150122,150208,150210,150216,150218,150240,150242,150243,155748,155752,155796,155800,155812,155816]};
|
||||
* var moc = A.MOCFromJSON(json, {opacity: 0.25, color: 'magenta', lineWidth: 3});
|
||||
* aladin.addMOC(moc);
|
||||
* aladin.addMOC(moc);
|
||||
*/
|
||||
A.MOCFromJSON = function (jsonMOC, options, successCallback, errorCallback) {
|
||||
var moc = new MOC(options);
|
||||
@@ -824,7 +812,6 @@ A.catalogFromSKAORucio = function (target, radiusDegrees, options, successCallba
|
||||
*
|
||||
* @example
|
||||
* const cat = A.catalogFromVizieR('I/311/hip2', 'M 45', 5, {onClick: 'showTable'});
|
||||
* const cat2 = A.catalogFromVizieR('I/311/hip2', '12 +9', 5, {onClick: 'showTable'});
|
||||
*/
|
||||
A.catalogFromVizieR = function (vizCatId, target, radius, options, successCallback, errorCallback) {
|
||||
options = options || {};
|
||||
@@ -992,7 +979,7 @@ A.box = function(options) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Utils object.
|
||||
* Returns utils object
|
||||
*
|
||||
* This contains utilitary methods such as HEALPix basic or projection methods.
|
||||
*
|
||||
|
||||
@@ -1462,7 +1462,7 @@ export let Aladin = (function () {
|
||||
* @memberof Aladin
|
||||
*/
|
||||
Aladin.prototype.removeOverlays = function () {
|
||||
this.view.removeOverlays();
|
||||
this.view.removeLayers();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1471,10 +1471,10 @@ export let Aladin = (function () {
|
||||
* @memberof Aladin
|
||||
*/
|
||||
Aladin.prototype.removeLayers = Aladin.prototype.removeOverlays;
|
||||
/**
|
||||
* @typedef {MOC|Catalog|ProgressiveCat|GraphicOverlay} Overlay
|
||||
* @description Possible overlays
|
||||
*/
|
||||
/**
|
||||
* @typedef {MOC|Catalog|ProgressiveCat|GraphicOverlay} Overlay
|
||||
* @description Possible overlays
|
||||
*/
|
||||
/**
|
||||
* Remove an overlay by its layer name
|
||||
*
|
||||
@@ -1482,11 +1482,10 @@ export let Aladin = (function () {
|
||||
* @param {string|Overlay} overlay - The name of the overlay to remove or the overlay object itself
|
||||
*/
|
||||
Aladin.prototype.removeOverlay = function (overlay) {
|
||||
if(typeof overlay === 'string' || overlay instanceof String) {
|
||||
if(overlay instanceof String)
|
||||
this.view.removeOverlayByName(overlay);
|
||||
} else {
|
||||
else
|
||||
this.view.removeOverlay(overlay);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1497,6 +1496,10 @@ export let Aladin = (function () {
|
||||
Aladin.prototype.removeLayer = Aladin.prototype.removeOverlay;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Creates and return an image survey (HiPS) object
|
||||
* Please use {@link A.hiPS} instead for creating a new survey image
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string} id - Mandatory unique identifier for the survey.
|
||||
* @param {string} [name] - A convinient name for the survey, optional
|
||||
@@ -1529,6 +1532,10 @@ export let Aladin = (function () {
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Creates and return an image survey (HiPS) object.
|
||||
* Please use {@link A.hiPS} instead for creating a new survey image
|
||||
*
|
||||
* @function createImageSurvey
|
||||
* @memberof Aladin
|
||||
* @static
|
||||
@@ -1647,6 +1654,7 @@ export let Aladin = (function () {
|
||||
* Please use {@link A.hiPS} instead for creating a new survey image
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @static
|
||||
* @param {string} id - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
@@ -1659,8 +1667,7 @@ export let Aladin = (function () {
|
||||
*/
|
||||
Aladin.prototype.newImageSurvey = function (id, options) {
|
||||
// a wrapper on createImageSurvey that aggregates all params in an options object
|
||||
return this.createImageSurvey(
|
||||
id,
|
||||
return this.createImageSurvey(id,
|
||||
options && options.name,
|
||||
id,
|
||||
options && options.cooFrame,
|
||||
@@ -1741,29 +1748,11 @@ export let Aladin = (function () {
|
||||
return this.backgroundColor;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove an image layer/overlay from the instance
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string|Overlay} item - the overlay object or image layer name to remove
|
||||
*/
|
||||
Aladin.prototype.remove = function (item) {
|
||||
const layers = this.getStackLayers()
|
||||
let idxToDelete = layers.findIndex(l => l === item);
|
||||
if (idxToDelete >= 0) {
|
||||
this.view.removeImageLayer(item);
|
||||
return;
|
||||
}
|
||||
|
||||
// must be an overlay
|
||||
this.view.removeOverlay(item)
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a specific layer
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string} layer - The name of the layer to remove or the HiPS/Image object
|
||||
* @param {string} layer - The name of the layer to remove
|
||||
*/
|
||||
Aladin.prototype.removeImageLayer = function (layer) {
|
||||
this.view.removeImageLayer(layer);
|
||||
@@ -1804,7 +1793,7 @@ export let Aladin = (function () {
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>2. Or it can be a CDS ID that refers to a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>3. A {@link HiPS} HiPS object created from {@link A.HiPS}</li>
|
||||
* <li>4. A {@link Image} FITS/jpeg/png image</li>
|
||||
* <li>4. A {@link Image} FITS/jped/png image</li>
|
||||
* </ul>
|
||||
* @param {string} [layer="overlay"] - A layer name. By default 'overlay' is chosen and it is destined to be plot
|
||||
* on top the 'base' layer. If the layer is already present in the view, it will be replaced by the new HiPS/FITS image given here.
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
*
|
||||
*****************************************************************************/
|
||||
import { Aladin } from "./Aladin";
|
||||
import { Sesame } from "./Sesame";
|
||||
|
||||
/**
|
||||
* @namespace AladinUtils
|
||||
@@ -146,28 +145,6 @@ export let AladinUtils = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @namespace Sesame
|
||||
* @memberof AladinUtils
|
||||
* @description Namespace for Sesame related service.
|
||||
*/
|
||||
Sesame: {
|
||||
/**
|
||||
* find RA, DEC for any target (object name or position) <br/>
|
||||
* if successful, callback is called with an object {ra: ra-value, dec: dec-value} <br/>
|
||||
* if not successful, errorCallback is called
|
||||
*
|
||||
* @function
|
||||
* @memberof AladinUtils.Sesame
|
||||
* @name resolveAstronomicalName
|
||||
*
|
||||
* @param {string} target - object name or position
|
||||
* @param {Function} callback - if successful, callback is called with an object {ra: <ra-value>, dec: <dec-value>}
|
||||
* @param {Function} errorCallback - if not successful, errorCallback is called
|
||||
*/
|
||||
resolveAstronomicalName: Sesame.getTargetRADec
|
||||
},
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
|
||||
@@ -47,7 +47,7 @@ import { Footprint } from "./Footprint.js";
|
||||
* @property {string} [name="catalog"] - The name of the catalog.
|
||||
* @property {string} [color] - The color associated with the catalog.
|
||||
* @property {number} [sourceSize=8] - The size of the sources in the catalog.
|
||||
* @property {string|Function|Image|HTMLCanvasElement|HTMLImageElement} [shape="square"] - The shape of the sources (can be, "square", "circle", "plus", "cross", "rhomb", "triangle").
|
||||
* @property {string|function|Image|HTMLCanvasElement} [shape="square"] - The shape of the sources (can be, "square", "circle", "plus", "cross", "rhomb", "triangle").
|
||||
* @property {number} [limit] - The maximum number of sources to display.
|
||||
* @property {string|Function} [onClick] - Whether the source data appears as a table row or a in popup. Can be 'showTable' string, 'showPopup' string or a custom user defined function that handles the click.
|
||||
* @property {boolean} [readOnly=false] - Whether the catalog is read-only.
|
||||
@@ -79,9 +79,7 @@ export let Catalog = (function () {
|
||||
* markerSize: 15,
|
||||
* shape: "circle",
|
||||
* limit: 1000,
|
||||
* onClick: (source) => {
|
||||
* // handle sources
|
||||
* },
|
||||
* onClick: (source) => { /* handle source click * },
|
||||
* readOnly: true,
|
||||
* raField: "ra",
|
||||
* decField: "dec",
|
||||
@@ -481,17 +479,7 @@ export let Catalog = (function () {
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the shape of the sources
|
||||
*
|
||||
* @memberof Catalog
|
||||
*
|
||||
* @param {Object} [options] - shape options
|
||||
* @param {string} [options.color] - the color of the shape
|
||||
* @param {number} [options.sourceSize] - size of the shape
|
||||
* @param {string|Function|HTMLImageCanvas|HTMLImageElement} [options.shape="square"] - the type of the shape. Can be square, rhomb, plus, cross, triangle, circle.
|
||||
* A callback function can also be called that return an HTMLImageElement in function of the source object. A canvas or an image can also be given.
|
||||
*/
|
||||
// API
|
||||
Catalog.prototype.updateShape = function (options) {
|
||||
options = options || {};
|
||||
this.color = options.color || this.color || Color.getNextColor();
|
||||
@@ -536,13 +524,7 @@ export let Catalog = (function () {
|
||||
this.reportChange();
|
||||
};
|
||||
|
||||
/**
|
||||
* Add sources to the catalog
|
||||
*
|
||||
* @memberof Catalog
|
||||
*
|
||||
* @param {Source[]} sources - An array of sources or only one source to add
|
||||
*/
|
||||
// API
|
||||
Catalog.prototype.addSources = function (sources) {
|
||||
// make sure we have an array and not an individual source
|
||||
sources = [].concat(sources);
|
||||
@@ -577,6 +559,17 @@ export let Catalog = (function () {
|
||||
this.reportChange();
|
||||
};
|
||||
|
||||
/*Catalog.prototype.addFootprints = function(footprintsToAdd) {
|
||||
footprintsToAdd = [].concat(footprintsToAdd); // make sure we have an array and not an individual footprints
|
||||
this.footprints = this.footprints.concat(footprintsToAdd);
|
||||
|
||||
footprintsToAdd.forEach(f => {
|
||||
f.setCatalog(this);
|
||||
})
|
||||
|
||||
this.reportChange();
|
||||
};*/
|
||||
|
||||
Catalog.prototype.computeFootprints = function (sources) {
|
||||
let footprints = [];
|
||||
|
||||
@@ -626,14 +619,12 @@ export let Catalog = (function () {
|
||||
this.showFieldCallback[field] = callback;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create sources from a 2d array and add them to the catalog
|
||||
*
|
||||
* @memberof Catalog
|
||||
*
|
||||
* @param {String[]} columnNames - array with names of the columns
|
||||
* @param {String[][]|number[][]} array - 2D-array, each item being a 1d-array with the same number of items as columnNames
|
||||
*/
|
||||
// API
|
||||
//
|
||||
// create sources from a 2d array and add them to the catalog
|
||||
//
|
||||
// @param columnNames: array with names of the columns
|
||||
// @array: 2D-array, each item being a 1d-array with the same number of items as columnNames
|
||||
Catalog.prototype.addSourcesAsArray = function (columnNames, array) {
|
||||
var fields = [];
|
||||
for (var colIdx = 0; colIdx < columnNames.length; colIdx++) {
|
||||
@@ -675,13 +666,7 @@ export let Catalog = (function () {
|
||||
this.addSources(newSources);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all the sources
|
||||
*
|
||||
* @memberof Catalog
|
||||
*
|
||||
* @returns {Source[]} - an array of all the sources in the catalog object
|
||||
*/
|
||||
// return the current list of Source objects
|
||||
Catalog.prototype.getSources = function () {
|
||||
return this.sources;
|
||||
};
|
||||
@@ -690,11 +675,7 @@ export let Catalog = (function () {
|
||||
return this.footprints;
|
||||
};
|
||||
|
||||
/**
|
||||
* Select all the source catalog
|
||||
*
|
||||
* @memberof Catalog
|
||||
*/
|
||||
// TODO : fonction générique traversant la liste des sources
|
||||
Catalog.prototype.selectAll = function () {
|
||||
if (!this.sources) {
|
||||
return;
|
||||
@@ -705,11 +686,6 @@ export let Catalog = (function () {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Unselect all the source of the catalog
|
||||
*
|
||||
* @memberof Catalog
|
||||
*/
|
||||
Catalog.prototype.deselectAll = function () {
|
||||
if (!this.sources) {
|
||||
return;
|
||||
@@ -720,15 +696,7 @@ export let Catalog = (function () {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get one source by its index in the catalog
|
||||
*
|
||||
* @memberof Catalog
|
||||
*
|
||||
* @param {number} idx - the index of the source in the catalog sources
|
||||
*
|
||||
* @returns {Source} - the source at the index
|
||||
*/
|
||||
// return a source by index
|
||||
Catalog.prototype.getSource = function (idx) {
|
||||
if (idx < this.sources.length) {
|
||||
return this.sources[idx];
|
||||
@@ -746,86 +714,37 @@ export let Catalog = (function () {
|
||||
this.reportChange();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the color of the catalog
|
||||
*
|
||||
* @memberof Catalog
|
||||
*
|
||||
* @param {String} - the new color
|
||||
*/
|
||||
Catalog.prototype.setColor = function (color) {
|
||||
this.color = color;
|
||||
this.updateShape();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the color of selected sources
|
||||
*
|
||||
* @memberof Catalog
|
||||
*
|
||||
* @param {String} - the new color
|
||||
*/
|
||||
Catalog.prototype.setSelectionColor = function (color) {
|
||||
this.selectionColor = color;
|
||||
this.updateShape();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the color of hovered sources
|
||||
*
|
||||
* @memberof Catalog
|
||||
*
|
||||
* @param {String} - the new color
|
||||
*/
|
||||
Catalog.prototype.setHoverColor = function (color) {
|
||||
this.hoverColor = color;
|
||||
this.updateShape();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the size of the catalog sources
|
||||
*
|
||||
* @memberof Catalog
|
||||
*
|
||||
* @param {number} - the new size
|
||||
*/
|
||||
Catalog.prototype.setSourceSize = function (sourceSize) {
|
||||
// will be discarded in updateShape if the shape is an Image
|
||||
this.sourceSize = sourceSize;
|
||||
this.updateShape();
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the color of the catalog
|
||||
*
|
||||
* @memberof Catalog
|
||||
*
|
||||
* @param {string|Function|HTMLImageCanvas|HTMLImageElement} [shape="square"] - the type of the shape. Can be square, rhomb, plus, cross, triangle, circle.
|
||||
* A callback function can also be called that return an HTMLImageElement in function of the source object. A canvas or an image can also be given.
|
||||
*/
|
||||
Catalog.prototype.setShape = function (shape) {
|
||||
this.shape = shape;
|
||||
this.updateShape();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the size of the catalog sources
|
||||
*
|
||||
* @memberof Catalog
|
||||
*
|
||||
* @returns {number} - the size of the sources
|
||||
*/
|
||||
Catalog.prototype.getSourceSize = function () {
|
||||
return this.sourceSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a specific source from the catalog
|
||||
*
|
||||
* @memberof Catalog
|
||||
*
|
||||
* @param {Source} - the source to remove
|
||||
*/
|
||||
// remove a source
|
||||
Catalog.prototype.remove = function (source) {
|
||||
var idx = this.sources.indexOf(source);
|
||||
if (idx < 0) {
|
||||
@@ -843,19 +762,12 @@ export let Catalog = (function () {
|
||||
this.reportChange();
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear all the sources from the catalog
|
||||
*
|
||||
* @memberof Catalog
|
||||
*/
|
||||
Catalog.prototype.removeAll = Catalog.prototype.clear = function () {
|
||||
// TODO : RAZ de l'index
|
||||
this.sources = [];
|
||||
this.ra = [];
|
||||
this.dec = [];
|
||||
this.footprints = [];
|
||||
|
||||
this.reportChange();
|
||||
};
|
||||
|
||||
Catalog.prototype.draw = function (ctx, width, height) {
|
||||
@@ -1001,11 +913,6 @@ export let Catalog = (function () {
|
||||
this.view && this.view.requestRedraw();
|
||||
};
|
||||
|
||||
/**
|
||||
* Show the catalog
|
||||
*
|
||||
* @memberof Catalog
|
||||
*/
|
||||
Catalog.prototype.show = function () {
|
||||
if (this.isShowing) {
|
||||
return;
|
||||
@@ -1019,11 +926,6 @@ export let Catalog = (function () {
|
||||
this.reportChange();
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the catalog
|
||||
*
|
||||
* @memberof Catalog
|
||||
*/
|
||||
Catalog.prototype.hide = function () {
|
||||
if (!this.isShowing) {
|
||||
return;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
import { ALEvent } from "./events/ALEvent.js";
|
||||
import { ColorCfg } from "./ColorCfg.js";
|
||||
import { HiPSProperties } from "./HiPSProperties.js";
|
||||
import { Aladin } from "./Aladin.js";
|
||||
|
||||
let PropertyParser = {};
|
||||
// Utilitary functions for parsing the properties and giving default values
|
||||
/// Mandatory tileSize property
|
||||
@@ -153,12 +153,6 @@ PropertyParser.isPlanetaryBody = function (properties) {
|
||||
* @property {number} [brightness=0.0] - The brightness value for the color configuration.
|
||||
* @property {number} [contrast=0.0] - The contrast value for the color configuration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} FileList
|
||||
*
|
||||
* JS {@link https://developer.mozilla.org/fr/docs/Web/API/FileList| FileList} API type
|
||||
*/
|
||||
export let HiPS = (function () {
|
||||
/**
|
||||
* The object describing an image survey
|
||||
@@ -167,12 +161,10 @@ export let HiPS = (function () {
|
||||
* @constructs HiPS
|
||||
*
|
||||
* @param {string} id - Mandatory unique identifier for the layer. Can be an arbitrary name
|
||||
* @param {string|FileList|Object} location - Can be:
|
||||
* @param {string} location - Can be:
|
||||
* - an http url <br/>
|
||||
* - a relative path to your HiPS <br/>
|
||||
* - a special ID pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here} <br/>
|
||||
* - a dict storing a local HiPS. This object contains a tile file: hips[order][ipix] = File and refers to the properties file like so: hips["properties"] = File. <br/>
|
||||
* A javascript FileList pointing to the opened webkit directory is also accepted.
|
||||
* - a special ID pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}
|
||||
* @param {HiPSOptions} [options] - The option for the survey
|
||||
*
|
||||
* @description Giving a CDS ID will do a query to the MOCServer first to retrieve metadata. Then it will also check for the presence of faster HiPS nodes to choose a faster url to query to tiles from.
|
||||
@@ -186,30 +178,6 @@ export let HiPS = (function () {
|
||||
this.name = (options && options.name) || undefined;
|
||||
this.startUrl = options.startUrl;
|
||||
|
||||
if (location instanceof FileList) {
|
||||
let files = {};
|
||||
for (var file of location) {
|
||||
let path = file.webkitRelativePath;
|
||||
if (path.includes("Norder") && path.includes("Npix")) {
|
||||
const order = +path.substring(path.indexOf("Norder") + 6).split("/")[0];
|
||||
if (!files[order]) {
|
||||
files[order] = {}
|
||||
}
|
||||
|
||||
const ipix = +path.substring(path.indexOf("Npix") + 4).split(".")[0];
|
||||
files[order][ipix] = file;
|
||||
}
|
||||
|
||||
if (path.includes("properties")) {
|
||||
files['properties'] = file;
|
||||
}
|
||||
}
|
||||
|
||||
this.files = files;
|
||||
} else if (location instanceof Object) {
|
||||
this.files = location;
|
||||
}
|
||||
|
||||
this.url = location;
|
||||
this.maxOrder = options.maxOrder;
|
||||
this.minOrder = options.minOrder || 0;
|
||||
@@ -434,30 +402,11 @@ export let HiPS = (function () {
|
||||
}
|
||||
this.view = view;
|
||||
|
||||
if (this.files) {
|
||||
// Fetch the properties file
|
||||
self.query = (async () => {
|
||||
// look for the properties file
|
||||
await HiPSProperties.fetchFromFile(self.files["properties"])
|
||||
.then((p) => {
|
||||
self._parseProperties(p);
|
||||
|
||||
self.url = "local";
|
||||
|
||||
delete self.files["properties"]
|
||||
})
|
||||
|
||||
return self;
|
||||
})();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let isIncompleteOptions = true;
|
||||
|
||||
// This is very dirty but it allows me to differentiate the location from whether it is an ID or a plain url
|
||||
// This is very dirty but it allows me to differentiate the location from
|
||||
// whether an ID or a plain url
|
||||
let isID = this.url.includes("P/") || this.url.includes("C/")
|
||||
|
||||
|
||||
if (this.imgFormat === "fits") {
|
||||
// a fits is given
|
||||
isIncompleteOptions = !(
|
||||
@@ -479,6 +428,7 @@ export let HiPS = (function () {
|
||||
}
|
||||
|
||||
self.query = (async () => {
|
||||
|
||||
if (isIncompleteOptions) {
|
||||
// ID typed url
|
||||
if (self.startUrl && isID) {
|
||||
@@ -509,6 +459,8 @@ export let HiPS = (function () {
|
||||
},
|
||||
1000
|
||||
);
|
||||
|
||||
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
@@ -847,7 +799,7 @@ export let HiPS = (function () {
|
||||
this.layer = layer;
|
||||
let self = this;
|
||||
|
||||
const config = {
|
||||
this.view.wasm.addHiPS({
|
||||
layer,
|
||||
properties: {
|
||||
creatorDid: self.creatorDid,
|
||||
@@ -869,24 +821,8 @@ export let HiPS = (function () {
|
||||
...this.colorCfg.get(),
|
||||
longitudeReversed: this.longitudeReversed,
|
||||
imgFormat: this.imgFormat,
|
||||
}
|
||||
};
|
||||
|
||||
let localFiles;
|
||||
if (this.files) {
|
||||
localFiles = new Aladin.wasmLibs.core.HiPSLocalFiles();
|
||||
for (var order in this.files) {
|
||||
for (var ipix in this.files[order]) {
|
||||
const file = this.files[order][ipix];
|
||||
localFiles.insert(+order, BigInt(+ipix), file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.view.wasm.addHiPS(
|
||||
config,
|
||||
localFiles
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return Promise.resolve(this)
|
||||
.then((hips) => {
|
||||
|
||||
@@ -70,8 +70,6 @@ HiPSProperties.fetchFromID = async function(ID) {
|
||||
}
|
||||
|
||||
HiPSProperties.fetchFromUrl = async function(urlOrId) {
|
||||
let url;
|
||||
|
||||
try {
|
||||
urlOrId = new URL(urlOrId);
|
||||
} catch (e) {
|
||||
@@ -87,7 +85,7 @@ HiPSProperties.fetchFromUrl = async function(urlOrId) {
|
||||
// Fetch the properties of the survey
|
||||
const HiPSServiceUrl = urlOrId.toString();
|
||||
|
||||
url = HiPSServiceUrl;
|
||||
let url = HiPSServiceUrl;
|
||||
// Use the url for retrieving the HiPS properties
|
||||
// remove final slash
|
||||
if (url.slice(-1) === '/') {
|
||||
@@ -100,7 +98,6 @@ HiPSProperties.fetchFromUrl = async function(urlOrId) {
|
||||
// fix for HTTPS support --> will work for all HiPS served by CDS
|
||||
url = Utils.fixURLForHTTPS(url)
|
||||
|
||||
|
||||
let init = {};
|
||||
if (Utils.requestCORSIfNotSameOrigin(url)) {
|
||||
init = { mode: 'cors' };
|
||||
@@ -124,9 +121,7 @@ HiPSProperties.fetchFromUrl = async function(urlOrId) {
|
||||
if (!metadata.hips_frame || !metadata.hips_order) {
|
||||
reject('Bad properties: do not contain the mandatory frame or order info')
|
||||
} else {
|
||||
if (!("hips_service_url" in metadata)) {
|
||||
metadata.hips_service_url = HiPSServiceUrl;
|
||||
}
|
||||
metadata.hips_service_url = HiPSServiceUrl;
|
||||
resolve(metadata);
|
||||
}
|
||||
} else {
|
||||
@@ -138,27 +133,6 @@ HiPSProperties.fetchFromUrl = async function(urlOrId) {
|
||||
return result;
|
||||
}
|
||||
|
||||
HiPSProperties.fetchFromFile = function(file) {
|
||||
let url = URL.createObjectURL(file);
|
||||
return fetch(url)
|
||||
.then((response) => response.text())
|
||||
.then(
|
||||
(response) => new Promise((resolve, reject) => {
|
||||
// We get the property here
|
||||
let metadata = HiPSDefinition.parseHiPSProperties(response);
|
||||
|
||||
URL.revokeObjectURL(url)
|
||||
|
||||
// 1. Ensure there is exactly one survey matching
|
||||
if (metadata && Object.keys(metadata).length > 0) {
|
||||
resolve(metadata)
|
||||
} else {
|
||||
reject('No surveys matching at this url: ' + rootURL);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
HiPSProperties.getFasterMirrorUrl = function (metadata) {
|
||||
const pingHiPSServiceUrl = async (baseUrl) => {
|
||||
baseUrl = Utils.fixURLForHTTPS(baseUrl);
|
||||
|
||||
@@ -134,7 +134,7 @@ export let MOC = (function() {
|
||||
if (data instanceof ArrayBuffer) {
|
||||
// from an url
|
||||
const buf = data;
|
||||
self.view.wasm.addFITSMOC(self.mocParams, new Uint8Array(buf));
|
||||
self.view.wasm.addFITSMoc(self.mocParams, new Uint8Array(buf));
|
||||
} else if(data.ra && data.dec && data.radius) {
|
||||
// circle
|
||||
const c = data;
|
||||
|
||||
@@ -62,18 +62,16 @@ export let Sesame = (function() {
|
||||
// ask resolution by Sesame
|
||||
else {
|
||||
Sesame.resolve(target,
|
||||
function(data) { // success callback
|
||||
callback({
|
||||
ra: data.coo.jradeg,
|
||||
dec: data.coo.jdedeg
|
||||
});
|
||||
},
|
||||
function(data) { // success callback
|
||||
callback({ra: data.Target.Resolver.jradeg,
|
||||
dec: data.Target.Resolver.jdedeg});
|
||||
},
|
||||
|
||||
function(data) { // error callback
|
||||
if (errorCallback) {
|
||||
errorCallback(data);
|
||||
}
|
||||
}
|
||||
function(data) { // error callback
|
||||
if (errorCallback) {
|
||||
errorCallback();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -126,7 +126,7 @@ export let View = (function () {
|
||||
this.aladinDiv.ondragover = Utils.dragOverHandler;
|
||||
|
||||
this.throttledPositionChanged = Utils.throttle(
|
||||
(dragging) => {
|
||||
() => {
|
||||
var posChangedFn = this.aladin.callbacksByEventName && this.aladin.callbacksByEventName['positionChanged'];
|
||||
if (typeof posChangedFn === 'function') {
|
||||
var pos = this.aladin.pix2world(this.width / 2, this.height / 2, 'icrs');
|
||||
@@ -135,7 +135,7 @@ export let View = (function () {
|
||||
posChangedFn({
|
||||
ra: pos[0],
|
||||
dec: pos[1],
|
||||
dragging: dragging
|
||||
dragging: true
|
||||
});
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
@@ -841,9 +841,6 @@ export let View = (function () {
|
||||
|
||||
if (wasDragging) {
|
||||
view.realDragging = false;
|
||||
|
||||
// call the positionChanged once more with a dragging = false
|
||||
view.throttledPositionChanged(false);
|
||||
}
|
||||
} // end of "if (view.dragging) ... "
|
||||
|
||||
@@ -1012,6 +1009,11 @@ export let View = (function () {
|
||||
view.updateObjectsLookup();
|
||||
}
|
||||
|
||||
/*if (!view.dragging || Utils.hasTouchScreen()) {
|
||||
// update location box
|
||||
view.updateLocation({mouseX: xymouse.x, mouseY: xymouse.y});
|
||||
}*/
|
||||
|
||||
if (!view.dragging && !view.moving && view.mode === View.PAN) {
|
||||
// call listener of 'mouseMove' event
|
||||
var onMouseMoveFunction = view.aladin.callbacksByEventName['mouseMove'];
|
||||
@@ -1125,7 +1127,7 @@ export let View = (function () {
|
||||
ALEvent.POSITION_CHANGED.dispatchedTo(view.aladin.aladinDiv, view.viewCenter);
|
||||
|
||||
// Apply position changed callback after the move
|
||||
view.throttledPositionChanged(true);
|
||||
view.throttledPositionChanged();
|
||||
}
|
||||
}); //// endof mousemove ////
|
||||
|
||||
@@ -1148,6 +1150,7 @@ export let View = (function () {
|
||||
view.zoom.stopAnimation();
|
||||
}, 100);
|
||||
|
||||
|
||||
const xymouse = Utils.relMouseCoords(e);
|
||||
view.xy = xymouse
|
||||
ALEvent.CANVAS_EVENT.dispatchedTo(view.aladinDiv, {
|
||||
@@ -1291,25 +1294,33 @@ export let View = (function () {
|
||||
const now = performance.now();
|
||||
const elapsedTime = now - this.then;
|
||||
this.dt = elapsedTime;
|
||||
// If enough time has elapsed, draw the next frame
|
||||
//if (elapsedTime >= View.FPS_INTERVAL) {
|
||||
// Get ready for next frame by setting then=now, but also adjust for your
|
||||
// specified fpsInterval not being a multiple of RAF's interval (16.7ms)
|
||||
//if (this.dt > 10)
|
||||
// console.log(this.dt)
|
||||
// Drawing code
|
||||
//try {
|
||||
this.moving = this.wasm.update(elapsedTime);
|
||||
|
||||
// inertia run throttled position
|
||||
if (this.moving && this.aladin.callbacksByEventName && this.aladin.callbacksByEventName['positionChanged'] && this.wasm.isInerting()) {
|
||||
// run the trottled position
|
||||
this.throttledPositionChanged();
|
||||
}
|
||||
|
||||
this.moving = this.wasm.update(elapsedTime);
|
||||
|
||||
// inertia run throttled position
|
||||
if (this.moving && this.aladin.callbacksByEventName && this.aladin.callbacksByEventName['positionChanged'] && this.wasm.isInerting()) {
|
||||
// run the trottled position
|
||||
this.throttledPositionChanged(false);
|
||||
}
|
||||
////// 2. Draw catalogues////////
|
||||
const isViewRendering = this.wasm.isRendering();
|
||||
if (isViewRendering || this.needRedraw) {
|
||||
this.drawAllOverlays();
|
||||
}
|
||||
this.needRedraw = false;
|
||||
|
||||
////// 2. Draw catalogues////////
|
||||
const isViewRendering = this.wasm.isRendering();
|
||||
if (isViewRendering || this.needRedraw) {
|
||||
this.drawAllOverlays();
|
||||
}
|
||||
this.needRedraw = false;
|
||||
|
||||
this.then = now;
|
||||
//this.then = now % View.FPS_INTERVAL;
|
||||
requestAnimFrame(this.redrawClbk);
|
||||
this.then = now;
|
||||
//this.then = now % View.FPS_INTERVAL;
|
||||
requestAnimFrame(this.redrawClbk);
|
||||
//}
|
||||
};
|
||||
|
||||
View.prototype.drawAllOverlays = function () {
|
||||
@@ -2009,7 +2020,7 @@ export let View = (function () {
|
||||
var self = this;
|
||||
setTimeout(function () { self.refreshProgressiveCats(); }, 1000);
|
||||
// Apply position changed callback after the move
|
||||
self.throttledPositionChanged(false);
|
||||
self.throttledPositionChanged();
|
||||
|
||||
// hide the popup if it is open
|
||||
this.aladin.hidePopup();
|
||||
@@ -2036,7 +2047,7 @@ export let View = (function () {
|
||||
return false;
|
||||
};
|
||||
|
||||
View.prototype.removeOverlays = function () {
|
||||
View.prototype.removeLayers = function () {
|
||||
this.catalogs = [];
|
||||
this.overlays = [];
|
||||
this.mocs = [];
|
||||
@@ -2052,11 +2063,6 @@ export let View = (function () {
|
||||
|
||||
View.prototype.removeOverlay = function (overlay) {
|
||||
let indexToDelete = this.allOverlayLayers.indexOf(overlay);
|
||||
if (indexToDelete === -1) {
|
||||
// overlay not found
|
||||
return;
|
||||
}
|
||||
|
||||
this.allOverlayLayers.splice(indexToDelete, 1);
|
||||
|
||||
if (overlay.type == 'catalog' || overlay.type == 'progressivecat') {
|
||||
@@ -2085,12 +2091,12 @@ export let View = (function () {
|
||||
};
|
||||
|
||||
View.prototype.removeOverlayByName = function (overlayName) {
|
||||
let overlay = this.allOverlayLayers.find(o => o.name === overlayName);
|
||||
if (!overlay) {
|
||||
console.error(`Overlay "${overlayName}" not found.`);
|
||||
let layer = this.allOverlayLayers.find(l => l.name === overlayName);
|
||||
if (!layer) {
|
||||
console.error(`Layer with name "${overlayName}" not found.`);
|
||||
return;
|
||||
}
|
||||
this.removeOverlay(overlay);
|
||||
this.removeOverlay(layer);
|
||||
};
|
||||
|
||||
View.prototype.add = function(overlay) {
|
||||
|
||||
@@ -580,8 +580,7 @@ export class OverlayStackBox extends Box {
|
||||
// Center the view around the new fits object
|
||||
self.aladin.gotoRaDec(ra, dec);
|
||||
self.aladin.setFoV(fov * 1.1);
|
||||
|
||||
URL.revokeObjectURL(url);
|
||||
//self.aladin.selectLayer(image.layer);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -591,31 +590,6 @@ export class OverlayStackBox extends Box {
|
||||
);
|
||||
},
|
||||
}),
|
||||
ContextMenu.webkitDir({
|
||||
label: "Load local HiPS",
|
||||
action(files) {
|
||||
let id = files[0].webkitRelativePath.split("/")[0];
|
||||
let name = id;
|
||||
|
||||
let hips = self.aladin.createImageSurvey(
|
||||
id,
|
||||
name,
|
||||
files,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
errorCallback: (e) => {
|
||||
aladin.addStatusBarMessage({
|
||||
duration: 2000,
|
||||
type: 'info',
|
||||
message: 'Could not add the local HiPS',
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
self.aladin.addNewImageLayer(hips);
|
||||
},
|
||||
}),
|
||||
],
|
||||
tooltip: {
|
||||
content: "Add a HiPS or an FITS image",
|
||||
@@ -794,7 +768,7 @@ export class OverlayStackBox extends Box {
|
||||
);
|
||||
layout = layout.concat(this._createSurveysList());
|
||||
|
||||
return Layout.vertical({ layout });
|
||||
return Layout.vertical({ layout, classList: ["content"] });
|
||||
}
|
||||
|
||||
_createOverlaysList() {
|
||||
|
||||
@@ -407,36 +407,4 @@ export class ContextMenu extends DOMElement {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static webkitDir(itemOptions) {
|
||||
return {
|
||||
...itemOptions,
|
||||
label: {
|
||||
icon: {
|
||||
monochrome: true,
|
||||
tooltip: {content: 'Load a local file from your computer.<br \>Accept ' + itemOptions.accept + ' files'},
|
||||
url: uploadIconUrl,
|
||||
cssStyle: {
|
||||
cursor: 'help',
|
||||
}
|
||||
},
|
||||
content: itemOptions.label
|
||||
},
|
||||
action(e) {
|
||||
let webkitDirLoader = document.createElement('input');
|
||||
webkitDirLoader.type = 'file';
|
||||
webkitDirLoader.webkitdirectory = true;
|
||||
webkitDirLoader.multiple = true;
|
||||
|
||||
// Case: The user is loading a FITS file
|
||||
webkitDirLoader.addEventListener("change", (e) => {
|
||||
if (itemOptions.action) {
|
||||
itemOptions.action(e.target.files)
|
||||
}
|
||||
});
|
||||
|
||||
webkitDirLoader.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import wasmPack from 'vite-plugin-wasm-pack';
|
||||
// To include and minify glsl into the bundle
|
||||
import glsl from 'vite-plugin-glsl';
|
||||
// To include css into the bundle
|
||||
//import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
|
||||
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
@@ -38,6 +38,7 @@ export default defineConfig({
|
||||
glsl({
|
||||
compress: true,
|
||||
}),
|
||||
cssInjectedByJsPlugin(),
|
||||
],
|
||||
resolve: {
|
||||
alias: [
|
||||
|
||||
Reference in New Issue
Block a user