Пример #1
0
def test_do_stage(mock_normalize):
    # tests that the normalized spectrum are assigned correctly.
    expected = 1
    # make a single order spectrum
    flux = np.arange(1, 101) * expected
    x = np.arange(1, 101)
    spectrum = Table({
        'wavelength': [x, 2 * x],
        'flux': [flux, 2 * flux],
        'blaze': [flux, 2 * flux],
        'blaze_error': [flux, 2 * flux],
        'uncertainty': [flux, 2 * flux],
        'fiber': [0, 0],
        'order': [1, 2]
    })
    image = NRESObservationFrame(
        [CCDData(np.zeros(
            (1, 1)), meta={'OBJECTS': 'tung&tung&none'})], 'test.fits')
    image.spectrum = Spectrum1D(spectrum)
    # make it so that ContinuumNormalizer.normalize just returns ones.
    mock_normalize.return_value = (expected * np.ones_like(flux),
                                   expected * np.ones_like(flux))

    # Run the normalizer code
    stage = ContinuumNormalizer(SimpleNamespace(db_address='foo'))
    image = stage.do_stage(image)
    for order in [1, 2]:
        assert np.allclose(image.spectrum[0, order]['normflux'], expected)
        assert np.allclose(image.spectrum[0, order]['normuncertainty'],
                           expected)
Пример #2
0
def test_background_subtraction_with_traces(seed):
    nx, ny = 405, 403
    x = np.arange(nx)
    y = np.arange(ny)
    X, Y = np.meshgrid(x, y)
    noise_sigma = 1.0
    input_background = 30 * np.exp(-(X - nx / 2.0)**2 / 300**2 -
                                   (Y - ny / 2.0 - 50.0)**2 / 200**2)
    test_data = input_background + np.random.normal(
        0.0, noise_sigma, size=input_background.shape)
    test_image = NRESObservationFrame([
        CCDData(data=test_data,
                uncertainty=np.ones((ny, nx)) * noise_sigma,
                meta={'OBJECTS': 'tung&tung&none'})
    ], 'foo.fits')

    test_image.traces = np.zeros((ny, nx))

    for i in range(1, 8):
        test_image.traces[40 * i:40 * i + 10] = i

    input_context = context.Context({})
    stage = BackgroundSubtractor(input_context)
    output_image = stage.do_stage(test_image)
    # Make sure our background estimation is good. This is roughly 4 counts which is not bad
    # If we fully model the image, we can do better than this, but that becomes computationally prohibitive on a 4kx4k
    # image
    np.testing.assert_allclose(output_image.background,
                               input_background,
                               atol=5.0)
Пример #3
0
def test_profile_fit_with_noise_with_blaze():
    nx, ny = 401, 403
    input_profile, trace_centers, input_traces = make_simple_traces(nx,
                                                                    ny,
                                                                    blaze=True)
    read_noise = 10.0

    # Filter out the numerical noise
    input_profile[input_profile < 1e-15] = 0.0
    input_profile += np.random.poisson(input_profile)
    input_profile += np.random.normal(0.0,
                                      read_noise,
                                      size=input_profile.shape)
    uncertainty = np.sqrt(input_profile + read_noise**2.0)
    image = NRESObservationFrame([
        CCDData(data=input_profile.copy(),
                uncertainty=uncertainty,
                meta={'OBJECTS': 'tung&tung&none'})
    ], 'foo.fits')
    image.traces = input_traces
    input_context = context.Context({})

    stage = ProfileFitter(input_context)
    image = stage.do_stage(image)

    for i in range(1, np.max(image.traces) + 1):
        this_trace = get_trace_region(image.traces == i)
        scale_factor = np.max(input_profile[this_trace]) / np.max(
            image.profile[this_trace] * image.blaze[i - 1]['blaze'])
        np.testing.assert_allclose(input_profile[this_trace],
                                   image.profile[this_trace] *
                                   image.blaze[i - 1]['blaze'] * scale_factor,
                                   rtol=1.5e-2,
                                   atol=1.0)
