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)
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
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])
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)
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)
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
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
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)
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)
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
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)
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)