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)