Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements to reading / writing FITS images #2246

Merged
merged 74 commits into from
May 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
d399c23
Allow the user to set the image center
jzuhone Feb 10, 2018
a7f3d4d
shorter
jzuhone Feb 11, 2018
4a82a53
Separate out the yt-generated FITS files into a new class which reads…
jzuhone Feb 11, 2018
8685e5d
Refactor of this to write all of the units and the current time (if i…
jzuhone Feb 19, 2018
6efba9a
Add an attribute for the header's comments
jzuhone Feb 19, 2018
68296dc
Loop over and get the units from the header
jzuhone Feb 19, 2018
286703d
Get the current_time from the header if it's there
jzuhone Feb 19, 2018
c38c18f
Special handling for velocity and magnetic units
jzuhone Feb 19, 2018
be76386
A method to fix the input current time
jzuhone Feb 19, 2018
cae102d
Bugfix
jzuhone Feb 19, 2018
192789c
I obviously didn't understand how that worked
jzuhone Feb 19, 2018
cf24b34
Bugfix
Feb 19, 2018
5c071b9
Bugfixes
Feb 20, 2018
af20d62
Try to determine the units of the image using AstroPy and yt-based un…
jzuhone Feb 20, 2018
4501dda
Bugfix
jzuhone Feb 20, 2018
b603797
Oops
jzuhone Feb 20, 2018
f551ed8
More refining on this
jzuhone Feb 20, 2018
31dd2ff
Removing stuff we don't need anymore
jzuhone Feb 20, 2018
6192ea7
Bugfix
jzuhone Feb 20, 2018
7ba6d64
Make the left and right edges in the length units of the dataset, whi…
jzuhone Feb 20, 2018
5677dac
Bugfixes
Mar 11, 2018
63e0ce5
Fix comment
jzuhone Feb 20, 2018
c5f8a03
Drop the fits suffix from the repr
jzuhone Feb 21, 2018
4924370
Fix bad header keywords
jzuhone Mar 15, 2018
9b9f946
Fix magnetic field units
Apr 10, 2018
7c8b21b
Bug fixes
Aug 1, 2018
f81de83
Some fallback logic for older FITSImageData files
jzuhone Aug 2, 2018
ca27d26
Fix bug for when units are not present
Aug 18, 2018
c931744
Fix current time bug with units
Aug 18, 2018
2afd13b
Only set the current time for YTFITSDataset
jzuhone Aug 18, 2018
3cfd03b
Bugfix
Aug 18, 2018
424cbbf
A more descriptive message
Aug 18, 2018
ca042f6
A new method for convolution
Aug 18, 2018
5a31de6
Document convolve and fix some whitespace issues
jzuhone Aug 22, 2018
d5d5556
Add wcsname to docstring
jzuhone Aug 22, 2018
e29dce9
image_res should now have a default value of 512 for all cases
jzuhone Aug 22, 2018
fe8f9a0
These changes make sure we always have some number for current_time
jzuhone Aug 22, 2018
a9330a9
Minor fix here so we don't put a mutable in the function definition
jzuhone Aug 22, 2018
b30a378
Getting the shape correct for all types
jzuhone Aug 22, 2018
de80d06
Bugfix
Aug 30, 2018
e20ac16
Move these down here
jzuhone Sep 9, 2018
d9531f1
Set the length unit of the FITS file by the same unit as the pixel sc…
jzuhone Sep 9, 2018
5dc6bee
Fix up docstring
jzuhone Sep 9, 2018
e896de1
A new method here, fixing line lengths
jzuhone Sep 10, 2018
636efac
Fixing PEP8-isms and cosmetic issues
jzuhone Sep 10, 2018
a4cf5ab
The length unit default should be the length unit of the dataset unle…
jzuhone Sep 10, 2018
c582e8b
Allow the default length unit to be specified here
jzuhone Sep 10, 2018
5cc69fa
Add a method for exporting a covering grid to a FITSImageData object
jzuhone Sep 10, 2018
a2e7f92
Bugfix
jzuhone Sep 10, 2018
8d2ee9d
We'll just leave the __repr__ alone
jzuhone Sep 12, 2018
0ff9b12
Making a change recommended by @cadair to agree with the FITS standard
jzuhone Sep 12, 2018
a8f3284
Restore some old code to allow length units to be detected from the h…
jzuhone Sep 14, 2018
e07f132
This fixes a regression--we want to include cubes with linear axes bu…
jzuhone Sep 14, 2018
143dbc7
Make sure we can handle code units
jzuhone Sep 17, 2018
65cb0fc
Fix deprecation warnings and whitespace
jzuhone Sep 17, 2018
93810af
A function to change the name of a fits image
jzuhone Nov 8, 2018
fa5e244
Some doc fixes
jzuhone Nov 20, 2018
52bd6e1
Some doc work
jzuhone Mar 25, 2019
b4b7b00
Updating docs for FITS data
jzuhone Apr 22, 2019
5b71a06
Forgot this
jzuhone Apr 22, 2019
171e10b
bugfix
jzuhone Apr 22, 2019
fef67ba
bugfix
jzuhone Apr 23, 2019
90672db
Make sure we can only do one image, and make sure that we make a copy
jzuhone Apr 23, 2019
60a6c50
Fix bugs
jzuhone Apr 23, 2019
339d1ed
Pass extra arguments to convolve
jzuhone Apr 23, 2019
6e67659
This only works for 2D data
jzuhone Apr 23, 2019
dc03347
Update FITS tests
jzuhone Apr 23, 2019
d452e45
Update docs
jzuhone Apr 23, 2019
5df175f
These should be set by the dataset
jzuhone Apr 29, 2019
3a2c01e
Failsafe against using code units here
jzuhone Apr 29, 2019
b3ffe21
Fix corner case of length units which are not pure
jzuhone Apr 29, 2019
e614199
account for potentially duplicate names
jzuhone Apr 29, 2019
6b98e5d
Don't fail here but convert to cgs instead
jzuhone Apr 29, 2019
0d2c955
Responding to comments by matthewturk and munkm
jzuhone May 20, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 78 additions & 80 deletions doc/source/examining/loading_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -698,90 +698,105 @@ can read FITS image files that have the following (case-insensitive) suffixes:
* fts.gz

yt can currently read two kinds of FITS files: FITS image files and FITS
binary table files containing positions, times, and energies of X-ray events.
binary table files containing positions, times, and energies of X-ray
events. These are described in more detail below.

Though a FITS image is composed of a single array in the FITS file,
upon being loaded into yt it is automatically decomposed into grids:
Types of FITS Datasets Supported by yt
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

.. code-block:: python
yt FITS Data Standard
"""""""""""""""""""""

import yt
ds = yt.load("m33_hi.fits")
ds.print_stats()
yt has facilities for creating 2 and 3-dimensional FITS images from derived,
fixed-resolution data products from other datasets. These include images
produced from slices, projections, and 3D covering grids. The resulting
FITS images are fully-describing in that unit, parameter, and coordinate
information is passed from the original dataset. These can be created via the
:class:`~yt.visualization.fits_image.FITSImageData` class and its subclasses.
For information about how to use these special classes, see
:ref:`writing_fits_images`.

.. parsed-literal::
Once you have produced a FITS file in this fashion, you can load it using
yt and it will be detected as a ``YTFITSDataset`` object, and it can be analyzed
in the same way as any other dataset in yt.

level # grids # cells # cells^3
----------------------------------------------
0 512 981940800 994
----------------------------------------------
512 981940800
Astronomical Image Data
"""""""""""""""""""""""

yt will generate its own domain decomposition, but the number of grids can be
set manually by passing the ``nprocs`` parameter to the ``load`` call:
These files are one of three types:

* Generic two-dimensional FITS images in sky coordinates
* Three or four-dimensional "spectral cubes"
* *Chandra* event files

These FITS images typically are in celestial or galactic coordinates, and
for 3D spectral cubes the third axis is typically in velocity, wavelength,
or frequency units. For these datasets, since yt does not yet recognize
non-spatial axes, the coordinates are in units of the image pixels. The
coordinates of these pixels in the WCS coordinate systems will be available
in separate fields.

Often, the aspect ratio of 3D spectral cubes can be far from unity. Because yt
sets the pixel scale as the ``code_length``, certain visualizations (such as
volume renderings) may look extended or distended in ways that are
undesirable. To adjust the width in ``code_length`` of the spectral axis, set
``spectral_factor`` equal to a constant which gives the desired scaling, or set
it to ``"auto"`` to make the width the same as the largest axis in the sky
plane:

.. code-block:: python

ds = load("m33_hi.fits", nprocs=1024)
ds = yt.load("m33_hi.fits.gz", spectral_factor=0.1)

For 4D spectral cubes, the fourth axis is assumed to be composed of different
fields altogether (e.g., Stokes parameters for radio data).

*Chandra* X-ray event data, which is in tabular form, will be loaded as
particle fields in yt, but a grid will be constructed from the WCS
information in the FITS header. There is a helper function,
``setup_counts_fields``, which may be used to make deposited image fields
from the event data for different energy bands (for an example see
:ref:`xray_fits`).

Generic FITS Images
"""""""""""""""""""

If the FITS file contains images but does not have adequate header information
to fall into one of the above categories, yt will still load the data, but
the resulting field and/or coordinate information will necessarily be
incomplete. Field names may not be descriptive, and units may be incorrect. To
get the full use out of yt for FITS files, make sure that the file is sufficiently
self-descripting to fall into one of the above categories.

Making the Most of yt for FITS Data
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

yt will load data without WCS information and/or some missing header keywords, but the resulting
field information will necessarily be incomplete. For example, field names may not be descriptive,
and units will not be correct. To get the full use out of yt for FITS files, make sure that for
each image the following header keywords have sensible values:
yt will load data without WCS information and/or some missing header keywords,
but the resulting field and/or coordinate information will necessarily be
incomplete. For example, field names may not be descriptive, and units will not
be correct. To get the full use out of yt for FITS files, make sure that for
each image HDU the following standard header keywords have sensible values:

* ``CDELTx``: The pixel width in along axis ``x``
* ``CRVALx``: The coordinate value at the reference position along axis ``x``
* ``CRPIXx``: The reference pixel along axis ``x``
* ``CTYPEx``: The projection type of axis ``x``
* ``CUNITx``: The units of the coordinate along axis ``x``
* ``BTYPE``: The type of the image
* ``BTYPE``: The type of the image, this will be used as the field name
* ``BUNIT``: The units of the image

FITS header keywords can easily be updated using AstroPy. For example,
to set the ``BTYPE`` and ``BUNIT`` keywords:

.. code-block:: python

import astropy.io.fits as pyfits
f = pyfits.open("xray_flux_image.fits", mode="update")
from astropy.io import fits
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how modern! 😁

f = fits.open("xray_flux_image.fits", mode="update")
f[0].header["BUNIT"] = "cts/s/pixel"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the notebook you showed updating header values with the update_header() method. Can that be used to do the same thing as the code block here too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually a different situation where we show how to make FITS files more self-descripting so yt can read them properly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok! That makes sense! Is there any threshold of requirements that yt needs to read FITS files properly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really a threshold, it's more that the more self-descripting your data is, the better it is supported. Even data that's not very self-descripting can still be loaded.

f[0].header["BTYPE"] = "flux"
f.flush()
f.close()

FITS Coordinates
^^^^^^^^^^^^^^^^

For FITS datasets, the unit of ``code_length`` is always the width of one
pixel. yt will attempt to use the WCS information in the FITS header to
construct information about the coordinate system, and provides support for
the following dataset types:

1. Rectilinear 2D/3D images with length units (e.g., Mpc, AU,
etc.) defined in the ``CUNITx`` keywords
2. 2D images in some celestial coordinate systems (RA/Dec,
galactic latitude/longitude, defined in the ``CTYPEx``
keywords), and X-ray binary table event files
3. 3D images with celestial coordinates and a third axis for another
quantity, such as velocity, frequency, wavelength, etc.
4. 4D images with the first three axes like Case 3, where the slices
along the 4th axis are interpreted as different fields.

If your data is of the first case, yt will determine the length units based
on the information in the header. If your data is of the second or third
cases, no length units will be assigned, but the world coordinate information
about the axes will be stored in separate fields. If your data is of the
fourth type, the coordinates of the first three axes will be determined
according to cases 1-3.

.. note::

Linear length-based coordinates (Case 1 above) are only supported if all
dimensions have the same value for ``CUNITx``. WCS coordinates are only
supported for Cases 2-4.

FITS Data Decomposition
^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -812,8 +827,7 @@ set manually by passing the ``nprocs`` parameter to the ``load`` call:

.. code-block:: python

ds = load("m33_hi.fits", nprocs=64)

ds = yt.load("m33_hi.fits", nprocs=64)

Fields in FITS Datasets
^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -833,7 +847,7 @@ The third way is if auxiliary files are included along with the main file, like

.. code-block:: python

ds = load("flux.fits", auxiliary_files=["temp.fits","metal.fits"])
ds = yt.load("flux.fits", auxiliary_files=["temp.fits","metal.fits"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checking: this is an example of a case where there might be auxiliary files. We don't have any datasets in the FITS frontend that have these, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@munkm we don't, no. I don't think I have any on hand at the moment, actually.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's ok! I just wanted to check that I shouldn't be able to run it with any files that I currently have locally.


The image blocks in each of these files will be loaded as a separate field,
provided they have the same dimensions as the image blocks in the main file.
Expand All @@ -843,12 +857,6 @@ based on the corresponding ``CTYPEx`` keywords. When queried, these fields
will be generated from the pixel coordinates in the file using the WCS
transformations provided by AstroPy.

X-ray event data will be loaded as particle fields in yt, but a grid will be
constructed from the WCS information in the FITS header. There is a helper
function, ``setup_counts_fields``, which may be used to make deposited image
fields from the event data for different energy bands (for an example see
:ref:`xray_fits`).

.. note::

Each FITS image from a single dataset, whether from one file or from one of
Expand All @@ -874,11 +882,11 @@ containing different mask values for different fields:

.. code-block:: python

# passing a single float
ds = load("m33_hi.fits", nan_mask=0.0)
# passing a single float for all images
ds = yt.load("m33_hi.fits", nan_mask=0.0)

# passing a dict
ds = load("m33_hi.fits", nan_mask={"intensity":-1.0,"temperature":0.0})
ds = yt.load("m33_hi.fits", nan_mask={"intensity":-1.0,"temperature":0.0})

``suppress_astropy_warnings``
"""""""""""""""""""""""""""""
Expand All @@ -887,17 +895,6 @@ Generally, AstroPy may generate a lot of warnings about individual FITS
files, many of which you may want to ignore. If you want to see these
warnings, set ``suppress_astropy_warnings = False``.

``spectral_factor``
"""""""""""""""""""

Often, the aspect ratio of 3D spectral cubes can be far from unity. Because yt
sets the pixel scale as the ``code_length``, certain visualizations (such as
volume renderings) may look extended or distended in ways that are
undesirable. To adjust the width in ``code_length`` of the spectral axis, set
``spectral_factor`` equal to a constant which gives the desired scaling, or set
it to ``"auto"`` to make the width the same as the largest axis in the sky
plane.

Miscellaneous Tools for Use with FITS Data
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -950,7 +947,7 @@ version of AstroPy >= 1.3 must be installed.
.. code-block:: python

wcs_slc = PlotWindowWCS(slc)
wcs_slc.show() # for the IPython notebook
wcs_slc.show() # for Jupyter notebooks
wcs_slc.save()

``WCSAxes`` is still in an experimental state, but as its functionality
Expand Down Expand Up @@ -978,8 +975,8 @@ individual lines from an intensity cube:
'CH3NH2': (218.40956, 'GHz')}
slab_width = (0.05, "GHz")
ds = create_spectral_slabs("intensity_cube.fits",
slab_centers, slab_width,
nan_mask=0.0)
slab_centers, slab_width,
nan_mask=0.0)

All keyword arguments to ``create_spectral_slabs`` are passed on to ``load`` when
creating the dataset (see :ref:`additional_fits_options` above). In the
Expand All @@ -992,11 +989,12 @@ zero, and the left and right edges of the domain along this axis are
Examples of Using FITS Data
^^^^^^^^^^^^^^^^^^^^^^^^^^^

The following IPython notebooks show examples of working with FITS data in yt,
The following Jupyter notebooks show examples of working with FITS data in yt,
which we recommend you look at in the following order:

* :ref:`radio_cubes`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you also want to add a link to the FITSImageData notebook in /visualizing/ here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good

* :ref:`xray_fits`
* :ref:`writing_fits_images`

.. _loading-flash-data:

Expand Down
Loading