def load_wcs(input_model, reference_files=None): """ Create a gWCS object and store it in ``Model.meta``. Parameters ---------- input_model : `~roman_datamodels.datamodels.WfiImage` The exposure. reference_files : dict A dict {reftype: reference_file_name} containing all reference files that apply to this exposure. Returns ------- output_model : `~roman_datamodels.ImageModel` The input image file with attached gWCS object. The data is not modified. """ output_model = input_model.copy() if reference_files is not None: for ref_type, ref_file in reference_files.items(): if ref_file not in ["N/A", ""]: reference_files[ref_type] = ref_file else: reference_files[ref_type] = None else: reference_files = {} # Frames detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) v2v3 = cf.Frame2D(name='v2v3', axes_order=(0, 1), axes_names=('v2', 'v3'), unit=(u.arcsec, u.arcsec)) world = cf.CelestialFrame(reference_frame=coord.ICRS(), name='world') # Transforms between frames distortion = wfi_distortion(output_model, reference_files) tel2sky = pointing.v23tosky(output_model) pipeline = [ Step(detector, distortion), Step(v2v3, tel2sky), Step(world, None) ] wcs = WCS(pipeline) if wcs.bounding_box is None: wcs.bounding_box = wcs_bbox_from_shape(output_model.data.shape) output_model.meta['wcs'] = wcs output_model.meta.cal_step['assign_wcs'] = 'COMPLETE' return output_model
def _generate_wcs_transform(dispaxis): """Create mock gwcs.WCS object for resampled s2d data""" detector = cf.Frame2D(name='detector', axes_order=(0, 1), unit=(u.pix, u.pix)) icrs = cf.CelestialFrame(name='icrs', reference_frame=coord.ICRS(), axes_order=(0, 1), unit=(u.deg, u.deg), axes_names=('RA', 'DEC')) spec = cf.SpectralFrame(name='spec', axes_order=(2, ), unit=(u.micron, ), axes_names=('lambda', )) world = cf.CompositeFrame(name="world", frames=[icrs, spec]) if dispaxis == 1: mapping = models.Mapping((0, 1, 0)) if dispaxis == 2: mapping = models.Mapping((0, 1, 1)) transform = mapping | (models.Const1D(42) & models.Const1D(42) & (models.Shift(30) | models.Scale(0.1))) pipeline = [(detector, transform), (world, None)] wcs = WCS(pipeline) return wcs
def load_wcs(input_model, reference_files={}): """ Create the WCS object from the input model and reference files and store the pickled WCS-related object into the model meta data. """ if reference_files: for ref_type, ref_file in reference_files.items(): if ref_file not in ["N/A", ""]: reference_files[ref_type] = ref_file else: reference_files[ref_type] = None if not any(reference_files.values()): log.critical( "assign_wcs needs reference files to compute the WCS, none were passed" ) raise ValueError( "assign_wcs needs reference files to compute the WCS, none were passed" ) instrument = input_model.meta.instrument.name.lower() mod = importlib.import_module('.' + instrument, 'jwst.assign_wcs') pipeline = mod.create_pipeline(input_model, reference_files) # Initialize the output model as a copy of the input # Make the copy after the WCS pipeline is created in order to pass updates to the model. if pipeline is None: input_model.meta.cal_step.assign_wcs = 'SKIPPED' log.warning("SKIPPED assign_wcs") return input_model else: output_model = input_model.copy() wcs = WCS(pipeline) output_model.meta.wcs = wcs output_model.meta.cal_step.assign_wcs = 'COMPLETE' log.info("COMPLETED assign_wcs") return output_model
def generate_s3d_wcs(): """ create a fake gwcs for a cube """ # create input /output frames detector = cf.CoordinateFrame(name='detector', axes_order=(0,1,2), axes_names=['x', 'y', 'z'], axes_type=['spatial', 'spatial', 'spatial'], naxes=3, unit=['pix', 'pix', 'pix']) sky = cf.CelestialFrame(reference_frame=coord.ICRS(), name='sky', axes_names=("RA", "DEC")) spec = cf.SpectralFrame(name='spectral', unit=['um'], axes_names=['wavelength'], axes_order=(2,)) world = cf.CompositeFrame(name="world", frames=[sky, spec]) # create fake transform to at least get a bounding box # for the s3d jwst loader # shape 30,10,10 (spec, y, x) crpix1, crpix2, crpix3 = 5, 5, 15 # (x, y, spec) crval1, crval2, crval3 = 1, 1, 1 cdelt1, cdelt2, cdelt3 = 0.01, 0.01, 0.05 shift = models.Shift(-crpix2) & models.Shift(-crpix1) scale = models.Multiply(cdelt2) & models.Multiply(cdelt1) proj = models.Pix2Sky_TAN() skyrot = models.RotateNative2Celestial(crval2, 90 + crval1, 180) celestial = shift | scale | proj | skyrot wave_model = models.Shift(-crpix3) | models.Multiply(cdelt3) | models.Shift(crval3) transform = models.Mapping((2, 0, 1)) | celestial & wave_model | models.Mapping((1, 2, 0)) # bounding box based on shape (30,10,10) in test transform.bounding_box = ((0, 29), (0, 9), (0, 9)) # create final wcs pipeline = [(detector, transform), (world, None)] return WCS(pipeline)
def load_wcs(input_model, reference_files={}): """ Create the WCS object from the input model and reference files and store the pickled WCS-related object into the model meta data. """ if reference_files: for ref_type, ref_file in reference_files.items(): if ref_file not in ["N/A", ""]: reference_files[ref_type] = ref_file else: reference_files[ref_type] = None if not any(reference_files.values()): log.critical( "assign_wcs needs reference files to compute the WCS, none were passed" ) raise ValueError( "assign_wcs needs reference files to compute the WCS, none were passed" ) instrument = input_model.meta.instrument.name.lower() mod = importlib.import_module('.' + instrument, 'jwst.assign_wcs') # Add WCS keywords for the spectral axis. if input_model.meta.wcsinfo.wcsaxes == 3: _add_3rd_axis(input_model) pipeline = mod.create_pipeline(input_model, reference_files) # Initialize the output model as a copy of the input # Make the copy after the WCS pipeline is created in order to pass updates to the model. if pipeline is None: input_model.meta.cal_step.assign_wcs = 'SKIPPED' log.warning("assign_wcs: SKIPPED") return input_model else: output_model = input_model.copy() wcs = WCS(pipeline) output_model.meta.wcs = wcs output_model.meta.cal_step.assign_wcs = 'COMPLETE' exclude_types = [ 'NRS_FIXEDSLIT', 'NRS_BRIGHTOBJ', 'NRS_IFU', 'NRS_MSASPEC', 'NRS_LAMP', 'MIR_MRS', 'NIS_SOSS', 'NRC_GRISM', 'NRC_TSGRISM', 'NIS_WFSS' ] if output_model.meta.exposure.type not in exclude_types: orig_s_region = output_model.meta.wcsinfo.s_region.strip() update_s_region(output_model) if orig_s_region != output_model.meta.wcsinfo.s_region.strip(): log.info("assign_wcs updated S_REGION to {0}".format( output_model.meta.wcsinfo.s_region)) else: log.info("assign_wcs did not update S_REGION for type {0}".format( output_model.meta.exposure.type)) log.info("COMPLETED assign_wcs") return output_model
def load_wcs(input_model, reference_files={}): """ Create a gWCS object and store it in ``Model.meta``. Parameters ---------- input_model : `~jwst.datamodels.DataModel` The exposure. reference_files : dict A dict {reftype: reference_file_name} containing all reference files that apply to this exposure. """ if "wcsinfo" not in input_model.meta: input_model.meta.cal_step.assign_wcs = "SKIPPED" log.warning("assign_wcs: SKIPPED") return input_model else: output_model = input_model.copy() shift_by_crpix = models.Shift( -(input_model.meta.wcsinfo.crpix1 - 1) * u.pix ) & models.Shift(-(input_model.meta.wcsinfo.crpix2 - 1) * u.pix) pix2sky = getattr( models, "Pix2Sky_{}".format(input_model.meta.wcsinfo.ctype1[-3:]) )() celestial_rotation = models.RotateNative2Celestial( input_model.meta.wcsinfo.crval1 * u.deg, input_model.meta.wcsinfo.crval2 * u.deg, 180 * u.deg, ) pix2sky.input_units_equivalencies = { "x": u.pixel_scale(input_model.meta.wcsinfo.cdelt1 * u.deg / u.pix), "y": u.pixel_scale(input_model.meta.wcsinfo.cdelt2 * u.deg / u.pix), } det2sky = shift_by_crpix | pix2sky | celestial_rotation det2sky.name = "linear_transform" detector_frame = cf.Frame2D( name="detector", axes_names=("x", "y"), unit=(u.pix, u.pix) ) sky_frame = cf.CelestialFrame( reference_frame=getattr( coord, input_model.meta.coordinates.reference_frame )(), name="sky_frame", unit=(u.deg, u.deg), ) pipeline = [(detector_frame, det2sky), (sky_frame, None)] wcs = WCS(pipeline) output_model.meta.wcs = wcs output_model.meta.cal_step.assign_wcs = "COMPLETE" return output_model
def create_spectral_wcs(ra, dec, wavelength): """Assign a WCS for sky coordinates and a table of wavelengths Parameters ---------- ra: float The right ascension (in degrees) at the nominal location of the entrance aperture (slit). dec: float The declination (in degrees) at the nominal location of the entrance aperture. wavelength: ndarray The wavelength in microns at each pixel of the extracted spectrum. Returns: -------- wcs: a gwcs.wcs.WCS object This takes a float or sequence of float and returns a tuple of the right ascension, declination, and wavelength (or sequence of wavelengths) at the pixel(s) specified by the input argument. """ # Only the first coordinate is used. input_frame = cf.Frame2D(axes_order=(0, 1), unit=(u.pix, u.pix), name="pixel_frame") sky = cf.CelestialFrame(name='sky', axes_order=(0, 1), reference_frame=coord.ICRS()) spec = cf.SpectralFrame(name='spectral', axes_order=(2, ), unit=(u.micron, ), axes_names=('wavelength', )) pixel = np.arange(len(wavelength), dtype=np.float) tab = Mapping((0, 0, 0)) | \ Const1D(ra) & Const1D(dec) & Tabular1D(pixel, wavelength) world = cf.CompositeFrame([sky, spec], name='world') pipeline = [(input_frame, tab), (world, None)] return WCS(pipeline)
def load_wcs(input_model, reference_files={}, nrs_slit_y_range=None): """ Create a gWCS object and store it in ``Model.meta``. Parameters ---------- input_model : `~jwst.datamodels.DataModel` The exposure. reference_files : dict A dict {reftype: reference_file_name} containing all reference files that apply to this exposure. nrs_slit_y_range : list The slit y-range for a Nirspec slit. The center is (0, 0). """ if reference_files: for ref_type, ref_file in reference_files.items(): if ref_file not in ["N/A", ""]: reference_files[ref_type] = ref_file else: reference_files[ref_type] = None if not any(reference_files.values()): log.critical( "assign_wcs needs reference files to compute the WCS, none were passed" ) raise ValueError( "assign_wcs needs reference files to compute the WCS, none were passed" ) instrument = input_model.meta.instrument.name.lower() mod = importlib.import_module('.' + instrument, 'jwst.assign_wcs') if input_model.meta.exposure.type.lower() in SPEC_TYPES: input_model.meta.wcsinfo.specsys = "BARYCENT" input_model.meta.wcsinfo.dispersion_direction = \ get_dispersion_direction( input_model.meta.exposure.type, input_model.meta.instrument.grating, input_model.meta.instrument.filter, input_model.meta.instrument.pupil) if instrument.lower() == 'nirspec': pipeline = mod.create_pipeline(input_model, reference_files, slit_y_range=nrs_slit_y_range) else: pipeline = mod.create_pipeline(input_model, reference_files) # Initialize the output model as a copy of the input # Make the copy after the WCS pipeline is created in order to pass updates to the model. if pipeline is None: input_model.meta.cal_step.assign_wcs = 'SKIPPED' log.warning("assign_wcs: SKIPPED") return input_model else: output_model = input_model.copy() wcs = WCS(pipeline) output_model.meta.wcs = wcs output_model.meta.cal_step.assign_wcs = 'COMPLETE' exclude_types = [ 'nrc_wfss', 'nrc_tsgrism', 'nis_wfss', 'nrs_fixedslit', 'nrs_msaspec', 'nrs_autowave', 'nrs_autoflat', 'nrs_lamp', 'nrs_brightobj', 'nis_soss' ] if output_model.meta.exposure.type.lower() not in exclude_types: imaging_types = IMAGING_TYPES.copy() imaging_types.update(['mir_lrs-fixedslit', 'mir_lrs-slitless']) if output_model.meta.exposure.type.lower() in imaging_types: try: update_s_region_imaging(output_model) except Exception as exc: log.error( "Unable to update S_REGION for type {}: {}".format( output_model.meta.exposure.type, exc)) else: log.info("assign_wcs updated S_REGION to {0}".format( output_model.meta.wcsinfo.s_region)) elif output_model.meta.exposure.type.lower() == "nrs_ifu": update_s_region_nrs_ifu(output_model, mod) elif output_model.meta.exposure.type.lower() == 'mir_mrs': update_s_region_mrs(output_model) else: try: update_s_region_spectral(output_model) except Exception as exc: log.info( "Unable to update S_REGION for type {}: {}".format( output_model.meta.exposure.type, exc)) log.info("COMPLETED assign_wcs") return output_model
def flag(input_datamodel, failed_slitlets, wcs_refnames): """ Takes the list of failed open shutters from the failedopen reference file and calculates the pixels affected using the WCS model. The affected pixels in the science data have their DQ flags combined with that for the MSA_FAILED_OPEN standard flag. All other science data arrays are unchanged. Parameters ---------- input_datamodel: data model object the input science data failed_slitlets: list List of failed open slitlets wcs_refnames: dict dictionary of reference file names used to calculate the WCS Returns ------- input_datamodel: data model object science data with DQ flags of affected modified """ # # Use the machinery in assign_wcs to create a WCS object for the bad shutters pipeline = slitlets_wcs(input_datamodel, wcs_refnames, failed_slitlets) wcs = WCS(pipeline) # Create output as a copy of the input science data model so we can overwrite # the wcs with the wcs for the failed open shutters temporary_copy = input_datamodel.copy() temporary_copy.meta.wcs = wcs dq_array = input_datamodel.dq for slitlet in failed_slitlets: # # Pick the WCS for this slitlet from the WCS of the exposure thiswcs = nrs_wcs_set_input(temporary_copy, slitlet.name) # # Convert the bounding box for this slitlet to a set of indices to use as a slice xmin, xmax, ymin, ymax = boundingbox_to_indices( temporary_copy, thiswcs.bounding_box) # # Make a grid of points within the slice y_indices, x_indices = np.mgrid[ymin:ymax, xmin:xmax] # # Calculate the arrays of coordinates for each pixel in the slice coordinate_array = thiswcs(x_indices, y_indices) # # The coordinate_array is a tuple of arrays, one for each output coordinate # In this case there should be 3 arrays, one each for RA, Dec and Wavelength # For pixels outside the slitlet, the arrays have NaN # # Make a subarray from these coordinate arrays by setting pixels that aren't # NaN to FAILDOPENFLAG, the rest to 0 dq_subarray = wcs_to_dq(coordinate_array, FAILEDOPENFLAG) # # bitwise-or this subarray with the slice in the original exposure's DQ array dq_array = or_subarray_with_array(dq_array, dq_subarray, xmin, xmax, ymin, ymax) # # Set the dq array of the input datamodel to the corrected dq array input_datamodel.dq = dq_array return input_datamodel
def load_wcs(input_model, reference_files={}): """ Create a gWCS object and store it in ``Model.meta``. Parameters ---------- input_model : `~jwst.datamodels.DataModel` The exposure. reference_files : dict A dict {reftype: reference_file_name} containing all reference files that apply to this exposure. """ if reference_files: for ref_type, ref_file in reference_files.items(): if ref_file not in ["N/A", ""]: reference_files[ref_type] = ref_file else: reference_files[ref_type] = None if not any(reference_files.values()): log.critical( "assign_wcs needs reference files to compute the WCS, none were passed" ) raise ValueError( "assign_wcs needs reference files to compute the WCS, none were passed" ) instrument = input_model.meta.instrument.name.lower() mod = importlib.import_module('.' + instrument, 'jwst.assign_wcs') # Add WCS keywords for the spectral axis. if input_model.meta.wcsinfo.wcsaxes == 3: _add_3rd_axis(input_model) if input_model.meta.exposure.type.lower() in SPEC2_SCIENCE_EXP_TYPES: input_model.meta.wcsinfo.specsys = "BARYCENT" pipeline = mod.create_pipeline(input_model, reference_files) # Initialize the output model as a copy of the input # Make the copy after the WCS pipeline is created in order to pass updates to the model. if pipeline is None: input_model.meta.cal_step.assign_wcs = 'SKIPPED' log.warning("assign_wcs: SKIPPED") return input_model else: output_model = input_model.copy() wcs = WCS(pipeline) output_model.meta.wcs = wcs output_model.meta.cal_step.assign_wcs = 'COMPLETE' exclude_types = [ 'nrc_wfss', 'nrc_tsgrism', 'nis_wfss', 'nrs_fixedslit', 'nrs_ifu', 'nrs_msaspec', 'nrs_autowave', 'nrs_autoflat', 'nrs_lamp', 'nrs_brightobj', 'mir_lrs-fixedslit', 'mir_lrs-slitless', 'mir_mrs', 'nis_soss' ] if output_model.meta.exposure.type.lower() not in exclude_types: if output_model.meta.exposure.type.lower() in IMAGING_TYPES: try: update_s_region_imaging(output_model) except Exception as exc: log.error( "Unable to update S_REGION for type {}: {}".format( output_model.meta.exposure.type, exc)) else: log.info("assign_wcs updated S_REGION to {0}".format( output_model.meta.wcsinfo.s_region)) else: try: update_s_region_spectral(output_model) except Exception as exc: log.info( "Unable to update S_REGION for type {}: {}".format( output_model.meta.exposure.type, exc)) log.info("COMPLETED assign_wcs") return output_model
def create_spectral_wcs(ra, dec, wavelength): """Assign a WCS for sky coordinates and a table of wavelengths Parameters ---------- ra: float The right ascension (in degrees) at the nominal location of the entrance aperture (slit). dec: float The declination (in degrees) at the nominal location of the entrance aperture. wavelength: ndarray The wavelength in microns at each pixel of the extracted spectrum. Returns: -------- wcs: a gwcs.wcs.WCS object This takes a float or sequence of float and returns a tuple of the right ascension, declination, and wavelength (or sequence of wavelengths) at the pixel(s) specified by the input argument. """ input_frame = cf.CoordinateFrame(naxes=1, axes_type=("SPATIAL", ), axes_order=(0, ), unit=(u.pix, ), name="pixel_frame") sky = cf.CelestialFrame(name='sky', axes_order=(0, 1), reference_frame=coord.ICRS()) spec = cf.SpectralFrame(name='spectral', axes_order=(2, ), unit=(u.micron, ), axes_names=('wavelength', )) world = cf.CompositeFrame([sky, spec], name='world') pixel = np.arange(len(wavelength), dtype=np.float) tab = Mapping((0, 0, 0)) | \ Const1D(ra) & Const1D(dec) & Tabular1D(points=pixel, lookup_table=wavelength, bounds_error=False, fill_value=None) tab.name = "pixel_to_world" if all(np.diff(wavelength) > 0): tab.inverse = Mapping((2, )) | Tabular1D( points=wavelength, lookup_table=pixel, bounds_error=False, ) elif all(np.diff(wavelength) < 0): tab.inverse = Mapping((2, )) | Tabular1D( points=wavelength[::-1], lookup_table=pixel[::-1], bounds_error=False, ) else: log.warning( "Wavelengths are not strictly monotonic, inverse transform is not set" ) pipeline = [(input_frame, tab), (world, None)] return WCS(pipeline)