From 2d64f8a78ea7cb7df76d5cfe6737ea88ccb60efa Mon Sep 17 00:00:00 2001 From: Arthur Vigan Date: Wed, 30 Aug 2017 14:23:23 +0200 Subject: [PATCH] Implemented anamorphism correction Implemented for both IRDIS and IFS. Close #32. --- examples/standard_ifs_reduction.py | 2 +- examples/standard_irdis_reduction.py | 2 +- pysphere/IFS.py | 78 +++++++++++++++++----------- pysphere/IRDIS.py | 54 +++++++++++++------ 4 files changed, 88 insertions(+), 48 deletions(-) diff --git a/examples/standard_ifs_reduction.py b/examples/standard_ifs_reduction.py index aa328a8..305f39a 100644 --- a/examples/standard_ifs_reduction.py +++ b/examples/standard_ifs_reduction.py @@ -32,5 +32,5 @@ # red.sph_ifs_science_cubes(postprocess=True, silent=True) # red.sph_ifs_wavelength_recalibration(high_pass=False, display=False, save=True) # red.sph_ifs_star_center(high_pass=False, display=False, save=True) -# red.sph_ifs_combine_data(cpix=True, psf_dim=80, science_dim=290, save_scaled=False) +# red.sph_ifs_combine_data(cpix=True, psf_dim=80, science_dim=290, correct_anamorphism=True, save_scaled=False) # red.sph_ifs_clean(delete_raw=False, delete_products=False) diff --git a/examples/standard_irdis_reduction.py b/examples/standard_irdis_reduction.py index 16dbe76..7a289c8 100644 --- a/examples/standard_irdis_reduction.py +++ b/examples/standard_irdis_reduction.py @@ -26,5 +26,5 @@ # collapse_science=False, collapse_type='mean', coadd_value=2, # collapse_psf=True, collapse_center=True) # red.sph_ird_star_center(high_pass=False, display=False, save=True) -# red.sph_ird_combine_data(cpix=True, psf_dim=100, science_dim=400, save_scaled=False) +red.sph_ird_combine_data(cpix=True, psf_dim=100, science_dim=400, correct_anamorphism=True, save_scaled=False) # red.sph_ird_clean(delete_raw=False, delete_products=False) diff --git a/pysphere/IFS.py b/pysphere/IFS.py index 753df97..7af7725 100644 --- a/pysphere/IFS.py +++ b/pysphere/IFS.py @@ -379,7 +379,7 @@ def __init__(self, path): config.read(configfile) self._pixel = float(config.get('instrument', 'pixel')) - self._nwave = float(config.get('instrument', 'nwave')) + self._nwave = int(config.get('instrument', 'nwave')) self._wave_cal_lasers = [float(w) for w in config.get('calibration', 'wave_cal_lasers').split(',')] except configparser.Error as e: @@ -461,11 +461,11 @@ def create_static_calibrations(self): Create all static calibrations, mainly with esorex ''' - self.sph_ifs_cal_dark(silent=True) - self.sph_ifs_cal_detector_flat(silent=True) - self.sph_ifs_cal_specpos(silent=True) - self.sph_ifs_cal_wave(silent=True) - self.sph_ifs_cal_ifu_flat(silent=True) + self.sph_ifs_cal_dark() + self.sph_ifs_cal_detector_flat() + self.sph_ifs_cal_specpos() + self.sph_ifs_cal_wave() + self.sph_ifs_cal_ifu_flat() def preprocess_science(self): @@ -473,9 +473,7 @@ def preprocess_science(self): Collapse and correct raw IFU images ''' - self.sph_ifs_preprocess_science(subtract_background=True, fix_badpix=True, correct_xtalk=True, - collapse_science=False, collapse_type='mean', coadd_value=2, - collapse_psf=True, collapse_center=True) + self.sph_ifs_preprocess_science() self.sph_ifs_preprocess_wave() @@ -485,10 +483,10 @@ def process_science(self): center and combine cubes into final (x,y,time,lambda) cubes ''' - self.sph_ifs_science_cubes(silent=True) - self.sph_ifs_wavelength_recalibration(high_pass=False, display=False, save=True) - self.sph_ifs_star_center(high_pass=False, display=False, save=True) - self.sph_ifs_combine_data(cpix=True, psf_dim=80, science_dim=290, save_scaled=False) + self.sph_ifs_science_cubes() + self.sph_ifs_wavelength_recalibration() + self.sph_ifs_star_center() + self.sph_ifs_combine_data() def clean(self): @@ -496,7 +494,7 @@ def clean(self): Clean the reduction directory ''' - self.sph_ifs_clean(delete_raw=False, delete_products=False) + self.sph_ifs_clean() def full_reduction(self): @@ -718,7 +716,7 @@ def sort_frames(self): print('Extracting frames information') # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sort_frames', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sort_frames', self.recipe_requirements) # parameters path = self._path @@ -762,7 +760,7 @@ def check_files_association(self): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'check_files_association', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'check_files_association', self.recipe_requirements) print('Performing file association for calibrations') @@ -901,7 +899,7 @@ def sph_ifs_cal_dark(self, silent=True): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_cal_dark', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_cal_dark', self.recipe_requirements) print('Creating darks and backgrounds') @@ -1006,7 +1004,7 @@ def sph_ifs_cal_detector_flat(self, silent=True): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_cal_detector_flat', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_cal_detector_flat', self.recipe_requirements) print('Creating flats') @@ -1097,7 +1095,7 @@ def sph_ifs_cal_specpos(self, silent=True): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_cal_specpos', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_cal_specpos', self.recipe_requirements) print('Creating specpos') @@ -1184,7 +1182,7 @@ def sph_ifs_cal_wave(self, silent=True): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_cal_wave', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_cal_wave', self.recipe_requirements) print('Creating wavelength calibration') @@ -1286,7 +1284,7 @@ def sph_ifs_cal_ifu_flat(self, silent=True): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_cal_ifu_flat', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_cal_ifu_flat', self.recipe_requirements) print('Creating IFU flat') @@ -1455,7 +1453,7 @@ def sph_ifs_preprocess_science(self, ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_preprocess_science', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_preprocess_science', self.recipe_requirements) print('Pre-processing science files') @@ -1640,7 +1638,7 @@ def sph_ifs_preprocess_wave(self): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_preprocess_wave', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_preprocess_wave', self.recipe_requirements) # parameters path = self._path @@ -1710,7 +1708,7 @@ def sph_ifs_science_cubes(self, silent=True): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_science_cubes', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_science_cubes', self.recipe_requirements) print('Creating the (x,y,lambda) science cubes') @@ -1854,7 +1852,7 @@ def sph_ifs_wavelength_recalibration(self, high_pass=False, display=False, save= ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_wavelength_recalibration', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_wavelength_recalibration', self.recipe_requirements) print('Recalibrating wavelength') @@ -2053,7 +2051,7 @@ def sph_ifs_star_center(self, high_pass=False, display=False, save=True): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_star_center', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_star_center', self.recipe_requirements) print('Star centers determination') @@ -2125,7 +2123,7 @@ def sph_ifs_star_center(self, high_pass=False, display=False, save=True): self._recipe_execution['sph_ifs_star_center'] = True - def sph_ifs_combine_data(self, cpix=True, psf_dim=80, science_dim=290, save_scaled=False): + def sph_ifs_combine_data(self, cpix=True, psf_dim=80, science_dim=290, correct_anamorphism=True, save_scaled=False): ''' Combine and save the science data into final cubes @@ -2166,14 +2164,18 @@ def sph_ifs_combine_data(self, cpix=True, psf_dim=80, science_dim=290, save_scal Size of the science images (star centers and standard coronagraphic images). Default is 290, 290 pixels - save_scaled : bool + correct_anamorphism : bool + Correct the optical anamorphism of the instrument. Default + is True. See user manual for details. + + save_scaled : bool Also save the wavelength-rescaled cubes. Makes the process much longer. The default is False ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_combine_data', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ifs_combine_data', self.recipe_requirements) print('Combine science data') @@ -2256,6 +2258,12 @@ def sph_ifs_combine_data(self, cpix=True, psf_dim=80, science_dim=290, save_scal psf_cube[wave_idx, file_idx] = nimg[:psf_dim, :psf_dim] + # correct anamorphism + if correct_anamorphism: + nimg = psf_cube[wave_idx, file_idx] + nimg = imutils.scale(nimg, (1.0059, 1.0011), method='interp') + psf_cube[wave_idx, file_idx] = nimg + # wavelength-scaled version if save_scaled: nimg = psf_cube[wave_idx, file_idx] @@ -2328,6 +2336,12 @@ def sph_ifs_combine_data(self, cpix=True, psf_dim=80, science_dim=290, save_scal cen_cube[wave_idx, file_idx] = nimg[:science_dim, :science_dim] + # correct anamorphism + if correct_anamorphism: + nimg = cen_cube[wave_idx, file_idx] + nimg = imutils.scale(nimg, (1.0059, 1.0011), method='interp') + cen_cube[wave_idx, file_idx] = nimg + # wavelength-scaled version if save_scaled: nimg = cen_cube[wave_idx, file_idx] @@ -2410,6 +2424,12 @@ def sph_ifs_combine_data(self, cpix=True, psf_dim=80, science_dim=290, save_scal sci_cube[wave_idx, file_idx] = nimg[:science_dim, :science_dim] + # correct anamorphism + if correct_anamorphism: + nimg = sci_cube[wave_idx, file_idx] + nimg = imutils.scale(nimg, (1.0059, 1.0011), method='interp') + sci_cube[wave_idx, file_idx] = nimg + # wavelength-scaled version if save_scaled: nimg = sci_cube[wave_idx, file_idx] diff --git a/pysphere/IRDIS.py b/pysphere/IRDIS.py index 6351853..549c4ac 100644 --- a/pysphere/IRDIS.py +++ b/pysphere/IRDIS.py @@ -71,7 +71,7 @@ def __init__(self, path): config.read(configfile) self._pixel = float(config.get('instrument', 'pixel')) - self._nwave = float(config.get('instrument', 'nwave')) + self._nwave = int(config.get('instrument', 'nwave')) self._wave_cal_lasers = [float(w) for w in config.get('calibration', 'wave_cal_lasers').split(',')] except configparser.Error as e: @@ -145,8 +145,8 @@ def create_static_calibrations(self): Create all static calibrations with esorex ''' - self.sph_ird_cal_dark(silent=True) - self.sph_ird_cal_detector_flat(silent=True) + self.sph_ird_cal_dark() + self.sph_ird_cal_detector_flat() def preprocess_science(self): @@ -154,9 +154,7 @@ def preprocess_science(self): Extract images in data cubes ''' - self.sph_ird_preprocess_science(subtract_background=True, fix_badpix=True, - collapse_science=False, collapse_type='mean', coadd_value=2, - collapse_psf=True, collapse_center=True) + self.sph_ird_preprocess_science() def process_science(self): @@ -165,8 +163,8 @@ def process_science(self): cubes ''' - self.sph_ird_star_center(high_pass=False, display=False, save=True) - self.sph_ird_combine_data(cpix=True, psf_dim=100, science_dim=800, save_scaled=False) + self.sph_ird_star_center() + self.sph_ird_combine_data() def clean(self): @@ -174,7 +172,7 @@ def clean(self): Clean the reduction directory ''' - self.sph_ird_clean(delete_raw=False, delete_products=False) + self.sph_ird_clean() def full_reduction(self): @@ -374,7 +372,7 @@ def sort_frames(self): print('Extracting frames information') # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sort_frames', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sort_frames', self.recipe_requirements) # parameters path = self._path @@ -418,7 +416,7 @@ def check_files_association(self): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'check_files_association', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'check_files_association', self.recipe_requirements) print('Performing file association for calibrations') @@ -501,7 +499,7 @@ def sph_ird_cal_dark(self, silent=True): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ird_cal_dark', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ird_cal_dark', self.recipe_requirements) print('Creating darks and backgrounds') @@ -618,7 +616,7 @@ def sph_ird_cal_detector_flat(self, silent=True): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ird_cal_detector_flat', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ird_cal_detector_flat', self.recipe_requirements) print('Creating flats') @@ -752,7 +750,7 @@ def sph_ird_preprocess_science(self, ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ird_preprocess_science', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ird_preprocess_science', self.recipe_requirements) print('Pre-processing science files') @@ -974,7 +972,7 @@ def sph_ird_star_center(self, high_pass=False, display=False, save=True): ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ird_star_center', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ird_star_center', self.recipe_requirements) print('Star centers determination') @@ -1040,7 +1038,7 @@ def sph_ird_star_center(self, high_pass=False, display=False, save=True): self._recipe_execution['sph_ird_star_center'] = True - def sph_ird_combine_data(self, cpix=True, psf_dim=80, science_dim=290, save_scaled=False): + def sph_ird_combine_data(self, cpix=True, psf_dim=80, science_dim=290, correct_anamorphism=True, save_scaled=False): ''' Combine and save the science data into final cubes @@ -1081,6 +1079,10 @@ def sph_ird_combine_data(self, cpix=True, psf_dim=80, science_dim=290, save_scal Size of the science images (star centers and standard coronagraphic images). Default is 290, 290 pixels + correct_anamorphism : bool + Correct the optical anamorphism of the instrument. Default + is True. See user manual for details. + save_scaled : bool Also save the wavelength-rescaled cubes. Makes the process much longer. The default is False @@ -1088,7 +1090,7 @@ def sph_ird_combine_data(self, cpix=True, psf_dim=80, science_dim=290, save_scal ''' # check if recipe can be executed - toolbox.check_recipe_execution(self._recipe_execution, 'sph_ird_combine_data', self._recipe_requirements) + toolbox.check_recipe_execution(self._recipe_execution, 'sph_ird_combine_data', self.recipe_requirements) print('Combine science data') @@ -1168,6 +1170,12 @@ def sph_ird_combine_data(self, cpix=True, psf_dim=80, science_dim=290, save_scal psf_cube[wave_idx, file_idx] = nimg[:psf_dim, :psf_dim] + # correct anamorphism + if correct_anamorphism: + nimg = psf_cube[wave_idx, file_idx] + nimg = imutils.scale(nimg, (1.0000, 1.0062), method='interp') + psf_cube[wave_idx, file_idx] = nimg + # wavelength-scaled version if save_scaled: nimg = psf_cube[wave_idx, file_idx] @@ -1237,6 +1245,12 @@ def sph_ird_combine_data(self, cpix=True, psf_dim=80, science_dim=290, save_scal cen_cube[wave_idx, file_idx] = nimg[:science_dim, :science_dim] + # correct anamorphism + if correct_anamorphism: + nimg = cen_cube[wave_idx, file_idx] + nimg = imutils.scale(nimg, (1.0000, 1.0062), method='interp') + cen_cube[wave_idx, file_idx] = nimg + # wavelength-scaled version if save_scaled: nimg = cen_cube[wave_idx, file_idx] @@ -1334,6 +1348,12 @@ def sph_ird_combine_data(self, cpix=True, psf_dim=80, science_dim=290, save_scal sci_cube[wave_idx, file_idx] = nimg[:science_dim, :science_dim] + # correct anamorphism + if correct_anamorphism: + nimg = sci_cube[wave_idx, file_idx] + nimg = imutils.scale(nimg, (1.0000, 1.0062), method='interp') + sci_cube[wave_idx, file_idx] = nimg + # wavelength-scaled version if save_scaled: nimg = sci_cube[wave_idx, file_idx]