use std::{
cmp::Ordering,
error::Error,
iter::{Cloned, Map},
slice::Iter,
vec::IntoIter,
};
use num_traits::{Float, FloatConst, FromPrimitive, PrimInt};
use crate::nested::{map::mom::new_chi2_density_merger, n_hash};
use super::{
super::{
super::skymap::{SkyMap, SkyMapValue},
LhsRhsBoth, Mom, ZUniqHashT,
},
bslice::{MomSliceImpl, V4FITS, Z4FITS},
};
#[derive(Debug)]
pub struct MomVecImpl<Z, V>
where
Z: ZUniqHashT,
V: SkyMapValue,
{
depth: u8,
entries: Vec<(Z, V)>,
}
impl<'a, Z, V> From<MomSliceImpl<'a, Z, V>> for MomVecImpl<Z, V>
where
Z: Z4FITS,
V: V4FITS,
{
fn from(mom: MomSliceImpl<'a, Z, V>) -> Self {
let depth = mom.depth_max();
let entries = mom.owned_entries().collect();
Self { depth, entries }
}
}
impl<'a, Z, V> Mom<'a> for MomVecImpl<Z, V>
where
Z: ZUniqHashT,
V: 'a + SkyMapValue,
{
type ZUniqHType = Z;
type ValueType = V;
type OverlappedEntries = Map<Iter<'a, (Z, V)>, fn(&'a (Z, V)) -> (Z, &'a V)>;
type OverlappedEntriesCopy = Cloned<Iter<'a, (Z, V)>>;
type ZuniqIt = Map<Iter<'a, (Z, V)>, fn(&'a (Z, V)) -> Z>;
type ValuesIt = Map<Iter<'a, (Z, V)>, fn(&'a (Z, V)) -> &'a V>;
type ValuesCopyIt = Cloned<Self::ValuesIt>;
type EntriesIt = Map<Iter<'a, (Z, V)>, fn(&'a (Z, V)) -> (Z, &'a V)>;
type EntriesCopyIt = Cloned<Iter<'a, (Z, V)>>;
type OwnedEntriesIt = IntoIter<(Z, V)>;
fn depth_max(&self) -> u8 {
self.depth
}
fn len(&self) -> usize {
self.entries.len()
}
fn get_cell_containing_unsafe(
&'a self,
hash_at_depth_max: Self::ZUniqHType,
) -> Option<(Self::ZUniqHType, &'a Self::ValueType)> {
match self
.entries
.binary_search_by(|&(z, _)| z.cmp(&hash_at_depth_max))
{
Ok(i) => {
let e = &self.entries[i];
Some((e.0, &e.1))
}
Err(i) => {
if i > 0 {
let e = &self.entries[i - 1];
if Z::are_overlapping(hash_at_depth_max, e.0) {
return Some((e.0, &e.1));
}
}
if i < self.entries.len() {
let e = &self.entries[i];
if Z::are_overlapping(hash_at_depth_max, e.0) {
return Some((e.0, &e.1));
}
}
None
}
}
}
fn get_copy_of_cell_containing_unsafe(
&'a self,
zuniq_at_depth_max: Self::ZUniqHType,
) -> Option<(Self::ZUniqHType, Self::ValueType)> {
match self
.entries
.binary_search_by(|&(z, _)| z.cmp(&zuniq_at_depth_max))
{
Ok(i) => {
let e = &self.entries[i];
Some(e.clone())
}
Err(i) => {
if i > 0 {
let e = &self.entries[i - 1];
if Z::are_overlapping(zuniq_at_depth_max, e.0) {
return Some(e.clone());
}
}
if i < self.entries.len() {
let e = &self.entries[i];
if Z::are_overlapping(zuniq_at_depth_max, e.0) {
return Some(e.clone());
}
}
None
}
}
}
fn get_overlapped_cells(&'a self, zuniq: Self::ZUniqHType) -> Self::OverlappedEntries {
let mut range = match self.entries.binary_search_by(|&(z, _)| z.cmp(&zuniq)) {
Ok(i) => i..i + 1,
Err(i) => i..i,
};
while range.start - 1 > 0 && Z::are_overlapping(zuniq, self.entries[range.start - 1].0) {
range.start -= 1;
}
while range.end < self.entries.len() && Z::are_overlapping(zuniq, self.entries[range.end].0) {
range.end += 1;
}
self.entries[range].iter().map(|(z, v)| (*z, v))
}
fn get_copy_of_overlapped_cells(
&'a self,
zuniq: Self::ZUniqHType,
) -> Self::OverlappedEntriesCopy {
let mut range = match self.entries.binary_search_by(|&(z, _)| z.cmp(&zuniq)) {
Ok(i) => i..i + 1,
Err(i) => i..i,
};
while range.start - 1 > 0 && Z::are_overlapping(zuniq, self.entries[range.start - 1].0) {
range.start -= 1;
}
while range.end < self.entries.len() && Z::are_overlapping(zuniq, self.entries[range.end].0) {
range.end += 1;
}
self.entries[range].iter().cloned()
}
fn zuniqs(&'a self) -> Self::ZuniqIt {
self.entries.iter().map(|&(zuniq, _)| zuniq)
}
fn values(&'a self) -> Self::ValuesIt {
self.entries.iter().map(|(_, value)| value)
}
fn values_copy(&'a self) -> Self::ValuesCopyIt {
self.values().cloned()
}
fn entries(&'a self) -> Self::EntriesIt {
self.entries.iter().map(|(z, v)| (*z, v))
}
fn entries_copy(&'a self) -> Self::EntriesCopyIt {
self.entries.iter().cloned()
}
fn owned_entries(self) -> Self::OwnedEntriesIt {
self.entries.into_iter()
}
fn from_hpx_sorted_entries<I, M>(depth: u8, sorted_entries_it: I, merger: M) -> Self
where
I: Iterator<Item = (Self::ZUniqHType, Self::ValueType)>,
M: Fn(
u8,
Self::ZUniqHType,
[Self::ValueType; 4],
) -> Result<Self::ValueType, [Self::ValueType; 4]>,
{
let parent_depth = depth - 1;
let mut entries: Vec<(Z, V)> =
Vec::with_capacity(((n_hash(depth) >> 2) as usize).min(10_000_000)); let mut expected_next_hash = Z::zero();
for (h, v) in sorted_entries_it {
entries.push((Z::to_zuniq(depth, h), v));
let parent_h = h >> 2;
if h == expected_next_hash && h & Z::LAST_LAYER_MASK == Z::LAST_LAYER_MASK {
let (z3, v3) = entries.pop().unwrap();
let (z2, v2) = entries.pop().unwrap();
let (z1, v1) = entries.pop().unwrap();
let (z0, v0) = entries.pop().unwrap();
match merger(parent_depth, parent_h, [v0, v1, v2, v3]) {
Ok(v_merged) => {
let z_merged = Z::to_zuniq(parent_depth, parent_h);
entries.push((z_merged, v_merged));
Self::from_skymap_recursive(&mut entries, &merger);
}
Err([v0, v1, v2, v3]) => {
entries.push((z0, v0));
entries.push((z1, v1));
entries.push((z2, v2));
entries.push((z3, v3));
}
}
} else if h & Z::LAST_LAYER_MASK == Z::zero() {
expected_next_hash = h;
}
expected_next_hash += Z::one();
}
Self { depth, entries }
}
fn from_hpx_sorted_entries_fallible<E, I, M>(
depth: u8,
sorted_entries_it: I,
merger: M,
) -> Result<Self, E>
where
E: Error,
I: Iterator<Item = Result<(Self::ZUniqHType, Self::ValueType), E>>,
M: Fn(
u8,
Self::ZUniqHType,
[Self::ValueType; 4],
) -> Result<Self::ValueType, [Self::ValueType; 4]>,
{
let parent_depth = depth - 1;
let mut entries: Vec<(Z, V)> =
Vec::with_capacity(((n_hash(depth) >> 2) as usize).min(10_000_000)); let mut expected_next_hash = Z::zero();
for res_hv in sorted_entries_it {
let (h, v) = res_hv?;
entries.push((Z::to_zuniq(depth, h), v));
let parent_h = h >> 2;
if h == expected_next_hash && h & Z::LAST_LAYER_MASK == Z::LAST_LAYER_MASK {
let (z3, v3) = entries.pop().unwrap();
let (z2, v2) = entries.pop().unwrap();
let (z1, v1) = entries.pop().unwrap();
let (z0, v0) = entries.pop().unwrap();
match merger(parent_depth, parent_h, [v0, v1, v2, v3]) {
Ok(v_merged) => {
let z_merged = Z::to_zuniq(parent_depth, parent_h);
entries.push((z_merged, v_merged));
Self::from_skymap_recursive(&mut entries, &merger);
}
Err([v0, v1, v2, v3]) => {
entries.push((z0, v0));
entries.push((z1, v1));
entries.push((z2, v2));
entries.push((z3, v3));
}
}
} else if h & Z::LAST_LAYER_MASK == Z::zero() {
expected_next_hash = h;
}
expected_next_hash += Z::one();
}
Ok(Self { depth, entries })
}
fn from_skymap_ref<'s, S, M>(skymap: &'s S, merger: M) -> Self
where
S: SkyMap<'s, HashType = Z, ValueType = V>,
M: Fn(u8, Z, [&V; 4]) -> Option<V>,
V: 's,
{
let depth = skymap.depth();
let parent_depth = depth - 1;
let mut entries: Vec<(Z, V)> = Vec::with_capacity(skymap.len());
let mut expected_next_hash = Z::zero();
for (h, v) in skymap.entries() {
entries.push((Z::to_zuniq(depth, h), v.clone()));
if h == expected_next_hash && h & Z::LAST_LAYER_MASK == Z::LAST_LAYER_MASK {
let n = entries.len();
let parent_h = h >> 2;
if let Some(combined_value) = merger(
parent_depth,
parent_h,
[
&entries[n - 4].1, &entries[n - 3].1, &entries[n - 2].1, &entries[n - 1].1, ],
) {
entries.truncate(n - 4);
let new_zuniq = Z::to_zuniq(parent_depth, parent_h);
entries.push((new_zuniq, combined_value));
Self::from_skymap_ref_recursive(&mut entries, &merger);
}
} else if h & Z::LAST_LAYER_MASK == Z::zero() {
expected_next_hash = h;
}
expected_next_hash += Z::one();
}
Self { depth, entries }
}
fn from_skymap<'s, S, M>(skymap: S, merger: M) -> Self
where
S: SkyMap<'s, HashType = Self::ZUniqHType, ValueType = Self::ValueType>,
M: Fn(u8, Z, [V; 4]) -> Result<V, [V; 4]>,
Self::ValueType: 's,
{
Self::from_hpx_sorted_entries(skymap.depth(), skymap.owned_entries(), merger)
}
fn merge<'s, L, R, S, O, M>(lhs: L, rhs: R, split: S, op: O, merge: M) -> Self
where
L: Mom<'s, ZUniqHType = Z, ValueType = V>,
R: Mom<'s, ZUniqHType = Z, ValueType = V>,
S: Fn(u8, Z, V) -> [V; 4],
O: Fn(LhsRhsBoth<V>) -> Option<V>,
M: Fn(u8, Z, [V; 4]) -> Result<V, [V; 4]>,
{
#[derive(Clone)]
struct DHZ<ZZ: ZUniqHashT> {
d: u8,
h: ZZ,
z: ZZ,
}
impl<ZZ: ZUniqHashT> DHZ<ZZ> {
fn new(d: u8, h: ZZ, z: ZZ) -> Self {
Self { d, h, z }
}
fn next(&self) -> Self {
let next_h = self.h + ZZ::one();
Self::new(self.d, next_h, ZZ::to_zuniq(self.d, next_h))
}
}
struct DHZV<ZZ: ZUniqHashT, VV> {
d: u8,
h: ZZ,
z: ZZ,
v: VV,
}
impl<ZZ: ZUniqHashT, VV> DHZV<ZZ, VV> {
fn new(d: u8, h: ZZ, z: ZZ, v: VV) -> Self {
Self { d, h, z, v }
}
}
let zv_to_dhzv = |(z, v)| {
let (d, h) = Self::ZUniqHType::from_zuniq(z);
DHZV { d, h, z, v }
};
let depth = lhs.depth_max().max(rhs.depth_max());
let mut stack: Vec<(Z, V)> = Vec::with_capacity(lhs.len() + rhs.len());
let mut it_left = lhs.owned_entries().map(zv_to_dhzv);
let mut it_right = rhs.owned_entries().map(zv_to_dhzv);
let mut lstack: Vec<DHZV<Z, V>> = Vec::with_capacity(128);
let mut rstack: Vec<DHZV<Z, V>> = Vec::with_capacity(128);
let mut left: Option<DHZV<Z, V>> = it_left.next();
let mut right: Option<DHZV<Z, V>> = it_right.next();
let mut expected_next_dhz = DHZ::new(depth, Z::zero(), Z::to_zuniq(depth, Z::zero()));
let mut last_dhz_added = expected_next_dhz.clone();
loop {
match (left, right) {
(Some(l), Some(r)) => match l.d.cmp(&r.d) {
Ordering::Equal => match l.h.cmp(&r.h) {
Ordering::Equal => {
if let Some(v) = op(LhsRhsBoth::Both(l.v, r.v)) {
last_dhz_added = DHZ::new(l.d, l.h, l.z);
stack.push((l.z, v));
}
left = if !lstack.is_empty() {
lstack.pop()
} else {
it_left.next()
};
right = if !rstack.is_empty() {
rstack.pop()
} else {
it_right.next()
};
}
Ordering::Less => {
if let Some(v) = op(LhsRhsBoth::Left(l.v)) {
last_dhz_added = DHZ::new(l.d, l.h, l.z);
stack.push((l.z, v));
}
left = if !lstack.is_empty() {
lstack.pop()
} else {
it_left.next()
};
right = Some(r);
}
Ordering::Greater => {
if let Some(v) = op(LhsRhsBoth::Right(r.v)) {
last_dhz_added = DHZ::new(r.d, r.h, r.z);
stack.push((r.z, v));
}
right = if !rstack.is_empty() {
rstack.pop()
} else {
it_right.next()
};
left = Some(l);
}
},
Ordering::Less => {
let r_hash_at_l_depth = r.h >> (((r.d - l.d) << 1) as usize);
match l.h.cmp(&r_hash_at_l_depth) {
Ordering::Equal => {
let [v0, v1, v2, v3] = split(l.d, l.h, l.v);
let new_d = l.d + 1;
let new_h = l.h << 2;
lstack.push(DHZV::new(
new_d,
new_h + Z::three(),
Z::to_zuniq(new_d, new_h + Z::three()),
v3,
));
lstack.push(DHZV::new(
new_d,
new_h + Z::two(),
Z::to_zuniq(new_d, new_h + Z::two()),
v2,
));
lstack.push(DHZV::new(
new_d,
new_h + Z::one(),
Z::to_zuniq(new_d, new_h + Z::one()),
v1,
));
left = Some(DHZV::new(new_d, new_h, Z::to_zuniq(new_d, new_h), v0));
right = Some(r);
}
Ordering::Less => {
if let Some(v) = op(LhsRhsBoth::Left(l.v)) {
last_dhz_added = DHZ::new(l.d, l.h, l.z);
stack.push((l.z, v));
}
left = if !lstack.is_empty() {
lstack.pop()
} else {
it_left.next()
};
right = Some(r);
}
Ordering::Greater => {
if let Some(v) = op(LhsRhsBoth::Right(r.v)) {
last_dhz_added = DHZ::new(r.d, r.h, r.z);
stack.push((r.z, v));
}
right = if !rstack.is_empty() {
rstack.pop()
} else {
it_right.next()
};
left = Some(l);
}
}
}
Ordering::Greater => {
let l_has_at_r_depth = l.h >> (((l.d - r.d) << 1) as usize);
match l_has_at_r_depth.cmp(&r.h) {
Ordering::Equal => {
let [v0, v1, v2, v3] = split(r.d, r.h, r.v);
let new_d = r.d + 1;
let new_h = r.h << 2;
rstack.push(DHZV::new(
new_d,
new_h + Z::three(),
Z::to_zuniq(new_d, new_h + Z::three()),
v3,
));
rstack.push(DHZV::new(
new_d,
new_h + Z::two(),
Z::to_zuniq(new_d, new_h + Z::two()),
v2,
));
rstack.push(DHZV::new(
new_d,
new_h + Z::one(),
Z::to_zuniq(new_d, new_h + Z::one()),
v1,
));
left = Some(l);
right = Some(DHZV::new(new_d, new_h, Z::to_zuniq(new_d, new_h), v0));
}
Ordering::Less => {
if let Some(v) = op(LhsRhsBoth::Left(l.v)) {
last_dhz_added = DHZ::new(l.d, l.h, l.z);
stack.push((l.z, v));
}
left = if !lstack.is_empty() {
lstack.pop()
} else {
it_left.next()
};
right = Some(r);
}
Ordering::Greater => {
if let Some(v) = op(LhsRhsBoth::Right(r.v)) {
last_dhz_added = DHZ::new(r.d, r.h, r.z);
stack.push((r.z, v));
}
right = if !rstack.is_empty() {
rstack.pop()
} else {
it_right.next()
};
left = Some(l);
}
}
}
},
(None, None) => break, (mut left, None) => {
while let Some(l) = left {
if let Some(v) = op(LhsRhsBoth::Left(l.v)) {
last_dhz_added = DHZ::new(l.d, l.h, l.z);
stack.push((l.z, v));
}
left = if !lstack.is_empty() {
lstack.pop()
} else {
it_left.next()
};
if last_dhz_added.z == expected_next_dhz.z {
if last_dhz_added.h & Z::LAST_LAYER_MASK == Z::LAST_LAYER_MASK {
Self::from_skymap_recursive(&mut stack, &merge);
} else {
expected_next_dhz = last_dhz_added.next();
}
} else if last_dhz_added.h & Z::LAST_LAYER_MASK == Z::zero() {
expected_next_dhz = last_dhz_added.next();
}
}
break;
}
(None, mut right) => {
while let Some(r) = right {
if let Some(v) = op(LhsRhsBoth::Right(r.v)) {
last_dhz_added = DHZ::new(r.d, r.h, r.z);
stack.push((r.z, v));
}
right = if !rstack.is_empty() {
rstack.pop()
} else {
it_right.next()
};
if last_dhz_added.z == expected_next_dhz.z {
if last_dhz_added.h & Z::LAST_LAYER_MASK == Z::LAST_LAYER_MASK {
Self::from_skymap_recursive(&mut stack, &merge);
} else {
expected_next_dhz = last_dhz_added.next();
}
} else if last_dhz_added.h & Z::LAST_LAYER_MASK == Z::zero() {
expected_next_dhz = last_dhz_added.next();
}
}
break;
}
}
if last_dhz_added.z == expected_next_dhz.z {
if last_dhz_added.h & Z::LAST_LAYER_MASK == Z::LAST_LAYER_MASK {
Self::from_skymap_recursive(&mut stack, &merge);
} else {
expected_next_dhz = last_dhz_added.next();
}
} else if last_dhz_added.h & Z::LAST_LAYER_MASK == Z::zero() {
expected_next_dhz = last_dhz_added.next();
}
}
Self {
depth,
entries: stack,
}
}
}
impl<Z, V> MomVecImpl<Z, V>
where
Z: ZUniqHashT,
V: SkyMapValue,
{
pub(crate) fn new(depth: u8, entries: Vec<(Z, V)>) -> Self {
Self { depth, entries }
}
pub fn from_map<M, F>(mom: M, map: F) -> Self
where
M: for<'a> Mom<'a, ZUniqHType = Z>,
F: Fn(Z, <M as Mom>::ValueType) -> V,
{
let depth = mom.depth_max();
let entries: Vec<(Z, V)> = mom.owned_entries().map(|(z, v)| (z, map(z, v))).collect();
Self { depth, entries }
}
fn from_skymap_ref_recursive<'s, M>(stack: &mut Vec<(Z, V)>, merger: &M)
where
M: Fn(u8, Z, [&V; 4]) -> Option<V>,
V: 's,
{
let n = stack.len();
if n >= 4 {
let e0 = &stack[n - 4];
let (d0, h0) = Z::from_zuniq(e0.0);
if d0 > 0 && h0 & Z::LAST_LAYER_MASK == Z::zero() {
let e1 = &stack[n - 3];
let e2 = &stack[n - 2];
let e3 = &stack[n - 1];
if e1.0 == Z::to_zuniq(d0, h0 + Z::one())
&& e2.0 == Z::to_zuniq(d0, h0 + Z::two())
&& e3.0 == Z::to_zuniq(d0, h0 + Z::three())
{
let parent_depth = d0 - 1;
let parent_h = h0 >> 2;
if let Some(combined_value) = merger(
parent_depth,
parent_h,
[
&e0.1, &e1.1, &e2.1, &e3.1, ],
) {
let _ = stack.pop().unwrap();
let _ = stack.pop().unwrap();
let _ = stack.pop().unwrap();
let _ = stack.pop().unwrap();
let new_zuniq = Z::to_zuniq(parent_depth, parent_h);
stack.push((new_zuniq, combined_value));
Self::from_skymap_ref_recursive(stack, merger);
}
}
}
}
}
fn from_skymap_recursive<'s, M>(stack: &mut Vec<(Z, V)>, merger: &M)
where
M: Fn(u8, Z, [V; 4]) -> Result<V, [V; 4]>,
V: 's,
{
let n = stack.len();
if n >= 4 {
let z0 = stack[n - 4].0;
let (d0, h0) = Z::from_zuniq(z0);
if d0 > 0 && h0 & Z::LAST_LAYER_MASK == Z::zero() {
let z1 = stack[n - 3].0;
let z2 = stack[n - 2].0;
let z3 = stack[n - 1].0;
if z1 == Z::to_zuniq(d0, h0 + Z::one())
&& z2 == Z::to_zuniq(d0, h0 + Z::two())
&& z3 == Z::to_zuniq(d0, h0 + Z::three())
{
let (_, v3) = stack.pop().unwrap();
let (_, v2) = stack.pop().unwrap();
let (_, v1) = stack.pop().unwrap();
let (_, v0) = stack.pop().unwrap();
let parent_depth = d0 - 1;
let parent_h = h0 >> 2;
match merger(parent_depth, parent_h, [v0, v1, v2, v3]) {
Ok(v_merged) => {
let z_merged = Z::to_zuniq(d0 - 1, h0 >> 2);
stack.push((z_merged, v_merged));
Self::from_skymap_recursive(stack, merger);
}
Err([v0, v1, v2, v3]) => {
stack.push((z0, v0));
stack.push((z1, v1));
stack.push((z2, v2));
stack.push((z3, v3));
}
}
}
}
}
}
}
impl<Z, V> MomVecImpl<Z, V>
where
Z: ZUniqHashT,
V: SkyMapValue + Float + FloatConst + FromPrimitive,
{
pub fn from_counts_to_densities<'s, I, T>(count_mom: &'s T) -> Self
where
I: SkyMapValue + PrimInt,
T: Mom<'s, ZUniqHType = Z, ValueType = I> + 's,
{
const FOUR_PI: f64 = 4_f64 * std::f64::consts::PI;
let depth = count_mom.depth_max();
let entries: Vec<(Z, V)> = count_mom
.entries_copy()
.map(|(z, v)| {
(
z,
V::from_f64(v.to_f64().unwrap() / (FOUR_PI / (n_hash(Z::depth_from_zuniq(z))) as f64))
.unwrap(),
)
})
.collect();
MomVecImpl::new(depth, entries)
}
pub fn lhs_time_rhs_time_cte_and_chi2merge_assuming_densities<'s, L, R>(
lhs: L,
rhs: R,
cte: V,
chi2_of_3dof_threshold: f64,
depth_threshold: Option<u8>,
) -> Self
where
L: Mom<'s, ZUniqHType = Z, ValueType = V>,
R: Mom<'s, ZUniqHType = Z, ValueType = V>,
{
let split = |_depth: u8, _hash: Z, val: V| -> [V; 4] { [val; 4] };
let op = |lrb: LhsRhsBoth<V>| -> Option<V> {
match lrb {
LhsRhsBoth::Left(_) => None,
LhsRhsBoth::Right(_) => None,
LhsRhsBoth::Both(l, b) => Some(cte * l * b),
}
};
Self::merge(
lhs,
rhs,
split,
op,
new_chi2_density_merger(chi2_of_3dof_threshold, depth_threshold),
)
}
}
#[cfg(test)]
mod tests {
use std::f64::consts::PI;
use mapproj::pseudocyl::mol::Mol;
use crate::{
n_hash,
nested::map::{
img::{to_mom_png_file, ColorMapFunctionType, PosConversion},
mom::{
impls::zvec::MomVecImpl, new_chi2_count_ref_merger_no_depth_threshold, Mom, ZUniqHashT,
},
skymap::SkyMapEnum,
},
};
#[test]
#[cfg(not(target_arch = "wasm32"))]
fn test_skymap_to_mom_basic() {
let path = "test/resources/skymap/skymap.fits";
let skymap = SkyMapEnum::from_fits_file(path).unwrap();
match skymap {
SkyMapEnum::ImplicitU64I32(skymap) => {
let merger = |_depth: u8, _hash: u64, [n0, n1, n2, n3]: [&i32; 4]| -> Option<i32> {
let sum = *n0 + *n1 + *n2 + *n3;
if sum < 1_000_000 {
Some(sum)
} else {
None
}
};
let mut mom = MomVecImpl::from_skymap_ref(&skymap, merger);
let mom = MomVecImpl {
depth: mom.depth,
entries: mom
.entries
.drain(..)
.map(|(z, v)| {
(
z,
v as f64 / (4.0 * PI / (n_hash(u64::depth_from_zuniq(z))) as f64),
)
})
.collect::<Vec<(u64, f64)>>(),
};
to_mom_png_file::<'_, _, Mol, _>(
&mom,
(1600, 800),
None,
None,
None,
Some(PosConversion::EqMap2GalImg),
None,
Some(ColorMapFunctionType::LinearLog), "test/resources/skymap/mom.png",
false,
)
.unwrap();
}
_ => panic!(),
}
}
#[test]
#[cfg(not(target_arch = "wasm32"))]
fn test_skymap_to_mom_chi2() {
let path = "test/resources/skymap/skymap.fits";
let skymap = SkyMapEnum::from_fits_file(path).unwrap();
match skymap {
SkyMapEnum::ImplicitU64I32(skymap) => {
let merger = new_chi2_count_ref_merger_no_depth_threshold(16.266);
let mut mom = MomVecImpl::from_skymap_ref(&skymap, merger);
let mom = MomVecImpl {
depth: mom.depth,
entries: mom
.entries
.drain(..)
.map(|(z, v)| {
(
z,
v as f64 / (4.0 * PI / (n_hash(u64::depth_from_zuniq(z))) as f64),
)
})
.collect::<Vec<(u64, f64)>>(),
};
to_mom_png_file::<'_, _, Mol, _>(
&mom,
(1600, 800),
None,
None,
None,
Some(PosConversion::EqMap2GalImg),
None,
Some(ColorMapFunctionType::LinearLog), "test/resources/skymap/mom.png",
false,
)
.unwrap();
}
_ => panic!(),
}
}
}