Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SolarNow

Tests

A Python package for easy access to real-time space weather information from NOAA's Space Weather Prediction Center (SWPC). Originally developed to be used as part of a hobby project, but may prove useful for those who wish to have access to such information.

Pi Zero Display Hobby project to make a desk ornament that displays real time space weather information and warnings. A touch E-ink display is used alongside a Raspberry Pi Zero 2 W.

Overview

SolarNow provides a simple, intuitive interface to fetch and analyse space weather data including solar wind conditions, geomagnetic indices, solar active regions, sunspot numbers, GOES satellite measurements, and F10.7 radio flux. All data is retrieved directly from NOAA SWPC's public APIs and formatted into convenient pandas DataFrames.

Note that the NOAA can change the locations of data sources, or suspend certain services. It is possible that this package breaks in the future as a result of this. If anyone finds that this is the case, please raise an issue or pull request.

Features

  • Solar Wind Data: Magnetic field components (Bx, By, Bz, Bt) and plasma parameters (density, speed, temperature)
  • Geomagnetic Indices: Dst and Kp indices for monitoring geomagnetic activity
  • Active Regions: Current and tracked solar active region data
  • Sunspot Numbers: SWPC observed sunspot numbers with date filtering
  • GOES Satellite Data:
    • Proton flux at 8 energy levels (≥1, 5, 10, 30, 50, 60, 100, 500 MeV)
    • Electron flux (≥2 MeV)
    • X-ray flux in two bands (0.05-0.4nm, 0.1-0.8nm)
    • Customisable time resolution with automatic re-sampling
    • GLE (ground level enhancement) proton event warning levels
  • F10.7 Radio Flux: Solar radio flux at 10.7 cm with 90-day running mean

Installation

Install from source:

git clone https://github.com/NLarsen15/SolarNow.git
cd SolarNow
pip install -e .

Quick Start

import SolarNow as sn

# Fetch solar wind data
solar_wind = sn.get_solar_wind_data()
sw_data = solar_wind.fetch_data()
print(sw_data.head())

# Fetch geomagnetic indices
geo_index = sn.get_geo_index_data()
geo_data = geo_index.fetch_data()
print(geo_data.head())

# Fetch GOES satellite data
goes = sn.get_goes_data()
proton_data = goes.fetch_proton_data(satellite='primary')
print(proton_data.head())

Detailed Usage

Solar Wind Data

Retrieve magnetic field and plasma measurements:

import SolarNow as sn
from datetime import datetime, timedelta

# Get solar wind data with custom resolution (default: 1min)
solar_wind = sn.get_solar_wind_data(resolution='5min')

# Fetch all available data (last ~24 hours)
all_data = solar_wind.fetch_data()

# Filter by date range
start = datetime.now() - timedelta(hours=5)
end = datetime.now()
filtered_data = solar_wind.fetch_data(start_date=start, end_date=end)

# Available columns:
# - date [UTC]: Timestamp
# - bx_gsm [nT], by_gsm [nT], bz_gsm [nT]: Magnetic field components
# - bt [nT]: Total magnetic field
# - density [cm^-3]: Plasma density
# - speed [km/s]: Solar wind speed
# - temperature [K]: Plasma temperature
print(filtered_data[['date [UTC]', 'speed [km/s]', 'bz_gsm [nT]']].head())

Geomagnetic Indices

Retrieve the Dst, Kp, and a indices for geomagnetic activity:

import SolarNow as sn

# Get geomagnetic index data with custom resolution
geo_index = sn.get_geo_index_data(resolution='1hour')

# Fetch data
geo_data = geo_index.fetch_data()

# Available columns:
# - date [UTC]: Timestamp
# - dst [nT]: Disturbance Storm Time index
# - kp: Planetary K-index
# - running a_index: Running A-index
print(geo_data.tail(24))  # Last 24 hours

# Filter for geomagnetic storms (Dst < -50 nT)
storm_periods = geo_data[geo_data['dst [nT]'] < -50]
print(f"Storm periods detected: {len(storm_periods)}")

