Examples¶
Here are examples of designing datamodels for files that do not yet exist on disk.
Converting a CSV File¶
This example documents how to convert an example CSV file
into a
valid FITS file, and produce a datamodel at the same time. It shows how to design new datamodels for
FITS files that do not yet exist, and to generate a template FITS file from the designed datamodel at
the end of the process. It follows the instructions in Designing Datamodels.
The example CSV file
contains 5 columns of data of types
integer, string, float, boolean, and float.
Generating the YAML stub¶
First we need to specify a desired file species name and abstract path location of where we want or expect the FITS file to live on disk. Then we instantiate a new DataModel with the “design” flag set to True. Then we generate the initial YAML datamodel.
from datamodel.generate import DataModel
# define the file species name and abstract path we want
fs = "exampleCatalog"
path = "SANDBOX_DIR/test/{ver}/example_catalog.fits"
# create a new datamodel, with the design flag set
dm = DataModel(file_spec=fs, path=path, design=True, tree_ver='sdss5')
# generate the initial YAML datamodel stub
dm.write_stubs()
This produces a YAML with the standard sections “general”, “changelog”, and “releases”, with new “WORK” release entry. It adds a default PRIMARY HDU extension 0. We can now design any additional HDUs.
We need to a design a new FITS BinaryTableHDU that maps to the tabular CSV data. To design a new
table HDU, we specify a “table” extension, the name of the extension, and a list of desired columns.
See Designing an HDU and the design_hdu
for details. The list of
columns can be a list of tuples, with the column name, and the column format. The allowed FITS column
formats are at FITS Column Creation.
# design a binary table hdu extension to add to the YAML file
columns = [("a", "J"), ("b", "5A"), ("c", "E"), ("d", "L"), ("e", "D")]
dm.design_hdu(ext="table", name="CATALOG", columns=columns)
This adds a new HDU extension into the YAML datamodel.
hdus:
hdu0:
name: PRIMARY
description: replace me description
is_image: true
size: 0 bytes
header:
- key: SIMPLE
value: true
comment: conforms to FITS standard
- key: BITPIX
value: 8
comment: array data type
- key: NAXIS
value: 0
comment: number of array dimensions
hdu1:
name: CATALOG
description: replace me description
is_image: false
size: 0 bytes
columns:
a:
name: A
type: int32
unit: replace me - with content
description: replace me - with content
b:
name: B
type: char[5]
unit: replace me - with content
description: replace me - with content
c:
name: C
type: float32
unit: replace me - with content
description: replace me - with content
d:
name: D
type: bool
unit: replace me - with content
description: replace me - with content
e:
name: E
type: float64
unit: replace me - with content
description: replace me - with content
Filling in the YAML content¶
We now have a YAML datamodel that must be properly validated and have all the “replace me” content filled in. Fill in any “replace me” fields with the relevant text. This includes the general short and long descriptions. All designed HDU content will have “replace me” fields. For our new BinaryTable HDU, we must fill in a description of the extension, as well as values for the column units and descriptions.
Generating the template FITS file¶
Once we’ve filled out our YAML file, and replaced all required content, we can generate a template FITS file from our designed datamodel. To generate a real file, we need to define example path keyword arguments to convert our abstract path to a real path.
# generate the FITS file, with version v1
dm.generate_designed_file(ver='v1')
This code creates a new FITS file at the example path location $SANDBOX_DIR/test/v1/example_catalog.fits
.
We can now read it in and examine it. The new FITS file is only a template, and will have empty data in
its HDU extensions. See Adding Data Values below on how to fill our CSV table data.
from astropy.io import fits
# read in our new FITS file
hdu = fits.open(dm.file)
# examine the FITS file
hdu.info()
Filename: ../sas/sdsswork/sandbox/test/v1/example_catalog.fits
No. Name Ver Type Cards Dimensions Format
0 PRIMARY 1 PrimaryHDU 6 ()
1 CATALOG 1 BinTableHDU 21 0R x 5C [J, 5A, E, L, D]
Generating Valid JSON¶
A valid datamodel JSON can only be produced for existing files, outside of the design phase. Generating a template FITS file creates a file and exits the design phase. If the YAML model is properly validated, we can now write out the JSON datamodel.
dm.write_stubs()
Adding Data Values¶
An optional final step is to add the CSV table data to our new FITS file HDU extension. We can do this easily by reading in the CSV file as an Astropy Table object, then converting the table to a valid FITS BinaryTableHDU, and finally copying the data over to our custom FITS file. We use the astropy helper function table_to_hdu to properly account for column formats, and any necessary big/little endian conversions.
Note
if you get the following error during data copy, TypeError: Table data has incorrect type.
,
this means that one of the columns designed in the datamodel does not match the column format Astropy
Table has detected. Double check that all columns have the correct format, and update any incorrect
columns formats in the datamodel file.
from astropy.io import fits
from astropy.table import Table
# read in our new FITS file
hdu = fits.open(dm.file)
# read in the csv as an Astropy Table and name the columns as the HDU columns
t = Table.read("example.csv", format="csv", names=hdu[1].data.columns.names)
# convert the table to HDU and write its data to our HDU
dd = fits.table_to_hdu(t)
hdu[1].data = dd.data
hdu.writeto(hdu.filename(), overwrite=True)