Skip to main content

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