Source code for psi_io.data

  1"""
  2Module for fetching HDF5 assets used through examples.
  3
  4This module uses the ``pooch`` library to manage the downloading and caching of
  5HDF4 and HDF5 files that adhere to PSI data conventions. It defines functions to
  6fetch specific example datasets, including 1D radial scale data, 2D coronal hole
  7maps, 3D radial magnetic field data, magnetic fieldline data, and synchronic maps
  8used in coronal and heliospheric magnetic field modeling.
  9
 10Currently, these files are hosted on the PredSci documentation website:
 11at https://www.predsci.com/doc/assets/ and are primarily intended for use in
 12building examples in the PSI I/O and mapflpy packages.
 13"""
 14
 15
 16from __future__ import annotations
 17
 18import inspect
 19from functools import wraps
 20from typing import Callable, ParamSpec, TypeVar
 21
 22from psi_io.psi_io import HdfExtType, HDFEXT
 23
 24try:
 25    import pooch
 26except ImportError as e:
 27    raise ImportError(
 28        "Missing the optional 'pooch' dependency required for data fetching. "
 29        "Please install it via pip or conda to access the necessary datasets."
 30    ) from e
 31
 32
 33REGISTRY = {
 34	"h4h5-files/rscale.h5": "sha256:60a0cbcd4dc69f7d250cbbdddd6fc3680f09d87c1e4cee6a79d8ec3731533718",
 35    "h4h5-files/chmap.h5": "sha256:668b5fe7e86903e6af4effdf65e3d2dd499a1217e93ca60d8b54b68941b6f1f7",
 36    "h4h5-files/fieldline.h5": "sha256:a5b2a1cc0c458d0d9510d8eacc93d3b4a2cc7e99e0a3f86cd3d6b164e74f370d",
 37    "h4h5-files/br.h5": "sha256:2038dc8e67303cf0b31414d532352b40e8c75ebd8917bc8b68614cf4e7b24055",
 38    "h4h5-files/rscale.hdf": "sha256:1c15bd669fc5a92dfdda7dc23703294c23f0a09440599fd5c30cf7a0e1a6f3c4",
 39    "h4h5-files/chmap.hdf": "sha256:fa2f1134aa4f1c9c0dd729b4e8f23f480bea5cb178e44e8da01bdffad09a2225",
 40    "h4h5-files/fieldline.hdf": "sha256:a4149783780e1ce44a8fe76a83c674e0a3082cd78c6a635b6c8e860e0fdd3891",
 41    "h4h5-files/br.hdf": "sha256:3a4b3174e5d6f45244bd25826890486b5659196b8fe093541c542375a88cdf52",
 42    "h4h5-files/synchronic_map.h5": "sha256:170794a5a19684246339ca9782a2b89066b89661400ec48bb6fc0a082e0a2450"
 43}
 44"""Registry of available magnetic field files with their SHA256 hashes. 
 45
 46This registry is used by the pooch fetcher to verify the integrity of
 47downloaded files, and is primarily intended for building sphinx-gallery
 48examples that require MHD data files.
 49"""
 50
 51
 52BASE_URL = "https://www.predsci.com/doc/assets/"
 53"""Base URL hosting magnetic field file assets.
 54"""
 55
 56
 57FETCHER = pooch.create(
 58    path=pooch.os_cache("psi"),
 59    base_url=BASE_URL,
 60    registry=REGISTRY,
 61    env="PSI_IO_CACHE",
 62)
 63"""Pooch fetcher for downloading and caching magnetic field files.
 64
 65.. note::
 66    The cache directory can be overridden by setting the ``PSI_IO_CACHE``
 67    environment variable to a desired path. Otherwise, the default cache
 68    directory is platform-dependent, as determined by :func:`pooch.os_cache`.
 69    
 70.. note::
 71    The default (os-dependent) cache directory stores assets under a
 72    subdirectory named ``psi``. The reason for this naming choice – as opposed
 73    to ``psi_io`` – is to maintain consistency with other PredSci packages
 74    that utilize the same asset hosting and caching mechanism.
 75"""
 76
 77_P = ParamSpec("_P")
 78_R = TypeVar("_R")
 79