Active Regions

Access current and historical solar active region data:

import SolarNow as sn

# Get active region data
ar_data = sn.get_ar_data()

# Fetch currently visible active regions
current_regions = ar_data.fetch_current_regions()
print(f"Current active regions: {len(current_regions)}")
print(current_regions[['ID', 'Location', 'Lo', 'Area', 'Z', 'LL', 'NN', 'MagType']])

# Get list of all tracked regions
ar_list = ar_data.fetch_ar_list()
print(f"\nTracked regions: {len(ar_list)}")

# Fetch historical data for a specific region
region_number = 3901  # Example region number
region_history = ar_data.fetch_region_history(region_number, verbose=True)
if not region_history.empty:
    print(f"\nRegion {region_number} history:")
    print(region_history[['Date', 'Location', 'Area', 'Z']].head())

Sunspot Numbers

Retrieve SWPC observed sunspot numbers:

import SolarNow as sn
from datetime import datetime

# Get sunspot number data
ssn_data = sn.get_ssn_data()

# Fetch all available data
all_ssn = ssn_data.fetch_ssn_data()
print(all_ssn.tail(10))

# Fetch data for a specific date
specific_date = datetime(2026, 5, 15)
ssn_on_date = ssn_data.fetch_ssn_by_date(specific_date)
print(f"\nSSN on {specific_date.date()}: {ssn_on_date['swpc sunspot number'].values}")

# Fetch data for a date range
start_date = datetime(2026, 5, 15)
end_date = datetime(2026, 5, 30)
ssn_range = ssn_data.fetch_ssn_in_date_range(start_date, end_date)
print(f"\nSSN data from {start_date.date()} to {end_date.date()}:")
print(ssn_range)

GOES Satellite Data

Access proton, electron, and X-ray flux data from GOES satellites:

import SolarNow as sn
from datetime import datetime, timedelta

# Get GOES data with custom resolutions for each instrument
# X-ray base resolution: 1min, Proton/Electron base resolution: 5min
goes = sn.get_goes_data(
    protonresolution='10min',    # Resample to 10 minutes
    electronresolution='5min',   # Keep at base 5 minutes
    xrayresolution='1min'        # Keep at base 1 minute
)

# --- Proton Flux Data ---
# Fetch proton data from primary satellite
proton_primary = goes.fetch_proton_data(satellite='primary')
print("Proton flux data (primary satellite):")
print(proton_primary.head())

# Available proton energy levels:
# - flux >=1 MeV [cm^-2 s^-1 sr^-1]
# - flux >=5 MeV [cm^-2 s^-1 sr^-1]
# - flux >=10 MeV [cm^-2 s^-1 sr^-1]
# - flux >=30 MeV [cm^-2 s^-1 sr^-1]
# - flux >=50 MeV [cm^-2 s^-1 sr^-1]
# - flux >=60 MeV [cm^-2 s^-1 sr^-1]
# - flux >=100 MeV [cm^-2 s^-1 sr^-1]
# - flux >=500 MeV [cm^-2 s^-1 sr^-1]

# Filter by date range
start = datetime.now() - timedelta(days=1)
proton_filtered = goes.fetch_proton_data(satellite='primary', start_date=start)
print(f"\nProton flux (last 24 hours): {len(proton_filtered)} records")

# --- Electron Flux Data ---
electron_primary = goes.fetch_electron_data(satellite='primary')
print("\nElectron flux data (primary satellite):")
print(electron_primary[['date [UTC]', 'flux >=2 MeV [cm^-2 s^-1 sr^-1]']].head())

# --- X-ray Flux Data ---
xray_primary = goes.fetch_xray_data(satellite='primary')
print("\nX-ray flux data (primary satellite):")
print(xray_primary[['date [UTC]', 'flux 0.05-0.4nm [W/m^2]', 'flux 0.1-0.8nm [W/m^2]']].head())

