Mon, 06 Jan 2025 21:37:03 -0500
Attempt to do more Serialize / Deserialize but run into csv problems
0 | 1 | //! Plotting helper utilities |
2 | ||
3 | use numeric_literals::replace_float_literals; | |
35 | 4 | use serde::Serialize; |
0 | 5 | use alg_tools::types::*; |
6 | use alg_tools::lingrid::LinGrid; | |
35 | 7 | use alg_tools::mapping::RealMapping; |
0 | 8 | use alg_tools::loc::Loc; |
9 | use alg_tools::tabledump::write_csv; | |
10 | use crate::measures::*; | |
11 | ||
12 | /// Helper trait for implementing dimension-dependent plotting routines. | |
13 | pub trait Plotting<const N : usize> { | |
14 | /// Plot several mappings and a discrete measure into a file. | |
15 | fn plot_into_file_spikes< | |
16 | F : Float, | |
17 | T1 : RealMapping<F, N>, | |
18 | T2 : RealMapping<F, N> | |
19 | > ( | |
35 | 20 | g : Option<&T1>, |
0 | 21 | ω : Option<&T2>, |
22 | grid : LinGrid<F, N>, | |
35 | 23 | μ : &RNDM<F, N>, |
0 | 24 | filename : String, |
25 | ); | |
26 | ||
27 | /// Plot a mapping into a file, sampling values on a given grid. | |
28 | fn plot_into_file< | |
29 | F : Float, | |
30 | T1 : RealMapping<F, N>, | |
31 | > ( | |
32 | g : &T1, | |
33 | grid : LinGrid<F, N>, | |
34 | filename : String, | |
35 | ); | |
36 | } | |
37 | ||
38 | /// Helper type for looking up a [`Plotting`] based on dimension. | |
39 | pub struct PlotLookup; | |
40 | ||
35 | 41 | #[derive(Serialize)] |
42 | struct CSVHelper1<F : Float> { | |
43 | x : F, | |
44 | f : F, | |
45 | } | |
46 | ||
47 | #[derive(Serialize)] | |
48 | struct CSVHelper1_2<F : Float>{ | |
49 | x : F, | |
50 | g : Option<F>, | |
51 | omega : Option<F> | |
52 | } | |
53 | ||
54 | #[derive(Serialize)] | |
55 | struct CSVSpike1<F : Float> { | |
56 | x : F, | |
57 | alpha : F, | |
58 | } | |
59 | ||
0 | 60 | impl Plotting<1> for PlotLookup { |
61 | fn plot_into_file_spikes< | |
62 | F : Float, | |
63 | T1 : RealMapping<F, 1>, | |
64 | T2 : RealMapping<F, 1> | |
65 | > ( | |
35 | 66 | g0 : Option<&T1>, |
0 | 67 | ω0 : Option<&T2>, |
68 | grid : LinGrid<F, 1>, | |
69 | μ : &DiscreteMeasure<Loc<F, 1>, F>, | |
70 | filename : String, | |
71 | ) { | |
35 | 72 | let data = grid.into_iter().map(|p@Loc([x]) : Loc<F, 1>| CSVHelper1_2 { |
73 | x, | |
74 | g : g0.map(|g| g.apply(&p)), | |
75 | omega : ω0.map(|ω| ω.apply(&p)) | |
0 | 76 | }); |
35 | 77 | let csv_f = format!("{}_functions.csv", filename); |
78 | write_csv(data, csv_f).expect("CSV save error"); | |
0 | 79 | |
35 | 80 | let spikes = μ.iter_spikes().map(|δ| { |
81 | let Loc([x]) = δ.x; | |
82 | CSVSpike1 { x, alpha : δ.α } | |
0 | 83 | }); |
35 | 84 | let csv_f = format!("{}_spikes.csv", filename); |
85 | write_csv(spikes, csv_f).expect("CSV save error"); | |
0 | 86 | } |
87 | ||
88 | fn plot_into_file< | |
89 | F : Float, | |
90 | T1 : RealMapping<F, 1>, | |
91 | > ( | |
92 | g : &T1, | |
93 | grid : LinGrid<F, 1>, | |
94 | filename : String, | |
95 | ) { | |
35 | 96 | let data = grid.into_iter().map(|p@Loc([x]) : Loc<F, 1>| CSVHelper1 { |
97 | x, | |
98 | f : g.apply(&p), | |
0 | 99 | }); |
100 | let csv_f = format!("{}.txt", filename); | |
35 | 101 | write_csv(data, csv_f).expect("CSV save error"); |
0 | 102 | } |
103 | ||
104 | } | |
105 | ||
35 | 106 | #[derive(Serialize)] |
107 | struct CSVHelper2<F : Float> { | |
108 | x : F, | |
109 | y : F, | |
110 | f : F, | |
0 | 111 | } |
112 | ||
35 | 113 | #[derive(Serialize)] |
114 | struct CSVHelper2_2<F : Float>{ | |
115 | x : F, | |
116 | y : F, | |
117 | g : Option<F>, | |
118 | omega : Option<F> | |
0 | 119 | } |
120 | ||
35 | 121 | #[derive(Serialize)] |
122 | struct CSVSpike2<F : Float> { | |
123 | x : F, | |
124 | y : F, | |
125 | alpha : F, | |
0 | 126 | } |
127 | ||
128 | ||
129 | impl Plotting<2> for PlotLookup { | |
130 | #[replace_float_literals(F::cast_from(literal))] | |
131 | fn plot_into_file_spikes< | |
132 | F : Float, | |
133 | T1 : RealMapping<F, 2>, | |
134 | T2 : RealMapping<F, 2> | |
135 | > ( | |
35 | 136 | g0 : Option<&T1>, |
0 | 137 | ω0 : Option<&T2>, |
138 | grid : LinGrid<F, 2>, | |
139 | μ : &DiscreteMeasure<Loc<F, 2>, F>, | |
140 | filename : String, | |
141 | ) { | |
35 | 142 | let data = grid.into_iter().map(|p@Loc([x, y]) : Loc<F, 2>| CSVHelper2_2 { |
143 | x, | |
144 | y, | |
145 | g : g0.map(|g| g.apply(&p)), | |
146 | omega : ω0.map(|ω| ω.apply(&p)) | |
147 | }); | |
148 | let csv_f = format!("{}_functions.csv", filename); | |
149 | write_csv(data, csv_f).expect("CSV save error"); | |
0 | 150 | |
35 | 151 | let spikes = μ.iter_spikes().map(|δ| { |
152 | let Loc([x, y]) = δ.x; | |
153 | CSVSpike2 { x, y, alpha : δ.α } | |
154 | }); | |
155 | let csv_f = format!("{}_spikes.csv", filename); | |
156 | write_csv(spikes, csv_f).expect("CSV save error"); | |
0 | 157 | } |
158 | ||
159 | fn plot_into_file< | |
160 | F : Float, | |
161 | T1 : RealMapping<F, 2>, | |
162 | > ( | |
163 | g : &T1, | |
164 | grid : LinGrid<F, 2>, | |
165 | filename : String, | |
166 | ) { | |
35 | 167 | let data = grid.into_iter().map(|p@Loc([x, y]) : Loc<F, 2>| CSVHelper2 { |
168 | x, | |
169 | y, | |
170 | f : g.apply(&p), | |
171 | }); | |
172 | let csv_f = format!("{}.txt", filename); | |
173 | write_csv(data, csv_f).expect("CSV save error"); | |
0 | 174 | } |
175 | ||
176 | } | |
177 | ||
178 | /// A helper structure for plotting a sequence of images. | |
179 | #[derive(Clone,Debug)] | |
180 | pub struct SeqPlotter<F : Float, const N : usize> { | |
181 | /// File name prefix | |
182 | prefix : String, | |
183 | /// Maximum number of plots to perform | |
184 | max_plots : usize, | |
185 | /// Sampling grid | |
186 | grid : LinGrid<F, N>, | |
187 | /// Current plot count | |
188 | plot_count : usize, | |
189 | } | |
190 | ||
191 | impl<F : Float, const N : usize> SeqPlotter<F, N> | |
192 | where PlotLookup : Plotting<N> { | |
193 | /// Creates a new sequence plotter instance | |
194 | pub fn new(prefix : String, max_plots : usize, grid : LinGrid<F, N>) -> Self { | |
195 | SeqPlotter { prefix, max_plots, grid, plot_count : 0 } | |
196 | } | |
197 | ||
198 | /// This calls [`PlotLookup::plot_into_file_spikes`] with a sequentially numbered file name. | |
199 | pub fn plot_spikes<T1, T2>( | |
200 | &mut self, | |
35 | 201 | iter : usize, |
202 | g : Option<&T1>, | |
0 | 203 | ω : Option<&T2>, |
35 | 204 | μ : &RNDM<F, N>, |
0 | 205 | ) where T1 : RealMapping<F, N>, |
206 | T2 : RealMapping<F, N> | |
207 | { | |
208 | if self.plot_count == 0 && self.max_plots > 0 { | |
209 | std::fs::create_dir_all(&self.prefix).expect("Unable to create plot directory"); | |
210 | } | |
211 | if self.plot_count < self.max_plots { | |
212 | PlotLookup::plot_into_file_spikes( | |
35 | 213 | g, |
214 | ω, | |
0 | 215 | self.grid, |
216 | μ, | |
35 | 217 | format!("{}out{:03}", self.prefix, iter) |
0 | 218 | ); |
219 | self.plot_count += 1; | |
220 | } | |
221 | } | |
222 | } |