go_pybindings/io.rs
1//! The following file is part of gaps-online-software and published
2//! under the GPLv3 license
3//!
4//! This file contains the source for pybindings with pyO3 for the
5//! i/o system to read Tof data files as well as telemetry files
6
7use std::collections::HashMap;
8use std::env;
9//use log::error;
10use tof_dataclasses::io as io_api;
11
12use pyo3::prelude::*;
13use pyo3::exceptions::PyIOError;
14//use pyo3::exceptions::PyValueError;
15
16use tof_dataclasses::packets::PacketType;
17use tof_dataclasses::database::{
18 Paddle,
19 connect_to_db
20};
21
22use crate::dataclasses::{
23 PyTofPacket,
24 PyTofEventSummary
25};
26
27/// Remove the waveforms from a .tof.gaps
28/// file and replace TofEvents with
29/// TofEventSummary
30#[pyfunction]
31#[pyo3(name="summarize_toffile")]
32pub fn py_summarize_toffile(fname : String) {
33 io_api::summarize_toffile(fname);
34}
35
36///// New style, agnostic reader for events from
37///// any source
38//#[pyclass]
39//#[pyo3(name="Adapter")]
40//pub struct PyAdapter {
41// pub paddles : HashMap<u8, Paddle>,
42// pub tpreader : Option<PyTofPacketReader>
43//}
44//
45//#[pymethods]
46//impl PyAdapter {
47//
48// /// Instanciate a new adapter. An adapter can connect to any type of (online) data
49// /// file - .tof.gaps, .tofsum.gaps, telemetry (.bin), a network port or a directory with
50// /// these files
51// #[new]
52// #[pyo3(signature = (source, filter=PacketType::Unknown,start=0, nevents=0))]
53// fn new<'py>(source : Bound<'py, PyAny>, filter : PacketType, start : usize, nevents : usize) -> PyResult<Self> {
54// let reader = PyTofPacketReader::new(source, filter, start, nevents).expect("Can not init reader!");
55// let mut paddles = HashMap::<u8, Paddle>::new();
56// let db_path = env::var("DATABASE_URL").unwrap_or_else(|_| "".to_string());
57// match connect_to_db(db_path) {
58// Err(err) => {
59// println!("Database can not be found! Did you load the setup-env.sh shell?");
60// return Err(PyIOError::new_err(err.to_string()));
61// }
62// Ok(mut conn) => {
63// match Paddle::all(&mut conn) {
64// None => {
65// return Err(PyIOError::new_err("Unable to retrieve paddle information from DB!"));
66// }
67// Some(pdls) => {
68// for p in pdls {
69// paddles.insert(p.paddle_id as u8, p.clone());
70// }
71// }
72// }
73// }
74// }
75//
76// Ok(PyAdapter {
77// paddles : paddles,
78// tpreader : Some(reader)
79// })
80// }
81//
82// #[getter]
83// fn packet_index(&mut self) -> PyResult<HashMap<PacketType, usize>> {
84// if self.tpreader.is_some() {
85// let idx = self.tpreader.get_packet_index()?;
86// self.tpreader.rewind()?;
87// Ok(idx)
88// }
89// Err(PyIOError::new_err("No reader is set! Can't return packet index!"));
90// }
91//
92// fn rewind(&mut self) {
93// let _ = self.tpreader.rewind();
94// }
95//
96// fn __repr__(&self) -> PyResult<String> {
97// if self.tpreader.is_some() {
98// Ok(format!("<PyO3Wrapper: {}>", self.tpreader.unwrap()))
99// } else {
100// Err(PyIOError::new_err("No reader is set! Can't return packet index!"));
101// }
102// }
103//
104// fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
105// slf
106// }
107//
108// pub fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<PyTofPacket> {
109// if slf.tpreader.is_some() {
110// //match slf.tpreader.unwrap().reader.next() {
111// match <Option<PyTofPacketReader> as Clone>::clone(&slf.tpreader).unwrap().reader.next() {
112// Some(tp) => {
113// let mut pytp = PyTofPacket::new();
114// pytp.set_tp(tp);
115// return Some(pytp)
116// }
117// None => {
118// return None;
119// }
120// }
121// }
122// None
123// }
124//}
125
126#[pyclass]
127#[pyo3(name="TofPacketReader")]
128pub struct PyTofPacketReader {
129 pub reader : io_api::TofPacketReader,
130 pub paddles : HashMap<u8,Paddle>,
131 //pub with_paddleinfo : bool
132}
133
134#[pymethods]
135impl PyTofPacketReader {
136
137 /// Create a new instance of a TofPacketReader.
138 #[new]
139 #[pyo3(signature = (filename, filter=PacketType::Unknown,start=0, nevents=0))]
140 pub fn new<'py>(filename : Bound<'py, PyAny>, filter : PacketType, start : usize, nevents : usize) -> PyResult<Self> {
141 let input_str : String;
142 match filename.extract::<String>() {
143 Ok(_fname) => {
144 input_str = _fname;
145 }
146 Err(_) => {
147 match filename.extract::<std::path::PathBuf>() {
148 Ok(_fname) => {
149 input_str = _fname.to_str().expect("Unable to convert input to string!").to_owned();
150 }
151 Err(_) => {
152 return Err(pyo3::exceptions::PyTypeError::new_err(
153 "Expected str or pathlib.Path",));
154 }
155 }
156 }
157 }
158 let mut paddles = HashMap::<u8, Paddle>::new();
159 let db_path = env::var("DATABASE_URL").unwrap_or_else(|_| "".to_string());
160 match connect_to_db(db_path) {
161 Err(err) => {
162 println!("Database can not be found! Did you load the setup-env.sh shell?");
163 return Err(PyIOError::new_err(err.to_string()));
164 }
165 Ok(mut conn) => {
166 match Paddle::all(&mut conn) {
167 None => {
168 return Err(PyIOError::new_err("Unable to retrieve paddle information from DB!"));
169 }
170 Some(pdls) => {
171 for p in pdls {
172 paddles.insert(p.paddle_id as u8, p.clone());
173 }
174 }
175 }
176 }
177 }
178
179 let mut pyreader = Self {
180 reader : io_api::TofPacketReader::new(input_str),
181 paddles : paddles,
182 //with_paddleinfo : false
183 };
184 pyreader.reader.filter = filter;
185 pyreader.reader.skip_ahead = start;
186 pyreader.reader.stop_after = nevents;
187 Ok(pyreader)
188 }
189
190 fn add_paddleinfo(&self, event : &mut PyTofEventSummary) {
191 event.event.set_paddles(&self.paddles);
192 }
193
194 #[getter]
195 fn current_filename(&self) -> Option<String> {
196 self.reader.get_current_filename()
197 }
198
199 #[getter]
200 fn first(&mut self) -> Option<PyTofPacket> {
201 let mut ptp = PyTofPacket::new();
202 let tp = self.reader.first_packet()?;
203 ptp.packet = tp;
204 return Some(ptp);
205 }
206
207 #[getter]
208 fn last(&mut self) -> Option<PyTofPacket> {
209 let mut ptp = PyTofPacket::new();
210 let tp = self.reader.last_packet()?;
211 ptp.packet = tp;
212 return Some(ptp);
213 }
214 //#[getter]
215 //fn get_with_paddleinfo(&self) -> PyResult<u32> {
216 // Ok(self.with_paddleinfo)
217 //}
218 //
219 //#[setter]
220 //fn set_with_paddleinfo(&mut self, pinfo : bool) -> PyResult<()> {
221 // self.with_paddleinfo = pinfo;
222 // Ok(())
223 //}
224
225 #[getter]
226 fn get_filenames(&self) -> Vec<String> {
227 self.reader.filenames.clone()
228 }
229
230 #[getter]
231 fn packet_index(&mut self) -> PyResult<HashMap<PacketType, usize>> {
232 let idx = self.reader.get_packet_index()?;
233 self.reader.rewind()?;
234 Ok(idx)
235 }
236
237 fn rewind(&mut self) {
238 let _ = self.reader.rewind();
239 }
240
241 pub fn __repr__(&self) -> PyResult<String> {
242 Ok(format!("<PyO3Wrapper: {}>", self
243 .reader))
244 }
245
246 pub fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
247 slf
248 }
249
250 pub fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<PyTofPacket> {
251 match slf.reader.next() {
252 Some(tp) => {
253 let mut pytp = PyTofPacket::new();
254 if tp.packet_type == PacketType::TofEventSummary {
255 //if tp.with_paddleinfo {
256 //
257 //}
258 }
259 pytp.set_tp(tp);
260 return Some(pytp)
261 }
262 None => {
263 return None;
264 }
265 }
266 // slf.reader.next()
267 }
268}