Skip to main content

space_units/quantities/
radiation.rs

1use super::DisplayWithUnit;
2
3// -------------------------
4// Absorbed dose
5// -------------------------
6
7/// An absorbed radiation dose quantity, stored internally in grays (Gy).
8///
9/// # Construction
10/// ```
11/// # use space_units::AbsorbedDose;
12/// let dose = AbsorbedDose::from_mgy(50.0);
13/// ```
14#[must_use]
15#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
16pub struct AbsorbedDose(pub(crate) f64);
17
18/// Display/conversion units for [`AbsorbedDose`].
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum AbsorbedDoseUnit {
21    /// Grays (Gy).
22    Gray,
23    /// Milligrays (mGy).
24    MilliGray,
25    /// Micrograys (uGy).
26    MicroGray,
27    /// Rads (rad). 1 rad = 0.01 Gy.
28    Rad,
29}
30
31impl AbsorbedDoseUnit {
32    const fn symbol(self) -> &'static str {
33        match self {
34            Self::Gray => "Gy",
35            Self::MilliGray => "mGy",
36            Self::MicroGray => "uGy",
37            Self::Rad => "rad",
38        }
39    }
40
41    const fn gy_per_unit(self) -> f64 {
42        match self {
43            Self::Gray => 1.0,
44            Self::MilliGray => 1e-3,
45            Self::MicroGray => 1e-6,
46            Self::Rad => 0.01,
47        }
48    }
49}
50
51impl AbsorbedDose {
52    /// Create from grays (canonical unit).
53    pub const fn from_gy(val: f64) -> Self {
54        Self(val)
55    }
56
57    /// Create from milligrays. 1 mGy = 1e-3 Gy.
58    pub const fn from_mgy(val: f64) -> Self {
59        Self(val * 1e-3)
60    }
61
62    /// Create from micrograys. 1 uGy = 1e-6 Gy.
63    pub const fn from_ugy(val: f64) -> Self {
64        Self(val * 1e-6)
65    }
66
67    /// Create from rads. 1 rad = 0.01 Gy.
68    pub const fn from_rad_dose(val: f64) -> Self {
69        Self(val * 0.01)
70    }
71
72    /// Get value in grays.
73    pub const fn in_gy(self) -> f64 {
74        self.0
75    }
76
77    /// Get value in milligrays.
78    pub const fn in_mgy(self) -> f64 {
79        self.0 / 1e-3
80    }
81
82    /// Get value in micrograys.
83    pub const fn in_ugy(self) -> f64 {
84        self.0 / 1e-6
85    }
86
87    /// Get value in rads.
88    pub const fn in_rad_dose(self) -> f64 {
89        self.0 / 0.01
90    }
91
92    /// Get value in the specified [`AbsorbedDoseUnit`].
93    pub fn in_unit(self, unit: AbsorbedDoseUnit) -> f64 {
94        self.0 / unit.gy_per_unit()
95    }
96
97    /// Return a display wrapper that formats this dose in the given unit.
98    pub fn display_as(self, unit: AbsorbedDoseUnit) -> DisplayWithUnit {
99        DisplayWithUnit {
100            value: self.in_unit(unit),
101            symbol: unit.symbol(),
102        }
103    }
104
105    /// Return the absolute value of this absorbed dose.
106    pub fn abs(self) -> Self {
107        Self(self.0.abs())
108    }
109}
110
111impl_quantity_display!(AbsorbedDose, "Gy");
112
113impl_common_ops!(AbsorbedDose);
114
115// -------------------------
116// Dose equivalent
117// -------------------------
118
119/// A dose equivalent quantity, stored internally in sieverts (Sv).
120///
121/// # Construction
122/// ```
123/// # use space_units::DoseEquivalent;
124/// let eq = DoseEquivalent::from_msv(1.0);
125/// ```
126#[must_use]
127#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
128pub struct DoseEquivalent(pub(crate) f64);
129
130/// Display/conversion units for [`DoseEquivalent`].
131#[derive(Debug, Clone, Copy, PartialEq, Eq)]
132pub enum DoseEquivalentUnit {
133    /// Sieverts (Sv).
134    Sievert,
135    /// Millisieverts (mSv).
136    MilliSievert,
137    /// Microsieverts (uSv).
138    MicroSievert,
139    /// Rem (rem). 1 rem = 0.01 Sv.
140    Rem,
141}
142
143impl DoseEquivalentUnit {
144    const fn symbol(self) -> &'static str {
145        match self {
146            Self::Sievert => "Sv",
147            Self::MilliSievert => "mSv",
148            Self::MicroSievert => "uSv",
149            Self::Rem => "rem",
150        }
151    }
152
153    const fn sv_per_unit(self) -> f64 {
154        match self {
155            Self::Sievert => 1.0,
156            Self::MilliSievert => 1e-3,
157            Self::MicroSievert => 1e-6,
158            Self::Rem => 0.01,
159        }
160    }
161}
162
163impl DoseEquivalent {
164    /// Create from sieverts (canonical unit).
165    pub const fn from_sv(val: f64) -> Self {
166        Self(val)
167    }
168
169    /// Create from millisieverts. 1 mSv = 1e-3 Sv.
170    pub const fn from_msv(val: f64) -> Self {
171        Self(val * 1e-3)
172    }
173
174    /// Create from microsieverts. 1 uSv = 1e-6 Sv.
175    pub const fn from_usv(val: f64) -> Self {
176        Self(val * 1e-6)
177    }
178
179    /// Create from rem. 1 rem = 0.01 Sv.
180    pub const fn from_rem(val: f64) -> Self {
181        Self(val * 0.01)
182    }
183
184    /// Get value in sieverts.
185    pub const fn in_sv(self) -> f64 {
186        self.0
187    }
188
189    /// Get value in millisieverts.
190    pub const fn in_msv(self) -> f64 {
191        self.0 / 1e-3
192    }
193
194    /// Get value in microsieverts.
195    pub const fn in_usv(self) -> f64 {
196        self.0 / 1e-6
197    }
198
199    /// Get value in rem.
200    pub const fn in_rem(self) -> f64 {
201        self.0 / 0.01
202    }
203
204    /// Get value in the specified [`DoseEquivalentUnit`].
205    pub fn in_unit(self, unit: DoseEquivalentUnit) -> f64 {
206        self.0 / unit.sv_per_unit()
207    }
208
209    /// Return a display wrapper that formats this dose equivalent in the given unit.
210    pub fn display_as(self, unit: DoseEquivalentUnit) -> DisplayWithUnit {
211        DisplayWithUnit {
212            value: self.in_unit(unit),
213            symbol: unit.symbol(),
214        }
215    }
216
217    /// Return the absolute value of this dose equivalent.
218    pub fn abs(self) -> Self {
219        Self(self.0.abs())
220    }
221}
222
223impl_quantity_display!(DoseEquivalent, "Sv");
224
225impl_common_ops!(DoseEquivalent);