Skip to content

Instantly share code, notes, and snippets.

@jdavies-st
Last active June 30, 2020 14:52
Show Gist options
  • Save jdavies-st/d1d5c74b879a0a718c94b97b248d665e to your computer and use it in GitHub Desktop.
Save jdavies-st/d1d5c74b879a0a718c94b97b248d665e to your computer and use it in GitHub Desktop.
Representing forked WCS trees in ASDF using GWCS
# This is to show how one might represent two linear WCS pipelines that share a step in ASDF using GWCS
# The transform comes from JWST NIRCam imaging.
from jwst import datamodels
import asdf
from copy import deepcopy
# Use some existing NIRCam Imaging data which has a GWCS object in it
model = datamodels.open("/Users/jdavies/Downloads/jw42424001001_01101_00001_nrca5_cal.fits")
# Pull out the GWCS object and make a deep copy of it
wcs = model.meta.wcs
wcs.name = "Primary WCS"
wcs2 = deepcopy(wcs)
wcs2.name = "Secondary WCS"
# Make the first step in the pipeline not just a copy, but the *same* object, i.e.
# one points the other
wcs2.pipeline[0] = wcs.pipeline[0]
# Store the WCSs as a list and serialize
tree = dict(wcs=[wcs, wcs2])
with asdf.AsdfFile(tree=tree) as af:
af.write_to("test.asdf", auto_inline=65000)
# The resulting serialized ASDF is below.
#
# Notice the Primary WCS transform:
#
# transform: &id002 !transform/compose-1.2.0
#
# has a reference "&id002" there. This allows it to be referenced by the Secondary
# WCS as:
#
# transform: *id002
#
# Voila!
# --------------------
# test.asdf
#ASDF 1.0.0
#ASDF_STANDARD 1.5.0
%YAML 1.1
%TAG ! tag:stsci.edu:asdf/
--- !core/asdf-1.1.0
asdf_library: !core/software-1.0.0 {author: Space Telescope Science Institute, homepage: 'http://github.com/spacetelescope/asdf',
name: asdf, version: 2.6.0}
history:
extensions:
- !core/extension_metadata-1.0.0
extension_class: asdf.extension.BuiltinExtension
software: !core/software-1.0.0 {name: asdf, version: 2.6.0}
- !core/extension_metadata-1.0.0
extension_class: jwst.transforms.jwextension.JWSTExtension
software: !core/software-1.0.0 {name: jwst, version: 0.16.3.dev28+gc6204a4b.d20200611}
- !core/extension_metadata-1.0.0
extension_class: astropy.io.misc.asdf.extension.AstropyAsdfExtension
software: !core/software-1.0.0 {name: astropy, version: 4.1rc1}
- !core/extension_metadata-1.0.0
extension_class: astropy.io.misc.asdf.extension.AstropyExtension
software: !core/software-1.0.0 {name: astropy, version: 4.1rc1}
- !core/extension_metadata-1.0.0
extension_class: gwcs.extension.GWCSExtension
software: !core/software-1.0.0 {name: gwcs, version: 0.13.0}
wcs:
- !<tag:stsci.edu:gwcs/wcs-1.0.0>
name: Primary WCS
steps:
- !<tag:stsci.edu:gwcs/step-1.0.0>
frame: !<tag:stsci.edu:gwcs/frame2d-1.0.0>
axes_names: [x, y]
axes_order: [0, 1]
axis_physical_types: ['custom:x', 'custom:y']
name: detector
unit: [!unit/unit-1.0.0 pixel, !unit/unit-1.0.0 pixel]
transform: &id002 !transform/compose-1.2.0
bounding_box:
- [-0.5, 2047.5]
- [-0.5, 2047.5]
forward:
- !transform/compose-1.2.0
forward:
- !transform/compose-1.2.0
forward:
- !transform/concatenate-1.2.0
forward:
- !transform/shift-1.2.0 {offset: 1.0}
- !transform/shift-1.2.0 {offset: 1.0}
- !transform/concatenate-1.2.0
forward:
- !transform/shift-1.2.0 {offset: -1024.5}
- !transform/shift-1.2.0 {offset: -1024.5}
- !transform/compose-1.2.0
forward:
- !transform/compose-1.2.0
forward:
- !transform/remap_axes-1.2.0
mapping: [0, 1, 0, 1]
- !transform/concatenate-1.2.0
forward:
- !transform/polynomial-1.2.0
coefficients: !core/ndarray-1.0.0
data:
- [-0.0, 0.0, -9.721046535057192e-08, -2.164006028817789e-13, -3.590620404845533e-16,
4.354424173002358e-20]
- [0.06277674557948036, -7.244807505775117e-07, 9.66518115581259e-11,
-3.191824242088728e-15, 4.71684808024088e-18, 0.0]
- [1.198364733530203e-07, -5.782468597491751e-12, 2.117937146007029e-16,
5.143162171129567e-19, 0.0, 0.0]
- [9.094661041997164e-11, -2.949576253844291e-15, 9.531355664635004e-18,
0.0, 0.0, 0.0]
- [6.449038115869934e-16, 4.879315376187496e-19, 0.0, 0.0, 0.0,
0.0]
- [4.706941538958384e-18, 0.0, 0.0, 0.0, 0.0, 0.0]
datatype: float64
shape: [6, 6]
domain:
- &id001 [-1, 1]
- *id001
window:
- *id001
- *id001
- !transform/polynomial-1.2.0
coefficients: !core/ndarray-1.0.0
data:
- [0.0, 0.0630762699429303, -4.239854922865822e-07, 9.762139471915262e-11,
-2.015274358881797e-15, 4.410393661077231e-18]
- [-9.102681200381172e-05, 2.287097298253153e-07, -6.481047139577153e-12,
1.0853593918469e-15, 4.941571953195922e-19, 0.0]
- [3.086258377388918e-07, 8.751405385759113e-11, -5.078890561912942e-16,
9.736970732740994e-18, 0.0, 0.0]
- [-6.696189796258203e-13, 1.146884680565914e-15, 5.986044579428994e-19,
0.0, 0.0, 0.0]
- [1.454596109813538e-15, 5.27551747031014e-18, 0.0, 0.0, 0.0, 0.0]
- [9.296183515265389e-20, 0.0, 0.0, 0.0, 0.0, 0.0]
datatype: float64
shape: [6, 6]
domain:
- *id001
- *id001
window:
- *id001
- *id001
- !transform/compose-1.2.0
forward:
- !transform/remap_axes-1.2.0
mapping: [0, 1, 0, 1]
- !transform/concatenate-1.2.0
forward:
- !transform/polynomial-1.2.0
coefficients: !core/ndarray-1.0.0
data:
- [0.0, -0.0012889474613725963]
- [-0.9999991693068759, 0.0]
datatype: float64
shape: [2, 2]
domain:
- *id001
- *id001
window:
- *id001
- *id001
- !transform/polynomial-1.2.0
coefficients: !core/ndarray-1.0.0
data:
- [0.0, 0.9999991693068759]
- [-0.0012889474613725963, 0.0]
datatype: float64
shape: [2, 2]
domain:
- *id001
- *id001
window:
- *id001
- *id001
- !transform/concatenate-1.2.0
forward:
- !transform/shift-1.2.0 {offset: 86.039011}
- !transform/shift-1.2.0 {offset: -493.385704}
inverse: !transform/compose-1.2.0
forward:
- !transform/concatenate-1.2.0
forward:
- !transform/shift-1.2.0 {offset: -86.039011}
- !transform/shift-1.2.0 {offset: 493.385704}
- !transform/compose-1.2.0
forward:
- !transform/compose-1.2.0
forward:
- !transform/compose-1.2.0
forward:
- !transform/remap_axes-1.2.0
mapping: [0, 1, 0, 1]
- !transform/concatenate-1.2.0
forward:
- !transform/polynomial-1.2.0
coefficients: !core/ndarray-1.0.0
data:
- [0.0, -0.0012889474613725963]
- [-0.9999991693068759, 0.0]
datatype: float64
shape: [2, 2]
domain:
- *id001
- *id001
window:
- *id001
- *id001
- !transform/polynomial-1.2.0
coefficients: !core/ndarray-1.0.0
data:
- [0.0, 0.9999991693068759]
- [-0.0012889474613725963, 0.0]
datatype: float64
shape: [2, 2]
domain:
- *id001
- *id001
window:
- *id001
- *id001
- !transform/compose-1.2.0
forward:
- !transform/remap_axes-1.2.0
mapping: [0, 1, 0, 1]
- !transform/concatenate-1.2.0
forward:
- !transform/polynomial-1.2.0
coefficients: !core/ndarray-1.0.0
data:
- [0.001606802685174102, 1.072121003490439e-05, 0.0003899472961152239,
1.741491572219416e-07, -1.730326086686541e-10, -1.214407164376713e-12]
- [15.92985674331845, 0.002932499409606826, -5.492406520770091e-06,
-3.48506269432795e-09, -6.053447585998923e-11, 0.0]
- [-0.0004827156577026869, -1.704997124234288e-07, 4.500242110641451e-10,
-7.573478292656556e-12, 0.0, 0.0]
- [-6.181790050341375e-06, -3.7994370832503e-09, -1.214837102200545e-10,
0.0, 0.0, 0.0]
- [6.600092079203932e-10, -6.325812350975392e-12, 0.0, 0.0, 0.0,
0.0]
- [-5.99901579643954e-11, 0.0, 0.0, 0.0, 0.0, 0.0]
datatype: float64
shape: [6, 6]
domain:
- *id001
- *id001
window:
- *id001
- *id001
- !transform/polynomial-1.2.0
coefficients: !core/ndarray-1.0.0
data:
- [-0.006780939009559006, 15.85435606632966, 0.001699308339193117,
-5.931127954103713e-06, -2.505780246788893e-09, -5.582941651153512e-11]
- [0.02314264781384863, -0.0009119151347307442, -1.968853925968155e-07,
9.314930747598225e-10, -6.10620822524126e-12, 0.0]
- [-0.001244711452021884, -6.450451269943015e-06, -2.485642883412269e-09,
-1.192566344000974e-10, 0.0, 0.0]
- [1.499394209694464e-07, 1.029780982881483e-09, -7.045014588881225e-12,
0.0, 0.0, 0.0]
- [3.124699039332876e-10, -6.284891892869384e-11, 0.0, 0.0, 0.0,
0.0]
- [-9.811118954903338e-13, 0.0, 0.0, 0.0, 0.0, 0.0]
datatype: float64
shape: [6, 6]
domain:
- *id001
- *id001
window:
- *id001
- *id001
- !transform/compose-1.2.0
forward:
- !transform/concatenate-1.2.0
forward:
- !transform/shift-1.2.0 {offset: 1024.5}
- !transform/shift-1.2.0 {offset: 1024.5}
- !transform/concatenate-1.2.0
forward:
- !transform/shift-1.2.0 {offset: -1.0}
- !transform/shift-1.2.0 {offset: -1.0}
- !<tag:stsci.edu:gwcs/step-1.0.0>
frame: !<tag:stsci.edu:gwcs/frame2d-1.0.0>
axes_names: [x, y]
axes_order: [0, 1]
axis_physical_types: ['custom:x', 'custom:y']
name: v2v3
unit: [!unit/unit-1.0.0 arcsec, !unit/unit-1.0.0 arcsec]
transform: !transform/compose-1.2.0
forward:
- !transform/concatenate-1.2.0
forward:
- !transform/scale-1.2.0 {factor: 0.0002777777777777778}
- !transform/scale-1.2.0 {factor: 0.0002777777777777778}
- !<tag:stsci.edu:jwst_pipeline/v23tosky-0.7.0>
angles: [-0.02389972527777778, -0.13705158444444443, -0.005076934167039675,
-11.99875540218638, 22.02351763251896]
axes_order: zyxyz
name: v23tosky
- !<tag:stsci.edu:gwcs/step-1.0.0>
frame: !<tag:stsci.edu:gwcs/celestial_frame-1.0.0>
axes_names: [lon, lat]
axes_order: [0, 1]
axis_physical_types: [pos.eq.ra, pos.eq.dec]
name: world
reference_frame: !<tag:astropy.org:astropy/coordinates/frames/icrs-1.1.0>
frame_attributes: {}
unit: [!unit/unit-1.0.0 deg, !unit/unit-1.0.0 deg]
- !<tag:stsci.edu:gwcs/wcs-1.0.0>
name: Secondary WCS
steps:
- !<tag:stsci.edu:gwcs/step-1.0.0>
frame: !<tag:stsci.edu:gwcs/frame2d-1.0.0>
axes_names: [x, y]
axes_order: [0, 1]
axis_physical_types: ['custom:x', 'custom:y']
name: detector
unit: [!unit/unit-1.0.0 pixel, !unit/unit-1.0.0 pixel]
transform: *id002
- !<tag:stsci.edu:gwcs/step-1.0.0>
frame: !<tag:stsci.edu:gwcs/frame2d-1.0.0>
axes_names: [x, y]
axes_order: [0, 1]
axis_physical_types: ['custom:x', 'custom:y']
name: v2v3
unit: [!unit/unit-1.0.0 arcsec, !unit/unit-1.0.0 arcsec]
transform: !transform/compose-1.2.0
forward:
- !transform/concatenate-1.2.0
forward:
- !transform/scale-1.2.0 {factor: 0.0002777777777777778}
- !transform/scale-1.2.0 {factor: 0.0002777777777777778}
- !<tag:stsci.edu:jwst_pipeline/v23tosky-0.7.0>
angles: [-0.02389972527777778, -0.13705158444444443, -0.005076934167039675,
-11.99875540218638, 22.02351763251896]
axes_order: zyxyz
name: v23tosky
- !<tag:stsci.edu:gwcs/step-1.0.0>
frame: !<tag:stsci.edu:gwcs/celestial_frame-1.0.0>
axes_names: [lon, lat]
axes_order: [0, 1]
axis_physical_types: [pos.eq.ra, pos.eq.dec]
name: world
reference_frame: !<tag:astropy.org:astropy/coordinates/frames/icrs-1.1.0>
frame_attributes: {}
unit: [!unit/unit-1.0.0 deg, !unit/unit-1.0.0 deg]
...
@jdavies-st
Copy link
Author

One thing I'm not clear on is why the internal reference points to the transform and not the step itself.

@eslavich
Copy link

One thing I'm not clear on is why the internal reference points to the transform and not the step itself.

The WCSType class creates new objects for each step when serializing the tree:

https://github.com/spacetelescope/gwcs/blob/0.13.0/gwcs/tags/wcs.py#L48

So the tagged steps end up with different ids, and pyyaml can't use anchors/aliases with the steps because it doesn't know that they're identical.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment