예제 #1
0
    def run(self, rinput):
        self.logger.info('starting spectral sky reduction')

        flow = self.init_filters(rinput)

        reduced_image = basic_processing_with_combination(
            rinput, flow,
            method=median,
            errors=True
        )

        hdr = reduced_image[0].header
        self.set_base_headers(hdr)

        # save intermediate image in work directory
        self.save_intermediate_img(reduced_image, 'reduced_image.fits')

        # RectWaveCoeff object with rectification and wavelength calibration
        # coefficients for the particular CSU configuration
        rectwv_coeff = rectwv_coeff_from_mos_library(
            reduced_image,
            rinput.master_rectwv
        )
        # save as JSON file in work directory
        self.save_structured_as_json(rectwv_coeff, 'rectwv_coeff.json')

        # generate associated ds9 region files and save them in work directory
        if self.intermediate_results:
            save_four_ds9(rectwv_coeff)

        # apply rectification and wavelength calibration
        skyspec = apply_rectwv_coeff(
            reduced_image,
            rectwv_coeff
        )

        self.logger.info('end sky spectral reduction')

        result = self.create_result(
            reduced_image=reduced_image,
            skyspec=skyspec
        )

        return result
예제 #2
0
    def run(self, rinput):
        self.logger.info('starting rect.+wavecal. reduction of arc spectra')

        # build object to proceed with bpm, bias, dark and flat
        flow = self.init_filters(rinput)

        # apply bpm, bias, dark and flat
        reduced_image = basic_processing_with_combination(rinput,
                                                          flow,
                                                          method=median)
        # update header con additional info
        hdr = reduced_image[0].header
        self.set_base_headers(hdr)

        # save intermediate image in work directory
        self.save_intermediate_img(reduced_image, 'reduced_image.fits')

        # RectWaveCoeff object (with rectification and wavelength calibration
        # coefficients for the particular CSU configuration of the arc image)
        # and HDUList object with the FITS image corresponding to 55 median
        # spectra of each slitlet
        rectwv_coeff, reduced_55sp = rectwv_coeff_from_arc_image(
            reduced_image,
            rinput.bound_param,
            rinput.lines_catalog,
        )

        # generate associated ds9 region files and save them in work directory
        if self.intermediate_results:
            save_four_ds9(rectwv_coeff)

        # apply rectification and wavelength calibration
        reduced_arc = apply_rectwv_coeff(reduced_image, rectwv_coeff)

        # save results in result directory
        self.logger.info('end rect.+wavecal. reduction of arc spectra')
        result = self.create_result(reduced_image=reduced_image,
                                    rectwv_coeff=rectwv_coeff,
                                    reduced_55sp=reduced_55sp,
                                    reduced_arc=reduced_arc)
        return result
예제 #3
0
    def run(self, rinput):
        self.logger.info('applying existing rect.+wavecal. calibration of '
                         'stare spectra')

        # build object to proceed with bpm, bias, dark and flat
        flow = self.init_filters(rinput)

        # apply bpm, bias, dark and flat
        reduced_image = basic_processing_with_combination(rinput,
                                                          flow,
                                                          method=median)
        # update header with additional info
        hdr = reduced_image[0].header
        self.set_base_headers(hdr)

        # save intermediate image in work directory
        self.save_intermediate_img(reduced_image, 'reduced_image.fits')

        # apply rectification and wavelength calibration
        reduced_mos = apply_rectwv_coeff(reduced_image, rinput.rectwv_coeff)

        # ds9 region files (to be saved in the work directory)
        if self.intermediate_results:
            save_four_ds9(rinput.rectwv_coeff)
            save_spectral_lines_ds9(rinput.rectwv_coeff)

        # compute median spectra employing the useful region of the
        # rectified image
        if self.intermediate_results:
            for imode, outfile in enumerate([
                    'median_spectra_full', 'median_spectra_slitlets',
                    'median_spectrum_slitlets'
            ]):
                median_image = median_slitlets_rectified(reduced_mos,
                                                         mode=imode)
                self.save_intermediate_img(median_image, outfile + '.fits')

        # save results in results directory
        self.logger.info('end rect.+wavecal. reduction of stare spectra')
        result = self.create_result(reduced_mos=reduced_mos)
        return result
예제 #4
0
파일: arc.py 프로젝트: guaix-ucm/pyemir
    def run(self, rinput):
        self.logger.info('starting rect.+wavecal. reduction of arc spectra')

        # build object to proceed with bpm, bias, dark and flat
        flow = self.init_filters(rinput)

        # apply bpm, bias, dark and flat
        reduced_image = basic_processing_with_combination(rinput, flow,
                                                          method=median)
        # update header con additional info
        hdr = reduced_image[0].header
        self.set_base_headers(hdr)

        # save intermediate image in work directory
        self.save_intermediate_img(reduced_image, 'reduced_image.fits')

        # RectWaveCoeff object (with rectification and wavelength calibration
        # coefficients for the particular CSU configuration of the arc image)
        # and HDUList object with the FITS image corresponding to 55 median
        # spectra of each slitlet
        rectwv_coeff, reduced_55sp = rectwv_coeff_from_arc_image(
            reduced_image,
            rinput.bound_param,
            rinput.lines_catalog,
        )

        # generate associated ds9 region files and save them in work directory
        if self.intermediate_results:
            save_four_ds9(rectwv_coeff)

        # apply rectification and wavelength calibration
        reduced_arc = apply_rectwv_coeff(reduced_image, rectwv_coeff)

        # save results in result directory
        self.logger.info('end rect.+wavecal. reduction of arc spectra')
        result = self.create_result(reduced_image=reduced_image,
                                    rectwv_coeff=rectwv_coeff,
                                    reduced_55sp=reduced_55sp,
                                    reduced_arc=reduced_arc)
        return result
