Skip to main content

rscm_core/python/
spatial.rs

1use crate::spatial::{
2    FourBoxGrid, FourBoxRegion, HemisphericGrid, HemisphericRegion, ScalarGrid, ScalarRegion,
3    SpatialGrid,
4};
5use pyo3::prelude::*;
6use pyo3::{pymodule, Bound, PyResult};
7
8#[pyclass]
9#[pyo3(name = "ScalarRegion")]
10#[derive(Clone, Copy)]
11pub struct PyScalarRegion(pub ScalarRegion);
12
13#[pymethods]
14impl PyScalarRegion {
15    #[classattr]
16    const GLOBAL: usize = ScalarRegion::Global as usize;
17
18    fn __repr__(&self) -> String {
19        "ScalarRegion.GLOBAL".to_string()
20    }
21}
22
23#[pyclass]
24#[pyo3(name = "FourBoxRegion")]
25#[derive(Clone, Copy)]
26pub struct PyFourBoxRegion(pub FourBoxRegion);
27
28#[pymethods]
29impl PyFourBoxRegion {
30    #[classattr]
31    const NORTHERN_OCEAN: usize = FourBoxRegion::NorthernOcean as usize;
32
33    #[classattr]
34    const NORTHERN_LAND: usize = FourBoxRegion::NorthernLand as usize;
35
36    #[classattr]
37    const SOUTHERN_OCEAN: usize = FourBoxRegion::SouthernOcean as usize;
38
39    #[classattr]
40    const SOUTHERN_LAND: usize = FourBoxRegion::SouthernLand as usize;
41
42    fn __repr__(&self) -> String {
43        match self.0 {
44            FourBoxRegion::NorthernOcean => "FourBoxRegion.NORTHERN_OCEAN".to_string(),
45            FourBoxRegion::NorthernLand => "FourBoxRegion.NORTHERN_LAND".to_string(),
46            FourBoxRegion::SouthernOcean => "FourBoxRegion.SOUTHERN_OCEAN".to_string(),
47            FourBoxRegion::SouthernLand => "FourBoxRegion.SOUTHERN_LAND".to_string(),
48        }
49    }
50}
51
52#[pyclass]
53#[pyo3(name = "HemisphericRegion")]
54#[derive(Clone, Copy)]
55pub struct PyHemisphericRegion(pub HemisphericRegion);
56
57#[pymethods]
58impl PyHemisphericRegion {
59    #[classattr]
60    const NORTHERN: usize = HemisphericRegion::Northern as usize;
61
62    #[classattr]
63    const SOUTHERN: usize = HemisphericRegion::Southern as usize;
64
65    fn __repr__(&self) -> String {
66        match self.0 {
67            HemisphericRegion::Northern => "HemisphericRegion.NORTHERN".to_string(),
68            HemisphericRegion::Southern => "HemisphericRegion.SOUTHERN".to_string(),
69        }
70    }
71}
72
73#[pyclass]
74#[pyo3(name = "ScalarGrid")]
75#[derive(Clone)]
76pub struct PyScalarGrid(pub ScalarGrid);
77
78#[pymethods]
79impl PyScalarGrid {
80    #[new]
81    fn new() -> Self {
82        Self(ScalarGrid)
83    }
84
85    fn __repr__(&self) -> String {
86        format!("<ScalarGrid size={}>", self.0.size())
87    }
88
89    fn grid_name(&self) -> &'static str {
90        self.0.grid_name()
91    }
92
93    fn size(&self) -> usize {
94        self.0.size()
95    }
96
97    fn region_names(&self) -> Vec<String> {
98        self.0.region_names().to_vec()
99    }
100
101    fn aggregate_global(&self, values: Vec<f64>) -> f64 {
102        self.0.aggregate_global(&values)
103    }
104}
105
106#[pyclass]
107#[pyo3(name = "FourBoxGrid")]
108#[derive(Clone)]
109pub struct PyFourBoxGrid(pub FourBoxGrid);
110
111#[pymethods]
112impl PyFourBoxGrid {
113    #[new]
114    #[pyo3(signature = (weights=None))]
115    fn new(weights: Option<[f64; 4]>) -> Self {
116        match weights {
117            Some(w) => Self(FourBoxGrid::with_weights(w)),
118            None => Self(FourBoxGrid::magicc_standard()),
119        }
120    }
121
122    #[staticmethod]
123    fn magicc_standard() -> Self {
124        Self(FourBoxGrid::magicc_standard())
125    }
126
127    #[staticmethod]
128    fn with_weights(weights: [f64; 4]) -> Self {
129        Self(FourBoxGrid::with_weights(weights))
130    }
131
132    fn __repr__(&self) -> String {
133        format!("<FourBoxGrid size={}>", self.0.size())
134    }
135
136    fn grid_name(&self) -> &'static str {
137        self.0.grid_name()
138    }
139
140    fn size(&self) -> usize {
141        self.0.size()
142    }
143
144    fn region_names(&self) -> Vec<String> {
145        self.0.region_names().to_vec()
146    }
147
148    fn weights(&self) -> [f64; 4] {
149        *self.0.weights()
150    }
151
152    fn aggregate_global(&self, values: Vec<f64>) -> f64 {
153        self.0.aggregate_global(&values)
154    }
155}
156
157#[pyclass]
158#[pyo3(name = "HemisphericGrid")]
159#[derive(Clone)]
160pub struct PyHemisphericGrid(pub HemisphericGrid);
161
162#[pymethods]
163impl PyHemisphericGrid {
164    #[new]
165    #[pyo3(signature = (weights=None))]
166    fn new(weights: Option<[f64; 2]>) -> Self {
167        match weights {
168            Some(w) => Self(HemisphericGrid::with_weights(w)),
169            None => Self(HemisphericGrid::equal_weights()),
170        }
171    }
172
173    #[staticmethod]
174    fn equal_weights() -> Self {
175        Self(HemisphericGrid::equal_weights())
176    }
177
178    #[staticmethod]
179    fn with_weights(weights: [f64; 2]) -> Self {
180        Self(HemisphericGrid::with_weights(weights))
181    }
182
183    fn __repr__(&self) -> String {
184        format!("<HemisphericGrid size={}>", self.0.size())
185    }
186
187    fn grid_name(&self) -> &'static str {
188        self.0.grid_name()
189    }
190
191    fn size(&self) -> usize {
192        self.0.size()
193    }
194
195    fn region_names(&self) -> Vec<String> {
196        self.0.region_names().to_vec()
197    }
198
199    fn weights(&self) -> [f64; 2] {
200        *self.0.weights()
201    }
202
203    fn aggregate_global(&self, values: Vec<f64>) -> f64 {
204        self.0.aggregate_global(&values)
205    }
206}
207
208#[pymodule]
209pub fn spatial(m: &Bound<'_, PyModule>) -> PyResult<()> {
210    m.add_class::<PyScalarRegion>()?;
211    m.add_class::<PyScalarGrid>()?;
212    m.add_class::<PyFourBoxRegion>()?;
213    m.add_class::<PyFourBoxGrid>()?;
214    m.add_class::<PyHemisphericRegion>()?;
215    m.add_class::<PyHemisphericGrid>()?;
216    Ok(())
217}