diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..6a3765b4 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,4 @@ +e451191cd772d9effbec8d64fe5d1e68a9e9e954 +d4572b0384ffdc009a8195c698b3de4e2532020b +1d009ed2ce5a26ddb7336bde38cfe483e9278ac2 +bfd79b562cd363e155c81d73e8b8e607bf4ae087 \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 136a830a..1392d485 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 9e92b4dd..21131c5f 100644 --- a/docs/swapi/figure_src/figure_utils.py +++ b/docs/swapi/figure_src/figure_utils.py @@ -4,15 +4,15 @@ 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 REPO_ROOT = Path(__file__).resolve().parents[3] sys.path.insert(0, str(REPO_ROOT)) -# ruff: disable[E402] from imap_l3_processing.constants import ( METERS_PER_KILOMETER, PROTON_CHARGE_COULOMBS, @@ -20,7 +20,6 @@ ) from imap_l3_processing.swapi.constants import SWAPI_K_FACTOR from imap_l3_processing.swapi.response.swapi_response import SwapiResponse -# ruff: enable[E402] FIGURES_DIR = REPO_ROOT / "docs" / "swapi" / "figures" @@ -180,12 +179,11 @@ def run_parallel_map( results: list[_T | None] = [None] * n_items report_every = max(1, n_items // 20) with multiprocessing.get_context("fork").Pool(processes=n_workers) as pool: - completed = 0 for index, value in pool.imap_unordered( _IndexedCall(process_one), range(n_items), chunksize=chunksize ): results[index] = value - completed += 1 + completed = index + 1 if completed % report_every == 0 or completed == n_items: elapsed = time.perf_counter() - start print(f" {desc}: {completed}/{n_items} ({elapsed:.1f}s)") diff --git a/docs/swapi/figure_src/plot_alpha_peak_finding.py b/docs/swapi/figure_src/plot_alpha_peak_finding.py old mode 100644 new mode 100755 index a4e9466c..9affb556 --- 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 @@ -126,9 +127,7 @@ def _furnish_spice_around(date_yyyymmdd: str) -> None: spk_start = target - timedelta(days=90) metakernel_url = ( - urlparse(imap_data_access.config["DATA_ACCESS_URL"]) - ._replace(path="metakernel") - .geturl() + urlparse(imap_data_access.config["DATA_ACCESS_URL"])._replace(path="metakernel").geturl() ) j2000 = datetime(2000, 1, 1, 12) @@ -176,23 +175,15 @@ def _read_5_sweep_block( epoch_ns = np.asarray( cdf.raw_var("epoch")[sweep_start : sweep_start + n_sweeps], dtype=np.int64 ) - cr = np.asarray( - cdf["swp_coin_rate"][sweep_start : sweep_start + n_sweeps, :], dtype=float - ) - esa = np.asarray( - cdf["esa_energy"][sweep_start : sweep_start + n_sweeps, :], dtype=float - ) + cr = np.asarray(cdf["swp_coin_rate"][sweep_start : sweep_start + n_sweeps, :], dtype=float) + esa = np.asarray(cdf["esa_energy"][sweep_start : sweep_start + n_sweeps, :], dtype=float) return epoch_ns, cr, esa 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() # --------------------------------------------------------------------------- # @@ -351,8 +342,7 @@ def _plot_case(ax, swapi_response, cdf_path, mag_data, chunk_index): def main(): if not os.environ.get("IMAP_API_KEY"): raise SystemExit( - "IMAP_API_KEY environment variable is not set. " - "Export it before running this script." + "IMAP_API_KEY environment variable is not set. Export it before running this script." ) print(f"Downloading L2 for {DATE_YYYYMMDD}…") cdf_path = _download_l2(DATE_YYYYMMDD) diff --git a/docs/swapi/figure_src/plot_calibration_curves.py b/docs/swapi/figure_src/plot_calibration_curves.py old mode 100644 new mode 100755 index ba062887..03e1fbe5 --- 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] @@ -37,9 +37,7 @@ def main(): eff_area = area_df["effective_area"].to_numpy() transmission = swapi_response._azimuthal_transmission - azimuths = ( - np.arange(len(transmission)) * SwapiResponse.AZIMUTHAL_TRANSMISSION_SPACING_DEG - ) + azimuths = np.arange(len(transmission)) * SwapiResponse.AZIMUTHAL_TRANSMISSION_SPACING_DEG fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4)) diff --git a/docs/swapi/figure_src/plot_collapsed_response_grid.py b/docs/swapi/figure_src/plot_collapsed_response_grid.py old mode 100644 new mode 100755 index 21f9a6b1..328d867f --- a/docs/swapi/figure_src/plot_collapsed_response_grid.py +++ b/docs/swapi/figure_src/plot_collapsed_response_grid.py @@ -23,20 +23,16 @@ 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 old mode 100644 new mode 100755 index 040aa57f..bed60e29 --- 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) @@ -86,9 +86,7 @@ def _load_wind_samples(csv_path: Path) -> tuple[np.ndarray, ...]: f"Missing WIND samples CSV: {csv_path}. " f"Run scripts/swapi/sample_wind_solar_wind.py first." ) - cols = np.genfromtxt( - csv_path, delimiter=",", names=True, dtype=None, encoding="utf-8" - ) + cols = np.genfromtxt(csv_path, delimiter=",", names=True, dtype=None, encoding="utf-8") return ( cols["v_R_km_s"].astype(float), cols["proton_temperature_K"].astype(float), @@ -177,7 +175,7 @@ def _process_one(i): ) try: initial_guess = calculate_initial_guess(fit_ctx) - except Exception: + except Exception: # noqa: BLE001 initial_guess = SolarWindParams( density=float("nan"), velocity_rtn=np.array([float("nan")] * 3), @@ -186,12 +184,13 @@ def _process_one(i): ) try: result = fit_solar_wind_proton_model(fit_ctx) - except Exception as e: + except Exception as e: # noqa: BLE001 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( @@ -293,9 +292,7 @@ def _plot_results(data: pd.DataFrame) -> None: color_initial_guess = "tab:orange" color_final_fit = "tab:blue" - for ax, (label, true_key, init_key, fit_key, fit_sigma_key, scale) in zip( - axes, plot_columns - ): + for ax, (label, true_key, init_key, fit_key, fit_sigma_key, scale) in zip(axes, plot_columns): truth = data[true_key] init = data[init_key] fit = data[fit_key] @@ -377,7 +374,7 @@ def _plot_results(data: pd.DataFrame) -> None: va="top", ha="left", fontsize=6.5, - bbox=dict(boxstyle="round,pad=0.3", fc="white", alpha=0.75), + bbox={"boxstyle": "round,pad=0.3", "fc": "white", "alpha": 0.75}, ) axes[0].legend(fontsize=8, loc="lower right", framealpha=0.8) @@ -393,9 +390,7 @@ def _plot_results(data: pd.DataFrame) -> None: def _rmse_label(truth, estimated, scale): mask = np.isfinite(estimated) if scale == "log": - rmse = np.sqrt( - np.mean((np.log10(estimated[mask]) - np.log10(truth[mask])) ** 2) - ) + rmse = np.sqrt(np.mean((np.log10(estimated[mask]) - np.log10(truth[mask])) ** 2)) return f"RMSE log₁₀ = {rmse:.3f}" else: rmse = np.sqrt(np.mean((estimated[mask] - truth[mask]) ** 2)) diff --git a/docs/swapi/figure_src/plot_passband_boundaries.py b/docs/swapi/figure_src/plot_passband_boundaries.py old mode 100644 new mode 100755 index 57abb5c8..4f707571 --- a/docs/swapi/figure_src/plot_passband_boundaries.py +++ b/docs/swapi/figure_src/plot_passband_boundaries.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import sys from pathlib import Path @@ -8,10 +10,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 @@ -40,9 +42,7 @@ def main(): else response_grid.sg_passband ) axis = axes[row, column] - last_image = plot_region_panel( - axis, grid, region, esa_voltage, central_speed - ) + last_image = plot_region_panel(axis, grid, region, esa_voltage, central_speed) if column == 0: axis.set_ylabel("Elevation (deg)") @@ -101,9 +101,7 @@ def grid_axis_coordinates( ) -> tuple[np.ndarray, np.ndarray]: n_elevations, n_speed_ratios = transmission_values.shape elevations = grid.min_elevation + np.arange(n_elevations) * grid.elevation_spacing - speed_ratios = ( - grid.min_speed_ratio + np.arange(n_speed_ratios) * grid.speed_ratio_spacing - ) + speed_ratios = grid.min_speed_ratio + np.arange(n_speed_ratios) * grid.speed_ratio_spacing return elevations, speed_ratios @@ -148,9 +146,7 @@ def draw_integration_window_outline( closed_x = np.concatenate( [lower_speed_ratios, upper_speed_ratios[::-1], [lower_speed_ratios[0]]] ) - closed_y = np.concatenate( - [active_elevations, active_elevations[::-1], [active_elevations[0]]] - ) + closed_y = np.concatenate([active_elevations, active_elevations[::-1], [active_elevations[0]]]) axis.plot(closed_x, closed_y, color="tab:blue", linewidth=2.5) diff --git a/docs/swapi/figure_src/plot_pui_cutoff_staircase.py b/docs/swapi/figure_src/plot_pui_cutoff_staircase.py old mode 100644 new mode 100755 index 7187749a..542f1bbf --- a/docs/swapi/figure_src/plot_pui_cutoff_staircase.py +++ b/docs/swapi/figure_src/plot_pui_cutoff_staircase.py @@ -28,14 +28,12 @@ REPO_ROOT = Path(__file__).resolve().parents[3] sys.path.insert(0, str(REPO_ROOT)) -# ruff: disable[E402] import matplotlib matplotlib.use("Agg") 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 ( @@ -60,7 +58,6 @@ from imap_l3_processing.swapi.l3a.utils import ( velocity_components_to_angles_in_instrument_frame, ) -# ruff: enable[E402] _SW_SPEED_KMS = 450.0 _SW_AZIMUTH_DEG = 0.0 @@ -98,9 +95,7 @@ def _params(cutoff_speed_kms: float) -> FittingParameters: def main(): voltages = ( - pd.read_csv( - REPO_ROOT / "tests" / "test_data" / "swapi" / "pui_count_rate_reference.csv" - ) + pd.read_csv(REPO_ROOT / "tests" / "test_data" / "swapi" / "pui_count_rate_reference.csv") .iloc[:, 0] .to_numpy() ) @@ -143,10 +138,8 @@ 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( @@ -183,9 +176,9 @@ def sampled_distribution(grid, params, apply_cutoff): coarse_grid, params, apply_cutoff=True ) # Production: trapezoidal partial cell, via the real forward model. - rate_with[i] = calculate_coincidence_rate( - chunk_response, distribution, params - )[0, voltage_index] + rate_with[i] = calculate_coincidence_rate(chunk_response, distribution, params)[ + 0, voltage_index + ] # Converged reference: grid-corrected cutoff on a fine grid. f_fine = sampled_distribution(fine_grid, params, apply_cutoff=False) apply_partial_heaviside_at_cutoff(f_fine, fine_grid, cutoff) diff --git a/docs/swapi/figure_src/plot_pui_distribution.py b/docs/swapi/figure_src/plot_pui_distribution.py old mode 100644 new mode 100755 index 5e1b3767..18e61899 --- a/docs/swapi/figure_src/plot_pui_distribution.py +++ b/docs/swapi/figure_src/plot_pui_distribution.py @@ -22,13 +22,11 @@ REPO_ROOT = Path(__file__).resolve().parents[3] sys.path.insert(0, str(REPO_ROOT)) -# ruff: disable[E402] import matplotlib 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 @@ -39,7 +37,6 @@ FittingParameters, VasyliunasSiscoeDistribution, ) -# ruff: enable[E402] _CUTOFF_SPEED_KMS = 450.0 _SW_SPEED_INERTIAL_KMS = 450.0 @@ -94,9 +91,7 @@ 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 old mode 100644 new mode 100755 index 900b2b97..18d7af9b --- a/docs/swapi/figure_src/plot_pui_reference_comparison.py +++ b/docs/swapi/figure_src/plot_pui_reference_comparison.py @@ -21,21 +21,17 @@ REPO_ROOT = Path(__file__).resolve().parents[3] sys.path.insert(0, str(REPO_ROOT)) -# ruff: disable[E402] import matplotlib matplotlib.use("Agg") 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 -# ruff: enable[E402] -_REFERENCE_CSV_PATH = ( - REPO_ROOT / "tests" / "test_data" / "swapi" / "pui_count_rate_reference.csv" -) +_REFERENCE_CSV_PATH = REPO_ROOT / "tests" / "test_data" / "swapi" / "pui_count_rate_reference.csv" # Must match scripts/swapi/pui_xarray_reference.py so the production kernel is # evaluated at the same point as the precomputed reference CSV. @@ -61,6 +57,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, @@ -75,7 +73,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, @@ -84,9 +81,7 @@ def compute_production_rates(voltages_v: np.ndarray) -> np.ndarray: background_count_rate=_BACKGROUND_RATE_HZ, ) lut = DensityOfNeutralHeliumLookupTable.from_file(_DENSITY_LUT_PATH) - min_speed_kms = max( - 1.0, _CUTOFF_SPEED_KMS * lut.get_minimum_distance() / _HELIO_DIST_AU - ) + min_speed_kms = max(1.0, _CUTOFF_SPEED_KMS * lut.get_minimum_distance() / _HELIO_DIST_AU) vasyliunas_siscoe_distribution = VasyliunasSiscoeDistribution( ephemeris_time=0.0, solar_wind_speed_inertial_frame=_SW_SPEED_INERTIAL_KMS, @@ -165,7 +160,7 @@ def main(): try: production_rate_hz = compute_production_rates(voltage_v) - except Exception: + except Exception: # noqa: BLE001 traceback.print_exc() print("calculate_coincidence_rate failed — skipping production overlay.") else: diff --git a/docs/swapi/figure_src/plot_real_data_fit.py b/docs/swapi/figure_src/plot_real_data_fit.py old mode 100644 new mode 100755 index af29fe15..33fd811c --- 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 = "