예제 #5
0
    def run(self, rinput):

        nimages = len(rinput.obresult.frames)
        pattern = rinput.pattern
        pattern_length = len(pattern)

        # check combination method
        if rinput.method != 'sigmaclip':
            if rinput.method_kwargs != {}:
                raise ValueError('Unexpected method_kwargs={}'.format(
                    rinput.method_kwargs))

        # check pattern sequence matches number of images
        if nimages % pattern_length != 0:
            raise ValueError('Number of images is not a multiple of pattern '
                             'length: {}, {}'.format(nimages, pattern_length))
        nsequences = nimages // pattern_length

        rectwv_coeff = rinput.rectwv_coeff
        self.logger.info(rectwv_coeff)
        self.logger.info('observation pattern: {}'.format(pattern))
        self.logger.info('nsequences.........: {}'.format(nsequences))

        full_set = pattern * nsequences
        self.logger.info('full set of images.: {}'.format(full_set))

        # build object to proceed with bpm, bias, dark and flat
        flow = self.init_filters(rinput)

        # available combination methods
        method = getattr(combine, rinput.method)
        method_kwargs = rinput.method_kwargs

        # basic reduction of A images
        list_a = [
            rinput.obresult.frames[i] for i, char in enumerate(full_set)
            if char == 'A'
        ]
        with contextlib.ExitStack() as stack:
            self.logger.info('starting basic reduction of A images')
            hduls = [stack.enter_context(fname.open()) for fname in list_a]
            reduced_image_a = combine_imgs(hduls,
                                           method=method,
                                           method_kwargs=method_kwargs,
                                           errors=False,
                                           prolog=None)
        reduced_image_a = flow(reduced_image_a)
        hdr = reduced_image_a[0].header
        self.set_base_headers(hdr)

        # basic reduction of B images
        list_b = [
            rinput.obresult.frames[i] for i, char in enumerate(full_set)
            if char == 'B'
        ]
        with contextlib.ExitStack() as stack:
            self.logger.info('starting basic reduction of B images')
            hduls = [stack.enter_context(fname.open()) for fname in list_b]
            reduced_image_b = combine_imgs(hduls,
                                           method=method,
                                           method_kwargs=method_kwargs,
                                           errors=False,
                                           prolog=None)
        reduced_image_b = flow(reduced_image_b)
        hdr = reduced_image_b[0].header
        self.set_base_headers(hdr)

        # save intermediate reduced_image_a and reduced_image_b
        self.save_intermediate_img(reduced_image_a, 'reduced_image_a.fits')
        self.save_intermediate_img(reduced_image_b, 'reduced_image_b.fits')

        # computation of A-B
        header_a = reduced_image_a[0].header
        header_b = reduced_image_b[0].header
        data_a = reduced_image_a[0].data.astype('float32')
        data_b = reduced_image_b[0].data.astype('float32')
        reduced_data = data_a - data_b

        # update reduced image header
        reduced_image = self.create_reduced_image(
            rinput,
            reduced_data,
            header_a,
            header_b,
            rinput.pattern,
            full_set,
            voffset_pix=0,
            header_mos_abba=None,
        )

        # save intermediate image in work directory
        self.save_intermediate_img(reduced_image, 'reduced_image.fits')

        # apply rectification and wavelength calibration
        self.logger.info('begin rect.+wavecal. reduction of ABBA spectra')
        reduced_mos_abba = apply_rectwv_coeff(reduced_image, rectwv_coeff)
        header_mos_abba = reduced_mos_abba[0].header

        # combine A and B data by shifting B on top of A
        voffset_pix = rinput.voffset_pix

        if voffset_pix is not None and voffset_pix != 0:
            self.logger.info(
                'correcting vertical offset (pixesl): {}'.format(voffset_pix))
            reduced_mos_abba_data = reduced_mos_abba[0].data.astype('float32')
            shifted_a_minus_b_data = shift_image2d(
                reduced_mos_abba_data,
                yoffset=-voffset_pix,
            ).astype('float32')
            reduced_mos_abba_combined_data = \
                reduced_mos_abba_data - shifted_a_minus_b_data
            # scale signal to exposure of a single image
            reduced_mos_abba_combined_data /= 2.0
        else:
            reduced_mos_abba_combined_data = None

        # update reduced combined image header
        reduced_mos_abba_combined = self.create_reduced_image(
            rinput,
            reduced_mos_abba_combined_data,
            header_a,
            header_b,
            rinput.pattern,
            full_set,
            voffset_pix,
            header_mos_abba=header_mos_abba)

        # ds9 region files (to be saved in the work directory)
        if self.intermediate_results:
            save_four_ds9(rectwv_coeff)
            save_spectral_lines_ds9(rectwv_coeff)

        # compute median spectra employing the useful region of the
        # rectified image
        if self.intermediate_results:
            for imode, outfile in enumerate([
                    'median_spectra_full', 'median_spectra_slitlets',
                    'median_spectrum_slitlets'
            ]):
                median_image = median_slitlets_rectified(reduced_mos_abba,
                                                         mode=imode)
                self.save_intermediate_img(median_image, outfile + '.fits')

        # save results in results directory
        self.logger.info('end rect.+wavecal. reduction of ABBA spectra')
        result = self.create_result(
            reduced_mos_abba=reduced_mos_abba,
            reduced_mos_abba_combined=reduced_mos_abba_combined)
        return result
