Skip to content

Commit

Permalink
Merge pull request #4 from cds-astro/wasm_with_store
Browse files Browse the repository at this point in the history
Wasm with store
  • Loading branch information
fxpineau authored Apr 21, 2023
2 parents 6af7602 + 1e75f83 commit 835c8c3
Show file tree
Hide file tree
Showing 16 changed files with 2,169 additions and 2,038 deletions.
13 changes: 13 additions & 0 deletions crates/wasm/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# `moc-wasm` Change Log

## 0.7.0

Released 2023-04-21

### ⚠️ BREAKING Changes

The full API has been changed!
Instead of relying on functions accessing MOCs by names,
we use methods on Javascirpt objects (MOC, TMOC, FMOC and STMOC).
The internal store is now the same as the one used in [MOCPy](https://github.com/cds-astro/mocpy/).
See the README file and the example index.html file for more details.


## 0.6.0

Released 2023-03-28
Expand Down
4 changes: 2 additions & 2 deletions crates/wasm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "moc-wasm"
version = "0.6.0"
version = "0.7.0"
authors = ["F.-X. Pineau <[email protected]>"]
description = """
WASM library to create and manipulate HEALPix
Expand All @@ -21,7 +21,7 @@ edition = "2018"
crate-type = ["cdylib", "rlib"]

[dependencies]
moclib = { package = "moc", path = "../.." }
moclib = { package = "moc", path = "../..", features = ["storage"] }
healpix = { package = "cdshealpix", version = "0.6.3" }
serde = { version = "1.0.80", features = ["derive"] }
wasm-bindgen = { version = "0.2.78", features = ["serde-serialize"] }
Expand Down
259 changes: 128 additions & 131 deletions crates/wasm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ For tools able to display MOCs, see:

### Try it

From this [demo page](http://cdsxmatch.u-strasbg.fr/lab/moc/).

* From version 0.7.0: from this [demo page](http://cdsxmatch.u-strasbg.fr/lab/mocwasm/).
* Older versions (pre v0.7.0): from this [demo page](http://cdsxmatch.u-strasbg.fr/lab/mocwasm/).

### Put it in your own Web page

Expand Down Expand Up @@ -61,180 +61,177 @@ Example of web page(s) using MOCwasm:
TBW


## Available JavaScript methods
## Available JavaScript methods (from v0.7.0)

Following the provided [index.html](index.html) example,
use the `moc` prefix to, call the following methods (e.g. `moc.list()`):
use the `moc` prefix to, call the following objects/methods (e.g. `moc.debugOn()` or `moc.MOC`):
```bash
# In case of failure, enable Rust stack trace
debugOn();

# Info
# - List the name of the MOCs loaded in memory.
list() -> Array<String>
# - Returns the quantity type (space, time or space-time) of the MOC having the given name
qtype(name) -> String
# - Returns information on the MOC having the given name
info(name) -> Object
# - Remove from memory the MOC of given name
drop(name)

# Load
# Available objects
MOC
TMOC
FMOC
STMOC

# You can then explore the various methods each object has,
# a large part are common, creation methods from parameters are specific

# - fires the select file dialog (see JS file for more details) to load a local MOCs
fromLocalFile(empty|'space'|'time'|'space-time')
# - load the MOC from a FITS file content in the provided UInt8Array
fromFits(name, data: UInt8Array)
# - load the MOC stored in a FITS file of given URL, and store it with the given name
fromFitsUrl(name, url) // A string of supported mimi types can be passed in an additional last parameter
# - load S/T/ST-MOC from a ASCII String or an ASCII file
smocFromAscii(name, data: String)
smocFromAsciiUrl(name, url)
tmocFromAscii(name, data: String)
tmocFromAsciiUrl(name, url)
stmocFromAscii(name, data: String)
stmocFromAsciiUrl(name, url)
# - load S/T/ST-MOC from a JSON String or a JSON file
smocFromJson(name, data: String)
smocFromJsonUrl(name, url)
tmocFromJson(name, data: String)
tmocFromJsonUrl(name, url)
stmocFromJson(name, data: String)
stmocFromJsonUrl(name, url)
let mymoc = (T|F|ST)MOC.fromLocalFile()
# - load the MOC from a FITS file content, provided in the UInt8Array
let mymoc = (T|F|ST)MOC.fromFits(data: UInt8Array)
# - load the MOC stored in a FITS file of given URL
let mymoc = (T|F|ST)MOC.fromFitsUrl(url) // A string of supported mime types can be passed in an additional last parameter
# - load from a ASCII String or an ASCII file
let mymoc = (T|F|ST)MOC.fromAscii(data: String)
let mymoc = (T|F|ST)MOC.fromAsciiUrl(url)

# - load from a JSON String or a JSON file
let mymoc = (T|F|ST)MOC.fromJson(data: String)
let mymoc = (T|F|ST)MOC.fromJsonUrl(url)


# - fires the select dialogto load a multi-order map FITS file and create a MOC from the given parameters
fromLocalMultiOrderMap(from_threshold: f64, to_threshold: f64, asc: bool, not_strict: bool, split: bool, revese_recursive_descent: bool)
let mymoc = MOC.fromLocalMultiOrderMap(from_threshold: f64, to_threshold: f64, asc: bool, not_strict: bool, split: bool, revese_recursive_descent: bool)
# - load a multi-order map FITS file and create a MOC from the given parameters
fromFitsMulitOrderMap(name, data: UInt8Array, from_threshold: f64, to_threshold: f64, asc: bool, not_strict: bool, split: bool, revese_recursive_descent: bool)
let mymoc = MOC.fromFitsMulitOrderMap(data: UInt8Array, from_threshold: f64, to_threshold: f64, asc: bool, not_strict: bool, split: bool, revese_recursive_descent: bool)
# - load a multi-order map FITS file of given URL and create a MOC from the given parameters
fromMultiOrderMapFitsUrl(name, url, from_threshold: f64, to_threshold: f64, asc: bool, not_strict: bool, split: bool, revese_recursive_descent: bool) // A string of supported mime types can be passed in an additional last parameter
let mymoc = MOC.fromMultiOrderMapFitsUrl(url, from_threshold: f64, to_threshold: f64, asc: bool, not_strict: bool, split: bool, revese_recursive_descent: bool) // A string of supported mime types can be passed in an additional last parameter

# Save a MOC
# - get the FITS binary representation of the MOC of given name
toFits(name) -> Uint8Array
# - get the ASCII representation of the MOC of given name
# - get the FITS binary representation of the MOC
mymoc.toFits() -> Uint8Array
# - get the ASCII representation of the MOC
toAscii(name, fold: null|int) -> String
# - get the JSON representation of the MOC of given name
toJson(name, fold: null|int) -> String
# - get the JSON representation of the MOC
mymoc.toJson(fold: null|int) -> String
# - fires the download dialog to save the MOC in an ASCII/JSON or FITS file.
toFitsFile(name)
toAsciiFile(name, fold: null|int)
toJsonFile(name, fold: null|int)
mymoc.toFitsFile()
mymoc.toAsciiFile(fold: null|int)
mymoc.toJsonFile(fold: null|int)

# Create MOC
# - create a S-MOC from a geometric shape
fromCone(name, depth, lon_deg, lat_deg, radius_deg)
fromRing(name, depth, lon_deg, lat_deg, internal_radius_deg, external_radius_deg)
fromEllipse(name, depth, lon_deg, lat_deg, a_deg, b_deg, pa_deg)
fromZone(name, depth, lon_deg_min, lat_deg_min, lon_deg_max, lat_deg_max)
fromBox(name, depth, lon_deg, lat_deg, a_deg, b_deg, pa_deg)
fromPolygon(name, depth, vertices_deg: Float64Array, complement: boolean)
let mymoc = MOC.fromCone(depth, lon_deg, lat_deg, radius_deg)
let mymoc = MOC.fromRing(depth, lon_deg, lat_deg, internal_radius_deg, external_radius_deg)
let mymoc = MOC.fromEllipse(depth, lon_deg, lat_deg, a_deg, b_deg, pa_deg)
let mymoc = MOC.fromZone(depth, lon_deg_min, lat_deg_min, lon_deg_max, lat_deg_max)
let mymoc = MOC.fromBox(depth, lon_deg, lat_deg, a_deg, b_deg, pa_deg)
let mymoc = MOC.fromPolygon(depth, vertices_deg: Float64Array, complement: boolean)
# - create a S-MOC from a list of coordinates
fromCoo(name, depth, coos_deg: Float64Array)
let mymoc = MOC.fromCoo(depth, coos_deg: Float64Array)
# - create a T-MOC from a list of Julian Days
fromDecimalJDs(name, depth, jd: Float64Array)
let mymoc = MOC.fromDecimalJDs(depth, jd: Float64Array)
# - create a T-MOC from a list of Juliand Days range
fromDecimalJDRanges(name, depth, jd_ranges: Float64Array)
let mymoc = MOC.fromDecimalJDRanges(depth, jd_ranges: Float64Array)
# - reate a new S-MOC from the given lists of UNIQ and Values (i.e. from a Multi-Order Map)
fromValuedCells(name, depth, density: bool, from_threshold: f64, to_threshold: f64, asc: bool, not_strict: bool, split: bool, revese_recursive_descent: bool, uniqs: Float64Array, values: Float64Array)
let mymoc = MOC.fromValuedCells(depth, density: bool, from_threshold: f64, to_threshold: f64, asc: bool, not_strict: bool, split: bool, revese_recursive_descent: bool, uniqs: Float64Array, values: Float64Array)

# Single MOC operations
# S/T-MOC
not(name, out_name) / complement(name, out_name)
degrade(name, depth, out_name)
let mynewmoc = mymoc.not() // or mymoc.complement()
let mynewmoc = mymoc.degrade(depth)
# - S-MOC only
extend(name, out_name)
contract(name, out_name)
externalBorder(name, out_name)
internalBorder(name, out_name)
let mynewmoc = mymoc.extend()
let mynewmoc = mymoc.contract()
let mynewmoc = mymoc.externalBorder()
let mynewmoc = mymoc.internalBorder()
# -- split considering the 4 direct neighbours (NE, NW, SE, SW) as being part of the same region
splitCount(name)
split(name, out_name_prefix)
let n = mymoc.splitCount()
let mysubmocs = mymoc.split()
# -- split considering the 4 direct neighbours (NE, NW, SE, SW) plus the 4 indirect neighbours (S, N, E, W) as being part of the same region
splitIndirectCount(name)
splitIndirect(name, out_name_prefix)
let n = mymoc.splitIndirectCount()
let mysubmocs = mymoc.splitIndirect()

# Two MOCs operations
or/union(left_name, right_name, out_name)
and/intersection(left_name, right_name, out_name)
xor/symmetric_difference(left_name, right_name, out_name)
minus/difference(left_name, right_name, out_name)
let union = mymoc1.or(mymoc2) // or mymoc1.union(mymoc2)
let inter = mymoc1.and(mymoc2) // or mymoc1.intersection(mymoc2)
let symdi = mymoc1.xor(mymoc2) // or mymoc1.symmetric_difference(mymoc2)
let diffe = mymoc1.minus(mymoc2) // or mymoc1.difference(mymoc2)

# Operation on ST-MOC
timeFold(tmoc_name, st_moc_name, out_smoc_name)
spaceFold(smoc_name, st_moc_name, out_tmoc_name)
let mysmoc = mystmoc.timeFold(mytmoc)
let mytmoc = mystmoc.spaceFold(mysmoc)

# Filter operations (return arrays containing 0 (out of the MOC) or 1 (in the MOC))
filterCoos(name, coos_deg: Float64Array) -> Uint8Array
filterJDs(name, jds: Float64Array) -> Uint8Array

let boolarray = mysmoc.filterCoos(coos_deg: Float64Array)
let boolarray = mytmoc.filterJDs( jds: Float64Array)
```

## Example 1: 2MASS and SDSS DR12 MOCs

In the [index.html](index.html) web page put behind a server (see next section),
simply copy/paste those line the web browser console:
```java
// Load 2MASS and SDSS DR12 MOCs from CDS
await moc.fromFitsUrl('2mass', 'http://alasky.u-strasbg.fr/footprints/tables/vizier/II_246_out/MOC');
await moc.fromFitsUrl('sdss12', 'http://alasky.u-strasbg.fr/footprints/tables/vizier/V_147_sdss12/MOC');

// List MOCs loaded in the page
console.log(moc.list());

// Init a timer
console.time('timer');
// Performs MOC intersection
moc.and('2mass', 'sdss12', '2mass_inter_sdss12');
// Log time
console.timeLog('timer', 'Intersection');
// Performs MOC union
moc.or('2mass', 'sdss12', '2mass_union_sdss12');
// Log time
console.timeLog('timer', 'Union');
// Degrade to order 2 the result of the intersection
moc.degrade('2mass_inter_sdss12', 2, '2mass_inter_sdss12_d2')
// Remove timer
console.timeEnd('timer');

// List MOCs loaded in the page
console.log(moc.list());

// Print the ASCII and JSON serializations of '2mass_inter_sdss12_d2'
console.log(moc.toAscii('2mass_inter_sdss12_d2'));
console.log(moc.toJson('2mass_inter_sdss12_d2'));

// Save the result of the intersection in a FITS file
moc.toFitsFile('2mass_inter_sdss12');
// Load 2MASS and SDSS DR12 MOCs from CDS
let moc2mass = await moc.MOC.fromFitsUrl('http://alasky.u-strasbg.fr/footprints/tables/vizier/II_246_out/MOC');
console.log("2MASS MOC depth: " + moc2mass.getDepth());
console.log("2MASS MOC coverage: " + moc2mass.coveragePercentage() + "%");
let mocsdss = await moc.MOC.fromFitsUrl('http://alasky.u-strasbg.fr/footprints/tables/vizier/V_147_sdss12/MOC');
console.log("SDSS DR12 MOC depth: " + mocsdss.getDepth());
console.log("SDSS DR12 MOC coverage: " + mocsdss.coveragePercentage() + "%");

// Init a timer
console.time('timer');
// Performs MOC intersection
let tmass_inter_sdss12 = moc2mass.and(mocsdss);
// Log time
console.timeLog('timer', 'Intersection');
// Performs MOC union
let tmass_union_sdss12 = moc2mass.or(mocsdss);
// Log time
console.timeLog('timer', 'Union');
// Degrade to order 2 the result of the intersection
let tmass_union_sdss12_d2 = tmass_union_sdss12.degrade(2);
// Remove timer
console.timeEnd('timer');

console.log("(2MASS AND SDSS DR12) MOC depth: " + tmass_inter_sdss12.getDepth());
console.log("(2MASS AND SDSS DR12) MOC coverage: " + tmass_inter_sdss12.coveragePercentage() + "%");
console.log("(2MASS OR SDSS DR12) MOC depth: " + tmass_union_sdss12.getDepth());
console.log("(2MASS OR SDSS DR12) MOC coverage: " + tmass_union_sdss12.coveragePercentage() + "%");
console.log("(2MASS OR SDSS DR12) MOC coverage at depth 2: " + tmass_union_sdss12_d2.coveragePercentage() + "%");

// Print the ASCII and JSON serializations of '2mass_inter_sdss12_d2'
console.log(tmass_inter_sdss12.toAscii());
console.log(tmass_inter_sdss12.toJson());

// Save the result of the intersection in a FITS file
tmass_inter_sdss12.toFitsFile();
```

## Example 2: Build a MOC from a Multi-Order Map and split it into disjoint MOCs

```java
var n;
// Load a multi-order map and create a MOC on-the-fly
await moc.fromMultiOrderMapFitsUrl('lalmap', 'http://cdsxmatch.u-strasbg.fr/lab/moc/LALInference.multiorder.fits', 0.0, 0.9, false, false, false, false);
// List MOCs loaded in the page
console.log(moc.list());

// Init a timer
console.time('timer');
// Count the number of disjoint MOCs in the MOC
n = moc.splitCount('lalmap');
console.log("n sub_mocs: " + n);
console.timeLog('timer', 'Spit count');
// Do split the MOC in 10 sub-MOCs
moc.split('lalmap', 'lalmap_sub');
console.timeLog('timer', 'Spit');
// Remove timer
console.timeEnd('timer');

// List MOCs loaded in the page
console.log(moc.list());

// Get info on sub-MOCs
for (let i = 0; i < n; i++){
console.log("Coverage percentage sub "+i+": "+moc.info("lalmap_sub_"+i).coverage_percentage);
}
// Load a multi-order map and create a MOC on-the-fly
let lalmap = await moc.MOC.fromMultiOrderMapFitsUrl('http://cdsxmatch.u-strasbg.fr/lab/moc/LALInference.multiorder.fits', 0.0, 0.9, false, false, false, false);

console.log("LALMAP MOC depth: " + lalmap.getDepth());
console.log("LALMAP MOC coverage: " + lalmap.coveragePercentage() + "%");

// Init a timer
console.time('timer');

// Count the number of disjoint MOCs in the MOC
let n = lalmap.splitCount();
console.log("n sub_mocs: " + n);
console.timeLog('timer', 'Spit count');

// Do split the MOC in 10 sub-MOCs
let mocs = lalmap.split();
console.timeLog('timer', 'Spit');
// Remove timer
console.timeEnd('timer');

// List MOCs loaded in the page
console.log(mocs);

// Get info on sub-MOCs
for (let i = 0; i < mocs.length; i++) {
console.log("Coverage percentage sub " + i + ": " + mocs[i].coveragePercentage());
}
```

## Install/run locally
Expand Down Expand Up @@ -287,7 +284,7 @@ And load the web page [http://0.0.0.0:8000/](http://0.0.0.0:8000/) in our favori

See [here](https://rustwasm.github.io/docs/book/game-of-life/publishing-to-npm.html)
```bash
wasm-pack build --out-name moc --release
wasm-pack build --out-name moc --release --scope fxpineau
wasm-pack login
wasm-pack publish
```
Expand Down
Loading

0 comments on commit 835c8c3

Please sign in to comment.