astroimsim_data/point_source.rs
1use std::fs::File;
2use std::io::Write;
3use std::time::Instant;
4use rand::distr::{Distribution, Uniform};
5use serde::Serialize;
6use astroimsim_geometry::grid2d::{Location, GRID2D};
7use astroimsim_geometry::points::Point;
8use crate::units::Units;
9pub const spectral_resolution:usize = 1000;
10#[derive( Clone, Debug)]
11pub enum Spectrum{
12 Full(f64,[f64;spectral_resolution], Units),
13 Bands(Vec<Bands>, Units),
14
15}
16#[derive(Clone,Debug)]
17pub enum Bands{
18 FUV(f64),
19 NUV(f64),
20}
21
22#[derive(Debug,Clone)]
23pub struct PointSource {
24 pub point: Point,
25 pub spectrum: Spectrum,
26}
27
28impl PointSource {
29 pub fn new_full(point:Point, spectrum: [f64;spectral_resolution],luminosity:f64, units: Units) -> PointSource {
30 let spectrum = Spectrum::Full(luminosity,spectrum, units);
31 PointSource {
32 point,
33 spectrum
34 }
35 }
36 pub fn new_fuv_nuv(point:Point,fuv:f64,nuv:f64,units: Units ) -> PointSource{
37 let spectrum = Spectrum::Bands(vec![Bands::NUV(nuv),Bands::FUV(fuv)],units);
38 PointSource{
39 point,
40 spectrum
41 }
42 }
43 pub fn new(point:Point, spectrum: Spectrum) -> PointSource{
44
45 PointSource{
46 point,
47 spectrum,
48 }
49 }
50
51 pub fn fake_spectrum()-> [f64;spectral_resolution]{
52 let mut spectrum = [0.0;spectral_resolution];
53 let luminosities = Uniform::new(0.0,1.0).expect("Could not generate random luminosities in the given range");
54 let mut rng = rand::rng();
55 for element in 0..spectrum.len(){
56 spectrum[element] = 1.0 + luminosities.sample(&mut rng);
57 }
58 /*
59 Spectrum::Full(1.0,spectrum)
60
61 */
62 spectrum
63 }
64
65 pub fn fake_bands(units: Units) -> Spectrum{
66 let luminosities = Uniform::new(0.0,1.0).expect("Could not generate random luminosities in the given range");
67 let mut rng = rand::rng();
68 Spectrum::Bands(vec![Bands::FUV(luminosities.sample(&mut rng)),Bands::NUV(luminosities.sample(&mut rng))],units)
69
70 }
71
72 pub fn scale(&mut self,scale:f64){
73 match &self.spectrum{
74 Spectrum::Full(l, c,u) => {self.spectrum = Spectrum::Full(l*scale,*c,(*u).clone())}
75 Spectrum::Bands(bands,u) => {
76 self.spectrum = Spectrum::Bands(bands.iter().map(|band|
77 match band {
78 Bands::FUV(l) => { Bands::FUV(l * scale) }
79 Bands::NUV(l) => { Bands::FUV(l * scale) }
80 }).collect(),(*u).clone() )
81 }
82 };
83 }
84
85
86
87}
88
89#[derive(Debug)]
90pub struct SourceList {
91 pub sources: Vec<PointSource>,
92}
93impl SourceList {
94 pub fn new_from(mut sources:Vec<PointSource> ) -> SourceList {
95 //sources.sort_by(|a:&point_source, b:&point_source| b.bin.cmp(&a.bin));
96 SourceList {
97 sources,
98 }
99 }
100 pub fn new_empty(capacity:usize) -> SourceList {
101 SourceList {
102 sources: Vec::with_capacity(capacity)
103 }
104 }
105 pub fn add_source(&mut self, source: PointSource) -> &mut SourceList {
106 self.sources.push(source);
107 self
108
109 }
110 pub fn random_full_spectrum_point_source_field(number_of_point_sources:usize,
111 min_brightness: f64,
112 max_brightness: f64,
113 grid: &GRID2D,
114 units: Units
115 ) -> SourceList {
116 //Some checks to make sure that the incoming values are as expected
117 //TODO Fix these checks to work with f64 values
118 /*
119 for end_point in [min_brightness,max_brightness,min_x,max_x,min_y,max_y]{
120 assert!((0.0 <= end_point) || (end_point <= 1.0),"{}: {} must be a float between 0 and 1",stringify!(end_point),end_point );
121 }
122 assert!(min_brightness <= max_brightness,"min_brightness must be less than or equal to max_brightness");
123 assert!(min_x <= max_x,"min_x must be less than or equal to max_x");
124 assert!(min_y <= max_y,"min_y must be less than or equal to max_y");
125
126 */
127
128 let luminosities = Uniform::new(min_brightness,max_brightness).expect("Could not generate random luminosities in the given range");
129 let mut rng = rand::rng();
130 let sources: Vec<PointSource> = (0..number_of_point_sources).map(|_x|{
131 let luminosity = luminosities.sample(&mut rng);
132 let point = grid.random();
133 // println!("Point is {:?}",point);
134 let spectrum = PointSource::fake_spectrum();
135 PointSource::new_full(point,spectrum,luminosity,units.clone())
136 }).collect();
137 SourceList::new_from(sources)
138 }
139 /*
140 pub fn write_to_yaml(&self, file_name:&str,) {
141 println!("Serializing point sources");
142 let serialized_self = serde_yaml::to_string(&self).expect("Failed to YAMLify the sources");
143 let mut file = File::create(file_name).expect("Couldn't create the config file");
144 write!(file, "{}", serialized_self).expect("Failed to write YAML to config file");
145 }
146
147 */
148
149 pub fn random_bands_point_source_field(number_of_point_sources:usize,
150 min_brightness: f64,
151 max_brightness: f64,
152 units: Units,
153 grid: &GRID2D,
154 ) -> SourceList {
155 //Some checks to make sure that the incoming values are as expected
156 //TODO Fix these checks to work with f64 values
157 /*
158 for end_point in [min_brightness,max_brightness,min_x,max_x,min_y,max_y]{
159 assert!((0.0 <= end_point) || (end_point <= 1.0),"{}: {} must be a float between 0 and 1",stringify!(end_point),end_point );
160 }
161 assert!(min_brightness <= max_brightness,"min_brightness must be less than or equal to max_brightness");
162 assert!(min_x <= max_x,"min_x must be less than or equal to max_x");
163 assert!(min_y <= max_y,"min_y must be less than or equal to max_y");
164
165 */
166
167 let luminosities = Uniform::new(min_brightness,max_brightness).expect("Could not generate random luminosities in the given range");
168 let mut rng = rand::rng();
169 let sources: Vec<PointSource> = (0..number_of_point_sources).map(|_x|{
170 let point = grid.random();
171 let spectrum = PointSource::fake_bands(units.clone());
172 PointSource { point, spectrum }
173 }).collect();
174 SourceList::new_from(sources)
175 }
176 /*
177 pub fn write_to_yaml(&self, file_name:&str,) {
178 println!("Serializing point sources");
179 let serialized_self = serde_yaml::to_string(&self).expect("Failed to YAMLify the sources");
180 let mut file = File::create(file_name).expect("Couldn't create the config file");
181 write!(file, "{}", serialized_self).expect("Failed to write YAML to config file");
182 }
183
184 */
185
186 /*
187
188 pub fn apply_flatfield_illumination(&mut self,illumination:flatfield){
189 let start = Instant::now();
190 for source in &mut self.sources{
191 let scale = match illumination.grid.inside_or_outside(&source.point){
192 Location::Outside => {continue}
193 Location::Inside => {
194 let (x_mod,y_mod,_x_residual,_y_residual) = illumination.grid.fit_grid(&source.point);
195 illumination.data[y_mod][x_mod]
196 }
197 };
198 // println!("Scle is {scale}");
199
200 source.scale(scale)
201 }
202 println!("Applied flatfield illumination to {:?} sources in {:?}ms",self.sources.len(),start.elapsed().as_millis())
203 }
204
205 */
206
207
208}
209