diff --git a/assets/vignettes/American Astronomical Society 225 demonstration.png b/assets/vignettes/American Astronomical Society 225 demonstration.png
new file mode 100644
index 00000000..0254a017
Binary files /dev/null and b/assets/vignettes/American Astronomical Society 225 demonstration.png differ
diff --git a/assets/vignettes/Basic Aladin Lite instanciation.png b/assets/vignettes/Basic Aladin Lite instanciation.png
new file mode 100644
index 00000000..8a470e53
Binary files /dev/null and b/assets/vignettes/Basic Aladin Lite instanciation.png differ
diff --git a/assets/vignettes/Display proper motions.png b/assets/vignettes/Display proper motions.png
new file mode 100644
index 00000000..22950f1b
Binary files /dev/null and b/assets/vignettes/Display proper motions.png differ
diff --git a/assets/vignettes/Load SIMBAD & NED catalogs data.png b/assets/vignettes/Load SIMBAD & NED catalogs data.png
new file mode 100644
index 00000000..91624fcf
Binary files /dev/null and b/assets/vignettes/Load SIMBAD & NED catalogs data.png differ
diff --git a/assets/vignettes/Load a FITS image.png b/assets/vignettes/Load a FITS image.png
new file mode 100644
index 00000000..39b08574
Binary files /dev/null and b/assets/vignettes/Load a FITS image.png differ
diff --git a/assets/vignettes/Visualization of Mars.png b/assets/vignettes/Visualization of Mars.png
new file mode 100644
index 00000000..73647b3c
Binary files /dev/null and b/assets/vignettes/Visualization of Mars.png differ
diff --git a/examples/al-adass2022.html b/examples/al-adass2022.html
index 47ee230b..50561fd9 100644
--- a/examples/al-adass2022.html
+++ b/examples/al-adass2022.html
@@ -10,8 +10,8 @@
import A from '../src/js/A.js';
let aladin;
A.init.then(() => {
- aladin = A.aladin('#aladin-lite-div', {survey: "P/PanSTARRS/DR1/color-z-zg-g", showReticle: false, projection: "AIT", cooFrame: 'icrs', target: "stephan's quintet", fov: 1000, showGotoControl: false, showFrame: false, fullScreen: true, showLayersControl: true, showCooGrid: true, showCooGridControl: false});
-
+ aladin = A.aladin('#aladin-lite-div', {showSettingsControl: true, survey: "P/PanSTARRS/DR1/color-z-zg-g", showReticle: false, projection: "AIT", cooFrame: 'icrs', target: "stephan's quintet", fov: 1000, showGotoControl: false, showFrame: false, fullScreen: true, showLayersControl: true, showCooGridControl: false});
+ aladin.showHealpixGrid(true);
const chft = aladin.createImageSurvey('CFHT', "CFHT deep view of NGC7331 and Stephan's quintet u+g+r", "https://cds.unistra.fr/~derriere/PR_HiPS/2022_Duc/", null, null, {imgFormat: 'png'});
const nircamJWST = aladin.createImageSurvey('Nircam', "Stephans Quintet NIRCam+MIRI", "http://alasky.cds.unistra.fr/JWST/CDS_P_JWST_Stephans-Quintet_NIRCam+MIRI/", null, null, {imgFormat: 'png', colormap: "viridis"});
diff --git a/examples/al-moc-sdss9.html b/examples/al-moc-sdss9.html
index fda81b89..0c96d336 100644
--- a/examples/al-moc-sdss9.html
+++ b/examples/al-moc-sdss9.html
@@ -12,7 +12,7 @@
import A from '../src/js/A.js';
let aladin;
A.init.then(() => {
- aladin = A.aladin('#aladin-lite-div', {target: '00 00 00 +07 00 00', fov: 130, survey: 'P/Mellinger/color', showContextMenu: true, fullScreen: true});
+ aladin = A.aladin('#aladin-lite-div', {inertia: false, target: '00 00 00 +07 00 00', fov: 130, survey: 'P/Mellinger/color', showContextMenu: true, fullScreen: true});
var moc11 = A.MOCFromURL('http://skies.esac.esa.int/HST/NICMOS/Moc.fits', {color: '#84f', lineWidth: 3}, (moc) => {
// moc is ready
console.log(moc.contains(205.9019247, +2.4492764));
diff --git a/examples/al-multiple-surveys.html b/examples/al-multiple-surveys.html
index 08a1c3d7..a3e4d36f 100644
--- a/examples/al-multiple-surveys.html
+++ b/examples/al-multiple-surveys.html
@@ -8,7 +8,7 @@
diff --git a/src/core/al-core/src/image/mod.rs b/src/core/al-core/src/image/mod.rs
index fd9a616b..d699149e 100644
--- a/src/core/al-core/src/image/mod.rs
+++ b/src/core/al-core/src/image/mod.rs
@@ -232,7 +232,7 @@ where
use crate::Abort;
use std::sync::{Arc, Mutex};
-impl Image for Arc>>
+/*impl Image for Arc>>
where
I: Image,
{
@@ -249,7 +249,7 @@ where
Ok(())
}
-}
+}*/
#[cfg(feature = "webgl2")]
use crate::image::format::{R16I, R32I, R64F, R8UI};
diff --git a/src/core/src/app.rs b/src/core/src/app.rs
index d7fce4d3..b2a5033f 100644
--- a/src/core/src/app.rs
+++ b/src/core/src/app.rs
@@ -612,7 +612,7 @@ impl App {
//let _depth = tile.cell().depth();
// do not perform tex_sub costly GPU calls while the camera is zooming
if tile.cell().is_root() || included_or_near_coverage {
- let is_missing = tile.missing();
+ //let is_missing = tile.missing();
/*self.tile_fetcher.notify_tile(
&tile,
true,
@@ -626,75 +626,77 @@ impl App {
..
} = tile;
- let image = if is_missing {
+ /*let image = if is_missing {
// Otherwise we push nothing, it is probably the case where:
// - an request error occured on a valid tile
// - the tile is not present, e.g. chandra HiPS have not the 0, 1 and 2 order tiles
None
} else {
Some(image)
- };
+ };*/
use al_core::image::ImageType;
use fitsrs::fits::Fits;
use std::io::Cursor;
- if let Some(image) = image.as_ref() {
- match &*image.lock().unwrap_abort() {
- Some(ImageType::FitsImage {
- raw_bytes: raw_bytes_buf,
- }) => {
- // check if the metadata has not been set
- if !cfg.fits_metadata {
- let num_bytes = raw_bytes_buf.length() as usize;
- let mut raw_bytes = vec![0; num_bytes];
- raw_bytes_buf.copy_to(&mut raw_bytes[..]);
+ //if let Some(image) = image.as_ref() {
+ match &*image.lock().unwrap_abort() {
+ Some(ImageType::FitsImage {
+ raw_bytes: raw_bytes_buf,
+ }) => {
+ // check if the metadata has not been set
+ if !cfg.fits_metadata {
+ let num_bytes = raw_bytes_buf.length() as usize;
+ let mut raw_bytes = vec![0; num_bytes];
+ raw_bytes_buf.copy_to(&mut raw_bytes[..]);
- let mut bytes_reader =
- Cursor::new(raw_bytes.as_slice());
- let Fits { hdu } =
- Fits::from_reader(&mut bytes_reader)
- .map_err(|_| {
- JsValue::from_str(
- "Parsing fits error",
- )
- })?;
+ let mut bytes_reader =
+ Cursor::new(raw_bytes.as_slice());
+ let Fits { hdu } =
+ Fits::from_reader(&mut bytes_reader).map_err(
+ |_| JsValue::from_str("Parsing fits error"),
+ )?;
- let header = hdu.get_header();
- let bscale = if let Some(
- fitsrs::card::Value::Float(bscale),
- ) = header.get(b"BSCALE ")
- {
- *bscale as f32
- } else {
- 1.0
- };
- let bzero = if let Some(
- fitsrs::card::Value::Float(bzero),
- ) = header.get(b"BZERO ")
- {
- *bzero as f32
- } else {
- 0.0
- };
- let blank = if let Some(
- fitsrs::card::Value::Float(blank),
- ) = header.get(b"BLANK ")
- {
- *blank as f32
- } else {
- std::f32::NAN
- };
+ let header = hdu.get_header();
+ let bscale = if let Some(
+ fitsrs::card::Value::Float(bscale),
+ ) = header.get(b"BSCALE ")
+ {
+ *bscale as f32
+ } else {
+ 1.0
+ };
+ let bzero = if let Some(
+ fitsrs::card::Value::Float(bzero),
+ ) = header.get(b"BZERO ")
+ {
+ *bzero as f32
+ } else {
+ 0.0
+ };
+ let blank = if let Some(
+ fitsrs::card::Value::Float(blank),
+ ) = header.get(b"BLANK ")
+ {
+ *blank as f32
+ } else {
+ std::f32::NAN
+ };
- cfg.set_fits_metadata(bscale, bzero, blank);
- }
+ cfg.set_fits_metadata(bscale, bzero, blank);
}
- _ => (),
}
- }
+ _ => (),
+ };
+ //}
- survey.add_tile(&cell, image, time_req)?;
- self.request_redraw = true;
+ match &*image.lock().unwrap_abort() {
+ Some(img) => {
+ survey.add_tile(&cell, img, time_req)?;
+ self.request_redraw = true;
- self.time_start_blending = Time::now();
+ self.time_start_blending = Time::now();
+ }
+ None => (),
+ };
}
}
}
diff --git a/src/core/src/renderable/hips/mod.rs b/src/core/src/renderable/hips/mod.rs
index 959634e0..a79a9338 100644
--- a/src/core/src/renderable/hips/mod.rs
+++ b/src/core/src/renderable/hips/mod.rs
@@ -662,7 +662,7 @@ impl HiPS {
))
}
} else {
- None
+ unreachable!();
}
} else {
None
@@ -679,8 +679,8 @@ impl HiPS {
let uv_1 = TileUVW::new(cell, ending_texture, cfg);
let start_time = ending_texture.start_time().as_millis();
- let miss_0 = (starting_texture.is_missing()) as i32 as f32;
- let miss_1 = (ending_texture.is_missing()) as i32 as f32;
+ let miss_0 = (false) as i32 as f32;
+ let miss_1 = (false) as i32 as f32;
let num_subdivision = num_subdivision(cell, camera, projection);
@@ -817,7 +817,7 @@ impl HiPS {
pub fn add_tile(
&mut self,
cell: &HEALPixCell,
- image: Option,
+ image: I,
time_request: Time,
) -> Result<(), JsValue> {
self.textures.push(&cell, image, time_request)
diff --git a/src/core/src/survey/buffer.rs b/src/core/src/survey/buffer.rs
index 8c60ec7b..e140d945 100644
--- a/src/core/src/survey/buffer.rs
+++ b/src/core/src/survey/buffer.rs
@@ -289,7 +289,7 @@ impl ImageSurveyTextures {
let mutex_locked = image.lock().unwrap_abort();
let images = mutex_locked.as_ref().unwrap_abort();
for (idx, image) in images.iter().enumerate() {
- self.push(&HEALPixCell(depth_tile, idx as u64), Some(image), time_req)?;
+ self.push(&HEALPixCell(depth_tile, idx as u64), image, time_req)?;
}
}
@@ -310,7 +310,7 @@ impl ImageSurveyTextures {
pub fn push(
&mut self,
cell: &HEALPixCell,
- image: Option,
+ image: I,
time_request: Time,
) -> Result<(), JsValue> {
if !self.contains_tile(cell) {
@@ -381,7 +381,7 @@ impl ImageSurveyTextures {
&mut self.base_textures[idx as usize]
};
- let missing = image.is_none();
+ //let missing = image.is_none();
send_to_gpu(
cell,
texture,
@@ -393,7 +393,7 @@ impl ImageSurveyTextures {
texture.append(
cell, // The tile cell
&self.config,
- missing,
+ //missing,
);
self.available_tiles_during_frame = true;
@@ -629,7 +629,7 @@ impl ImageSurveyTextures {
fn send_to_gpu(
cell: &HEALPixCell,
texture: &Texture,
- image: Option,
+ image: I,
texture_array: &Texture2DArray,
cfg: &mut HiPSConfig,
) -> Result<(), JsValue> {
@@ -663,12 +663,9 @@ fn send_to_gpu(
idx_slice,
);
- if let Some(image) = image {
- image.tex_sub_image_3d(&texture_array, &offset)
- } else {
- cfg.get_default_image()
- .tex_sub_image_3d(&texture_array, &offset)
- }
+ image.tex_sub_image_3d(&texture_array, &offset)?;
+
+ Ok(())
}
impl SendUniforms for ImageSurveyTextures {
diff --git a/src/core/src/survey/texture.rs b/src/core/src/survey/texture.rs
index 4f99fee4..94ca026c 100644
--- a/src/core/src/survey/texture.rs
+++ b/src/core/src/survey/texture.rs
@@ -31,7 +31,7 @@ pub struct Texture {
num_tiles_written: usize,
// Flag telling whether the texture is available
// for drawing
- missing: bool,
+ //missing: bool,
}
use super::config::HiPSConfig;
@@ -44,7 +44,7 @@ impl Texture {
let full = false;
let texture_cell = *texture_cell;
let uniq = texture_cell.uniq();
- let missing = true;
+ //let missing = true;
let num_tiles_written = 0;
Texture {
texture_cell,
@@ -55,19 +55,19 @@ impl Texture {
start_time,
full,
num_tiles_written,
- missing,
+ //missing,
}
}
// Panic if cell is not contained in the texture
// Do nothing if the texture is full
// Return true if the tile is newly added
- pub fn append(&mut self, cell: &HEALPixCell, cfg: &HiPSConfig, missing: bool) {
+ pub fn append(&mut self, cell: &HEALPixCell, cfg: &HiPSConfig /*, missing: bool */) {
let texture_cell = cell.get_texture_cell(cfg.delta_depth());
debug_assert!(texture_cell == self.texture_cell);
debug_assert!(!self.full);
- self.missing &= missing;
+ //self.missing &= missing;
//self.start_time = Some(Time::now());
//self.full = true;
let num_tiles_per_texture = cfg.num_tiles_per_texture();
@@ -127,9 +127,9 @@ impl Texture {
self.idx
}
- pub fn is_missing(&self) -> bool {
+ /*pub fn is_missing(&self) -> bool {
self.missing
- }
+ }*/
// Setter
pub fn replace(&mut self, texture_cell: &HEALPixCell, time_request: Time) {
@@ -143,7 +143,7 @@ impl Texture {
self.start_time = None;
self.time_request = time_request;
self.tiles.clear();
- self.missing = true;
+ //self.missing = true;
self.num_tiles_written = 0;
}
@@ -187,9 +187,7 @@ impl<'a> TextureUniforms<'a> {
}
}
-use al_core::{
- shader::{SendUniforms, ShaderBound},
-};
+use al_core::shader::{SendUniforms, ShaderBound};
impl<'a> SendUniforms for TextureUniforms<'a> {
fn attach_uniforms<'b>(&self, shader: &'b ShaderBound<'b>) -> &'b ShaderBound<'b> {
shader
@@ -200,7 +198,8 @@ impl<'a> SendUniforms for TextureUniforms<'a> {
)
.attach_uniform(
&format!("{}{}", self.name, "empty"),
- &((self.texture.missing as u8) as f32),
+ //&((self.texture.full as u8) as f32),
+ &0.0,
)
.attach_uniform(
&format!("{}{}", self.name, "start_time"),
diff --git a/src/core/src/tile_fetcher.rs b/src/core/src/tile_fetcher.rs
index 1eb4fc47..7dd6912a 100644
--- a/src/core/src/tile_fetcher.rs
+++ b/src/core/src/tile_fetcher.rs
@@ -23,34 +23,64 @@ pub struct TileFetcherQueue {
#[derive(Debug)]
#[wasm_bindgen]
pub struct HiPSLocalFiles {
- paths: Box<[HashMap]>,
+ tiles: Box<[Box<[HashMap]>; 4]>,
+ moc: web_sys::File,
}
use crate::tile_fetcher::query::Tile;
use crate::HEALPixCell;
+use al_api::hips::ImageExt;
+use al_core::image::format::ImageFormatType;
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();
+ pub fn new(moc: web_sys::File) -> Self {
+ let tiles_per_fmt = vec![HashMap::new(); 30].into_boxed_slice();
- Self { paths }
+ Self {
+ tiles: Box::new([
+ tiles_per_fmt.clone(),
+ tiles_per_fmt.clone(),
+ tiles_per_fmt.clone(),
+ tiles_per_fmt,
+ ]),
+ moc,
+ }
}
- pub fn insert(&mut self, depth: u8, ipix: u64, file: web_sys::File) {
- self.paths[depth as usize].insert(ipix, file);
+ pub fn insert(&mut self, depth: u8, ipix: u64, ext: ImageExt, file: web_sys::File) {
+ let mut tiles_per_fmt = match ext {
+ ImageExt::Fits => &mut self.tiles[0],
+ ImageExt::Jpeg => &mut self.tiles[1],
+ ImageExt::Png => &mut self.tiles[2],
+ ImageExt::Webp => &mut self.tiles[3],
+ };
+
+ tiles_per_fmt[depth as usize].insert(ipix, file);
}
- fn get(&self, cell: &HEALPixCell) -> Option<&web_sys::File> {
+ fn get_tile(&self, cell: &HEALPixCell, ext: ImageExt) -> Option<&web_sys::File> {
let d = cell.depth() as usize;
let i = cell.idx();
- return self.paths[d].get(&i);
+ let tiles_per_fmt = match ext {
+ ImageExt::Fits => &self.tiles[0],
+ ImageExt::Jpeg => &self.tiles[1],
+ ImageExt::Png => &self.tiles[2],
+ ImageExt::Webp => &self.tiles[3],
+ };
+
+ return tiles_per_fmt[d].get(&i);
+ }
+
+ fn get_moc(&self) -> &web_sys::File {
+ &self.moc
}
}
+
use crate::renderable::CreatorDid;
impl TileFetcherQueue {
pub fn new() -> Self {
@@ -116,9 +146,11 @@ impl TileFetcherQueue {
}
fn check_in_file_list(&self, mut query: Tile) -> Result {
- 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()) {
+ if let Some(local_hips) = self.hips_local_files.get(&query.hips_cdid) {
+ if let Some(tile) =
+ local_hips.get_tile(&query.cell, query.format.get_ext_file().clone())
+ {
+ if let Ok(url) = web_sys::Url::create_object_url_with_blob(tile.as_ref()) {
// rewrite the url
query.url = url;
Ok(query)
@@ -166,8 +198,21 @@ impl TileFetcherQueue {
// The allsky is not mandatory present in a HiPS service but it is better to first try to search for it
//downloader.fetch(query::PixelMetadata::new(cfg));
// Try to fetch the MOC
+ let hips_cdid = cfg.get_creator_did();
+ let moc_url = if let Some(local_hips) = self.hips_local_files.get(hips_cdid) {
+ if let Ok(url) =
+ web_sys::Url::create_object_url_with_blob(local_hips.get_moc().as_ref())
+ {
+ url
+ } else {
+ format!("{}/Moc.fits", cfg.get_root_url())
+ }
+ } else {
+ format!("{}/Moc.fits", cfg.get_root_url())
+ };
+
downloader.borrow_mut().fetch(query::Moc::new(
- format!("{}/Moc.fits", cfg.get_root_url()),
+ moc_url,
cfg.get_creator_did().to_string(),
al_api::moc::MOC::default(),
));
diff --git a/src/js/HiPS.js b/src/js/HiPS.js
index 095e86dc..52d0d1c7 100644
--- a/src/js/HiPS.js
+++ b/src/js/HiPS.js
@@ -201,27 +201,38 @@ export let HiPS = (function () {
this.startUrl = options.startUrl;
if (location instanceof FileList) {
- let files = {};
+ let localFiles = {};
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] = {}
+ if (!localFiles[order]) {
+ localFiles[order] = {}
}
- const ipix = +path.substring(path.indexOf("Npix") + 4).split(".")[0];
- files[order][ipix] = file;
+ let tile = path.substring(path.indexOf("Npix") + 4).split(".");
+ const ipix = +tile[0];
+ const fmt = tile[1];
+
+ if (!localFiles[order][ipix]) {
+ localFiles[order][ipix] = {}
+ }
+
+ localFiles[order][ipix][fmt] = file;
}
if (path.includes("properties")) {
- files['properties'] = file;
+ localFiles['properties'] = file;
+ }
+
+ if (path.includes("Moc")) {
+ localFiles['moc'] = file;
}
}
- this.files = files;
+ this.localFiles = localFiles;
} else if (location instanceof Object) {
- this.files = location;
+ this.localFiles = location;
}
this.url = location;
@@ -448,17 +459,17 @@ export let HiPS = (function () {
}
this.view = view;
- if (this.files) {
+ if (this.localFiles) {
// Fetch the properties file
self.query = (async () => {
// look for the properties file
- await HiPSProperties.fetchFromFile(self.files["properties"])
+ await HiPSProperties.fetchFromFile(self.localFiles["properties"])
.then((p) => {
self._parseProperties(p);
self.url = "local";
- delete self.files["properties"]
+ delete self.localFiles["properties"]
})
return self;
@@ -887,12 +898,27 @@ export let HiPS = (function () {
};
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)
+ if (this.localFiles) {
+ localFiles = new Aladin.wasmLibs.core.HiPSLocalFiles(this.localFiles["moc"]);
+
+ let fmt;
+ for (var order in this.localFiles) {
+ if (order === "moc")
+ continue;
+
+ for (var ipix in this.localFiles[order]) {
+ for (var f in this.localFiles[order][ipix]) {
+ if (f === "png") {
+ fmt = Aladin.wasmLibs.core.ImageExt.Png;
+ } else if (f === "fits") {
+ fmt = Aladin.wasmLibs.core.ImageExt.Fits;
+ } else {
+ fmt = Aladin.wasmLibs.core.ImageExt.Jpeg;
+ }
+
+ const tileFile = this.localFiles[order][+ipix][f];
+ localFiles.insert(+order, BigInt(+ipix), fmt, tileFile)
+ }
}
}
}
diff --git a/src/js/View.js b/src/js/View.js
index 76a460f2..d9539ca9 100644
--- a/src/js/View.js
+++ b/src/js/View.js
@@ -1284,12 +1284,12 @@ export let View = (function () {
/**
* redraw the whole view
*/
- View.prototype.redraw = function () {
+ View.prototype.redraw = function (timestamp) {
// request another frame
// Elapsed time since last loop
const now = performance.now();
- const elapsedTime = now - this.then;
+ const elapsedTime = now - timestamp;
this.dt = elapsedTime;
this.moving = this.wasm.update(elapsedTime);
@@ -1300,6 +1300,7 @@ export let View = (function () {
this.throttledPositionChanged(false);
}
+
////// 2. Draw catalogues////////
const isViewRendering = this.wasm.isRendering();
if (isViewRendering || this.needRedraw) {
@@ -1307,7 +1308,6 @@ export let View = (function () {
}
this.needRedraw = false;
- this.then = now;
//this.then = now % View.FPS_INTERVAL;
requestAnimFrame(this.redrawClbk);
};