[docs] 80def check_hdf_type(func: Callable[_P, _R]) -> Callable[_P, _R]: 81 sig = inspect.signature(func) 82 83 @wraps(func) 84 def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _R: 85 bound = sig.bind(*args, **kwargs) 86 bound.apply_defaults() 87 88 hdf = bound.arguments["hdf"] # assumes the param is literally named "hdf" 89 if hdf not in HDFEXT: 90 raise ValueError(f"Invalid HDF type {hdf!r}. Must be in {sorted(HDFEXT)}.") 91 92 return func(*bound.args, **bound.kwargs) 93 94 return wrapper
95 96
[docs] 97def file_ids() -> list[str]: 98 """List all available magnetic field files in the registry. 99 100 Returns 101 ------- 102 list[str] 103 List of available magnetic field file names. 104 """ 105 return list(FETCHER.registry.keys())
106 107
[docs] 108@check_hdf_type 109def get_1d_data(hdf: HdfExtType = ".h5") -> str: 110 """Fetch the radial scale (1D) data file. 111 112 Parameters 113 ---------- 114 hdf : HdfExtType, optional 115 The HDF file format to fetch, by default "h5". 116 Accepted values are "h5" for HDF5 and "hdf" for HDF4. 117 118 Returns 119 ------- 120 str 121 Path to the downloaded radial scale data file. 122 """ 123 filename = f"h4h5-files/rscale{hdf}" 124 return FETCHER.fetch(filename)
125 126
[docs] 127@check_hdf_type 128def get_2d_data(hdf: HdfExtType = ".h5") -> str: 129 """Fetch the coronal hole map (2D) data file. 130 131 Parameters 132 ---------- 133 hdf : HdfExtType, optional 134 The HDF file format to fetch, by default "h5". 135 Accepted values are "h5" for HDF5 and "hdf" for HDF4. 136 137 Returns 138 ------- 139 str 140 Path to the downloaded coronal hole map data file. 141 """ 142 filename = f"h4h5-files/chmap{hdf}" 143 return FETCHER.fetch(filename)
144 145
[docs] 146@check_hdf_type 147def get_3d_data(hdf: HdfExtType = ".h5") -> str: 148 """Fetch the radial magnetic field (3D) data file. 149 150 Parameters 151 ---------- 152 hdf : HdfExtType, optional 153 The HDF file format to fetch, by default "h5". 154 Accepted values are "h5" for HDF5 and "hdf" for HDF4. 155 156 Returns 157 ------- 158 str 159 Path to the downloaded radial magnetic field data file. 160 """ 161 filename = f"h4h5-files/br{hdf}" 162 return FETCHER.fetch(filename)
163 164
[docs] 165@check_hdf_type 166def get_fieldline_data(hdf: HdfExtType = ".h5") -> str: 167 """Fetch the magnetic fieldline (2D) data file. 168 169 .. warning:: 170 Unlike the other example data files, fieldline data files do not 171 contain scale datasets. 172 173 Parameters 174 ---------- 175 hdf : HdfExtType, optional 176 The HDF file format to fetch, by default "h5". 177 Accepted values are "h5" for HDF5 and "hdf" for HDF4. 178 179 Returns 180 ------- 181 str 182 Path to the downloaded magnetic fieldline data file. 183 """ 184 filename = f"h4h5-files/fieldline{hdf}" 185 return FETCHER.fetch(filename)
186 187
[docs] 188@check_hdf_type 189def get_synchronic_map_data(hdf: HdfExtType = ".h5") -> str: 190 """Fetch the synchronic map data file. 191 192 .. warning:: 193 Synchronic map data is only available in HDF5 format. Furthermore, 194 unlike the other example data files, synchronic map data files contain 195 additional datasets beyond the primary data and scales. 196 197 Parameters 198 ---------- 199 hdf : HdfExtType, optional 200 The HDF file format to fetch, by default "h5". 201 Accepted values are "h5" for HDF5 and "hdf" for HDF4. 202 203 Returns 204 ------- 205 str 206 Path to the downloaded synchronic map data file. 207 """ 208 if hdf == ".hdf": 209 raise NotImplemented("Synchronic map data is only available in HDF5 format.") 210 filename = f"h4h5-files/synchronic_map{hdf}" 211 return FETCHER.fetch(filename)