[{"data":1,"prerenderedAt":26},["ShallowReactive",2],{"analysis-playbook-general-cdf-format":3},{"@context":4,"@type":5,"name":6,"description":7,"proficiencyLevel":8,"dependencies":9,"programmingLanguage":15,"keywords":16,"articleBody":25},"https:\u002F\u002Fschema.org","TechArticle","Working with CDF Files","Format-focused guide for inspecting and plotting an unknown time-series CDF (Common Data Format) file. Covers listing variables and attributes with cdflib, identifying the Epoch time variable, converting CDF_EPOCH\u002FTT2000 values to Python datetimes, masking fill values, and plotting with matplotlib. Includes a reusable generic loader and a brief note on ISTP\u002FSPDF metadata conventions.","beginner",[10,11,12,13,14],"cdflib","astropy","matplotlib","numpy","requests","Python",[17,18,19,20,21,10,22,23,24],"CDF","Common Data Format","time series","CDF_EPOCH","CDF_TT2000","ISTP","space physics","heliophysics","## Working with CDF Files\n\nCDF (Common Data Format) is a self-describing binary format developed by NASA, widely used in space physics and heliophysics. A CDF file contains one or more **variables**, each accompanied by metadata **attributes** (units, description, fill value, etc.). Variables are independent arrays; the relationship between them (e.g., which variable is the time axis for another) is expressed through attributes rather than file structure. This playbook shows how to inspect an unfamiliar CDF file, identify the time variable, and plot numeric data against time.\n\n---\n\n### Requirements\n\n```\npip install cdflib astropy matplotlib numpy requests\n```\n\n---\n\n### Step 1: Inspect the file\n\nOpen the CDF and list its contents without loading data into memory.\n\n```python\nimport cdflib\n\npath = \"\u002Fpath\u002Fto\u002Ffile.cdf\"   # or a local path downloaded from a URL\n\ncdf  = cdflib.CDF(path)\ninfo = cdf.cdf_info()\n\nprint(\"Variables :\", info.zVariables)\nprint(\"Global attributes:\", list(info.Attributes))   # or info.Attributes depending on cdflib version\n```\n\nExamine individual variables:\n\n```python\nfor var in info.zVariables:\n    vi = cdf.varinq(var)\n    va = cdf.varattsget(var)\n    dtype = vi.Data_Type_Description\n    shape = vi.Dim_Sizes\n    units = va.get(\"UNITS\", va.get(\"units\", \"—\"))\n    desc  = va.get(\"CATDESC\", va.get(\"FIELDNAM\", \"\"))\n    print(f\"  {var:30s} {dtype:30s} units={units!r:15s} {desc}\")\n```\n\n**Identifying the time variable:** The time axis is usually a variable with data type `CDF_EPOCH`, `CDF_EPOCH16`, or `CDF_TT2000`. It is often named `Epoch` by convention. Check `vi.Data_Type_Description` for these strings, or look for the `VAR_TYPE = 'support_data'` attribute in combination with an epoch data type.\n\n---\n\n### Step 2: Load data and convert time\n\n`cdflib.cdfepoch.to_datetime` converts CDF epoch values to Python `datetime` objects regardless of whether the epoch type is `CDF_EPOCH`, `CDF_EPOCH16`, or `CDF_TT2000`.\n\n```python\nimport numpy as np\nimport cdflib\n\ncdf        = cdflib.CDF(path)\nepoch_raw  = cdf.varget(\"Epoch\")          # adjust variable name if needed\ntimes      = np.array(cdflib.cdfepoch.to_datetime(epoch_raw))\n\n# Load one or more numeric variables\nrate = cdf.varget(\"RATE\")                 # adjust to the variable you need\n```\n\n**Handling fill values:** Many CDF variables define a fill value (`FILLVAL` attribute) that marks missing data. Replace fill values with `NaN` before plotting:\n\n```python\nva   = cdf.varattsget(\"RATE\")\nfill = va.get(\"FILLVAL\")\nif fill is not None:\n    rate = rate.astype(float)\n    rate[rate == fill] = np.nan\n```\n\n---\n\n### Step 3: Plot\n\n```python\nimport matplotlib.pyplot as plt\nimport matplotlib.dates as mdates\n\nfig, ax = plt.subplots(figsize=(12, 4))\nax.plot(times, rate, lw=0.8)\nax.set_xlabel(\"Time (UTC)\")\nax.set_ylabel(va.get(\"UNITS\", \"\"))\nax.set_title(va.get(\"CATDESC\", \"RATE\"))\nax.xaxis.set_major_formatter(mdates.DateFormatter(\"%Y-%m-%d\"))\nfig.autofmt_xdate()\nplt.tight_layout()\nplt.close()\n```\n\n---\n\n### Working with remote files\n\nUse `astropy.utils.data.download_file` to fetch a CDF from a URL and cache it locally so repeated runs avoid re-downloading:\n\n```python\nfrom astropy.utils.data import download_file\nimport cdflib\n\nurl   = \"https:\u002F\u002F...\"\nlocal = download_file(url, cache=True)\ncdf   = cdflib.CDF(local)\n```\n\n---\n\n### Generic helper\n\nThe function below wraps the steps above into a reusable loader:\n\n```python\nimport numpy as np\nimport cdflib\nfrom astropy.utils.data import download_file\n\n\ndef load_cdf(url, time_var=\"Epoch\", value_vars=None):\n    \"\"\"\n    Load a CDF file from a URL (or local path) and return a dict of arrays.\n    time_var  : name of the CDF_EPOCH\u002FTT2000 variable to use as the time axis.\n    value_vars: list of variable names to load; if None, loads all zVariables.\n    \"\"\"\n    local = download_file(url, cache=True) if url.startswith(\"http\") else url\n    cdf   = cdflib.CDF(local)\n    info  = cdf.cdf_info()\n\n    if value_vars is None:\n        value_vars = [v for v in info.zVariables if v != time_var]\n\n    epoch_raw = cdf.varget(time_var)\n    times     = np.array(cdflib.cdfepoch.to_datetime(epoch_raw))\n\n    result = {\"time\": times}\n    for var in value_vars:\n        data = cdf.varget(var).astype(float)\n        va   = cdf.varattsget(var)\n        fill = va.get(\"FILLVAL\")\n        if fill is not None:\n            data[data == fill] = np.nan\n        result[var] = data\n\n    return result\n```\n\nUsage:\n\n```python\nd = load_cdf(\"https:\u002F\u002F...\", time_var=\"Epoch\", value_vars=[\"FLUX\", \"ENERGY\"])\n\nimport matplotlib.pyplot as plt\nfig, ax = plt.subplots()\nax.plot(d[\"time\"], d[\"FLUX\"])\nplt.close()\n```\n\n---\n\n### Note on ISTP\u002FSPDF conventions\n\nMany heliophysics CDF files follow the [ISTP metadata guidelines](https:\u002F\u002Fspdf.gsfc.nasa.gov\u002Fistp_guide\u002Fistp_guide.html). Under these conventions:\n\n- Each data variable has a `DEPEND_0` attribute naming its time variable.\n- `UNITS` holds the physical unit string.\n- `FILLVAL` marks bad\u002Fmissing samples.\n- `VALIDMIN` \u002F `VALIDMAX` give the expected physical range.\n- `VAR_TYPE` distinguishes data (`'data'`), time axes (`'support_data'`), and metadata (`'metadata'`).\n\nYou can use these attributes to automate axis labelling and fill-value masking without hardcoding variable names.\n\n---\n\n### References\n\n- [cdflib documentation](https:\u002F\u002Fcdflib.readthedocs.io\u002F)\n- [CDF Format Description (NASA\u002FGSFC)](https:\u002F\u002Fcdf.gsfc.nasa.gov\u002Fhtml\u002FCDF_docs.html)\n- [ISTP\u002FSPDF Metadata Guidelines](https:\u002F\u002Fspdf.gsfc.nasa.gov\u002Fistp_guide\u002Fistp_guide.html)\n- [astropy.utils.data.download_file](https:\u002F\u002Fdocs.astropy.org\u002Fen\u002Fstable\u002Futils\u002Fdata.html)\n",1780296758055]