GithubHelp home page GithubHelp logo

jgieseler / solarmach Goto Github PK

View Code? Open in Web Editor NEW
28.0 2.0 6.0 12.84 MB

Python package of the multi-spacecraft longitudinal configuration plotter Solar-MACH

Home Page: https://solarmach.readthedocs.io

License: BSD 3-Clause "New" or "Revised" License

Python 100.00%
esa heliophysics spacephysics spaceweather

solarmach's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

solarmach's Issues

Provide option to move the legend and logo

Provide option(s) to allow the user to easily move the position of the legend and the Solar-MACH logo. They are defined using matplotlib:

# legend
leg1 = ax.legend(loc=(1.2, 0.7), fontsize=13)

#logo
ax.text(0.94, 0.16, 'Solar-MACH', fontfamily='DejaVu Serif', fontsize=28,
        ha='right', va='bottom', transform=fig.transFigure)
ax.text(0.94, 0.12, 'https://solar-mach.github.io', fontfamily='DejaVu Sans', fontsize=18,
        ha='right', va='bottom', transform=fig.transFigure)

Maybe the best approach is to follow matplotlib's standard legend placement, that look like the following. The location can be provided by an integer or by a string like 'lower right':
image

So, for solarmach, the example in Python (the streamlit version would use GUI elements, e.g., a dropdown menu for each variable) would look like:

# locations provided by y and x position, e.g. 'upper right'
fig, ax = sm.plot(loc_legend='lower left', loc_logo='center right')

Note that in Python, it should already now be possible to change those locations by using the option to return the matplotlib figure object and modify it afterwards, but this is not straightforward.

The plot rotates with changing the date

Hi, I noticed that once the date and time are changed, the polar plot rotates and it's no longer adjusted as shown in the example notebook (i.e., the 90 deg. points upward, 0 deg. points to the right, etc.).
Is there a workaround to make the polar plot fixed when changing the date and time?
Also I don't know why the grid circles disappear

image

image

Draw the field line in 3D

Hi, I was trying to to plot the extracted field lines in a 3D figure, but it didn't succeed. Could you please take a look?
I transformed the points of the field line from the polar coordinates to the cartesian coordinates, but it didn't show up in the 3D figure. The scale of the polar plot is in AU, while the scale in the 3D figure is in solar radii unit.
Here's the code and the output figures:

from solarmach import SolarMACH
import astropy.constants as aconst
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sunpy.sun import constants as const


body_list = ['STEREO-A', 'Earth', 'PSP']
vsw_list = [400, 400, 400]
date = '2022-07-22 13:40:00'

coord_sys = 'Stonyhurst'                         # 'Carrington' (default) or 'Stonyhurst'
reference_long = -10                             # longitude of reference (None to omit)
reference_lat = 32                               # latitude of reference (None to omit)
reference_vsw = 400                              # define solar wind speed at reference
long_offset = 270                                # longitudinal offset for polar plot; defines where Earth's longitude is (by default 270, i.e., at "6 o'clock")
plot_spirals = True                              # plot Parker spirals for each body
plot_sun_body_line = False                       # plot straight line between Sun and body
return_plot_object = True                        # figure and axis object of matplotib are returned, allowing further adjustments to the figure
transparent = False                              # make output figure background transparent
numbered_markers = True                          # plot each body with a numbered marker

# initialize
sm = SolarMACH(date, body_list, vsw_list, reference_long, reference_lat, coord_sys)

# make plot
fig, ax = sm.plot(
                   plot_spirals=plot_spirals,
                   plot_sun_body_line=plot_sun_body_line,
                   reference_vsw=reference_vsw,
                   transparent=transparent,
                   numbered_markers=numbered_markers,
                   long_offset=long_offset,
                   return_plot_object=return_plot_object
                )

# Adding another field line info
new_reference_long = 120
new_reference_lat = 7
new_reference_vsw = 400

# add anther arrow
arrow_dist = min([sm.max_dist/3.2, 2.])
ax.arrow(np.deg2rad(new_reference_long), 0.01, 0, arrow_dist, head_width=0.2, head_length=0.07,
         edgecolor='dodgerblue', facecolor='dodgerblue', lw=1.8, zorder=5, overhang=0.2)

