Quickstart

This page takes five minutes. You will read a real CDF file, plot it, and write a new one. Every example on this page runs as-is: copy it into Python and try it.

Get a file

We use one day of magnetic field data from NASA’s ACE spacecraft. The file is small (250 kB) and comes from NASA’s public archive, SPDF.

import urllib.request

url = ("https://spdf.gsfc.nasa.gov/pub/data/ace/mag/level_2_cdaweb/"
       "mfi_h0/2020/ac_h0_mfi_20200101_v07.cdf")
urllib.request.urlretrieve(url, "ac_h0_mfi_20200101_v07.cdf")

Open it

import pycdfpp

cdf = pycdfpp.load("ac_h0_mfi_20200101_v07.cdf")
print(cdf)

print shows a summary: the file’s global attributes (information about the whole file), then each variable with its shape, type and attributes. Here is the start:

CDF:
  version: 3.7.1
  majority: column
  compression: None

Attributes:
  TITLE: "ACE> Magnetometer Parameters"
  Project: [ [ "ACE>Advanced Composition Explorer", "ISTP>International Solar-Terrestrial Physics" ] ]
  ...

Opening is instant, even for big files. CDFpp reads the data of a variable only when you ask for it.

See what’s inside

A CDF file holds variables. You use it like a dictionary of variables:

print(list(cdf))          # all variable names
print("BGSEc" in cdf)     # True

for name, var in cdf.items():
    print(name, var.shape, var.type)
Epoch (5401, 1) DataType.CDF_EPOCH
Magnitude (5401, 1) DataType.CDF_REAL4
BGSEc (5401, 3) DataType.CDF_REAL4
...

BGSEc is the magnetic field vector. It has 5401 records (one every 16 seconds) of 3 values each: the X, Y and Z components.

Get the data

.values gives you a numpy array:

b = cdf["BGSEc"].values
print(b.shape, b.dtype)   # (5401, 3) float32

The time is in the Epoch variable. Convert it to numpy datetime64:

time = pycdfpp.to_datetime64(cdf["Epoch"])
print(time[0])            # ['2020-01-01T00:00:00.000000000']

Read the metadata

Each variable has its own attributes. They tell you what the data means:

bgse = cdf["BGSEc"]
print(bgse.attributes["CATDESC"].value)   # Magnetic Field Vector in GSE Cartesian coordinates (16 sec)
print(bgse.attributes["UNITS"].value)     # nT
print(bgse.attributes["DEPEND_0"].value)  # Epoch  <- the time variable to use

Global attributes describe the whole file:

print(cdf.attributes["TITLE"][0])         # ACE> Magnetometer Parameters

Plot it

import matplotlib.pyplot as plt

plt.plot(time.ravel(), b, label=["Bx", "By", "Bz"])
plt.ylabel(bgse.attributes["UNITS"].value)
plt.legend()
plt.gcf().autofmt_xdate()
plt.show()

Write a file

Now the other way around. Build a CDF in memory, then save it:

import numpy as np

out = pycdfpp.CDF()
out.add_attribute("Project", ["My mission"])

time = np.arange("2024-01-01", "2024-01-02", np.timedelta64(1, "h"),
                 dtype="datetime64[ns]")
out.add_variable("Epoch", values=time)
out.add_variable("Temperature",
                 values=np.linspace(20.0, 25.0, len(time)),
                 attributes={"UNITS": "degC", "DEPEND_0": "Epoch"})

pycdfpp.save(out, "my_first.cdf")

And read it back:

check = pycdfpp.load("my_first.cdf")
print(check["Temperature"].values[:3])   # [20.    20.2173913  20.43478261]

Next steps