eppaurora.brems.berger1974()   A
last analyzed

Complexity

Conditions 4

Size

Total Lines 101
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 33
nop 10
dl 0
loc 101
rs 9.0879
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
# coding: utf-8
2
# Copyright (c) 2020 Stefan Bender
3
#
4
# This file is part of pyeppaurora.
5
# pyeppaurora is free software: you can redistribute it or modify
6
# it under the terms of the GNU General Public License as published
7
# by the Free Software Foundation, version 2.
8
# See accompanying LICENSE file or http://www.gnu.org/licenses/gpl-2.0.html.
9
"""Atmospheric bremsstrahlung ionization parametrization [1]_
10
11
.. [1] Berger, M.J., Seltzer, S.M., Maeda, K.,
12
	Some new results on electron transport in the atmosphere,
13
	Journal of Atmospheric and Terrestrial Physics, v36, i4, pp. 591--617,
14
	April 1974,
15
	doi: 10.1016/0021-9169(74)90085-3
16
"""
17
18
import numpy as np
19
from scipy import interpolate
20
21
__all__ = ["berger1974"]
22
23
E_BR = [2., 5., 10., 20., 50., 100., 200., 500., 1000., 2000.]
24
25
Z_BR = [
26
	2e-6, 4e-6, 8e-6,
27
	2e-5, 4e-5, 8e-5,
28
	2e-4, 4e-4, 8e-4,
29
	2e-3, 4e-3, 8e-3,
30
	2e-2, 4e-2, 8e-2,
31
	2e-1, 4e-1,
32
]
33
34
A_BR = [
35
	[np.nan] * 9 + [8.6e-6, 5.1e-7] + [np.nan] * 6,
36
	[np.nan] * 8 + [7.2e-4, 1.4e-4, 3.3e-5, 5.2e-6, 1.1e-7] + [np.nan] * 4,
37
	[np.nan] * 7 + [2.0e-3, 8.8e-4, 2.7e-4, 9.4e-5, 2.8e-5, 3.0e-6, 3.8e-7, 3.9e-8] + [np.nan] * 2,
38
	[np.nan] * 6 + [3.4e-3, 1.7e-3, 8.0e-4, 3.0e-4, 1.3e-4, 5.7e-5, 1.5e-5, 3.3e-6, 5.7e-7, 2.9e-8] + [np.nan],
39
	[np.nan] * 5 + [7.3e-3, 2.2e-3, 1.1e-3, 5.7e-4, 2.3e-4, 1.1e-4, 5.4e-5, 2.0e-5, 8.3e-6, 2.6e-6, 3.1e-7, 2.8e-8],
40
	[np.nan] * 4 + [1.1e-2, 7.9e-3, 1.7e-3, 8.4e-4, 4.4e-4, 1.9e-4, 1.0e-4, 5.4e-5, 2.3e-5, 1.1e-5, 3.9e-6, 5.4e-7, 2.4e-8],
41
	[np.nan] * 3 + [5.0e-3, 5.3e-3, 5.0e-3, 1.8e-3, 6.5e-4, 3.3e-4, 1.5e-4, 8.8e-5, 5.2e-5, 2.4e-5, 1.1e-5, 3.8e-6, 1.7e-7, 5.9e-9],
42
	[np.nan] * 2 + [2.2e-3, 2.4e-3, 2.5e-3, 2.5e-3, 1.6e-3, 5.2e-4, 2.8e-4, 1.5e-4, 9.9e-5, 6.5e-5, 2.8e-5, 9.5e-6, 1.5e-6, 6.0e-9] + [np.nan],
43
	[np.nan] + [1.0e-3, 1.1e-3, 1.2e-3, 1.3e-3, 1.4e-3, 1.2e-3, 5.5e-4, 3.2e-4, 1.9e-4, 1.3e-4, 8.3e-5, 2.8e-5, 5.5e-6, 2.4e-7] + [np.nan] * 2,
44
	[6.8e-4, 7.6e-4, 8.4e-4, 9.3e-4, 9.9e-4, 1.1e-3, 1.1e-3, 6.8e-4, 4.5e-4, 2.9e-4, 1.9e-4, 9.2e-5, 1.7e-5, 1.2e-6] + [np.nan] * 3,
45
]
46
47
48
def berger1974(
49
	energy, flux,
50
	scale_height, rho,
51
	ens=None, zm_p_en=None, coeffs=None,
52
	fillna=None, log3=True,
53
	rbf="multiquadric",
54
):
55
	"""Bremsstrahlung ionization by secondary electrons
56
57
	Formulae and parameters as described in [#]_.
58
59
	By default, the `log(coefficients)` are interpolated wrt. `log(energy)`
60
	and `log(zm)` using :class:`scipy.interpolated.Rbf`.
61
	The default "multiquadric" should work fine, if not consider
62
	using "thin-plate" splines.
63
64
	Parameters
65
	----------
66
	energy: array_like (M, ...)
67
		Energy E_0 of the mono-energetic electron beam [keV].
68
		A scalar (0-D) value is promoted to 1-D with one element.
69
	flux: array_like (M,...)
70
		Energy flux Q_0 of the mono-energetic electron beam [keV / cm² / s¹].
71
	scale_height: array_like (N, ...)
72
		The atmospheric scale heights [cm].
73
	rho: array_like (N, ...)
74
		The atmospheric mass density [g / cm³].
75
	ens: array_like (I,), optional
76
		The energies (one axis) of the coefficient array,
77
		used to interpolate the coefficients to `energy`.
78
		Defaults to the Berger et al., 1974 coefficients.
79
	zm_p_en: array_like (J,), optional
80
		The atmospheric depth (the other axis) of the coefficient array,
81
		used to interpolate the coefficients to `z` = `scale_height` * `rhos`.
82
		Defaults to the Berger et al., 1974 coefficients.
83
	coeffs: array_like, (J, I), optional
84
		The bremsstrahlung energy dissipation coefficients.
85
		Defaults to the Berger et al., 1974 coefficients.
86
	fillna: float or None, optional (default `None`)
87
		Value to use for `nan` values in `coeffs`, `None` skips them.
88
	log3: bool, optional (default `True`)
89
		Interpolate the coefficients as log(ens)-log(zm)-log(coeff)
90
		instead of a linear variant.
91
	rbf: str or callable, optional (default "multiquadric")
92
		Radial basis functions to use for :class:`scipy.interpolate.Rbf`.
93
94
	Returns
95
	-------
96
	a_br: array_like (M, N)
97
		A scalar (0-D) `energy` is promoted to 1-D, and the result will
98
		have shape (1, N), *not* (N,).
99
		Energy dissipation rate, units: [keV cm⁻³ s⁻¹]
100
101
	References
102
	----------
103
	.. [#] Berger, M.J., Seltzer, S.M., Maeda, K.,
104
		Some new results on electron transport in the atmosphere,
105
		Journal of Atmospheric and Terrestrial Physics, v36, i4, pp. 591--617,
106
		April 1974,
107
		doi: 10.1016/0021-9169(74)90085-3
108
109
	See also
110
	--------
111
	scipy.interpolate.Rbf
112
	"""