Пример #4
0
def test_refine_traces_offset_centroid():
    nx, ny = 401, 403
    x2d, y2d = np.meshgrid(np.arange(nx), np.arange(ny))
    test_data, trace_centers, input_traces = make_simple_traces(nx, ny)
    read_noise = 10.0

    # Filter out the numerical noise
    test_data[test_data < 1e-15] = 0.0
    test_data += np.random.poisson(test_data)
    test_data += np.random.normal(0.0, read_noise, size=test_data.shape)
    uncertainty = np.sqrt(test_data + read_noise**2.0)
    test_image = NRESObservationFrame([
        CCDData(data=test_data,
                uncertainty=uncertainty,
                meta={'OBJECTS': 'tung&tung&none'})
    ], 'foo.fits')
    test_image.traces = input_traces
    input_context = context.Context({'TRACE_HALF_HEIGHT': 5})

    stage = TraceRefiner(input_context)
    output_image = stage.do_stage(test_image)

    for trace_center in trace_centers:
        # Make sure that the center +- 4 pixels is in the trace image
        assert all(output_image.traces[np.abs(y2d - trace_center + 1) <= 4])
Пример #5
0
def test_refine_traces_curved_trace():
    nx, ny = 1001, 1003
    expected_trace = np.zeros((ny, nx), dtype=int)
    trace_half_height = 5
    x0 = 498
    input_y_center = 2e-4 * (np.arange(nx) - x0)**2.0 + 0.01 * (np.arange(nx) -
                                                                x0) + 502.0
    trace = np.round(input_y_center).astype(int)
    for i in np.arange(nx, dtype=int):
        for j in range(-trace_half_height, trace_half_height + 1):
            expected_trace[trace[i] + j, i] = 1
    x2d, y2d = np.meshgrid(np.arange(nx, dtype=int), np.arange(ny, dtype=int))
    sigma = 1.5
    y_center = np.array([input_y_center.copy() for i in range(ny)])
    test_data = 1 / sigma / (2.0 * np.pi) * np.exp(
        -0.5 * (y2d - y_center)**2.0 / sigma**2)

    test_image = NRESObservationFrame([
        CCDData(data=test_data,
                uncertainty=np.zeros_like(test_data),
                meta={'OBJECTS': 'tung&tung&none'})
    ], 'foo.fits')
    test_image.traces = np.ones_like(expected_trace)
    refine_traces(test_image,
                  weights=test_image.data,
                  trace_half_height=trace_half_height)

    np.testing.assert_equal(test_image.traces, expected_trace)
Пример #6
0
 def apply_master_calibration(self, image: NRESObservationFrame,
                              master_calibration_image):
     # TODO should not load a master arc calibration if it is older than ~a week.
     image.wavelengths = master_calibration_image.wavelengths
     image.fibers = master_calibration_image.fibers
     image.meta[
         'L1IDARC'] = master_calibration_image.filename, 'ID of ARC/DOUBLE frame'
     return image
Пример #7
0
 def test_do_stage_on_empty_features(self):
     input_context = context.Context({})
     image = NRESObservationFrame([CCDData(data=self.data, uncertainty=self.err,
                                   meta={'OBJECTS': 'tung&tung&none'})], 'foo.fits')
     image.traces = np.ones_like(self.data, dtype=int)
     image.blaze = {'blaze': np.ones_like(self.data, dtype=int)}
     stage = IdentifyFeatures(input_context)
     stage.fwhm, stage.nsigma = self.sigma, 1.5
     image = stage.do_stage(image)
     assert len(image.features) == 0
Пример #8
0
 def generate_image(self):
     traces = np.array([[0, 0, 0], [1, 1, 1], [1, 1, 1], [0, 0, 0], [0, 0, 0], [2, 2, 2], [3, 3, 3]])
     line_list = np.array([10, 11, 12])
     pixel_positions = np.array([1, 2, 1, 2])
     features = Table({'pixel': pixel_positions, 'id': np.array([1, 1, 2, 3]), 'order': np.array([1, 1, 2, 3]),
                       'wavelength': pixel_positions, 'centroid_err': np.ones_like(pixel_positions)})
     image = NRESObservationFrame([CCDData(data=np.zeros((2, 2)), uncertainty=np.zeros((2, 2)),
                                   meta={'OBJECTS': 'tung&tung&none'})], 'foo.fits')
     image.features = features
     image.traces = traces
     image.line_list = line_list
     return image
