Beispiel #1
0
    def test__regrid_spect(self, data__interp_spect):
        """
        Checks to make:

        - Ensure new_wavl comes out correctly in output
        - Ensure no interp'd points above/below input points
        """
        wavl, data, new_wavl = data__interp_spect

        gs = GHOSTSpect([])
        new_data = gs._regrid_spect(data, wavl, new_wavl, waveunits='angstrom')

        assert new_data.shape == new_wavl.shape, "Data was not successfully " \
                                                 "reshaped to the new " \
                                                 "wavelength scale " \
                                                 "(expected {}, " \
                                                 "have {})".format(
            new_wavl.shape, new_data.shape,
        )

        max_wavl_spacing = np.max(wavl[1:] - wavl[:-1])
        assert np.sum(new_data[np.logical_or(
            new_wavl < np.min(wavl) - max_wavl_spacing,
            new_wavl > np.max(wavl) + max_wavl_spacing,
        )]) < 1e-6, "Non-zero interpolated data points " \
                    "have been identified outside the " \
                    "range of the original wavelength " \
                    "scale"
Beispiel #2
0
    def test__compute_barycentric_correction_values(
            self, ra, dec, dt, known_corr,
            data__compute_barycentric_correction):
        """
        Checks to make:

        - Correct units of return based on input arguments
        - Some regression test values
        """
        ad, tmpsubdir = data__compute_barycentric_correction
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))
        ad.phu.set('RA', ra)
        ad.phu.set('DEC', dec)
        # Assume a 10 min exposure
        exp_time_min = 10.
        dt_obs = datetime.datetime.strptime(dt, '%Y-%m-%d %H:%M:%S')
        dt_start = dt_obs - datetime.timedelta(minutes=exp_time_min)
        ad.phu.set('DATE-OBS', dt_start.date().strftime('%Y-%m-%d'))
        ad.phu.set('UTSTART', dt_start.time().strftime('%H:%M:%S.00'))
        ad[0].hdr.set('EXPTIME', exp_time_min * 60.)

        gs = GHOSTSpect([])
        corr_fact = gs._compute_barycentric_correction(ad, )[0]
        assert abs(corr_fact - known_corr) < 1e-6, \
            "_compute_barycentric_correction " \
            "returned an incorrect value " \
            "(expected {}, returned {})".format(
                known_corr, corr_fact,
            )
Beispiel #3
0
    def test_responseCorrect(self, tmpdir):
        """
        Checks to make:

        - Ensure skip option functions correctly

        More complete testing to be made in 'all-up' reduction
        """
        tmpsubdir = tmpdir.mkdir('ghost_responsecorr')
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))
        ad = self.generate_minimum_file()
        gs = GHOSTSpect([])

        # Test the skip functionality
        ad_out = gs.responseCorrect([
            ad,
        ], skip=True)[0]
        assert ad_out.phu.get(
            gs.timestamp_keys['responseCorrect']
        ) is None, "responseCorrect appears to have acted on a file " \
                   "when skip=True"

        # Teardown - remove calibrations and output file
        for _ in glob.glob(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename, '*.fits')):
            os.remove(_)
        try:
            shutil.rmtree(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename,
                             'calibrations'))
        except OSError:
            pass
Beispiel #4
0
    def test_standardizeStructure(self, tmpdir):
        """
        Checks to make:

        - This is a no-op primitive - ensure no change is made
        """
        tmpsubdir = tmpdir.mkdir('ghost_standstruct')
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))
        ad = self.generate_minimum_file()
        ad_orig = copy.deepcopy(ad)
        gs = GHOSTSpect([])

        ad_out = gs.standardizeStructure([
            ad,
        ])[0]
        assert np.all([
            ad_orig.info() == ad_out.info(),
            ad_orig.phu == ad_out.phu,
            ad_orig[0].hdr == ad_out[0].hdr,
            len(ad_orig) == len(ad_out),
        ]), "standardizeStructure is no longer a no-op primitive"

        # Teardown - remove calibrations and output file
        for _ in glob.glob(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename, '*.fits')):
            os.remove(_)
        try:
            shutil.rmtree(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename,
                             'calibrations'))
        except OSError:
            pass
Beispiel #5
0
 def test__interp_spect_invalid_type(self, data__interp_spect):
     wavl, data, new_wavl = data__interp_spect
     gs = GHOSTSpect([])
     with pytest.raises(NotImplementedError):
         new_data = gs._interp_spect(data,
                                     wavl,
                                     new_wavl,
                                     interp='no-such-method')
