nyx_space/od/ground_station/
python.rs1use super::super::msr::MeasurementType;
2use super::super::noise::StochasticNoise;
3use super::{DopplerConfig, GroundStation};
4use anise::astro::Location;
5use anise::frames::FrameUid;
6use indexmap::{IndexMap, IndexSet};
7use pyo3::prelude::*;
8use std::collections::HashMap;
9
10#[cfg(feature = "python")]
11#[pymethods]
12impl GroundStation {
13 #[new]
24 #[pyo3(signature = (name, location, stochastic_noises, doppler_config=None, light_time_correction=false, timestamp_noise_s=None, obstructing_body=None, relativistic_corrections=false))]
25 fn py_new(
26 name: String,
27 location: Location,
28 stochastic_noises: HashMap<MeasurementType, StochasticNoise>,
29 doppler_config: Option<DopplerConfig>,
30 light_time_correction: Option<bool>,
31 timestamp_noise_s: Option<StochasticNoise>,
32 obstructing_body: Option<FrameUid>,
33 relativistic_corrections: Option<bool>,
34 ) -> Self {
35 Self {
36 name,
37 location,
38 measurement_types: IndexSet::from_iter(
39 stochastic_noises
40 .keys()
41 .copied()
42 .collect::<Vec<MeasurementType>>(),
43 ),
44 doppler_config,
45 light_time_correction: light_time_correction.unwrap_or(false),
46 timestamp_noise_s,
47 stochastic_noises: Some(stochastic_noises.into_iter().collect()),
48 obstructing_body,
49 relativistic_corrections: relativistic_corrections.unwrap_or(false),
50 }
51 }
52
53 #[classmethod]
58 #[pyo3(name = "from_yaml")]
59 fn py_from_yaml(_cls: &Bound<'_, pyo3::types::PyType>, yaml_str: &str) -> PyResult<Self> {
60 serde_yml::from_str(yaml_str)
61 .map_err(|e| pyo3::exceptions::PyValueError::new_err(e.to_string()))
62 }
63
64 #[pyo3(name = "to_yaml")]
66 fn py_to_yaml(&self) -> PyResult<String> {
67 serde_yml::to_string(self)
68 .map_err(|e| pyo3::exceptions::PyValueError::new_err(e.to_string()))
69 }
70
71 #[classmethod]
76 #[pyo3(name = "load_many_yaml")]
77 fn py_load_many_yaml(_cls: &Bound<'_, pyo3::types::PyType>, path: &str) -> PyResult<Vec<Self>> {
78 use crate::io::ConfigRepr;
79 Self::load_many(path).map_err(|e| pyo3::exceptions::PyValueError::new_err(e.to_string()))
80 }
81
82 #[classmethod]
87 #[pyo3(name = "loads_many_yaml")]
88 fn py_loads_many_yaml(
89 _cls: &Bound<'_, pyo3::types::PyType>,
90 yaml_str: &str,
91 ) -> PyResult<Vec<Self>> {
92 use crate::io::ConfigRepr;
93 Self::loads_many(yaml_str)
94 .map_err(|e| pyo3::exceptions::PyValueError::new_err(e.to_string()))
95 }
96
97 #[classmethod]
103 #[pyo3(name = "dump_many_yaml")]
104 fn py_dump_many_yaml(
105 _cls: &Bound<'_, pyo3::types::PyType>,
106 stations: Vec<Self>,
107 path: &str,
108 ) -> PyResult<()> {
109 let s = serde_yml::to_string(&stations)
110 .map_err(|e| pyo3::exceptions::PyValueError::new_err(e.to_string()))?;
111 std::fs::write(path, s).map_err(|e| pyo3::exceptions::PyIOError::new_err(e.to_string()))
112 }
113
114 #[classmethod]
119 #[pyo3(name = "dumps_many_yaml")]
120 fn py_dumps_many_yaml(
121 _cls: &Bound<'_, pyo3::types::PyType>,
122 stations: Vec<Self>,
123 ) -> PyResult<String> {
124 serde_yml::to_string(&stations)
125 .map_err(|e| pyo3::exceptions::PyValueError::new_err(e.to_string()))
126 }
127
128 #[getter]
129 pub fn get_name(&self) -> String {
130 self.name.clone()
131 }
132
133 #[setter]
134 pub fn set_name(&mut self, name: String) {
135 self.name = name;
136 }
137
138 #[getter]
139 pub fn get_location(&self) -> Location {
140 self.location.clone()
141 }
142
143 #[setter]
144 pub fn set_location(&mut self, location: Location) {
145 self.location = location;
146 }
147
148 #[getter]
149 pub fn get_doppler_config(&self) -> Option<DopplerConfig> {
150 self.doppler_config
151 }
152
153 #[setter]
154 pub fn set_doppler_config(&mut self, doppler_config: Option<DopplerConfig>) {
155 self.doppler_config = doppler_config;
156 }
157
158 #[getter]
159 pub fn get_light_time_correction(&self) -> bool {
160 self.light_time_correction
161 }
162
163 #[setter]
164 pub fn set_light_time_correction(&mut self, light_time_correction: bool) {
165 self.light_time_correction = light_time_correction;
166 }
167
168 #[getter]
169 pub fn get_timestamp_noise_s(&self) -> Option<StochasticNoise> {
170 self.timestamp_noise_s
171 }
172
173 #[setter]
174 pub fn set_timestamp_noise_s(&mut self, noise: Option<StochasticNoise>) {
175 self.timestamp_noise_s = noise;
176 }
177
178 #[getter]
179 pub fn get_obstruction_body(&self) -> Option<FrameUid> {
180 self.obstructing_body
181 }
182
183 #[setter]
184 pub fn set_obstruction_body(&mut self, obstruction_body: Option<FrameUid>) {
185 self.obstructing_body = obstruction_body;
186 }
187
188 #[getter]
189 pub fn get_relativistic_corrections(&self) -> bool {
190 self.relativistic_corrections
191 }
192
193 #[setter]
194 pub fn set_relativistic_corrections(&mut self, relativistic_corrections: bool) {
195 self.relativistic_corrections = relativistic_corrections;
196 }
197
198 #[getter]
199 pub fn get_measurement_types(&self) -> Vec<MeasurementType> {
200 self.measurement_types.iter().cloned().collect()
201 }
202
203 #[setter]
204 pub fn set_measurement_types(&mut self, types: Vec<MeasurementType>) {
205 self.measurement_types = types.into_iter().collect();
206 }
207
208 pub fn add_measurement_type(&mut self, msr_type: MeasurementType, noise: StochasticNoise) {
214 self.measurement_types.insert(msr_type);
215 self.stochastic_noises
216 .get_or_insert_with(IndexMap::new)
217 .insert(msr_type, noise);
218 }
219
220 pub fn remove_measurement_type(&mut self, msr_type: &MeasurementType) -> bool {
225 self.measurement_types.shift_remove(msr_type)
228 }
229
230 pub fn clear_measurement_types(&mut self) {
234 self.measurement_types.clear();
235 }
236
237 #[getter]
238 pub fn get_stochastic_noises(&self) -> Option<Vec<(MeasurementType, StochasticNoise)>> {
239 self.stochastic_noises
240 .as_ref()
241 .map(|map| map.iter().map(|(k, v)| (*k, *v)).collect())
242 }
243
244 pub fn get_stochastic_noise(&self, m_type: &MeasurementType) -> Option<StochasticNoise> {
249 self.stochastic_noises
250 .as_ref()
251 .and_then(|map| map.get(m_type).cloned())
252 }
253
254 pub fn set_stochastic_noise(&mut self, m_type: MeasurementType, noise: StochasticNoise) {
260 self.stochastic_noises
261 .get_or_insert_with(indexmap::IndexMap::new)
262 .insert(m_type, noise);
263 }
264
265 pub fn remove_stochastic_noise(&mut self, m_type: &MeasurementType) -> Option<StochasticNoise> {
270 self.stochastic_noises
271 .as_mut()
272 .and_then(|map| map.shift_remove(m_type))
273 }
274
275 pub fn clear_stochastic_noises(&mut self) {
279 self.stochastic_noises = None;
280 }
281
282 fn __str__(&self) -> String {
283 format!("{self}")
284 }
285
286 fn __repr__(&self) -> String {
287 format!("{self:?} @ {self:p}")
288 }
289
290 fn __eq__(&self, other: &Self) -> bool {
291 self == other
292 }
293}