mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2025-12-25 12:25:52 -08:00
Compare commits
14 Commits
3.5.1-beta
...
gui-add-la
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d613a9b42 | ||
|
|
09f1302646 | ||
|
|
c39045171e | ||
|
|
bbd5848bdb | ||
|
|
7062a3cd76 | ||
|
|
f79d47d61e | ||
|
|
e6321f3950 | ||
|
|
ea174b2182 | ||
|
|
1ad6c54538 | ||
|
|
7d3eb6e80a | ||
|
|
61f9af1415 | ||
|
|
2395cb9425 | ||
|
|
f5da11c337 | ||
|
|
e0726590ab |
171
README.md
171
README.md
@@ -1,4 +1,4 @@
|
||||
# Aladin Lite v3
|
||||
# [Aladin Lite](https://aladin.u-strasbg.fr/AladinLite)
|
||||
|
||||
**An astronomical HiPS visualizer in the browser** <img src="aladin-logo.png" alt="Aladin Lite logo" width="220">
|
||||
|
||||
@@ -12,31 +12,50 @@ More details on [Aladin Lite documentation page](http://aladin.u-strasbg.fr/Alad
|
||||
A new [API technical documentation](https://cds-astro.github.io/aladin-lite/) is now available.
|
||||
|
||||
[](https://github.com/cds-astro/aladin-lite/actions/workflows/test.yml)
|
||||
[](https://cds-astro.github.io/aladin-lite)
|
||||
[](https://cds-astro.github.io/aladin-lite)
|
||||
|
||||
# How to test it ?
|
||||
Aladin Lite is available [at this link](https://aladin.u-strasbg.fr/AladinLite).
|
||||
|
||||
Aladin Lite v3 is out! Please play with [Aladin Lite v3 at this link](https://aladin.u-strasbg.fr/AladinLite).
|
||||
## Running & editable JS examples
|
||||
|
||||
<!-- Examples -->
|
||||
<table><tbody>
|
||||
<tr><td>Basic Aladin Lite setup</td><td>Load SIMBAD & NED catalog data</td><td>Load a FITS image</td></tr>
|
||||
<tr><td align="left"><a href="https://aladin.cds.unistra.fr/AladinLite/doc/API/examples/AL-in-responsive-div/"><img height="200" src="https://github.com/cds-astro/aladin-lite/blob/develop/assets/vignettes/Basic%20Aladin%20Lite%20instanciation.png?raw=true"></img></a></td>
|
||||
<td align="center"><a href="https://aladin.cds.unistra.fr/AladinLite/doc/API/examples/easy-access-simbad-ned/"><img height="200" src="https://github.com/cds-astro/aladin-lite/blob/develop/assets/vignettes/Load%20SIMBAD%20&%20NED%20catalogs%20data.png?raw=true"></img></a></td>
|
||||
<td align="right"><a href="https://aladin.cds.unistra.fr/AladinLite/doc/API/examples/load-FITS-image-URL/"><img height="200" src="https://github.com/cds-astro/aladin-lite/blob/develop/assets/vignettes/Load%20a%20FITS%20image.png?raw=true"></img></a></td></tr><tr>
|
||||
<td>American Astronomical Society 225<br/>example</td><td>Display proper motion vectors</td><td>Visualization of Mars</td></tr><tr>
|
||||
<td align="left"><a href="https://aladin.cds.unistra.fr/AladinLite/doc/API/examples/AAS225/"><img height="200" src="https://github.com/cds-astro/aladin-lite/blob/develop/assets/vignettes/American%20Astronomical%20Society%20225%20demonstration.png?raw=true"></img></a></td>
|
||||
<td align="center"><a href="https://aladin.cds.unistra.fr/AladinLite/doc/API/examples/show-proper-motions/"><img height="200" src="https://github.com/cds-astro/aladin-lite/blob/develop/assets/vignettes/Display%20proper%20motions.png?raw=true"></img></a></td>
|
||||
<td align="right"><a href="https://aladin.cds.unistra.fr/AladinLite/doc/API/examples/mars-visualisation/"><img height="200" src="https://github.com/cds-astro/aladin-lite/blob/develop/assets/vignettes/Visualization%20of%20Mars.png?raw=true"></img></a></td></tr></tbody></table>
|
||||
<!-- Examples -->
|
||||
|
||||
## Releases
|
||||
|
||||
For integrating Aladin Lite into your personal website, please refer to this [release page](https://aladin.cds.unistra.fr/AladinLite/doc/release/).
|
||||
Always prefer using the latest version. If you want the new features without minding about the bugs coming with it, then the beta is the good way to go.
|
||||
A [release page](https://aladin.cds.unistra.fr/AladinLite/doc/release/) keeps track of all the current and previous builds.
|
||||
A ``release`` and ``beta`` versions, regularly updated are available. The ``beta`` version is usually more advanced than the ``release`` one but features more error prone and not production-ready code.
|
||||
|
||||
## API documentation
|
||||
> [!TIP]
|
||||
> If you are working on a project that uses Aladin Lite, prefer working with a fixed version. Every build is tagged with a version number and accessible with:
|
||||
>
|
||||
> ```https://aladin.cds.unistra.fr/AladinLite/api/v3/<version>/aladin.js```
|
||||
|
||||
There is a new in progress API documentation at [this link](https://cds-astro.github.io/aladin-lite).
|
||||
## Documentation
|
||||
|
||||
There is a new API documentation available [here](https://cds-astro.github.io/aladin-lite).
|
||||
Editable examples showing the API can also be found [here](https://aladin.cds.unistra.fr/AladinLite/doc/API/examples/).
|
||||
|
||||
## Embed it into your projects
|
||||
|
||||
**Terms of use**: you are welcome to integrate Aladin Lite in your web pages and to customize its GUI to your needs, but **please leave the Aladin logo and link intact** at the bottom right of the view.
|
||||
|
||||
You can embed Aladin Lite it into your webpages in two ways
|
||||
|
||||
### The vanilla way
|
||||
|
||||
Please include [the javascript script of Aladin Lite v3](https://aladin.cds.unistra.fr/AladinLite/api/v3/latest/aladin.js) into your project. API differences from the v2 are minimal, here is a snippet of code you can use to embed it into your webpages:
|
||||
|
||||
```js
|
||||
```html
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
@@ -59,60 +78,36 @@ Please include [the javascript script of Aladin Lite v3](https://aladin.cds.unis
|
||||
</html>
|
||||
```
|
||||
|
||||
### Using the aladin lite NPM package
|
||||
### NPM deployment
|
||||
|
||||
First, install it with npm:
|
||||
A [NPM package](https://www.npmjs.com/package/aladin-lite) is deployed and maintained. It is used by [ipyaladin](https://github.com/cds-astro/ipyaladin), a jupyter widget allowing to run aladin lite in a notebook.
|
||||
|
||||
```npm i aladin-lite```
|
||||
|
||||
Second, you can use it that way:
|
||||
|
||||
```js
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<!-- Mandatory when setting up Aladin Lite v3 for a smartphones/tablet usage -->
|
||||
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=no">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="aladin-lite-div" style="width: 500px; height: 400px"></div>
|
||||
Aladin Lite can be imported with:
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import A from 'aladin-lite';
|
||||
|
||||
A.init.then(() => {
|
||||
let aladin = A.aladin('#aladin-lite-div', {fov: 360, projection: "AIT", cooFrame: 'equatorial', showCooGridControl: true, showSimbadPointerControl: true, showCooGrid: true});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Goals of v3
|
||||
## New features
|
||||
|
||||
- Rust/WebGL new core integration
|
||||
|
||||
- Remove jQuery dep
|
||||
|
||||
- UI dev, better support for smartphones
|
||||
|
||||
- FITS images support
|
||||
|
||||
- easy sharing of current « view »
|
||||
|
||||
- support of all VOTable serializations (using votable.js?)
|
||||
|
||||
- support of FITS tables?
|
||||
|
||||
- creating HiPS instance from an URL
|
||||
|
||||
- multiple mirrors handling for HiPS tile retrival
|
||||
|
||||
## Source code
|
||||
|
||||
Source code is available in the ``src`` directory.
|
||||
* [X] Rust/WebGL2 new rendering engine
|
||||
* [X] Remove jQuery dep
|
||||
* [ ] UI dev, better support for smartphones
|
||||
* [X] FITS images support
|
||||
* [X] WCS parsing, displaying an (JPEG/PNG) image in aladin lite view
|
||||
* [X] Display customized shapes (e.g. proper motions) from astronomical catalog data
|
||||
* [X] AVM tags parsing support
|
||||
* [X] Easy sharing of current « view »
|
||||
* [ ] All VOTable serializations
|
||||
* [ ] FITS tables
|
||||
* [X] Creating HiPS instance from an URL
|
||||
* [X] Local HiPS loading
|
||||
* [X] Multiple mirrors handling for HiPS tile retrival
|
||||
* [ ] HiPS cube
|
||||
|
||||
## Licence
|
||||
|
||||
@@ -120,7 +115,7 @@ Aladin Lite is currently licensed under GPL v3.0
|
||||
|
||||
If you think this license might prevent you from using Aladin Lite in your pages/application/portal, please open an issue or [contact us](mailto:cds-question@unistra.fr)
|
||||
|
||||
## Contributing
|
||||
## Contribution guidelines
|
||||
|
||||
There are several ways to contribute to Aladin Lite:
|
||||
|
||||
@@ -131,12 +126,12 @@ There are several ways to contribute to Aladin Lite:
|
||||
- **develop new features/provide code fixing bugs**. As open development is a new thing for us, we will in a first time only take into consideration code contribution (_i.e._ Pull Requests) from our close partners.
|
||||
In any case, please get in touch before starting a major update or rewrite.
|
||||
|
||||
### Building the application steps
|
||||
### Building steps
|
||||
|
||||
First you need to install the dependencies from the package.json
|
||||
Please run:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
@@ -147,63 +142,73 @@ You will also need [wasm-pack](https://rustwasm.github.io/wasm-pack/), a tool he
|
||||
|
||||
Once it's installed you will need to switch to the nightly rust version:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
rustup default nightly
|
||||
```
|
||||
|
||||
Then you can build the project:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
:warning: **If you are experimenting rust error compilations**:
|
||||
> [!WARNING]
|
||||
> **If you are experimenting Rust compiling issues:**
|
||||
> - Make sure you have your **wasm-pack** version updated. To do so:
|
||||
> ```sh
|
||||
> cargo install wasm-pack --version ~0.12
|
||||
> ```
|
||||
> - Make sure you are using the rust **nightly** toolchain
|
||||
> ```sh
|
||||
> rustup default nightly
|
||||
> ```
|
||||
> - Remove your `src/core/Cargo.lock` file and `src/core/target` directory -- this ensures that you'd escape any bad compilation state:
|
||||
> ```sh
|
||||
> git clean -di
|
||||
> ```
|
||||
> - then recompile with `npm run build`.
|
||||
|
||||
- Make sure you have your **wasm-pack** version updated. To do so:
|
||||
It will generate the aladin lite compiled code into a `dist/` directory located at the root of the repository. This directory contains two javascript files. `aladin.umd.cjs` follows the UMD module export convention and it is the one you need to use for your project.
|
||||
|
||||
```bash
|
||||
cargo install wasm-pack --version ~0.12
|
||||
```
|
||||
### Testing guidelines
|
||||
|
||||
- Make sure you are using the rust **nightly** toolchain
|
||||
- Remove your `src/core/Cargo.lock` file and `src/core/target` directory -- this ensures that you'd escape any bad compilation state:
|
||||
#### Run the examples
|
||||
|
||||
```bash
|
||||
git clean -di
|
||||
```
|
||||
|
||||
- then recompile with `npm run build`.
|
||||
A bunch of examples are located into the `examples` directory.
|
||||
To run them, start a localhost server:
|
||||
|
||||
It will generate the aladin lite compiled code into a `dist/` directory located at the root of the repository. This directory contains two javascript files. `aladin.umd.cjs` follows the UMD module export convention and it is the one you can use for your project.
|
||||
|
||||
To run the examples, you can start a localhost server with the following command:
|
||||
|
||||
```bash
|
||||
```sh
|
||||
npm run serve
|
||||
```
|
||||
|
||||
For just compiling the rust core, from the root location do:
|
||||
#### Rust tests
|
||||
|
||||
```bash
|
||||
These can be executed separately from the JS part:
|
||||
|
||||
* Compile the Rust code:
|
||||
|
||||
```sh
|
||||
cd src/core
|
||||
cargo check --features webgl2
|
||||
```
|
||||
|
||||
and run the tests:
|
||||
* Run the tests:
|
||||
|
||||
```bash
|
||||
cd src/core
|
||||
```sh
|
||||
cargo test --features webgl2
|
||||
```
|
||||
|
||||
For running the playwright test locally please first install playwright like so:
|
||||
#### Snapshot comparisons
|
||||
|
||||
```bash
|
||||
We use [playwright](https://playwright.dev/) for snapshot comparison testing. Only ground truth snapshots have been generated for MacOS/Darwin architecture.
|
||||
First install playwright:
|
||||
|
||||
```sh
|
||||
npx playwright install
|
||||
```
|
||||
|
||||
After that you will be able to run them. These are generated snapshots that will be compared to ground truth snapshots:
|
||||
Run the tests, advises are given for opening the UI mode or for generating your own ground truth snapshots.
|
||||
|
||||
```bash
|
||||
```sh
|
||||
npm run test:playwright
|
||||
```
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
BIN
assets/vignettes/Basic Aladin Lite instanciation.png
Normal file
BIN
assets/vignettes/Basic Aladin Lite instanciation.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
BIN
assets/vignettes/Display proper motions.png
Normal file
BIN
assets/vignettes/Display proper motions.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
BIN
assets/vignettes/Load SIMBAD & NED catalogs data.png
Normal file
BIN
assets/vignettes/Load SIMBAD & NED catalogs data.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
BIN
assets/vignettes/Load a FITS image.png
Normal file
BIN
assets/vignettes/Load a FITS image.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
BIN
assets/vignettes/Visualization of Mars.png
Normal file
BIN
assets/vignettes/Visualization of Mars.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
@@ -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"});
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<script type="module">
|
||||
import A from '../src/js/A.js';
|
||||
A.init.then(() => {
|
||||
aladin = A.aladin('#aladin-lite-div', {projection: 'MOL', fullScreen: true, fov: 360, survey: ['P/DM/vizMine', 'P/HST/GOODS/color', 'P/MATLAS/g'], target: '0 0', showProjectionControl: true, showSettingsControl: true, showCooGrid: true});
|
||||
aladin = A.aladin('#aladin-lite-div', {projection: 'MOL', fullScreen: true, fov: 360, survey: ['P/DM/vizMine', 'P/HST/GOODS/color', 'P/MATLAS/g'], target: '0 0', showProjectionControl: false, showSettingsControl: false, showLayersControl: false, showCooGrid: false, showFrame: false, showCooLocation: false});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
8
jsdoc-custom-style.css
Normal file
8
jsdoc-custom-style.css
Normal file
@@ -0,0 +1,8 @@
|
||||
nav > h2 {
|
||||
color: blue;
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
nav > ul > li > a {
|
||||
font-size: medium;
|
||||
}
|
||||
57
jsdoc.json
57
jsdoc.json
@@ -10,13 +10,64 @@
|
||||
"allowUnknownTags": true,
|
||||
"dictionaries": ["jsdoc","closure"]
|
||||
},
|
||||
"docdash": {
|
||||
"scripts": [
|
||||
"jsdoc-custom-style.css"
|
||||
],
|
||||
"sectionOrder": [
|
||||
"Namespaces",
|
||||
"Classes",
|
||||
"Modules",
|
||||
"Externals",
|
||||
"Events",
|
||||
"Mixins",
|
||||
"Tutorials",
|
||||
"Interfaces"
|
||||
],
|
||||
"openGraph": {
|
||||
"title": "Aladin Lite API documentation",
|
||||
"type": "website",
|
||||
"image": "https://cds-astro.github.io/aladin-lite/aladin-logo.png",
|
||||
"site_name": "Aladin Lite API documentation",
|
||||
"url": "https://cds-astro.github.io/aladin-lite/"
|
||||
},
|
||||
"meta": {
|
||||
"title": "Aladin Lite API documentation",
|
||||
"description": "Aladin Lite API documentation",
|
||||
"keyword": "astronomy"
|
||||
},
|
||||
"search": true,
|
||||
"menu": {
|
||||
"Project Website": {
|
||||
"href":"https://aladin.cds.unistra.fr/AladinLite/doc/",
|
||||
"target":"_blank",
|
||||
"class":"menu-item",
|
||||
"id":"website_link"
|
||||
},
|
||||
"Forum": {
|
||||
"href":"https://github.com/cds-astro/aladin-lite/issues",
|
||||
"target":"_blank",
|
||||
"class":"menu-item",
|
||||
"id":"forum_link"
|
||||
}
|
||||
}
|
||||
},
|
||||
"templates": {
|
||||
"cleverLinks": true,
|
||||
"monospaceLinks": true
|
||||
"monospaceLinks": true,
|
||||
"default": {
|
||||
"staticFiles": {
|
||||
"include": [
|
||||
"./jsdoc-custom-style.css"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"opts": {
|
||||
"readme": "./README.md",
|
||||
"destination": "./docs/",
|
||||
"tutorials": "./tutorials"
|
||||
"template": "node_modules/docdash",
|
||||
"encoding": "utf8",
|
||||
"verbose": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,11 +44,12 @@
|
||||
"test:build": "cd src/core && cargo test --release --features webgl2",
|
||||
"test:playwright": "npx playwright test",
|
||||
"test:update-snapshots": "npx playwright test --update-snapshots",
|
||||
"doc": "jsdoc -c jsdoc.json src/js src/js/shapes src/js/libs/astro && cp aladin-logo.png docs/",
|
||||
"doc": "jsdoc -c jsdoc.json src/js src/js/shapes src/js/libs/astro && cp aladin-logo.png docs/ && cp jsdoc-custom-style.css docs/",
|
||||
"doc:dev": "npm run doc && open docs/index.html"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.47.0",
|
||||
"docdash": "^2.0.2",
|
||||
"jsdoc": "^4.0.2",
|
||||
"vite": "^4.3.8",
|
||||
"vite-plugin-glsl": "^1.1.2",
|
||||
|
||||
@@ -232,7 +232,7 @@ where
|
||||
use crate::Abort;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
impl<I> Image for Arc<Mutex<Option<I>>>
|
||||
/*impl<I> Image for Arc<Mutex<Option<I>>>
|
||||
where
|
||||
I: Image,
|
||||
{
|
||||
@@ -249,7 +249,7 @@ where
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
#[cfg(feature = "webgl2")]
|
||||
use crate::image::format::{R16I, R32I, R64F, R8UI};
|
||||
|
||||
@@ -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 => (),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<I: Image + Debug>(
|
||||
&mut self,
|
||||
cell: &HEALPixCell,
|
||||
image: Option<I>,
|
||||
image: I,
|
||||
time_request: Time,
|
||||
) -> Result<(), JsValue> {
|
||||
self.textures.push(&cell, image, time_request)
|
||||
|
||||
@@ -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<I: Image + std::fmt::Debug>(
|
||||
&mut self,
|
||||
cell: &HEALPixCell,
|
||||
image: Option<I>,
|
||||
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<I: Image>(
|
||||
cell: &HEALPixCell,
|
||||
texture: &Texture,
|
||||
image: Option<I>,
|
||||
image: I,
|
||||
texture_array: &Texture2DArray,
|
||||
cfg: &mut HiPSConfig,
|
||||
) -> Result<(), JsValue> {
|
||||
@@ -663,12 +663,9 @@ fn send_to_gpu<I: Image>(
|
||||
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 {
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -23,34 +23,64 @@ pub struct TileFetcherQueue {
|
||||
#[derive(Debug)]
|
||||
#[wasm_bindgen]
|
||||
pub struct HiPSLocalFiles {
|
||||
paths: Box<[HashMap<u64, web_sys::File>]>,
|
||||
tiles: Box<[Box<[HashMap<u64, web_sys::File>]>; 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<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()) {
|
||||
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(),
|
||||
));
|
||||
|
||||
12
src/js/A.js
12
src/js/A.js
@@ -112,12 +112,12 @@ A.aladin = function (divSelector, options) {
|
||||
* @function
|
||||
* @name A.HiPS
|
||||
* @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 {string} id - Can be:
|
||||
* <ul>
|
||||
* <li>An http url towards a HiPS.</li>
|
||||
* <li>A relative path to your HiPS</li>
|
||||
* <li>A special ID pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* </ul>
|
||||
* @param {HiPSOptions} [options] - Options describing the survey
|
||||
* @returns {HiPS} - A HiPS image object
|
||||
*/
|
||||
|
||||
@@ -1500,10 +1500,13 @@ export let Aladin = (function () {
|
||||
* @memberof Aladin
|
||||
* @param {string} id - Mandatory unique identifier for the survey.
|
||||
* @param {string} [name] - A convinient name for the survey, optional
|
||||
* @param {string} url - Can be:
|
||||
* @param {string|FileList|HiPSLocalFiles} url - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>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>An http url towards a HiPS.</li>
|
||||
* <li>A relative path to your HiPS</li>
|
||||
* <li>A special ID pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>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. </li>
|
||||
* A javascript {@link FileList} pointing to the opened webkit directory is also accepted.
|
||||
* </ul>
|
||||
* @param {string} [cooFrame] - Values accepted: 'equatorial', 'icrs', 'icrsd', 'j2000', 'gal', 'galactic'
|
||||
* @param {number} [maxOrder] - The maximum HEALPix order of the HiPS, i.e the HEALPix order of the most refined tile images of the HiPS.
|
||||
@@ -1534,10 +1537,13 @@ export let Aladin = (function () {
|
||||
* @static
|
||||
* @param {string} id - Mandatory unique identifier for the survey.
|
||||
* @param {string} [name] - A convinient name for the survey, optional
|
||||
* @param {string} url - Can be:
|
||||
* @param {string|FileList|HiPSLocalFiles} url - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>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>An http url towards a HiPS.</li>
|
||||
* <li>A relative path to your HiPS</li>
|
||||
* <li>A special ID pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>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. </li>
|
||||
* A javascript {@link FileList} pointing to the opened webkit directory is also accepted.
|
||||
* </ul>
|
||||
* @param {string} [cooFrame] - Values accepted: 'equatorial', 'icrs', 'icrsd', 'j2000', 'gal', 'galactic'
|
||||
* @param {number} [maxOrder] - The maximum HEALPix order of the HiPS, i.e the HEALPix order of the most refined tile images of the HiPS.
|
||||
@@ -1581,7 +1587,7 @@ export let Aladin = (function () {
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS</li>
|
||||
* <li>2. Or it can be a CDS identifier 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>3. A {@link HiPS} HiPS object</li>
|
||||
* <li>4. A {@link Image} Image object</li>
|
||||
* </ul>
|
||||
*/
|
||||
@@ -1649,8 +1655,9 @@ export let Aladin = (function () {
|
||||
* @memberof Aladin
|
||||
* @param {string} id - Can be:
|
||||
* <ul>
|
||||
* <li>1. An url that refers to a HiPS.</li>
|
||||
* <li>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>An http url towards a HiPS.</li>
|
||||
* <li>A relative path to your HiPS</li>
|
||||
* <li>A special ID pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* </ul>
|
||||
* @param {HiPSOptions} [options] - Options for rendering the image
|
||||
* @param {function} [success] - A success callback
|
||||
|
||||
@@ -153,8 +153,8 @@ export let AladinUtils = {
|
||||
*/
|
||||
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/>
|
||||
* Find RA, DEC for any target (object name or position) <br/>
|
||||
* if successful, callback is called with an object {ra: {@link number}, dec: {@link number}} <br/>
|
||||
* if not successful, errorCallback is called
|
||||
*
|
||||
* @function
|
||||
@@ -162,8 +162,8 @@ export let AladinUtils = {
|
||||
* @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
|
||||
* @param {Function} callback - if successful, callback is called with an object {ra: {@link number}, dec: {@link number}}
|
||||
* @param {Function} errorCallback - if not successful, errorCallback is called with the error
|
||||
*/
|
||||
resolveAstronomicalName: Sesame.getTargetRADec
|
||||
},
|
||||
@@ -182,20 +182,21 @@ export let AladinUtils = {
|
||||
* @param {number} ra - Right Ascension (RA) coordinate in degrees.
|
||||
* @param {number} dec - Declination (Dec) coordinate in degrees.
|
||||
* @param {Aladin} aladin - Aladin Lite object containing the WebAssembly API.
|
||||
* @returns {number[]} xy - A 2 elements array representing the screen coordinates [X, Y] in pixels.
|
||||
* @returns {number[]} A 2 elements array representing the screen coordinates [X, Y] in pixels.
|
||||
*/
|
||||
radecToViewXy: function(ra, dec, aladin) {
|
||||
return aladin.world2pix(ra, dec);
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert a number in degrees into a string<br>
|
||||
*
|
||||
* @function
|
||||
* @memberof AladinUtils
|
||||
* @name degreesToString
|
||||
* Convert a number in degrees into a string<br>
|
||||
*
|
||||
*
|
||||
* @param numberDegrees number in degrees (integer or decimal)
|
||||
* @return a formattes string
|
||||
* @return the formatted string
|
||||
*
|
||||
* @example <caption> Result in degrees </caption>
|
||||
* // returns "1°"
|
||||
|
||||
@@ -128,8 +128,8 @@ PropertyParser.isPlanetaryBody = function (properties) {
|
||||
};
|
||||
|
||||
/**
|
||||
* HiPS options
|
||||
* @typedef {Object} HiPSOptions
|
||||
*
|
||||
* @property {string} [name] - The name of the survey to be displayed in the UI
|
||||
* @property {Function} [successCallback] - A callback executed when the HiPS has been loaded
|
||||
* @property {Function} [errorCallback] - A callback executed when the HiPS could not be loaded
|
||||
@@ -155,10 +155,19 @@ PropertyParser.isPlanetaryBody = function (properties) {
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} FileList
|
||||
*
|
||||
* JS {@link https://developer.mozilla.org/fr/docs/Web/API/FileList| FileList} API type
|
||||
*
|
||||
* @typedef {Object} FileList
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tiles are accessed like so: HIPSLocalFiles[norder][ipix] = {@link File};<br/>
|
||||
* The properties file is accessed with: HIPSLocalFiles["properties"]
|
||||
* @typedef {Object} HiPSLocalFiles
|
||||
* @property {File} properties - The local properties file of the HiPS
|
||||
*/
|
||||
|
||||
|
||||
export let HiPS = (function () {
|
||||
/**
|
||||
* The object describing an image survey
|
||||
@@ -167,12 +176,14 @@ 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:
|
||||
* - 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.
|
||||
* @param {string|FileList|HiPSLocalFiles} url - Can be:
|
||||
* <ul>
|
||||
* <li>An http url towards a HiPS.</li>
|
||||
* <li>A relative path to your HiPS</li>
|
||||
* <li>A special ID pointing towards a HiPS. One can found the list of IDs {@link https://aladin.cds.unistra.fr/hips/list| here}</li>
|
||||
* <li>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. </li>
|
||||
* A javascript {@link FileList} pointing to the opened webkit directory is also accepted.
|
||||
* </ul>
|
||||
* @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.
|
||||
@@ -187,27 +198,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;
|
||||
@@ -434,17 +456,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;
|
||||
@@ -873,12 +895,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,36 @@ import { Utils } from "./Utils";
|
||||
import { AVM } from "./libs/avm.js";
|
||||
import { HiPS } from "./HiPS.js";
|
||||
|
||||
/**
|
||||
* @typedef {Object} WCS
|
||||
*
|
||||
* {@link https://ui.adsabs.harvard.edu/abs/2002A%26A...395.1077C/abstract|FITS (Paper II)}, Calabretta, M. R., and Greisen, E. W., Astronomy & Astrophysics, 395, 1077-1122, 2002
|
||||
*
|
||||
* @property {number} [NAXIS]
|
||||
* @property {string} CTYPE1
|
||||
* @property {string} [CTYPE2]
|
||||
* @property {number} [LONPOLE]
|
||||
* @property {number} [LATPOLE]
|
||||
* @property {number} [CRVAL1]
|
||||
* @property {number} [CRVAL2]
|
||||
* @property {number} [CRPIX1]
|
||||
* @property {number} [CRPIX2]
|
||||
* @property {string} [CUNIT1] - e.g. 'deg'
|
||||
* @property {string} [CUNIT2] - e.g. 'deg'
|
||||
* @property {number} [CD1_1]
|
||||
* @property {number} [CD1_2]
|
||||
* @property {number} [CD2_1]
|
||||
* @property {number} [CD2_2]
|
||||
* @property {number} [PC1_1]
|
||||
* @property {number} [PC1_2]
|
||||
* @property {number} [PC2_1]
|
||||
* @property {number} [PC2_2]
|
||||
* @property {number} [CDELT1]
|
||||
* @property {number} [CDELT2]
|
||||
* @property {number} [NAXIS1]
|
||||
* @property {number} [NAXIS2]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ImageOptions
|
||||
*
|
||||
@@ -48,7 +78,7 @@ import { HiPS } from "./HiPS.js";
|
||||
* @property {number} [saturation=0.0] - The saturation value for the color configuration.
|
||||
* @property {number} [brightness=0.0] - The brightness value for the color configuration.
|
||||
* @property {number} [contrast=0.0] - The contrast value for the color configuration.
|
||||
* @property {Object} [wcs] - an object describing the WCS of the image. In case of a fits image
|
||||
* @property {WCS} [wcs] - an object describing the WCS of the image. In case of a fits image
|
||||
* this property will be ignored as the WCS taken will be the one present in the fits file.
|
||||
* @property {string} [imgFormat] - Optional image format. Giving it will prevent the auto extension determination algorithm to be triggered. Possible values are 'jpeg', 'png' or 'fits'. tiff files are not supported. You can convert your tiff files to jpg ones by using the fantastic image magick suite.
|
||||
*
|
||||
|
||||
@@ -222,8 +222,8 @@ export let MOC = (function() {
|
||||
/**
|
||||
* Serialize a MOC into different format
|
||||
*
|
||||
* @memberof Aladin
|
||||
* @param {string} [format='json'] - The output format. Only json is currently supported but 'fits' could be added.
|
||||
* @memberof MOC
|
||||
* @param {string} [format='json'] - The output format. Only `json` is currently supported but `fits` could be added.
|
||||
*/
|
||||
MOC.prototype.serialize = function(format) {
|
||||
if (!this.ready) {
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user