Beispiel #6
0
    def test_darkCorrect_rebin(self, xbin, ybin, tmpdir):
        """
        Checks to make:

        - Ensure re-binning of darks is correctly triggered (i.e. deliberately
          pass science and dark data w/ different binning, ensure no failure)
        - Error mode check: see for error if length of dark list != length of
          science list
        - Check for DARKIM in output header
        - Check before & after data shape
        """
        tmpsubdir = tmpdir.mkdir('ghost_darkcorrect')
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))

        ad = self.generate_minimum_file()
        dark = self.generate_minimum_file()
        dark.filename = 'dark.fits'

        # 'Re-bin' the data file
        ad[0].data = np.ones((
            int(1024 / ybin),
            int(1024 / xbin),
        ),
                             dtype=np.float64)
        ad[0].hdr.set('CCDSUM', '{} {}'.format(
            xbin,
            ybin,
        ))

        gs = GHOSTSpect([])
        input_shape = ad[0].data.shape
        ad_out = gs.darkCorrect([
            ad,
        ], dark=[
            dark,
        ])[0]

        assert ad_out[0].data.shape == input_shape, "darkCorrect has mangled " \
                                                    "the shape of the input " \
                                                    "data"
        # Teardown - remove calibrations and output file
        for _ in glob.glob(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename, '*.fits')):
            os.remove(_)
        try:
            shutil.rmtree(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename,
                             'calibrations'))
        except OSError:
            pass
Beispiel #7
0
    def test__compute_barycentric_correction_returnwavl(
            self, return_wavl, units, data__compute_barycentric_correction):
        """
        Check the return units of _compute_barycentric_correction
        """
        # ad should be correctly populated from previous test
        ad, tmpsubdir = data__compute_barycentric_correction
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))

        gs = GHOSTSpect([])
        corr_fact = gs._compute_barycentric_correction(
            ad, return_wavl=return_wavl)[0]
        assert corr_fact.unit == units, \
            "_compute_barycentric_correction returned incorrect units " \
            "(expected {}, got {})".format(units, corr_fact.unit, )
Beispiel #8
0
    def test_clipSigmaBPM(self, tmpdir):
        """
        Checks to make:

        - Send it dummy file with known number of pixels outside range,
          make sure that many pixels are flagged out
        """
        tmpsubdir = tmpdir.mkdir('ghost_clipsigma')
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))

        ad = self.generate_minimum_file()
        ad[0].DQ = np.zeros(ad[0].data.shape, dtype=np.int)
        # Insert some very large data points into the otherwise all-1s data
        xs = list(range(0, 1024))
        ys = list(range(0, 1024))
        np.random.shuffle(xs)
        np.random.shuffle(ys)
        xs = xs[:10]
        ys = ys[:10]
        for i in range(10):
            ad[0].data[ys[i], xs[i]] = 1000.

        gs = GHOSTSpect([])
        ad_out = gs.clipSigmaBPM([
            ad,
        ], bpm_value=1)[0]

        assert np.all([ad_out[0].mask[ys[i], xs[i]] == 1
                       for i in range(10)]), "clipSigmaBPM failed to mask " \
                                             "out all injected outliers"

        assert ad_out.phu.get(
            gs.timestamp_keys['clipSigmaBPM']), "clipSigmaBPM did not " \
                                                "timestamp-mark the " \
                                                "output file"

        # Teardown - remove calibrations and output file
        for _ in glob.glob(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename, '*.fits')):
            os.remove(_)
        try:
            shutil.rmtree(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename,
                             'calibrations'))
        except OSError:
            pass
Beispiel #9
0
    def test__get_polyfit_filename_errors(self, data__get_polyfit_filename):
        """
        Check passing an invalid calib. type throws an error
        """
        ad, tmpsubdir = data__get_polyfit_filename
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))
        ad.phu.set('SMPNAME', 'HI_ONLY')
        ad.phu.set('CAMERA', 'RED')
        ad.phu.set('UTSTART',
                   datetime.datetime.now().time().strftime('%H:%M:%S'))
        ad.phu.set('DATE-OBS',
                   datetime.datetime.now().date().strftime('%Y-%m-%d'))

        gs = GHOSTSpect([])
        polyfit_file = gs._get_polyfit_filename(ad, 'not-a-cal-type')
        assert polyfit_file is None, "_get_polyfit_filename didn't return " \
                                     "None when asked for a bogus " \
                                     "model type"