113
	energy = np.atleast_1d(np.asarray(energy, dtype=float))
114
	ens = np.asarray(ens) or np.asarray(E_BR)
115
	zm_p_en = np.asarray(zm_p_en) or np.asarray(Z_BR)
116
117
	coeffs = (
118
		np.array(coeffs, copy=fillna is not None)
119
		or np.array(A_BR, copy=fillna is not None)
120
	)
121
	nans = np.isnan(coeffs)
122
	if fillna is not None:
123
		coeffs[nans] = fillna
124
		# update nan positions (should be all False)
125
		nans = np.isnan(coeffs)
126
127
	z = scale_height * rho / energy
128
	# reshape by `numpy`'s automatic broacdasting to the same shape as z
129
	enp = np.ones_like(z) * energy
130
131
	pts = [
132
		(_e, _z, coeffs[_i, _j])
133
		for _i, _e in enumerate(ens)
134
		for _j, _z in enumerate(zm_p_en)
135
		if not nans[_i, _j]
136
	]
137
	pts = np.array(pts, copy=False)
138
139
	if log3:
140
		enp = np.log(enp)
141
		z = np.log(z)
142
		pts = np.log(pts)
143
	intp = interpolate.Rbf(*(pts.T), function=rbf)
144
	abr_zm = intp(enp, z)
145
146
	if log3:
147
		abr_zm = np.exp(abr_zm)
148
	return abr_zm * rho * flux
149