예제 #6
0
    def run(self, rinput):

        nimages = len(rinput.obresult.frames)
        pattern = rinput.pattern
        pattern_length = len(pattern)

        # check combination method
        if rinput.method != 'sigmaclip':
            if rinput.method_kwargs != {}:
                raise ValueError('Unexpected method_kwargs={}'.format(
                    rinput.method_kwargs))

        # check pattern sequence matches number of images
        if nimages % pattern_length != 0:
            raise ValueError('Number of images is not a multiple of pattern '
                             'length: {}, {}'.format(nimages, pattern_length))
        nsequences = nimages // pattern_length

        # check rectification and wavelength calibration information
        if rinput.rectwv_coeff is None and rinput.list_rectwv_coeff is None:
            raise ValueError('No rectwv_coeff nor list_rectwv_coeff data have '
                             'been provided')
        elif rinput.rectwv_coeff is not None and \
                rinput.list_rectwv_coeff is not None:
            raise ValueError("rectwv_coeff and list_rectwv_coeff cannot be "
                             "used simultaneously")
        elif rinput.rectwv_coeff is not None:
            list_rectwv_coeff = [rinput.rectwv_coeff] * nimages
        elif rinput.list_rectwv_coeff is not None:
            if len(rinput.list_rectwv_coeff) != nimages:
                raise ValueError("Unexpected number of rectwv_coeff files "
                                 "in list_rectwv_coeff")
            else:
                list_rectwv_coeff = rinput.list_rectwv_coeff
                # check filter and grism are the same in all JSON files
                for item in ['grism', 'filter']:
                    list_values = []
                    for calib in list_rectwv_coeff:
                        list_values.append(calib.tags[item])
                    if len(set(list_values)) != 1:
                        raise ValueError(
                            'list_rectwv_coeff contains coefficients for '
                            'different {}s'.format(item))
        else:
            raise ValueError("Unexpected error!")

        # grism and filter names
        grism_name = list_rectwv_coeff[0].tags['grism']
        filter_name = list_rectwv_coeff[0].tags['filter']

        # compute offsets from WCS info in image headers
        with contextlib.ExitStack() as stack:
            hduls = [
                stack.enter_context(fname.open())
                for fname in rinput.obresult.frames
            ]
            sep_arcsec, spatial_scales = compute_wcs_offsets(hduls)

        sep_pixel = np.round(sep_arcsec / spatial_scales, 6)

        for i in range(nimages):
            self.logger.info(list_rectwv_coeff[i])
        self.logger.info(
            'observation pattern..................: {}'.format(pattern))
        self.logger.info(
            'nsequences...........................: {}'.format(nsequences))
        self.logger.info(
            'offsets (arcsec, from WCS)...........: {}'.format(sep_arcsec))
        self.logger.info(
            'spatial scales (arcsec/pix, from WCS): {}'.format(spatial_scales))
        self.logger.info(
            'spatial scales (pixels, from WCS)....: {}'.format(sep_pixel))

        full_set = pattern * nsequences
        self.logger.info(
            'full set of images...................: {}'.format(full_set))

        # basic parameters to determine useful pixels in the wavelength
        # direction
        dict_rtas = rinput.refine_target_along_slitlet

        valid_keys = [
            'npix_removed_near_ohlines', 'nwidth_medfilt',
            'save_individual_images', 'ab_different_target',
            'vpix_region_a_target', 'vpix_region_a_sky',
            'vpix_region_b_target', 'vpix_region_b_sky',
            'list_valid_wvregions_a', 'list_valid_wvregions_b'
        ]
        for dumkey in dict_rtas.keys():
            if dumkey not in valid_keys:
                raise ValueError('Unexpected key={}'.format(dumkey))

        if 'vpix_region_a_target' in dict_rtas.keys():
            vpix_region_a_target = dict_rtas['vpix_region_a_target']
        else:
            vpix_region_a_target = None

        if 'vpix_region_a_sky' in dict_rtas.keys():
            vpix_region_a_sky = dict_rtas['vpix_region_a_sky']
        else:
            vpix_region_a_sky = None

        if 'vpix_region_b_target' in dict_rtas.keys():
            vpix_region_b_target = dict_rtas['vpix_region_b_target']
        else:
            vpix_region_b_target = None

        if 'vpix_region_b_sky' in dict_rtas.keys():
            vpix_region_b_sky = dict_rtas['vpix_region_b_sky']
        else:
            vpix_region_b_sky = None

        if 'ab_different_target' in dict_rtas.keys():
            ab_different_target = int(dict_rtas['ab_different_target'])
            if ab_different_target not in [-1, 0, 1, 9]:
                raise ValueError('Invalid ab_different_target={} value'.format(
                    ab_different_target))
        else:
            raise ValueError('Missing ab_different_target value')

        try:
            npix_removed_near_ohlines = \
                int(dict_rtas['npix_removed_near_ohlines'])
        except KeyError:
            npix_removed_near_ohlines = 0
        except ValueError:
            raise ValueError('wrong value: npix_removed_near_ohlines='
                             '{}'.format(
                                 dict_rtas['npix_removed_near_ohlines']))

        if 'list_valid_wvregions_a' in dict_rtas.keys():
            if vpix_region_a_target is None:
                raise ValueError('Unexpected list_valid_wvregions_a when '
                                 'vpix_region_a_target is not set')
            list_valid_wvregions_a = dict_rtas['list_valid_wvregions_a']
        else:
            list_valid_wvregions_a = None

        if 'list_valid_wvregions_b' in dict_rtas.keys():
            if vpix_region_b_target is None:
                raise ValueError('Unexpected list_valid_wvregions_b when '
                                 'vpix_region_b_target is not set')

            list_valid_wvregions_b = dict_rtas['list_valid_wvregions_b']
        else:
            list_valid_wvregions_b = None

        try:
            nwidth_medfilt = int(dict_rtas['nwidth_medfilt'])
        except KeyError:
            nwidth_medfilt = 0
        except ValueError:
            raise ValueError('wrong value: nwidth_medfilt={}'.format(
                dict_rtas['nwidth_medfilt']))

        try:
            save_individual_images = int(dict_rtas['save_individual_images'])
        except KeyError:
            save_individual_images = 0
        except ValueError:
            raise ValueError('wrong value: save_individual_images={}'.format(
                dict_rtas['save_individual_images']))

        self.logger.info(
            'npix_removed_near_ohlines: {}'.format(npix_removed_near_ohlines))
        self.logger.info('nwidth_medfilt: {}'.format(nwidth_medfilt))
        self.logger.info(
            'vpix_region_a_target: {}'.format(vpix_region_a_target))
        self.logger.info(
            'vpix_region_b_target: {}'.format(vpix_region_b_target))
        self.logger.info(
            'list_valid_wvregions_a: {}'.format(list_valid_wvregions_a))
        self.logger.info(
            'list_valid_wvregions_b: {}'.format(list_valid_wvregions_b))

        # build object to proceed with bpm, bias, dark and flat
        flow = self.init_filters(rinput)

        # basic reduction, rectification and wavelength calibration of
        # all the individual images
        list_reduced_mos_images = []
        self.logger.info('starting reduction of individual images')
        for i, char in enumerate(full_set):
            frame = rinput.obresult.frames[i]
            self.logger.info('image {} ({} of {})'.format(
                char, i + 1, nimages))
            self.logger.info('image: {}'.format(frame.filename))
            with frame.open() as f:
                base_header = f[0].header.copy()
                data = f[0].data.astype('float32')
            grism_name_ = base_header['grism']
            if grism_name_ != grism_name:
                raise ValueError('Incompatible grism name in '
                                 'rectwv_coeff.json file and FITS image')
            filter_name_ = base_header['filter']
            if filter_name_ != filter_name:
                raise ValueError('Incompatible filter name in '
                                 'rectwv_coeff.json file and FITS image')
            hdu = fits.PrimaryHDU(data, header=base_header)
            hdu.header['UUID'] = str(uuid.uuid1())
            hdul = fits.HDUList([hdu])
            # basic reduction
            reduced_image = flow(hdul)
            hdr = reduced_image[0].header
            self.set_base_headers(hdr)
            # rectification and wavelength calibration
            reduced_mos_image = apply_rectwv_coeff(reduced_image,
                                                   list_rectwv_coeff[i])
            if save_individual_images != 0:
                self.save_intermediate_img(
                    reduced_mos_image, 'reduced_mos_image_' + char + '_' +
                    frame.filename[:10] + '.fits')
            list_reduced_mos_images.append(reduced_mos_image)

        # intermediate PDF file with crosscorrelation plots
        if self.intermediate_results:
            from matplotlib.backends.backend_pdf import PdfPages
            pdf = PdfPages('crosscorrelation_ab.pdf')
        else:
            pdf = None

        # compute offsets between images
        self.logger.info('computing offsets between individual images')
        first_a = True
        first_b = True
        xisok_a = None
        xisok_b = None
        reference_profile_a = None
        reference_profile_b = None
        refine_a = vpix_region_a_target is not None
        refine_b = vpix_region_b_target is not None
        list_offsets = []
        for i, char in enumerate(full_set):
            if char == 'A' and refine_a:
                refine_image = True
            elif char == 'B' and refine_b:
                refine_image = True
            else:
                refine_image = False
            if refine_image:
                frame = rinput.obresult.frames[i]
                isky = get_isky(i, pattern)
                frame_sky = rinput.obresult.frames[isky]
                self.logger.info('image {} ({} of {})'.format(
                    char, i + 1, nimages))
                self.logger.info('image: {}'.format(frame.filename))
                self.logger.info('(sky): {}'.format(frame_sky.filename))
                data = list_reduced_mos_images[i][0].data.copy()
                data_sky = list_reduced_mos_images[isky][0].data
                data -= data_sky
                base_header = list_reduced_mos_images[i][0].header

                # get useful pixels in the wavelength direction
                if char == 'A' and first_a:
                    xisok_a = useful_mos_xpixels(
                        data,
                        base_header,
                        vpix_region=vpix_region_a_target,
                        npix_removed_near_ohlines=npix_removed_near_ohlines,
                        list_valid_wvregions=list_valid_wvregions_a,
                        debugplot=0)
                elif char == 'B' and first_b:
                    xisok_b = useful_mos_xpixels(
                        data,
                        base_header,
                        vpix_region=vpix_region_b_target,
                        npix_removed_near_ohlines=npix_removed_near_ohlines,
                        list_valid_wvregions=list_valid_wvregions_b,
                        debugplot=0)

                if char == 'A':
                    nsmin = vpix_region_a_target[0]
                    nsmax = vpix_region_a_target[1]
                    xisok = xisok_a
                    if vpix_region_a_sky is not None:
                        nsmin_sky = vpix_region_a_sky[0]
                        nsmax_sky = vpix_region_a_sky[1]
                        skysubtraction = True
                    else:
                        nsmin_sky = None
                        nsmax_sky = None
                        skysubtraction = False
                elif char == 'B':
                    nsmin = vpix_region_b_target[0]
                    nsmax = vpix_region_b_target[1]
                    xisok = xisok_b
                    if vpix_region_b_sky is not None:
                        nsmin_sky = vpix_region_b_sky[0]
                        nsmax_sky = vpix_region_b_sky[1]
                        skysubtraction = True
                    else:
                        nsmin_sky = None
                        nsmax_sky = None
                        skysubtraction = False
                else:
                    raise ValueError('Unexpected char value: {}'.format(char))

                # initial slitlet region
                slitlet2d = data[(nsmin - 1):nsmax, :].copy()
                if skysubtraction:
                    slitlet2d_sky = data[(nsmin_sky - 1):nsmax_sky, :].copy()
                    median_sky = np.median(slitlet2d_sky, axis=0)
                    slitlet2d -= median_sky

                # selected wavelength regions after blocking OH lines
                slitlet2d_blocked = slitlet2d[:, xisok]

                # apply median filter in the X direction
                if nwidth_medfilt > 1:
                    slitlet2d_blocked_smoothed = ndimage.filters.median_filter(
                        slitlet2d_blocked, size=(1, nwidth_medfilt))
                else:
                    slitlet2d_blocked_smoothed = slitlet2d_blocked

                # ---
                # convert to 1D series of spatial profiles (note: this
                # option does not work very well when the signal is low;
                # a simple mean profile does a better job)
                # profile = slitlet2d_blocked_smoothed.transpose().ravel()
                # ---
                profile = np.mean(slitlet2d_blocked_smoothed, axis=1)
                if char == 'A' and first_a:
                    reference_profile_a = profile.copy()
                elif char == 'B' and first_b:
                    reference_profile_b = profile.copy()
                # ---
                # # To write pickle file
                # import pickle
                # with open(frame.filename[:10] + '_profile.pkl', 'wb') as f:
                #     pickle.dump(profile, f)
                # # To read pickle file
                # with open('test.pkl', 'rb') as f:
                #     x = pickle.load(f)
                # ---

                # crosscorrelation to find offset
                naround_zero = (nsmax - nsmin) // 3
                if char == 'A':
                    reference_profile = reference_profile_a
                elif char == 'B':
                    reference_profile = reference_profile_b
                else:
                    raise ValueError('Unexpected char value: {}'.format(char))
                offset, fpeak = periodic_corr1d(
                    sp_reference=reference_profile,
                    sp_offset=profile,
                    remove_mean=False,
                    frac_cosbell=0.10,
                    zero_padding=11,
                    fminmax=None,
                    nfit_peak=5,
                    naround_zero=naround_zero,
                    sp_label='spatial profile',
                    plottitle='Image #{} (type {}), {}'.format(
                        i + 1, char, frame.filename[:10]),
                    pdf=pdf)
                # round to 4 decimal places
                if abs(offset) < 1E-4:
                    offset = 0.0  # avoid -0.0
                else:
                    offset = round(offset, 4)
                list_offsets.append(offset)

                # end of loop
                if char == 'A' and first_a:
                    first_a = False
                elif char == 'B' and first_b:
                    first_b = False
            else:
                list_offsets.append(0.0)
        self.logger.info('computed offsets: {}'.format(list_offsets))

        self.logger.info('correcting vertical offsets between individual '
                         'images')
        list_a = []
        list_b = []
        for i, (char, offset) in enumerate(zip(full_set, list_offsets)):
            frame = rinput.obresult.frames[i]
            self.logger.info('image {} ({} of {})'.format(
                char, i + 1, nimages))
            self.logger.info('image: {}'.format(frame.filename))
            reduced_mos_image = list_reduced_mos_images[i]
            data = reduced_mos_image[0].data
            base_header = reduced_mos_image[0].header
            self.logger.info(
                'correcting vertical offset (pixesl): {}'.format(offset))
            if offset != 0:
                reduced_mos_image[0].data = shift_image2d(
                    data, yoffset=-offset).astype('float32')
            base_header['HISTORY'] = 'Applying voffset_pix {}'.format(offset)
            if save_individual_images != 0:
                self.save_intermediate_img(
                    reduced_mos_image, 'reduced_mos_image_refined_' + char +
                    '_' + frame.filename[:10] + '.fits')

            # store reduced_mos_image
            if char == 'A':
                list_a.append(reduced_mos_image)
            elif char == 'B':
                list_b.append(reduced_mos_image)
            else:
                raise ValueError('Unexpected char value: {}'.format(char))

        # combination method
        method = getattr(combine, rinput.method)
        method_kwargs = rinput.method_kwargs

        # final combination of A images
        self.logger.info('combining individual A images')
        reduced_mos_image_a = combine_imgs(list_a,
                                           method=method,
                                           method_kwargs=method_kwargs,
                                           errors=False,
                                           prolog=None)
        self.save_intermediate_img(reduced_mos_image_a,
                                   'reduced_mos_image_a.fits')

        # final combination of B images
        self.logger.info('combining individual B images')
        reduced_mos_image_b = combine_imgs(list_b,
                                           method=method,
                                           method_kwargs=method_kwargs,
                                           errors=False,
                                           prolog=None)
        self.save_intermediate_img(reduced_mos_image_b,
                                   'reduced_mos_image_b.fits')

        self.logger.info('mixing A and B spectra')
        header_a = reduced_mos_image_a[0].header
        header_b = reduced_mos_image_b[0].header
        data_a = reduced_mos_image_a[0].data.astype('float32')
        data_b = reduced_mos_image_b[0].data.astype('float32')

        reduced_mos_abba_data = data_a - data_b

        # update reduced mos image header
        reduced_mos_abba = self.create_mos_abba_image(rinput,
                                                      dict_rtas,
                                                      reduced_mos_abba_data,
                                                      header_a,
                                                      header_b,
                                                      pattern,
                                                      full_set,
                                                      list_offsets,
                                                      voffset_pix=0)

        # combine A and B data by shifting B on top of A
        if abs(ab_different_target) == 0:
            len_prof_a = len(reference_profile_a)
            len_prof_b = len(reference_profile_b)
            if len_prof_a == len_prof_b:
                reference_profile = reference_profile_a
                profile = reference_profile_b
                naround_zero = len_prof_a // 3
            elif len_prof_a > len_prof_b:
                ndiff = len_prof_a - len_prof_b
                reference_profile = reference_profile_a
                profile = np.concatenate(
                    (reference_profile_b, np.zeros(ndiff, dtype='float')))
                naround_zero = len_prof_a // 3
            else:
                ndiff = len_prof_b - len_prof_a
                reference_profile = np.concatenate(
                    (reference_profile_a, np.zeros(ndiff, dtype='float')))
                profile = reference_profile_b
                naround_zero = len_prof_b // 3
            offset, fpeak = periodic_corr1d(
                sp_reference=reference_profile,
                sp_offset=profile,
                remove_mean=False,
                frac_cosbell=0.10,
                zero_padding=11,
                fminmax=None,
                nfit_peak=5,
                naround_zero=naround_zero,
                sp_label='spatial profile',
                plottitle='Comparison of A and B profiles',
                pdf=pdf)
            voffset_pix = vpix_region_b_target[0] - vpix_region_a_target[0]
            voffset_pix += offset
        elif abs(ab_different_target) == 1:
            # apply nominal offset (from WCS info) between first A
            # and first B
            voffset_pix = sep_pixel[1] * ab_different_target
        elif ab_different_target == 9:
            voffset_pix = None
        else:
            raise ValueError(
                'Invalid ab_different_target={}'.format(ab_different_target))

        # close output PDF file
        if pdf is not None:
            pdf.close()

        if voffset_pix is not None:
            self.logger.info(
                'correcting vertical offset (pixesl): {}'.format(voffset_pix))
            shifted_a_minus_b_data = shift_image2d(
                reduced_mos_abba_data,
                yoffset=-voffset_pix,
            ).astype('float32')
            reduced_mos_abba_combined_data = \
                reduced_mos_abba_data - shifted_a_minus_b_data
            # scale signal to exposure of a single image
            reduced_mos_abba_combined_data /= 2.0
        else:
            reduced_mos_abba_combined_data = None

        # update reduced mos combined image header
        reduced_mos_abba_combined = self.create_mos_abba_image(
            rinput, dict_rtas, reduced_mos_abba_combined_data, header_a,
            header_b, pattern, full_set, list_offsets, voffset_pix)

        # ds9 region files (to be saved in the work directory)
        if self.intermediate_results:
            save_four_ds9(list_rectwv_coeff[0])
            save_spectral_lines_ds9(list_rectwv_coeff[0])

        # compute median spectra employing the useful region of the
        # rectified image
        if self.intermediate_results:
            for imode, outfile in enumerate([
                    'median_spectra_full', 'median_spectra_slitlets',
                    'median_spectrum_slitlets'
            ]):
                median_image = median_slitlets_rectified(reduced_mos_abba,
                                                         mode=imode)
                self.save_intermediate_img(median_image, outfile + '.fits')

        # save results in results directory
        self.logger.info('end rect.+wavecal. reduction of ABBA spectra')
        result = self.create_result(
            reduced_mos_abba=reduced_mos_abba,
            reduced_mos_abba_combined=reduced_mos_abba_combined)
        return result
