diff --git a/docs/generate_individual_options.py b/docs/generate_individual_options.py new file mode 100644 index 0000000..35b3bc5 --- /dev/null +++ b/docs/generate_individual_options.py @@ -0,0 +1,388 @@ +"""Generate all individual MSIS option example files. + +This script creates individual plot_option_XX_*.py files for all 14 main MSIS options. +Each file is designed to work with sphinx_gallery documentation system. +""" + +import os +import subprocess + + +# Define all options with their descriptions +OPTIONS_INFO = { + 0: { + "name": "F10.7 Effects", + "filename": "f107_effects", + "description": "Solar EUV flux variations", + "details": [ + "Solar extreme ultraviolet (EUV) radiation heating", + "Solar flux proxy (F10.7 radio flux) dependencies", + "Solar cycle and rotation effects on atmospheric heating", + "Thermospheric temperature and density variations", + ], + "importance": [ + "Primary driver of thermospheric density variations", + "Essential for solar cycle modeling and predictions", + "Critical for long-term orbital decay calculations", + "Fundamental for understanding solar-terrestrial coupling", + ], + }, + 1: { + "name": "Time Independent", + "filename": "time_independent", + "description": "Baseline atmospheric structure", + "details": [ + "Baseline atmospheric structure that varies with latitude", + "North-south atmospheric density and temperature gradients", + "Geographic variations in atmospheric properties", + "Time-independent latitude-dependent reference state", + ], + "importance": [ + "Provides fundamental atmospheric structure from poles to equator", + "Essential for accurate geographic atmospheric modeling", + "Critical for understanding latitude-dependent atmospheric behavior", + "Foundation for all other atmospheric variations", + ], + }, + 2: { + "name": "Symmetric Annual", + "filename": "symmetric_annual", + "description": "Annual seasonal variations (symmetric)", + "details": [ + "Seasonal atmospheric heating variations", + "Annual solar declination effects", + "Symmetric seasonal patterns in both hemispheres", + "Yearly cycle in atmospheric temperature and density", + ], + "importance": [ + "Models primary seasonal atmospheric changes", + "Essential for year-round atmospheric predictions", + "Critical for understanding seasonal density variations", + "Important for annual satellite drag variations", + ], + }, + 3: { + "name": "Symmetric Semiannual", + "filename": "symmetric_semiannual", + "description": "Semiannual atmospheric oscillations", + "details": [ + "Twice-yearly atmospheric oscillations", + "Semiannual density and temperature variations", + "Atmospheric response to semiannual solar forcing", + "Global atmospheric circulation effects", + ], + "importance": [ + "Captures important semiannual density variations", + "Affects satellite drag twice per year", + "Important for atmospheric dynamics understanding", + "Contributes to seasonal atmospheric modeling accuracy", + ], + }, + 4: { + "name": "Asymmetric Annual", + "filename": "asymmetric_annual", + "description": "Asymmetric annual variations", + "details": [ + "Hemisphere-dependent seasonal effects", + "Asymmetric seasonal atmospheric responses", + "North-south hemisphere seasonal differences", + "Latitude-dependent annual variations", + ], + "importance": [ + "Models hemisphere-specific seasonal differences", + "Important for accurate polar region modeling", + "Captures asymmetric seasonal atmospheric responses", + "Essential for global atmospheric accuracy", + ], + }, + 5: { + "name": "Asymmetric Semiannual", + "filename": "asymmetric_semiannual", + "description": "Asymmetric semiannual variations", + "details": [ + "Hemisphere-specific semiannual oscillations", + "Asymmetric twice-yearly atmospheric changes", + "Latitude-dependent semiannual effects", + "Complex seasonal atmospheric dynamics", + ], + "importance": [ + "Provides realistic hemisphere-dependent variations", + "Important for accurate seasonal modeling", + "Captures complex semiannual atmospheric behavior", + "Essential for global atmospheric precision", + ], + }, + 6: { + "name": "Diurnal", + "filename": "diurnal", + "description": "Day/night atmospheric variations", + "details": [ + "Solar heating during daytime hours", + "Radiative cooling during nighttime", + "Temperature-driven density changes", + "Local time dependencies in atmospheric structure", + ], + "importance": [ + "Most important short-term atmospheric variation", + "Essential for realistic atmospheric modeling", + "Critical for satellite drag predictions", + "Fundamental for space weather applications", + ], + }, + 7: { + "name": "Semidiurnal", + "filename": "semidiurnal", + "description": "12-hour atmospheric tidal effects", + "details": [ + "Thermal forcing by solar heating", + "Gravitational tidal forces (minor contribution)", + "Atmospheric wave propagation and resonance", + "Interaction with the Earth's rotation", + ], + "importance": [ + "Important for atmospheric wave dynamics", + "Affects satellite drag calculations", + "Key component of upper atmospheric dynamics", + "Provides insight into atmospheric wave propagation", + ], + }, + 8: { + "name": "Geomagnetic Activity", + "filename": "geomagnetic", + "description": "Geomagnetic storm effects on atmosphere", + "details": [ + "Joule heating from enhanced electric currents", + "Particle precipitation heating", + "Storm-time atmospheric expansion", + "Enhanced atmospheric mixing and circulation", + ], + "importance": [ + "Critical for space weather applications", + "Essential during geomagnetic storms", + "Important for satellite drag during active periods", + "Key for atmosphere-magnetosphere coupling studies", + ], + }, + 9: { + "name": "All UT Effects", + "filename": "ut_effects", + "description": "Universal Time atmospheric dependencies", + "details": [ + "Magnetic field orientation effects", + "UT-dependent geomagnetic coupling", + "Diurnal variation of magnetic field geometry", + "Solar wind-magnetosphere interaction timing", + ], + "importance": [ + "Important for geomagnetic coupling accuracy", + "Essential for magnetic field orientation effects", + "Critical for space weather applications", + "Improves model accuracy during active conditions", + ], + }, + 10: { + "name": "Longitudinal", + "filename": "longitudinal", + "description": "Longitude-dependent atmospheric variations", + "details": [ + "Geographic longitude effects", + "Magnetic field declination impacts", + "Regional atmospheric heating differences", + "Longitude-dependent magnetic coupling", + ], + "importance": [ + "Captures geographic atmospheric variations", + "Important for regional atmospheric accuracy", + "Essential for magnetic declination effects", + "Improves local atmospheric predictions", + ], + }, + 11: { + "name": "Mixed UT/Long", + "filename": "mixed_ut_long", + "description": "Combined UT and longitudinal effects", + "details": [ + "Coupled universal time and longitude effects", + "Complex temporal-spatial atmospheric variations", + "Combined magnetic and temporal dependencies", + "Interaction between UT and longitude effects", + ], + "importance": [ + "Captures complex temporal-spatial coupling", + "Important for accurate regional predictions", + "Essential for combined effect modeling", + "Improves atmospheric model sophistication", + ], + }, + 12: { + "name": "Lower Atmosphere", + "filename": "lower_atmosphere", + "description": "Lower atmospheric influences", + "details": [ + "Tropospheric and stratospheric coupling", + "Lower atmospheric wave propagation", + "Atmospheric tide generation from below", + "Coupling between atmospheric regions", + ], + "importance": [ + "Important for atmospheric coupling studies", + "Essential for wave propagation modeling", + "Critical for complete atmospheric representation", + "Improves understanding of atmospheric layers interaction", + ], + }, + 13: { + "name": "Lower Atm F10.7", + "filename": "lower_atm_f107", + "description": "Solar flux effects on lower atmosphere", + "details": [ + "Solar flux modulation of lower atmospheric effects", + "F10.7-dependent lower atmosphere coupling", + "Solar cycle effects on atmospheric layers interaction", + "Variable coupling strength with solar activity", + ], + "importance": [ + "Links solar activity to atmospheric coupling", + "Important for solar cycle atmospheric studies", + "Essential for complete solar-atmospheric modeling", + "Improves long-term atmospheric predictions", + ], + }, +} + + +def create_option_file(option_idx: int, info: dict) -> tuple[str, str]: + """Create an individual option analysis file.""" + filename = f"plot_option_{option_idx:02d}_{info['filename']}.py" + + content = f'''""" +{option_idx:02d}. MSIS Option {option_idx}: {info["name"]} +{"=" * (len(f"{option_idx:02d}. MSIS Option {option_idx}: {info['name']}"))} + +This example demonstrates the analysis of MSIS Option {option_idx}, +which controls {info["description"]}. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt + +from msis_options_utils import create_option_analysis_figure + +# %% +# Option {option_idx} controls {info["description"]} +# {"=" * (len(f"Option {option_idx} controls {info['description']}"))} +# +# This atmospheric effect includes: +# +{chr(10).join(f"# * {detail}" for detail in info["details"])} +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = {option_idx} +option_name = "{info["name"]}" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +{chr(10).join(f"# * {importance}" for importance in info["importance"])} +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. +''' + + return filename, content + + +def main() -> None: + """Generate all individual option analysis files.""" + print("Generating individual MSIS option analysis files...") + + # Determine the correct path for the output directory + script_dir = os.path.dirname(os.path.abspath(__file__)) + project_root = os.path.dirname(script_dir) # Go up one level from docs/ + output_dir = os.path.join(project_root, "examples", "individual_options") + + # Ensure the output directory exists + os.makedirs(output_dir, exist_ok=True) + + generated_files = [] + + for option_idx, info in OPTIONS_INFO.items(): + filename, content = create_option_file(option_idx, info) + filepath = os.path.join(output_dir, filename) + + with open(filepath, "w") as f: + f.write(content) + + generated_files.append(filename) + print(f" Created: {filename}") + + print(f"\\nGenerated {len(generated_files)} option analysis files:") + for filename in generated_files: + print(f" - {filename}") + + print("\\nAll files are ready for sphinx_gallery documentation!") + + # Format all generated files with ruff + print("\\nFormatting generated files with ruff...") + format_files_with_ruff(output_dir, generated_files) + + +def format_files_with_ruff(output_dir: str, filenames: list[str]) -> None: + """Format Python files using ruff formatter. + + Args: + output_dir: Directory containing the files. + filenames: List of Python file names to format. + """ + filepaths = [os.path.join(output_dir, filename) for filename in filenames] + + try: + # Run ruff format on all files + cmd = ["ruff", "format", *filepaths] + result = subprocess.run(cmd, capture_output=True, text=True, check=False) # noqa: S603 + + if result.returncode == 0: + print(f"Successfully formatted {len(filepaths)} files with ruff") + else: + print(f"Warning: ruff format returned code {result.returncode}") + if result.stderr: + print(f"Error output: {result.stderr}") + except subprocess.CalledProcessError as e: + print(f"Error running ruff format: {e}") + except FileNotFoundError: + print("Error: ruff not found. Please install ruff or run 'pip install ruff'") + + +if __name__ == "__main__": + main() diff --git a/docs/source/conf.py b/docs/source/conf.py index c472408..f3547c5 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -17,6 +17,8 @@ # from pathlib import Path +from sphinx_gallery.sorting import ExampleTitleSortKey, ExplicitOrder + sys.path.insert(0, Path("../../pymsis").resolve()) @@ -78,9 +80,20 @@ autosummary_generate = True autodoc_typehints = "none" +# Define subsection order for examples gallery +subsection_order = ExplicitOrder( + [ + "../../examples/general_examples", + "../../examples/options_overview", + "../../examples/individual_options", + ] +) + # Sphinx gallery sphinx_gallery_conf = { - "examples_dirs": "../../examples", # path to example scripts - "gallery_dirs": "examples", # path to where to save generated output + "examples_dirs": "../../examples", + "gallery_dirs": "examples", "matplotlib_animations": True, + "within_subsection_order": ExampleTitleSortKey, + "subsection_order": subsection_order, } diff --git a/examples/general_examples/README.txt b/examples/general_examples/README.txt new file mode 100644 index 0000000..e255587 --- /dev/null +++ b/examples/general_examples/README.txt @@ -0,0 +1,8 @@ +.. _general_examples: + +General Examples +---------------- + +Basic atmospheric modeling examples showing core pymsis functionality for +typical use cases like plotting atmospheric profiles, understanding seasonal +and diurnal variations, and comparing different MSIS versions. diff --git a/examples/plot_altitude_profiles.py b/examples/general_examples/plot_altitude_profiles.py similarity index 100% rename from examples/plot_altitude_profiles.py rename to examples/general_examples/plot_altitude_profiles.py diff --git a/examples/plot_annual_variation.py b/examples/general_examples/plot_annual_variation.py similarity index 100% rename from examples/plot_annual_variation.py rename to examples/general_examples/plot_annual_variation.py diff --git a/examples/plot_diurnal_variation.py b/examples/general_examples/plot_diurnal_variation.py similarity index 100% rename from examples/plot_diurnal_variation.py rename to examples/general_examples/plot_diurnal_variation.py diff --git a/examples/plot_surface.py b/examples/general_examples/plot_surface.py similarity index 100% rename from examples/plot_surface.py rename to examples/general_examples/plot_surface.py diff --git a/examples/plot_surface_animation.py b/examples/general_examples/plot_surface_animation.py similarity index 100% rename from examples/plot_surface_animation.py rename to examples/general_examples/plot_surface_animation.py diff --git a/examples/plot_version_diff_altitude.py b/examples/general_examples/plot_version_diff_altitude.py similarity index 100% rename from examples/plot_version_diff_altitude.py rename to examples/general_examples/plot_version_diff_altitude.py diff --git a/examples/plot_version_diff_surface.py b/examples/general_examples/plot_version_diff_surface.py similarity index 100% rename from examples/plot_version_diff_surface.py rename to examples/general_examples/plot_version_diff_surface.py diff --git a/examples/individual_options/README.txt b/examples/individual_options/README.txt new file mode 100644 index 0000000..2efeec2 --- /dev/null +++ b/examples/individual_options/README.txt @@ -0,0 +1,16 @@ +.. _individual_option_analysis: + +Individual Option Analysis +-------------------------- + +Comprehensive analysis for each of the 14 main MSIS options. Each example +provides detailed physical explanations and multi-dimensional visualization +showing how turning OFF a specific option affects atmospheric density across +altitude, geography, and time. + +Each analysis includes: + +- **Altitude profiles**: Seasonal and diurnal effects from 100-500 km +- **Geographic maps**: Global latitude vs longitude patterns at 300 km +- **Diurnal cycles**: 24-hour variations at a fixed location +- **Seasonal cycles**: Annual variations throughout the year diff --git a/examples/individual_options/msis_options_utils.py b/examples/individual_options/msis_options_utils.py new file mode 100644 index 0000000..a4355a0 --- /dev/null +++ b/examples/individual_options/msis_options_utils.py @@ -0,0 +1,387 @@ +""" +MSIS Options Analysis Utilities +============================== + +Utility functions for creating comprehensive MSIS option analysis plots. +This module provides reusable functions for sphinx_gallery documentation. +""" + +import matplotlib.pyplot as plt +import numpy as np + +import pymsis + + +def create_option_analysis_figure(option_index, option_name=None, figsize=(14, 10)): + """ + Create comprehensive analysis plots for a single MSIS option. + + This function generates a 2x2 subplot figure showing: + 1. Altitude profiles with seasonal/diurnal variations + 2. Geographic surface map (latitude vs longitude) + 3. Diurnal cycle (24-hour variation) + 4. Seasonal cycle (annual variation) + + Parameters + ---------- + option_index : int + Index of the MSIS option to analyze (0-24) + option_name : str, optional + Name of the option for plot titles. If None, uses default names. + figsize : tuple, optional + Figure size in inches. Default is (14, 10). + + Returns + ------- + fig : matplotlib.figure.Figure + The created figure object + """ + + # Get option name if not provided + if option_name is None: + option_names = [ + "F10.7 Effects", + "Time Independent", + "Symmetric Annual", + "Symmetric Semiannual", + "Asymmetric Annual", + "Asymmetric Semiannual", + "Diurnal", + "Semidiurnal", + "Geomagnetic Activity", + "All UT Effects", + "Longitudinal", + "Mixed UT/Long", + "Lower Atmosphere", + "Lower Atm F10.7", + ] + if option_index < len(option_names): + option_name = option_names[option_index] + else: + option_name = f"Option {option_index}" + + # Create figure with 2x2 subplots + fig, axes = plt.subplots(2, 2, figsize=figsize) + + # Common parameters for all calculations + f107 = 180 # High solar activity + f107a = 160 # 81-day average + ap = 15 # Moderate geomagnetic activity + aps = [[ap] * 7] # Ap array format for pymsis + + # Panel 1: Altitude Profiles + _create_altitude_panel(axes[0, 0], option_index, f107, f107a, aps) + + # Panel 2: Geographic Surface Map + _create_geographic_panel(axes[0, 1], option_index, f107, f107a, aps) + + # Panel 3: Diurnal Variation + _create_diurnal_panel(axes[1, 0], option_index, f107, f107a, aps) + + # Panel 4: Seasonal Variation + _create_seasonal_panel(axes[1, 1], option_index, f107, f107a, aps) + + # Overall title + fig.suptitle( + f"Comprehensive Analysis: MSIS {option_name} Option\n" + f"Atmospheric density changes when option is turned OFF\n" + f"F10.7={f107}, Ap={ap}", + fontsize=16, + y=0.96, + ) + + plt.tight_layout() + plt.subplots_adjust(top=0.88) + + return fig + + +def _create_altitude_panel(ax, option_index, f107, f107a, aps): + """Create altitude profile panel showing seasonal and diurnal effects.""" + + # Define four temporal conditions + date_winter_noon = np.datetime64("2003-01-01T12:00") + date_winter_midnight = np.datetime64("2003-01-01T00:00") + date_summer_noon = np.datetime64("2003-07-01T12:00") + date_summer_midnight = np.datetime64("2003-07-01T00:00") + + lon, lat = 0, 45 # Equator, mid-latitude + alts = np.linspace(100, 500, 100) # Thermosphere focus + + # Define options arrays + options_on = [1] * 25 + options_off = options_on.copy() + options_off[option_index] = 0 + + # Calculate baseline densities (all options ON) + baselines = {} + tests = {} + + for condition, date in [ + ("winter_noon", date_winter_noon), + ("winter_midnight", date_winter_midnight), + ("summer_noon", date_summer_noon), + ("summer_midnight", date_summer_midnight), + ]: + # Baseline calculation + baseline = pymsis.calculate( + date, lon, lat, alts, f107, f107a, aps, options=options_on + ) + baselines[condition] = np.squeeze(baseline)[:, pymsis.Variable.MASS_DENSITY] + + # Test calculation (option OFF) + test = pymsis.calculate( + date, lon, lat, alts, f107, f107a, aps, options=options_off + ) + tests[condition] = np.squeeze(test)[:, pymsis.Variable.MASS_DENSITY] + + # Calculate and plot percentage differences + colors = {"winter": "blue", "summer": "red"} + styles = {"noon": "-", "midnight": "--"} + + for condition, baseline_value in baselines.items(): + season, time = condition.split("_") + test_value = tests[condition] + percent_diff = 100 * (test_value - baseline_value) / baseline_value + + label = f"{season.capitalize()} {time}" + ax.plot( + percent_diff, + alts, + color=colors[season], + linestyle=styles[time], + linewidth=2, + label=label, + ) + + # Formatting + ax.axvline(x=0, color="gray", linestyle=":", alpha=0.5, linewidth=1) + ax.set_xlabel("Change when OFF (%)") + ax.set_ylabel("Altitude (km)") + ax.set_title("A) Altitude Profiles") + ax.grid(True, alpha=0.3) + ax.legend(fontsize=9) + + +def _create_geographic_panel(ax, option_index, f107, f107a, aps): + """Create geographic surface map panel (latitude vs longitude).""" + + lats = np.linspace(-90, 90, 19) # 10-degree spacing + lons = np.linspace(-180, 180, 37) # 10-degree spacing + alt_surface = 300 # km altitude + date_surface = np.datetime64("2003-06-21T12:00") # Summer solstice noon + + lon_grid, lat_grid = np.meshgrid(lons, lats) + + # Define options arrays + options_on = [1] * 25 + options_off = options_on.copy() + options_off[option_index] = 0 + + # Calculate density arrays + density_on_surface = np.zeros_like(lon_grid) + density_off_surface = np.zeros_like(lon_grid) + + # Calculate for each lat/lon combination + for i, lat_val in enumerate(lats): + for j, lon_val in enumerate(lons): + # Baseline (ON) + result_on = pymsis.calculate( + date_surface, + lon_val, + lat_val, + alt_surface, + f107, + f107a, + aps, + options=options_on, + ) + density_on_surface[i, j] = np.squeeze(result_on)[ + pymsis.Variable.MASS_DENSITY + ] + + # Option OFF + result_off = pymsis.calculate( + date_surface, + lon_val, + lat_val, + alt_surface, + f107, + f107a, + aps, + options=options_off, + ) + density_off_surface[i, j] = np.squeeze(result_off)[ + pymsis.Variable.MASS_DENSITY + ] + + # Calculate percentage difference + percent_diff_surface = ( + 100 * (density_off_surface - density_on_surface) / density_on_surface + ) + + # Create contour plot + levels = np.linspace(-20, 20, 21) + contour = ax.contourf( + lon_grid, + lat_grid, + percent_diff_surface, + levels=levels, + cmap="RdBu_r", + extend="both", + ) + ax.contour( + lon_grid, + lat_grid, + percent_diff_surface, + levels=levels[::4], + colors="black", + alpha=0.3, + linewidths=0.5, + ) + + # Formatting + ax.set_xlabel("Longitude (°)") + ax.set_ylabel("Latitude (°)") + ax.set_title(f"B) Geographic Pattern at {alt_surface} km") + ax.grid(True, alpha=0.3) + + # Add colorbar + cbar = plt.colorbar(contour, ax=ax, shrink=0.8) + cbar.set_label("Change when OFF (%)", fontsize=9) + + +def _create_diurnal_panel(ax, option_index, f107, f107a, aps): + """Create diurnal cycle panel (24-hour variation).""" + + times = np.linspace(0, 24, 25) + dates_temporal = [ + np.datetime64("2003-06-21") + np.timedelta64(int(h), "h") for h in times + ] + + alt_temporal = 300 + lat_temporal = 45 + lon_temporal = 0 + + # Define options arrays + options_on = [1] * 25 + options_off = options_on.copy() + options_off[option_index] = 0 + + density_on_temporal = [] + density_off_temporal = [] + + for date in dates_temporal: + # Baseline (ON) + result_on = pymsis.calculate( + date, + lon_temporal, + lat_temporal, + alt_temporal, + f107, + f107a, + aps, + options=options_on, + ) + density_on_temporal.append(np.squeeze(result_on)[pymsis.Variable.MASS_DENSITY]) + + # Option OFF + result_off = pymsis.calculate( + date, + lon_temporal, + lat_temporal, + alt_temporal, + f107, + f107a, + aps, + options=options_off, + ) + density_off_temporal.append( + np.squeeze(result_off)[pymsis.Variable.MASS_DENSITY] + ) + + density_on_temporal = np.array(density_on_temporal) + density_off_temporal = np.array(density_off_temporal) + + percent_diff_temporal = ( + 100 * (density_off_temporal - density_on_temporal) / density_on_temporal + ) + + # Plot + ax.plot(times, percent_diff_temporal, "b-", linewidth=2, marker="o", markersize=4) + ax.axhline(y=0, color="gray", linestyle=":", alpha=0.5, linewidth=1) + + # Formatting + ax.set_xlabel("Time (hours UT)") + ax.set_ylabel("Change when OFF (%)") + ax.set_title(f"C) Diurnal Cycle at {lat_temporal}°N, {alt_temporal} km") + ax.grid(True, alpha=0.3) + ax.set_xlim(0, 24) + + +def _create_seasonal_panel(ax, option_index, f107, f107a, aps): + """Create seasonal variation panel (annual cycle).""" + + # Create dates for full year (monthly sampling) + months = np.arange(1, 13) + dates_seasonal = [np.datetime64(f"2003-{month:02d}-15T12:00") for month in months] + + alt_temporal = 300 + lat_temporal = 45 + lon_temporal = 0 + + # Define options arrays + options_on = [1] * 25 + options_off = options_on.copy() + options_off[option_index] = 0 + + density_on_seasonal = [] + density_off_seasonal = [] + + for date in dates_seasonal: + # Baseline (ON) + result_on = pymsis.calculate( + date, + lon_temporal, + lat_temporal, + alt_temporal, + f107, + f107a, + aps, + options=options_on, + ) + density_on_seasonal.append(np.squeeze(result_on)[pymsis.Variable.MASS_DENSITY]) + + # Option OFF + result_off = pymsis.calculate( + date, + lon_temporal, + lat_temporal, + alt_temporal, + f107, + f107a, + aps, + options=options_off, + ) + density_off_seasonal.append( + np.squeeze(result_off)[pymsis.Variable.MASS_DENSITY] + ) + + density_on_seasonal = np.array(density_on_seasonal) + density_off_seasonal = np.array(density_off_seasonal) + + percent_diff_seasonal = ( + 100 * (density_off_seasonal - density_on_seasonal) / density_on_seasonal + ) + + # Plot + ax.plot(months, percent_diff_seasonal, "r-", linewidth=2, marker="s", markersize=6) + ax.axhline(y=0, color="gray", linestyle=":", alpha=0.5, linewidth=1) + + # Formatting + ax.set_xlabel("Month") + ax.set_ylabel("Change when OFF (%)") + ax.set_title(f"D) Seasonal Cycle at {lat_temporal}°N, {alt_temporal} km") + ax.grid(True, alpha=0.3) + ax.set_xlim(1, 12) + ax.set_xticks(months) diff --git a/examples/individual_options/plot_option_00_f107_effects.py b/examples/individual_options/plot_option_00_f107_effects.py new file mode 100644 index 0000000..272539f --- /dev/null +++ b/examples/individual_options/plot_option_00_f107_effects.py @@ -0,0 +1,69 @@ +""" +00. MSIS Option 0: F10.7 Effects +================================ + +This example demonstrates the analysis of MSIS Option 0, +which controls Solar EUV flux variations. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 0 controls Solar EUV flux variations +# =========================================== +# +# This atmospheric effect includes: +# +# * Solar extreme ultraviolet (EUV) radiation heating +# * Solar flux proxy (F10.7 radio flux) dependencies +# * Solar cycle and rotation effects on atmospheric heating +# * Thermospheric temperature and density variations +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 0 +option_name = "F10.7 Effects" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Primary driver of thermospheric density variations +# * Essential for solar cycle modeling and predictions +# * Critical for long-term orbital decay calculations +# * Fundamental for understanding solar-terrestrial coupling +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_01_time_independent.py b/examples/individual_options/plot_option_01_time_independent.py new file mode 100644 index 0000000..4301401 --- /dev/null +++ b/examples/individual_options/plot_option_01_time_independent.py @@ -0,0 +1,69 @@ +""" +01. MSIS Option 1: Time Independent +=================================== + +This example demonstrates the analysis of MSIS Option 1, +which controls Baseline atmospheric structure. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 1 controls Baseline atmospheric structure +# ================================================ +# +# This atmospheric effect includes: +# +# * Baseline atmospheric structure that varies with latitude +# * North-south atmospheric density and temperature gradients +# * Geographic variations in atmospheric properties +# * Time-independent latitude-dependent reference state +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 1 +option_name = "Time Independent" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Provides fundamental atmospheric structure from poles to equator +# * Essential for accurate geographic atmospheric modeling +# * Critical for understanding latitude-dependent atmospheric behavior +# * Foundation for all other atmospheric variations +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_02_symmetric_annual.py b/examples/individual_options/plot_option_02_symmetric_annual.py new file mode 100644 index 0000000..214736c --- /dev/null +++ b/examples/individual_options/plot_option_02_symmetric_annual.py @@ -0,0 +1,69 @@ +""" +02. MSIS Option 2: Symmetric Annual +=================================== + +This example demonstrates the analysis of MSIS Option 2, +which controls Annual seasonal variations (symmetric). This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 2 controls Annual seasonal variations (symmetric) +# ======================================================== +# +# This atmospheric effect includes: +# +# * Seasonal atmospheric heating variations +# * Annual solar declination effects +# * Symmetric seasonal patterns in both hemispheres +# * Yearly cycle in atmospheric temperature and density +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 2 +option_name = "Symmetric Annual" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Models primary seasonal atmospheric changes +# * Essential for year-round atmospheric predictions +# * Critical for understanding seasonal density variations +# * Important for annual satellite drag variations +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_03_symmetric_semiannual.py b/examples/individual_options/plot_option_03_symmetric_semiannual.py new file mode 100644 index 0000000..4005a97 --- /dev/null +++ b/examples/individual_options/plot_option_03_symmetric_semiannual.py @@ -0,0 +1,69 @@ +""" +03. MSIS Option 3: Symmetric Semiannual +======================================= + +This example demonstrates the analysis of MSIS Option 3, +which controls Semiannual atmospheric oscillations. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 3 controls Semiannual atmospheric oscillations +# ===================================================== +# +# This atmospheric effect includes: +# +# * Twice-yearly atmospheric oscillations +# * Semiannual density and temperature variations +# * Atmospheric response to semiannual solar forcing +# * Global atmospheric circulation effects +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 3 +option_name = "Symmetric Semiannual" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Captures important semiannual density variations +# * Affects satellite drag twice per year +# * Important for atmospheric dynamics understanding +# * Contributes to seasonal atmospheric modeling accuracy +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_04_asymmetric_annual.py b/examples/individual_options/plot_option_04_asymmetric_annual.py new file mode 100644 index 0000000..5accaf0 --- /dev/null +++ b/examples/individual_options/plot_option_04_asymmetric_annual.py @@ -0,0 +1,69 @@ +""" +04. MSIS Option 4: Asymmetric Annual +==================================== + +This example demonstrates the analysis of MSIS Option 4, +which controls Asymmetric annual variations. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 4 controls Asymmetric annual variations +# ============================================== +# +# This atmospheric effect includes: +# +# * Hemisphere-dependent seasonal effects +# * Asymmetric seasonal atmospheric responses +# * North-south hemisphere seasonal differences +# * Latitude-dependent annual variations +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 4 +option_name = "Asymmetric Annual" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Models hemisphere-specific seasonal differences +# * Important for accurate polar region modeling +# * Captures asymmetric seasonal atmospheric responses +# * Essential for global atmospheric accuracy +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_05_asymmetric_semiannual.py b/examples/individual_options/plot_option_05_asymmetric_semiannual.py new file mode 100644 index 0000000..42d585e --- /dev/null +++ b/examples/individual_options/plot_option_05_asymmetric_semiannual.py @@ -0,0 +1,69 @@ +""" +05. MSIS Option 5: Asymmetric Semiannual +======================================== + +This example demonstrates the analysis of MSIS Option 5, +which controls Asymmetric semiannual variations. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 5 controls Asymmetric semiannual variations +# ================================================== +# +# This atmospheric effect includes: +# +# * Hemisphere-specific semiannual oscillations +# * Asymmetric twice-yearly atmospheric changes +# * Latitude-dependent semiannual effects +# * Complex seasonal atmospheric dynamics +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 5 +option_name = "Asymmetric Semiannual" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Provides realistic hemisphere-dependent variations +# * Important for accurate seasonal modeling +# * Captures complex semiannual atmospheric behavior +# * Essential for global atmospheric precision +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_06_diurnal.py b/examples/individual_options/plot_option_06_diurnal.py new file mode 100644 index 0000000..92c66aa --- /dev/null +++ b/examples/individual_options/plot_option_06_diurnal.py @@ -0,0 +1,69 @@ +""" +06. MSIS Option 6: Diurnal +========================== + +This example demonstrates the analysis of MSIS Option 6, +which controls Day/night atmospheric variations. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 6 controls Day/night atmospheric variations +# ================================================== +# +# This atmospheric effect includes: +# +# * Solar heating during daytime hours +# * Radiative cooling during nighttime +# * Temperature-driven density changes +# * Local time dependencies in atmospheric structure +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 6 +option_name = "Diurnal" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Most important short-term atmospheric variation +# * Essential for realistic atmospheric modeling +# * Critical for satellite drag predictions +# * Fundamental for space weather applications +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_07_semidiurnal.py b/examples/individual_options/plot_option_07_semidiurnal.py new file mode 100644 index 0000000..d70c029 --- /dev/null +++ b/examples/individual_options/plot_option_07_semidiurnal.py @@ -0,0 +1,69 @@ +""" +07. MSIS Option 7: Semidiurnal +============================== + +This example demonstrates the analysis of MSIS Option 7, +which controls 12-hour atmospheric tidal effects. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 7 controls 12-hour atmospheric tidal effects +# =================================================== +# +# This atmospheric effect includes: +# +# * Thermal forcing by solar heating +# * Gravitational tidal forces (minor contribution) +# * Atmospheric wave propagation and resonance +# * Interaction with the Earth's rotation +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 7 +option_name = "Semidiurnal" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Important for atmospheric wave dynamics +# * Affects satellite drag calculations +# * Key component of upper atmospheric dynamics +# * Provides insight into atmospheric wave propagation +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_08_geomagnetic.py b/examples/individual_options/plot_option_08_geomagnetic.py new file mode 100644 index 0000000..5391ff7 --- /dev/null +++ b/examples/individual_options/plot_option_08_geomagnetic.py @@ -0,0 +1,69 @@ +""" +08. MSIS Option 8: Geomagnetic Activity +======================================= + +This example demonstrates the analysis of MSIS Option 8, +which controls Geomagnetic storm effects on atmosphere. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 8 controls Geomagnetic storm effects on atmosphere +# ========================================================= +# +# This atmospheric effect includes: +# +# * Joule heating from enhanced electric currents +# * Particle precipitation heating +# * Storm-time atmospheric expansion +# * Enhanced atmospheric mixing and circulation +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 8 +option_name = "Geomagnetic Activity" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Critical for space weather applications +# * Essential during geomagnetic storms +# * Important for satellite drag during active periods +# * Key for atmosphere-magnetosphere coupling studies +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_09_ut_effects.py b/examples/individual_options/plot_option_09_ut_effects.py new file mode 100644 index 0000000..3507bfd --- /dev/null +++ b/examples/individual_options/plot_option_09_ut_effects.py @@ -0,0 +1,69 @@ +""" +09. MSIS Option 9: All UT Effects +================================= + +This example demonstrates the analysis of MSIS Option 9, +which controls Universal Time atmospheric dependencies. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 9 controls Universal Time atmospheric dependencies +# ========================================================= +# +# This atmospheric effect includes: +# +# * Magnetic field orientation effects +# * UT-dependent geomagnetic coupling +# * Diurnal variation of magnetic field geometry +# * Solar wind-magnetosphere interaction timing +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 9 +option_name = "All UT Effects" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Important for geomagnetic coupling accuracy +# * Essential for magnetic field orientation effects +# * Critical for space weather applications +# * Improves model accuracy during active conditions +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_10_longitudinal.py b/examples/individual_options/plot_option_10_longitudinal.py new file mode 100644 index 0000000..43e38b4 --- /dev/null +++ b/examples/individual_options/plot_option_10_longitudinal.py @@ -0,0 +1,69 @@ +""" +10. MSIS Option 10: Longitudinal +================================ + +This example demonstrates the analysis of MSIS Option 10, +which controls Longitude-dependent atmospheric variations. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 10 controls Longitude-dependent atmospheric variations +# ============================================================= +# +# This atmospheric effect includes: +# +# * Geographic longitude effects +# * Magnetic field declination impacts +# * Regional atmospheric heating differences +# * Longitude-dependent magnetic coupling +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 10 +option_name = "Longitudinal" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Captures geographic atmospheric variations +# * Important for regional atmospheric accuracy +# * Essential for magnetic declination effects +# * Improves local atmospheric predictions +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_11_mixed_ut_long.py b/examples/individual_options/plot_option_11_mixed_ut_long.py new file mode 100644 index 0000000..7116dd1 --- /dev/null +++ b/examples/individual_options/plot_option_11_mixed_ut_long.py @@ -0,0 +1,69 @@ +""" +11. MSIS Option 11: Mixed UT/Long +================================= + +This example demonstrates the analysis of MSIS Option 11, +which controls Combined UT and longitudinal effects. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 11 controls Combined UT and longitudinal effects +# ======================================================= +# +# This atmospheric effect includes: +# +# * Coupled universal time and longitude effects +# * Complex temporal-spatial atmospheric variations +# * Combined magnetic and temporal dependencies +# * Interaction between UT and longitude effects +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 11 +option_name = "Mixed UT/Long" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Captures complex temporal-spatial coupling +# * Important for accurate regional predictions +# * Essential for combined effect modeling +# * Improves atmospheric model sophistication +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_12_lower_atmosphere.py b/examples/individual_options/plot_option_12_lower_atmosphere.py new file mode 100644 index 0000000..ed3a9ae --- /dev/null +++ b/examples/individual_options/plot_option_12_lower_atmosphere.py @@ -0,0 +1,69 @@ +""" +12. MSIS Option 12: Lower Atmosphere +==================================== + +This example demonstrates the analysis of MSIS Option 12, +which controls Lower atmospheric influences. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 12 controls Lower atmospheric influences +# =============================================== +# +# This atmospheric effect includes: +# +# * Tropospheric and stratospheric coupling +# * Lower atmospheric wave propagation +# * Atmospheric tide generation from below +# * Coupling between atmospheric regions +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 12 +option_name = "Lower Atmosphere" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Important for atmospheric coupling studies +# * Essential for wave propagation modeling +# * Critical for complete atmospheric representation +# * Improves understanding of atmospheric layers interaction +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/individual_options/plot_option_13_lower_atm_f107.py b/examples/individual_options/plot_option_13_lower_atm_f107.py new file mode 100644 index 0000000..304c32f --- /dev/null +++ b/examples/individual_options/plot_option_13_lower_atm_f107.py @@ -0,0 +1,69 @@ +""" +13. MSIS Option 13: Lower Atm F10.7 +=================================== + +This example demonstrates the analysis of MSIS Option 13, +which controls Solar flux effects on lower atmosphere. This option represents a key +physical process that affects atmospheric density variations. + +Understanding how this option affects atmospheric structure is important for +atmospheric modeling, satellite operations, and space weather applications. +""" + +import matplotlib.pyplot as plt +from msis_options_utils import create_option_analysis_figure + + +# %% +# Option 13 controls Solar flux effects on lower atmosphere +# ========================================================= +# +# This atmospheric effect includes: +# +# * Solar flux modulation of lower atmospheric effects +# * F10.7-dependent lower atmosphere coupling +# * Solar cycle effects on atmospheric layers interaction +# * Variable coupling strength with solar activity +# +# This analysis shows how turning OFF this option affects atmospheric density +# across different dimensions and conditions. + +option_index = 13 +option_name = "Lower Atm F10.7" + +fig = create_option_analysis_figure(option_index, option_name) + +# %% +# Understanding the Results +# ========================= +# +# **Panel A (Altitude Profiles)**: Shows how this effect varies with altitude +# and between different seasonal and diurnal conditions. Look for differences +# between the four curves to understand temporal variability. +# +# **Panel B (Geographic Map)**: Reveals the global pattern of this atmospheric +# effect. The contour plot shows percentage changes when the option is turned OFF +# compared to the baseline (all options ON). +# +# **Panel C (Diurnal Cycle)**: Demonstrates how this effect varies throughout +# a 24-hour period at a fixed location (45°N, 0°E, 300 km altitude). +# +# **Panel D (Seasonal Cycle)**: Shows how the strength of this effect +# varies throughout the year, revealing seasonal dependencies. + +plt.show() + +# %% +# Physical Importance +# =================== +# +# This atmospheric effect is important because: +# +# * Links solar activity to atmospheric coupling +# * Important for solar cycle atmospheric studies +# * Essential for complete solar-atmospheric modeling +# * Improves long-term atmospheric predictions +# +# When this option is turned OFF, these physical processes are removed +# from the atmospheric model, which can significantly impact the accuracy +# of density predictions depending on the specific application and conditions. diff --git a/examples/options_overview/README.txt b/examples/options_overview/README.txt new file mode 100644 index 0000000..e07a530 --- /dev/null +++ b/examples/options_overview/README.txt @@ -0,0 +1,9 @@ +.. _options_overview: + +MSIS Options Overview +--------------------- + +High-level visualization of MSIS option effects across multiple dimensions. +These examples provide comparative analysis showing how different options +affect atmospheric structure and help identify which options have the most +significant impacts under various conditions. diff --git a/examples/options_overview/plot_options_01_altitude_impact_overview.py b/examples/options_overview/plot_options_01_altitude_impact_overview.py new file mode 100644 index 0000000..4fa2042 --- /dev/null +++ b/examples/options_overview/plot_options_01_altitude_impact_overview.py @@ -0,0 +1,202 @@ +""" +Altitude Impact Comparison +========================== + +This example demonstrates the visual impact of each MSIS option by showing +altitude profiles of percentage changes in atmospheric mass density when +each option is turned OFF compared to when it's ON. This makes it easy to +see which options have the largest effects and at what altitudes. + +The plot shows a 4x4 grid where each subplot displays the percentage change +in density when a specific option is turned off. Four conditions are tested: +- Winter noon (solid blue line) +- Winter midnight (dashed blue line) +- Summer noon (solid red line) +- Summer midnight (dashed red line) + +This reveals both seasonal and diurnal variations for each atmospheric process. + +""" + +import matplotlib.pyplot as plt +import numpy as np + +import pymsis + + +# Define common parameters for all calculations +lon = 0 # Equator +lat = 45 # Mid-latitude +alts = np.linspace(100, 500, 100) # Focus on thermosphere where effects are largest +f107 = 200 # High solar activity to enhance effects +f107a = 180 +ap = 15 # Moderate geomagnetic activity + +# Define four conditions to show both seasonal and diurnal effects clearly +date_winter_noon = np.datetime64("2003-01-01T12:00") # Winter solstice, noon +date_winter_midnight = np.datetime64("2003-01-01T00:00") # Winter solstice, midnight +date_summer_noon = np.datetime64("2003-07-01T12:00") # Summer solstice, noon +date_summer_midnight = np.datetime64("2003-07-01T00:00") # Summer solstice, midnight +aps = [[ap] * 7] + +# Define the options to test (first 14 are the main physical effects) +option_names = [ + "F10.7 Effects", + "Time Independent", + "Symmetric Annual", + "Symmetric Semiannual", + "Asymmetric Annual", + "Asymmetric Semiannual", + "Diurnal", + "Semidiurnal", + "Geomagnetic Activity", + "All UT Effects", + "Longitudinal", + "Mixed UT/Long", + "Mixed Ap/UT/Long", + "Terdiurnal", +] + +# Create the subplot grid +fig, axes = plt.subplots(4, 4, figsize=(16, 12)) +axes = axes.flatten() + +# Calculate baseline with all options on for all four conditions +baseline_options = [1] * 25 +baseline_winter_noon = pymsis.calculate( + date_winter_noon, lon, lat, alts, f107, f107a, aps, options=baseline_options +) +baseline_winter_midnight = pymsis.calculate( + date_winter_midnight, lon, lat, alts, f107, f107a, aps, options=baseline_options +) +baseline_summer_noon = pymsis.calculate( + date_summer_noon, lon, lat, alts, f107, f107a, aps, options=baseline_options +) +baseline_summer_midnight = pymsis.calculate( + date_summer_midnight, lon, lat, alts, f107, f107a, aps, options=baseline_options +) + +# Extract mass density (first component) and squeeze dimensions +baseline_winter_noon = np.squeeze(baseline_winter_noon)[:, pymsis.Variable.MASS_DENSITY] +baseline_winter_midnight = np.squeeze(baseline_winter_midnight)[ + :, pymsis.Variable.MASS_DENSITY +] +baseline_summer_noon = np.squeeze(baseline_summer_noon)[:, pymsis.Variable.MASS_DENSITY] +baseline_summer_midnight = np.squeeze(baseline_summer_midnight)[ + :, pymsis.Variable.MASS_DENSITY +] + +for i, (ax, option_name) in enumerate(zip(axes[:14], option_names, strict=True)): + # Create options array with the i-th option turned off + test_options = [1] * 25 + test_options[i] = 0 + + # Calculate atmosphere with option turned off for all four conditions + test_winter_noon = pymsis.calculate( + date_winter_noon, lon, lat, alts, f107, f107a, aps, options=test_options + ) + test_winter_midnight = pymsis.calculate( + date_winter_midnight, lon, lat, alts, f107, f107a, aps, options=test_options + ) + test_summer_noon = pymsis.calculate( + date_summer_noon, lon, lat, alts, f107, f107a, aps, options=test_options + ) + test_summer_midnight = pymsis.calculate( + date_summer_midnight, lon, lat, alts, f107, f107a, aps, options=test_options + ) + + # Extract mass density and squeeze dimensions + test_winter_noon = np.squeeze(test_winter_noon)[:, pymsis.Variable.MASS_DENSITY] + test_winter_midnight = np.squeeze(test_winter_midnight)[ + :, pymsis.Variable.MASS_DENSITY + ] + test_summer_noon = np.squeeze(test_summer_noon)[:, pymsis.Variable.MASS_DENSITY] + test_summer_midnight = np.squeeze(test_summer_midnight)[ + :, pymsis.Variable.MASS_DENSITY + ] + + # Calculate percentage differences (Option OFF vs Option ON) + percent_diff_winter_noon = ( + 100 * (test_winter_noon - baseline_winter_noon) / baseline_winter_noon + ) + percent_diff_winter_midnight = ( + 100 + * (test_winter_midnight - baseline_winter_midnight) + / baseline_winter_midnight + ) + percent_diff_summer_noon = ( + 100 * (test_summer_noon - baseline_summer_noon) / baseline_summer_noon + ) + percent_diff_summer_midnight = ( + 100 + * (test_summer_midnight - baseline_summer_midnight) + / baseline_summer_midnight + ) + + # Always plot all four conditions with clear color/linestyle scheme + # Blue = Winter, Red = Summer, Solid = Noon, Dashed = Midnight + ax.plot(percent_diff_winter_noon, alts, "b-", linewidth=2, label="Winter noon") + ax.plot( + percent_diff_winter_midnight, alts, "b--", linewidth=2, label="Winter midnight" + ) + ax.plot(percent_diff_summer_noon, alts, "r-", linewidth=2, label="Summer noon") + ax.plot( + percent_diff_summer_midnight, alts, "r--", linewidth=2, label="Summer midnight" + ) + + # Calculate max differences for axis scaling + all_diffs = [ + np.max(np.abs(percent_diff_winter_noon)), + np.max(np.abs(percent_diff_winter_midnight)), + np.max(np.abs(percent_diff_summer_noon)), + np.max(np.abs(percent_diff_summer_midnight)), + ] + + # Add vertical line at zero for reference + ax.axvline(x=0, color="gray", linestyle=":", alpha=0.5, linewidth=1) + + ax.set_title(option_name, fontsize=10) + ax.grid(True, alpha=0.3) + + # Set reasonable x-axis limits based on the data + max_abs_diff = max(all_diffs) + if max_abs_diff > 0.1: # Only set limits if there's meaningful variation + ax.set_xlim(-max_abs_diff * 1.1, max_abs_diff * 1.1) + else: + ax.set_xlim(-5, 5) # Default small range for options with minimal effect + + # Only show x-labels on bottom row + if i >= 10: + ax.set_xlabel("Change when OFF (%)", fontsize=9) + + # Only show y-labels on leftmost column + if i % 4 == 0: + ax.set_ylabel("Altitude (km)", fontsize=9) + +# Remove unused subplots +for i in range(14, 16): + axes[i].remove() + +# Add overall title and legend +fig.suptitle( + "MSIS Options Impact: Percentage Change in Atmospheric Mass Density\n" + "Shows how much density changes when each option is turned OFF\n" + f"{lat}°N, {lon}°E, F10.7={f107}, Ap={ap}", + fontsize=14, + y=0.98, +) + +# Add single legend for all subplots showing all four conditions +handles, labels = axes[0].get_legend_handles_labels() +fig.legend( + handles, + labels, + loc="upper center", + bbox_to_anchor=(0.5, 0.02), + ncol=len(labels), + fontsize=10, +) + +plt.tight_layout() +plt.subplots_adjust(top=0.92, bottom=0.12) +plt.show() diff --git a/examples/options_overview/plot_options_02_geographic_patterns.py b/examples/options_overview/plot_options_02_geographic_patterns.py new file mode 100644 index 0000000..09f3842 --- /dev/null +++ b/examples/options_overview/plot_options_02_geographic_patterns.py @@ -0,0 +1,124 @@ +""" +Geographic and Temporal Patterns +================================ + +This example demonstrates how different MSIS options affect atmospheric density +across longitude and time. The plots show surface maps of mass density at 300 km +altitude, revealing the geographic and temporal patterns controlled by each option. + +Four key MSIS options with strong spatial/temporal patterns are highlighted: +1. Diurnal variations (day/night differences) +2. Semidiurnal tidal effects (12-hour cycles) +3. Longitudinal variations (geographic differences) +4. Universal Time effects (UT dependencies) + +This complements the altitude overview by showing horizontal structure patterns. + +""" + +import matplotlib.pyplot as plt +import numpy as np + +import pymsis + + +# Define grid parameters +lons = np.linspace(-180, 180, 37) # 10-degree longitude spacing +times = np.linspace(0, 24, 25) # Hourly through one day +lat = 45 # Mid-latitude +alt = 300 # Thermosphere where effects are clear +f107 = 180 +f107a = 160 +ap = 10 + +# Create date array for one day +base_date = np.datetime64("2003-03-20") # Spring equinox - sun centered on equator +dates = [base_date + np.timedelta64(int(h), "h") for h in times] + +# Select key options that show strong geographic/temporal patterns +key_options = { + "Diurnal (Day/Night)": 6, # Index 6 = diurnal + "Semidiurnal (12h tides)": 7, # Index 7 = semidiurnal + "Longitudinal": 10, # Index 10 = longitudinal + "All UT Effects": 9, # Index 9 = all UT effects +} + +# Create figure with subplots +fig, axes = plt.subplots(2, 2, figsize=(14, 10)) +axes = axes.flatten() + +# Create aps array for single calculations +aps_single = [[ap] * 7] # Array of arrays for single date calculations + +for plot_idx, (option_name, option_idx) in enumerate(key_options.items()): + ax = axes[plot_idx] + + # Create meshgrid for plotting + LON, TIME = np.meshgrid(lons, times) + density_on = np.zeros_like(LON) + density_off = np.zeros_like(LON) + + # Calculate density for each lon/time combination + for i, _ in enumerate(times): + date = dates[i] + + # All options ON + options_on = [1] * 25 + result_on = pymsis.calculate( + date, lons, lat, alt, f107, f107a, aps_single, options=options_on + ) + density_on[i, :] = np.squeeze(result_on)[:, pymsis.Variable.MASS_DENSITY] + + # Target option OFF + options_off = [1] * 25 + options_off[option_idx] = 0 + result_off = pymsis.calculate( + date, lons, lat, alt, f107, f107a, aps_single, options=options_off + ) + density_off[i, :] = np.squeeze(result_off)[:, pymsis.Variable.MASS_DENSITY] + + # Calculate relative difference (%) + relative_diff = 100 * (density_on - density_off) / density_on + + # Create contour plot + levels = np.linspace(-50, 50, 21) + contour = ax.contourf( + LON, TIME, relative_diff, levels=levels, cmap="RdBu_r", extend="both" + ) + + # Add contour lines for clarity + ax.contour( + LON, + TIME, + relative_diff, + levels=levels[::4], + colors="black", + alpha=0.3, + linewidths=0.5, + ) + + ax.set_title( + f"{option_name} Effect\n{base_date} (Spring Equinox)", + fontsize=12, + fontweight="bold", + ) + ax.set_xlabel("Longitude (degrees)") + ax.set_ylabel("Time (hours UT)") + ax.grid(True, alpha=0.3) + + # Add colorbar + cbar = plt.colorbar(contour, ax=ax, shrink=0.8) + cbar.set_label("Effect when ON vs OFF (%)", fontsize=10) + +# Add overall title +fig.suptitle( + f"Geographic and Temporal Effects of MSIS Options\n" + f"Mass Density at {alt} km altitude, {lat}°N latitude\n" + f"Spring Equinox 2003-03-20, F10.7={f107}, Ap={ap}", + fontsize=14, + y=0.98, +) + +plt.tight_layout() +plt.subplots_adjust(top=0.88) +plt.show() diff --git a/pymsis/msis.py b/pymsis/msis.py index c1d97eb..abc58bd 100644 --- a/pymsis/msis.py +++ b/pymsis/msis.py @@ -164,34 +164,69 @@ def calculate( Other Parameters ---------------- f107 : float - Account for F10.7 variations + Solar flux F10.7 effects on atmospheric density. Controls how much + the current F10.7 value modifies the base atmospheric state. When set to 0, + F10.7 variations are ignored and the atmosphere uses a standard reference + solar flux level. time_independent : float - Account for time variations + Time-independent baseline atmospheric structure. Controls the + basic north-south atmospheric variations that provide the fundamental + geographic structure of the atmosphere independent of time. Setting + to 0 removes these baseline latitude-dependent terms, leaving only + time-varying atmospheric patterns. symmetrical_annual : float - Account for symmetrical annual variations + Annual variations that are the same in both hemispheres. Controls + seasonal changes in atmospheric density due to Earth's orbit around + the Sun. When set to 0, removes symmetric year-to-year variations. symmetrical_semiannual : float - Account for symmetrical semiannual variations + Semiannual (6-month) variations that are symmetric between hemispheres. + Controls atmospheric changes that occur twice per year due to solar + heating patterns. Setting to 0 removes these biannual variations. asymmetrical_annual : float - Account for asymmetrical annual variations + Annual variations that differ between northern and southern hemispheres. + Accounts for seasonal differences caused by land/ocean distribution and + other hemispheric asymmetries. When set to 0, removes asymmetric + seasonal effects. asymmetrical_semiannual : float - Account for asymmetrical semiannual variations + Semiannual variations that differ between hemispheres. Controls + atmospheric changes that occur twice yearly but with different magnitudes + in each hemisphere. Setting to 0 removes these asymmetric biannual variations. diurnal : float - Account for diurnal variations + Daily (24-hour) variations in atmospheric density. Controls day/night + differences caused by solar heating and atmospheric tides. When set to 0, + removes all diurnal atmospheric variations. semidiurnal : float - Account for semidiurnal variations + Semi-daily (12-hour) variations in atmospheric density. Controls + atmospheric tides that occur twice per day due to solar heating patterns. + Setting to 0 removes these twice-daily atmospheric oscillations. geomagnetic_activity : float - Account for geomagnetic activity - (1 = Daily Ap mode, -1 = Storm-time Ap mode) + Geomagnetic activity effects on atmospheric heating and expansion. + Controls how magnetic storms and aurora affect atmospheric density. + (1 = Daily Ap mode using average daily values, -1 = Storm-time Ap mode + using 3-hourly Ap indices for more detailed storm modeling) all_ut_effects : float - Account for all UT/longitudinal effects + Universal Time (UT) and longitudinal effects combined. Controls + atmospheric variations that depend on the time of day in UT and + geographic longitude. Setting to 0 removes all UT/longitude-dependent + variations. longitudinal : float - Account for longitudinal effects + Pure longitudinal variations independent of UT. Controls atmospheric + differences that vary only with geographic longitude (e.g., land/sea contrasts, + topography). When set to 0, removes longitude-only atmospheric variations. mixed_ut_long : float - Account for UT and mixed UT/longitudinal effects + Mixed Universal Time and longitudinal effects. Controls atmospheric + variations that depend on both UT and longitude simultaneously (e.g., + regional differences in tidal patterns). Setting to 0 removes these + coupled effects. mixed_ap_ut_long : float - Account for mixed Ap, UT, and longitudinal effects + Combined geomagnetic activity, UT, and longitudinal effects. Controls + how magnetic activity affects the atmosphere differently across longitude + and UT. When set to 0, removes the geographic/temporal coupling of + magnetic effects. terdiurnal : float - Account for terdiurnal variations + Terdiurnal (8-hour) atmospheric variations. Controls atmospheric tides + that occur three times per day due to solar heating harmonics. Setting + to 0 removes these 8-hourly atmospheric oscillations. Notes ----- @@ -277,43 +312,83 @@ def create_options( """ Create the options list based on keyword argument choices. - Defaults to all 1's for the input options. Any value other than 1 - will turn off the corresponding effect in the MSIS model, with the - exception of geomagnetic activity, which can be set to -1 for storm-time - Ap mode. You may also use booleans for the options, ``diurnal=False`` will + Defaults to all 1's for the input options. + 0 turns the option off. + 1 turns the option on. + 2 turns the main effects off, but the cross terms on. + + For geomagnetic_activity, 1 is for daily Ap mode, and -1 is for storm-time Ap mode. + You may also use booleans for the options, ``diurnal=False`` will turn off the diurnal effect. Parameters ---------- f107 : float - Account for F10.7 variations + Solar flux F10.7 effects on atmospheric density. Controls how much + the current F10.7 value modifies the base atmospheric state. When set to 0, + F10.7 variations are ignored and the atmosphere uses a standard reference + solar flux level. time_independent : float - Account for time variations + Time-independent baseline atmospheric structure. Controls the + basic north-south atmospheric variations that provide the fundamental + geographic structure of the atmosphere independent of time. Setting + to 0 removes these baseline latitude-dependent terms, leaving only + time-varying atmospheric patterns. symmetrical_annual : float - Account for symmetrical annual variations + Annual variations that are the same in both hemispheres. Controls + seasonal changes in atmospheric density due to Earth's orbit around + the Sun. When set to 0, removes symmetric year-to-year variations. symmetrical_semiannual : float - Account for symmetrical semiannual variations + Semiannual (6-month) variations that are symmetric between hemispheres. + Controls atmospheric changes that occur twice per year due to solar + heating patterns. Setting to 0 removes these biannual variations. asymmetrical_annual : float - Account for asymmetrical annual variations + Annual variations that differ between northern and southern hemispheres. + Accounts for seasonal differences caused by land/ocean distribution and + other hemispheric asymmetries. When set to 0, removes asymmetric + seasonal effects. asymmetrical_semiannual : float - Account for asymmetrical semiannual variations + Semiannual variations that differ between hemispheres. Controls + atmospheric changes that occur twice yearly but with different magnitudes + in each hemisphere. Setting to 0 removes these asymmetric biannual + variations. diurnal : float - Account for diurnal variations + Daily (24-hour) variations in atmospheric density. Controls day/night + differences caused by solar heating and atmospheric tides. When set to 0, + removes all diurnal atmospheric variations. semidiurnal : float - Account for semidiurnal variations + Semi-daily (12-hour) variations in atmospheric density. Controls + atmospheric tides that occur twice per day due to solar heating patterns. + Setting to 0 removes these twice-daily atmospheric oscillations. geomagnetic_activity : float - Account for geomagnetic activity - (1 = Daily Ap mode, -1 = Storm-time Ap mode) + Geomagnetic activity effects on atmospheric heating and expansion. + Controls how magnetic storms and aurora affect atmospheric density. + (1 = Daily Ap mode using average daily values, -1 = Storm-time Ap mode + using 3-hourly Ap indices for more detailed storm modeling) all_ut_effects : float - Account for all UT/longitudinal effects + Universal Time (UT) and longitudinal effects combined. Controls + atmospheric variations that depend on the time of day in UT and + geographic longitude. Setting to 0 removes all UT/longitude-dependent + variations. longitudinal : float - Account for longitudinal effects + Pure longitudinal variations independent of UT. Controls atmospheric + differences that vary only with geographic longitude (e.g., land/sea + contrasts, topography). When set to 0, removes longitude-only + atmospheric variations. mixed_ut_long : float - Account for UT and mixed UT/longitudinal effects + Mixed Universal Time and longitudinal effects. Controls atmospheric + variations that depend on both UT and longitude simultaneously (e.g., + regional differences in tidal patterns). Setting to 0 removes these + coupled effects. mixed_ap_ut_long : float - Account for mixed Ap, UT, and longitudinal effects + Combined geomagnetic activity, UT, and longitudinal effects. Controls + how magnetic activity affects the atmosphere differently across longitude + and UT. When set to 0, removes the geographic/temporal coupling of + magnetic effects. terdiurnal : float - Account for terdiurnal variations + Terdiurnal (8-hour) atmospheric variations. Controls atmospheric tides + that occur three times per day due to solar heating harmonics. Setting + to 0 removes these 8-hourly atmospheric oscillations. Returns -------