Skip to main content

astroimsim_data/
point_sources.rs

1use std::fs::File;
2use std::io::Write;
3use std::time::Instant;
4use astroimsim_geometry::grid1d::GRID1D;
5use astroimsim_geometry::grid2d::{Location, GRID2D};
6use astroimsim_geometry::points::Point;
7use rand::distr::{Distribution, Uniform};
8use astroimsim_spectra::power_spectrum::{PowerSpectrum, SpectrumUnits};
9use astroimsim_spectra::power_spectrum::SpectrumUnits::f_lambda;
10use astroimsim_spectra::spectral_response::SpectralResponseCurve;
11use egui::accesskit::Invalid::Spelling;
12use rand_distr::Poisson;
13use crate::point_sources::BandUnits::{AverageElectronFlux, Electrons};
14use crate::spatial_effect::SpatialEffect;
15
16#[derive(Debug,Clone)]
17pub struct FullSpectrumPointSource {
18    pub point: Point,
19    pub spectrum: PowerSpectrum,
20    pub scale: f64,
21}
22
23#[derive(Debug)]
24pub struct Bands {
25    pub fuv: f64,
26    pub nuv: f64,
27    pub units: BandUnits,
28}
29
30#[derive(Debug)]
31pub enum BandUnits{
32    AverageElectronFlux,
33    Electrons,
34}
35
36impl FullSpectrumPointSource {
37    pub fn flat_AB(point:Point,ab_mag:f64,grid1d: GRID1D)->FullSpectrumPointSource{
38        let mut spectrum = PowerSpectrum::flat_AB(ab_mag,grid1d," ");
39            spectrum.convert_to(&SpectrumUnits::f_lambda);
40        //println!("spectrum is {:?}",spectrum);
41        FullSpectrumPointSource{point,spectrum,scale:1.0}
42    }
43    pub fn new_from_spectrum(point: Point,spectrum:PowerSpectrum)->FullSpectrumPointSource{
44        FullSpectrumPointSource{point,spectrum,scale:1.0}
45    }
46
47    pub fn scale(&mut self,scale:f64){
48        self.scale *= scale
49    }
50
51    pub fn apply_spectral_response_curve(&mut self, curve:&SpectralResponseCurve){
52        self.spectrum.convert_to(&f_lambda);
53        self.spectrum.apply_spectral_response(curve);
54    }
55    pub fn to_bands(&self,fuv_path:&SpectralResponseCurve,nuv_path:&SpectralResponseCurve,area:f64)->Bands{
56        let mut fuv_spectrum = self.clone();
57        let mut nuv_spectrum = self.clone();
58        fuv_spectrum.apply_spectral_response_curve(fuv_path);
59        nuv_spectrum.apply_spectral_response_curve(nuv_path);
60        fuv_spectrum.spectrum.write_to_dat("fuv_spectrum", "fuv spectrum ");
61        nuv_spectrum.spectrum.write_to_dat("nuv_spectrum", "nuv spectrum");
62        let fuv = fuv_spectrum.spectrum.total_average_photon_flux(area);
63        let nuv = nuv_spectrum.spectrum.total_average_photon_flux(area);
64        Bands{fuv,nuv,units:AverageElectronFlux}
65    }
66}
67#[derive(Debug)]
68pub struct FullSpectrumSourceList {
69    pub sources: Vec<FullSpectrumPointSource>,
70}
71impl FullSpectrumSourceList {
72    pub fn new_from(mut sources:Vec<FullSpectrumPointSource> ) -> FullSpectrumSourceList {
73        //sources.sort_by(|a:&point_source, b:&point_source| b.bin.cmp(&a.bin));
74        FullSpectrumSourceList {
75            sources,
76        }
77    }
78    pub fn new_empty(capacity:usize) -> FullSpectrumSourceList {
79        FullSpectrumSourceList {
80            sources: Vec::with_capacity(capacity)
81        }
82    }
83    pub fn add_source(&mut self, source: FullSpectrumPointSource) -> &mut FullSpectrumSourceList {
84        self.sources.push(source);
85        self
86
87    }
88    pub fn full_spectrum_point_source_field(number_of_point_sources:usize,
89                                           min_brightness: f64,
90                                           max_brightness: f64,
91                                            spectrum:PowerSpectrum,
92                                            grid: &GRID2D,
93    ) -> FullSpectrumSourceList {
94        assert!(max_brightness>=min_brightness,"max brightness must be greater or equal to min brightness");
95        let luminosities = Uniform::new(min_brightness,max_brightness).expect("Could not generate random luminosities in the given range");
96        let mut rng = rand::rng();
97        let sources: Vec<FullSpectrumPointSource> = (0..number_of_point_sources).map(|_x|{
98            let scale = luminosities.sample(&mut rng);
99            let point = grid.random();
100            FullSpectrumPointSource { point,spectrum: spectrum.clone(), scale}
101        }).collect();
102        FullSpectrumSourceList::new_from(sources)
103    }
104
105    pub fn apply_spatial_effect(&mut self,effect:SpatialEffect){
106        let start = Instant::now();
107        for source in &mut self.sources{
108            let scale = match effect.grid.inside_or_outside(&source.point){
109                Location::Outside => continue,
110                Location::Inside => effect.get_data(&source.point)
111            };
112            source.scale(scale)
113        }
114        println!("Applied spatial effect {:?} to {:?} sources in {:?} ms",effect.label,self.sources.len(),start.elapsed().as_millis())
115    }
116}
117
118
119impl Bands{
120    pub fn poisson(&mut self){
121        let mut rng = rand::rng();
122        let fuv_poisson = Poisson::new(self.fuv as f64).unwrap();
123        let nuv_poisson = Poisson::new(self.nuv as f64).unwrap();
124        let fuv_electrons = fuv_poisson.sample(&mut rng);
125        let nuv_electrons = nuv_poisson.sample(&mut rng);
126        self.units = Electrons;
127        self.nuv = nuv_electrons;
128        self.fuv = fuv_electrons;
129    }
130}