| 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 |