Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs #213

Merged
merged 42 commits into from
Oct 1, 2024
Merged

Docs #213

Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a91f4cb
linked nb to root folder, deleted dupes
plesiopterys Apr 4, 2024
7e8c458
added requirements nbsphinx-link pytest
plesiopterys Apr 4, 2024
36c96da
renamed example 6 in notebooks.rst so file gets included
plesiopterys Apr 4, 2024
cdd0b0b
new branch
plesiopterys Apr 9, 2024
7bdc4ac
Merge branch 'main' of https://github.com/sandialabs/pyscan into plot…
plesiopterys Apr 9, 2024
b773f5c
testing in progress
plesiopterys Apr 11, 2024
9d28493
feature: plot generator handles 3D data for 2D plots
plesiopterys Apr 25, 2024
638c4dc
update from main
plesiopterys Apr 25, 2024
591b497
docstrings fixed to not have Properties (breaking the docs build)
plesiopterys Apr 25, 2024
e55062c
trying to make docs build
plesiopterys Apr 25, 2024
d4c25be
flake8 fix
plesiopterys Apr 25, 2024
352e68f
flake8 fix
plesiopterys Apr 25, 2024
0b746f6
Update __init__.py
plesiopterys Apr 25, 2024
2ad8630
Merge branch 'main' of https://github.com/sandialabs/pyscan into plot…
rsbrost May 13, 2024
d9b9796
implemented experiment killswitch into live_plot_funtion so that user…
rsbrost May 13, 2024
dba302d
added note for using this new feature.
rsbrost May 13, 2024
241fee2
additionally implemented killswitch in experiment.py. May want to onl…
rsbrost May 14, 2024
1e39892
added killswitch ability to experiments that can run liveplots while …
rsbrost May 14, 2024
e717e33
including the killswitch demo_nb in this commit since I moved it out …
rsbrost May 14, 2024
cd2b930
fix: tried updating killswitch example notebook to skip last cell on …
rsbrost May 14, 2024
1be0de8
deleting extranneous files
rsbrost May 23, 2024
f36280f
merged from main
rsbrost May 23, 2024
a7af1f8
updated keithley2260b doc string to match other syntax for documentat…
rsbrost May 23, 2024
3e204d1
updated syntax to be kill_switch rather than killswitch
rsbrost May 23, 2024
63205b9
removing kill switch from plotting branch.
rsbrost May 23, 2024
37c1fc6
cleaning up...
rsbrost May 23, 2024
c66064a
cleaning up...
rsbrost May 23, 2024
f999285
chore: pulled from main.
rsbrost Jun 10, 2024
3502a7d
feat: Added live_multi_plot function
plesiopterys Aug 6, 2024
9897f3a
fixed live multiplot display issues
plesiopterys Aug 7, 2024
72be5b8
fix get_pyscan_version in run_info to work without -e install
plesiopterys Aug 9, 2024
f953665
added -e to installation instructions in docs
plesiopterys Aug 9, 2024
f92dcc3
Added advanced notebooks to docs
plesiopterys Aug 12, 2024
fe68b3f
2 levels shown on secondary sidebar
plesiopterys Aug 12, 2024
254047a
docs: renaming advanced demo notebooks to begin with an a so their nu…
rsbrost Sep 18, 2024
b341479
revert(general): restoring main version of get_pyscan_version.
rsbrost Sep 18, 2024
9d3558e
revert(measurement): restoring main version of run_info.py.
rsbrost Sep 18, 2024
b28d2c7
Merge branch 'main' of https://github.com/sandialabs/pyscan into docs
rsbrost Sep 26, 2024
21d088c
chore: incrementally removing plotting PR changes from docs branch.
rsbrost Sep 26, 2024
b5f7cb4
chore: incrementally removing plotting PR changes from docs branch - …
rsbrost Sep 26, 2024
98e3580
chore: incrementally removing plotting PR changes from docs branch - …
rsbrost Sep 26, 2024
a39196e
Merge branch 'main' of https://github.com/sandialabs/pyscan into docs
rsbrost Oct 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions demo_notebooks/02-example_plotting_multiD_data.ipynb

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions demo_notebooks/advanced/01-custom_live_plot.ipynb
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 01 Example - Custom Live Plot"
]
},
{
"cell_type": "code",
"execution_count": 1,
Expand Down Expand Up @@ -30,6 +37,13 @@
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setup devices"
]
},
{
"cell_type": "code",
"execution_count": 2,
Expand All @@ -43,6 +57,13 @@
"devices.v3 = ps.TestVoltage() # Device 3"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define a measure function"
]
},
{
"cell_type": "code",
"execution_count": 8,
Expand All @@ -68,6 +89,13 @@
" return d"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define Plot Function"
]
},
{
"cell_type": "code",
"execution_count": 15,
Expand All @@ -86,6 +114,13 @@
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Experiments"
]
},
{
"cell_type": "code",
"execution_count": 16,
Expand Down
220 changes: 220 additions & 0 deletions demo_notebooks/advanced/02-multi_live_plot.ipynb

Large diffs are not rendered by default.

Empty file.
10 changes: 10 additions & 0 deletions docs/source/advanced/advanced_notebooks.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Demo Notebooks
==============

You can find demo notebooks for advanced examples on how to use pyscan

.. toctree::
:maxdepth: 1

demo_notebooks/01-custom_live_plot
demo_notebooks/02-multi_live_plot
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"path": "../../../../demo_notebooks/advanced/01-custom_live_plot.ipynb"
}
3 changes: 3 additions & 0 deletions docs/source/advanced/demo_notebooks/02-multi_live_plot.nblink
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"path": "../../../../demo_notebooks/advanced/02-multi_live_plot.ipynb"
}
10 changes: 9 additions & 1 deletion docs/source/advanced_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,12 @@ Advanced Usage
:maxdepth: 2