Пример #9
0
 def test_do_stage_no_blaze(self):
     input_context = context.Context({})
     ccd_data = CCDData(data=self.data, uncertainty=self.err, meta={'OBJECTS': 'tung&tung&none'})
     image = NRESObservationFrame([ccd_data], 'foo.fits')
     image.traces = np.ones_like(self.data, dtype=int)
     stage = IdentifyFeatures(input_context)
     stage.fwhm, stage.nsigma = self.sigma, 0.5
     image = stage.do_stage(image)
     image.features.sort('pixel')
     assert np.allclose(image.features['pixel'], self.xcoords, atol=0.001)
     assert np.allclose(image.features['ycentroid'], self.ycoords, atol=0.001)
     assert np.allclose(image.features['id'], 1)
Пример #10
0
 def do_stage(self, image: NRESObservationFrame):
     if image.profile is None:
         logger.error('Profile missing. Rejecting image.', image=image)
         return None
     image.add_or_update(
         ArrayData(np.zeros_like(image.data, dtype=float), name='WEIGHTS'))
     trace_ids = np.arange(1, image.num_traces + 1)
     for trace_id in trace_ids:
         yx = get_trace_region(np.isclose(image.traces, trace_id))
         image.weights[yx] = self.weights(image.profile[yx],
                                          image.uncertainty[yx]**2,
                                          image.mask[yx])
     return image
Пример #11
0
def test_refining_on_noisy_data():
    nx, ny = 401, 403
    read_noise = 10.0
    test_data = np.zeros((ny, nx))
    x2d, y2d = np.meshgrid(np.arange(nx), np.arange(ny))

    trace_centers = []
    y_0s = [100, 200, 300]
    for i in range(3):
        trace_centers.append(5e-4 * (np.arange(nx) - nx / 2.)**2 + y_0s[i])
        test_data += gaussian(y2d, trace_centers[i], 3, a=10000.0)

    test_data += np.random.poisson(test_data)
    test_data += np.random.normal(0.0, read_noise, size=test_data.shape)
    uncertainty = np.sqrt(test_data + read_noise**2.0)
    test_image = NRESObservationFrame([
        CCDData(data=test_data,
                uncertainty=uncertainty,
                meta={'OBJECTS': 'tung&tung&none'})
    ], 'foo.fits')
    input_context = context.Context({'TRACE_HALF_HEIGHT': 5})
    stage = TraceInitializer(input_context)
    output_image = stage.do_stage(test_image)

    for trace_center in trace_centers:
        # Make sure that the center +- 4 pixels is in the trace image
        assert all(output_image.traces[np.abs(y2d - trace_center) <= 4])
Пример #12
0
    def test_do_stage(self):
        blaze_factor = 0.5
        input_context = context.Context({})
        ccd_data = CCDData(data=self.data, uncertainty=self.err, meta={'OBJECTS': 'tung&tung&none'})
        image = NRESObservationFrame([ccd_data], 'foo.fits')
        image.traces = np.ones_like(self.data, dtype=int)
        image.blaze = {'blaze': blaze_factor * np.ones((1, self.data.shape[1]), dtype=int)}

        stage = IdentifyFeatures(input_context)
        stage.fwhm, stage.nsigma = self.sigma, 0.5
        image = stage.do_stage(image)
        image.features.sort('pixel')
        assert np.allclose(image.features['corrected_flux'], image.features['flux'] / blaze_factor, rtol=1E-4)
        assert np.allclose(image.features['pixel'], self.xcoords, atol=0.001)
        assert np.allclose(image.features['ycentroid'], self.ycoords, atol=0.001)
        assert np.allclose(image.features['id'], 1)
Пример #13
0
def test_get_num_lit_fibers():
    image = NRESObservationFrame(
        [HeaderOnly(meta={'OBJECTS': 'tung&tung&none'})], 'foo.fits')
    assert image.num_lit_fibers() == 2
    image = NRESObservationFrame(
        [HeaderOnly(meta={'OBJECTS': 'none&tung&none'})], 'foo.fits')
    assert image.num_lit_fibers() == 1
