Skip to content

Commit

Permalink
grammar and typo fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
IvoVellekoop committed Oct 4, 2024
1 parent 2f4a968 commit e77b00d
Show file tree
Hide file tree
Showing 30 changed files with 278 additions and 182 deletions.
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: "2"
version: 2

build:
os: "ubuntu-22.04"
Expand Down
227 changes: 171 additions & 56 deletions README.md

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions STYLEGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@

# General

- The package `black` is used to ensure correct formatting. Install with `pip install black` and run in the terminal
using `black .` when located at the root of the repository.
- The package `black` is used to ensure correct formatting.
When using PyCharm, just install black through the settings dialog.
- PyCharm warnings and errors should be fixed. Exceptions:
- PEP 8: E501 line too long. May be disabled. This is already checked by black. For docstrings, keeping a string
line limit can be very cumbersome.
- PEP 8:E203 whitespace before ':'. May be disabled. This is already checked by (and conflicts with) black.

# Tests

Expand Down
9 changes: 5 additions & 4 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
\author[1]{Tom~Knop}
\author[1,2]{Harish~Sasikumar}
\author[1]{Ivo~M.~Vellekoop}
\affil[1]{University of Twente, Biomedical Photonic Imaging, TechMed Institute, P. O. Box 217, 7500 AE Enschede, The Netherlands}
\affil[1]{University of Twente, Biomedical Photonic Imaging, TechMed Institute, P. O. Box 217,
7500 AE Enschede, The Netherlands}
\affil[2]{Imec (Netherlands), Holst Centre (HTC-31), 5656 AE, Eindhoven, The Netherlands}
\publishers{%
\normalfont\normalsize%
Expand Down Expand Up @@ -128,11 +129,11 @@
autodoc_mock_imports = ["PyOpenGL", "OpenGL"]


## Hide some classes that are not production ready yet
def skip(app, what, name, obj, skip, options):
# Hide some classes that are not production ready yet
def skip(app, what, name, obj, do_skip, options):
if name in ("WFSController", "Gain"):
return True
return skip
return do_skip


def visit_citation(self, node):
Expand Down
4 changes: 2 additions & 2 deletions docs/source/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Detectors in OpenWFS are objects that capture, generate, or process data. All de
def coordinates(dimension: int) -> Quantity
The :meth:`~.Detector.read()` method of a detector starts a measurement and returns the captured data. It triggers the detector and blocks until the data is available. Data is always returned as `numpy` array :cite:`numpy`. Subclasses of :class:`~.Detector` typically add properties specific to that detector (e.g. shutter time, gain, etc.). In the simplest case, setting these properties and calling :meth:`.~Detector.read()` is all that is needed to capture data. The :meth:`~.Detector.trigger()` method is used for asynchronous measurements as described below. All other properties and methods are used for metadata and units, as described in :numref:`Units and metadata`.
The :meth:`~.Detector.read()` method of a detector starts a measurement and returns the captured data. It triggers the detector and blocks until the data is available. Data is always returned as `numpy` array :cite:`numpy`. Subclasses of :class:`~.Detector` typically add properties specific to that detector (e.g. shutter time, gain, etc.). In the simplest case, setting these properties and calling :meth:`.~Detector.read()` is all that is needed to capture data. The :meth:`~.Detector.trigger()` method is used for asynchronous measurements as described below. All other properties and methods are used for metadata and units, as described in :numref:`Units and metadata`.
The detector object inherits some properties and methods from the base class :class:`~.Device`. These are used by the synchronization mechanism to determine when it is safe to start a measurement, as described in :numref:`device-synchronization`.
Expand Down Expand Up @@ -88,7 +88,7 @@ OpenWFS consistently uses `astropy.units` :cite:`astropy` for quantities with ph
c.shutter_time = 0.01 * u.s # equivalent to the previous line
c.shutter_time = 10 # raises an error, since the unit is missing
In addition, OpenWFS allows attaching pixel-size metadata to data arrays using the functions :func:`~.set_pixel_size()`. Pixel sizes can represent a physical length (e.g. as in the size pixels on an image sensor), or other units such as time (e.g. as the sampling period in a time series). OpenWFS fully supports anisotropic pixels, where the pixel sizes in the x and y directions are different.
In addition, OpenWFS allows attaching pixel-size metadata to data arrays using the functions :func:`~.set_pixel_size()`. Pixel sizes can represent a physical length (e.g. as in the size pixels on an image sensor), or other units such as time (e.g. as the sampling period in a time series). OpenWFS fully supports anisotropic pixels, where the pixel sizes in the x and y directions are different.

The data arrays returned by the :meth:`~.Detector.read()` function of a detector have `pixel_size` metadata attached whenever appropriate. The pixel size can be retrieved from the array using :func:`~.get_pixel_size()`, or obtained from the :attr:`~.Detector.pixel_size` attribute directly. As an alternative to accessing the pixel size directly, :func:`~get_extent()` and :class:`~.Detector.extent` provide access to the extent of the array, which is always equal to the pixel size times the shape of the array. Finally, the convenience function :meth:`~.Detector.coordinates` returns a vector of coordinates with appropriate units along a specified dimension of the array.

Expand Down
4 changes: 2 additions & 2 deletions docs/source/development.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ If the detector is created with the flag ``multi_threaded = True``, then `_fetch

Implementing a processor
++++++++++++++++++++++++++++++++++
To implement a data processing step that dynamically processes date from one or more input detectors, implement a custom processor. This is done by deriving from the `Processor` base class and implementing the `__init__` function. This function should pass a list of all upstream nodes, i.e. all detectors which provide the input signals to the processor, the base class constructor. In addition, the :meth"`~Detector._fetch()` method should be implemented to process the data. The framework will wait until the data from all sources is available, and calls `_fetch()` with this data as input. See the implementation of :class:`~.Shutter` or any other processor for an example of how to implement this function.
To implement a data processing step that dynamically processes date from one or more input detectors, implement a custom processor. This is done by deriving from the `Processor` base class and implementing the `__init__` function. This function should pass a list of all upstream nodes, i.e. all detectors which provide the input signals to the processor, the base class constructor. In addition, the :meth"`~Detector._fetch()` method should be implemented to process the data. The framework will wait until the data from all sources is available, and calls `_fetch()` with this data as input. See the implementation of :class:`~.Shutter` or any other processor for an example of how to implement this function.

Implementing an actuator
+++++++++++++++++++++++++++++++
To implement an actuator, the user should subclass the `Actuator` base class, and implement whatever properties and logic appropriate to the device. All methods that start the actuator (e.g. `update()` or `move()`), should first call `self._start()` to request a state switch to the `moving` state. As for detectors, actuators should either specify a static `duration` and `latency` if known, or override these properties to return run-time values for the duration and latency. Similarly, if the duration of an action of the actuator is not known in advance, the class should override `busy` to poll for the action to complete.
To implement an actuator, the user should subclass the `Actuator` base class, and implement whatever properties and logic appropriate to the device. All methods that start the actuator (e.g. `update()` or `move()`), should first call `self._start()` to request a state switch to the `moving` state. As for detectors, actuators should either specify a static `duration` and `latency` if known, or override these properties to return run-time values for the duration and latency. Similarly, if the duration of an action of the actuator is not known in advance, the class should override `busy` to poll for the action to complete.



Expand Down
4 changes: 2 additions & 2 deletions docs/source/readme.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ OpenWFS is a Python package for performing and for simulating wavefront shaping
* **Spatial light modulator**. The :class:`~.slm.SLM` object provides a versatile way to control spatial light modulators, allowing for software lookup tables, synchronization, texture warping, and multi-texture functionality accelerated by OpenGL.
* **Scanning microscope**. The :class:`~.devices.ScanningMicroscope` object uses a National Instruments data acquisition card to control a laser-scanning microscope.
* **GenICam cameras**. The :class:`~.devices.Camera` object uses the `harvesters` backend :cite:`harvesters` to access any camera supporting the GenICam standard :cite:`genicam`.
* **Automatic synchronization**. OpenWFS provides tools for automatic synchronization of actuators (e.g. an SLM) and detectors (e.g. a camera). The automatic synchronization makes it trivial to perform pipelined measurements that avoid the delay normally caused by the latency of the video card and SLM.
* **Automatic synchronization**. OpenWFS provides tools for automatic synchronization of actuators (e.g. an SLM) and detectors (e.g. a camera). The automatic synchronization makes it trivial to perform pipelined measurements that avoid the delay normally caused by the latency of the video card and SLM.

* **Wavefront shaping algorithms**. A (growing) collection of wavefront shaping algorithms. OpenWFS abstracts the hardware control, synchronization, and signal processing so that the user can focus on the algorithm itself. As a result, most algorithms can be implemented cleanly without hardware-specific programming.

Expand Down Expand Up @@ -78,7 +78,7 @@ If these fidelities are much lower than 1, this indicates a problem in the exper

Further troubleshooting can be performed with the :func:`~.troubleshoot` function, which estimates the following fidelities:

* :attr:`~.WFSTroubleshootResult.fidelity_non_modulated`: The fidelity reduction due to non-modulated light., e.g. due to reflection from the front surface of the SLM.
* :attr:`~.WFSTroubleshootResult.fidelity_non_modulated`: The fidelity reduction due to non-modulated light., e.g. due to reflection from the front surface of the SLM.
* :attr:`~.WFSTroubleshootResult.fidelity_decorrelation`: The fidelity reduction due to decorrelation of the field during the measurement.

All fidelity estimations are combined to make an order of magnitude estimation of the expected enhancement. :func:`~.troubleshoot` returns a ``WFSTroubleshootResult`` object containing the outcome of the different tests and analyses, which can be printed to the console as a comprehensive troubleshooting report with the method :meth:`~.WFSTroubleshootResult.report()`. See ``examples/troubleshooter_demo.py`` for an example of how to use the automatic troubleshooter.
Expand Down
2 changes: 1 addition & 1 deletion docs/source/slms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The :meth:`~.PhaseSLM.set_phases()` method takes a scalar or a 2-D array of phas

Currently, there are two implementations of the `PhaseSLM` interface. The :class:`simulation.SLM` is used for simulating experiments and for testing algorithms (see :numref:`section-simulations`). The :class:`hardware.SLM` is an OpenGL-accelerated controller for using a phase-only SLM that is connected to the video output of a computer. The SLM can be created in windowed mode (useful for debugging), or full screen. It is possible to have multiple windowed SLMs on the same monitor, but only one full-screen SLM per monitor. In addition, the SLM implements some advanced features that are discussed below.

At the time of writing, SLMs that are controlled through other interfaces than the video output are not supported. However, the interface of the `PhaseSLM` class is designed to accommodate these devices in the future. Through this interface, support for intensity-only light modulators (e. g. Digital Mirror Devices) operating in phase-modulation mode (e. g. :cite:`conkey2012high`) may also be added.
At the time of writing, SLMs that are controlled through other interfaces than the video output are not supported. However, the interface of the `PhaseSLM` class is designed to accommodate these devices in the future. Through this interface, support for intensity-only light modulators (e.g. Digital Mirror Devices) operating in phase-modulation mode (e.g. :cite:`conkey2012high`) may also be added.

Texture mapping and blending
-----------------------------------
Expand Down
2 changes: 1 addition & 1 deletion examples/slm_demo.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
SLM Demo
========
Example on how different geometries and patches work for an SLM. Currently uses SLM number 0, which is the left
Example on how different geometries and patches work for an SLM. Currently, uses SLM number 0, which is the left
upper corner of the primary monitor.
EPILEPSY WARNING: YOUR PRIMARY SCREEN MAY QUICKLY FLASH DURING RUNNING THIS FILE
Expand Down
13 changes: 7 additions & 6 deletions openwfs/algorithms/basic_fourier.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ class FourierDualReference(DualReference):
Improvements over [1]:
- The set of plane waves is taken from a disk in k-space instead of a square.
- No overlap between the two halves is needed, instead the final stitching step is done using measurements already in the data set.
- When only a single target is optimized, the algorithm can be used in an iterative version to increase SNR during the measurument,
similar to [2].
- No overlap between the two halves is needed, instead the final stitching step is done
using measurements already in the data set.
- When only a single target is optimized, the algorithm can be used in an iterative version
to increase SNR during the measurement, similar to [2].
[1]: Bahareh Mastiani, Gerwin Osnabrugge, and Ivo M. Vellekoop,
[1]: Bahareh Mastiani, Gerwin Osnabrugge, and Ivo M. Vellekoop,
"Wavefront shaping for forward scattering," Opt. Express 30, 37436-37445 (2022)
[2]: X. Tao, T. Lam, B. Zhu, et al., “Three-dimensional focusing through scattering media using conjugate adaptive
Expand Down Expand Up @@ -89,8 +90,8 @@ def _update_modes(self):
modes = np.zeros((*self._slm_shape, len(k)), dtype=np.float32)
for i, k_i in enumerate(k):
# tilt generates a pattern from -2.0 to 2.0 (The convention for Zernike modes normalized to an RMS of 1).
# The natural step to take is the Abbe diffraction limit of the modulated part, which corresponds to a gradient
# from -π to π over the modulated part.
# The natural step to take is the Abbe diffraction limit of the modulated part,
# which corresponds to a gradient from -π to π over the modulated part.
modes[..., i] = tilt(self._slm_shape, g=k_i * 0.5 * np.pi)

self.phase_patterns = (modes, modes)
Expand Down
Loading

0 comments on commit e77b00d

Please sign in to comment.