corona3d 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- corona3d-0.1.2/CHANGELOG.md +108 -0
- corona3d-0.1.2/CITATION.cff +64 -0
- corona3d-0.1.2/LICENSE +21 -0
- corona3d-0.1.2/MANIFEST.in +5 -0
- corona3d-0.1.2/PKG-INFO +216 -0
- corona3d-0.1.2/README.md +165 -0
- corona3d-0.1.2/docs/LIMITATIONS.md +59 -0
- corona3d-0.1.2/docs/METHODS.md +516 -0
- corona3d-0.1.2/docs/MODEL_AUDIT.md +116 -0
- corona3d-0.1.2/docs/RELEASING.md +24 -0
- corona3d-0.1.2/docs/USER_GUIDE.md +619 -0
- corona3d-0.1.2/docs/index.md +20 -0
- corona3d-0.1.2/docs/refs.bib +190 -0
- corona3d-0.1.2/pyproject.toml +65 -0
- corona3d-0.1.2/scripts/gcs_fit_2013-10-25.json +53 -0
- corona3d-0.1.2/setup.cfg +4 -0
- corona3d-0.1.2/src/corona3d/__init__.py +23 -0
- corona3d-0.1.2/src/corona3d/__main__.py +3 -0
- corona3d-0.1.2/src/corona3d/_extras.py +37 -0
- corona3d-0.1.2/src/corona3d/animate.py +223 -0
- corona3d-0.1.2/src/corona3d/api.py +176 -0
- corona3d-0.1.2/src/corona3d/bursts.py +110 -0
- corona3d-0.1.2/src/corona3d/cli.py +483 -0
- corona3d-0.1.2/src/corona3d/default_config.json +143 -0
- corona3d-0.1.2/src/corona3d/doctor.py +75 -0
- corona3d-0.1.2/src/corona3d/euv.py +168 -0
- corona3d-0.1.2/src/corona3d/events/2024-05-09.json +22 -0
- corona3d-0.1.2/src/corona3d/events.py +81 -0
- corona3d-0.1.2/src/corona3d/exporting.py +220 -0
- corona3d-0.1.2/src/corona3d/fetch.py +147 -0
- corona3d-0.1.2/src/corona3d/gcs.py +840 -0
- corona3d-0.1.2/src/corona3d/geometry.py +138 -0
- corona3d-0.1.2/src/corona3d/heights.py +221 -0
- corona3d-0.1.2/src/corona3d/layers.py +5 -0
- corona3d-0.1.2/src/corona3d/mast_model.py +84 -0
- corona3d-0.1.2/src/corona3d/nrh.py +145 -0
- corona3d-0.1.2/src/corona3d/ovro_lwa.py +222 -0
- corona3d-0.1.2/src/corona3d/paths.py +122 -0
- corona3d-0.1.2/src/corona3d/pb.py +598 -0
- corona3d-0.1.2/src/corona3d/pipeline.py +589 -0
- corona3d-0.1.2/src/corona3d/radio.py +118 -0
- corona3d-0.1.2/src/corona3d/reconstruction.py +705 -0
- corona3d-0.1.2/src/corona3d/report_sections.py +22 -0
- corona3d-0.1.2/src/corona3d/scattering.py +126 -0
- corona3d-0.1.2/src/corona3d/shock.py +870 -0
- corona3d-0.1.2/src/corona3d/shockphys.py +490 -0
- corona3d-0.1.2/src/corona3d/solo.py +183 -0
- corona3d-0.1.2/src/corona3d/sources.py +216 -0
- corona3d-0.1.2/src/corona3d/spectra.py +768 -0
- corona3d-0.1.2/src/corona3d/whitelight.py +172 -0
- corona3d-0.1.2/src/corona3d.egg-info/PKG-INFO +216 -0
- corona3d-0.1.2/src/corona3d.egg-info/SOURCES.txt +79 -0
- corona3d-0.1.2/src/corona3d.egg-info/dependency_links.txt +1 -0
- corona3d-0.1.2/src/corona3d.egg-info/entry_points.txt +2 -0
- corona3d-0.1.2/src/corona3d.egg-info/requires.txt +32 -0
- corona3d-0.1.2/src/corona3d.egg-info/top_level.txt +1 -0
- corona3d-0.1.2/tests/conftest.py +37 -0
- corona3d-0.1.2/tests/data/20131025events.txt +169 -0
- corona3d-0.1.2/tests/test_animate.py +181 -0
- corona3d-0.1.2/tests/test_api_export.py +142 -0
- corona3d-0.1.2/tests/test_authorship.py +21 -0
- corona3d-0.1.2/tests/test_bursts.py +101 -0
- corona3d-0.1.2/tests/test_cli.py +179 -0
- corona3d-0.1.2/tests/test_density_radio.py +289 -0
- corona3d-0.1.2/tests/test_euv.py +94 -0
- corona3d-0.1.2/tests/test_event.py +507 -0
- corona3d-0.1.2/tests/test_events.py +30 -0
- corona3d-0.1.2/tests/test_gcs_fit.py +486 -0
- corona3d-0.1.2/tests/test_geometry.py +76 -0
- corona3d-0.1.2/tests/test_legacy_config.py +33 -0
- corona3d-0.1.2/tests/test_model.py +61 -0
- corona3d-0.1.2/tests/test_nrh.py +115 -0
- corona3d-0.1.2/tests/test_online.py +23 -0
- corona3d-0.1.2/tests/test_opacity.py +48 -0
- corona3d-0.1.2/tests/test_ovro_lwa.py +63 -0
- corona3d-0.1.2/tests/test_packaging.py +58 -0
- corona3d-0.1.2/tests/test_reviewfix.py +60 -0
- corona3d-0.1.2/tests/test_shock.py +233 -0
- corona3d-0.1.2/tests/test_shockphys.py +214 -0
- corona3d-0.1.2/tests/test_solo.py +145 -0
- corona3d-0.1.2/tests/test_whitelight.py +125 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.2 (2026-11-04)
|
|
4
|
+
|
|
5
|
+
- First release on PyPI: `pip install corona3d` (or `pip install "corona3d[all]"` with every extra). A pushed version tag now publishes to PyPI through a trusted publisher, and the README links and images use absolute URLs so that they show on PyPI.
|
|
6
|
+
|
|
7
|
+
- `corona3d render` chooses the views and the layout of the figure: `--panel` selects any views in any order (`earth`, `north`, `stereo`, `solo`, or Carrington degrees `lon,lat[,roll]`), and `--layout landscape|portrait|separate` draws them in one row (1 x N), in one column (N x 1), or as one image per view. The default three-panel figure is unchanged pixel for pixel (`reconstruction.select_views`, `compose`, `make_figure(panels=, layout=)`).
|
|
8
|
+
- New command `corona3d animate` (`corona3d/animate.py`; USER_GUIDE Section 4.1) writes a GIF and an MP4 of the reconstruction through a time interval, with the same views and layouts. The shell height follows a line through two GCS fits, a speed, or measured EUV or Solar Orbiter heights; the radio sources accumulate up to each frame time; the model surface and field lines are computed once; cameras, colour limits, panel scale, and the radio time range are fixed, and the frame time is on the figure. A GIF uses one shared palette without dithering that reserves the colours of the Alfvén speed map and of the radio blobs. The MP4 needs imageio-ffmpeg (new extra `animate`) or ffmpeg. 10 new offline tests in `tests/test_animate.py`.
|
|
9
|
+
- The density scale of the shock ensemble (`corona3d shock --mc`) now follows the density of the run: with `density_scale` = `"pb"` it is drawn uniformly between the 16th and 84th percentiles of the pB fit, otherwise between 0.75 and 1.5 times `density_scale` (1.5 to 3 for the default of 2, as before); `shock.mc_density_scale` still overrides it, and the summary records the source of the range (`shock.mc_density_range`). The ensembles of the paper runs are reproduced with the stored configurations. One new offline test.
|
|
10
|
+
- The preset `2024-05-09` holds the refit with COR2-A and Metis at 18:50 UT (Stonyhurst longitude 26.0°, latitude +10.2°, κ 0.54, α 10.7°), the apex height of 2.64 ± 0.89 R⊙ at 17:32 UT and the speed of 1474 ± 136 km s⁻¹ (recorded as assumed), the pB density scale, and the sources on the plasma surface of the model.
|
|
11
|
+
- METHODS (Sections 3, 8.3, 16.6, 16.7) and LIMITATIONS (Sections 5, 6, 8) describe the stand-off shock surface, the placement of the sources on the plasma surface, and the pB density scale, with the results of both events with the calibrated density.
|
|
12
|
+
|
|
13
|
+
## 0.1.1 (2026-10-30)
|
|
14
|
+
|
|
15
|
+
- Solar Orbiter as an observer (`corona3d/solo.py`; METHODS Section 23, USER_GUIDE Sections 3, 5.6, 6, and 9.3, LIMITATIONS Section 10). `corona3d fetch --solo` downloads from the SOAR, one file at a time, the level-2 Metis tB and pB images into `data/wl/` and the EUI/FSI 174 Å images into `data/euv/` (with `--solohi` also SoloHI into `data/solohi/`), and writes the position of the spacecraft from the image headers to `config.json` (`solo`, `solo_dsun_au`). Metis is the view `metis` of `corona3d gcs`, with its field read from the header (4.13 to 8.77 R⊙ at 0.688 AU), and FSI is the EUV view `fsi174` of `--euv`; every Solar Orbiter frame carries the time at 1 AU, the calibrated images are not divided by the exposure time, and the two alternating FSI filters are separate programmes. The new layer `metis` and the view `--view c=solo` draw the Metis image and the reconstruction seen from Solar Orbiter. Citations of Müller et al. (2020), Antonucci et al. (2020), Rochus et al. (2020), and Howard et al. (2020) were checked with Argus. Both are off by default, and the 2013 figures are unchanged pixel for pixel. 12 new offline tests with synthetic headers in `tests/test_solo.py` and `tests/test_gcs_fit.py`.
|
|
16
|
+
- STEREO frames of fewer than 512 pixels (summed on board) form an observing programme of their own in the GCS envelopes (`gcs.seq`). On 2024 May 9 the last COR2-A frame before the cutoff was a 256-pixel frame, so that every full COR2-A frame had been skipped as another binning and COR2-A gave almost no envelope.
|
|
17
|
+
- Refit of 2024 May 9 with Solar Orbiter (METHODS Section 23): COR2-A and Metis, 155° apart, give a free direction of Stonyhurst longitude 26.0° and latitude +10.2° (IoU 0.72 and 0.61) at 18:50 UT; with the onset at 1 R⊙ the apex height at 17:32 UT is 2.64 ± 0.89 R⊙ at 1474 ± 136 km s⁻¹, recorded as assumed.
|
|
18
|
+
|
|
19
|
+
- Density and radio upgrades (`corona3d/pb.py`, `scattering.py`, `sources.py`, `spectra.py`, `report_sections.py`, additions to `heights.py` and `ovro_lwa.py`; METHODS Sections 17 to 22, USER_GUIDE Section 9.7, LIMITATIONS Section 9). `corona3d pb` forward-models the Thomson-scattered polarised brightness of the MAS density (van de Hulst coefficients with limb darkening), calibrates the COR1 and C2 polarisation sequences as secchi_prep and c2_calibrate do, fits the density scale per instrument and radial range, writes `analysis/pb/` with the comparison profiles, and stores `pb_fit`, which `"density_scale": "pb"` uses (2013 October 25: 0.71 ± 0.03; 2024 May 9: 1.14 ± 0.10). The radio sources can be placed on the plasma-frequency surface of the scaled MAS density (`radio_deproject`, `render --radio-surface model`), with fundamental or harmonic emission per entry and frequency or chosen from the NRH polarisation (`radio_emission`, `emission`, `dcp_fundamental`, `render --emission`), with the radial shift by scattering after Chrysaphi et al. (2018) (`scattering`, `render --scattering`), and with an OVRO-LWA offset measured on the quiet Sun (`position_offset`, `corona3d sources --ovro-offset`); `corona3d sources` writes every placement to `analysis/radio_sources.csv`. `corona3d spectra` downloads the e-CALLISTO spectra and the OVRO-LWA spectrum (range requests) of the type II interval, finds the lanes, pairs fundamental and harmonic lanes across spectra, and gives the shock speed from the drift in each density model and the Alfvén Mach number from band splitting (Vršnak et al. 2002). `corona3d event --pb --sources --spectra` adds the sections to `event_report.md`. 25 new offline tests in `tests/test_density_radio.py`; the three 2013 figures are unchanged pixel for pixel.
|
|
20
|
+
|
|
21
|
+
- Shock physics beyond the shell in `corona3d shock` (`corona3d/shockphys.py`; METHODS Section 16, USER_GUIDE Section 9.6): the first critical Mach number $M_c(\theta_{Bn}, \beta)$ from the Rankine-Hugoniot relations (Edmiston & Kennel 1984) with $M_f/M_c$ and the supercritical fractions on the shell and at the sources; with `--standoff`, a shock surface ahead of the shell at the stand-off distance of Russell & Mulligan (2002) after Farris & Russell (1994), with the radius of curvature from the principal curvatures of the shell, on which every diagnostic and the ahead or behind test of the radio sources are repeated; the magnetic connectivity of every radio source to the shock (`shock_connectivity.csv`); collapsing magnetic traps after Kong et al. (2015) (`shock_traps.csv`); the evolution through the burst with the times at which $M_f$ and $M_f/M_c$ cross one, compared with the radio sources and the SWPC type II burst (`shock_evolution.csv`); and, with `--mc N`, an ensemble over apex height, speed, density scale, and model runs (`shock_mc.csv`, `shock_mc_radio.csv`). New options `--standoff`, `--standoff-radius`, `--mc`, `--mc-seed`, `--no-connectivity`, `--no-traps`, `--no-evolution`, `--evolution-step`, and the keys of `shock` in `config.json`; 13 new offline tests in `tests/test_shockphys.py`. The figures are unchanged pixel for pixel.
|
|
22
|
+
|
|
23
|
+
- New physical analysis of the reconstruction, `corona3d shock` (`corona3d/shock.py`, `corona3d/heights.py`; METHODS Sections 12 to 14, USER_GUIDE Section 9.6, LIMITATIONS Section 8). On every point of the GCS shell and at every radio source it samples the upstream MAS/MAST corona, including the temperature and flow of the run (`t002`, `vr002`, `vt002`, `vp002`, read by `mast_model.load_plasma` and downloaded with `corona3d fetch --model-extra`), and computes the Alfvén, sound, and fast-magnetosonic speeds, the shock angle theta_Bn with the quasi-perpendicular fraction, the normal speed of the self-similar shell relative to the upstream flow, and the Alfvén, fast-magnetosonic, and sonic Mach numbers, grouped by nose, flanks, and open or closed field. It also gives the apex and lateral expansion speeds, the speeds of the radio tracks in three dimensions and in the plane of the sky, the heights of every radio position in the Newkirk ×1, ×2, ×4, ×6 models, the Saito et al. (1977) model, and the MHD density along the line of sight, with their range, and the degree of circular polarisation from NRH Stokes V (the column `STOKESV` of the `_i` files, which the 2013 files hold, or a separate `_v` file; `nrh.stokes_v_at`, `nrh.polarisation`). Tables and summaries go to `analysis/` and the section *Shock diagnostics* of `event_report.md`; `corona3d event --shock` runs it and draws `figures/shock/corona3d.png`. Settings in the key `shock` of `config.json`.
|
|
24
|
+
- `corona3d render --shell-color mach_f|mach_a|theta_bn|vn|va` colours the shell by the shock quantities, and `--radio-height-range` draws the height range of every radio position along its line of sight. Both are off by default, and the three 2013 figures are unchanged pixel for pixel.
|
|
25
|
+
- EUV images: `corona3d fetch --euv` downloads SDO/AIA 193 and 211 Å and STEREO/EUVI 195 Å images (`corona3d/euv.py`), and `corona3d gcs --euv` and `corona3d event --euv` measure the apex height at the reconstruction time in them with the shape of the white-light fit, in place of the extrapolated height, which is kept as `height_t_out_wl`; frames whose apex lies beyond the EUV field are not used (METHODS Section 15). For 2013 October 25 the EUVI-B height at 15:00 UT is 1.50 ± 0.04 R_sun against 1.83 ± 0.61 R_sun extrapolated from the same download. Without `--euv` the fit is unchanged.
|
|
26
|
+
- `fetch.model` takes the list of files to download (`names`), so that the extra files of the run are fetched with the same safeguards.
|
|
27
|
+
- 22 new offline tests in `tests/test_shock.py` and `tests/test_euv.py`.
|
|
28
|
+
|
|
29
|
+
- The README, the documentation, the citation file, and the module docstrings describe corona3d with what it adds to earlier three-dimensional reconstructions: the event of 2013 October 25 is the validation case, compared with the reconstruction of Morosan et al. (2022), the user guide has a section on what is new and a table that compares the two reconstructions item by item (Section 11), and every number, command, option, and figure is unchanged.
|
|
30
|
+
- Every layer of the figure can be made semitransparent through the new configuration key `opacity` and the option `corona3d render --opacity LAYER=VALUE`. The radio contours, the radio blobs, the density surface, and the coronagraph images also take a variable opacity: one value per contour level (from the lowest to the highest) or per blob (from the first image to the last), and for the surface and the coronagraph images a list or a transfer function such as `linear` over the colour range, so that the dark background of a ratio image can be transparent while the CME front stays opaque. The radio contours can be drawn at several fractions of the peak with `contour_levels` in an entry of `radio_images` or `--contour-levels 0.3,0.5,0.7,0.9` (which implies the new `--contours`), and they are semitransparent by default (0.6). `wl_opacity` remains valid and replaces `opacity.wl`. The defaults of all other layers are the former fixed values, and the three 2013 figures are unchanged pixel for pixel (`reconstruction.check_opacity`, `reconstruction.opacities`; tests in `tests/test_opacity.py` and `tests/test_nrh.py`).
|
|
31
|
+
- The CME envelopes of `corona3d gcs` are measured more robustly: saturated and stray-light pixels of the base frame are masked (`gcs.clean_diff`), and the difference is smoothed with a Gaussian of 0.06 R_sun, opened with a radius of 0.05 R_sun, and cleared of bright regions below 0.1 R_sun^2 before the convex hull. A repeated 2013 fit changes little (mean IoU 0.825 instead of 0.804, 1.83 instead of 1.94 R_sun at 15:00 UT, within its uncertainty); on 2024 May 9 the COR1-A fit rises from IoU 0.59 to 0.89 at 17:51 UT with the axis in the south, but its apex of 5.1 R_sun is still outside the field. An instrument without frames in the folder is now left out of the fit with a message instead of stopping it.
|
|
32
|
+
- `corona3d render --shell-on-top` draws the GCS shell and the radio sources in a second layer over the model surface, because a shell at the burst time (1.77 R_sun on 2024 May 9) lies largely inside the surface of constant density and was hidden by it. Off by default; the 2013 figure is unchanged.
|
|
33
|
+
- The coronagraph figure can be drawn at the burst time: `corona3d render --wl-at burst` and `corona3d event --wl-at burst` place the shell at the reconstruction time with the parameters at t_out (a height that is assumed stays marked as assumed on the panel and in `event_report.md`), and each coronagraph shows its own frame nearest to that time after its base frame. A frame more than 30 min away is labelled as the nearest frame with its distance. A configuration without `gcs_fit` takes `--wl-height` and `--wl-height-note`. The default (`--wl-at fit`) and the 2013 figure are unchanged (`reconstruction.burst_shell`, `whitelight.nearest_frame`, `load_plane(nearest=True)`). Reason: for 2024 May 9 the shell was drawn at 18:52 UT, 80 min after the OVRO-LWA type II sources of 17:32 to 17:37 UT.
|
|
34
|
+
- The automatic fit time t_ref is chosen while the CME front is still inside the field of view (`gcs.FRONT_FRAC` 0.9): the front, measured from the envelope as in `front_profile`, must lie at most 0.9 of the outer field radius from the Sun in the view, together with the developed-envelope criterion (3 R_sun^2). Among the times at which the largest number of views satisfy this, the earliest is taken. When none does, the earlier rule is kept and `event_report.md` says so; `t_ref_choice` records `reason`, `front_fraction` and `front_inside_fov`. An explicit `--t-ref` is unchanged. `gcs.pick_t_ref` now returns the time, the views and the rule that applied. Reason: on 2024 May 9 the former choice, 18:06 UT, lay after the front had left the 4 R_sun field of COR1-A. METHODS 7.2, USER_GUIDE and offline tests in `tests/test_event.py`.
|
|
35
|
+
- The apex height of every GCS fit is bounded above by 1.5 times the largest outer field-of-view radius of the fitted views (`gcs.HEIGHT_FOV_FACTOR`, `gcs.height_limit`; 6 R_sun for COR1 alone, 9 R_sun with C2, never above 15 R_sun), for the fit to all views, every refit and single-view fit of the view rule, and the fixed-direction fit. `gcs.quality` marks a fit poor when the half-angle is below 5 deg (`gcs.ALPHA_MIN`, a degenerate shell) or when the apex lies outside the outer field of view of every fitted view, and uses the bounds of the fit, so that a height at the new upper bound is a bound hit. The bound is recorded in `height_bound` of `gcs_fit.json` and named in `event_report.md`. Reason: on 2024 May 9 the fit to COR1-A alone, which sees out to 4 R_sun, had an apex at 14.6 R_sun and a half-angle of 1.7 deg, a thin shell whose legs matched the envelope.
|
|
36
|
+
- The view rule no longer lets the joint fit choose the surviving view when the observers are less than 30 deg apart (`gcs.check_views` with `limit` and `problems`). On 2024 May 9 both views are from STEREO-A, the joint fit gave COR1-A 0.28 and COR2-A 0.62, COR1-A was dropped, and the kept COR2-A fit had the aspect ratio at its bound of 0.1 (alpha 59.6 deg near its bound of 60 deg), whereas COR1-A alone reaches 0.90. Each view (or each subset with one view left out) is now fitted separately and the refits are compared. A fit with no parameter at a bound comes first, then the higher mean IoU, and within 0.02 the fit with more views and the view nearer the Sun. All candidates are recorded in `refits` of `view_check` (with `bounds`) and described in one sentence in the report. Widely separated views keep the former behaviour. When the kept fit still has kappa or alpha at a bound, `event_report.md` names the parameter and the fit stays poor, and the bounds are unchanged. METHODS 7.3 and USER_GUIDE are updated, and offline tests with synthetic masks and callbacks are in `tests/test_gcs_fit.py`.
|
|
37
|
+
- The direction of the GCS shell is no longer free when it cannot be measured: with one view left in the fit, or views whose observers are less than 30 deg apart (`gcs.direction_limit`), the longitude and latitude are bounded within `--direction-cone DEG` of the flare site (default 15; 0 fixes them), the practice of Thernisien (2011). On 2024 May 9 the free fit on COR1-A alone (IoU 0.902) had put the axis at latitude +14 deg for a flare at S14. The constraint is recorded in `direction` of `gcs_fit.json`, in `direction_constraint` of `gcs_fit` and in the report ("direction constrained by the source region (single viewpoint)"); a direction at the edge of the cone is not counted as a bound hit in the quality check. The 2013 three-view fit stays free. METHODS 7.4 (the later sections move down by one), USER_GUIDE, and LIMITATIONS; offline tests in `tests/test_gcs_fit.py`.
|
|
38
|
+
|
|
39
|
+
- Order of the fit decision in `corona3d event --fit auto`: the free fit on all views, the view rule and a refit of the free fit, the judgement of its quality, the fixed-direction fit (also with the view rule) only when the free fit is poor or failed, and the better of the two (a good fit beats a poor one, then the higher mean IoU of the kept views, a difference below 0.02 to the free fit; `gcs.choose_fit`). The view rule kept a refit only when the mean IoU of the other views rose by 0.05, so that on 2024 May 9 COR2-A with an IoU of 0 stayed in the free fit (COR1-A 0.9009 with it, 0.9017 without it), the mean of 0.45 counted as poor, and the fixed-direction fit with a mean of 0.38 replaced it; the refit is now kept unless the mean IoU of the other views falls by more than 0.01. The steps, both fits, and the criterion are written to `decision` in `gcs_fit.json` and to *Fit quality* in `event_report.md`; the list of fitted views comes from the views used (`views_used`), so that an instrument without an envelope, such as C2 when its first frame is the base frame, is never listed. METHODS 7.3 and 7.4, USER_GUIDE and LIMITATIONS updated; offline tests on the May 9 numbers.
|
|
40
|
+
- `corona3d event` and `corona3d gcs` choose the time of the six-parameter fit from the images when `--t-ref` is not given: the earliest coronagraph frame within 150 min after the reconstruction time at which the envelope covers at least 3 R_sun^2 with its front 0.2 R_sun inside the field edge in most views (`gcs.pick_t_ref`, `gcs.auto_t_ref`). Before, the default was the reconstruction time plus 60 min, which for the type II burst of 2024 May 9 (17:32 UT) gave a fit at 18:32 UT. The reconstruction time (shell, radio interval) is always `--time`, the begin time of the burst with `--burst`. The choice is recorded in `gcs_fit` (`t_ref_choice`) and stated in `event_report.md`; `wl_time` follows the time of the fit (`wl_time_from` is `"t_ref chosen automatically"`).
|
|
41
|
+
- White-light figure of `corona3d event`: an instrument whose nearest frame to `wl_time` is the base frame (the first frame of `wl_window`, as LASCO C2 at 18:52 UT on 2024 May 9) is now a gap like one without a frame within 30 min, which is why the figure failed although a frame lay within the tolerance (`pipeline.wl_gaps`). When no instrument has a usable frame, `wl_time` moves to the time of the nearest frame that can be drawn (`pipeline.wl_nearest`), the figure is drawn with it, and the report says so under Warnings.
|
|
42
|
+
- Exit code of `corona3d event`: 0 for a partial result, with the failed steps under a new section Warnings of `event_report.md`; 1 only when no figure could be drawn. `--strict` restores the former behaviour (1 when any step failed).
|
|
43
|
+
- `pip install corona3d` is prepared (not uploaded to PyPI). The metadata in `pyproject.toml` has classifiers, the licence file, URLs, and lower bounds of the dependencies; the core install is light (NumPy, SciPy, Matplotlib, Astropy, SunPy, pyhdf, platformdirs) and the extras are `render` (PyVista, PyThea), `gcs` (PyThea, scikit-image), `radio` (h5py), `all`, `docs`, and `test` (the former extra `fit` is now `gcs`). PyVista, PyThea, scikit-image, and h5py are imported where they are first used, and a missing one stops with the extra to install (`corona3d/_extras.py`). The wheel (70 kB) holds only the package and its data (`default_config.json`, `events/*.json`); the sdist adds the documentation text, the tests, and the licence. `docs/RELEASING.md` lists the release steps.
|
|
44
|
+
- Nothing depends on the repository layout: when neither `--home`, `CORONA3D_HOME`, nor a `config.json` in the current folder is found, the working directory is the platform cache directory (platformdirs). `corona3d --version` and the new `corona3d doctor [--offline]` (`corona3d/doctor.py`) report the installed extras, the working directory and its origin, the package data, and whether PSI, the VSO, the OVRO-LWA bucket, NOAA NCEI, and JPL Horizons answer. Offline tests in `tests/test_packaging.py`.
|
|
45
|
+
- The base frame of the GCS envelopes no longer depends on the start of the download: for each instrument and observing programme it is the last frame at or before the flare onset (`--onset`, default the time of the reconstruction) minus `--base-minutes` (default 10 min), and the earliest frame only when none is that early (reported). The onset, the cutoff, the base frames, and the fallbacks are recorded in `base` of `gcs_fit` in `config.json` and in `gcs_fit.json`. METHODS Section 7.2 and the user guide describe the rule, and `tests/test_gcs_fit.py` tests it on synthetic frame lists. This settles the open question on the 2013 October 25 height (1.80 against 1.93 R⊙ for two download windows).
|
|
46
|
+
- A view whose IoU is far below the others no longer spoils the GCS fit: after the first fit, `corona3d gcs` and `corona3d event` take a view with an IoU below 0.5 (`--iou-min`) and below 0.75 times the mean of the others, fit again without it, and keep the refit when the mean IoU of the remaining views rises by at least 0.05; views are removed one at a time, the worst first, and at least one remains. Both fits are written to `view_check` in `gcs_fit.json` and to the section *Fit quality* of `event_report.md`, and the views left out to `views_dropped` in `gcs_fit` of `config.json`. The option `--drop-poor-views` (default) or `--keep-all-views` switches the rule; the rule is in `docs/METHODS.md`, Section 7.3 (`gcs.poor_view`, `gcs.check_views`, offline tests on synthetic masks in `tests/test_gcs_fit.py`).
|
|
47
|
+
- `corona3d event --time DATE` with a date and no time lists the type II and type III bursts of that day from the daily edited events of NOAA SWPC (served without a login by the NCEI archive, with the SWPC FTP server as fallback), and `--burst N` runs the event at the begin time of burst N, for example `--time 2024-05-09 --burst 4` for the type II burst of 17:32 UT. The file is cached in `data/bursts/`. An unreachable source or a day without bursts is reported and asks for `--time` (`corona3d/bursts.py`, `tests/test_bursts.py` with a stored file of 2013 October 25).
|
|
48
|
+
- `corona3d fetch` ends with a message that names the number of failed files per source and the remedy (the same command again), instead of a bare exit code 1; the failed Fido downloads are printed one by one. The intermittent exit code 1 of the online test in 2026 October could not be reproduced (the next run passed); the only place where `corona3d fetch` exits with 1 is a failed or damaged download, which this message now names.
|
|
49
|
+
- The envelope areas of the COR1-B frames of 2013 October 25 differ from `scripts/gcs_fit_2013-10-25.json` (2.16 against 2.66 R⊙² at 15:08) because the base frame was then the first frame of the folder (replaced by the fixed pre-event window above): the folder of the stored fit starts at 14:43 UT and the current download at 14:35 UT. The old and the current code give identical values on the same folder; documented in `docs/METHODS.md`, Section 7.2.
|
|
50
|
+
|
|
51
|
+
- The height-time step of `corona3d gcs` and `corona3d event` uses only the uninterrupted run of frames whose envelope covers at least 2 R⊙² (before: 1 R⊙², with gaps allowed). On the real data of 2013 October 25 the small envelopes of 1.0 and 1.2 R⊙² before the eruption had flattened the line to 334 km s⁻¹ and 2.71 R⊙ at 15:00 UT; the run of four frames gives 1126 km s⁻¹ and 1.80 ± 0.06 R⊙ (`gcs.front_profile`, `tests/test_gcs_fit.py`).
|
|
52
|
+
- `corona3d event` draws the coronagraph figure with the instruments that have a frame within 30 min of `wl_time` and names the others as missing in `event_report.md`; before, a gap of one instrument (LASCO C2 on 2024 May 9) failed the whole figure (`pipeline.wl_gaps`).
|
|
53
|
+
- `corona3d event --t-ref` and `corona3d gcs --t-ref` also set `wl_time` of `config.json` to the time of the fit, so that the coronagraph figure is drawn at that time when the images have a gap (for 2024 May 9, LASCO C2 has no frame between 14:48 and 18:52 UT, and `--t-ref 2024-05-09T17:55` gives `wl_time` 17:55). The provenance `gcs_fit` records the value as `wl_time` with `"wl_time_from": "--t-ref"` (`corona3d/gcs.py`, `corona3d/pipeline.py`).
|
|
54
|
+
- `--views` of `corona3d gcs` and `corona3d event` and `--view` of `corona3d render` accept the legacy names `stereo_a` and `stereo_b`, as `paths.legacy` does for the configuration. In `--views` they stand for COR1 and COR2 of that spacecraft, and in `--view` for the view from `stereo`; a name for the spacecraft that is not `stereo_sc` of the event is refused.
|
|
55
|
+
- When a coronagraph has no frame within `wl_window`, or none within 30 min of `wl_time`, the error of the rendering and `event_report.md` name the nearest frame times before and after `wl_time` (`corona3d/whitelight.py`).
|
|
56
|
+
- Documentation for solar physicists: the README (purpose, installation, the one-command quick start, what is measured and what is assumed, data sources with their access, citation, and licence), the restructured user guide, `docs/METHODS.md` (moved from the repository root, with equations for the MAS/MAST units and the Alfvén speed, the Runge-Kutta tracing of field lines, the four-fold Newkirk heights, the GCS geometry and the fit with its IoU and quality criteria, the coordinate frames, and the plane-of-sky projection), and the new `docs/LIMITATIONS.md`. The references Mikić et al. (1999), Thernisien et al. (2006), and Chhabra et al. (2021) are added to `docs/refs.bib`.
|
|
57
|
+
- `corona3d event --time T --flare S14W28` runs `new`, `fetch`, `radio-interval`, `gcs`, and `render` for one event and writes `event_report.md`, which lists what was measured, what was assumed and why, what data were missing, the fit quality for each instrument, and the figures (`corona3d/pipeline.py`). The shell is fitted freely first, and the fit with the direction held at the flare site follows when the free fit fails or is poor (mean IoU below `--iou-min`, default 0.5, or a parameter at a bound of the optimisation, `gcs.quality`). The default figure is drawn, with the coronagraph and radio layers when their data exist. Every step skips work that is done (`event_state.json`), and the command ends with exit code 1 when a step failed. The options are `--fit`, `--height-out`, `--height-note`, `--iou-min`, `--views`, `--t-ref`, `--radio-search`, `--home`, and `--force`.
|
|
58
|
+
- `corona3d radio-interval`, and the step of the same name in `corona3d event`, choose the start, end, and step of the radio blobs from the images, namely from the brightest source of each frequency above `min_tb` (`corona3d/radio.py`). The entries written by `corona3d new` carry `"interval_source": "default"` and are the only ones changed, so that an interval given by hand is kept.
|
|
59
|
+
- `corona3d fetch --nrh` downloads nothing, since the 2-D NRH images are supplied only on request by the Radio Solar Database at Nançay; it reports the frequencies of each NRH entry that the files in `data/nrh/` cover, and the manual step for the others. The 2013 October 25 render is unchanged and pixel-identical to the baseline.
|
|
60
|
+
- Offline tests of the order of the steps, of skipping finished work, of the fallback to the fixed-direction fit, of the report, and of the interval chosen from synthetic NRH images (`tests/test_event.py`).
|
|
61
|
+
- Python interface for analysis without the figure: `corona3d.build(home, params, **layers)` returns a `Reconstruction` with the density iso-surface (vertices, triangles, and the Alfvén speed and electron density at each vertex), the open, closed, and streamer field lines with their class, the GCS shell at the time of the reconstruction and of the coronagraph images, the coronagraph planes, a table of the radio source positions, and the observers, all in R⊙ in Heliographic Carrington Cartesian coordinates. The radio table also gives the sky-plane position seen from Earth, the height, and the Carrington and Stonyhurst longitude and latitude of every position. `corona3d.load_config` is exported, and `__all__` lists the public names (`corona3d/api.py`). The figure is built by the same functions and is unchanged (the 2013 October 25 render is pixel-identical to the one of the previous commit).
|
|
62
|
+
- `corona3d export [--format npz|csv|vtk] [--out DIR]` and `corona3d.export` write every enabled layer to data files (one npz archive, one table per layer, or VTK files for ParaView) together with `metadata.json`, which records the corona3d version, the SHA-256 and the values of the configuration, the model run, the event time, the coordinate frame and units, the observers, and the sources of every input (`corona3d/exporting.py`). Offline tests of the arrays, the three formats, and one round trip per format (`tests/test_api_export.py`).
|
|
63
|
+
- The preset `2024-05-09` holds the GCS shell fitted to COR1-A and COR2-A at 17:55 UT (apex 3.722 R⊙) and an assumed apex height of 1.77 R⊙ at 17:32 UT; the new optional key `gcs_note` records the reason, is ignored by the figure, and is copied into the metadata of the export.
|
|
64
|
+
- Configuration files written by version 0.1.0 and by the commits before this release load again: `stereo_b` is read as `stereo` with `stereo_sc` "B", views from `stereo_a` or `stereo_b` as views from `stereo`, and `radio_nrh` as an entry of `radio_images` (`paths.legacy`, `tests/test_legacy_config.py`).
|
|
65
|
+
- `corona3d gcs` fits the shell of the CME to the white-light images of the working directory and writes it into `config.json`. The fit of `scripts/gcs_fit.py` is now the module `corona3d/gcs.py` (the script is removed), and the command takes the same options (`--t-ref`, `--t-out`, `--flare LON LAT`, `--views`, `--fix-direction`, `--front`, `--skip-step1`) with the folder `data/wl` as default. It replaces the keys `gcs` and `gcs_wl`, writes `gcs_fit.json` beside them, and records in the new key `gcs_fit` the times, instruments, intersection over union per instrument, front speed, apex height with its uncertainty, and the parameters held fixed. `--running-diff MINUTES` builds the envelopes from running differences, and `--height-out` with `--height-note` gives the apex height at the time of the reconstruction by hand and records it as assumed. PyThea, SunPy, and scikit-image are imported only when a fit is run, and the tests of the pure functions and of the written keys use a mocked fit (`tests/test_gcs_fit.py`).
|
|
66
|
+
- The keys of `scripts/gcs_fit_2013-10-25.json` are `t_ref` and `t_out`, with their times, in place of `t1524` and `t1500`; the values are unchanged (1.931 R⊙, 1039 km s⁻¹).
|
|
67
|
+
- STEREO-A and STEREO-B are both supported: `stereo` and `stereo_sc` replace `stereo_b`, and the third panel, the COR1 and COR2 layers, and the download follow `stereo_sc`.
|
|
68
|
+
- Event presets: `corona3d init --event NAME` (the preset `2024-05-09` is added), and `corona3d new --time T --flare S14W28` writes `config.json` of a new event from Earth and STEREO positions, the PSI run of the Carrington rotation, and the image windows. User guide, Section 9, describes these and the fit.
|
|
69
|
+
- The radio layer also reads the spectral images of OVRO-LWA (`corona3d/ovro_lwa.py`; 32 to 87 MHz, from 2024 April onward), and `corona3d fetch --ovro-lwa` downloads them from the public OVRO-LWA solar data bucket. The radio image sets are listed under `radio_images` in `config.json`, one entry per instrument (NRH or OVRO-LWA), in place of `radio_nrh`; h5py is a new dependency. Offline tests on synthetic OVRO-LWA files (`tests/test_ovro_lwa.py`).
|
|
70
|
+
- The radio layer reads the 2-D images of the Nançay Radioheliograph (`corona3d/nrh.py`), copied into `data/nrh/` of the working directory, and draws the sources of a burst as a chain of coloured blobs for each frequency, one per time step, at the Newkirk height of that frequency, in the manner of the blobs in Fig. 7 of Morosan et al. (2022); contours of the last image are optional (`radio_nrh` in `config.json`). For 2013 October 25, the images at 150.9 and 432 MHz between 14:59 and 15:03 UT give five and three blobs.
|
|
71
|
+
- At most 150 streamer lines are drawn (`streamer_max_lines`), more faintly when the radio layer is on, so that the blobs remain visible; the notes of each panel are placed at its top right.
|
|
72
|
+
- `"projection": "perspective"` draws the panels with the perspective camera of the published Fig. 7 (`camera_distance` 6.65 R⊙), and the panels have its aspect (`window` 1200 × 918 pixels); the orthographic projection remains the default.
|
|
73
|
+
- The README compares the 2013 October 25 validation figure with Fig. 7 of Morosan et al. (2022) and states where the two differ.
|
|
74
|
+
- Offline tests of the NRH reader and of the radio blobs on synthetic NRH files (`tests/test_nrh.py`).
|
|
75
|
+
- The height-time step of `corona3d gcs` is divided into three functions (`projection_factor`, `front_profile`, and `extrapolate`), which `tests/test_gcs_fit.py` checks on a synthetic rise with a known speed and height; the fit of 2013 October 25 is unchanged (1.931 R⊙, 1039 km s⁻¹), and CI runs these tests from the checkout.
|
|
76
|
+
- The installation and the offline tests were checked on Python 3.12.15 as well as 3.13.
|
|
77
|
+
- The README, METHODS.md, the user guide, the model audit, and this changelog were edited into the author's writing style, with every number, citation, and command unchanged.
|
|
78
|
+
|
|
79
|
+
## 0.1.0 (2026-10-27)
|
|
80
|
+
|
|
81
|
+
A review of version 0.0.1 found errors in the physics, the code, the documentation, and the packaging, and this version corrects all of them (`docs/MODEL_AUDIT.md`, items F1 to F9).
|
|
82
|
+
|
|
83
|
+
- The model is no longer rotated by −8.243° in Carrington longitude (`model_dlon` = 0), since MAS is a steady-state Carrington model and the observers' longitudes already contain the solar rotation.
|
|
84
|
+
- The panels are drawn with an orthographic projection, so that the model, the shell, the radio sources, and the coronagraph images share one scale, whereas the perspective camera had magnified structures in front of the plane of the sky by up to 18 %.
|
|
85
|
+
- The CME shell at 15:00 UT keeps the shape of the 15:24 UT white-light fit, and its apex height (1.931 ± 0.158 R⊙) is extrapolated from the COR1-B front, which moves at 1039 km s⁻¹. The shell at 15:24 UT is drawn when coronagraph images are shown, and the fit is reproducible with `corona3d gcs`, with its result kept in `scripts/gcs_fit_2013-10-25.json`.
|
|
86
|
+
- The streamer loops are now the closed field lines through the CME shell, selected without free parameters, in place of a tuned seed line.
|
|
87
|
+
- Field lines are traced through the whole model (to 30.5 R⊙) with a step of 0.01 r and classed as open, closed, or undetermined, and they are drawn within 3 R⊙ (`line_r_max`).
|
|
88
|
+
- The viewpoint of every panel can be chosen (`views` in `config.json`, `--view` on the command line) as Earth, STEREO-B, the north pole, or any Carrington longitude and latitude with a roll angle, and the panel images are now `view_a.png`, `view_b.png`, and `view_c.png`.
|
|
89
|
+
- `va_density` chooses the density from which the Alfvén speed is computed. Moreover, radio positions in arcsec are converted with the angular solar radius at the time of the event, and a position that cannot lie at its height produces a warning.
|
|
90
|
+
- Coronagraph images are compared with the first frame of `wl_window` as a ratio by default (`wl_mode`), which removes vignetting. In addition, inputs that would draw a wrong or blank image are refused, COR1 triplets are grouped by time, frames of different size are resampled, times with a time zone are accepted, and each panel states the times of the model, the shell, and the images.
|
|
91
|
+
- Nested configuration keys are merged one by one, `make_figure` reads the working directory's `config.json` and writes inside that directory, and `reconstruct` accepts partial parameters.
|
|
92
|
+
- Damaged and partial downloads are removed, `corona3d fetch` ends with exit code 1 when files fail, and `--cor1a` adds the STEREO-A COR1 images for the GCS fit.
|
|
93
|
+
- Python 3.12 or newer is required by PyThea 1.3, the dependencies have lower bounds, and PyThea is pinned to 1.3. The version now has one source, a release workflow was added, and CI installs HDF4 on macOS and runs the authorship tests.
|
|
94
|
+
- The command line no longer loads VTK for `--version` and `init`, and figures are drawn without a GUI backend.
|
|
95
|
+
- Offline tests were added for the MAS units and the Alfvén speed, the model rotation, the streamer selection, the undetermined lines, the radio warning, the coronagraph frames (five roll angles, ratio and difference, mixed sizes, refused inputs, C2 headers, and COR1 triplets across a minute), the configuration merge, the panel scale, the viewpoints, and the downloads, giving 40 offline tests in all.
|
|
96
|
+
- The README, METHODS.md, and the user guide were corrected against the code, and `docs/MODEL_AUDIT.md` was added.
|
|
97
|
+
|
|
98
|
+
## 0.0.1 (2026-10-27)
|
|
99
|
+
|
|
100
|
+
First pre-release, in a private repository.
|
|
101
|
+
|
|
102
|
+
- Three-dimensional reconstruction of a coronal mass ejection and the surrounding corona in the layout of Fig. 7 of Morosan et al. (2022), seen from Earth, from above the solar north pole, and from STEREO-B, built from public data only, with every layer switchable from the command line (`--<layer>` / `--no-<layer>`) and from Python (`make_figure(..., layer=True)`).
|
|
103
|
+
- Layers: the electron-density surface of a PSI MAS/MAST run at a chosen plasma level, coloured by the Alfvén speed computed from the scaled density; open and closed field lines; the streamer loops above the CME flank, from a seed line; the 1.2 R⊙ reference sphere; the GCS shell of the CME (PyThea); radio sources placed at their four-fold Newkirk harmonic heights from sky-plane positions given by the user; and base-difference images of LASCO C2 and of STEREO-B COR1 (total brightness of the polarisation triplets) and COR2, drawn in the plane of the sky of their spacecraft.
|
|
104
|
+
- A working directory with its own `config.json` (`corona3d init`), downloads of the model run from the PSI archive and of the coronagraph images through the Virtual Solar Observatory (`corona3d fetch`), and figures with their full-resolution panels (`corona3d render`).
|
|
105
|
+
- Field-line tracer written for corona3d (fourth-order Runge-Kutta along the unit field vector), since the tracer of psipy did not follow these files correctly.
|
|
106
|
+
- GCS parameters of the event fitted again from public images, as the paper does not list them (METHODS.md, Section 7).
|
|
107
|
+
- Offline tests: the tracer against the analytic field lines of a dipole, the radio heights of the paper, the observer axes and the deprojection, the placement of a feature from synthetic coronagraph images at three roll angles, the grouping of COR1 triplets, the command line, and a rendering without data; an online test that downloads the data of 2013 October 25 and draws both figures of the README (`CORONA3D_ONLINE=1`).
|
|
108
|
+
- README, user guide (`docs/USER_GUIDE.md`), and METHODS.md, with every reference checked against its registry record (`docs/refs.bib`).
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use corona3d in your work, please cite it, together with the model run, the coronagraph data, and the methods that it lists for each layer."
|
|
3
|
+
title: "corona3d: a three-dimensional reconstruction of a coronal mass ejection and the corona from public MHD, coronagraph, and radio data"
|
|
4
|
+
type: software
|
|
5
|
+
authors:
|
|
6
|
+
- family-names: Aggarwal
|
|
7
|
+
given-names: Keshav
|
|
8
|
+
affiliation: "Space Physics Laboratory (SPL), Vikram Sarabhai Space Centre (VSSC), ISRO"
|
|
9
|
+
email: keshavaggarwal2310@gmail.com
|
|
10
|
+
version: 0.1.2
|
|
11
|
+
license: MIT
|
|
12
|
+
date-released: 2026-11-04
|
|
13
|
+
abstract: >-
|
|
14
|
+
corona3d is a physics-based Python package that reconstructs the solar corona, a coronal mass
|
|
15
|
+
ejection (CME), and the sources of its radio burst in three dimensions for any event from public
|
|
16
|
+
data. It renders the electron-density surface of a PSI MAS/MAST magnetohydrodynamic model at a
|
|
17
|
+
chosen plasma level coloured by the Alfven speed, traces the open and closed coronal field lines
|
|
18
|
+
through the whole model with its own fourth-order Runge-Kutta tracer, and selects without free
|
|
19
|
+
parameters the closed lines that pass through the CME shell, using PyVista and VTK. The graduated
|
|
20
|
+
cylindrical shell of the CME is fitted automatically to coronagraph images with PyThea, with the
|
|
21
|
+
intersection over union in each instrument as its objective and stated quality, guards against
|
|
22
|
+
degenerate shells and unconstrained directions, and an apex height at the time of the burst
|
|
23
|
+
extrapolated from the height-time profile of the front with its uncertainty. The white-light
|
|
24
|
+
images of SOHO/LASCO C2 and of the STEREO COR1 and COR2 coronagraphs are drawn as ratio or
|
|
25
|
+
difference planes in the plane of the sky of their spacecraft. The sources of a radio burst are
|
|
26
|
+
measured in images of the Nancay Radioheliograph and of the Owens Valley Radio Observatory Long
|
|
27
|
+
Wavelength Array as coloured blobs and contours, which are placed at their Newkirk heights on the
|
|
28
|
+
side of the plane of the sky that faces the observer. Each panel is drawn with an orthographic
|
|
29
|
+
projection from Earth, STEREO-A or STEREO-B, the solar north pole, or any chosen direction, every
|
|
30
|
+
layer can be switched on or off and exported with its provenance, and a command-line interface
|
|
31
|
+
driven by one configuration file reconstructs an event from its time and flare position and
|
|
32
|
+
writes a report that separates what was measured from what was assumed. The CME of 2013 October
|
|
33
|
+
25 is the validation case, in which the result is compared with the earlier reconstruction of
|
|
34
|
+
Morosan et al. (2022), and the CME and type II burst of 2024 May 9 is a new application.
|
|
35
|
+
repository-code: "https://github.com/jovian-explorer/corona3d"
|
|
36
|
+
url: "https://jovian-explorer.github.io/software.html#corona3d"
|
|
37
|
+
keywords:
|
|
38
|
+
- solar corona
|
|
39
|
+
- coronal mass ejections
|
|
40
|
+
- MHD
|
|
41
|
+
- Alfven speed
|
|
42
|
+
- type II radio bursts
|
|
43
|
+
- LASCO
|
|
44
|
+
- STEREO
|
|
45
|
+
- GCS
|
|
46
|
+
references:
|
|
47
|
+
- type: article
|
|
48
|
+
title: "Shock-accelerated electrons during the fast expansion of a coronal mass ejection"
|
|
49
|
+
authors:
|
|
50
|
+
- family-names: Morosan
|
|
51
|
+
given-names: D. E.
|
|
52
|
+
- family-names: Pomoell
|
|
53
|
+
given-names: J.
|
|
54
|
+
- family-names: Kumari
|
|
55
|
+
given-names: A.
|
|
56
|
+
- family-names: Vainio
|
|
57
|
+
given-names: R.
|
|
58
|
+
- family-names: Kilpua
|
|
59
|
+
given-names: E. K. J.
|
|
60
|
+
journal: "Astronomy & Astrophysics"
|
|
61
|
+
volume: 668
|
|
62
|
+
start: A15
|
|
63
|
+
year: 2022
|
|
64
|
+
doi: 10.1051/0004-6361/202244432
|
corona3d-0.1.2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Keshav Aggarwal
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
corona3d-0.1.2/PKG-INFO
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: corona3d
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Physics-based, reproducible three-dimensional reconstruction of the solar corona, coronal mass ejections, and radio sources for any event from public MHD, coronagraph, and radio data, with an automated CME shell fit and a record of every input
|
|
5
|
+
Author-email: Keshav Aggarwal <keshavaggarwal2310@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://jovian-explorer.github.io/software.html#corona3d
|
|
8
|
+
Project-URL: Documentation, https://github.com/jovian-explorer/corona3d/blob/main/docs/USER_GUIDE.md
|
|
9
|
+
Project-URL: Source, https://github.com/jovian-explorer/corona3d
|
|
10
|
+
Project-URL: Issues, https://github.com/jovian-explorer/corona3d/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/jovian-explorer/corona3d/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: solar physics,corona,coronal mass ejection,MHD,Alfven speed,radio bursts,LASCO,STEREO
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Astronomy
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: numpy>=1.26
|
|
26
|
+
Requires-Dist: scipy>=1.11
|
|
27
|
+
Requires-Dist: matplotlib>=3.8
|
|
28
|
+
Requires-Dist: astropy>=6.0
|
|
29
|
+
Requires-Dist: sunpy[map,net]>=7.1
|
|
30
|
+
Requires-Dist: pyhdf>=0.11
|
|
31
|
+
Requires-Dist: platformdirs>=3.0
|
|
32
|
+
Provides-Extra: render
|
|
33
|
+
Requires-Dist: pyvista>=0.43; extra == "render"
|
|
34
|
+
Requires-Dist: PyThea<1.4,>=1.3; extra == "render"
|
|
35
|
+
Provides-Extra: gcs
|
|
36
|
+
Requires-Dist: PyThea<1.4,>=1.3; extra == "gcs"
|
|
37
|
+
Requires-Dist: scikit-image>=0.22; extra == "gcs"
|
|
38
|
+
Provides-Extra: radio
|
|
39
|
+
Requires-Dist: h5py>=3.8; extra == "radio"
|
|
40
|
+
Provides-Extra: animate
|
|
41
|
+
Requires-Dist: imageio-ffmpeg>=0.5; extra == "animate"
|
|
42
|
+
Provides-Extra: docs
|
|
43
|
+
Requires-Dist: mkdocs>=1.5; extra == "docs"
|
|
44
|
+
Requires-Dist: mkdocs-material>=9; extra == "docs"
|
|
45
|
+
Provides-Extra: test
|
|
46
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
47
|
+
Requires-Dist: pillow>=10; extra == "test"
|
|
48
|
+
Provides-Extra: all
|
|
49
|
+
Requires-Dist: corona3d[animate,gcs,radio,render]; extra == "all"
|
|
50
|
+
Dynamic: license-file
|
|
51
|
+
|
|
52
|
+
<p align="center"><img src="https://raw.githubusercontent.com/jovian-explorer/corona3d/main/docs/logo.png" width="180" alt="corona3d logo"></p>
|
|
53
|
+
|
|
54
|
+
# corona3d
|
|
55
|
+
|
|
56
|
+
[](https://doi.org/10.5281/zenodo.23801369)
|
|
57
|
+
|
|
58
|
+
> **Public** (pre-release). corona3d is ready for use and for testing, although its results can still change between versions, and problems, wrong results, and suggestions are welcome on the [issue tracker](https://github.com/jovian-explorer/corona3d/issues/new/choose). To cite corona3d, please use [CITATION.cff](https://github.com/jovian-explorer/corona3d/blob/main/CITATION.cff); the Zenodo concept DOI [10.5281/zenodo.23801369](https://doi.org/10.5281/zenodo.23801369) always resolves to the latest version, and version 0.1.1 has [10.5281/zenodo.23801370](https://doi.org/10.5281/zenodo.23801370).
|
|
59
|
+
|
|
60
|
+
## Purpose
|
|
61
|
+
|
|
62
|
+
Coronal mass ejections (CMEs) drive shocks through a corona whose density, magnetic field, and Alfvén speed vary strongly with height, latitude, and longitude. The radio bursts that these shocks excite, such as type II bursts and their herringbones, are emitted where the shock meets plasma of a particular density and field geometry. Whether a shock becomes super-Alfvénic, and whether it accelerates electrons along closed streamer loops or along open field, therefore depends on the three-dimensional structure of the corona at the moment the CME passes, which no single image can show. Global models of the corona, coronagraphs on spacecraft at different positions, and imaging radio arrays together contain the information needed to recover this structure, although each of them is distributed in its own format, coordinate frame, and archive. Reconstructions that combine a magnetohydrodynamic (MHD) model of the corona, a graduated cylindrical shell (GCS) of the CME, and radio-source positions have therefore been built by hand for single events, as for the CME of 2013 October 25 by Morosan et al. ([2022](https://doi.org/10.1051/0004-6361/202244432)), and their inputs and steps are rarely published in a form that another group can repeat. The relation between CME shocks, the coronal field, and the radio sources therefore remains poorly quantified for most events.
|
|
63
|
+
|
|
64
|
+
corona3d is a Python package that we developed to make this three-dimensional reconstruction of the corona, the CME, and the radio sources a repeatable measurement for any event, from its time and flare position, using public data and physical models only. The coronal model of Predictive Science Inc. (PSI) is rendered in three dimensions, the GCS shell of the CME is fitted to the coronagraph images, the white-light images of the Solar and Heliospheric Observatory (SOHO) and of the Solar Terrestrial Relations Observatory (STEREO) are placed in the plane of the sky of their spacecraft, and the radio sources measured in images of the Nançay Radioheliograph (NRH; Kerdraon & Delouis [1997](https://doi.org/10.1007/BFb0106458)) and of the Owens Valley Radio Observatory Long Wavelength Array (OVRO-LWA; Chhabra et al. [2021](https://doi.org/10.3847/1538-4357/abc94b)) are deprojected to their emission heights. Every layer can be switched on or off, every viewpoint can be chosen, every layer can be exported as arrays or tables, and every step is recorded with its inputs, so that a reconstruction can be repeated and checked by others. The CME of 2013 October 25 is the validation case of corona3d, in which its result is compared with the earlier reconstruction of Morosan et al. (2022), and the CME and type II burst of 2024 May 9 is a new application.
|
|
65
|
+
|
|
66
|
+
## What is new in corona3d
|
|
67
|
+
|
|
68
|
+
Compared with the earlier hand-built reconstruction of Morosan et al. (2022), corona3d adds several capabilities that make the result objective and repeatable. Its own field-line tracer integrates the unit field vector with a fourth-order Runge-Kutta scheme through the whole model, and on the run of 2013 October 25 its lines are tangent to the field (median |cos(line, B)| of 1.000, against 0.83 for the tracer of psipy that we tested), while every line is classed as open, closed, or undetermined. The streamer loops that the CME meets are selected without free parameters as the closed lines through the CME shell, and the GCS shell is fitted automatically to the coronagraph images, with the intersection over union (IoU) in each instrument as its objective and its measure of quality, with guards against degenerate shells and unconstrained directions, and with an apex height at the time of the burst that is extrapolated from the height-time profile of the front together with its uncertainty. Moreover, the coronagraph images are placed inside the three-dimensional reconstruction on one common scale, the radio sources are measured directly in the images of two radioheliographs and drawn as blobs or as contours at chosen levels, any viewpoint can be chosen, and every layer can be exported with its provenance. Finally, one command reconstructs any event from its time and flare position and writes a report that separates what was measured from what was assumed, and 150 offline tests check each step. Section 11 of the [user guide](https://github.com/jovian-explorer/corona3d/blob/main/docs/USER_GUIDE.md) compares the two reconstructions item by item.
|
|
69
|
+
|
|
70
|
+
## What corona3d does
|
|
71
|
+
|
|
72
|
+
The reconstruction is built from layers, each of which is computed from its own data and placed in one common Heliographic Carrington frame in solar radii (R⊙), so that the model, the shell, the images, and the radio sources can be compared directly.
|
|
73
|
+
|
|
74
|
+
| Element | What corona3d computes | Data and tools |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| Coronal model | the surface of constant electron density at the plasma level of a chosen frequency, coloured by the Alfvén speed, the open and closed field lines traced through the whole model, and the closed lines through the CME shell, which are the streamer loops that the CME meets | the PSI MAS/MAST thermodynamic MHD run of the Carrington rotation of the event, drawn with PyVista and the Visualization Toolkit (VTK) |
|
|
77
|
+
| CME shell | the GCS shell fitted to the CME envelopes in the coronagraph images, with its apex height extrapolated to the time of the reconstruction from the height-time profile of the front, and the quality of the fit stated with the intersection over union (IoU) in each instrument | PyThea, with the images of the Large Angle and Spectrometric Coronagraph (LASCO) C2 and of COR1 and COR2 on STEREO-A or STEREO-B |
|
|
78
|
+
| White-light images | the brightness ratio, or difference, of each frame against the first frame of the download window, drawn on the plane through Sun centre perpendicular to the line of sight of its spacecraft | LASCO C2 and STEREO COR1 and COR2, level 0.5, through the Virtual Solar Observatory |
|
|
79
|
+
| Radio sources | the centroids of the burst sources as chains of coloured blobs, and their contours at chosen fractions of the peak, placed at the heights of the four-fold Newkirk model for emission at the second harmonic | NRH images at 150 to 450 MHz, OVRO-LWA images at 32 to 87 MHz from 2024 April onward, and positions supplied by the user |
|
|
80
|
+
| Viewpoints | orthographic panels from Earth, from the STEREO spacecraft, from above the solar north pole, or from any Carrington longitude and latitude | observer positions from the ephemerides of the Jet Propulsion Laboratory (JPL Horizons) through SunPy |
|
|
81
|
+
| Workflow | one `config.json` per event, the commands `new`, `fetch`, `radio-interval`, `gcs`, `render`, `export`, and `event`, and a list of the radio bursts of a day from the event reports of the Space Weather Prediction Center (SWPC) of the National Oceanic and Atmospheric Administration (NOAA) | the public archives above |
|
|
82
|
+
| Output | figures, the layers as `npz`, `csv`, or VTK files with `metadata.json`, and `event_report.md`, which separates what was measured from what was assumed | |
|
|
83
|
+
|
|
84
|
+
Since every element is a key of the configuration, the same commands apply to an event observed by STEREO-B before 2014 October or by STEREO-A afterwards, with NRH or OVRO-LWA images, and with a model run of any Carrington rotation in the PSI archive.
|
|
85
|
+
|
|
86
|
+
## Install
|
|
87
|
+
|
|
88
|
+
corona3d needs Python 3.12 or newer, because PyThea 1.3, which builds the GCS shell, requires it, and it runs on Windows, macOS, and Linux. It is released on PyPI, and one command installs it with every optional part:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
pip install "corona3d[all]"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The newest development version installs directly from the repository with `pip install "corona3d[all] @ git+https://github.com/jovian-explorer/corona3d.git"`.
|
|
95
|
+
|
|
96
|
+
The plain package is the light core (downloads, event set-up, radio interval, `corona3d doctor`). The extras `render` (PyVista and PyThea, for the figures), `gcs` (PyThea and scikit-image, for the shell fit), and `radio` (h5py, for OVRO-LWA) add the heavy packages, `all` adds the three, and a command that needs a missing one names the extra to install. `corona3d --version` prints the version, and `corona3d doctor` reports the extras, the working directory (by default the platform cache directory, changed with `--home` or `CORONA3D_HOME`), and which archives answer. Since the newest pyhdf wheel for macOS requires macOS 26 and Homebrew no longer provides the HDF4 library, older Macs install with `pip install --prefer-binary`, which takes the previous pyhdf wheel, and `conda install -c conda-forge pyhdf` is an alternative on any system. The user guide ([Section 1](https://github.com/jovian-explorer/corona3d/blob/main/docs/USER_GUIDE.md#1-install-and-start)) gives the details.
|
|
97
|
+
|
|
98
|
+
## Quick start: one command for any event
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
mkdir event_work
|
|
102
|
+
cd event_work
|
|
103
|
+
corona3d event --time 2024-05-09T17:32 --flare S14W28
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The command writes the configuration of the event from its time and the flare position (14° south and 28° west of the disc centre), downloads the PSI MAS/MAST run and the white-light images, and, from 2024 April onward, the OVRO-LWA images, chooses the interval of the radio burst from the images, fits the GCS shell to the coronagraph images, draws the figures, and writes `event_report.md`. The report separates what was measured from what was assumed, lists the missing data, and gives the quality of the fit. When the free fit of the shell fails or is poor, the fit with the direction held at the flare site follows, and the report says so. The 2-D images of the NRH cannot be downloaded automatically (see the data sources below), and the report then names the manual step. The download takes a few minutes and the fit several more, whereas a figure takes about 40 s.
|
|
107
|
+
|
|
108
|
+
When only the date of an event is known, `corona3d event --time 2024-05-09 --flare S14W28` lists the type II and type III bursts of that day, and `--burst N` runs the event at the begin time of burst N, for example `--time 2024-05-09 --burst 4` for the type II burst of 17:32 UT. The same steps can also be run one at a time, which is useful when a step has to be checked or repeated with other options:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
corona3d new --time 2024-05-09T17:32 --flare S14W28 # config.json of the event
|
|
112
|
+
corona3d fetch # model run and white-light images
|
|
113
|
+
corona3d fetch --ovro-lwa # OVRO-LWA images of the radio interval
|
|
114
|
+
corona3d radio-interval # burst interval chosen from the radio images
|
|
115
|
+
corona3d gcs --flare 28 -14 --views c2,cor1a,cor2a # GCS fit to the coronagraph images
|
|
116
|
+
corona3d render --radio # figures/corona3d.png with the radio sources
|
|
117
|
+
corona3d export --format vtk # the layers as files for ParaView
|
|
118
|
+
corona3d animate --start 2024-05-09T17:30 --end 2024-05-09T17:40 --step 60 --radio --gif --mp4
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The figures are written to `figures/` together with the image of each panel (`view_a.png`, `view_b.png`, `view_c.png`). The options `--panel` and `--layout` of `render` and `animate` choose any views (Earth, solar north, STEREO, Solar Orbiter, or a Carrington direction) and draw them in one row, in one column, or as separate images, while `animate` writes a GIF and an MP4 of the reconstruction through a time interval (user guide, Section 4.1). Moreover, the [user guide](https://github.com/jovian-explorer/corona3d/blob/main/docs/USER_GUIDE.md) describes every command, option, and parameter, [docs/METHODS.md](https://github.com/jovian-explorer/corona3d/blob/main/docs/METHODS.md) derives how each element of the reconstruction is computed, [docs/LIMITATIONS.md](https://github.com/jovian-explorer/corona3d/blob/main/docs/LIMITATIONS.md) states where the results cannot be trusted, and [docs/MODEL_AUDIT.md](https://github.com/jovian-explorer/corona3d/blob/main/docs/MODEL_AUDIT.md) lists every method and number with its source and its test.
|
|
122
|
+
|
|
123
|
+
## Validation: the CME of 2013 October 25
|
|
124
|
+
|
|
125
|
+
The validation case of corona3d is the CME of 2013 October 25, which was launched from the eastern hemisphere at about 15:00 UT and observed from Earth and from STEREO-B, 142° apart, while the NRH recorded herringbones at 173 and 228 MHz. Morosan et al. (2022) published a hand-built three-dimensional reconstruction of this event (their Fig. 7), so that it is the one event for which the result of corona3d can be compared with an independent reconstruction. Its configuration is installed with the package, and the three panels are drawn from the same viewpoints as their Fig. 7, so that each layer can be compared panel by panel:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
mkdir corona3d_work
|
|
129
|
+
cd corona3d_work
|
|
130
|
+
corona3d init # writes config.json of the validation event
|
|
131
|
+
corona3d fetch # model run and white-light images (about 130 MB)
|
|
132
|
+
corona3d render # figures/corona3d.png
|
|
133
|
+
corona3d render --c2 --cor1 --cor2 --out figures/corona3d_wl.png
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The command `corona3d render` draws this event as seen from Earth, from above the solar north pole, and from STEREO-B. The electron-density surface lies at 9 × 10⁷ cm⁻³, the level that Morosan et al. used for the 173 MHz harmonic emission, and is coloured by the Alfvén speed between 100 and 700 km s⁻¹. The open and closed field lines are traced from 4,500 footpoints, and the closed lines that pass through the CME shell, the loops of the streamer that the CME meets, are drawn in purple.
|
|
137
|
+
|
|
138
|
+
<p align="center"><img src="https://raw.githubusercontent.com/jovian-explorer/corona3d/main/docs/corona3d_2013-10-25.png" width="100%" alt="The reconstruction of 2013 October 25 seen from Earth, the solar north pole, and STEREO-B"></p>
|
|
139
|
+
|
|
140
|
+
With `--c2 --cor1 --cor2`, the LASCO C2 image of 15:24 UT appears in the Earth view and the COR1 and COR2 images of STEREO-B appear in the STEREO-B view, each divided by the first image of the download window (14:35 to 14:39 UT). The shell is then drawn at 15:24 UT, the time of the images.
|
|
141
|
+
|
|
142
|
+
<p align="center"><img src="https://raw.githubusercontent.com/jovian-explorer/corona3d/main/docs/corona3d_2013-10-25_wl.png" width="100%" alt="The same reconstruction with LASCO C2 and STEREO-B COR1 and COR2 images"></p>
|
|
143
|
+
|
|
144
|
+
With `--radio` and the NRH images of the event copied into `data/nrh/`, the sources of the burst are added as coloured blobs (user guide, Section 5.7). The images available for the afternoon of that day are those at 150.9 and 432 MHz, and between 14:59 and 15:03 UT one image per minute gives five blobs at 150.9 MHz and three at 432 MHz, at 1.647 and 1.221 R⊙. These frequencies differ from the 173 and 228 MHz of Morosan et al. (2022), so that the radio layer agrees with their sources in kind but not in frequency.
|
|
145
|
+
|
|
146
|
+
<p align="center"><img src="https://raw.githubusercontent.com/jovian-explorer/corona3d/main/docs/corona3d_2013-10-25_radio.png" width="100%" alt="The reconstruction with the NRH radio sources at 150.9 and 432 MHz as coloured blobs"></p>
|
|
147
|
+
|
|
148
|
+
Since the model run of Morosan et al. (2022) is no longer served and their CME shell and radio positions were not published, the comparison tests whether corona3d, working from public data alone, recovers the structures of their reconstruction. Among the public runs of the same Carrington rotation, the one whose density surface agrees best with the outline of theirs was chosen, the GCS shell was fitted by corona3d from the public coronagraph images, and the radio sources are measured from the NRH images that can be obtained today. Section 11 of the [user guide](https://github.com/jovian-explorer/corona3d/blob/main/docs/USER_GUIDE.md) lists what agrees, what differs, and what corona3d adds.
|
|
149
|
+
|
|
150
|
+
## Application: the CME and type II burst of 2024 May 9
|
|
151
|
+
|
|
152
|
+
The CME of 2024 May 9 followed an X1.1 flare at S14W28 in active region 13664, and its type II burst began at 17:32 UT. Since STEREO-B lost contact with Earth in 2014 October and LASCO C2 has no frame between 14:48 and 18:52 UT, this event tests the parts of corona3d that the validation case does not, namely STEREO-A, a data gap, and the OVRO-LWA images. The preset installs its configuration, with the PSI run `cr2284-high/hmi_mast_mas_std_0201`, the positions of Earth and STEREO-A, and the OVRO-LWA images at 34.1, 52.4, 70.8, and 84.6 MHz:
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
mkdir may2024_work
|
|
156
|
+
cd may2024_work
|
|
157
|
+
corona3d init --event 2024-05-09
|
|
158
|
+
corona3d fetch
|
|
159
|
+
corona3d fetch --ovro-lwa
|
|
160
|
+
corona3d render --radio --shell-on-top
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The GCS shell of the preset was fitted to the COR1-A and COR2-A images at 17:55 UT with the direction held at the flare site, which gives an apex height of 3.722 R⊙ and an IoU of 0.878 in COR1-A. Earth and STEREO-A were separated by only about 12° in Carrington longitude, so that the two coronagraphs see the CME nearly from the same side and do not constrain its direction, and corona3d therefore ties the direction to the source region. Moreover, the coronagraph images show no rising front at 17:32 UT, and the apex height of 1.77 R⊙ at the time of the burst is assumed from a constant speed of about 985 km s⁻¹ after the flare onset at 17:23 UT, which the key `gcs_note` records. A shell this low lies partly inside the density surface, and `--shell-on-top` draws it, together with the radio sources, over the surface. The same event is reconstructed from its date alone with `corona3d event --time 2024-05-09 --flare S14W28 --burst 4`, and its `event_report.md` then states what was measured and what was assumed for this event, including the gap of LASCO C2 (user guide, Sections 9.1 and 9.5; [docs/LIMITATIONS.md](https://github.com/jovian-explorer/corona3d/blob/main/docs/LIMITATIONS.md), Sections 1 to 4).
|
|
164
|
+
|
|
165
|
+
## What is measured and what is assumed
|
|
166
|
+
|
|
167
|
+
| Element | Measured from data | Assumed or chosen |
|
|
168
|
+
|---|---|---|
|
|
169
|
+
| Corona before the CME | none | the steady-state PSI MAS/MAST run of the Carrington rotation; the density multiplied by 2 after Morosan et al. (2022) |
|
|
170
|
+
| Density surface and Alfvén speed | none | the density level `ne_level` (9 × 10⁷ cm⁻³); the Alfvén speed from the scaled density |
|
|
171
|
+
| Field lines and streamer loops | none | traced in the static model; loops selected as the closed lines through the shell |
|
|
172
|
+
| CME shell | six GCS parameters, fitted to the envelopes in LASCO C2 and COR1 or COR2 at the time of the images; apex height and speed extrapolated from the front | the direction held at the flare site when the free fit fails; an apex height given by hand; a constant speed between the frames |
|
|
173
|
+
| Coronagraph images | brightness ratio or difference against the first frame of the window | the image is placed in the plane of the sky through Sun centre |
|
|
174
|
+
| Radio sources | sky-plane centroids of the NRH or OVRO-LWA images above `min_tb` | the height of the four-fold Newkirk model at the second harmonic, on the side facing the observer; no correction for scattering |
|
|
175
|
+
| Observers | Carrington positions of Earth and STEREO from JPL Horizons through SunPy | none |
|
|
176
|
+
|
|
177
|
+
[docs/LIMITATIONS.md](https://github.com/jovian-explorer/corona3d/blob/main/docs/LIMITATIONS.md) describes the cases in which these inputs fail, namely halo CMEs, data gaps, a small separation between Earth and STEREO, assumed heights, the manual step for the NRH, and the resolution of the model.
|
|
178
|
+
|
|
179
|
+
## Data sources
|
|
180
|
+
|
|
181
|
+
The model run and the images are public, and `corona3d fetch` downloads them into the working directory.
|
|
182
|
+
|
|
183
|
+
| Data | Source and access | Used for |
|
|
184
|
+
|---|---|---|
|
|
185
|
+
| MAS/MAST thermodynamic MHD run (density and magnetic field; the mesh of the Alfvén-speed file), by default `cr2143-medium/hmi_mast_mas_std_0201` | [PSI model archive](https://www.predsci.com/data/runs/), public (Mikić et al. [1999](https://doi.org/10.1063/1.873474); Lionello et al. [2009](https://doi.org/10.1088/0004-637X/690/1/902); Mikić et al. [2018](https://doi.org/10.1038/s41550-018-0562-5)) | density surface, Alfvén speed, field lines |
|
|
186
|
+
| SOHO/LASCO C2 images, level 0.5 | Virtual Solar Observatory through SunPy, public (Brueckner et al. [1995](https://doi.org/10.1007/BF00733434)) | Earth-view overlay, GCS fit |
|
|
187
|
+
| STEREO-A or STEREO-B SECCHI COR1 polarisation triplets and COR2 total-brightness images, level 0.5 | Virtual Solar Observatory through SunPy, public (Howard et al. [2008](https://doi.org/10.1007/s11214-008-9341-4)); `--cor1a` adds STEREO-A COR1 | STEREO-view overlay, GCS fit |
|
|
188
|
+
| NRH 2-D images (Stokes I, about 10 s) | **On request only.** BASS2000 (Paris Observatory) holds only four snapshots per day at 164 and 327 MHz, movies, and visibility files; the 10 s images (`nrh2_*_i.fts`) are delivered by the Radio Solar Database at Nançay, [https://rsdb.obs-nancay.fr/](https://rsdb.obs-nancay.fr/), after a request there. The user copies the files into `data/nrh/`, and `corona3d fetch --nrh` reports which frequencies they cover | radio layer |
|
|
189
|
+
| OVRO-LWA spectral images (Stokes I, 10 s, 12 bands at 34 to 85 MHz), from 2024 April | [OVRO-LWA solar data](https://ovsa.njit.edu/docs/pages/ovro-lwa-solar-data-products/), public bucket on Amazon Web Services (CC BY 4.0); `corona3d fetch --ovro-lwa` | radio layer |
|
|
190
|
+
| Other radio-source positions (optional) | supplied by the user | radio layer |
|
|
191
|
+
|
|
192
|
+
SECCHI is the Sun Earth Connection Coronal and Heliospheric Investigation of STEREO. Work that uses these data should acknowledge the PSI model runs, the LASCO and SECCHI teams, the Nançay Radioheliograph, and OVRO-LWA with the references above, and all references are collected in [docs/refs.bib](https://github.com/jovian-explorer/corona3d/blob/main/docs/refs.bib).
|
|
193
|
+
|
|
194
|
+
## Using corona3d from Python
|
|
195
|
+
|
|
196
|
+
`corona3d.build(home, **layers)` returns the layers of a working directory as NumPy arrays in a `Reconstruction`, and `corona3d export` writes them as `npz`, `csv`, or VTK files together with `metadata.json`, which records the version, the configuration, and the sources of every input (user guide, Section 8). In this way the density, the Alfvén speed, the field lines, the shell, and the radio positions of an event can be used in further analysis without the figure.
|
|
197
|
+
|
|
198
|
+
## Citing
|
|
199
|
+
|
|
200
|
+
If you use corona3d, please cite it with [CITATION.cff](https://github.com/jovian-explorer/corona3d/blob/main/CITATION.cff), and cite Morosan et al. (2022) for the earlier reconstruction of the event of 2013 October 25 and for the density scaling and the radio heights that corona3d shares with it, Thernisien et al. ([2006](https://doi.org/10.1086/508254)) and Thernisien ([2011](https://doi.org/10.1088/0067-0049/194/2/33)) for the GCS model, Kouloumvakos et al. ([2022](https://doi.org/10.3389/fspas.2022.974137)) for PyThea, and the references of the data above.
|
|
201
|
+
|
|
202
|
+
## Licence
|
|
203
|
+
|
|
204
|
+
corona3d is free software under the MIT licence (`LICENSE`). Copyright 2026 Keshav Aggarwal.
|
|
205
|
+
|
|
206
|
+
## Author
|
|
207
|
+
|
|
208
|
+
Keshav Aggarwal, Student Visitor, Space Physics Laboratory (SPL), Vikram Sarabhai Space Centre (VSSC), Indian Space Research Organisation (ISRO), Thiruvananthapuram.
|
|
209
|
+
|
|
210
|
+
## Tests
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
pip install -e ".[all,test]"
|
|
214
|
+
python -m pytest # offline checks (about 1 min)
|
|
215
|
+
CORONA3D_ONLINE=1 python -m pytest # also downloads the data of 2013 October 25
|
|
216
|
+
```
|