Conditions | 8 |
Total Lines | 110 |
Code Lines | 47 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
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:
If many parameters/temporary variables are present:
1 | # coding: utf-8 |
||
31 | def ssusiq2023(gmlat, mlt, alt, sw_coeffs, coeff_ds=None, return_var=False): |
||
32 | u""" |
||
33 | Parameters |
||
34 | ---------- |
||
35 | gmlat: float |
||
36 | Geomagnetic latitude in [degrees]. |
||
37 | mlt: float |
||
38 | Magnetic local time in [hours]. |
||
39 | alt: float |
||
40 | Altitude in [km] |
||
41 | sw_coeffs: array_like or `xarray.DataArray` |
||
42 | The space weather index values to use (for the requested time(s)), |
||
43 | should be of shape (N, M) with N = number of proxies, currently 5: |
||
44 | [Kp, PC, Ap, log(f10.7_81ctr_obs), log(v_plasma)]. |
||
45 | The `xarray.DataArray` should have a dimension named "proxy" with |
||
46 | matching coordinates: |
||
47 | ["Kp", "PC", "Ap", "log_f107_81ctr_obs", "log_v_plasma"] |
||
48 | All the other dimensions will be broadcasted. |
||
49 | coeff_ds: `xarray.Dataset`, optional (default: None) |
||
50 | Dataset with the model coefficients, `None` uses the packaged version. |
||
51 | return_var: bool, optional (default: False) |
||
52 | If `True`, returns the predicted variance in addition to the values, |
||
53 | otherwise only the mean prediction is returned. |
||
54 | |||
55 | Returns |
||
56 | ------- |
||
57 | q: `xarray.DataArray` |
||
58 | log(q), where q is the ionization rate in [cm⁻³ s⁻¹] |
||
59 | if `return_var` is False. |
||
60 | q, var(q): tuple of `xarray.DataArray`s |
||
61 | log(q) and var(log(q)) where q is the ionization rate in [cm⁻³ s⁻¹] |
||
62 | if `return_var` is True. |
||
63 | """ |
||
64 | coeff_ds = coeff_ds or xr.open_dataset( |
||
65 | COEFF_PATH, decode_times=False, engine="h5netcdf" |
||
66 | ) |
||
67 | coeff_sel = coeff_ds.sel( |
||
68 | altitude=alt, latitude=gmlat, mlt=mlt, method="nearest", |
||
69 | ) |
||
70 | |||
71 | # Determine if `xarray` read bytes or strings to |
||
72 | # match the correct name in the proxy names. |
||
73 | # Default is plain strings. |
||
74 | offset = "offset" |
||
75 | if isinstance(coeff_ds.proxy.values[0], bytes): |
||
76 | offset = offset.encode() |
||
77 | have_offset = offset in coeff_ds.proxy.values |
||
78 | |||
79 | # prepare the coefficients (array) as a `xarray.DataArray` |
||
80 | if isinstance(sw_coeffs, xr.DataArray): |
||
81 | if have_offset: |
||
82 | ones = xr.ones_like(sw_coeffs.isel(proxy=0)) |
||
83 | ones = ones.assign_coords(proxy="offset") |
||
84 | sw_coeffs = xr.concat([sw_coeffs, ones], dim="proxy") |
||
85 | else: |
||
86 | sw_coeffs = np.atleast_2d(sw_coeffs) |
||
87 | if have_offset: |
||
88 | aix = sw_coeffs.shape.index(len(coeff_ds.proxy.values) - 1) |
||
89 | if aix != 0: |
||
90 | warn( |
||
91 | "Automatically changing axis. " |
||
92 | "This is ambiguous, to remove the ambiguity, " |
||
93 | "make sure that the different indexes (proxies) " |
||
94 | "are ordered along the zero-th axis in multi-" |
||
95 | "dimensional settings. I.e. each row corresponds " |
||
96 | "to a different index, Kp, PC, Ap, etc." |
||
97 | ) |
||
98 | sw_coeffs = sw_coeffs.swapaxes(aix, 0) |
||
99 | sw_coeffs = np.vstack([sw_coeffs, np.ones(sw_coeffs.shape[1])]) |
||
100 | else: |
||
101 | aix = sw_coeffs.shape.index(len(coeff_ds.proxy.values)) |
||
102 | if aix != 0: |
||
103 | warn( |
||
104 | "Automatically changing axis. " |
||
105 | "This is ambiguous, to remove the ambiguity, " |
||
106 | "make sure that the different indexes (proxies) " |
||
107 | "are ordered along the zero-th axis in multi-" |
||
108 | "dimensional settings. I.e. each row corresponds " |
||
109 | "to a different index, Kp, PC, Ap, etc." |
||
110 | ) |
||
111 | sw_coeffs = sw_coeffs.swapaxes(aix, 0) |
||
112 | extra_dims = ["dim_{0}".format(_d) for _d in range(sw_coeffs.ndim - 1)] |
||
113 | sw_coeffs = xr.DataArray( |
||
114 | sw_coeffs, |
||
115 | dims=["proxy"] + extra_dims, |
||
116 | coords={"proxy": coeff_ds.proxy.values}, |
||
117 | ) |
||
118 | |||
119 | # Calculate model (mean) values from `beta` |
||
120 | # fill NaNs with zero for `.dot()` |
||
121 | coeffs = coeff_sel.beta.fillna(0.) |
||
122 | q = coeffs.dot(sw_coeffs) |
||
123 | q = q.rename("log_q") |
||
124 | q.attrs = { |
||
125 | "long_name": "natural logarithm of ionization rate", |
||
126 | "units": "log(cm-3 s-1)", |
||
127 | } |
||
128 | if not return_var: |
||
129 | return q |
||
130 | |||
131 | # Calculate variance of the model from `beta_std` |
||
132 | # fill NaNs with zero for `.dot()` |
||
133 | coeffv = coeff_sel.beta_std.fillna(0.)**2 |
||
134 | q_var = coeffv.dot(sw_coeffs**2) |
||
135 | q_var = q_var.rename("var_log_q") |
||
136 | q_var.attrs = { |
||
137 | "long_name": "variance of the natural logarithm of ionization rate", |
||
138 | "units": "1", |
||
139 | } |
||
140 | return q, q_var |
||
141 |