예제 #7
0
    def run(self, rinput):
        self.logger.info('starting reduction of stare spectra')

        self.logger.info(rinput.master_rectwv)

        # build object to proceed with bpm, bias, dark and flat
        flow = self.init_filters(rinput)

        # apply bpm, bias, dark and flat
        reduced_image = basic_processing_with_combination(rinput,
                                                          flow,
                                                          method=median)
        # update header with additional info
        hdr = reduced_image[0].header
        self.set_base_headers(hdr)

        # save intermediate image in work directory
        self.save_intermediate_img(reduced_image, 'reduced_image.fits')

        # rectification and wavelength calibration (if a model has
        # been provided)
        if rinput.master_rectwv:
            # RectWaveCoeff object with rectification and wavelength
            # calibration coefficients for the particular CSU configuration
            rectwv_coeff = rectwv_coeff_from_mos_library(
                reduced_image, rinput.master_rectwv)

            # apply rectification and wavelength calibration
            stare_image = apply_rectwv_coeff(reduced_image, rectwv_coeff)

            # save as JSON file in work directory
            self.save_structured_as_json(rectwv_coeff, 'rectwv_coeff.json')

            # ds9 region files (to be saved in the work directory)
            if self.intermediate_results:
                save_four_ds9(rectwv_coeff)
                save_spectral_lines_ds9(rectwv_coeff)

            # compute median spectra employing the useful region of the
            # rectified image
            if self.intermediate_results:
                for imode, outfile in enumerate([
                        'median_spectra_full', 'median_spectra_slitlets',
                        'median_spectrum_slitlets'
                ]):
                    median_image = median_slitlets_rectified(stare_image,
                                                             mode=imode)
                    self.save_intermediate_img(median_image, outfile + '.fits')

            # image_wl_calibrated = True

        else:

            stare_image = reduced_image

            self.logger.info('No wavelength calibration provided')
            grism_value = hdr.get('GRISM', 'unknown')
            self.logger.debug('GRISM is %s', grism_value)
            if grism_value.lower() == 'open':
                self.logger.debug('GRISM is %s, so this seems OK', grism_value)

            # image_wl_calibrated = False

        if rinput.master_sky:
            # Sky subtraction after rectification
            msky = rinput.master_sky.open()
            # Check if images have the same size.
            # if so, go ahead
            if msky[0].data.shape != stare_image[0].data.shape:
                self.logger.warning(
                    "sky and current image don't have the same shape")
            else:
                sky_corrector = proc.SkyCorrector(
                    msky[0].data,
                    datamodel=self.datamodel,
                    calibid=self.datamodel.get_imgid(msky))

                stare_image = sky_corrector(stare_image)
        else:
            self.logger.info('No sky image provided')

        # save results in results directory
        self.logger.info('end reduction of stare spectra')
        result = self.create_result(reduced_image=reduced_image,
                                    stare=stare_image)
        return result
