autd3_core/gain/
mod.rs

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
mod drive;
mod emit_intensity;
mod error;
mod phase;

use std::collections::HashMap;

/// A bit vector type.
pub type BitVec = bit_vec::BitVec<u32>;

pub use drive::Drive;
pub use emit_intensity::EmitIntensity;
pub use error::GainError;
pub use phase::Phase;

use crate::{
    datagram::{Segment, TransitionMode},
    geometry::{Device, Geometry, Transducer},
};

/// A trait to calculate the phase and intensity for [`Gain`].
///
/// [`Gain`]: crate::gain::Gain
pub trait GainCalculator: Send + Sync {
    /// Calculates the phase and intensity for the transducer.
    fn calc(&self, tr: &Transducer) -> Drive;
}

impl GainCalculator for Box<dyn GainCalculator> {
    fn calc(&self, tr: &Transducer) -> Drive {
        self.as_ref().calc(tr)
    }
}

/// A trait for generating a calculator for the gain operation.
pub trait GainCalculatorGenerator {
    /// The type of the calculator that actually performs the calculation.
    type Calculator: GainCalculator;

    /// Generate a calculator for the given device.
    fn generate(&mut self, device: &Device) -> Self::Calculator;
}

/// Trait for calculating the phase/amplitude of each transducer.
///
/// See also [`Gain`] derive macro.
///
/// [`Gain`]: autd3_derive::Gain
pub trait Gain: std::fmt::Debug + Sized {
    /// The type of the calculator generator.
    type G: GainCalculatorGenerator;

    /// Initialize the gain and generate the calculator generator.
    fn init(self) -> Result<Self::G, GainError>;

    /// Initialize the gain and generate the calculator generator.
    ///
    /// `filter` is a hash map that holds a bit vector representing the indices of the enabled transducers for each device index.
    /// If `filter` is `None`, all transducers are enabled.
    fn init_full(
        self,
        _: &Geometry,
        _filter: Option<&HashMap<usize, BitVec>>,
        _parallel: bool,
    ) -> Result<Self::G, GainError> {
        self.init()
    }
}

#[doc(hidden)]
pub struct GainOperationGenerator<G: GainCalculatorGenerator> {
    pub generator: G,
    pub segment: Segment,
    pub transition: Option<TransitionMode>,
}

impl<G: GainCalculatorGenerator> GainOperationGenerator<G> {
    pub fn new<T: Gain<G = G>>(
        gain: T,
        geometry: &Geometry,
        segment: Segment,
        transition: Option<TransitionMode>,
        parallel: bool,
    ) -> Result<Self, GainError> {
        Ok(Self {
            generator: gain.init_full(geometry, None, parallel)?,
            segment,
            transition,
        })
    }
}