bbf 0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
bbf-0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Nicolas Regnault
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
bbf-0.1/PKG-INFO ADDED
@@ -0,0 +1,298 @@
1
+ Metadata-Version: 2.1
2
+ Name: bbf
3
+ Version: 0.1
4
+ Summary: Fast computation of broadband fluxes and mags
5
+ Home-page: https://gitlab.in2p3.fr/lemaitre/bbf
6
+ Author: Nicolas Regnault
7
+ Author-email: nicolas.regnault@lpnhe.in2p3.fr
8
+ License: Apache Software License
9
+ Keywords: astronomy,astrophysics
10
+ Classifier: Development Status :: 2 - Pre-Alpha
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
15
+ Classifier: Topic :: Scientific/Engineering :: Physics
16
+ Requires-Python: >=3.8
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: importlib_resources; python_version < "3.9"
20
+ Requires-Dist: numpy
21
+ Requires-Dist: pandas
22
+ Requires-Dist: scipy
23
+ Requires-Dist: scikit-sparse
24
+ Requires-Dist: mkl
25
+ Requires-Dist: sparse_dot_mkl
26
+ Requires-Dist: matplotlib
27
+ Requires-Dist: platformdirs
28
+ Requires-Dist: sncosmo
29
+ Requires-Dist: astropy
30
+ Requires-Dist: getCalspec
31
+
32
+
33
+
34
+ # Broadband fluxes (`bbf`)
35
+
36
+ A module to evaluate the broadband fluxes and magnitudes of spectrophotometric standards.
37
+
38
+ `bbf` relies on a modified version of `sncosmo` for passbands and magsys definition.
39
+
40
+
41
+ # Installation
42
+
43
+ ## virtual environments
44
+
45
+ It is generally a good idea to work in a virtual environment. You may use either
46
+ a classical `venv`, or you may opt for a `anaconda` / Miniconda / `mamba` environment.
47
+
48
+ Since `bbf` relies on cholmod, which is part of suitesparse, we recommend using
49
+ `conda` which comes with a compiled version of suitesparse. `venv` is also a
50
+ perfectly suitable option if suitesparse is already installed on your machine,
51
+ or if you are ready to compile it yourself.
52
+
53
+
54
+ ### venv
55
+
56
+ As a reminder, a `venv` is created as follows:
57
+
58
+ ``` bash
59
+ python -m venv lemaitre
60
+ ```
61
+ and activated with:
62
+
63
+ ``` bash
64
+ source lemaitre/bin/activate
65
+ ```
66
+
67
+ This `venv` is called `lemaitre` but you may pick anyname you like.
68
+
69
+ ### conda / mamba
70
+
71
+ To create a Miniconda / Conda / Mamba virtual environment (called `lemaitre` in
72
+ this example, but you may pick another name):
73
+
74
+ ``` bash
75
+ conda create -n lemaitre
76
+ ```
77
+
78
+ and activated with:
79
+
80
+ ``` bash
81
+ conda activate lemaitre
82
+ ```
83
+
84
+
85
+ ## Prerequisites
86
+
87
+ A few packages are required. If you work with conda, you may install them with:
88
+
89
+ ``` bash
90
+ mamba install ipython numpy matplotlib scikit-sparse scipy jupyter pandas mkl sparse_dot_mkl h5py fastparquet pyarrow
91
+ ```
92
+
93
+
94
+ ### sncosmo
95
+
96
+ Until our changes are merged in sncosmo, we use a modified version of it:
97
+
98
+ ``` bash
99
+ git clone https://github.com/nregnault/sncosmo.git
100
+ cd sncosmo
101
+ pip install .
102
+ ```
103
+
104
+ ### latest Lemaitre bandpasses
105
+
106
+ If you plan to use the latest version of the megacam6, ztf and hsc passbands,
107
+ use the `lemaitre.bandpasses` package:
108
+
109
+ ``` bash
110
+ git clone https://gitlab.in2p3.fr/lemaitre/lemaitre/bandpasses
111
+ # or alternatively
112
+ git clone git@gitlab.in2p3.fr:lemaitre/bbf.git
113
+ ```
114
+
115
+ The `lemaitre.bandpasses` repository comes with moderately large data files,
116
+ whose history is not tracked by git. They are managed using git-lfs (large file
117
+ storage). git-lfs has been packaged for all major distributions. It is also
118
+ available from Homebrew.
119
+
120
+ To retrieve the data files:
121
+
122
+ ``` bash
123
+ cd bandpasses/
124
+ git lfs pull
125
+ ```
126
+
127
+ And to install the code:
128
+
129
+ ``` bash
130
+ cd bandpasses
131
+ pip install .
132
+ ```
133
+
134
+ or `pip install -e .` to install in editable mode (if you intend to hack the code).
135
+
136
+ ## Installing the `bbf` package:
137
+
138
+ ``` bash
139
+ git clone https://gitlab.in2p3.fr/lemaitre/lemaitre/bbf
140
+ # or alternatively
141
+ git clone git@gitlab.in2p3.fr:lemaitre/bbf
142
+
143
+ cd bbf
144
+ pip install .
145
+ ```
146
+
147
+ (or `pip install -e . ` to install in editable mode).
148
+
149
+ # Getting started
150
+
151
+ The goal of `bbf` is to efficiently compute broadband fluxes and magnitudes, i.e. quantities
152
+ of the form:
153
+
154
+ $$f_{xys} = \int S(\lambda) \lambda T_{xys}(\lambda) d\lambda$$
155
+
156
+ where $\lambda$ is the SED of an object, $T_{xyz}(\lambda)$ is the bandpass of
157
+ the instrument used to observe it. $T$ may depend on the focal plane position of
158
+ the object and, if the focal plane is a mosaic of sensors, on the specific
159
+ sensor $s$ where the observation is made. In practice, $x,y$ are coordinates, in
160
+ pixels, in the sensor frame, and $s$ is a unique sensor index (or amplifier
161
+ index).
162
+
163
+ Computing magnitudes requires an additional ingredient: the flux of a reference
164
+ spectrum $S_{ref}(\lambda)$, usually the AB spectrum, integrated in the same
165
+ passband (same sensor, same position).
166
+
167
+ $$m = -2.5 \log_{10} \left(\frac{\int S(\lambda) \lambda T_{xyz}(\lambda) d\lambda}{\int S_{ref}(\lambda) \lambda T_{xyz}(\lambda) d\lambda}\right)$$
168
+
169
+ To compute these integrales, `bbf` uses the technique implemented in `nacl`,
170
+ which consists in projecting the bandpasses and SED on spline bases:
171
+
172
+ $$S(\lambda) = \sum_i \theta_i {\cal B}_i(\lambda)$$
173
+
174
+ and
175
+
176
+ $$T(\lambda) = \sum_j t_j {\cal B}_j(\lambda)$$
177
+
178
+ If we precompute the products $G_{ij} = \int \lambda {\cal B}_i(\lambda)_{\cal B}_j(\lambda) d\lambda$
179
+ the integrals above can be expressed as a simple contraction:
180
+
181
+ $$f = \theta_i G_{ij} t_j$$
182
+
183
+ where $G$ is very sparse, since the B-Splines ${\cal B}_i$ have a compact
184
+ support. If the bandpass $T$ is spatially variable, the $t_j$ coefficients are
185
+ themselves developped on a spatial spline basis.
186
+
187
+ $$t_j = \sum_{kj} \tau_{kj} {\cal K}(x,y)$$
188
+
189
+ The contraction above is then of the form:
190
+
191
+
192
+
193
+ ## FilterSets and StellarLibs
194
+
195
+ `bbf` implements two main kind of objects: `FilterLib`, which holds a set of
196
+ band passes, projected on spline bases (${\cal K_j(x,y)}$ and ${\cal
197
+ B}_i_(\lambda)$), and `StellarLib` which manages a set of spectra, also
198
+ projected on a spline basis (not necessily the splines used for the filters).
199
+
200
+
201
+ ## Loading a filter lib
202
+
203
+ Building a complete version of a `FilterLib` requires some care. The standard
204
+ `FilterLib` used in the Lemaître analysis is build and maintained within the
205
+ package `lemaitre.bandpasses`. To access it:
206
+
207
+ ``` python
208
+ from lemaitre import bandpasses
209
+
210
+ flib = bandpasses.get_filterlib()
211
+ ```
212
+ The first time this function is called, the `FilterLib`` is built and cached. The subsequent calls
213
+ access the cached version, and never take more than a few milliseconds.
214
+
215
+ ## Loading Stellar Libraries
216
+
217
+ As of today, `bbf` implements two kinds of StellarLibs: pickles and Calspec. An
218
+ interface to gaiaXP is in development.
219
+
220
+ To load the pickles library:
221
+
222
+ ``` python
223
+
224
+ import bbf.stellarlib.pickles
225
+ pickles = bbf.stellarlib.pickles.fetch()
226
+ ```
227
+
228
+ To load the most recent version of Calspec:
229
+
230
+ ``` python
231
+ import bbf.stellarlib.calspec
232
+ calspec = bbf.stellarlib.calspec.fetch()
233
+ ```
234
+
235
+
236
+ ## Computing Broadband fluxes
237
+
238
+ With a `FilterSet` and a `StellarLib` in hand, one can compute broadband fluxes and broadband mags.
239
+
240
+ ### Broadband fluxes
241
+
242
+ ``` python
243
+ import bbf.stellarlib.pickles
244
+ from lemaitre import bandpasses
245
+
246
+ flib = bandpasses.get_filterlib()
247
+ pickles = bbf.stellarlib.pickles.fetch()
248
+
249
+ # number of measurements
250
+ nmeas = 100_000
251
+
252
+ # which stars ?
253
+ star = np.random.choice(np.arange(0, len(pickles)), size=nmeas)
254
+
255
+ # in which band ?
256
+ band = np.random.choice(['ztf::g', 'ztf::r', 'ztf::I'], size=nmeas)
257
+
258
+ # observation positions
259
+ x = np.random.uniform(0., 3072., size=nmeas)
260
+ y = np.random.uniform(0., 3080., size=nmeas)
261
+ sensor_id = np.random.choice(np.arange(1, 65), size=nmeas)
262
+
263
+ fluxes = flib.flux(pickles, star, band, x=x, y=y, sensor_id=sensor_id)
264
+ ```
265
+
266
+
267
+ ### Broadband magnitudes
268
+
269
+ To convert broadband fluxes into broadband magnitudes, we need to compute the reference fluxes,
270
+ in the same effective measurement band passes. This is done using an auxiliary object called `MagSys`:
271
+
272
+ ``` python
273
+
274
+ from bbf.magsys import SpecMagSys
275
+ import bbf.stellarlib.pickles
276
+ from lemaitre import bandpasses
277
+
278
+ flib = bandpasses.get_filterlib()
279
+ pickles = bbf.stellarlib.pickles.fetch()
280
+
281
+ # number of measurements
282
+ nmeas = 100_000
283
+
284
+ # which stars ?
285
+ star = np.random.choice(np.arange(0, len(pickles)), size=nmeas)
286
+
287
+ # in which band ?
288
+ band = np.random.choice(['ztf::g', 'ztf::r', 'ztf::I'], size=nmeas)
289
+
290
+ # observation positions
291
+ x = np.random.uniform(0., 3072., size=nmeas)
292
+ y = np.random.uniform(0., 3080., size=nmeas)
293
+ sensor_id = np.random.choice(np.arange(1, 65), size=nmeas)
294
+
295
+ ms = SpecMagSys('AB')
296
+ mags = ms.mag(pickles, star, band, x=x, y=y, sensor_id=sensor_id)
297
+ ```
298
+
bbf-0.1/README.md ADDED
@@ -0,0 +1,267 @@
1
+
2
+
3
+ # Broadband fluxes (`bbf`)
4
+
5
+ A module to evaluate the broadband fluxes and magnitudes of spectrophotometric standards.
6
+
7
+ `bbf` relies on a modified version of `sncosmo` for passbands and magsys definition.
8
+
9
+
10
+ # Installation
11
+
12
+ ## virtual environments
13
+
14
+ It is generally a good idea to work in a virtual environment. You may use either
15
+ a classical `venv`, or you may opt for a `anaconda` / Miniconda / `mamba` environment.
16
+
17
+ Since `bbf` relies on cholmod, which is part of suitesparse, we recommend using
18
+ `conda` which comes with a compiled version of suitesparse. `venv` is also a
19
+ perfectly suitable option if suitesparse is already installed on your machine,
20
+ or if you are ready to compile it yourself.
21
+
22
+
23
+ ### venv
24
+
25
+ As a reminder, a `venv` is created as follows:
26
+
27
+ ``` bash
28
+ python -m venv lemaitre
29
+ ```
30
+ and activated with:
31
+
32
+ ``` bash
33
+ source lemaitre/bin/activate
34
+ ```
35
+
36
+ This `venv` is called `lemaitre` but you may pick anyname you like.
37
+
38
+ ### conda / mamba
39
+
40
+ To create a Miniconda / Conda / Mamba virtual environment (called `lemaitre` in
41
+ this example, but you may pick another name):
42
+
43
+ ``` bash
44
+ conda create -n lemaitre
45
+ ```
46
+
47
+ and activated with:
48
+
49
+ ``` bash
50
+ conda activate lemaitre
51
+ ```
52
+
53
+
54
+ ## Prerequisites
55
+
56
+ A few packages are required. If you work with conda, you may install them with:
57
+
58
+ ``` bash
59
+ mamba install ipython numpy matplotlib scikit-sparse scipy jupyter pandas mkl sparse_dot_mkl h5py fastparquet pyarrow
60
+ ```
61
+
62
+
63
+ ### sncosmo
64
+
65
+ Until our changes are merged in sncosmo, we use a modified version of it:
66
+
67
+ ``` bash
68
+ git clone https://github.com/nregnault/sncosmo.git
69
+ cd sncosmo
70
+ pip install .
71
+ ```
72
+
73
+ ### latest Lemaitre bandpasses
74
+
75
+ If you plan to use the latest version of the megacam6, ztf and hsc passbands,
76
+ use the `lemaitre.bandpasses` package:
77
+
78
+ ``` bash
79
+ git clone https://gitlab.in2p3.fr/lemaitre/lemaitre/bandpasses
80
+ # or alternatively
81
+ git clone git@gitlab.in2p3.fr:lemaitre/bbf.git
82
+ ```
83
+
84
+ The `lemaitre.bandpasses` repository comes with moderately large data files,
85
+ whose history is not tracked by git. They are managed using git-lfs (large file
86
+ storage). git-lfs has been packaged for all major distributions. It is also
87
+ available from Homebrew.
88
+
89
+ To retrieve the data files:
90
+
91
+ ``` bash
92
+ cd bandpasses/
93
+ git lfs pull
94
+ ```
95
+
96
+ And to install the code:
97
+
98
+ ``` bash
99
+ cd bandpasses
100
+ pip install .
101
+ ```
102
+
103
+ or `pip install -e .` to install in editable mode (if you intend to hack the code).
104
+
105
+ ## Installing the `bbf` package:
106
+
107
+ ``` bash
108
+ git clone https://gitlab.in2p3.fr/lemaitre/lemaitre/bbf
109
+ # or alternatively
110
+ git clone git@gitlab.in2p3.fr:lemaitre/bbf
111
+
112
+ cd bbf
113
+ pip install .
114
+ ```
115
+
116
+ (or `pip install -e . ` to install in editable mode).
117
+
118
+ # Getting started
119
+
120
+ The goal of `bbf` is to efficiently compute broadband fluxes and magnitudes, i.e. quantities
121
+ of the form:
122
+
123
+ $$f_{xys} = \int S(\lambda) \lambda T_{xys}(\lambda) d\lambda$$
124
+
125
+ where $\lambda$ is the SED of an object, $T_{xyz}(\lambda)$ is the bandpass of
126
+ the instrument used to observe it. $T$ may depend on the focal plane position of
127
+ the object and, if the focal plane is a mosaic of sensors, on the specific
128
+ sensor $s$ where the observation is made. In practice, $x,y$ are coordinates, in
129
+ pixels, in the sensor frame, and $s$ is a unique sensor index (or amplifier
130
+ index).
131
+
132
+ Computing magnitudes requires an additional ingredient: the flux of a reference
133
+ spectrum $S_{ref}(\lambda)$, usually the AB spectrum, integrated in the same
134
+ passband (same sensor, same position).
135
+
136
+ $$m = -2.5 \log_{10} \left(\frac{\int S(\lambda) \lambda T_{xyz}(\lambda) d\lambda}{\int S_{ref}(\lambda) \lambda T_{xyz}(\lambda) d\lambda}\right)$$
137
+
138
+ To compute these integrales, `bbf` uses the technique implemented in `nacl`,
139
+ which consists in projecting the bandpasses and SED on spline bases:
140
+
141
+ $$S(\lambda) = \sum_i \theta_i {\cal B}_i(\lambda)$$
142
+
143
+ and
144
+
145
+ $$T(\lambda) = \sum_j t_j {\cal B}_j(\lambda)$$
146
+
147
+ If we precompute the products $G_{ij} = \int \lambda {\cal B}_i(\lambda)_{\cal B}_j(\lambda) d\lambda$
148
+ the integrals above can be expressed as a simple contraction:
149
+
150
+ $$f = \theta_i G_{ij} t_j$$
151
+
152
+ where $G$ is very sparse, since the B-Splines ${\cal B}_i$ have a compact
153
+ support. If the bandpass $T$ is spatially variable, the $t_j$ coefficients are
154
+ themselves developped on a spatial spline basis.
155
+
156
+ $$t_j = \sum_{kj} \tau_{kj} {\cal K}(x,y)$$
157
+
158
+ The contraction above is then of the form:
159
+
160
+
161
+
162
+ ## FilterSets and StellarLibs
163
+
164
+ `bbf` implements two main kind of objects: `FilterLib`, which holds a set of
165
+ band passes, projected on spline bases (${\cal K_j(x,y)}$ and ${\cal
166
+ B}_i_(\lambda)$), and `StellarLib` which manages a set of spectra, also
167
+ projected on a spline basis (not necessily the splines used for the filters).
168
+
169
+
170
+ ## Loading a filter lib
171
+
172
+ Building a complete version of a `FilterLib` requires some care. The standard
173
+ `FilterLib` used in the Lemaître analysis is build and maintained within the
174
+ package `lemaitre.bandpasses`. To access it:
175
+
176
+ ``` python
177
+ from lemaitre import bandpasses
178
+
179
+ flib = bandpasses.get_filterlib()
180
+ ```
181
+ The first time this function is called, the `FilterLib`` is built and cached. The subsequent calls
182
+ access the cached version, and never take more than a few milliseconds.
183
+
184
+ ## Loading Stellar Libraries
185
+
186
+ As of today, `bbf` implements two kinds of StellarLibs: pickles and Calspec. An
187
+ interface to gaiaXP is in development.
188
+
189
+ To load the pickles library:
190
+
191
+ ``` python
192
+
193
+ import bbf.stellarlib.pickles
194
+ pickles = bbf.stellarlib.pickles.fetch()
195
+ ```
196
+
197
+ To load the most recent version of Calspec:
198
+
199
+ ``` python
200
+ import bbf.stellarlib.calspec
201
+ calspec = bbf.stellarlib.calspec.fetch()
202
+ ```
203
+
204
+
205
+ ## Computing Broadband fluxes
206
+
207
+ With a `FilterSet` and a `StellarLib` in hand, one can compute broadband fluxes and broadband mags.
208
+
209
+ ### Broadband fluxes
210
+
211
+ ``` python
212
+ import bbf.stellarlib.pickles
213
+ from lemaitre import bandpasses
214
+
215
+ flib = bandpasses.get_filterlib()
216
+ pickles = bbf.stellarlib.pickles.fetch()
217
+
218
+ # number of measurements
219
+ nmeas = 100_000
220
+
221
+ # which stars ?
222
+ star = np.random.choice(np.arange(0, len(pickles)), size=nmeas)
223
+
224
+ # in which band ?
225
+ band = np.random.choice(['ztf::g', 'ztf::r', 'ztf::I'], size=nmeas)
226
+
227
+ # observation positions
228
+ x = np.random.uniform(0., 3072., size=nmeas)
229
+ y = np.random.uniform(0., 3080., size=nmeas)
230
+ sensor_id = np.random.choice(np.arange(1, 65), size=nmeas)
231
+
232
+ fluxes = flib.flux(pickles, star, band, x=x, y=y, sensor_id=sensor_id)
233
+ ```
234
+
235
+
236
+ ### Broadband magnitudes
237
+
238
+ To convert broadband fluxes into broadband magnitudes, we need to compute the reference fluxes,
239
+ in the same effective measurement band passes. This is done using an auxiliary object called `MagSys`:
240
+
241
+ ``` python
242
+
243
+ from bbf.magsys import SpecMagSys
244
+ import bbf.stellarlib.pickles
245
+ from lemaitre import bandpasses
246
+
247
+ flib = bandpasses.get_filterlib()
248
+ pickles = bbf.stellarlib.pickles.fetch()
249
+
250
+ # number of measurements
251
+ nmeas = 100_000
252
+
253
+ # which stars ?
254
+ star = np.random.choice(np.arange(0, len(pickles)), size=nmeas)
255
+
256
+ # in which band ?
257
+ band = np.random.choice(['ztf::g', 'ztf::r', 'ztf::I'], size=nmeas)
258
+
259
+ # observation positions
260
+ x = np.random.uniform(0., 3072., size=nmeas)
261
+ y = np.random.uniform(0., 3080., size=nmeas)
262
+ sensor_id = np.random.choice(np.arange(1, 65), size=nmeas)
263
+
264
+ ms = SpecMagSys('AB')
265
+ mags = ms.mag(pickles, star, band, x=x, y=y, sensor_id=sensor_id)
266
+ ```
267
+
@@ -0,0 +1,62 @@
1
+ """
2
+ """
3
+
4
+ import os
5
+ from pathlib import Path
6
+
7
+ import numpy as np
8
+
9
+ # import sncosmo
10
+
11
+ from .filterlib import FilterLib
12
+ from .stellarlib import StellarLib
13
+ from .snfilterset import SNFilterSet
14
+ from .magsys import *
15
+ from .bspline import lgram
16
+
17
+
18
+ __version__ = "0.1"
19
+
20
+ __all__ = ['FilterLib', 'StellarLib', 'SpecMagsys', 'SNFilterSet', 'SNMagSys']
21
+
22
+
23
+ def get_cache_dir():
24
+ """return a default location for caching stuff
25
+ """
26
+ import platformdirs
27
+
28
+ # environment variable overrides default platformdirs
29
+ cache_dir = os.environ.get('BBF_CACHE_DIR')
30
+
31
+ if cache_dir is None:
32
+ cache_dir = Path(platformdirs.user_cache_dir('bbf'))
33
+ else:
34
+ cache_dir = Path(cache_dir)
35
+
36
+ if not cache_dir.is_dir():
37
+ if cache_dir.exists():
38
+ raise RuntimeError(f"{cache_dir} not a directory")
39
+ cache_dir.mkdir(parents=True)
40
+
41
+ return cache_dir
42
+
43
+
44
+ def get_data_dir():
45
+ """return a default location for storing stuff
46
+ """
47
+ import platformdirs
48
+
49
+ # environment variable overrides platformdirs
50
+ data_dir = os.environ.get('BBF_DATA_DIR')
51
+
52
+ if data_dir is None:
53
+ data_dir = Path(platformdirs.user_data_dir('bbf'))
54
+ else:
55
+ data_dir = Path(data_dir)
56
+
57
+ if not data_dir.is_dir():
58
+ if data_dir.exists():
59
+ raise RuntimeError(f"{data_dir} not a directory")
60
+ data_dir.mkdir(parents=True)
61
+
62
+ return data_dir