Пример #14
0
def two_order_image():
    # generate 2 flat traces.
    traces = np.zeros((60, 20))
    traces[[10, 11, 12], :] = 1
    # the second trace that does not span the image entirely
    traces[[50, 51, 52], :] = 2
    traces[[50, 51, 52], 0] = 0
    traces[[50, 51, 52], -1] = 0
    # generate test data with zero noise
    data = np.ones_like(traces, dtype=float)
    data[~np.isclose(traces, 0)] = 100.
    uncertainty = 1. * data
    wavelengths = (traces > 0).astype(float) * 5
    image = NRESObservationFrame([
        CCDData(data=data,
                uncertainty=uncertainty,
                meta={'OBJECTS': 'tung&tung&none'})
    ], 'foo.fits')
    image.wavelengths = wavelengths
    image.traces = traces
    image.fibers = {'fiber': np.arange(2), 'order': np.arange(2)}
    image.blaze = {
        'id': np.arange(2),
        'blaze': [np.arange(20), np.arange(20)],
        'blaze_error': [np.arange(20), np.arange(20)]
    }
    return image
Пример #15
0
def test_refine_traces_with_previous_trace():
    nx, ny = 401, 403
    num_traces = 3
    read_noise = 10.0
    test_data = np.zeros((ny, nx))
    x2d, y2d = np.meshgrid(np.arange(nx), np.arange(ny))

    trace_half_width = 6
    trace_centers = []
    y_0s = [100, 200, 300]
    blaze_function = 1 - 1e-5 * (x2d - nx / 2.)**2
    input_traces = np.zeros((ny, nx), dtype=np.int)
    for i in range(num_traces):
        trace_centers.append(5e-4 * (np.arange(nx) - nx / 2.)**2 + y_0s[i])
        test_data += gaussian(y2d, trace_centers[i], 2,
                              a=10000.0) * blaze_function
        input_traces[np.abs(y2d -
                            trace_centers[i]) <= trace_half_width] = i + 1

    # Filter out the numerical noise
    test_data[test_data < 1e-15] = 0.0
    test_data += np.random.poisson(test_data)
    test_data += np.random.normal(0.0, read_noise, size=test_data.shape)
    uncertainty = np.sqrt(test_data + read_noise**2.0)
    test_image = NRESObservationFrame([
        CCDData(data=test_data,
                uncertainty=uncertainty,
                meta={'OBJECTS': 'tung&tung&none'})
    ], 'foo.fits')
    test_image.traces = input_traces
    input_context = context.Context({'TRACE_HALF_HEIGHT': 5})

    stage = TraceRefiner(input_context)
    output_image = stage.do_stage(test_image)

    for trace_center in trace_centers:
        # Make sure that the center +- 4 pixels is in the trace image
        assert all(output_image.traces[np.abs(y2d - trace_center) <= 4])
    assert np.isclose(num_traces, output_image.num_traces)
Пример #16
0
def test_profile_fit_without_noise_without_blaze():
    nx, ny = 401, 403
    input_profile, trace_centers, input_traces = make_simple_traces(
        nx, ny, blaze=False)
    # Filter out the numerical noise
    input_profile[input_profile < 1e-15] = 0.0
    uncertainty = np.sqrt(input_profile)
    image = NRESObservationFrame([
        CCDData(data=input_profile.copy(),
                uncertainty=uncertainty,
                meta={'OBJECTS': 'tung&tung&none'})
    ], 'foo.fits')
    image.traces = input_traces
    input_context = context.Context({})

    stage = ProfileFitter(input_context)
    image = stage.do_stage(image)
    scale_factor = np.max(input_profile) / np.max(image.profile)
    assert np.allclose(input_profile[input_traces != 0],
                       image.profile[input_traces != 0] * scale_factor,
                       rtol=5e-3,
                       atol=1.0)
Пример #17
0
def test_blind_solve():
    trace_centers, test_data, x2d, y2d = make_realistic_trace_image()
    test_image = NRESObservationFrame([
        CCDData(data=test_data,
                uncertainty=1e-5 * np.ones_like(test_data),
                meta={'OBJECTS': 'tung&tung&none'})
    ], 'foo.fits')
    input_context = context.Context({'TRACE_HALF_HEIGHT': 5})
    stage = TraceInitializer(input_context)
    output_image = stage.do_stage(test_image)
    for trace_center in trace_centers:
        # Make sure that the center +- 4 pixels is in the trace image
        assert all(output_image.traces[np.abs(y2d - trace_center) <= 4])