# Available X-ray columns for each band (0.05-0.4nm and 0.1-0.8nm):
# - flux [W/m^2]: Corrected flux
# - observed_flux [W/m^2]: Raw observed flux
# - electron_correction: Correction factor
# - electron_contamination: Contamination level

# Compare primary and secondary satellites
proton_secondary = goes.fetch_proton_data(satellite='secondary')
print(f"\nPrimary satellite records: {len(proton_primary)}")
print(f"Secondary satellite records: {len(proton_secondary)}")

# --- GLE (Ground Level Enhancement) Warning ---
# Checks the >=50/100/500 MeV proton flux nearest the given time against the
# spaceweather.gov S1 threshold (10 pfu) to flag a possible proton event.
gle = goes.get_gle_warning(datetime.now(), satellite='primary')
print(f"\nGLE warning level: {gle['GLE warning level']}")  # 0 (none) - 3 (>=500 MeV crossed)

GLE Warning Levels

GOESData.get_gle_warning(time, satellite='primary') is a convenience helper that classifies solar energetic particle (proton) events by checking the GOES proton flux nearest the given time against the NOAA Space Weather Scale S1 "Minor" threshold of 10 pfu (particle flux units, cm^-2 s^-1 sr^-1) at three energy channels. It is a package-defined heuristic for spotting a potential Ground Level Enhancement (GLE) — a proton event energetic enough to be detected by instruments at Earth's surface — not an official NOAA classification. Dedicated GLE detection systems should be used for more reliable alerts.

Level Trigger Meaning
0 No channel at/above 10 pfu No indication of a proton event
1 ≥50 MeV flux ≥ 10 pfu Energetic proton event in progress
2 ≥100 MeV flux ≥ 10 pfu Higher-energy protons present; increased GLE likelihood
3 ≥500 MeV flux ≥ 10 pfu Highest-energy protons present; strong GLE candidate

The check only looks at the single flux reading nearest time, evaluated highest-energy-channel-first, and returns a dict with that reading and the resulting level:

import SolarNow as sn
from datetime import datetime

goes = sn.get_goes_data()
gle = goes.get_gle_warning(datetime.now(), satellite='primary')

print(gle)
# {
#     'date [UTC]': Timestamp(...),
#     'flux >=50 MeV [cm^-2 s^-1 sr^-1]': ...,
#     'flux >=100 MeV [cm^-2 s^-1 sr^-1]': ...,
#     'flux >=500 MeV [cm^-2 s^-1 sr^-1]': ...,
#     'GLE warning level': 0,  # 0-3
# }

if gle['GLE warning level'] > 0:
    print(f"Proton event detected — GLE warning level {gle['GLE warning level']}")

F10.7 Radio Flux

Monitor 10.7 cm solar radio emissions:

import SolarNow as sn
from datetime import datetime, timedelta

# Get F10.7 flux data
f107 = sn.get_F107_data()

# Fetch all available data
f107_data = f107.fetch_data()
print("F10.7 flux data:")
print(f107_data.head())

# Available columns:
# - date [UTC]: Observation date
# - flux [sfu]: Solar radio flux at 10.7 cm (1 sfu = 10^-22 W/m^2/Hz)
# - 90 day mean [sfu]: 90-day running mean

# Filter by date range
start = datetime.now() - timedelta(days=30)
recent_f107 = f107.fetch_data(start_date=start)
print(f"\nF10.7 flux (last 30 days):")
print(recent_f107[['date [UTC]', 'flux [sfu]', '90 day mean [sfu]']].tail())

# Calculate average flux
avg_flux = recent_f107['flux [sfu]'].mean()
print(f"\nAverage F10.7 flux (last 30 days): {avg_flux:.2f} sfu")

Advanced Examples

Combining Multiple Data Sources

import SolarNow as sn
import pandas as pd
from datetime import datetime, timedelta

# Define time range
end_time = datetime.now()
start_time = end_time - timedelta(hours-10)

# Fetch multiple datasets
solar_wind = sn.get_solar_wind_data(resolution='5min')
geo_index = sn.get_geo_index_data(resolution='5min')
goes = sn.get_goes_data(xrayresolution='5min')