advanced/writing_a_driver
advanced/nested_experiments
advanced/nested_experiments

Demo Notebooks
==============

.. toctree::
:maxdepth: 2

advanced/advanced_notebooks
2 changes: 1 addition & 1 deletion docs/source/api_index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ API
===

.. toctree::
:maxdepth: 3
:maxdepth: 4

api/general
api/measurement
Expand Down
4 changes: 3 additions & 1 deletion docs/source/basics/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ git clone https://github.com/sandialabs/pyscan
3. Install pyscan with

```
pip install .
pip install -e .
```

The `-e` makes the package editable, so that if you make modifications to your drivers, for example, you don't need to reinstall the package. This is the recommended method of installation since pyscan is largely intended to be modified when you add drivers for new instruments.

## Additional Requirements

Some instruments require extra installations in order to use them. For example, Ocean Optics (now known as Ocean Insight) spectrometers require the python package `seabreeze`. Thorlabs drivers may also require the installation of proprietary .dll files available on their website by installing Thorlabs Kinesis.
8 changes: 1 addition & 7 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
# "collapse_navigation": not is_release_build,
"show_prev_next": True,
"navbar_align": "left",
"show_toc_level": 2,
# social media links
"icon_links": [
{
Expand All @@ -91,7 +92,6 @@
"icon": "fab fa-github-square",
}
],
"primary_sidebar_end": [],
"use_edit_page_button": True,
}

Expand All @@ -103,9 +103,3 @@
"github_repo": "https://github.com/sandialabs/pyscan",
"github_version": "main",
}

html_sidebars = {
# default is
# "**": ["sidebar-nav-bs", "sidebar-ethical-ads"],
"**": ["sidebar-nav-bs"]
}
2 changes: 1 addition & 1 deletion pyscan/__init__.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tag this as a fix

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pyscan.general import *
from pyscan.measurement import *
from pyscan.drivers import *
from pyscan.general import *
from pyscan.plotting import *
from pyscan.drivers.testing import *
4 changes: 2 additions & 2 deletions pyscan/general/get_pyscan_version.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs to be moved to new branch.

Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@


# function that gets the overarching version of pyscan from VERSION.json
def get_pyscan_version(path="../../VERSION.json"):
def get_pyscan_version(path="VERSION.json"):
base_dir = os.path.dirname(os.path.abspath(__file__))
path = os.path.join(base_dir, path)
path = os.path.join(base_dir, os.pardir, os.pardir, path)
with open(path) as version_file:
version = json.load(version_file)['version']
if type(version) is str:
Expand Down
1 change: 0 additions & 1 deletion pyscan/measurement/experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class Experiment(AbstractExperiment):
The path to save the data, defaults to './backup'
verbose: bool, optional
Indicates whether to print status updates, defaults to `False`

'''

def __init__(self, runinfo, devices, data_dir=None, verbose=False, time=False):
Expand Down
5 changes: 4 additions & 1 deletion pyscan/measurement/run_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ def __init__(self):
self.average_d = -1

self.verbose = False
self._pyscan_version = get_pyscan_version()
try:
self._pyscan_version = get_pyscan_version()
except:
pass

def check(self):
'''Checks to see if runinfo is properly formatted. Called by Experiment object's `run()` methods.
Expand Down
1 change: 1 addition & 0 deletions pyscan/plotting/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Methods
from .basic_plots import *
from .oscilloscope import oscilloscope
from .live_plot import multi_live_plot