Пример #18
0
def test_do_stage_does_not_fit_non_science_fiber():
    # make a single order spectrum
    flux = np.arange(1, 101) * 2
    x = np.arange(1, 101)
    spectrum = Table({
        'wavelength': [x],
        'flux': [flux],
        'blaze': [flux],
        'blaze_error': [flux],
        'uncertainty': [flux],
        'fiber': [1],
        'order': [1]
    })
    image = NRESObservationFrame(
        [CCDData(np.zeros(
            (1, 1)), meta={'OBJECTS': 'tung&tung&none'})], 'test.fits')
    image.spectrum = Spectrum1D(spectrum)

    # Run the normalizer code
    stage = ContinuumNormalizer(SimpleNamespace(db_address='foo'))
    image = stage.do_stage(image)
    assert 'normflux' not in image.spectrum._table.colnames
    assert 'normuncertainty' not in image.spectrum._table.colnames
Пример #19
0
def test_blind_solve_with_edge_clipping_traces():
    trace_centers, test_data, x2d, y2d = make_realistic_trace_image(
        nx=401, ny=403, y0_centers=[1, 200, 400])
    test_image = NRESObservationFrame([
        CCDData(data=test_data,
                uncertainty=1e-5 * np.ones_like(test_data),
                meta={'OBJECTS': 'tung&tung&none'})
    ], 'foo.fits')
    input_context = context.Context({'TRACE_HALF_HEIGHT': 5})
    stage = TraceInitializer(input_context)
    output_image = stage.do_stage(test_image)
    assert np.count_nonzero(list(set(output_image.traces[:, 200]))) == 1
    # test that the only valid trace is centered correctly
    assert all(output_image.traces[np.abs(y2d - trace_centers[1]) <= 4])
Пример #20
0
def test_blind_solve_with_bpm():
    trace_centers, test_data, x2d, y2d = make_realistic_trace_image()
    bpm_mask = np.ones_like(test_data, dtype=bool)
    bpm_mask[
        150:
        250, :] = 0  # set the pixels around the center trace as good. Leave the other pixels masked.
    test_image = NRESObservationFrame([
        CCDData(data=test_data,
                uncertainty=1e-5 * np.ones_like(test_data),
                meta={'OBJECTS': 'tung&tung&none'},
                mask=bpm_mask)
    ], 'foo.fits')
    input_context = context.Context({'TRACE_HALF_HEIGHT': 5})
    stage = TraceInitializer(input_context)
    output_image = stage.do_stage(test_image)
    assert np.count_nonzero(list(set(output_image.traces[:, 200]))) == 1
    # test that the only valid trace is centered correctly
    assert all(output_image.traces[np.abs(y2d - trace_centers[1]) <= 4])
Пример #21
0
    def do_stage(self, image: NRESObservationFrame):
        if image.weights is None:
            logger.error('Extraction weights are missing. Rejecting image.',
                         image=image)
            return None
        if image.wavelengths is None:
            logger.error('Wavelengths are missing. Rejecting image.',
                         image=image)
            return None
        # consider adding a method to image, i.e. image.extracted_spectrum_shape.
        flux = np.zeros((image.num_traces, image.data.shape[1]), dtype=float)
        wavelength = np.zeros_like(flux, dtype=float)
        variance = np.zeros_like(flux, dtype=float)
        mask = np.zeros_like(flux, dtype=np.uint8)

        trace_ids = np.arange(1, image.num_traces + 1, dtype=int)
        for i, trace_id in enumerate(trace_ids):
            this_trace = get_trace_region(np.isclose(image.traces, trace_id))
            # get the horizontal (x) extent of the trace. Consider making this a get_extent function.
            x_extent = slice(np.min(this_trace[1]), np.max(this_trace[1]) + 1)
            flux[i, x_extent] = self.extract_order(image.data[this_trace],
                                                   image.weights[this_trace])
            variance[i, x_extent] = self.extract_order(
                image.uncertainty[this_trace]**2, image.weights[this_trace]**2)
            # TODO: some fix that allows for actual wavelength extraction:
            # wavelength[i, x_extent] = self.extract_order(image.wavelengths[this_trace],
            # weights=1/image.wavelengths[this_trace].shape[0])
            wavelength[i, x_extent] = np.median(image.wavelengths[this_trace],
                                                axis=0)

            mask[i, x_extent] = image.weights[this_trace].sum(axis=0) == 0.0

        image.spectrum = Spectrum1D({
            'id': trace_ids,
            'order': image.fibers['order'],
            'fiber': image.fibers['fiber'],
            'wavelength': wavelength,
            'flux': flux,
            'uncertainty': np.sqrt(variance),
            'blaze': image.blaze['blaze'],
            'blaze_error': image.blaze['blaze_error'],
            'mask': mask
        })
        return image
