Skip to content

Image Format

George N. Wong edited this page Mar 9, 2021 · 9 revisions

HDF5 Image Output Format

Images produced by the ipole code (and similar) are saved in HDF5 "image" files according to the format specified on this page. It is intended that this format encapsulate all data required to both regenerate the image from scratch and enable quick extraction of physically meaningful quantities.

In the specification below, we use "double" to mean the 8-byte wide floating-point type, "float" to mean the 4-byte wide floating-point type, "int" to mean the 4-byte wide floating point type, and "string" to mean fixed-size zero-terminated character arrays of size 20. Arrays are indicated by the use of trailing square brackets "[]" where the number of sets of brackets corresponds to the dimension of the array. All numerical values are stored in little-endian format.

At a glance

Making an image

Full specification

At a glance

Image data comprises two groups: output image data and the parameters used to generate the image. The actual image data is stored at the top level of the file in several arrays. Most important among these are the unpol and pol arrays which contain intensity information in cgs units. The unpolarized array is of shape NX,NY and reports Stokes I values computed via the unpolarized transport methods. The pol array is of shape NX,NY,5 and contains each of Stokes I,Q,U,V (in order) and also tauF.

Pixels are ordered from E to W, then S to N on the sky, i.e., the first index corresponds to "how far right" the pixel is and the second corresponds to "how far up" the pixel is on a standard image.

Pixel values can be translated from cgs intensity to flux density in Jy by multiplying by the geometric scale factor saved in the image parameter header, accessible at /header/scale.

Other quantities of interest might include image FOV data which can be found in units of L_unit at /header/camera/dx. To convert this value into microarcseconds at Earth, note that

fov_muas = /header/camera/dx * /header/units/L_unit / /header/dsource * 2.06265e11

Making an image

The easiest way to make an image would be to use the python plotting scripts found in the ipole repository at ipole/scripts/plot*.py. These take any number of arguments where each should be the filename of an hdf5 image file. A new png image will be generated from each of these hdf5 files with the same filename (but h5 → png extension).

Otherwise, see the minimalist example plotting script below:

import matplotlib.pyplot as plt
import numpy as np
import h5py
import sys

# load image data (unpolarized intensity and scaling factors) from hdf5 image
hfp = h5py.File(sys.argv[1],'r')
dx_cgs = hfp['header']['camera']['dx'][()] * hfp['header']['units']['L_unit'][()]
fovMuas = dx_cgs / hfp['header']['dsource'][()] * 2.06265e11
cgsToJy = hfp['header']['scale'][()]
unpol = np.copy(hfp['unpol']).transpose((1,0)) * cgsToJy
hfp.close()

# make plot and show
ext = [ -fovMuas/2, fovMuas/2, -fovMuas/2, fovMuas/2 ]
plt.imshow(unpol, origin='lower', extent=ext)
plt.show()

Full specification

Root values

  • Ftot: Total flux calculated with polarized transport. Equals sum(pol[:,:,0]) * /header/scale
  • Ftot_unpol: Total flux calcualated with unpolarized transport
  • Mdot: Accretion rate of the BH in the image, in CGS
  • MdotEdd: Mdot as a fraction of the Eddington accretion rate
  • pol: Polarized image, see above
  • unpol: Intensity-only image, see above
  • tau: Optical depth of each pixel

Header

Base parameters ('/header/'):

Some parameters about the image:

  • dsource: Distance to source in cm
  • evpa_0: Convention for measuring the Electric Vector Position Angle. "N" means the angle is measured East of North. That is, positive values of the Stokes parameter +Q correspond to vertical linear polarization on the sky, and +U corresponds to polarization 45 degrees East (i.e. counter-clockwise) of +Q. The "W" convention measures from West corresponding to switching the signs of both Q and U.
  • freqcgs: Frequency of observation, in Hz
  • scale: Conversion factor between Stokes I in CGS units, as recorded by ipole, and Jy/px for plotting and total flux calculations. See "At a Glance."
  • t: Simulation time of the dump file being imaged, measured in M.

And a couple recording the code version:

  • version: output version string. Bumped when ipole would produce significantly different results, or when the output format changes (except recording extra parameters).
  • githash: git commit of the code that produced this output. Useful for reproducibility and as a special-case of last resort

Camera parameters ('/header/camera/'):

ipole does not compute geodesics all the way from M87 to a camera based on Earth. Instead, it locates the camera some sufficient distance away rcam, and sets the FOV of this camera (fovx, fovy) to match the desired FOV in microarcseconds from Earth (fovx_dsource, fovy_dsource). However, the views produce an image of exactly the same area measured in the plane (dx, dy). All these values are recorded for repeatability, but the most useful are nearly always the _dsource values, or dx and dy.

Coordinates of the camera in space are given in Spherical Kerr-Schild coordinates by the values rcam, thetacam, and phicam. The exact location in native coordinates of the GRMHD dump being imaged are given in x as a 4-vector. The former are likely more useful. Camera rotation is given by rotcam. The camera is always centered on the BH, that is, the null geodesic with zero angular momentum hits the center of the camera.

  • dx, dy: Planar size of the camera FOV. Measured in M.
  • fovx, fovy: Camera FOV from rcam, much larger than FOV from Earth. Measured in radians.
  • fovx_dsource, fovy_dsource: Camera FOV from Earth. Measured in micro-arcseconds
  • rcam: Distance of actual camera to source in M
  • thetacam, phicam: Camera location in KS coordinates. Values given in degrees, and are measured vs the simulation's grid. For iharm3D, this means that values are measured vs the angular momentum vector of the accreting material
  • rotcam: Camera rotation (roll). Measured in degrees
  • xoff, yoff: Camera offset (pan ~= truck) in pixels. Designed for debugging and to create jitter in images to avoid overfitting ML models.

Electrons ('/header/electrons/'):

Electrons can be simulated with several different models. ipole numbers these and records the number of the model being used in /electrons/type. The models are:

  1. Constant fraction. Accompanied by tp_over_te, the ratio of ion to eletron temperatures
  2. Native electrons. Electron temperatures are read from GRMHD output
  3. Rhigh model. Plasma-beta-dependent model as described in Paper V. Accompanied by rhigh, rlow, and more recently also beta_crit. The latter two are set to 1 in Paper V and similar models.

Units ('/header/units/'):

Since GRMHD simulations have no inherent scale, ipole sets scales based on the BH mass and accretion rate when producing images. It records the scaling factors in '/header/units'.

  • L_unit: M_BH * G / c^2
  • T_unit: L_unit/c
  • M_unit: Density scaling unit, fit to produce correct average flux over a simulation run. That is, Mdot calculated in code units from the GRMHD dump, multipled by M_unit, is Mdot of the BH being imaged.

Fluid Header ('/fluid_header/'):

Header of the GRMHD dump being imaged. See that wiki page for documentation.