Skip to main content

astroimsim_data/
psf.rs

1use std::iter::Flatten;
2use std::path::PathBuf;
3use std::slice::Iter;
4use serde::{Deserialize, Serialize};
5use uvex_fitrs::{Fits, FitsData, FitsDataArray, Hdu, HeaderValue};
6use astroimsim_geometry::coordinate_system::{CoordinateSystem, Coordinates};
7use astroimsim_geometry::grid2d::GRID2D;
8use astroimsim_geometry::points::Point;
9use crate::point_source::{PointSource, SourceList};
10
11#[derive(Debug,Clone,Serialize)]
12pub struct PSF {
13    pub path: PathBuf,
14    pub data: Vec<Vec<f32>>,
15    pub x_pixels: usize,
16    pub y_pixels: usize,
17    pub center: Point,
18    pub size: (f64,f64),
19}
20
21pub struct DataFile {
22    pub description: String,
23    pub path: PathBuf,
24    pub x_pixels: usize,
25    pub y_pixels: usize,
26}
27
28
29pub enum Load{
30    FromKey(String),
31    FromValue(f64)
32}
33
34impl PSF {
35    pub fn load_file(file:DataFile,center:(Load,Load),size:(Load,Load)) -> PSF {
36        println!("Loading {:?} into a DataFrame from {:?}",file.description,file.path);
37        let fits = Fits::open(file.path.clone()).expect("Failed to open FITS file");
38        let primary_hdu= fits.iter().next().expect("Couldn't find primary HDU");
39        let (mut data,shape) = match primary_hdu.read_data() {
40            FitsData::FloatingPoint32(FitsDataArray { shape, data }) => (data,shape),
41            _ => panic!("Could not unpack PSF data")
42        }; //TODO add support for f64 etc
43
44        assert_eq!(shape[0], file.x_pixels,"Diva down! Tried to load a file with data of the wrong x size"); //check that the data is the expected size
45        assert_eq!(shape[1], file.y_pixels,"Diva down! Tried to load a file with data of the wrong y size");
46
47
48        let center_x:f64 = PSF::load(center.0, &primary_hdu);
49        let center_y:f64 = PSF::load(center.1, &primary_hdu);
50        let size_x:f64 = PSF::load(size.0, &primary_hdu);
51        let size_y:f64 = PSF::load(size.1, &primary_hdu);
52        let data = data.chunks(file.x_pixels).map(|i| i.to_vec()).collect();
53        PSF {
54            path: file.path,
55            data,
56            x_pixels: file.x_pixels,
57            y_pixels: file.y_pixels,
58            center: Point::new(center_x,center_y,Coordinates::ABSOLUTE),
59            size: (size_x,size_y),
60        }
61    }
62    pub fn snap_to_grid(&self, grid: &GRID2D) -> usize{
63        let index = grid.snap(self.center.clone());
64        index
65    }
66
67
68    pub fn repack_data(flat_data: Vec<f32>) -> Vec<Vec<f32>>{
69        flat_data.chunks(64).map(|i| i.to_vec()).collect()
70    }
71
72    fn load(thingy:Load, header:&Hdu)-> f64{
73        match thingy{
74            Load::FromKey(Key) => {
75                match header.value(&Key).expect("failed to get key") {
76                    HeaderValue::RealFloatingNumber(value)=> *value,
77                    _ => panic!("could not unpack FITS header value")
78                }}
79            Load::FromValue(value) => value
80        }
81    }
82    /*
83
84        pub fn downsample(&self, x_offset:f64, y_offset:f64, scale:f64)-> Vec<Vec<f32>>{
85            //scale is the wdith of one big pixel in terms of little pixels
86            //how many pixels from the lower corner is the corner of the psf
87            //TODO PSF must be square
88            assert_eq!(self.x_pixels % 2 , self.y_pixels % 2 );
89
90            match (self.x_pixels % 2 == 0 ){
91                true => {}
92                false => {
93                    //for an odd number of pixels in the psf the center of the psf and the center of the point
94                }
95            }
96
97        }
98
99     */
100    /*
101
102    pub fn calculate_pixel_locations(&self) {
103        let indexes: Vec<Vec<(usize,usize)>> = self.data.iter().enumerate().map(|(y_index,row)|
104            row.iter().enumerate().map(|(x_index, value)| (x_index,y_index)).collect::<Vec<(usize,usize)>>()).collect();
105    }
106
107     */
108    /*
109
110    pub fn convolve(&self,point_source: PointSource) -> SourceList{
111        let bottom_left_corner = (self.center.0 - self.size.0/2.0,self.center.1 - self.size.1/2.0);
112        let pixel_width = self.size.0/self.x_pixels as f64;
113        let pixel_height = self.size.1/self.y_pixels as f64;
114        let mut output_sources = SourceList::new_empty(self.x_pixels*self.y_pixels);
115        for y_index in 0..self.y_pixels{
116            for x_index in 0..self.x_pixels{
117                let x = bottom_left_corner.0 + pixel_width*(x_index as f64 + 0.5);
118                let y  = bottom_left_corner.1 + pixel_height*(y_index as f64 + 0.5);
119                let value = self.data[y_index][x_index] as f64 * point_source.luminosity ;
120                let source = PointSource::new(x,y,point_source.spectrum.clone(),value);
121                output_sources.add_source(source);
122
123            }
124        }
125        output_sources
126    }
127
128     */
129}
130
131
132
133