Пример #22
0
def test_to_fits():
    data = np.ones((2, 2))
    spec = Spectrum1D({
        'fiber': [0],
        'order': [1],
        'flux': [np.arange(10)],
        'wavelength': [np.arange(10)]
    })
    image = NRESObservationFrame([
        CCDData(data=data,
                uncertainty=2 * data,
                name='SCI',
                meta={
                    'OBJECTS': 'tung&tung&none',
                    'EXTNAME': ''
                })
    ], 'foo.fits')
    image.add_or_update(ArrayData(3 * data, name='TRACES'))
    image.add_or_update(ArrayData(4 * data, name='WEIGHTS'))
    image.add_or_update(ArrayData(5 * data, name='BACKGROUND'))
    image.add_or_update(DataTable(spec.table, name='SPECTRUM'))
    hdulist = image.to_fits(
        context.Context({
            'EXTENSION_NAMES_TO_CONDENSE': ['SCI'],
            'REDUCED_DATA_EXTENSION_TYPES': {},
            'fpack': True,
            'LOSSLESS_EXTENSIONS': []
        }))
    hdu_ext_names = [
        hdulist[i].header.get('EXTNAME') for i in range(len(hdulist))
        if hdulist[i].header.get('EXTNAME') is not None
    ]
    for name in [
            'SCI', 'BPM', 'ERR', 'TRACES', 'WEIGHTS', 'BACKGROUND', 'SPECTRUM'
    ]:
        assert name in hdu_ext_names
Пример #23
0
def five_hundred_square_image(maxflux,
                              number_traces,
                              trace_width,
                              read_noise=10,
                              seed=None):
    traces = np.zeros((500, 500))
    data = np.ones_like(traces, dtype=float)
    profile = np.zeros_like(traces, dtype=float)
    ix = np.arange(trace_width)
    for i in range(1, number_traces + 1):
        traces[40 * i:40 * i + trace_width, :] = i
        for j in range(0, trace_width):
            data[40 * i + j, :] += maxflux * np.exp(
                (-1.) * (ix[j] - trace_width / 2.)**2 / (trace_width / 6.)**2)
        for j in range(0, trace_width):
            profile[40 * i + j, :] = data[40 * i + j, :] / np.sum(
                data[40 * i:40 * i + trace_width, 0])
    np.random.seed(seed=seed)
    data += np.random.poisson(data)
    data += np.random.normal(0.0, read_noise, size=data.shape)
    uncertainty = np.sqrt(data + read_noise**2)
    wavelengths = np.ones_like(
        traces
    ) * 5  # dummy wavelengths image that has values distinct from flux and traces.
    image = NRESObservationFrame([
        CCDData(data=data,
                uncertainty=uncertainty,
                meta={'OBJECTS': 'tung&tung&none'})
    ], 'foo.fits')
    image.traces = traces
    image.profile = profile
    image.wavelengths = wavelengths
    image.blaze = {
        'id': np.arange(number_traces) + 1,
        'blaze': [np.ones(traces.shape[1]) for i in range(number_traces)],
        'blaze_error':
        [np.ones(traces.shape[1]) for i in range(number_traces)]
    }
    image.fibers = {
        'fiber': np.arange(number_traces) + 1,
        'order': np.arange(number_traces) + 1
    }
    return image
Пример #24
0
class TestCalculateScienceFrameMetrics:
    input_context = context.Context({'PIXELS_PER_RESOLUTION_ELEMENT': 4.15})
    test_wavelengths = np.linspace(5100.0, 5200.0, 4096)
    test_flux = -0.001 * test_wavelengths**2 + 10.3 * test_wavelengths
    test_uncertainty = np.sqrt(test_flux)
    snr_order = 90
    spectrum = []
    header = fits.Header({'OBJECTS': 'test&none&none'})
    for i in range(5):
        order = snr_order + i
        row = {'wavelength': test_wavelengths, 'flux': test_flux, 'uncertainty': test_uncertainty,
               'fiber': 0, 'order': snr_order}
        spectrum.append(row)
    test_image = NRESObservationFrame([CCDData(np.zeros((1, 1)), meta=header)], 'test.fits')
    test_image.spectrum = Spectrum1D(spectrum)

    def test_do_stage_does_not_crash(self):
        image = CalculateScienceFrameMetrics(self.input_context).do_stage(self.test_image)
        assert image is not None

    def test_snr_calculation(self):
        snr, _ = get_snr(self.test_image, self.snr_order, self.input_context.PIXELS_PER_RESOLUTION_ELEMENT)
        snr_test = self.test_flux/self.test_uncertainty * np.sqrt(self.input_context.PIXELS_PER_RESOLUTION_ELEMENT)
        assert np.isclose(snr, np.max(snr_test), rtol=0.1)
