11import pytest
22import numpy as np
33from numpy .testing import assert_allclose
4- from astropy .io import fits
5- import stdatamodels .jwst .datamodels as dm
6- from jwst .datamodels .utils .wfss_multispec import make_wfss_multiexposure , make_wfss_multicombined , wfss_multiexposure_to_multispec
74
5+ import stdatamodels .jwst .datamodels as dm
6+ from jwst .datamodels .utils .wfss_multispec import (
7+ make_wfss_multiexposure ,
8+ make_wfss_multicombined ,
9+ wfss_multiexposure_to_multispec ,
10+ )
11+ from jwst .datamodels .utils .tests .wfss_helpers import (
12+ wfss_spec2_multi ,
13+ wfss_spec3_multi ,
14+ wfss_multi ,
15+ wfss_comb ,
16+ N_EXPOSURES ,
17+ N_SOURCES ,
18+ N_ROWS ,
19+ )
820
9- N_SOURCES = 5
10- N_EXPOSURES = 4
11- N_ROWS = 3
1221
1322@pytest .fixture
14- def example_spec ():
15-
16- def mock_wcs (* args , ** kwargs ):
17- return 0.0 , 0.0 , 0.0
18- spec = dm .SpecModel ()
19- spectable_dtype = spec .schema ["properties" ]["spec_table" ]["datatype" ]
20- recarray_dtype = [(d ["name" ], d ["datatype" ]) for d in spectable_dtype ]
21- spec .meta .wcs = mock_wcs
22- spec_table = np .recarray ((N_ROWS ,), dtype = recarray_dtype )
23- spec_table ["WAVELENGTH" ] = np .linspace (1.0 , 10.0 , N_ROWS )
24- spec_table ["FLUX" ] = np .ones (N_ROWS )
25- spec .spec_table = spec_table
26- spec .spec_table .columns ["wavelength" ].unit = "um"
27- return spec
28-
29- def _add_multispec_meta (spec ):
30- """
31- Add specmeta attributes to a spec-like ObjectNode inside a MultiSpecModel.
32-
33- This only includes attributes that do NOT need to change for each source/exposure
34- for the purposes of this test.
35-
36- input spec is updated in place.
37- """
38- spec .source_type = "POINT"
39- spec .source_ra = 0.0
40- spec .source_dec = 0.0
41- spec .extract2d_xstart = 0.0
42- spec .extract2d_ystart = 0.0
43- spec .extract2d_xstop = 0.0
44- spec .extract2d_ystop = 0.0
45- spec .extraction_xstart = 0.0
46- spec .extraction_ystart = 0.0
47- spec .extraction_xstop = 0.0
48- spec .extraction_ystop = 0.0
23+ def wfss_spec2_multispec ():
24+ return wfss_spec2_multi ()
4925
5026
5127@pytest .fixture
52- def wfss_spec2_multispec (example_spec ):
53- """
54- Set up a MultiSpecModel object that looks like outputs from extract_1d during calwebb_spec2.
55-
56- Each of the spectra is from the SAME exposure, but DIFFERENT sources.
57- """
58- multi = dm .MultiSpecModel ()
59- for i in range (N_SOURCES ):
60- # create a new SpecModel for each source
61- spec = example_spec .copy ()
62- spec .meta .filename = f"exposure_1.fits" # all sources in the same exposure
63- spec .meta .group_id = "1" # all sources in the same exposure
64- spec .source_id = N_SOURCES - i # reverse the order to test sorting
65- spec .name = str (spec .source_id )
66- _add_multispec_meta (spec )
67- multi .spec .append (spec )
28+ def wfss_spec3_multispec ():
29+ return wfss_spec3_multi ()
6830
69- return multi
31+
32+ @pytest .fixture
33+ def wfss_multiexposure ():
34+ return wfss_multi ()
7035
7136
7237@pytest .fixture
73- def wfss_spec3_multispec (example_spec ):
74- """
75- Set up a MultiSpecModel object that looks like outputs from extract_1d during calwebb_spec3.
76-
77- Each of the spectra is from the SAME source, but DIFFERENT exposures.
78- """
79- multi = dm .MultiSpecModel ()
80- multi .meta .exposure .exposure_time = 7.0
81- multi .meta .exposure .integration_time = 7.0
82- for j in range (N_EXPOSURES ):
83- # create a new SpecModel for each exposure
84- spec = example_spec .copy ()
85- spec .meta .filename = f"exposure_{ j } .fits"
86- spec .meta .group_id = str (j + 1 )
87- spec .source_id = 999 # all sources are the same
88- spec .dispersion_direction = 3
89- spec .name = str (spec .source_id )
90- _add_multispec_meta (spec )
91- multi .spec .append (spec )
92-
93- return multi
38+ def multi_combined ():
39+ return wfss_comb ()
40+
9441
9542
9643@pytest .mark .parametrize ("input_model_maker" , ["wfss_spec2_multispec" , "wfss_spec3_multispec" ])
9744def test_make_wfss_multiexposure (input_model_maker , request ):
9845 """
9946 Test reorganization of x1d data to flat file format.
100-
47+
10148 The two fixtures wfss_spec2_multispec and wfss_spec3_multispec have spectra that are
10249 identical, except that in the first case, all spectra are from the same exposure,
10350 and in the second case, all spectra are from the same source.
@@ -113,12 +60,12 @@ def test_make_wfss_multiexposure(input_model_maker, request):
11360 elif input_model_maker == "wfss_spec3_multispec" :
11461 assert len (output_model .spec ) == 4
11562 assert output_model .spec [0 ].spec_table .shape == (1 ,)
116-
63+
11764 # check the required metadata attributes
11865 assert not hasattr (output_model .meta , "wcs" )
11966 for i , exposure in enumerate (output_model .spec ):
12067 assert exposure .group_id == str (i + 1 )
121-
68+
12269 # check that units are present
12370 # test one vector-like column, which should come from the input specmodels
12471 # and one meta column, which should be copied from the schema by set_schema_units
@@ -147,20 +94,7 @@ def test_orders_are_separated(wfss_spec3_multispec):
14794 # ensure spectral order is in the metadata
14895 for i , exposure in enumerate (output_model .spec ):
14996 assert exposure .spectral_order == (i // 4 ) + 1 # first 4 are order 1, next 4 are order 2
150- assert exposure .group_id == str (i % 4 + 1 ) + str (exposure .spectral_order - 1 )
151-
152-
153- @pytest .fixture
154- def wfss_multiexposure (wfss_spec3_multispec ):
155- """Make a MultiExposureSpecModel object with N_EXPOSURES exposures and N_SOURCES sources."""
156- inputs_list = []
157- for i in range (N_SOURCES ):
158- this_source = wfss_spec3_multispec .copy ()
159- for spec in this_source .spec :
160- spec .source_id = N_SOURCES - i
161- inputs_list .append (this_source )
162- output_model = make_wfss_multiexposure (inputs_list )
163- return output_model
97+ assert exposure .group_id == str (i % 4 + 1 ) + str (exposure .spectral_order - 1 )
16498
16599
166100def test_wfss_flat_to_multispec (wfss_multiexposure ):
@@ -180,7 +114,7 @@ def test_wfss_flat_to_multispec(wfss_multiexposure):
180114 assert isinstance (multispec , dm .MultiSpecModel )
181115 assert len (multispec .spec ) == N_EXPOSURES
182116 for j , spec in enumerate (multispec .spec ):
183- assert spec .source_id == i + 1 # they will now be sorted
117+ assert spec .source_id == i + 1 # they will now be sorted
184118
185119 # check that the data is the same as the original
186120 assert_allclose (spec .spec_table ["WAVELENGTH" ], np .linspace (1.0 , 10.0 , N_ROWS ))
@@ -193,8 +127,14 @@ def test_wfss_flat_to_multispec(wfss_multiexposure):
193127
194128 # test that the rest of the metadata exist and are default values
195129 assert spec .source_type == "POINT"
196- for name in ["source_ra" , "source_dec" , "extract2d_xstart" , "extract2d_ystart" ,
197- "extract2d_xstop" , "extract2d_ystop" ]:
130+ for name in [
131+ "source_ra" ,
132+ "source_dec" ,
133+ "extract2d_xstart" ,
134+ "extract2d_ystart" ,
135+ "extract2d_xstop" ,
136+ "extract2d_ystop" ,
137+ ]:
198138 assert getattr (spec , name ) == 0.0
199139
200140
@@ -220,46 +160,19 @@ def test_wfss_multi_from_wfss_multi(wfss_multiexposure):
220160 # check that the output model has the correct dimensions
221161 assert isinstance (output_model , dm .WFSSMultiSpecModel )
222162 assert len (output_model .spec ) == N_EXPOSURES
223- assert output_model .spec [0 ].spec_table .shape == (N_SOURCES * 2 ,)
163+ assert output_model .spec [0 ].spec_table .shape == (N_SOURCES * 2 ,)
224164
225165 # test that the data has all the appropriate data and metadata
226166 for i , exposure in enumerate (output_model .spec ):
227167 assert exposure .group_id == str (i + 1 )
228- assert exposure .spec_table .shape == (N_SOURCES * 2 ,)
229-
230-
231- @pytest .fixture
232- def multi_combined ():
233- """
234- Make a MultiCombinedSpecModel object with N_SOURCES sources, N_ROWS rows, and 2 orders.
235-
236- This looks like the output of combine_1d.
237- """
238- multi = dm .MultiCombinedSpecModel ()
239- spec = dm .CombinedSpecModel ()
240- _add_multispec_meta (spec )
241- spectable_dtype = spec .schema ["properties" ]["spec_table" ]["datatype" ]
242- recarray_dtype = [(d ["name" ], d ["datatype" ]) for d in spectable_dtype ]
243- spec_table = np .recarray ((N_ROWS ,), dtype = recarray_dtype )
244- spec_table ["WAVELENGTH" ] = np .linspace (1.0 , 10.0 , N_ROWS )
245- spec_table ["FLUX" ] = np .ones (N_ROWS )
246- spec .spec_table = spec_table
247- spec .spec_table .columns ["wavelength" ].unit = "um"
248- spec .dispersion_direction = 3
249-
250- spec .spectral_order = 1
251- spec2 = spec .copy ()
252- spec2 .spectral_order = 2
253- multi .spec .append (spec )
254- multi .spec .append (spec2 )
255- return multi
168+ assert exposure .spec_table .shape == (N_SOURCES * 2 ,)
256169
257170
258171@pytest .fixture
259172def comb1d_list (multi_combined ):
260173 """
261174 Make a list of MultiCombinedSpecModel objects with N_SOURCES sources in list.
262-
175+
263176 Each MultiCombinedSpecModel object has only one spec, but the source_id is different.
264177 This looks like the output of calwebb_spec3 after calling combine_1d a bunch of times.
265178 """
@@ -287,7 +200,7 @@ def test_make_wfss_combined(comb1d_list):
287200 for col in to_check :
288201 assert col in spec .spec_table .columns .names
289202 assert spec .spec_table .columns [col ].unit == expected_units [to_check .index (col )]
290-
203+
291204 # check metadata
292205 assert spec .dispersion_direction == 3
293- assert spec .spectral_order == i + 1
206+ assert spec .spectral_order == i + 1
0 commit comments