# Get filtered data
sw_data = solar_wind.fetch_data(start_date=start_time, end_date=end_time)
geo_data = geo_index.fetch_data(start_date=start_time, end_date=end_time)
xray_data = goes.fetch_xray_data(satellite='primary', start_date=start_time, end_date=end_time)

# Merge datasets on timestamp
merged = pd.merge(sw_data, geo_data, on='date [UTC]', how='outer')
merged = pd.merge(merged, xray_data[['date [UTC]', 'flux 0.1-0.8nm [W/m^2]']], 
                  on='date [UTC]', how='outer')

print("Combined space weather data:")
print(merged[['date [UTC]', 'speed [km/s]', 'bz_gsm [nT]', 
              'dst [nT]', 'flux 0.1-0.8nm [W/m^2]']].head())

Plotting Example

import SolarNow as sn
import matplotlib.pyplot as plt
from datetime import datetime, timedelta

# Fetch solar wind data for the last 24 hours (the full window NOAA's real-time feed retains)
solar_wind = sn.get_solar_wind_data(resolution='5min')
start = datetime.now() - timedelta(hours=24)
sw_data = solar_wind.fetch_data(start_date=start)

# Create plot
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8), sharex=True)

# Plot solar wind speed
ax1.plot(sw_data['date [UTC]'], sw_data['speed [km/s]'], color='blue')
ax1.set_ylabel('Speed [km/s]')
ax1.set_title('Solar Wind Conditions (Last 24 Hours)')
ax1.grid(True, alpha=0.3)

# Plot Bz component
ax2.plot(sw_data['date [UTC]'], sw_data['bz_gsm [nT]'], color='red')
ax2.axhline(y=0, color='black', linestyle='--', alpha=0.5)
ax2.set_ylabel('Bz GSM [nT]')
ax2.set_xlabel('Date [UTC]')
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

Data Availability

  • Solar Wind: Last ~24 hours (NOAA's real-time RTSW feed; sourced from ACE, DSCOVR, or IMAP depending on which is currently active)
  • Geomagnetic Indices: Last 7 days
  • GOES Satellite Data: Last 7 days
  • Active Regions: Current visible regions and recently tracked regions
  • Sunspot Numbers: Historical data from solar cycle observations
  • F10.7 Radio Flux: Historical data with daily observations

Resolution and Resampling

SolarNow supports automatic time-series resampling for real-time data:

  • Solar Wind: Base resolution 1 minute, customizable via resolution parameter
  • Geomagnetic Indices: Base resolution 1 minute, customizable via resolution parameter
  • GOES Protons: Base resolution 5 minutes, customizable via protonresolution parameter
  • GOES Electrons: Base resolution 5 minutes, customizable via electronresolution parameter
  • GOES X-rays: Base resolution 1 minute, customizable via xrayresolution parameter

Resampling automatically uses:

  • Backfill for upsampling (higher resolution than base)
  • Mean for downsampling (lower resolution than base)

Requirements

  • Python ≥ 3.8
  • pandas ≥ 1.3.0
  • numpy ≥ 1.20.0
  • requests ≥ 2.25.0

Testing

The test suite uses pytest and covers both mocked unit tests and live-API integration tests:

pip install -e .[test]

# Unit tests only (mocked, no network calls)
pytest -v -m "not integration"

# Integration tests (hit the live NOAA/GFZ APIs)
pytest -v -m "integration"

Tests run automatically on push/PR via GitHub Actions across Python 3.10-3.12, plus a daily scheduled run to catch upstream API changes.

Data Source

Data is sourced from NOAA's Space Weather Prediction Center (SWPC) and GFZ Potsdam's geomagnetic observatory:

License

This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Issues

If you encounter any problems or have suggestions, please open an issue on GitHub.

Author

Nicholas Larsen - nlarsen1505@gmail.com

Acknowledgments

  • NOAA Space Weather Prediction Center for providing open access to space weather data
  • The space physics community for their continued research and monitoring efforts

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages