{"id":8208,"library":"gwcs","title":"Generalized World Coordinate System (GWCS)","description":"GWCS (Generalized World Coordinate System) is an Astropy affiliated package designed for managing the World Coordinate System of astronomical data. It provides a flexible and general approach to defining and transforming coordinates between detector pixels and various world coordinate systems. Tightly integrated with Astropy, it leverages Astropy's modeling, units, and coordinates frameworks to build complex transformation pipelines. The library maintains an active development pace with frequent patch and minor releases.","status":"active","version":"1.0.3","language":"en","source_language":"en","source_url":"https://github.com/spacetelescope/gwcs","tags":["astronomy","astrophysics","wcs","coordinates","astropy"],"install":[{"cmd":"pip install gwcs","lang":"bash","label":"PyPI"},{"cmd":"conda install -c conda-forge gwcs","lang":"bash","label":"Conda"}],"dependencies":[{"reason":"Core functionality relies heavily on astropy.modeling for transforms, astropy.units for quantities, and astropy.coordinates for celestial frames.","package":"astropy","optional":false},{"reason":"Recommended for saving and loading GWCS objects.","package":"asdf","optional":true},{"reason":"Requires Python 3.11 or later.","package":"python","optional":false}],"imports":[{"symbol":"WCS","correct":"from gwcs import WCS"},{"symbol":"coordinate_frames","correct":"from gwcs import coordinate_frames as cf"},{"note":"Transforms are Astropy models, not directly from gwcs.","symbol":"models","correct":"from astropy.modeling import models"},{"symbol":"units","correct":"from astropy import units as u"},{"symbol":"coordinates","correct":"from astropy import coordinates as coord"}],"quickstart":{"code":"import numpy as np\nfrom astropy.modeling import models\nfrom astropy import units as u\nfrom astropy import coordinates as coord\nfrom gwcs import wcs\nfrom gwcs import coordinate_frames as cf\n\n# Define the transformations\npixel_scale = 0.05 * u.arcsec / u.pixel\ndetector_center_pixel = (500, 500)\nreference_sky_coord = coord.SkyCoord(ra=20 * u.deg, dec=30 * u.deg, frame='icrs')\n\n# 1. Shift pixel coordinates to have (0,0) at detector center\npixel_to_intermediate_frame = models.Shift(-detector_center_pixel[0] * u.pixel) & \\\n                              models.Shift(-detector_center_pixel[1] * u.pixel)\n\n# 2. Apply pixel scale\nintermediate_to_celestial_angles = models.Scale(pixel_scale) & models.Scale(pixel_scale)\n\n# 3. Tangent projection (TAN) from celestial angles to sky coordinates\ncelestial_angles_to_sky = models.Pix2Sky_TAN()\n\n# 4. Rotate and shift to final celestial position (simple case for illustration)\n# In a real scenario, this would be more complex, involving proper rotation models\n# and matching reference points. Here we directly set the reference_sky_coord.\n\n# Define the frames\ndetector_frame = cf.Frame2D(name=\"detector\", axes_names=('x', 'y'), unit=(u.pixel, u.pixel))\ncelestial_frame = cf.CelestialFrame(reference_frame=reference_sky_coord.frame,\n                                    name='icrs', unit=(u.deg, u.deg))\n\n# Build the GWCS pipeline\npipeline = [\n    wcs.Step(detector_frame, pixel_to_intermediate_frame | intermediate_to_celestial_angles | celestial_angles_to_sky),\n    wcs.Step(celestial_frame, None)\n]\n\n# Create the WCS object\nimage_wcs = wcs.WCS(pipeline)\n\n# Example transformation\npixel_coords = np.array([[100, 200], [500, 500]]) * u.pixel\nworld_coords = image_wcs.pixel_to_world(pixel_coords[:, 0], pixel_coords[:, 1])\n\nprint(f\"Input pixel coordinates:\\n{pixel_coords}\")\nprint(f\"Output world coordinates:\\n{world_coords}\")","lang":"python","description":"This example demonstrates how to construct a simple imaging GWCS object by chaining Astropy models and defining coordinate frames. It transforms input pixel coordinates to ICRS sky coordinates, illustrating the core pipeline concept of GWCS."},"warnings":[{"fix":"Upgrade your Python environment to 3.11 or newer: `conda install python=3.11` or `pyenv install 3.11`.","message":"As of GWCS 0.25.0, support for Python 3.10 has been dropped. Users must upgrade to Python 3.11 or later to use recent versions of `gwcs`.","severity":"breaking","affected_versions":">=0.25.0"},{"fix":"Avoid using `with_units=True`. Ensure transforms are defined to handle units directly. If encountering data loss with array inputs, upgrade `gwcs` to 0.25.0+ and review your transform definitions to ensure unit-aware operations.","message":"The `with_units` argument (e.g., in `LabelMapperArray`) was deprecated in version 0.26.0 and will be removed in future releases. It caused issues with array-like inputs losing entries.","severity":"deprecated","affected_versions":">=0.26.0"},{"fix":"Replace calls to `_toindex` with `to_index`.","message":"The private `_toindex` function was deprecated in 0.26.1 in favor of the public `to_index` function.","severity":"deprecated","affected_versions":">=0.26.1"},{"fix":"Be mindful of the coordinate order. It is recommended to set the bounding box directly on the GWCS object and heed the warning, or use `bind_bounding_box` with the `order` argument if setting on the transform directly.","message":"GWCS and Astropy have different default conventions for ordering multi-dimensional bounding boxes ('F' (x, y) for GWCS vs. 'C' (y, x) for Astropy). Setting `bounding_box` directly on a GWCS object will convert to GWCS's 'F' ordering and issue a `GwcsBoundingBoxWarning` if a conversion occurs.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Handle `NoConvergence` exceptions explicitly, or set `quiet=True` and `detect_divergence=True` with `adaptive=True` in `numerical_inverse()` to manage non-converging points. Inspect the `divergent` or `slow_conv` attributes of the exception for problematic indices.","message":"The `WCS.numerical_inverse()` method may raise `NoConvergence` exceptions if the iterative process fails to converge or diverges. This can lead to `NaN` or `Inf` values in results if not handled.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Upgrade to `gwcs` version 0.25.0 or later. Ensure array inputs have the expected shape (e.g., `(1, N)` for 1D data or `(N, M)` for 2D data) if `with_units` (though deprecated) is implicitly used or affects behavior.","cause":"In versions prior to 0.25.0, 'vector' shaped arrays (e.g., `(N,)` instead of `(1, N)`) would lose all but their first entry if `with_units=True` was used in `LabelMapperArray`.","error":"ValueError: operands could not be broadcast together with shapes (N,) (1,N)"},{"fix":"Upgrade to `gwcs` version 1.0.1 or later. Ensure that coordinate frames are properly defined and not `None` or `EmptyFrame` where a valid frame is expected.","cause":"Prior to version 1.0.1, GWCS evaluation could fail when input or output frames were `None` or `EmptyFrame` objects, leading to incorrect or uncallable transform steps.","error":"TypeError: 'NoneType' object is not callable"},{"fix":"Transforms should typically be inserted between existing frames or appended. If modifying the very beginning of the pipeline, reconstruct the `WCS` object with the desired initial transform and frame, or append/insert after the initial frame.","cause":"Attempting to insert a new transform before the initial coordinate frame in a `GWCS` pipeline (e.g., using `wcs.insert_transform(frame, transform, before=True)` with the `input_frame`). This was explicitly disallowed or raised an error from version 1.0.0 onwards.","error":"ValueError: Cannot insert a transform before the first frame in the pipeline."}]}