#add another dashed Parker spiral at arrow
AU = (const.au/1000).value # km
r_array = np.arange(0.007, (sm.max_dist+0.1)/np.cos(np.deg2rad(sm.max_dist_lat)) + 3.0, 0.001)
omega_ref = sm.solar_diff_rot(new_reference_lat)
alpha_ref = np.deg2rad(new_reference_long) + omega_ref / (reference_vsw / AU) * (sm.target_solar_radius*aconst.R_sun.to(u.AU).value - r_array) * np.cos(np.deg2rad(new_reference_lat))
ax.plot(alpha_ref, r_array * np.cos(np.deg2rad(new_reference_lat)), '--', color='dodgerblue',
        label='Second filed line')

# reset max. radius for plot
ax.set_rmax(sm.max_dist + 0.3)

# extract the field lines
xfl1, yfl1 = ax.get_children()[10].get_data()
xfl2, yfl2 = ax.get_children()[19].get_data()

fig

image
image

# make the 3D figure
fig = plt.figure(figsize=[8,8])
ax = fig.add_subplot(111, projection='3d', computed_zorder=False)

# draw the Sun
theta, phi = np.mgrid[0:np.pi:100j, 0:2*np.pi:100j]
x = np.sin(theta)*np.cos(phi) 
y = np.sin(theta)*np.sin(phi) 
z = np.cos(theta)
ax.plot_surface(x, y, z, color='orange', zorder=0)

# draw the field lines from solarmach
r = xfl1  # Radial distance (r) from polar plot
theta = yfl1  # Angular coordinate (theta) from polar plot

# Convert polar coordinates to Cartesian coordinates
x_3d = r * np.cos(theta)
y_3d = r * np.sin(theta)

# make the 3rd axis as a 1D array of points similar to the given latitute
z_3d = np.full(len(x_3d), reference_lat)

ax.plot3D(x_3d, y_3d, z_3d, zorder=10)

# plot settings
axes_limit = 3
ax.set_xlim(-axes_limit, axes_limit)
ax.set_ylim(-axes_limit, axes_limit)
ax.set_zlim(-axes_limit, axes_limit)
ax.set_box_aspect([axes_limit, axes_limit, axes_limit])
for axis in 'xyz':
    getattr(ax, 'set_{}label'.format(axis))(axis+' [R$_\odot]$')
plt.show()

image

Fully implement Astropy units

Adjust code so that Astropy units are used wherever possible. This is already included in recent code changes like the following:

alpha = math.degrees(omega * (radius-target_solar_radius*aconst.R_sun).to(u.km).value / vsw)

But in this example, the solar wind speed vsw is still fixed to km/s. Fully incorporating units would help to avoid possible problems.

Try different representation of the plot (3d, latitudinal)

