Skip to content

Commit

Permalink
Updating documentation and version number
Browse files Browse the repository at this point in the history
  • Loading branch information
bryan-harter committed Jan 7, 2020
1 parent 0a88aa4 commit c3576f3
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 22 deletions.
Binary file added docs/source/_images/2d.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/_images/3d.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/_images/gui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
146 changes: 134 additions & 12 deletions docs/source/interactivity.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,30 @@ Interactive Plots

Part of the appeal of IDL tplot is that its easy to make plots that interact with the primary plotting window, primarily based on the time that the user is hovering the mouse over.

For now, we have implemented one type of interactive plot that slices the spectrograms so that you can better see the data from a single point in time.
There are several interactive plots that are in pytplot, specifically ones that are useful for the MAVEN spacecraft, but this page will also describe how to create your own interactive plots.


Spectrogram Slicing
-------------------

Slicing a spectrogram can be called in a few different ways. Probably the easiest way to do it for now would be to simply specify "interactive=True" when calling tplot (which is a very general keyword that should definitely be changed in the future) ::
Slicing a spectrogram can be called in a few different ways. The easiest way to do it would be to simply specify "slice=True" when calling tplot ::
pytplot.tplot("spectrogram_data", interactive=True)
pytplot.tplot("spectrogram_data", slice=True)

Below is what the spectrogram slicer command looks like in a Bokeh graph.

.. raw:: html
:file: _images/specslicer.html

There are a few options one can set with the options command to modify this plot (see the options command):
There are a few options one can set with the options command to modify this plot (see the options section):

=================== ========== =====
Options Value type Notes
=================== ========== =====
xlog_interactive bool Sets x axis on interactive plot to log scale if True.
ylog_interactive bool Sets y axis on interactive plot to log scale if True.
xrange_interactive flt list Two numberes that give the x axis range of interactive plots.
yrange_interactive flt list Two numberes that give the y axis range of interactive plots.
xlog_slice bool Sets x axis on interactive plot to log scale if True.
ylog_slice bool Sets y axis on interactive plot to log scale if True.
xrange_slice flt list Two numberes that give the x axis range of interactive plots.
yrange_slice flt list Two numberes that give the y axis range of interactive plots.
static str Creates a non-interactive spec-slicing plot. Datetime string that
gives desired time to plot y and z values from a specplot.
static_tavg str Creates a non-interactive spec-slicing plot. Datetime string that
Expand All @@ -36,6 +36,37 @@ t_average int Seconds around which the cursor is averaged whe
=================== ========== =====


Mars 2D Position
----------------

By linking a data tplot variable to tplot variables that contain spacecraft position information, one can bring up an interactive visualization of the spacecraft's position in MSO coordinates that changes depending on the time the
user is hovering over.

For example, suppose you have data in a tplot variable called "maven_data" and position information in the variables "mvn::kp::mso_x/y/z" ::
pytplot.link("maven_data", "mvn::kp::mso_x", "x")
pytplot.link("maven_data", "mvn::kp::mso_y", "y")
pytplot.link("maven_data", "mvn::kp::mso_z", "z")
pytplot.tplot("maven_data", pos_3d=True)

A window like the one below would appear, with a dot that moves around depending on where your mouse is hovered over on the main window.

.. image:: _images/2d.png


Mars 3D Position
-----------------

Similar to the above interactive plot, there is also a 3D viewer that is available if the user has pyopengl installed, which can be installed with the command ::

pip install pyopengl
In this case, you can create a 3D spacecraft position viewer of mars after linking x/y/z position information to the data, and plotting it with the command ::

pytplot.tplot("maven_data", pos_3d=True)

.. image:: _images/3d.png


