| |
1 /*! |
| |
2 Access to Python-side plotter implementations. |
| |
3 */ |
| 1 use super::process_error; |
4 use super::process_error; |
| 2 use alg_tools::types::Float; |
5 use alg_tools::types::Float; |
| 3 use pointsource_algs::measures::RNDM; |
6 use pointsource_algs::measures::RNDM; |
| 4 use pointsource_algs::plot::Plotter; |
7 use pointsource_algs::plot::Plotter; |
| 5 use pyo3::conversion::FromPyObject; |
8 use pyo3::conversion::FromPyObject; |
| 6 use pyo3::intern; |
9 use pyo3::intern; |
| 7 use pyo3::prelude::*; |
10 use pyo3::prelude::*; |
| 8 use std::marker::PhantomData; |
11 use std::marker::PhantomData; |
| 9 |
12 |
| |
13 /// A factor for generating a [`PythonPlotter`]. |
| 10 #[derive(Debug, Clone)] |
14 #[derive(Debug, Clone)] |
| 11 pub struct PythonPlotFactory<'py, T1, T2> { |
15 pub struct PythonPlotFactory<'py, T1, T2> { |
| |
16 /// Python side object implementing the plot factory |
| 12 pub(super) obj: Option<Bound<'py, PyAny>>, |
17 pub(super) obj: Option<Bound<'py, PyAny>>, |
| |
18 /// Phantoms |
| 13 pub(super) _phantoms: PhantomData<(T1, T2)>, |
19 pub(super) _phantoms: PhantomData<(T1, T2)>, |
| 14 } |
20 } |
| 15 |
21 |
| 16 impl<'a, 'py, T1, T2> FromPyObject<'a, 'py> for PythonPlotFactory<'py, T1, T2> { |
22 impl<'a, 'py, T1, T2> FromPyObject<'a, 'py> for PythonPlotFactory<'py, T1, T2> { |
| 17 type Error = PyErr; |
23 type Error = PyErr; |
| 22 obj.getattr(intern!(obj.py(), "produce"))?; |
28 obj.getattr(intern!(obj.py(), "produce"))?; |
| 23 Ok(PythonPlotFactory { obj: Some(obj), _phantoms: PhantomData }) |
29 Ok(PythonPlotFactory { obj: Some(obj), _phantoms: PhantomData }) |
| 24 } |
30 } |
| 25 } |
31 } |
| 26 |
32 |
| |
33 /// Python-side implementation of [`Plotter`] |
| 27 #[derive(Debug, Clone)] |
34 #[derive(Debug, Clone)] |
| 28 pub struct PythonPlotter<'py, T1, T2> { |
35 pub struct PythonPlotter<'py, T1, T2> { |
| |
36 /// Python side object implementing the [`Plotter`] |
| 29 pub(super) obj: Option<Bound<'py, PyAny>>, |
37 pub(super) obj: Option<Bound<'py, PyAny>>, |
| 30 pub(super) _phantoms: PhantomData<(T1, T2)>, |
38 pub(super) _phantoms: PhantomData<(T1, T2)>, |
| 31 } |
39 } |
| 32 |
40 |
| 33 impl<'a, 'py, T1, T2> FromPyObject<'a, 'py> for PythonPlotter<'py, T1, T2> { |
41 impl<'a, 'py, T1, T2> FromPyObject<'a, 'py> for PythonPlotter<'py, T1, T2> { |
| 58 } |
66 } |
| 59 } |
67 } |
| 60 } |
68 } |
| 61 |
69 |
| 62 impl<'py, T1, T2> PythonPlotFactory<'py, T1, T2> { |
70 impl<'py, T1, T2> PythonPlotFactory<'py, T1, T2> { |
| |
71 /// Creates a dummy plotter factory that doe snothing |
| 63 pub fn dummy() -> Self { |
72 pub fn dummy() -> Self { |
| 64 PythonPlotFactory { obj: None, _phantoms: PhantomData } |
73 PythonPlotFactory { obj: None, _phantoms: PhantomData } |
| 65 } |
74 } |
| 66 } |
75 } |
| 67 |
76 |
| 68 impl<'py, T1: Clone, T2: Clone> PythonPlotFactory<'py, T1, T2> { |
77 impl<'py, T1: Clone, T2: Clone> PythonPlotFactory<'py, T1, T2> { |
| |
78 /// Produces a [`PythonPlotter`] out of the factory. |
| |
79 /// The `prefix` parameter indicates where to store the files. |
| 69 pub fn produce(&self, prefix: String) -> PythonPlotter<'py, T1, T2> { |
80 pub fn produce(&self, prefix: String) -> PythonPlotter<'py, T1, T2> { |
| 70 if let Some(ref obj) = self.obj { |
81 if let Some(ref obj) = self.obj { |
| 71 let produce = intern!(obj.py(), "produce"); |
82 let produce = intern!(obj.py(), "produce"); |
| 72 process_error( |
83 process_error( |
| 73 "PythonPlotFactory::produce", |
84 "PythonPlotFactory::produce", |