Right now, we only plot the heliographic equatorial plane, so radial distance projected to it and longitude.

  • A nice (and easy) addition would be to plot a sideview, showing the different latitudes of the spacecraft (with longitude projected to the plane).
  • Also worthwhile to check is actually using a 3d plot. Not sure how this works with Streamlit; maybe something else such as plotly or bokeh needs/can be used instead of matplotlib (see https://docs.streamlit.io/library/api-reference/charts for supported versions).

Optimize pdf file output

While it is in principle already possible to save the figure as a (vectorized) pdf file, the resulting plot needs more fine-tuning. Especially, the fonts are too small and partly misaligned (in the legend).

from solarmach import SolarMACH

body_list = ['STEREO-A', 'Earth', 'BepiColombo', 'PSP', 'Solar Orbiter', 'Mars']
vsw_list = [400, 400, 400, 400, 400, 400, 400]   # position-sensitive solar wind speed per body in body_list
date = '2021-10-28 15:15:00'
filename = 'Solar-MACH_'+date.replace(' ', '_')+'.pdf'

sm = SolarMACH(date, body_list, vsw_list)
fig, ax = sm.plot(numbered_markers=True, return_plot_object=True, outfile=filename)

PDF file:
Solar-MACH_2021-10-28_15:15:00.pdf

Corresponding PNG file:
solarmach

(In the code plt.savefig is used with bbox_inches="tight" - does that work for pdf files?)

Extracting objects from the plot

Hello, I would like to ask is it possible to extract the Parker spiral line object (dashed black curve) from the plot somehow, to plot it into another plot?
Also when I set the coord_sys to be Stonyhurst, the inner grid circles disappear. Is it possible to show them?
Here's the code to reproduce the same plot below:

from solarmach import SolarMACH
import warnings
warnings.filterwarnings('ignore')
import matplotlib.pyplot as plt
plt.rcParams['figure.dpi'] = 100
plt.rcParams['figure.facecolor'] = 'white'
plt.rcParams['savefig.dpi'] = 300
plt.rcParams['savefig.format'] = 'png'
plt.rcParams['savefig.facecolor'] = 'white'
plt.rcParams['figure.figsize'] = [5,5]


# necessary options
body_list = ['STEREO-A', 'Earth', 'PSP']
vsw_list = [400, 400, 400]
obs_date = '2022-01-03 12:40:00'

# optional parameters
reference_long = -45
reference_lat = 12
reference_vsw = 400
long_offset = 270
plot_spirals = True
numbered_markers = True
return_plot_object = True
plot_sun_body_line = True
show_earth_centered_coord = False

# initialize
sm = SolarMACH(obs_date, body_list, vsw_list, 
               reference_long, reference_lat,
               coord_sys='Stonyhurst'
              )

# make plot
fig, ax = sm.plot(plot_spirals=plot_spirals, 
                  plot_sun_body_line=plot_sun_body_line, 
                  show_earth_centered_coord=show_earth_centered_coord, 
                  reference_vsw=reference_vsw, 
                  numbered_markers=numbered_markers, 
                  return_plot_object=return_plot_object,
                  long_offset=long_offset
                 )

Versions:
solarmach.__version__ is 0.1.5
matplotlib.__version__ is 3.7.1
python --version is 3.9.12

image

pandas.options.display.max_rows is set to "None" in __init__.py

pd.options.display.max_rows is set to "None" in init.py:

plt.rcParams['axes.linewidth'] = 1.5
plt.rcParams['font.size'] = 15
plt.rcParams['agg.path.chunksize'] = 20000
pd.options.display.max_rows = None
pd.options.display.float_format = '{:.1f}'.format

This causes trouble for users who might want to use pandas and print bits of large dataframes (e.g. SEP data) after using solarmach in the same notebook: The whole dataframe is printed, swamping the whole notebook session...

Is the pd.options.display.max_rows=None really needed? The default seems to be 60, I'd be hard-pressed to find more than 60 spacecraft for solarmach to handle...

Likewise, the display format is set, which could cause annoyance (but not as big trouble as the max_rows=None).

There are also a couple of plt rcParams there that could be used only temporally, restoring back to whatever values were used outside of the solarmach calls.

Occasionally missing reference arrow line

On some occasions, the line of the arrow indicating the reference is missing:
Solar-MACH_2020-07-11_03-00-00b

This might be connected to the radial range that is plotted because in the following it is fine:
Solar-MACH_2020-07-11_03-00-00

In addition, if the radial range changes, e.g. by adding Mars or some other further positioned observer, the tip of the arrow changes in size. So it might be better to not define the arrow length & shape in absolute values, but rather fraction of r_max.

Hopefully this also fixes the bug of the missing arrow line.

Give the option to show the figure after plot()

Currently, because plt.show() is called by default in plot() the figure is created there and this prevents the user to add more data in the plots after function returns.

It would be usefull to select plt.show() with a key.

Fix plot position

The position of the plot can vary slightly because of the moving Carrington longitude (with the additional Earth-centered coordinates plotted on top this doesn't happen). This might be a bit problematic if one wants to use multiple plots to make an animation (example).

=> Change the code to ensure that the plot always is at the same position in the figure.

Plot magnetogram on solar surface in PFSS 3d plot

The PFSS extension offers a 3d plot including the Sun, like the following (e.g., run PFSS analysis in streamlit beta version):

newplot

For this figure, provide the option to plot the magnetogram (that has been downloaded for the PFSS analysis before) on the solar surface. This is already accomplished with sunkit-pyvista's example https://docs.sunpy.org/projects/sunkit-pyvista/en/stable/generated/gallery/field_lines.html:

image

But that uses a different plotting engine. So either check if it makes sense to start with the sunkit-pyvista plot and add the solarmach functionality to that, or see how the plotting is done there and apply it to the current plotly figure used in solarmach. For the first option, one important question to check is whether sunkit-pyvista can be run within streamlit.

Legend misaligned with latest matplotlib

Until (at least) matplotlib version 3.5.3 the solarmach plot looks fine, but with the latest version (3.6.2), the figure is cropped a bit on the right side, resulting the legend to be cropped (and the logo being closer to the edge):
Solar-MACH_2021-10-20_00:00:00

Don't know yet what has changed, but maybe it's a good moment to make the figure code a bit more "robust". And also tackle it together with Provide option to move the legend and logo (#24).

Take into account solar differential rotation

Right now, the solar rotation period at the equator is used to calculate Parker spirals and perform ballistic backmapping. For near-ecliptic observers this might be fine, but with Solar Orbiter going to higher latitudes, this needs to be adjusted by taking into account the solar differential rotation.

Plot distance projected to the ecliptic plane instead of radial distance (optionally)

At the moment, Solar-MACH shows the configuration plot only with respect to longitude and radius. For high latitude orbits (e.g., Solar Orbiter), it might be worthwhile to (optionally) plot the distance projected to the ecliptic plane instead of the radial distance (in spherical coordinates). So in the following picture (where x, y span the ecliptic), using r instead of ρ:

(Figure source. Note that this picture plots the colatitude ф, and not the latitude, which would be 90-ф)

Thanks to @AthKouloumvakos for the idea

Add trajectories of bodies

Provide the option to provide (plot) trajectories of bodies. For example, over 24 hours plot the hourly positions of Parker Solar Probe, connecting them with a line. This line could also have some color/saturation coding to allow for time-dependency.

Too different values in long_sector_vsw cause a plotting glitch

#32 added the option to fill the area of the plot between two Parker spirals with a given color. But when the solar wind speeds in long_sector_vsw differ to some extent, the plotting does not work as intended:

from solarmach import SolarMACH
body_list = ['STEREO-A', 'Earth', 'BepiColombo', 'PSP', 'Solar Orbiter', 'Mars']
vsw_list = [400, 400, 400, 400, 400, 400]
date = '2022-3-11 12:00:00'

sm = SolarMACH(date, body_list, vsw_list)
sm.plot(numbered_markers=True, long_sector=[290,328], long_sector_vsw=[400,700], long_sector_color='cyan')

issue32_bug

The problem can be seen a bit better when zoomed out to further distances:

issue32_bug2

The problem originates in the fact that plt.fill_between() fills the area between the two Parker spirals at a given radial distance. Maybe the problem could be solved if the filling wouldn't be done with respect to radial distance, but distance along the spiral line. Not sure how to implement that, though.

Add a small figure mode

Occasionally people use the solarmach plot in a small size (in a publication or presentation), like this:

This often results in too thin lines and/or too small figure items. Investigate the possibility to add a "small figure" option for producing a modified version of the figure optimised for small size.

Definition of connection angle

From @Laura-GitHub:
For me (and in other studies I have consulted), a positive connection angle means the opposite as you have in the table. Positive CA denotes a flare source located at the western side of the spacecraft magnetic footpoint.

For example, in the following map and table (see below), MESSENGER has a negative connection angle to the flare location and EARTH has a positive connection angle. It is shown the opposite in the table. It might be possible that there are people who prefer the other way around, but I just wanted to share with you my point of view.

image
image

Adding the figure to another figure + stopping the fig from showing up

Hello, I have two questions, please.

  1. How can I stop the output figure from showing up? Is there an option to just return the fig, ax objects of sm.plot without showing the figure itself?

  2. How can I add the output figure to a matplotlib.axes._subplots.AxesSubplot object to show the figure in another subplot figure? I tried the code below but I was wondering if there was a more efficient way to do that.

Here's the code I tried:

from solarmach import SolarMACH
import matplotlib.pyplot as plt

body_list = ['Earth', 'Mars', 'STEREO-A', 'PSP', 'Solo']
vsw_list = []                                    # leave empty to obtain measurements
date_solmach = '2021-06-07'

coord_sys = 'Stonyhurst'                         # 'Carrington' (default) or 'Stonyhurst'
reference_long = None                            # longitude of reference (None to omit)
reference_lat = None                             # latitude of reference (None to omit)
reference_vsw = 400                              # define solar wind speed at reference
long_offset = 270                                # longitudinal offset for polar plot; defines where Earth's longitude is (by default 270, i.e., at "6 o'clock")
plot_spirals = True                              # plot Parker spirals for each body
plot_sun_body_line = False                       # plot straight line between Sun and body
return_plot_object = True                        # figure and axis object of matplotib are returned, allowing further adjustments to the figure
transparent = True                               # make output figure background transparent
numbered_markers = True                          # plot each body with a numbered marker

# initialize
sm = SolarMACH(date_solmach, body_list, vsw_list, reference_long, reference_lat, coord_sys)

# make plot
fig_solmach, ax_solmach = sm.plot(plot_spirals=plot_spirals,
                  plot_sun_body_line=plot_sun_body_line,
                  reference_vsw=reference_vsw,
                  transparent=transparent,
                  numbered_markers=numbered_markers,
                  long_offset=long_offset,
                  return_plot_object=return_plot_object,
                                  figsize=[17,10])


fig = plt.figure(figsize=[20,10])
ax = fig.add_subplot(331)
ax.imshow(fig_solmach.canvas.renderer.buffer_rgba())
ax.axes.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)

# Add more panels to the figure
# ..............................

plt.show()

Make effective use of `sunpy.time.parse_time`

The function sunpy.time.parse_time provides a way to parse many different time inputs into an astropy.time.Time object. I see that this function is used once in the sc_distance function. I would recommend that this function also be used when parsing date inputs in the SolarMach object. This would greatly simplify any later handling of the date as one can program against a single astropy.time.Time object rather than an ambiguous representation of that date.

conda version without speasy support

solarmach uses speasy to obtain the measured solar wind speeds for selected spacecraft and falls back to an editable default value is this fails or speasy is not available. Because speasy is not available through conda, the conda version of solarmach skips its installation, and consequently, this version doesn't offer the functionality provided by speasy.

  1. Add a mentioning of this to the documentation, so that a user might op to install the pypi version of solarmach, or pip-install speasy in their conda environment.
  2. Investigate the option to automatically install the pypi version of speasy with the conda version of solarmach.

Occasionally missing grid circles

Occasionally the grid circles that indicate distances of 0.5, 1.0, 1.5 AU (set by ax.set_rgrids) are not plotted. The problem can't (yet) be fully reproduced, but it is connected to the chosen date and time. It seems to occur more often when setting the current (or a future) date and early times in the day.

In this example, taken on 2021-10-20, 8:45 (UTC), the problem manifest when choosing 2021-10-20, 1:00, but it vanishes for 2021-10-20, 1:15 (i.e., set to 15 minutes later):

bug
nobug

Problems with dependencies in the conda-forge version

Recent additional features require the packages pfsspy and speasy (to do PFSS modelling or acquire solar wind speeds, respectively). The problem is that these packages are not available at conda-forge as of now, so they can't be added as requirements.

Provide option to plot a bunch of IMF lines in the background

Right now, for each observer, an IMF line for a given solar wind speed is plotted. Provide the option to plot a bunch of these filed lines in the background (for a single given solar wind speed); with an option for the total number, and then spread them evenly.

This is a user request from the SERPENTINE User Workshop.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.