Beispiel #10
0
    def test__interp_spect(self, interp, data__interp_spect):
        """
        Checks to make:

        - New wavelength array appears in output
        - Any point in output can be interpolated from surrounding points in
          input
        - Verify allowed values for kwarg 'interp'
        """
        wavl, data, new_wavl = data__interp_spect

        gs = GHOSTSpect([])
        new_data = gs._interp_spect(data, wavl, new_wavl, interp='linear')

        assert new_data.shape == new_wavl.shape, "Data was not successfully " \
                                                 "reshaped to the new " \
                                                 "wavelength scale " \
                                                 "(expected {}, " \
                                                 "have {})".format(
            new_wavl.shape, new_data.shape,
        )
Beispiel #11
0
    def test__get_polyfit_filename(self, arm, res, caltype,
                                   data__get_polyfit_filename):
        """
        Checks to make:

        - Provide a set of input (arm, res, ) arguments, see if a/ name is
          returned
        """
        ad, tmpsubdir = data__get_polyfit_filename
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))
        ad.phu.set('SMPNAME', res)
        ad.phu.set('CAMERA', arm)
        ad.phu.set('UTSTART',
                   datetime.datetime.now().time().strftime('%H:%M:%S'))
        ad.phu.set('DATE-OBS',
                   datetime.datetime.now().date().strftime('%Y-%m-%d'))

        gs = GHOSTSpect([])
        polyfit_file = gs._get_polyfit_filename(ad, caltype)

        assert polyfit_file is not None, "Could not find polyfit file"
Beispiel #12
0
    def test_applyFlatBPM(self, data_applyFlatBPM):
        """
        Checks to make:

        - Check for addition of flat BPM
        - Make sure the flat BPM has been added correctly (find a second method
          of combining and checking)
        - Check before & after data shape
        """
        ad, flat_ad, tmpsubdir = data_applyFlatBPM
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))

        # Check the AttributeError is no flat is provided
        gs = GHOSTSpect([
            ad,
        ])
        with pytest.raises(AttributeError):
            ad_output = gs.applyFlatBPM([ad, ]), "applyFlatBPM failed to " \
                                                 "raise AttributeError when " \
                                                 "not passed a flat or flat " \
                                                 "stream"

        ad_output = gs.applyFlatBPM([
            ad,
        ], flat=flat_ad)
        # Check that flat BPM is correctly carried over to (blank) ad BPM
        assert np.allclose(ad_output[0].mask,
                           flat_ad[0].mask), "applyFlatBPM failed to " \
                                             "correctly apply a flat BPM " \
                                             "to a data file with a blank " \
                                             "BPM"

        # Double the BPM on the data (i.e. make all the values 2), and ensure
        # that the re-applied values come out as 3
        ad[0].mask *= 2
        ad_output = gs.applyFlatBPM([
            ad,
        ], flat=flat_ad)
        assert np.allclose(ad_output[0].mask,
                           flat_ad[0].mask * 3), "applyFlatBPM failed to " \
                                                 "correctly apply a flat BPM " \
                                                 "to a data file with a non-" \
                                                 "zero BPM"

        # Ensure the correct behaviour when the data file has no BPM
        ad[0].mask = None  # Is this the right way to do this? del doesn't work
        ad_output = gs.applyFlatBPM([
            ad,
        ], flat=flat_ad)
        assert np.allclose(ad_output[0].mask,
                           flat_ad[0].mask), "applyFlatBPM failed to " \
                                             "correctly apply a flat BPM " \
                                             "to a data file with no inital " \
                                             "BPM"

        # Check that the file has been marked as processed
        assert ad.phu.get(
            gs.timestamp_keys['applyFlatBPM']), "clipSigmaBPM did not " \
                                                "timestamp-mark the " \
                                                "output file"
