def test__array_with_offset_through_arctic(): arr = ac.Array2D.manual( array=[[1.0, 2.0], [3.0, 4.0]], pixel_scales=1.0, header=ac.Header(header_sci_obj=None, header_hdu_obj=None, readout_offsets=(3, 5)), ).native roe = ac.ROE( dwell_times=[1.0], empty_traps_between_columns=True, empty_traps_for_first_transfers=False, force_release_away_from_readout=True, use_integer_express_matrix=False, ) ccd_phase = ac.CCDPhase(full_well_depth=1e3, well_notch_depth=0.0, well_fill_power=1.0) ccd = ac.CCD(phases=[ccd_phase], fraction_of_traps_per_phase=[1.0]) traps = [ac.TrapInstantCapture(10.0, -1.0 / np.log(0.5))] image_via_arctic = cti.add_cti( image=arr, parallel_traps=traps, parallel_ccd=ccd, parallel_roe=roe, parallel_express=3, parallel_offset=3, ) clocker = ac.Clocker2D(parallel_express=3, parallel_roe=roe) image_via_clocker = clocker.add_cti(data=arr, parallel_trap_list=traps, parallel_ccd=ccd_phase) assert image_via_arctic == pytest.approx(image_via_clocker, 1.0e-4) image_via_arctic = cti.add_cti( image=arr, serial_traps=traps, serial_ccd=ccd, serial_roe=roe, serial_express=2, serial_offset=5, ) clocker = ac.Clocker2D(serial_express=2, serial_roe=roe) image_via_clocker = clocker.add_cti(data=arr, serial_trap_list=traps, serial_ccd=ccd_phase) assert image_via_arctic == pytest.approx(image_via_clocker, 1.0e-4)
def add_cti( self, data: aa.Array1D, ccd: Optional[CCDPhase] = None, trap_list: Optional[List[AbstractTrap]] = None, ) -> aa.Array1D: """ Add CTI to a 1D dataset by passing it from the c++ arctic clocking algorithm. The c++ arctic wrapper takes as input a 2D ndarray, therefore this function converts the input 1D data to a 2D ndarray where the second dimension is 1, passes this from arctic and then flattens the 2D ndarray that is returned by to a 1D `Array1D` object with the input data's dimensions. Parameters ---------- data The 1D data that is clocked via arctic and has CTI added to it. ccd The ccd phase settings describing the volume-filling behaviour of the CCD which characterises the capture and release of electrons and therefore CTI. trap_list A list of the trap species on the CCD which capture and release electrons during clock to as to add CTI. """ self.check_traps(trap_list_0=trap_list) self.check_ccd(ccd_list=[ccd]) image_pre_cti_2d = aa.Array2D.zeros( shape_native=(data.shape_native[0], 1), pixel_scales=data.pixel_scales).native image_pre_cti_2d[:, 0] = data ccd = self.ccd_from(ccd_phase=ccd) image_post_cti = cti.add_cti( image=image_pre_cti_2d, parallel_ccd=ccd, parallel_roe=self.roe, parallel_traps=trap_list, parallel_express=self.express, parallel_offset=data.readout_offsets[0], parallel_window_start=self.window_start, parallel_window_stop=self.window_stop, verbosity=self.verbosity, ) return aa.Array1D.manual_native(array=image_post_cti.flatten(), pixel_scales=data.pixel_scales)
def add_cti_poisson_traps( self, data: aa.Array2D, parallel_ccd: Optional[CCDPhase] = None, parallel_trap_list: Optional[List[AbstractTrap]] = None, serial_ccd: Optional[CCDPhase] = None, serial_trap_list: Optional[List[AbstractTrap]] = None, ) -> aa.Array2D: """ Add CTI to a 2D dataset by passing it to the c++ arctic clocking algorithm. Clocking is performed towards the readout register and electronics, with parallel CTI added first followed by serial CTI. If both parallel and serial CTI are added, parallel CTI is added and the post-CTI image (therefore including trailing after parallel clocking) is used to perform serial clocking and add serial CTI. This algorithm adds CTI via arctic in the same way as the normal `add_cti` function, however for parallel clocking the density of traps in every column is drawn from a Poisson distribution to represent the stochastic nature of how many traps are in each column of a real CCD. Parameters ---------- data The 1D data that is clocked via arctic and has CTI added to it. parallel_ccd The ccd phase settings describing the volume-filling behaviour of the CCD which characterises the capture and release of electrons and therefore CTI for clocking in the parallel direction. parallel_trap_list A list of the parallel trap species on the CCD which capture and release electrons during parallel clocking which adds CTI. serial_ccd The ccd phase settings describing the volume-filling behaviour of the CCD which characterises the capture and release of electrons and therefore CTI for clocking in the serial direction. serial_trap_list A list of the serial trap species on the CCD which capture and release electrons during serial clocking which adds CTI. """ self.check_traps(trap_list_0=parallel_trap_list, trap_list_1=serial_trap_list) self.check_ccd(ccd_list=[parallel_ccd, serial_ccd]) parallel_ccd = self.ccd_from(ccd_phase=parallel_ccd) try: parallel_offset = data.readout_offsets[0] except AttributeError: parallel_offset = 0 image_pre_cti = data.native image_post_cti = np.zeros(data.shape_native) total_rows = image_post_cti.shape[0] total_columns = image_post_cti.shape[1] parallel_trap_column_list = [] for column in range(total_columns): parallel_trap_poisson_list = [ parallel_trap.poisson_density_from( total_pixels=total_rows, seed=self.poisson_seed ) for parallel_trap in parallel_trap_list ] parallel_trap_column_list.append(parallel_trap_poisson_list) image_pre_cti_pass = np.zeros(shape=(total_rows, 1)) image_pre_cti_pass[:, 0] = image_pre_cti[:, column] image_post_cti[:, column] = cti.add_cti( image=image_pre_cti_pass, parallel_ccd=parallel_ccd, parallel_roe=self.parallel_roe, parallel_traps=parallel_trap_poisson_list, parallel_express=self.parallel_express, parallel_offset=parallel_offset, parallel_window_start=self.parallel_window_start, parallel_window_stop=self.parallel_window_stop, verbosity=self.verbosity, )[:, 0] self.parallel_trap_column_list = parallel_trap_column_list serial_ccd = self.ccd_from(ccd_phase=serial_ccd) try: serial_offset = data.readout_offsets[1] except AttributeError: serial_offset = 0 image_post_cti = cti.add_cti( image=image_post_cti, serial_ccd=serial_ccd, serial_roe=self.serial_roe, serial_traps=serial_trap_list, serial_express=self.serial_express, serial_offset=serial_offset, serial_window_start=self.serial_window_start, serial_window_stop=self.serial_window_stop, verbosity=self.verbosity, ) try: return aa.Array2D.manual_mask(array=image_post_cti, mask=data.mask).native except AttributeError: return image_post_cti
def add_cti_serial_fast( self, data: aa.Array2D, serial_ccd: Optional[CCDPhase] = None, serial_trap_list: Optional[List[AbstractTrap]] = None, perform_checks: bool = True, ): """ Add CTI to a 2D dataset by passing it to the c++ arctic clocking algorithm. Clocking is performed towards the readout register and electronics, with parallel CTI added first followed by serial CTI. If both parallel and serial CTI are added, serial CTI is added and the post-CTI image (therefore including trailing after serial clocking) is used to perform serial clocking and add serial CTI. For 2D images where the same signal is repeated over all columns (e.g. uniform charge injection imaging) the CTI added to each row via arctic is identical. Therefore, this function speeds up CTI addition by only a single column to arcitc once and copying the output column the NumPy array to construct the the final post-cti image. This only works for serial CTI when parallel CTI is omitted. By default, checks are performed which ensure that the input data fits the criteria for this speed up. Parameters ---------- data The 1D data that is clocked via arctic and has CTI added to it. serial_ccd The ccd phase settings describing the volume-filling behaviour of the CCD which characterises the capture and release of electrons and therefore CTI for clocking in the serial direction. serial_trap_list A list of the serial trap species on the CCD which capture and release electrons during serial clocking which adds CTI. perform_checks Check that it is value for the input data to use the fast clocking speed up (e.g. all columns are identical and all entries outside this region are zero). """ image_pre_cti = data.native if perform_checks: self._check_serial_fast(image_pre_cti=image_pre_cti) self.check_traps(trap_list_0=serial_trap_list) self.check_ccd(ccd_list=[serial_ccd]) serial_ccd = self.ccd_from(ccd_phase=serial_ccd) image_pre_cti_pass = np.zeros(shape=(1, data.shape[1])) image_pre_cti_pass[0, :] = image_pre_cti[self.serial_fast_pixels[0], :] image_post_cti_pass = cti.add_cti( image=image_pre_cti_pass, serial_ccd=serial_ccd, serial_roe=self.serial_roe, serial_traps=serial_trap_list, serial_express=self.serial_express, serial_offset=0, verbosity=self.verbosity, ) image_post_cti = copy.copy(data.native) image_post_cti[ self.serial_fast_pixels[0] : self.serial_fast_pixels[1], : ] = image_post_cti_pass return image_post_cti
def add_cti( self, data: aa.Array2D, parallel_ccd: Optional[CCDPhase] = None, parallel_trap_list: Optional[List[AbstractTrap]] = None, serial_ccd: Optional[CCDPhase] = None, serial_trap_list: Optional[List[AbstractTrap]] = None, ) -> aa.Array2D: """ Add CTI to a 2D dataset by passing it to the c++ arctic clocking algorithm. Clocking is performed towards the readout register and electronics, with parallel CTI added first followed by serial CTI. If both parallel and serial CTI are added, parallel CTI is added and the post-CTI image (therefore including trailing after parallel clocking) is used to perform serial clocking and add serial CTI. If the flag `parallel_poisson_traps=True` the parallel clocking algorithm is sent through the alternative function `add_cti_poisson_traps`. This adds CTI via arctic in the same way, however for parallel clocking the density of traps in every column is drawn from a Poisson distribution to represent the stochastic nature of how many traps are in each column of a real CCD. Parameters ---------- data The 1D data that is clocked via arctic and has CTI added to it. parallel_ccd The ccd phase settings describing the volume-filling behaviour of the CCD which characterises the capture and release of electrons and therefore CTI for clocking in the parallel direction. parallel_trap_list A list of the parallel trap species on the CCD which capture and release electrons during parallel clocking which adds CTI. serial_ccd The ccd phase settings describing the volume-filling behaviour of the CCD which characterises the capture and release of electrons and therefore CTI for clocking in the serial direction. serial_trap_list A list of the serial trap species on the CCD which capture and release electrons during serial clocking which adds CTI. """ if self.parallel_poisson_traps: return self.add_cti_poisson_traps( data=data, parallel_ccd=parallel_ccd, parallel_trap_list=parallel_trap_list, serial_ccd=serial_ccd, serial_trap_list=serial_trap_list, ) if self.parallel_fast_pixels is not None: return self.add_cti_parallel_fast( data=data, parallel_ccd=parallel_ccd, parallel_trap_list=parallel_trap_list, ) if self.serial_fast_pixels is not None: return self.add_cti_serial_fast( data=data, serial_ccd=serial_ccd, serial_trap_list=serial_trap_list ) self.check_traps(trap_list_0=parallel_trap_list, trap_list_1=serial_trap_list) self.check_ccd(ccd_list=[parallel_ccd, serial_ccd]) parallel_ccd = self.ccd_from(ccd_phase=parallel_ccd) serial_ccd = self.ccd_from(ccd_phase=serial_ccd) try: parallel_offset = data.readout_offsets[0] serial_offset = data.readout_offsets[1] except AttributeError: parallel_offset = 0 serial_offset = 0 image_post_cti = cti.add_cti( image=data, parallel_ccd=parallel_ccd, parallel_roe=self.parallel_roe, parallel_traps=parallel_trap_list, parallel_express=self.parallel_express, parallel_offset=parallel_offset, parallel_window_start=self.parallel_window_start, parallel_window_stop=self.parallel_window_stop, serial_ccd=serial_ccd, serial_roe=self.serial_roe, serial_traps=serial_trap_list, serial_express=self.serial_express, serial_offset=serial_offset, serial_window_start=self.serial_window_start, serial_window_stop=self.serial_window_stop, verbosity=self.verbosity, ) try: return aa.Array2D.manual_mask(array=image_post_cti, mask=data.mask).native except AttributeError: return image_post_cti