mirror of
https://github.com/cds-astro/aladin-lite.git
synced 2025-12-12 07:40:26 -08:00
fix some bugs, adapt ui for a new release
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
# Changelogs
|
||||
|
||||
## Unreleased
|
||||
## 3.4.5-beta
|
||||
|
||||
* [feat] add `layerChanged` event when a layer is added or removed
|
||||
* [deprecate] of `select` event, use `objectsSelected` event instead
|
||||
* [ui] add the ability to switch the tile format to download
|
||||
|
||||
## 3.4.3-beta
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ See [A&A 578, A114 (2015)](https://arxiv.org/abs/1505.02291) and [IVOA HiPS Reco
|
||||
Aladin Lite is built to be easily embeddable in any web page. It powers astronomical portals like [ESASky](https://sky.esa.int/), [ESO Science Archive portal](http://archive.eso.org/scienceportal/) and [ALMA Portal](https://almascience.eso.org/asax/).
|
||||
|
||||
More details on [Aladin Lite documentation page](http://aladin.u-strasbg.fr/AladinLite/doc/).
|
||||
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)
|
||||
|
||||
@@ -34,7 +34,7 @@ A.init.then(() => {
|
||||
console.log(objs, "are selected");
|
||||
})
|
||||
|
||||
aladin.select();
|
||||
aladin.select('circle');
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"homepage": "https://aladin.u-strasbg.fr/",
|
||||
"name": "aladin-lite",
|
||||
"type": "module",
|
||||
"version": "3.4.4-beta",
|
||||
"version": "3.4.5-beta",
|
||||
"description": "An astronomical HiPS visualizer in the browser",
|
||||
"author": "Thomas Boch and Matthieu Baumann",
|
||||
"license": "GPL-3",
|
||||
|
||||
@@ -7,6 +7,6 @@ use crate::fov::CenteredFoV;
|
||||
pub struct ImageParams {
|
||||
pub centered_fov: CenteredFoV,
|
||||
|
||||
pub min_cut: Option<f32>,
|
||||
pub max_cut: Option<f32>,
|
||||
pub min_cut: f32,
|
||||
pub max_cut: f32,
|
||||
}
|
||||
|
||||
@@ -180,6 +180,52 @@ impl Texture2D {
|
||||
Ok(texture)
|
||||
}
|
||||
|
||||
pub fn create_from_raw_bytes<F: ImageFormat>(
|
||||
gl: &WebGlContext,
|
||||
width: i32,
|
||||
height: i32,
|
||||
tex_params: &'static [(u32, u32)],
|
||||
bytes: Option<&[u8]>,
|
||||
) -> Result<Texture2D, JsValue> {
|
||||
let texture = gl.create_texture();
|
||||
|
||||
gl.bind_texture(WebGlRenderingCtx::TEXTURE_2D, texture.as_ref());
|
||||
|
||||
for (pname, param) in tex_params.iter() {
|
||||
gl.tex_parameteri(WebGlRenderingCtx::TEXTURE_2D, *pname, *param as i32);
|
||||
}
|
||||
|
||||
gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array(
|
||||
WebGlRenderingCtx::TEXTURE_2D,
|
||||
0,
|
||||
F::INTERNAL_FORMAT,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
F::FORMAT,
|
||||
F::TYPE,
|
||||
bytes,
|
||||
)
|
||||
.expect("Texture 2D");
|
||||
|
||||
let gl = gl.clone();
|
||||
let metadata = Some(Rc::new(RefCell::new(Texture2DMeta {
|
||||
width: width as u32,
|
||||
height: height as u32,
|
||||
internal_format: F::INTERNAL_FORMAT,
|
||||
format: F::FORMAT,
|
||||
type_: F::TYPE,
|
||||
})));
|
||||
|
||||
Ok(Texture2D {
|
||||
texture,
|
||||
|
||||
gl,
|
||||
|
||||
metadata,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_empty_unsized(
|
||||
gl: &WebGlContext,
|
||||
tex_params: &'static [(u32, u32)],
|
||||
@@ -591,10 +637,6 @@ impl<'a> Texture2DBoundMut<'a> {
|
||||
src_type: u32,
|
||||
pixels: Option<&[u8]>,
|
||||
) {
|
||||
//let Texture2DMeta {format, type_, ..} = self.texture_2d.metadata.unwrap_abort();
|
||||
/*self.texture_2d
|
||||
.gl
|
||||
.pixel_storei(WebGlRenderingCtx::UNPACK_ALIGNMENT, 1);*/
|
||||
self.texture_2d
|
||||
.gl
|
||||
.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array(
|
||||
|
||||
@@ -40,14 +40,6 @@ impl WebGlContext {
|
||||
let context_options =
|
||||
js_sys::JSON::parse("{\"antialias\":false, \"preserveDrawingBuffer\": true}")?;
|
||||
|
||||
#[cfg(feature = "webgl1")]
|
||||
let gl = Rc::new(
|
||||
canvas
|
||||
.get_context_with_context_options("webgl", context_options.as_ref())?
|
||||
.unwrap_abort()
|
||||
.dyn_into::<WebGlRenderingCtx>()
|
||||
.unwrap_abort(),
|
||||
);
|
||||
#[cfg(feature = "webgl2")]
|
||||
let gl = Rc::new(
|
||||
canvas
|
||||
@@ -56,6 +48,9 @@ impl WebGlContext {
|
||||
.dyn_into::<WebGlRenderingCtx>()
|
||||
.unwrap_abort(),
|
||||
);
|
||||
// https://webgl2fundamentals.org/webgl/lessons/webgl-data-textures.html
|
||||
#[cfg(feature = "webgl2")]
|
||||
gl.pixel_storei(WebGlRenderingCtx::UNPACK_ALIGNMENT, 1);
|
||||
|
||||
#[cfg(feature = "webgl2")]
|
||||
{
|
||||
|
||||
@@ -48,10 +48,10 @@ pub struct Image {
|
||||
|
||||
/// Parameters extracted from the fits
|
||||
wcs: WCS,
|
||||
blank: Option<f32>,
|
||||
scale: Option<f32>,
|
||||
offset: Option<f32>,
|
||||
cuts: Option<Range<f32>>,
|
||||
blank: f32,
|
||||
scale: f32,
|
||||
offset: f32,
|
||||
cuts: Range<f32>,
|
||||
/// The center of the fits
|
||||
centered_fov: CenteredFoV,
|
||||
|
||||
@@ -80,9 +80,9 @@ impl Image {
|
||||
gl: &WebGlContext,
|
||||
mut reader: R,
|
||||
wcs: WCS,
|
||||
mut scale: Option<f32>,
|
||||
mut offset: Option<f32>,
|
||||
mut blank: Option<f32>,
|
||||
scale: Option<f32>,
|
||||
offset: Option<f32>,
|
||||
blank: Option<f32>,
|
||||
// Coo sys of the view
|
||||
coo_sys: CooSystem,
|
||||
) -> Result<Self, JsValue>
|
||||
@@ -101,11 +101,9 @@ impl Image {
|
||||
let mut max_tex_size_y = max_tex_size;
|
||||
|
||||
// apply bscale to the cuts
|
||||
if F::NUM_CHANNELS == 1 {
|
||||
offset = offset.or(Some(0.0));
|
||||
scale = scale.or(Some(1.0));
|
||||
blank = blank.or(Some(std::f32::NAN));
|
||||
}
|
||||
let offset = offset.unwrap_or(0.0);
|
||||
let scale = scale.unwrap_or(1.0);
|
||||
let blank = blank.unwrap_or(std::f32::NAN);
|
||||
|
||||
let (textures, mut cuts) = if width <= max_tex_size as u64 && height <= max_tex_size as u64
|
||||
{
|
||||
@@ -119,14 +117,15 @@ impl Image {
|
||||
let mut buf = vec![0; num_bytes_to_read];
|
||||
|
||||
let _ = reader
|
||||
.read_exact(&mut buf[..])
|
||||
.read_exact(&mut buf[..num_bytes_to_read])
|
||||
.await
|
||||
.map_err(|e| JsValue::from_str(&format!("{:?}", e)))?;
|
||||
|
||||
// bytes aligned
|
||||
unsafe {
|
||||
let slice = std::slice::from_raw_parts(
|
||||
buf.as_mut_ptr() as *const <F::P as Pixel>::Item,
|
||||
num_bytes_to_read / std::mem::size_of::<<F::P as Pixel>::Item>(),
|
||||
buf[..].as_ptr() as *const <F::P as Pixel>::Item,
|
||||
(num_pixels_to_read as usize) * F::NUM_CHANNELS,
|
||||
);
|
||||
|
||||
let cuts = if F::NUM_CHANNELS == 1 {
|
||||
@@ -135,7 +134,7 @@ impl Image {
|
||||
.filter_map(|item| {
|
||||
let t: f32 =
|
||||
<<F::P as Pixel>::Item as al_core::convert::Cast<f32>>::cast(*item);
|
||||
if t.is_nan() || t == blank.unwrap() {
|
||||
if t.is_nan() || t == blank {
|
||||
None
|
||||
} else {
|
||||
Some(t)
|
||||
@@ -143,22 +142,20 @@ impl Image {
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let cuts = cuts::first_and_last_percent(&mut samples, 1, 99);
|
||||
Some(cuts)
|
||||
cuts::first_and_last_percent(&mut samples, 1, 99)
|
||||
} else {
|
||||
None
|
||||
0.0..1.0
|
||||
};
|
||||
|
||||
(
|
||||
vec![Texture2D::create_from_raw_pixels::<F>(
|
||||
gl,
|
||||
width as i32,
|
||||
height as i32,
|
||||
TEX_PARAMS,
|
||||
Some(slice),
|
||||
)?],
|
||||
cuts,
|
||||
)
|
||||
let texture = Texture2D::create_from_raw_pixels::<F>(
|
||||
gl,
|
||||
width as i32,
|
||||
height as i32,
|
||||
TEX_PARAMS,
|
||||
Some(slice),
|
||||
)?;
|
||||
|
||||
(vec![texture], cuts)
|
||||
}
|
||||
} else {
|
||||
subdivide_texture::crop_image::<F, R>(
|
||||
@@ -172,12 +169,10 @@ impl Image {
|
||||
.await?
|
||||
};
|
||||
|
||||
if let Some(cuts) = cuts.as_mut() {
|
||||
let start = cuts.start * scale.unwrap() + offset.unwrap();
|
||||
let end = cuts.end * scale.unwrap() + offset.unwrap();
|
||||
let start = cuts.start * scale + offset;
|
||||
let end = cuts.end * scale + offset;
|
||||
|
||||
*cuts = start..end;
|
||||
}
|
||||
cuts = start..end;
|
||||
|
||||
let num_indices = vec![];
|
||||
let indices = vec![];
|
||||
@@ -293,7 +288,7 @@ impl Image {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_cuts(&self) -> &Option<Range<f32>> {
|
||||
pub fn get_cuts(&self) -> &Range<f32> {
|
||||
&self.cuts
|
||||
}
|
||||
|
||||
@@ -712,9 +707,9 @@ impl Image {
|
||||
.attach_uniforms_with_params_from(color, colormaps)
|
||||
.attach_uniform("opacity", opacity)
|
||||
.attach_uniform("tex", texture)
|
||||
.attach_uniform("scale", &self.scale.unwrap_or(1.0))
|
||||
.attach_uniform("offset", &self.offset.unwrap_or(0.0))
|
||||
.attach_uniform("blank", &self.blank.unwrap_or(std::f32::NAN))
|
||||
.attach_uniform("scale", &self.scale)
|
||||
.attach_uniform("offset", &self.offset)
|
||||
.attach_uniform("blank", &self.blank)
|
||||
.bind_vertex_array_object_ref(&self.vao)
|
||||
.draw_elements_with_i32(
|
||||
WebGl2RenderingContext::TRIANGLES,
|
||||
|
||||
@@ -16,8 +16,8 @@ pub async fn crop_image<'a, F, R>(
|
||||
height: u64,
|
||||
mut reader: R,
|
||||
max_tex_size: u64,
|
||||
blank: Option<f32>,
|
||||
) -> Result<(Vec<Texture2D>, Option<Range<f32>>), JsValue>
|
||||
blank: f32,
|
||||
) -> Result<(Vec<Texture2D>, Range<f32>), JsValue>
|
||||
where
|
||||
F: ImageFormat,
|
||||
R: AsyncReadExt + Unpin,
|
||||
@@ -35,12 +35,11 @@ where
|
||||
];
|
||||
|
||||
for _ in 0..num_textures {
|
||||
tex_chunks.push(Texture2D::create_from_raw_pixels::<F>(
|
||||
tex_chunks.push(Texture2D::create_empty_with_format::<F>(
|
||||
gl,
|
||||
max_tex_size as i32,
|
||||
max_tex_size as i32,
|
||||
TEX_PARAMS,
|
||||
None,
|
||||
)?);
|
||||
}
|
||||
|
||||
@@ -101,11 +100,7 @@ where
|
||||
f32,
|
||||
>>::cast(slice[j]);
|
||||
if !sj.is_nan() {
|
||||
if let Some(b) = blank {
|
||||
if b != sj {
|
||||
samples.push(sj);
|
||||
}
|
||||
} else {
|
||||
if blank != sj {
|
||||
samples.push(sj);
|
||||
}
|
||||
}
|
||||
@@ -136,9 +131,9 @@ where
|
||||
}
|
||||
|
||||
let cuts = if F::NUM_CHANNELS == 1 {
|
||||
Some(cuts::first_and_last_percent(&mut samples, 1, 99))
|
||||
cuts::first_and_last_percent(&mut samples, 1, 99)
|
||||
} else {
|
||||
None
|
||||
0.0..1.0
|
||||
};
|
||||
|
||||
Ok((tex_chunks, cuts))
|
||||
|
||||
@@ -106,16 +106,13 @@ pub struct ImageLayer {
|
||||
|
||||
impl ImageLayer {
|
||||
pub fn get_params(&self) -> ImageParams {
|
||||
let (min_cut, max_cut) = self.images[0]
|
||||
.get_cuts()
|
||||
.as_ref()
|
||||
.map_or((None, None), |r| (Some(r.start), Some(r.end)));
|
||||
let cuts = self.images[0].get_cuts();
|
||||
|
||||
let centered_fov = self.images[0].get_centered_fov().clone();
|
||||
ImageParams {
|
||||
centered_fov,
|
||||
min_cut,
|
||||
max_cut,
|
||||
min_cut: cuts.start,
|
||||
max_cut: cuts.end,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
32
src/js/A.js
32
src/js/A.js
@@ -134,7 +134,37 @@ A.imageHiPS = function (id, options) {
|
||||
* @param {ImageOptions} [options] - Options describing the fits file. An url is mandatory
|
||||
* @returns {Image} - A HiPS image object
|
||||
* @example
|
||||
* const sourceObj = A.source(180.0, 30.0, data, options);
|
||||
* aladin.setOverlayImageLayer(A.image(
|
||||
* "https://nova.astrometry.net/image/25038473?filename=M61.jpg",
|
||||
* {
|
||||
* name: "M61",
|
||||
* imgFormat: 'jpeg',
|
||||
* wcs: {
|
||||
* NAXIS: 0, // Minimal header
|
||||
* CTYPE1: 'RA---TAN', // TAN (gnomic) projection
|
||||
* CTYPE2: 'DEC--TAN', // TAN (gnomic) projection
|
||||
* EQUINOX: 2000.0, // Equatorial coordinates definition (yr)
|
||||
* LONPOLE: 180.0, // no comment
|
||||
* LATPOLE: 0.0, // no comment
|
||||
* CRVAL1: 185.445488837, // RA of reference point
|
||||
* CRVAL2: 4.47896032431, // DEC of reference point
|
||||
* CRPIX1: 588.995094299, // X reference pixel
|
||||
* CRPIX2: 308.307905197, // Y reference pixel
|
||||
* CUNIT1: 'deg', // X pixel scale units
|
||||
* CUNIT2: 'deg', // Y pixel scale units
|
||||
* CD1_1: -0.000223666022989, // Transformation matrix
|
||||
* CD1_2: 0.000296578064584, // no comment
|
||||
* CD2_1: -0.000296427555509, // no comment
|
||||
* CD2_2: -0.000223774308964, // no comment
|
||||
* NAXIS1: 1080, // Image width, in pixels.
|
||||
* NAXIS2: 705 // Image height, in pixels.
|
||||
* },
|
||||
* successCallback: (ra, dec, fov, image) => {
|
||||
* aladin.gotoRaDec(ra, dec);
|
||||
* aladin.setFoV(fov * 5)
|
||||
* }
|
||||
* },
|
||||
* ));
|
||||
*/
|
||||
A.image = function (url, options) {
|
||||
return Aladin.createImageFITS(url, options, options.successCallback, options.errorCallback);
|
||||
|
||||
@@ -232,7 +232,9 @@ import { Polyline } from "./shapes/Polyline";
|
||||
|
||||
/**
|
||||
* @typedef {string} ListenerCallback
|
||||
* String with possible values: 'select',
|
||||
* String with possible values:
|
||||
* 'select' (deprecated, use objectsSelected instead),
|
||||
* 'objectsSelected',
|
||||
'objectClicked',
|
||||
'objectHovered',
|
||||
'objectHoveredStop',
|
||||
@@ -1949,7 +1951,8 @@ export let Aladin = (function () {
|
||||
|
||||
// Select corresponds to rectangular selection
|
||||
Aladin.AVAILABLE_CALLBACKS = [
|
||||
"select",
|
||||
"select", // deprecated, use objectsSelected instead
|
||||
"objectsSelected",
|
||||
|
||||
"objectClicked",
|
||||
"objectHovered",
|
||||
@@ -2019,12 +2022,16 @@ aladin.on('objectClicked', function(object, xyMouseCoords) {
|
||||
$('#infoDiv').html(msg);
|
||||
});
|
||||
|
||||
aladin.on("objectsSelected", (objs) => {
|
||||
console.log("objs", objs)
|
||||
})
|
||||
|
||||
aladin.on("positionChanged", ({ra, dec}) => {
|
||||
console.log("positionChanged", ra, dec)
|
||||
})
|
||||
|
||||
aladin.on("layerChanged", (imageHips, layerName, state) => {
|
||||
console.log("positionChanged", imageHips, layerName, state)
|
||||
aladin.on("layerChanged", (layer, layerName, state) => {
|
||||
console.log("layerChanged", layer, layerName, state)
|
||||
})
|
||||
*/
|
||||
Aladin.prototype.on = function (what, myFunction) {
|
||||
|
||||
@@ -46,8 +46,13 @@
|
||||
this.reversed = true;
|
||||
}
|
||||
|
||||
this.minCut = (options && options.minCut) || undefined;
|
||||
this.maxCut = (options && options.maxCut) || undefined;
|
||||
if (options && Number.isFinite(options.minCut)) {
|
||||
this.minCut = options.minCut;
|
||||
}
|
||||
|
||||
if (options && Number.isFinite(options.maxCut)) {
|
||||
this.maxCut = options.maxCut;
|
||||
}
|
||||
|
||||
this.additiveBlending = options && options.additive;
|
||||
if (this.additiveBlending === undefined) {
|
||||
|
||||
@@ -102,9 +102,11 @@ export class CircleSelect extends FSM {
|
||||
|
||||
// execute general callback
|
||||
if (view.aladin.callbacksByEventName) {
|
||||
var callback = view.aladin.callbacksByEventName['select'];
|
||||
var callback = view.aladin.callbacksByEventName['objectsSelected'] || view.aladin.callbacksByEventName['select'];
|
||||
|
||||
if (typeof callback === "function") {
|
||||
let objList = Selector.getObjects(s, view);
|
||||
view.selectObjects(objList);
|
||||
callback(objList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ export class PolySelect extends FSM {
|
||||
|
||||
// execute general callback
|
||||
if (view.aladin.callbacksByEventName) {
|
||||
var callback = view.aladin.callbacksByEventName['select'];
|
||||
var callback = view.aladin.callbacksByEventName['objectsSelected'] || view.aladin.callbacksByEventName['select'];
|
||||
if (typeof callback === "function") {
|
||||
console.warn('polygon selection is not fully implemented, PolySelect.contains is needed for finding sources inside a polygon')
|
||||
}
|
||||
|
||||
@@ -107,9 +107,10 @@ export class RectSelect extends FSM {
|
||||
|
||||
// execute general callback
|
||||
if (view.aladin.callbacksByEventName) {
|
||||
var callback = view.aladin.callbacksByEventName['select'];
|
||||
var callback = view.aladin.callbacksByEventName['objectsSelected'] || view.aladin.callbacksByEventName['select'];
|
||||
if (typeof callback === "function") {
|
||||
let objList = Selector.getObjects(s, view);
|
||||
view.selectObjects(objList);
|
||||
callback(objList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
/******************************************************************************
|
||||
* Aladin Lite project
|
||||
*
|
||||
* File ImageFITS
|
||||
* File Image
|
||||
*
|
||||
* Authors: Matthieu Baumann [CDS]
|
||||
*
|
||||
@@ -40,8 +40,8 @@ import { Aladin } from "./Aladin.js";
|
||||
* @property {string} [colormap="native"] - The colormap configuration for the survey or image.
|
||||
* @property {string} [stretch="linear"] - The stretch configuration for the survey or image.
|
||||
* @property {boolean} [reversed=false] - If true, the colormap is reversed; otherwise, it is not reversed.
|
||||
* @property {number} [minCut] - The minimum cut value for the color configuration. If not given, 0.0 for JPEG/PNG surveys, the value of the property file for FITS surveys
|
||||
* @property {number} [maxCut] - The maximum cut value for the color configuration. If not given, 1.0 for JPEG/PNG surveys, the value of the property file for FITS surveys
|
||||
* @property {number} [minCut=0.0] - The minimum cut value for the color configuration. If not given, 0.0 is chosen
|
||||
* @property {number} [maxCut=1.0] - The maximum cut value for the color configuration. If not given, 1.0 is chosen
|
||||
* @property {boolean} [additive=false] - If true, additive blending is applied; otherwise, it is not applied.
|
||||
* @property {number} [gamma=1.0] - The gamma correction value for the color configuration.
|
||||
* @property {number} [saturation=0.0] - The saturation value for the color configuration.
|
||||
@@ -115,10 +115,12 @@ export let Image = (function () {
|
||||
/*if (options) {
|
||||
options.stretch = options.stretch || "asinh";
|
||||
}*/
|
||||
|
||||
this.colorCfg = new ColorCfg(options);
|
||||
this.options = options;
|
||||
|
||||
let self = this;
|
||||
|
||||
this.query = Promise.resolve(self);
|
||||
}
|
||||
|
||||
@@ -310,9 +312,12 @@ export let Image = (function () {
|
||||
self.setView(self.view);
|
||||
|
||||
// Set the automatic computed cuts
|
||||
let [minCut, maxCut] = self.getCuts();
|
||||
minCut = minCut || imageParams.min_cut;
|
||||
maxCut = maxCut || imageParams.max_cut;
|
||||
self.setCuts(
|
||||
imageParams.min_cut,
|
||||
imageParams.max_cut
|
||||
minCut,
|
||||
maxCut
|
||||
);
|
||||
|
||||
self.ra = imageParams.centered_fov.ra;
|
||||
|
||||
@@ -184,6 +184,9 @@ export let ImageHiPS = (function () {
|
||||
? false
|
||||
: options.longitudeReversed;
|
||||
this.imgFormat = options.imgFormat;
|
||||
this.formats = options.formats;
|
||||
this.defaultFitsMinCut = options.defaultFitsMinCut;
|
||||
this.defaultFitsMaxCut = options.defaultFitsMaxCut;
|
||||
this.numBitsPerPixel = options.numBitsPerPixel;
|
||||
this.creatorDid = options.creatorDid;
|
||||
this.errorCallback = options.errorCallback;
|
||||
@@ -331,8 +334,8 @@ export let ImageHiPS = (function () {
|
||||
|
||||
// Cutouts
|
||||
const cutoutFromProperties = PropertyParser.cutouts(properties);
|
||||
self.minCut = cutoutFromProperties[0];
|
||||
self.maxCut = cutoutFromProperties[1];
|
||||
self.defaultFitsMinCut = cutoutFromProperties[0];
|
||||
self.defaultFitsMaxCut = cutoutFromProperties[1];
|
||||
|
||||
// Bitpix
|
||||
self.numBitsPerPixel =
|
||||
@@ -418,8 +421,8 @@ export let ImageHiPS = (function () {
|
||||
let minCut, maxCut;
|
||||
if (self.imgFormat === "fits") {
|
||||
// Take into account the default cuts given by the property file (this is true especially for FITS HiPSes)
|
||||
minCut = self.colorCfg.minCut || self.minCut || 0.0;
|
||||
maxCut = self.colorCfg.maxCut || self.maxCut || 1.0;
|
||||
minCut = self.colorCfg.minCut || self.defaultFitsMinCut || 0.0;
|
||||
maxCut = self.colorCfg.maxCut || self.defaultFitsMaxCut || 1.0;
|
||||
} else {
|
||||
minCut = self.colorCfg.minCut || 0.0;
|
||||
maxCut = self.colorCfg.maxCut || 1.0;
|
||||
@@ -456,7 +459,6 @@ export let ImageHiPS = (function () {
|
||||
|
||||
ImageHiPS.prototype._saveInCache = function () {
|
||||
let self = this;
|
||||
|
||||
let colorOpt = Object.fromEntries(Object.entries(this.colorCfg));
|
||||
let surveyOpt = {
|
||||
id: self.id,
|
||||
@@ -467,9 +469,12 @@ export let ImageHiPS = (function () {
|
||||
cooFrame: self.cooFrame,
|
||||
maxOrder: self.maxOrder,
|
||||
tileSize: self.tileSize,
|
||||
formats: self.formats,
|
||||
imgFormat: self.imgFormat,
|
||||
successCallback: self.successCallback,
|
||||
errorCallback: self.errorCallback,
|
||||
defaultFitsMinCut: self.defaultFitsMinCut,
|
||||
defaultFitsMaxCut: self.defaultFitsMaxCut,
|
||||
...colorOpt,
|
||||
};
|
||||
|
||||
@@ -577,9 +582,9 @@ export let ImageHiPS = (function () {
|
||||
self.imgFormat === "jpeg") &&
|
||||
imgFormat === "fits"
|
||||
) {
|
||||
if (self.minCut && self.maxCut) {
|
||||
if (Number.isFinite(self.defaultFitsMinCut) && Number.isFinite(self.defaultFitsMaxCut)) {
|
||||
// reset cuts to those given from the properties
|
||||
self.setCuts(self.minCut, self.maxCut);
|
||||
self.setCuts(self.defaultFitsMinCut, self.defaultFitsMaxCut);
|
||||
}
|
||||
// Switch from fits to png/webp/jpeg
|
||||
} else if (self.imgFormat === "fits") {
|
||||
|
||||
@@ -1668,16 +1668,16 @@ export let View = (function () {
|
||||
const layerName = imageLayer.layer;
|
||||
// Check whether this layer already exist
|
||||
const idxOverlayLayer = this.overlayLayers.findIndex(overlayLayer => overlayLayer == layerName);
|
||||
let alreadyPresentImageLayer;
|
||||
if (idxOverlayLayer == -1) {
|
||||
// it does not exist so we add it to the stack
|
||||
this.overlayLayers.push(layerName);
|
||||
} else {
|
||||
// it exists
|
||||
let alreadyPresentImageLayer = this.imageLayers.get(layerName);
|
||||
alreadyPresentImageLayer = this.imageLayers.get(layerName);
|
||||
alreadyPresentImageLayer.added = false;
|
||||
|
||||
// Notify that this image layer has been replaced by the wasm part
|
||||
ALEvent.HIPS_LAYER_REMOVED.dispatchedTo(this.aladinDiv, { layer: alreadyPresentImageLayer });
|
||||
this.imageLayers.delete(layerName);
|
||||
}
|
||||
|
||||
imageLayer.added = true;
|
||||
@@ -1688,6 +1688,11 @@ export let View = (function () {
|
||||
if (idxOverlayLayer == -1) {
|
||||
this.selectLayer(layerName);
|
||||
}
|
||||
|
||||
// Notify that this image layer has been replaced by the wasm part
|
||||
if (alreadyPresentImageLayer) {
|
||||
ALEvent.HIPS_LAYER_REMOVED.dispatchedTo(this.aladinDiv, { layer: alreadyPresentImageLayer });
|
||||
}
|
||||
|
||||
ALEvent.HIPS_LAYER_ADDED.dispatchedTo(this.aladinDiv, { layer: imageLayer });
|
||||
}
|
||||
|
||||
@@ -99,12 +99,12 @@ import { ColorCfg } from "../../ColorCfg.js";
|
||||
// Define the contents
|
||||
|
||||
let opacitySettingsContent = new Form({
|
||||
type: 'group',
|
||||
subInputs: [
|
||||
{
|
||||
label: 'opacity:',
|
||||
name: 'opacity',
|
||||
tooltip: {content: 1.0, position: {direction: 'bottom'}},
|
||||
name: 'opacitySlider',
|
||||
name: 'opacity',
|
||||
type: 'range',
|
||||
min: 0.0,
|
||||
max: 1.0,
|
||||
@@ -229,7 +229,6 @@ import { ColorCfg } from "../../ColorCfg.js";
|
||||
options: ColorCfg.COLORMAPS,
|
||||
change: (e, cmapSelector) => {
|
||||
self.options.layer.setColormap(e.target.value)
|
||||
//cmapSelector.update({value: e.target.value})
|
||||
},
|
||||
}]
|
||||
});
|
||||
@@ -271,14 +270,20 @@ import { ColorCfg } from "../../ColorCfg.js";
|
||||
}
|
||||
fmtInput.value = hips.imgFormat;
|
||||
|
||||
|
||||
this.colorSettingsContent.set('cmap', colormap)
|
||||
this.opacitySettingsContent.set('opacity', hips.getOpacity())
|
||||
this.colorSettingsContent.set('cmap', colormap);
|
||||
this.opacitySettingsContent.set('opacity', hips.getOpacity());
|
||||
this.luminositySettingsContent.set('brightness', colorCfg.getBrightness());
|
||||
this.luminositySettingsContent.set('contrast', colorCfg.getContrast());
|
||||
this.luminositySettingsContent.set('saturation', colorCfg.getSaturation());
|
||||
}
|
||||
|
||||
super.update(options)
|
||||
}
|
||||
|
||||
_updateCursors() {
|
||||
|
||||
}
|
||||
|
||||
_show(options) {
|
||||
/*if (this.selector) {
|
||||
this.selector._show();
|
||||
@@ -300,13 +305,24 @@ import { ColorCfg } from "../../ColorCfg.js";
|
||||
let colorCfg = hips.getColorCfg();
|
||||
let stretch = colorCfg.stretch;
|
||||
let colormap = colorCfg.getColormap();
|
||||
|
||||
|
||||
let [minCut, maxCut] = colorCfg.getCuts();
|
||||
this.pixelSettingsContent.set('mincut', +minCut.toFixed(4))
|
||||
this.pixelSettingsContent.set('maxcut', +maxCut.toFixed(4))
|
||||
this.pixelSettingsContent.set('stretch', stretch)
|
||||
this.colorSettingsContent.set('cmap', colormap)
|
||||
this.opacitySettingsContent.set('opacity', hips.getOpacity())
|
||||
let fmtInput = this.pixelSettingsContent.getInput('fmt')
|
||||
|
||||
fmtInput.innerHTML = '';
|
||||
for (const option of hips.formats) {
|
||||
fmtInput.innerHTML += "<option>" + option + "</option>";
|
||||
}
|
||||
fmtInput.value = hips.imgFormat;
|
||||
|
||||
this.colorSettingsContent.set('cmap', colormap);
|
||||
this.opacitySettingsContent.set('opacity', hips.getOpacity());
|
||||
this.luminositySettingsContent.set('brightness', colorCfg.getBrightness());
|
||||
this.luminositySettingsContent.set('contrast', colorCfg.getContrast());
|
||||
this.luminositySettingsContent.set('saturation', colorCfg.getSaturation());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -646,13 +646,6 @@ export class OverlayStackBox extends Box {
|
||||
}
|
||||
);
|
||||
|
||||
ALEvent.HIPS_LAYER_RENAMED.listenedBy(
|
||||
this.aladin.aladinDiv,
|
||||
function (e) {
|
||||
updateOverlayList();
|
||||
}
|
||||
);
|
||||
|
||||
ALEvent.HIPS_LAYER_SWAP.listenedBy(this.aladin.aladinDiv, function (e) {
|
||||
updateOverlayList();
|
||||
});
|
||||
@@ -912,6 +905,7 @@ export class OverlayStackBox extends Box {
|
||||
hipsOptions.sort()
|
||||
|
||||
for (const layer of layers) {
|
||||
|
||||
let HiPSSelector = Input.select({
|
||||
value: layer.name,
|
||||
options: hipsOptions,
|
||||
@@ -974,9 +968,11 @@ export class OverlayStackBox extends Box {
|
||||
});
|
||||
|
||||
let settingsBox = new HiPSSettingsBox(self.aladin);
|
||||
|
||||
settingsBox.update({ layer });
|
||||
settingsBox._hide();
|
||||
|
||||
|
||||
let settingsBtn = new TogglerActionButton({
|
||||
icon: { url: settingsIconUrl, monochrome: true },
|
||||
size: "small",
|
||||
@@ -986,6 +982,15 @@ export class OverlayStackBox extends Box {
|
||||
},
|
||||
toggled: false,
|
||||
actionOn: (e) => {
|
||||
// toggle off the other settings if opened
|
||||
for (var l in self.HiPSui) {
|
||||
let ui = self.HiPSui[l]
|
||||
|
||||
if (l != layer.layer) {
|
||||
ui.settingsBtn.close();
|
||||
}
|
||||
}
|
||||
|
||||
settingsBox._show({
|
||||
position: {
|
||||
nextTo: settingsBtn,
|
||||
|
||||
@@ -51,6 +51,12 @@ export class TogglerActionButton extends ActionButton {
|
||||
self = this;
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.toggled) {
|
||||
this.toggle()
|
||||
}
|
||||
}
|
||||
|
||||
toggle(o) {
|
||||
this.toggled = !this.toggled;
|
||||
|
||||
|
||||
@@ -60,6 +60,9 @@ export class SettingsCtxMenu extends ContextMenu {
|
||||
value: reticleColor.toHex(),
|
||||
name: 'reticleColor',
|
||||
change(e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault();
|
||||
|
||||
let hex = e.target.value;
|
||||
let reticle = aladin.getReticle();
|
||||
reticle.update({color: hex})
|
||||
@@ -170,7 +173,7 @@ export class SettingsCtxMenu extends ContextMenu {
|
||||
{
|
||||
label: {
|
||||
content: [self.reticleColorInput, 'Color']
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: Layout.horizontal(['Size', sliderReticleSize]),
|
||||
|
||||
Reference in New Issue
Block a user