1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
/*
* File: gain.rs
* Project: src
* Created Date: 27/04/2022
* Author: Shun Suzuki
* -----
* Last Modified: 12/09/2023
* Modified By: Shun Suzuki (suzuki@hapis.k.u-tokyo.ac.jp)
* -----
* Copyright (c) 2022-2023 Shun Suzuki. All rights reserved.
*
*/
use std::collections::HashMap;
use crate::{
defined::Drive,
error::AUTDInternalError,
geometry::{Device, Geometry, Transducer},
};
use bitvec::prelude::*;
pub enum GainFilter<'a> {
All,
Filter(&'a HashMap<usize, BitVec<usize, Lsb0>>),
}
pub trait GainAsAny {
fn as_any(&self) -> &dyn std::any::Any;
}
/// Gain controls amplitude and phase of each transducer.
pub trait Gain<T: Transducer>: GainAsAny {
fn calc(
&self,
geometry: &Geometry<T>,
filter: GainFilter,
) -> Result<HashMap<usize, Vec<Drive>>, AUTDInternalError>;
fn transform<F: Fn(&Device<T>, &T) -> Drive + Sync + Send>(
geometry: &Geometry<T>,
filter: GainFilter,
f: F,
) -> HashMap<usize, Vec<Drive>>
where
Self: Sized,
{
match filter {
GainFilter::All => geometry
.devices()
.map(|dev| (dev.idx(), dev.iter().map(|tr| f(dev, tr)).collect()))
.collect(),
GainFilter::Filter(filter) => geometry
.devices()
.map(|dev| {
if let Some(filter) = filter.get(&dev.idx()) {
(
dev.idx(),
dev.iter()
.map(|tr| {
if filter[tr.local_idx()] {
f(dev, tr)
} else {
Drive { phase: 0., amp: 0. }
}
})
.collect(),
)
} else {
(
dev.idx(),
dev.iter().map(|_| Drive { phase: 0., amp: 0. }).collect(),
)
}
})
.collect(),
}
}
}
impl<'a, T: Transducer> GainAsAny for Box<dyn Gain<T> + 'a> {
fn as_any(&self) -> &dyn std::any::Any {
self.as_ref().as_any()
}
}
impl<'a, T: Transducer> Gain<T> for Box<dyn Gain<T> + 'a> {
fn calc(
&self,
geometry: &Geometry<T>,
filter: GainFilter,
) -> Result<HashMap<usize, Vec<Drive>>, AUTDInternalError> {
self.as_ref().calc(geometry, filter)
}
}