Пример #25
0
def test_get_telescope_filename():
    image = NRESObservationFrame([HeaderOnly(meta={'OBJECTS': 'tung&tung&none', 'TELESCOP': 'nres01'})], 'foo.fits')
    assert runtime_utils.get_telescope_filename(image) == 'nrs01'
Пример #26
0
def test_fiber_state_to_filename():
    image = NRESObservationFrame([HeaderOnly(meta={'OBJECTS': 'tung&tung&none'})], 'foo.fits')
    assert fibers_state_to_filename(image) == '110'
Пример #27
0
def test_rv(mock_loader, mock_db):
    # parameters that define the test data
    num_orders = 5
    lam_per_order = 70
    res = 0.1
    # Make fake data
    test_wavelengths = np.arange(4500.0,
                                 4500 + num_orders * lam_per_order + 100, res)
    flux = np.ones(test_wavelengths.shape) * 1000

    read_noise = 10.0
    # add in fake lines
    for i in range(1000):
        central_wavelength = np.random.uniform() * 2000.0 + 4500.0
        width = 0.1  # angstroms
        sigma = width / 2 / np.sqrt(2.0 * np.log(2.0))
        flux += gaussian(test_wavelengths, central_wavelength,
                         sigma) * 10000.0 * np.random.uniform()

    noisy_flux = np.random.poisson(flux).astype(float)
    noisy_flux += np.random.normal(0.0, read_noise, size=len(flux))
    uncertainty = np.sqrt(flux + read_noise**2.0)

    class MockLoader:
        def load(self, *args):
            return {'wavelength': test_wavelengths, 'flux': flux}

    mock_loader.return_value = MockLoader()
    true_v = 1.205 * units.km / units.s

    # Make the fake image
    # Set the site to the north pole, and the ra and dec to the ecliptic pole. The time we chose is just
    # to minimize the rv correction
    header = fits.Header({
        'DATE-OBS': '2020-09-12T00:00:00.000000',
        'RA': '18:00:00',
        'DEC': '+66:33:32.8178',
        'OBJECTS': 'foo&none&none',
        'EXPTIME': 1200.0
    })
    site_info = {'longitude': 0.0, 'latitude': 90.0, 'elevation': 0.0}

    # Each NRES order is ~70 Angstroms wide
    spectrum = []
    dx = int(lam_per_order / res)
    for i in range(5):
        order = slice(i * dx, (i + 1) * dx, 1)
        row = {
            'wavelength':
            test_wavelengths[order] * (1.0 + true_v / constants.c),
            'normflux': noisy_flux[order],
            'normuncertainty': uncertainty[order],
            'fiber': 0,
            'order': i
        }
        spectrum.append(row)
    image = NRESObservationFrame([CCDData(np.zeros((1, 1)), meta=header)],
                                 'test.fits')
    image.spectrum = Spectrum1D(spectrum)
    image.instrument = SimpleNamespace()
    image.instrument.site = 'npt'
    # Classification just can't be None so that the stage does not abort.
    image.classification = SimpleNamespace(**{
        'T_effective': 5000.0,
        'log_g': 0.0,
        'metallicity': 0.0,
        'alpha': 0.0
    })
    mock_db.return_value = SimpleNamespace(**site_info)

    # Run the RV code
    stage = RVCalculator(
        SimpleNamespace(db_address='foo',
                        MIN_ORDER_TO_CORRELATE=0,
                        MAX_ORDER_TO_CORRELATE=num_orders - 1))
    image = stage.do_stage(image)
    # Assert that the true_v + rv_correction is what is in the header within 5 m/s
    assert np.abs(
        true_v.to('m / s').value + image.meta['BARYCORR'] -
        image.meta['RV']) < 5.0