Beispiel #13
0
    def test_interpolateAndCombine(self, tmpdir):
        """
        Checks to make:

        - Error on invalid scale option
        - Correct functioning of 'skip' parameter

        Fuller testing needs to be done 'all-up' in a reduction sequence.
        """
        tmpsubdir = tmpdir.mkdir('ghost_inc')
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))
        ad = self.generate_minimum_file()
        gs = GHOSTSpect([])

        # Make sure the correct error is thrown on an invalid scale
        with pytest.raises(ValueError):
            gs.interpolateAndCombine([
                ad,
            ], scale='not-a-scale')

        # Test the skip functionality
        ad_out = gs.interpolateAndCombine([
            ad,
        ], skip=True)[0]
        assert ad_out.phu.get(
            gs.timestamp_keys['interpolateAndCombine']
        ) is None, "interpolateAndCombine appears to have acted on a file " \
                   "when skip=True"

        # Teardown - remove calibrations and output file
        for _ in glob.glob(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename, '*.fits')):
            os.remove(_)
        try:
            shutil.rmtree(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename,
                             'calibrations'))
        except OSError:
            pass
Beispiel #14
0
    def test_darkCorrect(self, tmpdir):
        tmpsubdir = tmpdir.mkdir('ghost_darkcorr')
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))

        ad = self.generate_minimum_file()
        dark = self.generate_minimum_file()
        dark.filename = 'dark.fits'

        gs = GHOSTSpect([])
        ad_out = gs.darkCorrect([
            ad,
        ], dark=[
            dark,
        ])

        # import pdb; pdb.set_trace()

        assert ad_out[0].phu.get('DARKIM') == dark.filename, \
            "darkCorrect failed to record the name of the dark " \
            "file used in the output header (expected {}, got {})".format(
                dark.filename, ad_out[0].phu.get('DARKIM'),
            )

        assert ad_out[0].phu.get(
            gs.timestamp_keys['darkCorrect']), "darkCorrect did not " \
                                               "timestamp-mark the " \
                                               "output file"

        # Teardown - remove calibrations and output file
        for _ in glob.glob(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename, '*.fits')):
            os.remove(_)
        try:
            shutil.rmtree(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename,
                             'calibrations'))
        except OSError:
            pass
Beispiel #15
0
    def test_barycentricCorrect(self, data_barycentricCorrect):
        """
        Checks to make:

        - Make random checks that a non-1.0 correction factor works properly
        - Check before & after data shape

        Testing of the helper _compute_barycentric_correction is done
        separately.
        """
        ad, orig_wavl, tmpsubdir = data_barycentricCorrect
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))
        orig_ad = copy.deepcopy(ad)

        gs = GHOSTSpect([
            ad,
        ])
        corr_fact = random.uniform(0.5, 1.5)
        ad_out = gs.barycentricCorrect([
            ad,
        ], correction_factor=corr_fact)[0]
        assert np.allclose(ad_out[0].WAVL / corr_fact,
                           orig_wavl), "barycentricCorrect appears not to " \
                                       "have made a valid correction " \
                                       "(tried to correct by {}, " \
                                       "apparent correction {})".format(
            corr_fact, np.average(ad_out[0].WAVL / orig_wavl)
        )
        assert orig_ad[0].WAVL.shape == ad_out[0].WAVL.shape, \
            "barycentricCorrect has mangled the shape of the output " \
            "WAVL extension"

        assert ad_out.phu.get(
            gs.timestamp_keys['barycentricCorrect']), "clipSigmaBPM did not " \
                                                      "timestamp-mark the " \
                                                      "output file"
Beispiel #16
0
    def test_darkCorrect_errors(self, tmpdir):
        tmpsubdir = tmpdir.mkdir('ghost_dcerrors')
        os.chdir(os.path.join(tmpsubdir.dirname, tmpsubdir.basename))

        ad = self.generate_minimum_file()
        dark = self.generate_minimum_file()
        dark.filename = 'dark.fits'

        gs = GHOSTSpect([])

        # Passing in data inputs with different binnings
        with pytest.raises(IOError):
            ad2 = copy.deepcopy(ad)
            ad2[0].hdr.set('CCDSUM', '2 2')
            gs.darkCorrect([
                ad,
                ad2,
            ], dark=[
                dark,
                dark,
            ])

        # Mismatched list lengths
        with pytest.raises(Exception):
            gs.darkCorrect([
                ad,
                ad2,
                ad,
            ], dark=[
                dark,
                dark,
            ])

        # Teardown - remove calibrations and output file
        for _ in glob.glob(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename, '*.fits')):
            os.remove(_)
        try:
            shutil.rmtree(
                os.path.join(tmpsubdir.dirname, tmpsubdir.basename,
                             'calibrations'))
        except OSError:
            pass