astroimsim_data/
point_sources.rs1use 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 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 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}