py-lfkit 0.1.4__py3-none-any.whl
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.
- lfkit/__init__.py +19 -0
- lfkit/_version.py +24 -0
- lfkit/api/__init__.py +0 -0
- lfkit/api/corrections.py +308 -0
- lfkit/api/lumfunc.py +914 -0
- lfkit/corrections/__init__.py +0 -0
- lfkit/corrections/color_anchors.py +176 -0
- lfkit/corrections/filters.py +185 -0
- lfkit/corrections/kcorrect_backend.py +149 -0
- lfkit/corrections/kcorrect_from_color.py +111 -0
- lfkit/corrections/kcorrect_grids.py +242 -0
- lfkit/corrections/poggianti1997.py +386 -0
- lfkit/corrections/responses.py +183 -0
- lfkit/cosmo/__init__.py +0 -0
- lfkit/cosmo/cosmology.py +211 -0
- lfkit/data/demo_catalogs/fake_magnitude_limited_catalog.csv +201 -0
- lfkit/data/kcorrect/grids/kcorrect__bessell__z0.0000_4.0__Nz801__bsnone.npz +0 -0
- lfkit/data/kcorrect/grids/kcorrect__decam__z0.0000_4.0__Nz801__bsnone.npz +0 -0
- lfkit/data/kcorrect/grids/kcorrect__sdss__z0.0000_4.0__Nz801__bsnone.npz +0 -0
- lfkit/data/kcorrect/grids/kcorrect__subaru_suprimecam__z0.0000_4.0__Nz801__bsnone.npz +0 -0
- lfkit/data/poggianti1997/__init__.py +0 -0
- lfkit/data/poggianti1997/ecorr.csv +603 -0
- lfkit/data/poggianti1997/filters.csv +516 -0
- lfkit/data/poggianti1997/kcorr.csv +490 -0
- lfkit/data/poggianti1997/kcorrv.csv +37 -0
- lfkit/data/poggianti1997/sed.csv +295 -0
- lfkit/photometry/__init__.py +0 -0
- lfkit/photometry/catalog_completeness.py +381 -0
- lfkit/photometry/lf_integrals.py +500 -0
- lfkit/photometry/lf_parameter_models.py +386 -0
- lfkit/photometry/lf_redshift_density.py +238 -0
- lfkit/photometry/luminosities.py +426 -0
- lfkit/photometry/luminosity_function.py +707 -0
- lfkit/photometry/magnitudes.py +214 -0
- lfkit/utils/__init__.py +0 -0
- lfkit/utils/download_poggianti97_data.py +70 -0
- lfkit/utils/evaluators.py +104 -0
- lfkit/utils/interpolation.py +216 -0
- lfkit/utils/io.py +240 -0
- lfkit/utils/types.py +27 -0
- lfkit/utils/units.py +160 -0
- lfkit/utils/validators.py +63 -0
- py_lfkit-0.1.4.dist-info/METADATA +94 -0
- py_lfkit-0.1.4.dist-info/RECORD +47 -0
- py_lfkit-0.1.4.dist-info/WHEEL +5 -0
- py_lfkit-0.1.4.dist-info/licenses/LICENSE +21 -0
- py_lfkit-0.1.4.dist-info/top_level.txt +1 -0
lfkit/api/lumfunc.py
ADDED
|
@@ -0,0 +1,914 @@
|
|
|
1
|
+
r"""Public luminosity-function interface.
|
|
2
|
+
|
|
3
|
+
This module provides the user-facing :class:`LuminosityFunction` API for
|
|
4
|
+
evaluating luminosity functions in absolute- or apparent-magnitude space.
|
|
5
|
+
|
|
6
|
+
The class wraps the lower-level LFKit photometry functions behind a small,
|
|
7
|
+
stable interface. Users can construct standard, evolving, or double Schechter
|
|
8
|
+
models, evaluate :math:`\phi(M, z)`, evaluate from apparent magnitudes, and
|
|
9
|
+
compute integrated, observed, and missing number densities for
|
|
10
|
+
magnitude-limited catalog selections.
|
|
11
|
+
|
|
12
|
+
File reading is intentionally not handled here. Catalog-derived LF parameters,
|
|
13
|
+
magnitude limits, or correction models should be loaded elsewhere and passed
|
|
14
|
+
into this API as scalars, arrays, or correction objects.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from collections.abc import Callable, Mapping
|
|
20
|
+
from typing import TYPE_CHECKING
|
|
21
|
+
|
|
22
|
+
import numpy as np
|
|
23
|
+
|
|
24
|
+
from lfkit.photometry.luminosity_function import (
|
|
25
|
+
schechter,
|
|
26
|
+
schechter_evolving,
|
|
27
|
+
schechter_double,
|
|
28
|
+
schechter_from_m,
|
|
29
|
+
schechter_evolving_from_m,
|
|
30
|
+
schechter_double_from_m,
|
|
31
|
+
)
|
|
32
|
+
from lfkit.photometry.magnitudes import (
|
|
33
|
+
absolute_magnitude,
|
|
34
|
+
absolute_magnitude_from_luminosity_distance,
|
|
35
|
+
apparent_magnitude,
|
|
36
|
+
apparent_magnitude_from_luminosity_distance,
|
|
37
|
+
)
|
|
38
|
+
from lfkit.photometry.lf_integrals import (
|
|
39
|
+
cumulative_number_density,
|
|
40
|
+
integrated_luminosity_density,
|
|
41
|
+
integrated_number_density,
|
|
42
|
+
lf_weighted_integral,
|
|
43
|
+
mean_luminosity,
|
|
44
|
+
selection_weighted_number_density,
|
|
45
|
+
)
|
|
46
|
+
from lfkit.photometry.lf_parameter_models import (
|
|
47
|
+
available_lf_parameter_models,
|
|
48
|
+
evaluate_lf_parameters,
|
|
49
|
+
register_alpha_model,
|
|
50
|
+
register_m_star_model,
|
|
51
|
+
register_phi_star_model,
|
|
52
|
+
)
|
|
53
|
+
from lfkit.photometry.lf_redshift_density import (
|
|
54
|
+
lf_integrated_number_density,
|
|
55
|
+
lf_weighted_redshift_density,
|
|
56
|
+
)
|
|
57
|
+
from lfkit.photometry.catalog_completeness import (
|
|
58
|
+
absolute_magnitude_limit,
|
|
59
|
+
catalog_completeness_fraction,
|
|
60
|
+
out_of_catalog_fraction,
|
|
61
|
+
observed_number_density,
|
|
62
|
+
missing_number_density,
|
|
63
|
+
)
|
|
64
|
+
from lfkit.utils.types import (
|
|
65
|
+
Cosmology,
|
|
66
|
+
FloatArray,
|
|
67
|
+
FloatInput,
|
|
68
|
+
ParameterModel,
|
|
69
|
+
ParameterValue,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
if TYPE_CHECKING:
|
|
73
|
+
from lfkit.api.corrections import Corrections
|
|
74
|
+
else:
|
|
75
|
+
Corrections = object
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
__all__ = ["LuminosityFunction"]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class LuminosityFunction:
|
|
82
|
+
"""User-facing wrapper for luminosity-function evaluation."""
|
|
83
|
+
|
|
84
|
+
def __init__(
|
|
85
|
+
self,
|
|
86
|
+
*,
|
|
87
|
+
model: str,
|
|
88
|
+
parameters: Mapping[str, object],
|
|
89
|
+
meta: Mapping[str, object] | None = None,
|
|
90
|
+
) -> None:
|
|
91
|
+
"""Store a luminosity-function model and its parameters.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
model: Name of the luminosity-function model.
|
|
95
|
+
parameters: Model parameters passed to the underlying LF function.
|
|
96
|
+
meta: Optional metadata describing the LF source or calibration.
|
|
97
|
+
"""
|
|
98
|
+
self.model = str(model)
|
|
99
|
+
self.parameters_dict = dict(parameters)
|
|
100
|
+
self.meta = {} if meta is None else dict(meta)
|
|
101
|
+
|
|
102
|
+
def absolute_magnitude(
|
|
103
|
+
self,
|
|
104
|
+
cosmo_obj: Cosmology,
|
|
105
|
+
z: FloatInput,
|
|
106
|
+
apparent_mag: FloatInput,
|
|
107
|
+
*,
|
|
108
|
+
h: float | None = None,
|
|
109
|
+
corrections: Corrections | None = None,
|
|
110
|
+
) -> FloatArray:
|
|
111
|
+
"""Convert apparent magnitude to absolute magnitude.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
cosmo_obj: Cosmology object used for distance-modulus conversion.
|
|
115
|
+
z: Redshift values.
|
|
116
|
+
apparent_mag: Apparent magnitude values.
|
|
117
|
+
h: Optional reduced Hubble parameter used in the magnitude conversion.
|
|
118
|
+
corrections: Optional object providing k-correction and e-correction values.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Absolute magnitudes using the LFKit convention
|
|
122
|
+
``M = m - mu - K + E``.
|
|
123
|
+
"""
|
|
124
|
+
k_corr, e_corr = self._correction_values(corrections, z)
|
|
125
|
+
|
|
126
|
+
return absolute_magnitude(
|
|
127
|
+
cosmo_obj,
|
|
128
|
+
z,
|
|
129
|
+
apparent_mag,
|
|
130
|
+
h=h,
|
|
131
|
+
k_correction=k_corr,
|
|
132
|
+
e_correction=e_corr,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
def apparent_magnitude(
|
|
136
|
+
self,
|
|
137
|
+
cosmo_obj: Cosmology,
|
|
138
|
+
z: FloatInput,
|
|
139
|
+
absolute_mag: FloatInput,
|
|
140
|
+
*,
|
|
141
|
+
h: float | None = None,
|
|
142
|
+
corrections: Corrections | None = None,
|
|
143
|
+
) -> FloatArray:
|
|
144
|
+
"""Convert absolute magnitude to apparent magnitude.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
cosmo_obj: Cosmology object used for distance-modulus conversion.
|
|
148
|
+
z: Redshift values.
|
|
149
|
+
absolute_mag: Absolute magnitude values.
|
|
150
|
+
h: Optional reduced Hubble parameter used in the magnitude conversion.
|
|
151
|
+
corrections: Optional object providing k-correction and e-correction values.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
Apparent magnitudes using the LFKit convention
|
|
155
|
+
``m = M + mu + K - E``.
|
|
156
|
+
"""
|
|
157
|
+
k_corr, e_corr = self._correction_values(corrections, z)
|
|
158
|
+
|
|
159
|
+
return apparent_magnitude(
|
|
160
|
+
cosmo_obj,
|
|
161
|
+
z,
|
|
162
|
+
absolute_mag,
|
|
163
|
+
h=h,
|
|
164
|
+
k_correction=k_corr,
|
|
165
|
+
e_correction=e_corr,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
def absolute_magnitude_from_luminosity_distance(
|
|
169
|
+
self,
|
|
170
|
+
apparent_mag: FloatInput,
|
|
171
|
+
luminosity_distance_mpc: FloatInput,
|
|
172
|
+
*,
|
|
173
|
+
z: FloatInput,
|
|
174
|
+
corrections: Corrections | None = None,
|
|
175
|
+
) -> FloatArray:
|
|
176
|
+
"""Convert apparent magnitude to absolute magnitude from luminosity distance.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
apparent_mag: Apparent magnitude values.
|
|
180
|
+
luminosity_distance_mpc: Luminosity distance values in Mpc.
|
|
181
|
+
corrections: Optional object providing k-correction and e-correction values.
|
|
182
|
+
z: Redshift values where corrections are evaluated.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
Absolute magnitudes using ``M = m - mu - K + E``.
|
|
186
|
+
"""
|
|
187
|
+
k_corr, e_corr = self._correction_values(corrections, z)
|
|
188
|
+
|
|
189
|
+
return absolute_magnitude_from_luminosity_distance(
|
|
190
|
+
apparent_mag,
|
|
191
|
+
luminosity_distance_mpc,
|
|
192
|
+
k_correction=k_corr,
|
|
193
|
+
e_correction=e_corr,
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
def apparent_magnitude_from_luminosity_distance(
|
|
197
|
+
self,
|
|
198
|
+
absolute_mag: FloatInput,
|
|
199
|
+
luminosity_distance_mpc: FloatInput,
|
|
200
|
+
*,
|
|
201
|
+
z: FloatInput,
|
|
202
|
+
corrections: Corrections | None = None,
|
|
203
|
+
) -> FloatArray:
|
|
204
|
+
"""Convert absolute magnitude to apparent magnitude from luminosity distance.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
absolute_mag: Absolute magnitude values.
|
|
208
|
+
luminosity_distance_mpc: Luminosity distance values in Mpc.
|
|
209
|
+
z: Redshift values where corrections are evaluated.
|
|
210
|
+
corrections: Optional object providing k-correction and e-correction values.
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
Apparent magnitudes using ``m = M + mu + K - E``.
|
|
214
|
+
"""
|
|
215
|
+
k_corr, e_corr = self._correction_values(corrections, z)
|
|
216
|
+
|
|
217
|
+
return apparent_magnitude_from_luminosity_distance(
|
|
218
|
+
absolute_mag,
|
|
219
|
+
luminosity_distance_mpc,
|
|
220
|
+
k_correction=k_corr,
|
|
221
|
+
e_correction=e_corr,
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
def lf_integrated_number_density(
|
|
225
|
+
self,
|
|
226
|
+
z: FloatInput,
|
|
227
|
+
*,
|
|
228
|
+
m_lim: float,
|
|
229
|
+
m_bright: float,
|
|
230
|
+
n_m: int = 512,
|
|
231
|
+
luminosity_distance_mpc_fn: Callable[[FloatArray], FloatArray],
|
|
232
|
+
corrections: Corrections | None = None,
|
|
233
|
+
) -> FloatArray:
|
|
234
|
+
"""Return LF-integrated number density for an apparent-magnitude limit.
|
|
235
|
+
|
|
236
|
+
This integrates the luminosity function from ``m_bright`` to the
|
|
237
|
+
absolute-magnitude limit implied by ``m_lim`` and the supplied
|
|
238
|
+
luminosity-distance callable.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
z: Redshift values.
|
|
242
|
+
m_lim: Apparent-magnitude limit of the catalog.
|
|
243
|
+
m_bright: Bright absolute-magnitude integration bound.
|
|
244
|
+
n_m: Number of magnitude-grid points used in the integration.
|
|
245
|
+
luminosity_distance_mpc_fn: Callable returning luminosity distance
|
|
246
|
+
in Mpc as a function of redshift.
|
|
247
|
+
corrections: Optional object providing k-correction and
|
|
248
|
+
e-correction values.
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
LF-integrated number density evaluated at redshift.
|
|
252
|
+
"""
|
|
253
|
+
k_corr, e_corr = self._correction_values(corrections, z)
|
|
254
|
+
|
|
255
|
+
return lf_integrated_number_density(
|
|
256
|
+
z,
|
|
257
|
+
self._as_callable(),
|
|
258
|
+
m_lim=m_lim,
|
|
259
|
+
m_bright=m_bright,
|
|
260
|
+
n_m=n_m,
|
|
261
|
+
luminosity_distance_mpc_fn=luminosity_distance_mpc_fn,
|
|
262
|
+
k_correction=k_corr,
|
|
263
|
+
evolution_correction=e_corr,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
def lf_weighted_redshift_density(
|
|
267
|
+
self,
|
|
268
|
+
z: FloatInput,
|
|
269
|
+
*,
|
|
270
|
+
m_lim: float,
|
|
271
|
+
m_bright: float,
|
|
272
|
+
n_m: int = 512,
|
|
273
|
+
luminosity_distance_mpc_fn: Callable[[FloatArray], FloatArray],
|
|
274
|
+
volume_weight_fn: Callable[[FloatArray], FloatArray],
|
|
275
|
+
corrections: Corrections | None = None,
|
|
276
|
+
normalize: bool = True,
|
|
277
|
+
) -> FloatArray:
|
|
278
|
+
"""Return an LF-weighted redshift-density curve.
|
|
279
|
+
|
|
280
|
+
This computes an LF-selected redshift distribution by integrating the
|
|
281
|
+
luminosity function up to the apparent-magnitude limit and multiplying
|
|
282
|
+
by a supplied redshift or volume weight.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
z: Redshift values.
|
|
286
|
+
m_lim: Apparent-magnitude limit of the catalog.
|
|
287
|
+
m_bright: Bright absolute-magnitude integration bound.
|
|
288
|
+
n_m: Number of magnitude-grid points used in the integration.
|
|
289
|
+
luminosity_distance_mpc_fn: Callable returning luminosity distance
|
|
290
|
+
in Mpc as a function of redshift.
|
|
291
|
+
volume_weight_fn: Callable returning the redshift or volume weight.
|
|
292
|
+
corrections: Optional object providing k-correction and
|
|
293
|
+
e-correction values.
|
|
294
|
+
normalize: If True, normalize the returned curve to integrate to
|
|
295
|
+
one over redshift.
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
LF-weighted redshift-density curve.
|
|
299
|
+
"""
|
|
300
|
+
k_corr, e_corr = self._correction_values(corrections, z)
|
|
301
|
+
|
|
302
|
+
return lf_weighted_redshift_density(
|
|
303
|
+
z,
|
|
304
|
+
self._as_callable(),
|
|
305
|
+
m_lim=m_lim,
|
|
306
|
+
m_bright=m_bright,
|
|
307
|
+
n_m=n_m,
|
|
308
|
+
luminosity_distance_mpc_fn=luminosity_distance_mpc_fn,
|
|
309
|
+
volume_weight_fn=volume_weight_fn,
|
|
310
|
+
k_correction=k_corr,
|
|
311
|
+
evolution_correction=e_corr,
|
|
312
|
+
normalize=normalize,
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
@classmethod
|
|
316
|
+
def schechter(
|
|
317
|
+
cls,
|
|
318
|
+
*,
|
|
319
|
+
phi_star: ParameterValue,
|
|
320
|
+
m_star: ParameterValue,
|
|
321
|
+
alpha: ParameterValue,
|
|
322
|
+
) -> "LuminosityFunction":
|
|
323
|
+
"""Create a standard Schechter luminosity function.
|
|
324
|
+
|
|
325
|
+
Args:
|
|
326
|
+
phi_star: Normalization of the luminosity function.
|
|
327
|
+
m_star: Characteristic absolute magnitude.
|
|
328
|
+
alpha: Faint-end slope.
|
|
329
|
+
|
|
330
|
+
Returns:
|
|
331
|
+
Luminosity-function API object using the standard Schechter model.
|
|
332
|
+
"""
|
|
333
|
+
return cls(
|
|
334
|
+
model="schechter",
|
|
335
|
+
parameters={
|
|
336
|
+
"phi_star": phi_star,
|
|
337
|
+
"m_star": m_star,
|
|
338
|
+
"alpha": alpha,
|
|
339
|
+
},
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
@classmethod
|
|
343
|
+
def evolving_schechter(
|
|
344
|
+
cls,
|
|
345
|
+
*,
|
|
346
|
+
phi_model: str = "linear_p",
|
|
347
|
+
phi_kwargs: Mapping[str, ParameterValue] | None = None,
|
|
348
|
+
m_star_model: str = "linear_q",
|
|
349
|
+
m_star_kwargs: Mapping[str, ParameterValue] | None = None,
|
|
350
|
+
alpha_model: str = "constant",
|
|
351
|
+
alpha_kwargs: Mapping[str, ParameterValue] | None = None,
|
|
352
|
+
) -> "LuminosityFunction":
|
|
353
|
+
"""Create a redshift-evolving Schechter luminosity function.
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
phi_model: Parameter model used for the normalization evolution.
|
|
357
|
+
phi_kwargs: Keyword arguments for the normalization model.
|
|
358
|
+
m_star_model: Parameter model used for characteristic-magnitude evolution.
|
|
359
|
+
m_star_kwargs: Keyword arguments for the characteristic-magnitude model.
|
|
360
|
+
alpha_model: Parameter model used for faint-end-slope evolution.
|
|
361
|
+
alpha_kwargs: Keyword arguments for the faint-end-slope model.
|
|
362
|
+
|
|
363
|
+
Returns:
|
|
364
|
+
Luminosity-function API object using an evolving Schechter model.
|
|
365
|
+
"""
|
|
366
|
+
return cls(
|
|
367
|
+
model="evolving_schechter",
|
|
368
|
+
parameters={
|
|
369
|
+
"phi_model": phi_model,
|
|
370
|
+
"phi_kwargs": {} if phi_kwargs is None else dict(phi_kwargs),
|
|
371
|
+
"m_star_model": m_star_model,
|
|
372
|
+
"m_star_kwargs": {} if m_star_kwargs is None else dict(m_star_kwargs),
|
|
373
|
+
"alpha_model": alpha_model,
|
|
374
|
+
"alpha_kwargs": {} if alpha_kwargs is None else dict(alpha_kwargs),
|
|
375
|
+
},
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
@classmethod
|
|
379
|
+
def double_schechter(
|
|
380
|
+
cls,
|
|
381
|
+
*,
|
|
382
|
+
phi_star: ParameterValue,
|
|
383
|
+
m_star: ParameterValue,
|
|
384
|
+
alpha: float,
|
|
385
|
+
beta: float,
|
|
386
|
+
m_transition: ParameterValue,
|
|
387
|
+
) -> "LuminosityFunction":
|
|
388
|
+
"""Create a double-power-law Schechter luminosity function.
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
phi_star: Normalization of the luminosity function.
|
|
392
|
+
m_star: Characteristic absolute magnitude.
|
|
393
|
+
alpha: Bright-end or main Schechter slope.
|
|
394
|
+
beta: Additional slope controlling the second power-law component.
|
|
395
|
+
m_transition: Transition magnitude for the second component.
|
|
396
|
+
|
|
397
|
+
Returns:
|
|
398
|
+
Luminosity-function API object using the double Schechter model.
|
|
399
|
+
"""
|
|
400
|
+
return cls(
|
|
401
|
+
model="double_schechter",
|
|
402
|
+
parameters={
|
|
403
|
+
"phi_star": phi_star,
|
|
404
|
+
"m_star": m_star,
|
|
405
|
+
"alpha": alpha,
|
|
406
|
+
"beta": beta,
|
|
407
|
+
"m_transition": m_transition,
|
|
408
|
+
},
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
def phi(
|
|
412
|
+
self,
|
|
413
|
+
absolute_mag: FloatInput,
|
|
414
|
+
z: FloatInput | None = None,
|
|
415
|
+
) -> FloatArray:
|
|
416
|
+
"""Evaluate the luminosity function in absolute-magnitude space.
|
|
417
|
+
|
|
418
|
+
Args:
|
|
419
|
+
absolute_mag: Absolute magnitude values where the LF is evaluated.
|
|
420
|
+
z: Redshift values. Required for evolving Schechter models.
|
|
421
|
+
|
|
422
|
+
Returns:
|
|
423
|
+
Luminosity-function values evaluated at the input magnitudes.
|
|
424
|
+
"""
|
|
425
|
+
if self.model == "schechter":
|
|
426
|
+
return schechter(
|
|
427
|
+
np.asarray(absolute_mag, dtype=float),
|
|
428
|
+
**self.parameters_dict,
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
if self.model == "evolving_schechter":
|
|
432
|
+
if z is None:
|
|
433
|
+
raise ValueError("z is required for an evolving luminosity function.")
|
|
434
|
+
|
|
435
|
+
return schechter_evolving(
|
|
436
|
+
np.asarray(absolute_mag, dtype=float),
|
|
437
|
+
np.asarray(z, dtype=float),
|
|
438
|
+
**self.parameters_dict,
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
if self.model == "double_schechter":
|
|
442
|
+
return schechter_double(
|
|
443
|
+
np.asarray(absolute_mag, dtype=float),
|
|
444
|
+
**self.parameters_dict,
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
raise ValueError(f"Unsupported luminosity-function model '{self.model}'.")
|
|
448
|
+
|
|
449
|
+
def phi_from_m(
|
|
450
|
+
self,
|
|
451
|
+
cosmo_obj: Cosmology,
|
|
452
|
+
z: FloatInput,
|
|
453
|
+
apparent_mag: FloatInput,
|
|
454
|
+
*,
|
|
455
|
+
h: float | None = None,
|
|
456
|
+
corrections: Corrections | None = None,
|
|
457
|
+
) -> FloatArray:
|
|
458
|
+
"""Evaluate the luminosity function from apparent magnitudes.
|
|
459
|
+
|
|
460
|
+
Apparent magnitudes are converted to absolute magnitudes using the
|
|
461
|
+
supplied cosmology, optional reduced Hubble parameter, and optional
|
|
462
|
+
k- and e-correction model.
|
|
463
|
+
|
|
464
|
+
Args:
|
|
465
|
+
cosmo_obj: Cosmology object used for distance-modulus conversion.
|
|
466
|
+
z: Redshift values.
|
|
467
|
+
apparent_mag: Apparent magnitude values.
|
|
468
|
+
h: Optional reduced Hubble parameter used in the magnitude conversion.
|
|
469
|
+
corrections: Optional object providing k-correction and e-correction values.
|
|
470
|
+
|
|
471
|
+
Returns:
|
|
472
|
+
Luminosity-function values evaluated from apparent magnitudes.
|
|
473
|
+
"""
|
|
474
|
+
k_corr, e_corr = self._correction_values(corrections, z)
|
|
475
|
+
|
|
476
|
+
if self.model == "schechter":
|
|
477
|
+
return schechter_from_m(
|
|
478
|
+
cosmo_obj,
|
|
479
|
+
np.asarray(z, dtype=float),
|
|
480
|
+
np.asarray(apparent_mag, dtype=float),
|
|
481
|
+
h=h,
|
|
482
|
+
k_correction=k_corr,
|
|
483
|
+
e_correction=e_corr,
|
|
484
|
+
**self.parameters_dict,
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
if self.model == "evolving_schechter":
|
|
488
|
+
return schechter_evolving_from_m(
|
|
489
|
+
cosmo_obj,
|
|
490
|
+
np.asarray(z, dtype=float),
|
|
491
|
+
np.asarray(apparent_mag, dtype=float),
|
|
492
|
+
h=h,
|
|
493
|
+
k_correction=k_corr,
|
|
494
|
+
e_correction=e_corr,
|
|
495
|
+
**self.parameters_dict,
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
if self.model == "double_schechter":
|
|
499
|
+
return schechter_double_from_m(
|
|
500
|
+
cosmo_obj,
|
|
501
|
+
np.asarray(z, dtype=float),
|
|
502
|
+
np.asarray(apparent_mag, dtype=float),
|
|
503
|
+
h=h,
|
|
504
|
+
k_correction=k_corr,
|
|
505
|
+
e_correction=e_corr,
|
|
506
|
+
**self.parameters_dict,
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
raise ValueError(f"Unsupported luminosity-function model '{self.model}'.")
|
|
510
|
+
|
|
511
|
+
def parameters(
|
|
512
|
+
self,
|
|
513
|
+
z: FloatInput,
|
|
514
|
+
) -> tuple[FloatArray, FloatArray, FloatArray]:
|
|
515
|
+
"""Evaluate evolving Schechter parameters at redshift.
|
|
516
|
+
|
|
517
|
+
Args:
|
|
518
|
+
z: Redshift values where the evolving LF parameters are evaluated.
|
|
519
|
+
|
|
520
|
+
Returns:
|
|
521
|
+
Tuple containing ``phi_star(z)``, ``m_star(z)``, and ``alpha(z)``.
|
|
522
|
+
"""
|
|
523
|
+
if self.model != "evolving_schechter":
|
|
524
|
+
raise ValueError("parameters(z) is only defined for evolving_schechter.")
|
|
525
|
+
|
|
526
|
+
return evaluate_lf_parameters(
|
|
527
|
+
np.asarray(z, dtype=float),
|
|
528
|
+
**self.parameters_dict,
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
def absolute_magnitude_limit(
|
|
532
|
+
self,
|
|
533
|
+
cosmo_obj: Cosmology,
|
|
534
|
+
z: FloatInput,
|
|
535
|
+
*,
|
|
536
|
+
m_lim: float,
|
|
537
|
+
h: float | None = None,
|
|
538
|
+
corrections: Corrections | None = None,
|
|
539
|
+
) -> FloatArray:
|
|
540
|
+
"""Return the absolute-magnitude limit of a catalog apparent-magnitude cut.
|
|
541
|
+
|
|
542
|
+
Args:
|
|
543
|
+
cosmo_obj: Cosmology object used for distance-modulus conversion.
|
|
544
|
+
z: Redshift values.
|
|
545
|
+
m_lim: Apparent-magnitude limit of the catalog.
|
|
546
|
+
h: Optional reduced Hubble parameter used in the magnitude conversion.
|
|
547
|
+
corrections: Optional object providing k-correction and e-correction values.
|
|
548
|
+
|
|
549
|
+
Returns:
|
|
550
|
+
Absolute-magnitude limits using the LFKit convention
|
|
551
|
+
``M_lim = m_lim - mu - K + E``.
|
|
552
|
+
"""
|
|
553
|
+
k_corr, e_corr = self._correction_values(corrections, z)
|
|
554
|
+
|
|
555
|
+
return absolute_magnitude_limit(
|
|
556
|
+
cosmo_obj,
|
|
557
|
+
z,
|
|
558
|
+
m_lim=m_lim,
|
|
559
|
+
h=h,
|
|
560
|
+
k_correction=k_corr,
|
|
561
|
+
e_correction=e_corr,
|
|
562
|
+
)
|
|
563
|
+
|
|
564
|
+
@staticmethod
|
|
565
|
+
def available_parameter_models() -> dict[str, list[str]]:
|
|
566
|
+
"""Return available LF parameter evolution models."""
|
|
567
|
+
return available_lf_parameter_models()
|
|
568
|
+
|
|
569
|
+
@staticmethod
|
|
570
|
+
def register_phi_star_model(
|
|
571
|
+
name: str,
|
|
572
|
+
model: ParameterModel,
|
|
573
|
+
*,
|
|
574
|
+
overwrite: bool = False,
|
|
575
|
+
) -> None:
|
|
576
|
+
"""Register a phi_star evolution model."""
|
|
577
|
+
register_phi_star_model(name, model, overwrite=overwrite)
|
|
578
|
+
|
|
579
|
+
@staticmethod
|
|
580
|
+
def register_m_star_model(
|
|
581
|
+
name: str,
|
|
582
|
+
model: ParameterModel,
|
|
583
|
+
*,
|
|
584
|
+
overwrite: bool = False,
|
|
585
|
+
) -> None:
|
|
586
|
+
"""Register an M_star evolution model."""
|
|
587
|
+
register_m_star_model(name, model, overwrite=overwrite)
|
|
588
|
+
|
|
589
|
+
@staticmethod
|
|
590
|
+
def register_alpha_model(
|
|
591
|
+
name: str,
|
|
592
|
+
model: ParameterModel,
|
|
593
|
+
*,
|
|
594
|
+
overwrite: bool = False,
|
|
595
|
+
) -> None:
|
|
596
|
+
"""Register an alpha evolution model."""
|
|
597
|
+
register_alpha_model(name, model, overwrite=overwrite)
|
|
598
|
+
|
|
599
|
+
def integrated_number_density(
|
|
600
|
+
self,
|
|
601
|
+
z: FloatInput,
|
|
602
|
+
*,
|
|
603
|
+
m_bright: ParameterValue,
|
|
604
|
+
m_faint: ParameterValue,
|
|
605
|
+
n_m: int = 512,
|
|
606
|
+
) -> FloatArray:
|
|
607
|
+
"""Integrate the LF over an absolute-magnitude range.
|
|
608
|
+
|
|
609
|
+
Args:
|
|
610
|
+
z: Redshift values.
|
|
611
|
+
m_bright: Bright absolute-magnitude integration limit.
|
|
612
|
+
m_faint: Faint absolute-magnitude integration limit.
|
|
613
|
+
n_m: Number of magnitude-grid points used in the integration.
|
|
614
|
+
|
|
615
|
+
Returns:
|
|
616
|
+
Number density integrated over the requested magnitude range.
|
|
617
|
+
"""
|
|
618
|
+
return integrated_number_density(
|
|
619
|
+
z,
|
|
620
|
+
self._as_callable(),
|
|
621
|
+
m_bright=m_bright,
|
|
622
|
+
m_faint=m_faint,
|
|
623
|
+
n_m=n_m,
|
|
624
|
+
)
|
|
625
|
+
|
|
626
|
+
def lf_weighted_integral(
|
|
627
|
+
self,
|
|
628
|
+
z: FloatInput,
|
|
629
|
+
*,
|
|
630
|
+
m_bright: ParameterValue,
|
|
631
|
+
m_faint: ParameterValue,
|
|
632
|
+
weight_fn: Callable[[FloatArray, FloatArray], FloatArray],
|
|
633
|
+
n_m: int = 512,
|
|
634
|
+
) -> FloatArray:
|
|
635
|
+
"""Integrate the LF with a user-supplied magnitude-redshift weight."""
|
|
636
|
+
return lf_weighted_integral(
|
|
637
|
+
z,
|
|
638
|
+
self._as_callable(),
|
|
639
|
+
m_bright=m_bright,
|
|
640
|
+
m_faint=m_faint,
|
|
641
|
+
weight_fn=weight_fn,
|
|
642
|
+
n_m=n_m,
|
|
643
|
+
)
|
|
644
|
+
|
|
645
|
+
def selection_weighted_number_density(
|
|
646
|
+
self,
|
|
647
|
+
z: FloatInput,
|
|
648
|
+
*,
|
|
649
|
+
m_bright: ParameterValue,
|
|
650
|
+
m_faint: ParameterValue,
|
|
651
|
+
selection_fn: Callable[[FloatArray, FloatArray], FloatArray],
|
|
652
|
+
n_m: int = 512,
|
|
653
|
+
) -> FloatArray:
|
|
654
|
+
"""Return LF number density weighted by a selection function."""
|
|
655
|
+
return selection_weighted_number_density(
|
|
656
|
+
z,
|
|
657
|
+
self._as_callable(),
|
|
658
|
+
m_bright=m_bright,
|
|
659
|
+
m_faint=m_faint,
|
|
660
|
+
selection_fn=selection_fn,
|
|
661
|
+
n_m=n_m,
|
|
662
|
+
)
|
|
663
|
+
|
|
664
|
+
def integrated_luminosity_density(
|
|
665
|
+
self,
|
|
666
|
+
z: FloatInput,
|
|
667
|
+
*,
|
|
668
|
+
m_bright: ParameterValue,
|
|
669
|
+
m_faint: ParameterValue,
|
|
670
|
+
m_reference: float = 0.0,
|
|
671
|
+
n_m: int = 512,
|
|
672
|
+
) -> FloatArray:
|
|
673
|
+
"""Return luminosity density over an absolute-magnitude range."""
|
|
674
|
+
return integrated_luminosity_density(
|
|
675
|
+
z,
|
|
676
|
+
self._as_callable(),
|
|
677
|
+
m_bright=m_bright,
|
|
678
|
+
m_faint=m_faint,
|
|
679
|
+
m_reference=m_reference,
|
|
680
|
+
n_m=n_m,
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
def mean_luminosity(
|
|
684
|
+
self,
|
|
685
|
+
z: FloatInput,
|
|
686
|
+
*,
|
|
687
|
+
m_bright: ParameterValue,
|
|
688
|
+
m_faint: ParameterValue,
|
|
689
|
+
m_reference: float = 0.0,
|
|
690
|
+
n_m: int = 512,
|
|
691
|
+
) -> FloatArray:
|
|
692
|
+
"""Return mean luminosity over an absolute-magnitude range."""
|
|
693
|
+
return mean_luminosity(
|
|
694
|
+
z,
|
|
695
|
+
self._as_callable(),
|
|
696
|
+
m_bright=m_bright,
|
|
697
|
+
m_faint=m_faint,
|
|
698
|
+
m_reference=m_reference,
|
|
699
|
+
n_m=n_m,
|
|
700
|
+
)
|
|
701
|
+
|
|
702
|
+
def cumulative_number_density(
|
|
703
|
+
self,
|
|
704
|
+
z: FloatInput,
|
|
705
|
+
*,
|
|
706
|
+
m_threshold: ParameterValue,
|
|
707
|
+
m_bright: ParameterValue,
|
|
708
|
+
m_faint: ParameterValue,
|
|
709
|
+
brighter_than: bool = True,
|
|
710
|
+
n_m: int = 512,
|
|
711
|
+
) -> FloatArray:
|
|
712
|
+
"""Return cumulative LF number density around a magnitude threshold."""
|
|
713
|
+
return cumulative_number_density(
|
|
714
|
+
z,
|
|
715
|
+
self._as_callable(),
|
|
716
|
+
m_threshold=m_threshold,
|
|
717
|
+
m_bright=m_bright,
|
|
718
|
+
m_faint=m_faint,
|
|
719
|
+
brighter_than=brighter_than,
|
|
720
|
+
n_m=n_m,
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
def observed_number_density(
|
|
724
|
+
self,
|
|
725
|
+
cosmo_obj: Cosmology,
|
|
726
|
+
z: FloatInput,
|
|
727
|
+
*,
|
|
728
|
+
m_lim: float,
|
|
729
|
+
m_bright: float,
|
|
730
|
+
m_faint: float,
|
|
731
|
+
n_m: int = 512,
|
|
732
|
+
h: float | None = None,
|
|
733
|
+
corrections: Corrections | None = None,
|
|
734
|
+
) -> FloatArray:
|
|
735
|
+
"""Return the LF number density observable in a magnitude-limited catalog.
|
|
736
|
+
|
|
737
|
+
Args:
|
|
738
|
+
cosmo_obj: Cosmology object used for apparent-to-absolute conversion.
|
|
739
|
+
z: Redshift values.
|
|
740
|
+
m_lim: Apparent-magnitude limit of the catalog.
|
|
741
|
+
m_bright: Bright absolute-magnitude integration limit.
|
|
742
|
+
m_faint: Faint absolute-magnitude integration limit.
|
|
743
|
+
n_m: Number of magnitude-grid points used in the integration.
|
|
744
|
+
h: Optional reduced Hubble parameter used in the magnitude conversion.
|
|
745
|
+
corrections: Optional object providing k-correction and e-correction values.
|
|
746
|
+
|
|
747
|
+
Returns:
|
|
748
|
+
Number density brighter than the catalog magnitude limit.
|
|
749
|
+
"""
|
|
750
|
+
k_corr, e_corr = self._correction_values(corrections, z)
|
|
751
|
+
|
|
752
|
+
return observed_number_density(
|
|
753
|
+
cosmo_obj,
|
|
754
|
+
z,
|
|
755
|
+
self._as_callable(),
|
|
756
|
+
m_lim=m_lim,
|
|
757
|
+
m_bright=m_bright,
|
|
758
|
+
m_faint=m_faint,
|
|
759
|
+
n_m=n_m,
|
|
760
|
+
h=h,
|
|
761
|
+
k_correction=k_corr,
|
|
762
|
+
e_correction=e_corr,
|
|
763
|
+
)
|
|
764
|
+
|
|
765
|
+
def missing_number_density(
|
|
766
|
+
self,
|
|
767
|
+
cosmo_obj: Cosmology,
|
|
768
|
+
z: FloatInput,
|
|
769
|
+
*,
|
|
770
|
+
m_lim: float,
|
|
771
|
+
m_bright: float,
|
|
772
|
+
m_faint: float,
|
|
773
|
+
n_m: int = 512,
|
|
774
|
+
h: float | None = None,
|
|
775
|
+
corrections: Corrections | None = None,
|
|
776
|
+
) -> FloatArray:
|
|
777
|
+
"""Return the LF number density missing from a magnitude-limited catalog.
|
|
778
|
+
|
|
779
|
+
Args:
|
|
780
|
+
cosmo_obj: Cosmology object used for apparent-to-absolute conversion.
|
|
781
|
+
z: Redshift values.
|
|
782
|
+
m_lim: Apparent-magnitude limit of the catalog.
|
|
783
|
+
m_bright: Bright absolute-magnitude integration limit.
|
|
784
|
+
m_faint: Faint absolute-magnitude integration limit.
|
|
785
|
+
n_m: Number of magnitude-grid points used in the integration.
|
|
786
|
+
h: Optional reduced Hubble parameter used in the magnitude conversion.
|
|
787
|
+
corrections: Optional object providing k-correction and e-correction values.
|
|
788
|
+
|
|
789
|
+
Returns:
|
|
790
|
+
Number density fainter than the catalog magnitude limit but inside
|
|
791
|
+
the requested absolute-magnitude range.
|
|
792
|
+
"""
|
|
793
|
+
k_corr, e_corr = self._correction_values(corrections, z)
|
|
794
|
+
|
|
795
|
+
return missing_number_density(
|
|
796
|
+
cosmo_obj,
|
|
797
|
+
z,
|
|
798
|
+
self._as_callable(),
|
|
799
|
+
m_lim=m_lim,
|
|
800
|
+
m_bright=m_bright,
|
|
801
|
+
m_faint=m_faint,
|
|
802
|
+
n_m=n_m,
|
|
803
|
+
h=h,
|
|
804
|
+
k_correction=k_corr,
|
|
805
|
+
e_correction=e_corr,
|
|
806
|
+
)
|
|
807
|
+
|
|
808
|
+
def catalog_completeness(
|
|
809
|
+
self,
|
|
810
|
+
cosmo_obj: Cosmology,
|
|
811
|
+
z: FloatInput,
|
|
812
|
+
*,
|
|
813
|
+
m_lim: float,
|
|
814
|
+
m_bright: float,
|
|
815
|
+
m_faint: float,
|
|
816
|
+
n_m: int = 512,
|
|
817
|
+
h: float | None = None,
|
|
818
|
+
corrections: Corrections | None = None,
|
|
819
|
+
) -> FloatArray:
|
|
820
|
+
"""Return the observed LF fraction in a magnitude-limited catalog.
|
|
821
|
+
|
|
822
|
+
Args:
|
|
823
|
+
cosmo_obj: Cosmology object used for apparent-to-absolute conversion.
|
|
824
|
+
z: Redshift values.
|
|
825
|
+
m_lim: Apparent-magnitude limit of the catalog.
|
|
826
|
+
m_bright: Bright absolute-magnitude integration limit.
|
|
827
|
+
m_faint: Faint absolute-magnitude integration limit.
|
|
828
|
+
n_m: Number of magnitude-grid points used in the integration.
|
|
829
|
+
h: Optional reduced Hubble parameter used in the magnitude conversion.
|
|
830
|
+
corrections: Optional object providing k-correction and e-correction values.
|
|
831
|
+
|
|
832
|
+
Returns:
|
|
833
|
+
Fraction of the LF number density observable in the catalog.
|
|
834
|
+
"""
|
|
835
|
+
k_corr, e_corr = self._correction_values(corrections, z)
|
|
836
|
+
|
|
837
|
+
return catalog_completeness_fraction(
|
|
838
|
+
cosmo_obj,
|
|
839
|
+
z,
|
|
840
|
+
self._as_callable(),
|
|
841
|
+
m_lim=m_lim,
|
|
842
|
+
m_bright=m_bright,
|
|
843
|
+
m_faint=m_faint,
|
|
844
|
+
n_m=n_m,
|
|
845
|
+
h=h,
|
|
846
|
+
k_correction=k_corr,
|
|
847
|
+
e_correction=e_corr,
|
|
848
|
+
)
|
|
849
|
+
|
|
850
|
+
def out_of_catalog_fraction(
|
|
851
|
+
self,
|
|
852
|
+
cosmo_obj: Cosmology,
|
|
853
|
+
z: FloatInput,
|
|
854
|
+
*,
|
|
855
|
+
m_lim: float,
|
|
856
|
+
m_bright: float,
|
|
857
|
+
m_faint: float,
|
|
858
|
+
n_m: int = 512,
|
|
859
|
+
h: float | None = None,
|
|
860
|
+
corrections: Corrections | None = None,
|
|
861
|
+
) -> FloatArray:
|
|
862
|
+
"""Return the missing LF fraction for a magnitude-limited catalog.
|
|
863
|
+
|
|
864
|
+
Args:
|
|
865
|
+
cosmo_obj: Cosmology object used for apparent-to-absolute conversion.
|
|
866
|
+
z: Redshift values.
|
|
867
|
+
m_lim: Apparent-magnitude limit of the catalog.
|
|
868
|
+
m_bright: Bright absolute-magnitude integration limit.
|
|
869
|
+
m_faint: Faint absolute-magnitude integration limit.
|
|
870
|
+
n_m: Number of magnitude-grid points used in the integration.
|
|
871
|
+
h: Optional reduced Hubble parameter used in the magnitude conversion.
|
|
872
|
+
corrections: Optional object providing k-correction and e-correction values.
|
|
873
|
+
|
|
874
|
+
Returns:
|
|
875
|
+
Fraction of the LF number density missing from the catalog.
|
|
876
|
+
"""
|
|
877
|
+
k_corr, e_corr = self._correction_values(corrections, z)
|
|
878
|
+
|
|
879
|
+
return out_of_catalog_fraction(
|
|
880
|
+
cosmo_obj,
|
|
881
|
+
z,
|
|
882
|
+
self._as_callable(),
|
|
883
|
+
m_lim=m_lim,
|
|
884
|
+
m_bright=m_bright,
|
|
885
|
+
m_faint=m_faint,
|
|
886
|
+
n_m=n_m,
|
|
887
|
+
h=h,
|
|
888
|
+
k_correction=k_corr,
|
|
889
|
+
e_correction=e_corr,
|
|
890
|
+
)
|
|
891
|
+
|
|
892
|
+
def _as_callable(self):
|
|
893
|
+
"""Return this object as an ``lf(M, z)`` callable."""
|
|
894
|
+
return lambda absolute_mag, z: self.phi(absolute_mag, z)
|
|
895
|
+
|
|
896
|
+
@staticmethod
|
|
897
|
+
def _correction_values(
|
|
898
|
+
corrections: Corrections | None,
|
|
899
|
+
z: FloatInput,
|
|
900
|
+
) -> tuple[FloatArray | None, FloatArray | None]:
|
|
901
|
+
"""Evaluate optional correction values at redshift.
|
|
902
|
+
|
|
903
|
+
Args:
|
|
904
|
+
corrections: Optional correction object with ``k(z)`` and ``e(z)`` methods.
|
|
905
|
+
z: Redshift values where corrections are evaluated.
|
|
906
|
+
|
|
907
|
+
Returns:
|
|
908
|
+
Tuple of k-correction and e-correction arrays, or ``None`` values
|
|
909
|
+
when no correction object is supplied.
|
|
910
|
+
"""
|
|
911
|
+
if corrections is None:
|
|
912
|
+
return None, None
|
|
913
|
+
|
|
914
|
+
return corrections.k(z), corrections.e(z)
|