Understanding the Roman WFI Photometry Reference File#
Kernel Information and Read-Only Status#
To run this notebook, please select “Roman Research Nexus {VERSION}” kernel at the top right of your window. For example “Roman Research Nexus 2026.2”.
This notebook is read-only. You can run cells and make edits, but you must save changes to a different location. We recommend saving the notebook within your home directory, or to a new folder within your home (e.g. file > save notebook as > my-nbs/nb.ipynb). Note that a directory must exist before you attempt to add a notebook to it.
Introduction#
The purpose of this notebook is to understand the content and purpose of the Photometry (PHOTOM) reference file.
This file provides the photometric calibration information used by the photom to convert instrumental units (DN/s) into physical flux units (MJy/sr) and to populate photometric metadata (zero points, etc.).
More details about this and other reference files can be found in the Reference File Information.
Imports#
Libraries used:
astropy for image normalization and units
copy for making copies of Python objects
crds for access to calibration reference files
matplotlib and mpl_toolkits for plotting images
numpy for array manipulation
os for operating system functions
pandas for structured visualization of files in table format
import os
from astropy.visualization import simple_norm
from astropy import units as u
import copy
import matplotlib.pyplot as plt
from matplotlib import colors, colormaps as cm
from mpl_toolkits.axes_grid1 import make_axes_locatable
import pandas as pd
import numpy as np
import roman_datamodels as rdm
The Calibration Reference Data System (CRDS)#
The reference files, developed and validated by STScI’s Science Operations Center, are continually updated as new WFI data become available. For more information about how CRDS works and how it assigns the most appropriate reference file for each calibration step, refer to the notebook Inderstanding CRDS and How to Select Calibration Reference files.
IMPORTANT NOTE: Reference files are a work in progress and will be updated several times before Roman launch. If you notice irregularities or missing information, please understand that they may be a known issue. If you have questions, please contact the Roman Help Desk.
import crds
Now let’s dive into this reference file.
Photometry Reference File (PHOTOM)#
The PHOTOM reference file contains photometric conversion factors for each optical element. It is used to convert pixel values into physical units and to populate header keywords with zero points.
For more details, see the romancal photom documentation and Rdox documentation for photometric calibration.
Let’s check the environmental variables set for CRDS
print(f"CRDS server location: {os.environ.get('CRDS_SERVER_URL')}")
print(f"CRDS context file: {os.environ.get('CRDS_CONTEXT')}")
CRDS server location: https://roman-crds.stsci.edu
CRDS context file: roman-edit
If we want to change the context, we can do it in the next cell. In this case, we choose context roman_0058.pmap.
os.environ['CRDS_CONTEXT']='roman_0058.pmap'
Retrieving Reference Files#
As you run the exposure pipeline, the most up-to-date reference files will be automatically selected for each step. However, if you would like to use a specific reference file, retrieve it using the CRDS Python API and feed it to the Exposure Level Pipeline, see the notebook Understanding CRDS and How to Select Calibration Reference files for more details.
For the PHOTOM files in particular, the required keywords are:
- `ROMAN.META.INSTRUMENT.NAME`
- `ROMAN.META.INSTRUMENT.DETECTOR`
- `ROMAN.META.EXPOSURE.START_TIME`
These keywords may be combined into a single dictionary that is later fed to the crds.getrecommendations function. This function returns a dictionary of file names that match the criteria that you supply.
meta = {'ROMAN.META.INSTRUMENT.NAME': 'WFI',
'ROMAN.META.INSTRUMENT.DETECTOR': 'WFI01',
'ROMAN.META.EXPOSURE.START_TIME': '2026-01-01 00:00:00'
}
ref_files = crds.getreferences(meta, reftypes=['PHOTOM'], observatory='roman')
ref_files
CRDS - INFO - Syncing 30 files
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_specpsf_0001.rmap 572 bytes (1 / 30 files) (0 / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_skycells_0002.rmap 712 bytes (2 / 30 files) (572 / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_sflat_0001.rmap 548 bytes (3 / 30 files) (1.3 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_saturation_0003.rmap 2.4 K bytes (4 / 30 files) (1.8 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_relflux_0001.rmap 555 bytes (5 / 30 files) (4.3 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_refpix_0003.rmap 2.3 K bytes (6 / 30 files) (4.8 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_readnoise_0006.rmap 3.4 K bytes (7 / 30 files) (7.1 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_photom_0004.rmap 2.3 K bytes (8 / 30 files) (10.5 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_optmodel_0001.rmap 586 bytes (9 / 30 files) (12.9 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_matable_0004.rmap 690 bytes (10 / 30 files) (13.4 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_mask_0003.rmap 2.3 K bytes (11 / 30 files) (14.1 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_linearity_0005.rmap 2.4 K bytes (12 / 30 files) (16.4 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_ipc_0003.rmap 3.3 K bytes (13 / 30 files) (18.8 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_inverselinearity_0005.rmap 2.6 K bytes (14 / 30 files) (22.1 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_integralnonlinearity_0002.rmap 2.8 K bytes (15 / 30 files) (24.7 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_gain_0003.rmap 2.3 K bytes (16 / 30 files) (27.5 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_flat_0006.rmap 8.5 K bytes (17 / 30 files) (29.7 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_etc_0002.rmap 2.3 K bytes (18 / 30 files) (38.2 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_epsf_0004.rmap 16.3 K bytes (19 / 30 files) (40.5 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_dustmap_0003.rmap 855 bytes (20 / 30 files) (56.8 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_distortion_0002.rmap 3.6 K bytes (21 / 30 files) (57.7 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_detectorstatus_0002.rmap 773 bytes (22 / 30 files) (61.2 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_darkdecaysignal_0002.rmap 783 bytes (23 / 30 files) (62.0 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_dark_0011.rmap 4.4 K bytes (24 / 30 files) (62.8 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_area_0002.rmap 2.3 K bytes (25 / 30 files) (67.2 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_apcorr_0003.rmap 2.3 K bytes (26 / 30 files) (69.5 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_abvegaoffset_0002.rmap 2.5 K bytes (27 / 30 files) (71.8 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_absflux_0001.rmap 555 bytes (28 / 30 files) (74.3 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_wfi_0056.imap 2.4 K bytes (29 / 30 files) (74.8 K / 77.6 K bytes)
CRDS - INFO - Fetching /home/runner/crds_cache/mappings/roman/roman_0058.pmap 344 bytes (30 / 30 files) (77.3 K / 77.6 K bytes)
CRDS - INFO - Syncing 1 files
CRDS - INFO - Fetching /home/runner/crds_cache/references/roman/wfi/roman_wfi_photom_0040.asdf 3.5 K bytes (1 / 1 files) (0 / 3.5 K bytes)
{'photom': '/home/runner/crds_cache/references/roman/wfi/roman_wfi_photom_0040.asdf'}
Examining Reference Files#
Reference files use roman_datamodels just like WFI science data products and can be accessed in the same way (see the tutorial Working with ASDF for more information). Let’s take a closer look at the files we retrieved from our crds.getreferences() example starting with the flat file:
photom = rdm.open(ref_files['photom'])
photom.info(max_rows=50)
root (AsdfObject)
├─asdf_library (Software)
│ ├─author (str): The ASDF Developers
│ ├─homepage (str): http://github.com/asdf-format/asdf
│ ├─name (str): asdf
│ └─version (str): 4.0.0
├─history (AsdfDictNode)
│ └─extensions (AsdfListNode)
│ ├─0 (ExtensionMetadata)
│ │ ├─extension_class (str): asdf.extension._manifest.ManifestExtension
│ │ ├─extension_uri (str): asdf://asdf-format.org/core/extensions/core-1.6.0
│ │ ├─manifest_software (Software) ...
│ │ └─software (Software) ...
│ ├─1 (ExtensionMetadata)
│ │ ├─extension_class (str): asdf.extension._manifest.ManifestExtension
│ │ ├─extension_uri (str): asdf://stsci.edu/datamodels/roman/extensions/datamodels-1.0
│ │ ├─manifest_software (Software) ...
│ │ └─software (Software) ...
│ └─2 (ExtensionMetadata)
│ ├─extension_class (str): asdf.extension._manifest.ManifestExtension
│ ├─extension_uri (str): asdf://asdf-format.org/astronomy/extensions/astronomy-1.0.0
│ ├─manifest_software (Software) ...
│ └─software (Software) ...
└─roman (WfiImgPhotomRef) # WFI Imaging Photometric Flux Conversion Data Model
├─meta (AsdfDictNode) # Common Reference File Metadata Properties
│ ├─author (str): T. Desjardins # Author
│ ├─description (str): Roman WFI absolute photometric calibration information. Throughput information come (truncated)
│ ├─instrument (AsdfDictNode)
│ │ ├─detector (str): WFI01
│ │ ├─median_gain (float): 1.9266027212142944
│ │ ├─name (str): WFI # Instrument
│ │ └─sigma_gain (float): 0.07495339959859848
│ ├─origin (Origin): STSCI/SOC # Institution / Organization Name
│ ├─pedigree (str): GROUND # Pedigree
│ ├─reftype (str): PHOTOM
│ ├─telescope (Telescope): ROMAN # Telescope Name
│ └─useafter (Time): 2020-01-01 00:00:00 # Use After Date
└─phot_table (AsdfDictNode) # Photometric Flux Conversion Factors Table
├─DARK (AsdfDictNode) ...
├─F062 (AsdfDictNode) ...
├─F087 (AsdfDictNode) ...
├─F106 (AsdfDictNode) ...
├─F129 (AsdfDictNode) ...
├─F146 (AsdfDictNode) ...
├─F158 (AsdfDictNode) ...
├─F184 (AsdfDictNode) ...
├─F213 (AsdfDictNode) ...
├─GRISM (AsdfDictNode) ...
└─PRISM (AsdfDictNode) ...
Some nodes not shown.
In this case, the data is in the photom_table which includes the Photometric Flux Conversion Factors. Let’s take a look at the photometric conversion information.
print("Photometric conversion information:")
# Common fields in Roman PHOTOM files
df = pd.DataFrame.from_dict(photom.phot_table, orient='index')
print("\nFull Photometric Table:")
print(df)
Photometric conversion information:
Full Photometric Table:
photmjsr pixelareasr uncertainty
DARK NaN NaN NaN
F062 0.583626 2.808339e-13 0.022706
F087 0.805092 2.808339e-13 0.031322
F106 0.741749 2.808339e-13 0.028857
F129 0.738893 2.808339e-13 0.028746
F146 0.240393 2.808339e-13 0.009352
F158 0.736781 2.808339e-13 0.028664
F184 1.133710 2.808339e-13 0.044106
F213 1.175891 2.808339e-13 0.045747
GRISM NaN NaN NaN
PRISM NaN NaN NaN
Get unit values
def get_unit(val):
if hasattr(val, 'unit'):
return str(val.unit)
elif isinstance(val, (int, float)):
return "dimensionless"
else:
return "unknown"
print("PHOTOM Units Summary:\n")
for filt, info in photom.phot_table.items():
print(f"{filt:6s}:")
print(f" photmjsr : {info.get('photmjsr')} [{get_unit(info.get('photmjsr'))}]")
print(f" uncertainty : {info.get('uncertainty')} [{get_unit(info.get('uncertainty'))}]")
print(f" pixelareasr : {info.get('pixelareasr')} [{get_unit(info.get('pixelareasr'))}]")
PHOTOM Units Summary:
DARK :
photmjsr : None [unknown]
uncertainty : None [unknown]
pixelareasr : None [unknown]
F062 :
photmjsr : 0.5836263702584822 [dimensionless]
uncertainty : 0.022705656904495823 [dimensionless]
pixelareasr : 2.8083389953727505e-13 [dimensionless]
F087 :
photmjsr : 0.8050920510180883 [dimensionless]
uncertainty : 0.03132165511790955 [dimensionless]
pixelareasr : 2.8083389953727505e-13 [dimensionless]
F106 :
photmjsr : 0.7417487930165987 [dimensionless]
uncertainty : 0.028857321159254122 [dimensionless]
pixelareasr : 2.8083389953727505e-13 [dimensionless]
F129 :
photmjsr : 0.7388933595729765 [dimensionless]
uncertainty : 0.028746232121149497 [dimensionless]
pixelareasr : 2.8083389953727505e-13 [dimensionless]
F146 :
photmjsr : 0.24039322273833708 [dimensionless]
uncertainty : 0.009352363628198133 [dimensionless]
pixelareasr : 2.8083389953727505e-13 [dimensionless]
F158 :
photmjsr : 0.7367810113020512 [dimensionless]
uncertainty : 0.02866405239530676 [dimensionless]
pixelareasr : 2.8083389953727505e-13 [dimensionless]
F184 :
photmjsr : 1.1337095345751624 [dimensionless]
uncertainty : 0.04410633417749541 [dimensionless]
pixelareasr : 2.8083389953727505e-13 [dimensionless]
F213 :
photmjsr : 1.1758909217444202 [dimensionless]
uncertainty : 0.04574737740930944 [dimensionless]
pixelareasr : 2.8083389953727505e-13 [dimensionless]
GRISM :
photmjsr : None [unknown]
uncertainty : None [unknown]
pixelareasr : None [unknown]
PRISM :
photmjsr : None [unknown]
uncertainty : None [unknown]
pixelareasr : None [unknown]
Extracting Zero Points and Units#
We can use this information to calculate the AB magnitude zero points
# Add Zero Point column (AB magnitude)
# Approximate conversion: zp_ab ≈ -2.5 * log10(photmjsr) + 8.90
# (check the constant for Roman)
if 'photmjsr' in df.columns:
df['zp_ab'] = np.where(
df['photmjsr'].notna() & (df['photmjsr'] > 0),
-2.5 * np.log10(df['photmjsr']) + 8.90,
np.nan
)
df['zp_ab'] = df['zp_ab'].round(3)
# Reorder columns
cols = ['photmjsr', 'zp_ab', 'pixelareasr', 'uncertainty']
df = df[cols + [c for c in df.columns if c not in cols]]
print("\nFull Photometric Table with Zero Points:")
print(df)
Full Photometric Table with Zero Points:
photmjsr zp_ab pixelareasr uncertainty
DARK NaN NaN NaN NaN
F062 0.583626 9.485 2.808339e-13 0.022706
F087 0.805092 9.135 2.808339e-13 0.031322
F106 0.741749 9.224 2.808339e-13 0.028857
F129 0.738893 9.229 2.808339e-13 0.028746
F146 0.240393 10.448 2.808339e-13 0.009352
F158 0.736781 9.232 2.808339e-13 0.028664
F184 1.133710 8.764 2.808339e-13 0.044106
F213 1.175891 8.724 2.808339e-13 0.045747
GRISM NaN NaN NaN NaN
PRISM NaN NaN NaN NaN
About this Notebook#
Author: R. Diaz
Updated On: 2026-07-06
| Top of page |
|
|