# Objects
from .jupyter_tools import JupyterTools
109 changes: 108 additions & 1 deletion pyscan/plotting/live_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ def live_plot(plotting_function, dt=1):
'''

def live_plot_function(expt=None, *arg, **kwarg):

while (expt.runinfo.running is True and len(expt.runinfo.measured) < 1):
sleep(1)

Expand All @@ -49,3 +48,111 @@ def live_plot_function(expt=None, *arg, **kwarg):
display.clear_output(wait=True)

return live_plot_function


def multi_live_plot(plotting_functions, subplot_locators=None, projections=None, nrows=1, ncols=1,
subplot_kw={}, dt=1):
'''
Generates a function that executes all plotting_function provided while data
is still being taken in Jupyter notebooks. Used by the live plotting
functions such as :func:`~pyscan.plotting.basicplots.live_plot2D`.

Parameters
----------
plotting_functions : list
list of plotting functions to be refreshed. Each function must take exactly
two parameters: expt and ax. The function should take data from expt and plot
to a matplotlib axis object.
subplot_locators : list, optional
list of subplot locators in accordance with matplotlib subplot formatted as
A 3-digit integer or a tuple with three numbers (nrows, ncols, index).
If omitted, then plotting functions will occupy the axes object according to
their index position.
projections: list, optional
list of projections such as None, '3d', 'polar', according to each plotting function.
If ommitted, all plots default to 2d.
nrows : int, optional
How many rows to add to the multiplot. Only used if subplot_locators are not provided.
ncols : int, optional
How many cols to add to the multiplot. Only used if subplot_locators are not provided.
subplot_kw : dict
Dict with keywords passed to matplotlib's `add_subplot` call used to create each subplot.
dt : float
Time in s between refreshes

Returns
-------
func : function
Its mandatory parameter is list of experiments in the same order as the plotting_functions as
defined in the multi_live_plot function. Keyword arguments can be provided and accessed by the
plotting_functions as well to further customize plots.

'''

# check if subplot_locators was specified
if not subplot_locators:
# check if n_cols and n_rows accomodates all of the plotting_functions
total_axes = nrows * ncols
if len(plotting_functions) > total_axes:
raise ValueError(f"not enough plots based on {nrows} nrows and {ncols} ncols to accomodate "
+ f"{len(plotting_functions)} plotting_functions.")
else:
# check plotting functions is same length as subplot locators
if not len(plotting_functions) == len(subplot_locators):
raise ValueError("subplot_locators must be the same length as plotting_functions")

# check if projections was specified
if projections:
# check plotting functions is same length as proejctions
if not len(plotting_functions) == len(projections):
raise ValueError("projections must be the same length as plotting_functions")

def live_plot_function(expt, *arg, **kwarg):
while (expt.runinfo.running is True and len(expt.runinfo.measured) < 1):
sleep(1)

fig = plt.figure(layout="constrained")
plt.ion()

def plot():
if subplot_locators:
for i, func in enumerate(plotting_functions):
subplot_locator = subplot_locators[i]
if projections:
projection = projections[i]
else:
projection = None
# check if subplot locator is int or tuple
if isinstance(subplot_locator, int):
ax = fig.add_subplot(subplot_locator, projection=projection, **subplot_kw)
elif isinstance(subplot_locator, tuple):
ax = fig.add_subplot(*subplot_locator, projection=projection, **subplot_kw)
func(expt, ax, *arg, **kwarg)
else:
for i, func in enumerate(plotting_functions):
if projections:
projection = projections[i]
else:
projection = None
ax = fig.add_subplot(nrows, ncols, i + 1, projection=projection, **subplot_kw)
func(expt, ax, *arg, **kwarg)
plt.tight_layout()

while expt.runinfo.running:
sleep(dt)

plt.clf()

plot()

display.display(plt.gcf())
display.clear_output(wait=True)

plt.clf()

plot()

display.display(plt.gcf())
display.clear_output(wait=True)

return live_plot_function
12 changes: 10 additions & 2 deletions pyscan/plotting/plot_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,16 @@ def get_data(self):
if (self.d == 2) and (self.data.ndim > 2):
if self.index3D is None:
self.index3D = 0
self.data_name = self.data_name + '[{}/{}]'.format(self.index3D, self.data.shape[2])
self.data = self.data[:, :, self.index3D]
# take the latest level if there are three scans and point data
if self.expt.runinfo.ndim == 3:
# get latest row that is being filled (i.e. first data point is not 0)
for i in range(self.data.shape[2]):
if self.data[0, 0, i]:
self.index3D = i
else:
self.index3D = 0
self.data_name = self.data_name + '[{}/{}]'.format(self.index3D + 1, self.data.shape[2])
self.data = self.data.T[self.index3D].T

def get_title(self):
'''
Expand Down
Loading