def fitswcs_nonlinear(header): """ Create a WCS linear transform from a FITS header. Parameters ---------- header : astropy.io.fits.Header or dict FITS Header or dict with basic FITS WCS keywords. """ if isinstance(header, fits.Header): wcs_info = read_wcs_from_header(header) elif isinstance(header, dict): wcs_info = header else: raise TypeError("Expected a FITS Header or a dict.") transforms = [] projcode = get_projcode(wcs_info) if projcode is not None: projection = create_projection_transform(projcode).rename(projcode) transforms.append(projection) # Create the sky rotation transform sky_axes, _, _ = get_axes(wcs_info) if sky_axes: phip, lonp = [wcs_info['CRVAL'][i] for i in sky_axes] # TODO: write "def compute_lonpole(projcode, l)" # Set a defaul tvalue for now thetap = 180 n2c = astmodels.RotateNative2Celestial(phip, lonp, thetap, name="crval") transforms.append(n2c) if transforms: return functools.reduce(core._model_oper('|'), transforms) else: return None
def fitswcs_nonlinear(header): """ Create a WCS linear transform from a FITS header. Parameters ---------- header : astropy.io.fits.Header or dict FITS Header or dict with basic FITS WCS keywords. """ if isinstance(header, fits.Header): wcs_info = read_wcs_from_header(header) elif isinstance(header, dict): wcs_info = header else: raise TypeError("Expected a FITS Header or a dict.") transforms = [] projcode = get_projcode(wcs_info) if projcode is not None: projection = create_projection_transform(projcode).rename(projcode) transforms.append(projection) # Create the sky rotation transform sky_axes, _, _ = get_axes(wcs_info) if sky_axes: phip, lonp = [wcs_info['CRVAL'][i] for i in sky_axes] # TODO: write "def compute_lonpole(projcode, l)" # Set a defaul tvalue for now thetap = 180 n2c = astmodels.RotateNative2Celestial(phip, lonp, thetap, name="crval") transforms.append(n2c) if transforms: return functools.reduce(core._model_oper('|'), transforms) return None
def make_fitswcs_transform(header): """ Create a basic FITS WCS transform. It does not include distortions. Parameters ---------- header : astropy.io.fits.Header or dict FITS Header (or dict) with basic WCS information """ if isinstance(header, fits.Header): wcs_info = read_wcs_from_header(header) elif isinstance(header, dict): wcs_info = header else: raise TypeError("Expected a FITS Header or a dict.") wcs_linear = fitswcs_linear(wcs_info) projcode = get_projcode(wcs_info['CTYPE']) projection = create_projection_transform(projcode) projection = projection.rename(projcode) # Create the sky rotation transform phip, lonp = wcs_info['CRVAL'] # TODO: write "def compute_lonpole(projcode, l)" # Set a defaul tvalue for now thetap = 180 n2c = astmodels.RotateNative2Celestial(phip, lonp, thetap, name="crval") return functools.reduce(core._model_oper('|'), [wcs_linear, projection, n2c])
def make_fitswcs_transform(header): """ Create a basic FITS WCS transform. It does not include distortions. Parameters ---------- header : `astropy.io.fits.Header` or dict FITS Header (or dict) with basic WCS information """ if isinstance(header, fits.Header): wcs_info = read_wcs_from_header(header) elif isinstance(header, dict): wcs_info = header else: raise TypeError("Expected a FITS Header or a dict.") # If a pixel axis maps directly to an output axis, we want to have that # model completely self-contained, so don't put all the CRPIXj shifts # in a single CompoundModel at the beginning transforms = [] # The tricky stuff! sky_model = fitswcs_image(wcs_info) linear_models = fitswcs_linear(wcs_info) all_models = linear_models if sky_model: all_models.append(sky_model) # Now arrange the models so the inputs and outputs are in the right places all_models.sort(key=lambda m: m.meta['output_axes'][0]) input_axes = [ax for m in all_models for ax in m.meta['input_axes']] output_axes = [ax for m in all_models for ax in m.meta['output_axes']] if input_axes != list(range(len(input_axes))): input_mapping = models.Mapping(input_axes) transforms.append(input_mapping) transforms.append(functools.reduce(core._model_oper('&'), all_models)) if output_axes != list(range(len(output_axes))): output_mapping = models.Mapping(output_axes) transforms.append(output_mapping) return functools.reduce(core._model_oper('|'), transforms)
def make_fitswcs_transform(header): """ Create a basic FITS WCS transform. It does not include distortions. Parameters ---------- header : astropy.io.fits.Header or dict FITS Header (or dict) with basic WCS information """ if isinstance(header, fits.Header): wcs_info = read_wcs_from_header(header) elif isinstance(header, dict): wcs_info = header else: raise TypeError("Expected a FITS Header or a dict.") wcs_linear = fitswcs_linear(wcs_info) wcs_nonlinear = fitswcs_nonlinear(wcs_info) return functools.reduce(core._model_oper('|'), [wcs_linear, wcs_nonlinear])
def make_fitswcs_transform(header): """ Create a basic FITS WCS transform. It does not include distortions. Parameters ---------- header : astropy.io.fits.Header or dict FITS Header (or dict) with basic WCS information """ if isinstance(header, fits.Header): wcs_info = read_wcs_from_header(header) elif isinstance(header, dict): wcs_info = header else: raise TypeError("Expected a FITS Header or a dict.") transforms = [] wcs_linear = fitswcs_linear(wcs_info) transforms.append(wcs_linear) wcs_nonlinear = fitswcs_nonlinear(wcs_info) if wcs_nonlinear is not None: transforms.append(wcs_nonlinear) return functools.reduce(core._model_oper('|'), transforms)
""" This is a temporary home for a bunch of code for removing stuff from CompoundModels I would imagine this will end up in gwcs or maybe even astropy at somepoint. """ from collections import defaultdict from astropy.modeling import separable from astropy.modeling.core import BINARY_OPERATORS, _model_oper OPERATORS = dict((oper, _model_oper(oper)) for oper in BINARY_OPERATORS) def tree_is_separable(tree): """ Given a tree, convert it to a `CompoundModel` and then return the separability of the inputs. """ return separable.is_separable(tree.evaluate(OPERATORS)) def make_tree_input_map(tree): """ Construct a mapping of tree to input names. This function iterates over all the inputs of a model and determines which side of the tree (left or right) the input corresponds to. It returns a mapping of tree to set of all inputs for that side of the tree (which is also a tree).
def fitswcs_linear(header): """ Create a WCS linear transform from a FITS header. Parameters ---------- header : astropy.io.fits.Header or dict FITS Header or dict with basic FITS WCS keywords. """ if isinstance(header, fits.Header): wcs_info = read_wcs_from_header(header) elif isinstance(header, dict): wcs_info = header else: raise TypeError("Expected a FITS Header or a dict.") wcsaxes = wcs_info['WCSAXES'] pc = wcs_info['PC'] # get the part of the PC matrix corresponding to the imaging axes sky_axes = None if pc.shape != (2, 2): sky_axes, _ = get_axes(wcs_info) i, j = sky_axes sky_pc = np.zeros((2,2)) sky_pc[0, 0] = pc[i, i] sky_pc[0, 1] = pc[i, j] sky_pc[1, 0] = pc[j, i] sky_pc[1, 1] = pc[j, j] pc = sky_pc.copy() if sky_axes is not None: crpix = [] cdelt = [] for i in sky_axes: crpix.append(wcs_info['CRPIX'][i]) cdelt.append(wcs_info['CDELT'][i]) else: cdelt = wcs_info['CDELT'] crpix = wcs_info['CRPIX'] if wcsaxes == 2: rotation = astmodels.AffineTransformation2D(matrix=pc, name='pc_matrix') #elif wcsaxes == 3 : #rotation = AffineTransformation3D(matrix=matrix) #else: #raise DimensionsError("WCSLinearTransform supports only 2 or 3 dimensions, " #"{0} given".format(wcsaxes)) translation_models = [astmodels.Shift(-shift, name='crpix' + str(i + 1)) \ for i, shift in enumerate(crpix)] translation = functools.reduce(core._model_oper('&'), translation_models) if not wcs_info['has_cd']: # Do not compute scaling since CDELT* = 1 if CD is present. scaling_models = [astmodels.Scale(scale, name='cdelt' + str(i + 1)) \ for i, scale in enumerate(cdelt)] scaling = functools.reduce(core._model_oper('&'), scaling_models) wcs_linear = translation | rotation | scaling else: wcs_linear = translation | rotation return wcs_linear