Adding your Own Supplementary Qt Plots
----------------------------------------
Expand All @@ -49,15 +80,21 @@ However, if you are using python in a non-interactive environment (say just runn

This means that if you want multiple plots to appear at the same time, you need to supply a function to the tplot() command to call before it starts its event loop. Lets say you have a custom plot you'd like to appear at the same time as the pytplot plot, you would make sure your function gets called with the following addition to the tplot command::
pytplot.tplot(['variables_to_plot], extra_functions=[your_func])
pytplot.tplot(['variables_to_plot'], extra_functions=[your_func])

Or, if you need to supply arguements to your function::

pytplot.tplot(['variables_to_plot], extra_functions=[your_func], extra_function_args=[(arg1, arg2, arg3)])
pytplot.tplot(['variables_to_plot'], extra_functions=[your_func], extra_function_args=[(arg1, arg2, arg3)])

Why would you want to ensure plots appear at the same time? Mainly for interactivity purposes, as described in the following section.


*Alternatively*, you can tell the tplot command to not begin the event loop at all, and you can call it yourself later. This can be done simply by specifying::
pytplot.tplot(['variables_to_plot'], exec_qt=False)

Then you can run your own functions and begin the event loop after calling tplot.


Adding Interactivity
--------------------
Expand Down Expand Up @@ -105,5 +142,90 @@ This is a very simple script that will create a qt window using pyqtgraph that d
.. image:: _images/interactivity.png


For a more complex example, you can take a look at the spec_slicer function.

For a more complex example, you can take a look at the spec_slicer, 2d_position_mars, and 3d_position_mars functions.


GUI Creation
-------------

When plots are created in pytplot using pyqtgraph, they are actually stored in a list alongside a list of names at the global level, which can be accessed via ::
pytplot.pytplotWindow_names
pytplot.pytplotWindows

You can specify window names when you call pytplot so that you can reference them later to build a GUI. For example ::
pytplot.tplot('mvn_kp::spacecraft::altitude', exec_qt=False, window_name='PYDIVIDE_MAP2D')

The above command will a) stop the qt event loop from starting and b) name the window created "PYDIVIDE_MAP2D". Then you can find the window again by ::

for i, plot_name in enumerate(pytplot.pytplotWindow_names):
if plot_name == 'PYDIVIDE_MAP2D':
The_window_I_need = pytplot.pytplotWindows[i]

This can be useful if you want to add the window to a GUI you are creating.


GUI Creation Example
---------------------

Below is some sample code of how the MAVEN SDC creates a simple GUI from pytplot ::

# Load in MAVEN Data from PySPEDAS (variables assumed to be filled in from elsewhere)
tplot_names = pyspedas.maven_load(filenames=filenames, instruments=instruments, level=level, type=type, start_date=start_date, end_date=end_date)

# Change Altitude information to plot as a Map
pytplot.options('mvn_kp::spacecraft::altitude', 'map', 1)

# Grab local Map file and specify it as the background map
map_file = os.path.join(os.path.dirname(__file__), 'basemaps', 'MAG_Connerny_2005.jpg')
pytplot.options('mvn_kp::spacecraft::altitude', 'basemap', map_file)

# Plot items without execution of the qt event loop
pytplot.tplot(tplot_names, pos_2d=True, pos_3d=True, interactive=True, exec_qt=False, window_name='PYDIVIDE_PLOT')
pytplot.tplot('mvn_kp::spacecraft::altitude', exec_qt=False, window_name='PYDIVIDE_MAP2D', extra_functions=[],
extra_function_args=[])

# Build up the GUI from QSplitter items
app = QtGui.QApplication([])
win = QtGui.QMainWindow()
app.setStyle("Fusion")

plot_splitter = QtGui.QSplitter(QtCore.Qt.Vertical, frameShape=QtGui.QFrame.StyledPanel,
frameShadow=QtGui.QFrame.Plain)
ancillary_splitter = QtGui.QSplitter(QtCore.Qt.Vertical, frameShape=QtGui.QFrame.StyledPanel,
frameShadow=QtGui.QFrame.Plain)
main_splitter = QtGui.QSplitter(QtCore.Qt.Horizontal, frameShape=QtGui.QFrame.StyledPanel,
frameShadow=QtGui.QFrame.Plain)
main_splitter.addWidget(plot_splitter)
main_splitter.addWidget(ancillary_splitter)

for i, plot_name in enumerate(pytplot.pytplotWindow_names):
if plot_name == 'PYDIVIDE_PLOT':
plot_splitter.addWidget(pytplot.pytplotWindows[i])

for i, plot_name in enumerate(pytplot.pytplotWindow_names):
if plot_name == 'PYDIVIDE_MAP2D':
plot_splitter.addWidget(pytplot.pytplotWindows[i])

for i, plot_name in enumerate(pytplot.pytplotWindow_names):
if plot_name == 'Spec_Slice':
ancillary_splitter.addWidget(pytplot.pytplotWindows[i])
for i, plot_name in enumerate(pytplot.pytplotWindow_names):
if plot_name == '2D_MARS':
ancillary_splitter.addWidget(pytplot.pytplotWindows[i])
for i, plot_name in enumerate(pytplot.pytplotWindow_names):
if plot_name == '3D_MARS':
ancillary_splitter.addWidget(pytplot.pytplotWindows[i])

main_splitter.show()

# Finally, start the event loop
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
app.exec_()


Below is a sample of what the created interactive GUI looks like.

.. image:: _images/gui.png
14 changes: 7 additions & 7 deletions docs/source/linking.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Non-Time Series Plots
=====================
Linking Two Variables and Non-Time Series Plots
==================================================

Sometimes plots other than time series may be desired. Typically, this is either altitude or latitude/longitude plots.

Expand All @@ -10,7 +10,7 @@ In other words, if you have a tplot variable for altitude named "spacecraft_alt"
pytplot.link("spacecraft_data", "spacecraft_alt", link_type = 'alt')

If the data are not on the same time cadence, the linked variable will be interpolated to match that of the data variable.
If the data are not on the same time cadence, the linked variable will be interpolated to match that of the data variable at the time of plotting.


Why Linking?
Expand Down Expand Up @@ -87,8 +87,8 @@ It also plots only the euv_lyman variable::
# Plot!
pytplot.tplot("euv_lyman")




.. raw:: html
:file: _images/map.html
:file: _images/map.html


If pyqtgraph is used to plot the map plot instead, a little marker will appear on the map at the time the user is hovering over with their mouse.
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
numpy
bokeh
bokeh >= 1.1
pyqtgraph
pandas
matplotlib
Expand Down
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = pytplot
version = 1.4.8
version = 1.5.0
author = MAVEN SDC
author_email = [email protected]
description = A python version of IDL tplot libraries
Expand Down Expand Up @@ -31,7 +31,7 @@ include_package_data = True
packages = find:
install_requires =
numpy
bokeh
bokeh >= 1.1
pyqtgraph
pandas
matplotlib
Expand Down

0 comments on commit c3576f3

Please sign in to comment.