diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 136a830a9..1392d4851 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: | docs/.*\.(svg|png)$ # documentation images ) - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.15.2" + rev: "v0.16.10" hooks: - id: ruff-check args: [--fix] diff --git a/docs/swapi/figure_src/figure_utils.py b/docs/swapi/figure_src/figure_utils.py index 9e9dc7b2a..84623c6c8 100644 --- a/docs/swapi/figure_src/figure_utils.py +++ b/docs/swapi/figure_src/figure_utils.py @@ -4,8 +4,9 @@ import os import sys import time +from collections.abc import Callable from pathlib import Path -from typing import Callable, TypeVar +from typing import TypeVar import numpy as np @@ -42,14 +43,68 @@ def load_swapi_response() -> SwapiResponse: COARSE_SWEEP_VOLTAGES_MEAN_V = np.array( [ - 9895.52, 9088.69, 8348.80, 7667.55, 7042.16, 6469.31, 5941.77, 5457.31, - 5013.22, 4603.65, 4230.77, 3886.92, 3569.16, 3278.72, 3011.13, 2766.25, - 2539.54, 2333.83, 2144.24, 1969.31, 1808.74, 1660.86, 1525.75, 1401.82, - 1287.58, 1182.24, 1085.15, 995.55, 914.31, 839.94, 771.70, 709.46, - 651.59, 598.47, 549.91, 505.12, 463.89, 425.92, 391.18, 359.35, - 329.94, 303.02, 278.25, 255.55, 234.77, 215.61, 197.95, 181.82, - 167.04, 153.46, 140.91, 129.50, 118.91, 109.20, 100.30, 92.11, - 84.61, 77.73, 71.40, 65.59, 60.23, 55.34, + 9895.52, + 9088.69, + 8348.80, + 7667.55, + 7042.16, + 6469.31, + 5941.77, + 5457.31, + 5013.22, + 4603.65, + 4230.77, + 3886.92, + 3569.16, + 3278.72, + 3011.13, + 2766.25, + 2539.54, + 2333.83, + 2144.24, + 1969.31, + 1808.74, + 1660.86, + 1525.75, + 1401.82, + 1287.58, + 1182.24, + 1085.15, + 995.55, + 914.31, + 839.94, + 771.70, + 709.46, + 651.59, + 598.47, + 549.91, + 505.12, + 463.89, + 425.92, + 391.18, + 359.35, + 329.94, + 303.02, + 278.25, + 255.55, + 234.77, + 215.61, + 197.95, + 181.82, + 167.04, + 153.46, + 140.91, + 129.50, + 118.91, + 109.20, + 100.30, + 92.11, + 84.61, + 77.73, + 71.40, + 65.59, + 60.23, + 55.34, ] ) diff --git a/docs/swapi/figure_src/plot_alpha_peak_finding.py b/docs/swapi/figure_src/plot_alpha_peak_finding.py index 0b8446d58..6cf26ef11 100644 --- a/docs/swapi/figure_src/plot_alpha_peak_finding.py +++ b/docs/swapi/figure_src/plot_alpha_peak_finding.py @@ -34,6 +34,8 @@ sys.path.insert(0, str(Path(__file__).resolve().parents[3])) +from figure_utils import FIGURES_DIR, load_swapi_response + from imap_l3_processing.constants import ( ALPHA_MASS_PER_CHARGE_M_P_PER_E, ALPHA_PARTICLE_MASS_KG, @@ -70,7 +72,6 @@ ) from imap_l3_processing.swapi.response.deadtime import deadtime_factor from imap_l3_processing.utils import SpiceKernelTypes -from figure_utils import FIGURES_DIR, load_swapi_response DATE_YYYYMMDD = "20260101" N_SWEEPS = 5 @@ -187,8 +188,12 @@ def _read_5_sweep_block( def _coarse_measurement_times_ns(epoch_ns: np.ndarray) -> np.ndarray: coarse_bins = np.arange(SWAPI_COARSE_SWEEP_BINS.start, SWAPI_COARSE_SWEEP_BINS.stop) - seconds_into_sweep = coarse_bins * SWAPI_BIN_PERIOD_S + SWAPI_LIVETIME_CENTER_OFFSET_S - return (epoch_ns[:, None] + seconds_into_sweep * ONE_SECOND_IN_NANOSECONDS).flatten() + seconds_into_sweep = ( + coarse_bins * SWAPI_BIN_PERIOD_S + SWAPI_LIVETIME_CENTER_OFFSET_S + ) + return ( + epoch_ns[:, None] + seconds_into_sweep * ONE_SECOND_IN_NANOSECONDS + ).flatten() # --------------------------------------------------------------------------- # @@ -261,9 +266,7 @@ def _plot_case(ax, swapi_response, cdf_path, mag_data, chunk_index): proton_moments=proton_moments, magnetic_field_direction=b_hat, ) - alpha_velocity_rtn = np.array( - [c.nominal_value for c in alpha_moments.velocity_rtn] - ) + alpha_velocity_rtn = np.array([c.nominal_value for c in alpha_moments.velocity_rtn]) alpha_sw = SolarWindParams( density=alpha_moments.density.nominal_value, velocity_rtn=alpha_velocity_rtn, diff --git a/docs/swapi/figure_src/plot_calibration_curves.py b/docs/swapi/figure_src/plot_calibration_curves.py index ba0628877..e96022bea 100644 --- a/docs/swapi/figure_src/plot_calibration_curves.py +++ b/docs/swapi/figure_src/plot_calibration_curves.py @@ -17,9 +17,9 @@ import matplotlib.pyplot as plt import numpy as np import pandas as pd +from figure_utils import FIGURES_DIR, load_swapi_response from imap_l3_processing.swapi.response.swapi_response import SwapiResponse -from figure_utils import FIGURES_DIR, load_swapi_response _AREA_CSV = ( Path(__file__).resolve().parents[3] diff --git a/docs/swapi/figure_src/plot_collapsed_response_grid.py b/docs/swapi/figure_src/plot_collapsed_response_grid.py index 53be77b27..7211d9a5a 100644 --- a/docs/swapi/figure_src/plot_collapsed_response_grid.py +++ b/docs/swapi/figure_src/plot_collapsed_response_grid.py @@ -23,16 +23,20 @@ import matplotlib.pyplot as plt import numpy as np import pandas as pd +from figure_utils import FIGURES_DIR, REPO_ROOT, load_swapi_response +from imap_l3_processing.constants import HE_PUI_PARTICLE_MASS_PER_CHARGE_M_P_PER_E from imap_l3_processing.swapi.l3a.science.pickup_ion.collapsed_response_grid import ( build_collapsed_response_grid, solar_wind_frame_speed_range, ) -from figure_utils import FIGURES_DIR, REPO_ROOT, load_swapi_response -from imap_l3_processing.constants import HE_PUI_PARTICLE_MASS_PER_CHARGE_M_P_PER_E _REFERENCE_CSV_PATH = ( - REPO_ROOT / "tests" / "test_data" / "swapi" / "collapsed_response_grid_reference.csv" + REPO_ROOT + / "tests" + / "test_data" + / "swapi" + / "collapsed_response_grid_reference.csv" ) _ESA_VOLTAGE = 5000.0 diff --git a/docs/swapi/figure_src/plot_fit_accuracy.py b/docs/swapi/figure_src/plot_fit_accuracy.py index 795583dee..5ec337861 100644 --- a/docs/swapi/figure_src/plot_fit_accuracy.py +++ b/docs/swapi/figure_src/plot_fit_accuracy.py @@ -29,19 +29,13 @@ import types +import matplotlib import numpy as np import pandas as pd from uncertainties import UFloat -import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt - -from imap_l3_processing.constants import ( - PROTON_MASS_KG, - PROTON_MASS_PER_CHARGE_M_P_PER_E, -) -from imap_l3_processing.swapi.constants import SWAPI_LIVETIME_S from figure_utils import ( COARSE_BIN_INDICES_IN_SWEEP, COARSE_SWEEP_VOLTAGES_MEAN_V, @@ -50,20 +44,26 @@ load_swapi_response, run_parallel_map, ) -from imap_l3_processing.swapi.l3a.science.solar_wind.proton.fit_solar_wind_proton_model import ( - fit_solar_wind_proton_model, + +from imap_l3_processing.constants import ( + PROTON_MASS_KG, + PROTON_MASS_PER_CHARGE_M_P_PER_E, ) -from imap_l3_processing.swapi.l3a.science.solar_wind.proton.calculate_initial_guess import ( - calculate_initial_guess, +from imap_l3_processing.swapi.constants import SWAPI_LIVETIME_S +from imap_l3_processing.swapi.l3a.science.solar_wind.fit_context import ( + build_solar_wind_fit_context, ) from imap_l3_processing.swapi.l3a.science.solar_wind.forward_model import ( model_solar_wind_ideal_coincidence_rates, ) -from imap_l3_processing.swapi.response.deadtime import deadtime_factor -from imap_l3_processing.swapi.l3a.science.solar_wind.fit_context import ( - build_solar_wind_fit_context, -) from imap_l3_processing.swapi.l3a.science.solar_wind.params import SolarWindParams +from imap_l3_processing.swapi.l3a.science.solar_wind.proton.calculate_initial_guess import ( + calculate_initial_guess, +) +from imap_l3_processing.swapi.l3a.science.solar_wind.proton.fit_solar_wind_proton_model import ( + fit_solar_wind_proton_model, +) +from imap_l3_processing.swapi.response.deadtime import deadtime_factor _N_SWEEPS = 5 _N_BINS = len(COARSE_SWEEP_VOLTAGES_MEAN_V) @@ -188,10 +188,11 @@ def _process_one(i): result = fit_solar_wind_proton_model(fit_ctx) except Exception as e: print(f" case {i}: fit failed ({type(e).__name__}: {e}); flagging bad") + from uncertainties import ufloat + from imap_l3_processing.swapi.l3a.science.solar_wind.proton.fit_solar_wind_proton_model import ( ProtonSolarWindFitResult, ) - from uncertainties import ufloat nan_uf = ufloat(float("nan"), float("nan")) result = ProtonSolarWindFitResult( @@ -315,7 +316,7 @@ def _plot_results(data: pd.DataFrame) -> None: marker="o", zorder=2, label="Initial guess", - rasterized=True + rasterized=True, ) ax.errorbar( truth[good], @@ -344,7 +345,7 @@ def _plot_results(data: pd.DataFrame) -> None: edgecolors="k", linewidths=0.4, zorder=4, - rasterized=True + rasterized=True, ) ax.scatter( truth[~good], @@ -356,7 +357,7 @@ def _plot_results(data: pd.DataFrame) -> None: edgecolors="k", linewidths=0.4, zorder=4, - rasterized=True + rasterized=True, ) ax.set_xlabel(f"True {label}", fontsize=9) diff --git a/docs/swapi/figure_src/plot_passband_boundaries.py b/docs/swapi/figure_src/plot_passband_boundaries.py index 862d543ee..5187f9b2b 100644 --- a/docs/swapi/figure_src/plot_passband_boundaries.py +++ b/docs/swapi/figure_src/plot_passband_boundaries.py @@ -8,10 +8,10 @@ matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np +from figure_utils import FIGURES_DIR, load_swapi_response from imap_l3_processing.swapi.response.passband_grid import PassbandGrid from imap_l3_processing.swapi.response.swapi_response import SwapiResponse -from figure_utils import FIGURES_DIR, load_swapi_response _ELEVATION_DISPLAY_LIMIT_DEG = 15.0 _ACTIVE_ELEVATION_SAMPLE_COUNT = 300 @@ -85,9 +85,7 @@ def plot_region_panel( grid, grid.max_boundary, active_elevations, np.maximum ) - image = draw_transmission_heatmap( - axis, grid.values, elevations, speed_ratios - ) + image = draw_transmission_heatmap(axis, grid.values, elevations, speed_ratios) draw_integration_window_outline( axis, active_elevations, lower_speed_ratios, upper_speed_ratios ) diff --git a/docs/swapi/figure_src/plot_pui_cutoff_staircase.py b/docs/swapi/figure_src/plot_pui_cutoff_staircase.py index 9d16ad2a4..a075e092d 100644 --- a/docs/swapi/figure_src/plot_pui_cutoff_staircase.py +++ b/docs/swapi/figure_src/plot_pui_cutoff_staircase.py @@ -34,10 +34,12 @@ import matplotlib.pyplot as plt import numpy as np import pandas as pd - from figure_utils import FIGURES_DIR, load_swapi_response -from imap_l3_processing.constants import HE_PUI_PARTICLE_MASS_PER_CHARGE_M_P_PER_E, ONE_AU_IN_KM +from imap_l3_processing.constants import ( + HE_PUI_PARTICLE_MASS_PER_CHARGE_M_P_PER_E, + ONE_AU_IN_KM, +) from imap_l3_processing.swapi.l3a.science.pickup_ion.calculate_coincidence_rate import ( apply_partial_heaviside_at_cutoff, calculate_coincidence_rate, @@ -53,7 +55,9 @@ FittingParameters, VasyliunasSiscoeDistribution, ) -from imap_l3_processing.swapi.l3a.utils import velocity_components_to_angles_in_instrument_frame +from imap_l3_processing.swapi.l3a.utils import ( + velocity_components_to_angles_in_instrument_frame, +) _SW_SPEED_KMS = 450.0 _SW_AZIMUTH_DEG = 0.0 @@ -90,9 +94,13 @@ def _params(cutoff_speed_kms: float) -> FittingParameters: def main(): - voltages = pd.read_csv( - REPO_ROOT / "tests" / "test_data" / "swapi" / "pui_count_rate_reference.csv" - ).iloc[:, 0].to_numpy() + voltages = ( + pd.read_csv( + REPO_ROOT / "tests" / "test_data" / "swapi" / "pui_count_rate_reference.csv" + ) + .iloc[:, 0] + .to_numpy() + ) voltage_index = int(np.argmin(np.abs(voltages - _ESA_VOLTAGE_V))) swapi_response = load_swapi_response() @@ -109,11 +117,13 @@ def main(): azimuth_rad = np.radians(_SW_AZIMUTH_DEG) elevation_rad = np.radians(_SW_ELEVATION_DEG) - bulk_vec = _SW_SPEED_KMS * np.array([ - -np.cos(elevation_rad) * np.sin(azimuth_rad), - -np.cos(elevation_rad) * np.cos(azimuth_rad), - -np.sin(elevation_rad), - ]) + bulk_vec = _SW_SPEED_KMS * np.array( + [ + -np.cos(elevation_rad) * np.sin(azimuth_rad), + -np.cos(elevation_rad) * np.cos(azimuth_rad), + -np.sin(elevation_rad), + ] + ) bulk_per_bin = np.broadcast_to(bulk_vec, (1, voltages.size, 3)).copy() chunk_response = build_chunk_collapsed_response( @@ -130,8 +140,10 @@ def main(): bin_weights = chunk_response.bin_weights[0, voltage_index, :] # Fine-grid reference response for the same voltage step. - bulk_azimuth_deg, bulk_elevation_deg = velocity_components_to_angles_in_instrument_frame( - bulk_vec[0], bulk_vec[1], bulk_vec[2] + bulk_azimuth_deg, bulk_elevation_deg = ( + velocity_components_to_angles_in_instrument_frame( + bulk_vec[0], bulk_vec[1], bulk_vec[2] + ) ) fine_grid = np.linspace(1.0, _GRID_MAX_KMS, _FINE_GRID_POINTS) fine_collapsed = build_collapsed_response_grid( @@ -145,9 +157,7 @@ def main(): bulk_elevation_deg, speed_in_sw_frame=fine_grid, ) - fine_weights = ( - fine_collapsed.values * fine_grid**2 * (fine_grid[1] - fine_grid[0]) - ) + fine_weights = fine_collapsed.values * fine_grid**2 * (fine_grid[1] - fine_grid[0]) # Below the neutral-helium LUT support the distribution is physically zero; # the LUT extrapolation returns non-finite values there, so clamp them. @@ -190,15 +200,26 @@ def sampled_distribution(grid, params, apply_cutoff): axis.axvline(grid_edges[0], color="0.85", lw=0.8, zorder=0, label="$v'$ grid edges") axis.plot( - _CUTOFF_SWEEP_KMS, rate_reference, "-", color="0.4", lw=1, - label=f"fine-grid reference", + _CUTOFF_SWEEP_KMS, + rate_reference, + "-", + color="0.4", + lw=1, + label="fine-grid reference", ) axis.scatter( - _CUTOFF_SWEEP_KMS, rate_without, color="tab:red", s=10, + _CUTOFF_SWEEP_KMS, + rate_without, + color="tab:red", + s=10, label="no correction", ) axis.scatter( - _CUTOFF_SWEEP_KMS, rate_with, color="tab:blue", s=10, marker='x', + _CUTOFF_SWEEP_KMS, + rate_with, + color="tab:blue", + s=10, + marker="x", label="with correction", ) @@ -207,7 +228,10 @@ def sampled_distribution(grid, params, apply_cutoff): axis.set_xlim(_CUTOFF_SWEEP_KMS[0], _CUTOFF_SWEEP_KMS[-1]) axis.annotate( rf"grid $\Delta v' = {delta_v_prime:.2f}$ km/s", - xy=(0.02, 0.04), xycoords="axes fraction", fontsize=9, color="0.3", + xy=(0.02, 0.04), + xycoords="axes fraction", + fontsize=9, + color="0.3", ) axis.grid(True, alpha=0.3) axis.legend(loc="upper left") diff --git a/docs/swapi/figure_src/plot_pui_distribution.py b/docs/swapi/figure_src/plot_pui_distribution.py index 79275342f..f8fc254cf 100644 --- a/docs/swapi/figure_src/plot_pui_distribution.py +++ b/docs/swapi/figure_src/plot_pui_distribution.py @@ -27,7 +27,6 @@ matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np - from figure_utils import FIGURES_DIR from imap_l3_processing.constants import ONE_AU_IN_KM @@ -92,7 +91,9 @@ def main(): label=r"cutoff speed $v_b$", ) axis.set_yscale("log") - axis.set_xlabel(r"Comoving speed $v' = \|\mathbf{v} - \mathbf{v}_\text{sw}\|$ [km/s]") + axis.set_xlabel( + r"Comoving speed $v' = \|\mathbf{v} - \mathbf{v}_\text{sw}\|$ [km/s]" + ) axis.set_ylabel(r"$f_\text{PUI}(v')$ [s$^3$ km$^{-6}$]") axis.set_xlim(speed_in_sw_frame[0], speed_in_sw_frame[-1]) axis.set_ylim(1e0, 1e4) diff --git a/docs/swapi/figure_src/plot_pui_reference_comparison.py b/docs/swapi/figure_src/plot_pui_reference_comparison.py index 9b32aaab5..e39a32b2a 100644 --- a/docs/swapi/figure_src/plot_pui_reference_comparison.py +++ b/docs/swapi/figure_src/plot_pui_reference_comparison.py @@ -27,8 +27,8 @@ import matplotlib.pyplot as plt import numpy as np import pandas as pd - from figure_utils import FIGURES_DIR + from imap_l3_processing.constants import HE_PUI_PARTICLE_MASS_PER_CHARGE_M_P_PER_E _REFERENCE_CSV_PATH = ( @@ -59,6 +59,8 @@ def compute_production_rates(voltages_v: np.ndarray) -> np.ndarray: """Build the chunk-level collapsed response and call the in-development production kernel. Imports live inside the function so a broken module doesn't break the figure script at import time.""" + from figure_utils import load_swapi_response + from imap_l3_processing.constants import ONE_AU_IN_KM from imap_l3_processing.swapi.l3a.science.pickup_ion.calculate_coincidence_rate import ( calculate_coincidence_rate, @@ -73,7 +75,6 @@ def compute_production_rates(voltages_v: np.ndarray) -> np.ndarray: FittingParameters, VasyliunasSiscoeDistribution, ) - from figure_utils import load_swapi_response fitting_params = FittingParameters( cooling_index=_COOLING_INDEX, @@ -95,14 +96,14 @@ def compute_production_rates(voltages_v: np.ndarray) -> np.ndarray: sw_az_rad = np.radians(_SW_AZIMUTH_DEG) sw_el_rad = np.radians(_SW_ELEVATION_DEG) - bulk_vec = _SW_SPEED_KMS * np.array([ - -np.cos(sw_el_rad) * np.sin(sw_az_rad), - -np.cos(sw_el_rad) * np.cos(sw_az_rad), - -np.sin(sw_el_rad), - ]) - bulk_sw_per_bin = np.broadcast_to( - bulk_vec, (1, voltages_v.size, 3) - ).copy() + bulk_vec = _SW_SPEED_KMS * np.array( + [ + -np.cos(sw_el_rad) * np.sin(sw_az_rad), + -np.cos(sw_el_rad) * np.cos(sw_az_rad), + -np.sin(sw_el_rad), + ] + ) + bulk_sw_per_bin = np.broadcast_to(bulk_vec, (1, voltages_v.size, 3)).copy() swapi_response = load_swapi_response() swapi_response.warm_cache(voltages_v) @@ -115,7 +116,9 @@ def compute_production_rates(voltages_v: np.ndarray) -> np.ndarray: min_speed_kms=min_speed_kms, central_effective_area_scale=_HELIUM_EFFICIENCY_RATIO, ) - return calculate_coincidence_rate(chunk_response, vasyliunas_siscoe_distribution, fitting_params)[0] + return calculate_coincidence_rate( + chunk_response, vasyliunas_siscoe_distribution, fitting_params + )[0] def main(): @@ -133,11 +136,17 @@ def main(): ) sw_az_rad = np.radians(_SW_AZIMUTH_DEG) sw_el_rad = np.radians(_SW_ELEVATION_DEG) - bulk_vec = _SW_SPEED_KMS * np.array([ - -np.cos(sw_el_rad) * np.sin(sw_az_rad), - -np.cos(sw_el_rad) * np.cos(sw_az_rad), - -np.sin(sw_el_rad), - ]) + 0.0 # normalize -0.0 to +0.0 for display + bulk_vec = ( + _SW_SPEED_KMS + * np.array( + [ + -np.cos(sw_el_rad) * np.sin(sw_az_rad), + -np.cos(sw_el_rad) * np.cos(sw_az_rad), + -np.sin(sw_el_rad), + ] + ) + + 0.0 + ) # normalize -0.0 to +0.0 for display axes[0].set_title( f"PUI He coincidence rate — m/q={_HELIUM_MASS_PER_CHARGE_M_P_PER_E:.0f}, " f"efficiency ratio={_HELIUM_EFFICIENCY_RATIO:.2f}\n" @@ -165,7 +174,7 @@ def main(): ".", color="red", label="Optimized", - markersize=4 + markersize=4, ) rel_err = np.abs(production_rate_hz - count_rate_hz) / count_rate_hz axes[1].semilogy(voltage_v, rel_err, ".", color="red") diff --git a/docs/swapi/figure_src/plot_real_data_fit.py b/docs/swapi/figure_src/plot_real_data_fit.py index 70c11f713..7024ce7e2 100644 --- a/docs/swapi/figure_src/plot_real_data_fit.py +++ b/docs/swapi/figure_src/plot_real_data_fit.py @@ -37,40 +37,40 @@ sys.path.insert(0, str(Path(__file__).resolve().parents[3])) +import scipy.optimize +from figure_utils import FIGURES_DIR, REPO_ROOT, load_swapi_response + from imap_l3_processing.constants import ( BOLTZMANN_CONSTANT_JOULES_PER_KELVIN, ONE_SECOND_IN_NANOSECONDS, PROTON_MASS_KG, PROTON_MASS_PER_CHARGE_M_P_PER_E, ) -import scipy.optimize - +from imap_l3_processing.swapi.constants import ( + SWAPI_BIN_PERIOD_S, + SWAPI_COARSE_SWEEP_BINS, + SWAPI_FINE_SWEEP_BINS, + SWAPI_K_FACTOR, + SWAPI_L2_K_FACTOR, + SWAPI_LIVETIME_CENTER_OFFSET_S, + SWAPI_SCIENCE_BINS, +) from imap_l3_processing.swapi.l3a.science.solar_wind.fit_context import ( build_solar_wind_fit_context, ) from imap_l3_processing.swapi.l3a.science.solar_wind.forward_model import ( model_solar_wind_ideal_coincidence_rates, ) +from imap_l3_processing.swapi.l3a.science.solar_wind.params import SolarWindParams from imap_l3_processing.swapi.l3a.science.solar_wind.proton.fit_solar_wind_proton_model import ( fit_solar_wind_proton_model, ) -from imap_l3_processing.swapi.l3a.science.solar_wind.params import SolarWindParams from imap_l3_processing.swapi.l3a.utils import ( get_spacecraft_velocity_rtn, get_swapi_geometry, ) from imap_l3_processing.swapi.response.deadtime import deadtime_factor -from imap_l3_processing.swapi.constants import ( - SWAPI_BIN_PERIOD_S, - SWAPI_COARSE_SWEEP_BINS, - SWAPI_FINE_SWEEP_BINS, - SWAPI_K_FACTOR, - SWAPI_L2_K_FACTOR, - SWAPI_LIVETIME_CENTER_OFFSET_S, - SWAPI_SCIENCE_BINS, -) from imap_l3_processing.utils import SpiceKernelTypes -from figure_utils import FIGURES_DIR, REPO_ROOT, load_swapi_response _DOC_PATH = REPO_ROOT / "docs" / "swapi" / "proton-sw.md" _TABLE_BEGIN = "