{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Annotating and Converting the Radial Magnetic Field\n\nRead the radial magnetic field dataset from HDF4, attach physically meaningful\nmetadata, and produce a PSI-convention HDF5 file.\n\nThis example walks through a realistic data-preparation workflow:\n\n1. Read the radial magnetic field (Br) data and its coordinate scales from the\n   example HDF4 file.\n2. Attach attributes that describe the physical quantity, coordinate system, and\n   units using types compatible with both HDF4 and HDF5.\n3. Write an annotated HDF4 file.\n4. Convert that file to HDF5 using :func:`~psi_io.psi_io.convert_psih4_to_psih5`,\n   which preserves the attached attributes in the output.\n\n<div class=\"alert alert-info\"><h4>Note</h4><p>This example can be amended to include additional or domain-specific metadata\n   once the basic pipeline is confirmed to work end-to-end.</p></div>\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import tempfile\nfrom pathlib import Path\nimport numpy as np\nfrom psi_io import read_hdf_data, write_hdf_data, read_hdf_meta, convert_psih4_to_psih5, data"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "**Step 1 \u2013 Read the source HDF4 file**\n\nFetch the example radial magnetic field file and load the primary dataset\ntogether with its (r, \u03b8, \u03c6) coordinate scales:\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "br_filepath = data.get_3d_data(hdf=\".hdf\")\nprint(f\"Source file : {Path(br_filepath).name}\")\n\nbr_data, r, t, p = read_hdf_data(br_filepath)\nprint(f\"\\nData shape : {br_data.shape}  (n\u03c6 \u00d7 n\u03b8 \u00d7 nr, Fortran-ordered)\")\nprint(f\"r scale    : {r.shape},  range = [{r[0]:.4f},  {r[-1]:.4f}]  R\u2609\")\nprint(f\"\u03b8 scale    : {t.shape},  range = [{t[0]:.4f},  {t[-1]:.4f}]  rad\")\nprint(f\"\u03c6 scale    : {p.shape},  range = [{p[0]:.4f}, {p[-1]:.4f}]  rad\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "**Step 2 \u2013 Define the attributes**\n\nAll attribute values are chosen to be compatible with HDF4's SDC type system:\n``float32`` and ``int32`` scalars for numeric quantities, and plain Python\nstrings for descriptive fields. ``float16``, ``int64``, and ``uint64`` are\n**not** supported by HDF4 and must be avoided (see the\n`sphx_glr_gallery_02_writing_files_p02_writing_datasets_with_attributes.py`\nexample for a full discussion of type restrictions):\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "br_attrs = dict(\n    variable=\"br\",\n    long_name=\"Radial Magnetic Field\",\n    coord_system=\"Carrington\",\n    r_units=\"R_sun\",\n    angle_units=\"radians\",\n    b_scale=np.float32(2.2047),     # reference field scale [Gauss]\n    cr_number=np.int32(2190),       # Carrington rotation number\n)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "**Step 3 \u2013 Write an annotated HDF4 file**\n\nPass the attributes as keyword arguments to :func:`~psi_io.psi_io.write_hdf_data`.\nThe dataset identifier is omitted so the PSI-standard name ``'Data-Set-2'`` is\nused, which is required by :func:`~psi_io.psi_io.convert_psih4_to_psih5` in\nthe next step:\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "_tmp = tempfile.TemporaryDirectory()\ntmpdir = Path(_tmp.name)\n\nannotated_hdf = tmpdir / \"br_annotated.hdf\"\nwrite_hdf_data(annotated_hdf, br_data, r, t, p, **br_attrs)\nprint(f\"Annotated HDF4 written : {annotated_hdf.name}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "**Step 4 \u2013 Convert to PSI-convention HDF5**\n\n:func:`~psi_io.psi_io.convert_psih4_to_psih5` reads ``'Data-Set-2'`` from the\nHDF4 file, remaps it to ``'Data'``, and carries over the attached attributes:\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "annotated_h5 = tmpdir / \"br_annotated.h5\"\nconvert_psih4_to_psih5(annotated_hdf, annotated_h5)\nprint(f\"Converted to HDF5      : {annotated_h5.name}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "**Step 5 \u2013 Verify the round-trip**\n\nConfirm that the dataset, scales, and all attributes survived the write-and-convert\npipeline intact:\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "meta = read_hdf_meta(annotated_h5)\nprint(f\"\\nDataset : {meta[0].name!r}  shape={meta[0].shape}  dtype={meta[0].type}\")\n\nprint(\"\\nAttributes:\")\nfor key, val in meta[0].attr.items():\n    print(f\"  {key:<16}: {val!r}\")\n\nprint(\"\\nScales:\")\nfor s in meta[0].scales:\n    print(f\"  {s.name!r:<8} shape={s.shape}  \"\n          f\"range=[{s.imin:.4f}, {s.imax:.4f}]\")\n\n_tmp.cleanup()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.13.9"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}