예제 #8
0
    def run(self, rinput):
        self.logger.info('starting rect.+wavecal. reduction of stare spectra')

        self.logger.info(rinput.master_rectwv)
        self.logger.info('Wavelength calibration refinement mode: {}'.format(
            rinput.refine_wavecalib_mode))
        self.logger.info('Minimum slitlet width (mm)............: {}'.format(
            rinput.minimum_slitlet_width_mm))
        self.logger.info('Maximum slitlet width (mm)............: {}'.format(
            rinput.maximum_slitlet_width_mm))
        self.logger.info('Global offset X direction (pixels)....: {}'.format(
            rinput.global_integer_offset_x_pix))
        self.logger.info('Global offset Y direction (pixels)....: {}'.format(
            rinput.global_integer_offset_y_pix))

        # build object to proceed with bpm, bias, dark and flat
        flow = self.init_filters(rinput)

        # apply bpm, bias, dark and flat
        reduced_image = basic_processing_with_combination(rinput,
                                                          flow,
                                                          method=median)
        # update header with additional info
        hdr = reduced_image[0].header
        self.set_base_headers(hdr)

        # save intermediate image in work directory
        self.save_intermediate_img(reduced_image, 'reduced_image.fits')

        # RectWaveCoeff object with rectification and wavelength
        # calibration coefficients for the particular CSU configuration
        rectwv_coeff = rectwv_coeff_from_mos_library(reduced_image,
                                                     rinput.master_rectwv)

        # set global offsets
        rectwv_coeff.global_integer_offset_x_pix = \
            rinput.global_integer_offset_x_pix
        rectwv_coeff.global_integer_offset_y_pix = \
            rinput.global_integer_offset_y_pix

        # apply rectification and wavelength calibration
        reduced_mos = apply_rectwv_coeff(reduced_image, rectwv_coeff)

        # wavelength calibration refinement
        # 0 -> no refinement
        # 1 -> apply global offset to all the slitlets (using ARC lines)
        # 2 -> apply individual offset to each slitlet (using ARC lines)
        # 11 -> apply global offset to all the slitlets (using OH lines)
        # 12 -> apply individual offset to each slitlet (using OH lines)
        if rinput.refine_wavecalib_mode != 0:
            self.logger.info(
                'Refining wavelength calibration (mode={})'.format(
                    rinput.refine_wavecalib_mode))
            # refine RectWaveCoeff object
            rectwv_coeff, expected_catalog_lines = refine_rectwv_coeff(
                reduced_mos,
                rectwv_coeff,
                rinput.refine_wavecalib_mode,
                rinput.minimum_slitlet_width_mm,
                rinput.maximum_slitlet_width_mm,
                save_intermediate_results=self.intermediate_results)
            self.save_intermediate_img(expected_catalog_lines,
                                       'expected_catalog_lines.fits')
            # re-apply rectification and wavelength calibration
            reduced_mos = apply_rectwv_coeff(reduced_image, rectwv_coeff)

        # ds9 region files (to be saved in the work directory)
        if self.intermediate_results:
            save_four_ds9(rectwv_coeff)
            save_spectral_lines_ds9(rectwv_coeff)

        # compute median spectra employing the useful region of the
        # rectified image
        if self.intermediate_results:
            for imode, outfile in enumerate([
                    'median_spectra_full', 'median_spectra_slitlets',
                    'median_spectrum_slitlets'
            ]):
                median_image = median_slitlets_rectified(reduced_mos,
                                                         mode=imode)
                self.save_intermediate_img(median_image, outfile + '.fits')

        # save results in results directory
        self.logger.info('end rect.+wavecal. reduction of stare spectra')
        result = self.create_result(reduced_mos=reduced_mos,
                                    rectwv_coeff=rectwv_coeff)
        return result
예제 #9
0
파일: stare.py 프로젝트: bxy8804/pyemir
    def run(self, rinput):
        self.logger.info('starting rect.+wavecal. reduction of stare spectra')

        self.logger.info(rinput.master_rectwv)
        self.logger.info(
            'Wavelength calibration refinement mode....: {}'.format(
                rinput.refine_wavecalib_mode))
        self.logger.info(
            'Minimum slitlet width (mm)................: {}'.format(
                rinput.minimum_slitlet_width_mm))
        self.logger.info(
            'Maximum slitlet width (mm)................: {}'.format(
                rinput.maximum_slitlet_width_mm))
        self.logger.info(
            'Global integer offsets mode...............: {}'.format(
                rinput.global_integer_offsets_mode))
        self.logger.info(
            'Global integer offset X direction (pixels): {}'.format(
                rinput.global_integer_offset_x_pix))
        self.logger.info(
            'Global integer offset Y direction (pixels): {}'.format(
                rinput.global_integer_offset_y_pix))

        # build object to proceed with bpm, bias, dark and flat
        flow = self.init_filters(rinput)

        # apply bpm, bias, dark and flat
        reduced_image = basic_processing_with_combination(rinput,
                                                          flow,
                                                          method=sigmaclip)
        # update header with additional info
        hdr = reduced_image[0].header
        self.set_base_headers(hdr)

        # save intermediate image in work directory
        self.save_intermediate_img(reduced_image, 'reduced_image.fits')

        # RectWaveCoeff object with rectification and wavelength
        # calibration coefficients for the particular CSU configuration
        rectwv_coeff = rectwv_coeff_from_mos_library(reduced_image,
                                                     rinput.master_rectwv)

        # wavelength calibration refinement
        # 0 -> no refinement
        # 1 -> apply global offset to all the slitlets (using ARC lines)
        # 2 -> apply individual offset to each slitlet (using ARC lines)
        # 11 -> apply global offset to all the slitlets (using OH lines)
        # 12 -> apply individual offset to each slitlet (using OH lines)
        if rinput.refine_wavecalib_mode != 0:
            main_header = reduced_image[0].header

            # determine useful slitlets
            csu_config = CsuConfiguration.define_from_header(main_header)
            # segregate slitlets
            list_useful_slitlets = csu_config.widths_in_range_mm(
                minwidth=rinput.minimum_slitlet_width_mm,
                maxwidth=rinput.maximum_slitlet_width_mm)
            # remove missing slitlets
            if len(rectwv_coeff.missing_slitlets) > 0:
                for iremove in rectwv_coeff.missing_slitlets:
                    if iremove in list_useful_slitlets:
                        list_useful_slitlets.remove(iremove)

            list_not_useful_slitlets = [
                i for i in list(range(1, EMIR_NBARS + 1))
                if i not in list_useful_slitlets
            ]
            self.logger.info(
                'list of useful slitlets: {}'.format(list_useful_slitlets))
            self.logger.info('list of unusable slitlets: {}'.format(
                list_not_useful_slitlets))

            # retrieve arc/OH lines
            catlines_all_wave, catlines_all_flux = retrieve_catlines(
                rinput.refine_wavecalib_mode, main_header['grism'])

            # global integer offsets
            if rinput.global_integer_offsets_mode == 'auto':
                if (rinput.global_integer_offset_x_pix != 0) or \
                        (rinput.global_integer_offset_y_pix != 0):
                    raise ValueError('Global integer offsets must be zero when'
                                     ' mode=auto')

                # ToDo: include additional airglow emission lines

                self.logger.info('computing synthetic image')
                # generate synthetic image
                synthetic_raw_data = synthetic_lines_rawdata(
                    catlines_all_wave, catlines_all_flux, list_useful_slitlets,
                    rectwv_coeff)
                synthetic_raw_header = main_header.copy()
                synthetic_raw_header['DATE-OBS'] = \
                    datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
                chistory = 'Synthetic image'
                synthetic_raw_header.add_history(chistory)
                hdu = fits.PrimaryHDU(synthetic_raw_data.astype('float32'),
                                      header=synthetic_raw_header)
                synthetic_raw_image = fits.HDUList([hdu])
                if self.intermediate_results:
                    self.save_intermediate_img(synthetic_raw_image,
                                               'synthetic_raw_image.fits')

                # cross-correlation to determine global integer offsets
                # (rescaling data arrays to [0, 1] before using skimage
                # function)
                data1_rs, coef1_rs = rescale_array_to_z1z2(
                    reduced_image[0].data, (0, 1))
                data2_rs, coef2_rs = rescale_array_to_z1z2(
                    synthetic_raw_data, (0, 1))
                shifts, error, diffphase = register_translation(
                    data1_rs, data2_rs, 100)
                self.logger.info(
                    'global_float_offset_x_pix..: {}'.format(-shifts[1]))
                self.logger.info(
                    'global_float_offset_y_pix..: {}'.format(-shifts[0]))
                rectwv_coeff.global_integer_offset_x_pix = \
                    -int(round(shifts[1]))
                rectwv_coeff.global_integer_offset_y_pix = \
                    -int(round(shifts[0]))
                self.logger.info('global_integer_offset_x_pix: {}'.format(
                    rectwv_coeff.global_integer_offset_x_pix))
                self.logger.info('global_integer_offset_y_pix: {}'.format(
                    rectwv_coeff.global_integer_offset_y_pix))
                if self.intermediate_results:
                    data_product = np.fft.fft2(data1_rs) * \
                                   np.fft.fft2(data2_rs).conj()
                    cc_image = np.fft.fftshift(np.fft.ifft2(data_product))
                    power = np.log10(cc_image.real)
                    hdu_power = fits.PrimaryHDU(power)
                    hdul_power = fits.HDUList([hdu_power])
                    hdul_power.writeto('power.fits', overwrite=True)
            else:
                rectwv_coeff.global_integer_offset_x_pix = \
                    rinput.global_integer_offset_x_pix
                rectwv_coeff.global_integer_offset_y_pix = \
                    rinput.global_integer_offset_y_pix

            # apply initial rectification and wavelength calibration
            reduced_mos = apply_rectwv_coeff(reduced_image, rectwv_coeff)

            self.logger.info(
                'Refining wavelength calibration (mode={})'.format(
                    rinput.refine_wavecalib_mode))
            # refine RectWaveCoeff object
            rectwv_coeff, expected_catalog_lines = refine_rectwv_coeff(
                reduced_mos,
                rectwv_coeff,
                catlines_all_wave,
                catlines_all_flux,
                rinput.refine_wavecalib_mode,
                list_useful_slitlets,
                save_intermediate_results=self.intermediate_results)
            self.save_intermediate_img(expected_catalog_lines,
                                       'expected_catalog_lines.fits')

        # apply rectification and wavelength calibration
        reduced_mos = apply_rectwv_coeff(reduced_image, rectwv_coeff)

        # ds9 region files (to be saved in the work directory)
        if self.intermediate_results:
            save_four_ds9(rectwv_coeff)
            save_spectral_lines_ds9(rectwv_coeff)

        # compute median spectra employing the useful region of the
        # rectified image
        if self.intermediate_results:
            for imode, outfile in enumerate([
                    'median_spectra_full', 'median_spectra_slitlets',
                    'median_spectrum_slitlets'
            ]):
                median_image = median_slitlets_rectified(reduced_mos,
                                                         mode=imode)
                self.save_intermediate_img(median_image, outfile + '.fits')

        # save results in results directory
        self.logger.info('end rect.+wavecal. reduction of stare spectra')
        result = self.create_result(reduced_mos=reduced_mos,
                                    rectwv_coeff=rectwv_coeff)
        return result