Skip to content

Commit

Permalink
docs: updated documentation - mostly language
Browse files Browse the repository at this point in the history
  • Loading branch information
LynnSchmittwilken committed May 12, 2023
1 parent 108ac44 commit d8f4211
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 86 deletions.
32 changes: 16 additions & 16 deletions docs/getting_started/composition.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ kernelspec:
# Composing stimuli, composed stimuli

Most stimuli consist not just of one shape or element,
but as a composition of multiple components.
but they consists of a composition of multiple components.
The geometric {py:mod}`components <stimupy.components>`
form the basic building blocks for all stimuli implemented in `stimupy`.
In this tutorial, we will explore how stimulus consisting of multiple geometric elements,
In this tutorial, we will explore how a simple example stimulus consisting of multiple geometric elements,
can be composed using the functions that generate components.

```{code-cell}
Expand All @@ -27,7 +27,7 @@ from stimupy.utils import plot_stim, plot_stimuli
from stimupy.components import shapes
```

First we will create our two components that we want to combine in some way;
First, we will create the two components that we want to combine in our example;
here we will use the {py:func}`rectangle <stimupy.components.shapes.rectangle>`
and {py:func}`disc <stimupy.components.shapes.disc>`
(from our [previous tutorial](first_stim))
Expand All @@ -46,16 +46,16 @@ plt.show()
```

Since the `"img"`s of the two stimuli are {py:class}`numpy.ndarray`s,
we can simple manipulate these to combine our stimuli:
the simplest manipulation that we can perform to combine our components is to add or subtract them:
```{code-cell}
new_img = disc["img"] - rectangle["img"]
plt.imshow(new_img, cmap="gray")
```

We can even turn this into a something resembling more of a `stimupy` stimulus
-- and use the `stimupy` tooling
like {py:func}`plot_stimuli <stimupy.utils.plot_stimuli>` on it --
We can even turn this new stimulus-array into something that resembles a `stimupy` stimulus more
-- in order to use `stimupy` tooling
like {py:func}`plot_stimuli <stimupy.utils.plotting.plot_stimuli>` on it --
simply by wrapping it in a {py:class}`dict`,
and optionally adding some additional metadata:
```{code-cell}
Expand All @@ -70,19 +70,19 @@ plot_stimuli({"rect": rectangle, "disc": disc, "composed": new_stim})
## Masked regions

The downside of this, is that such an operation (`-`) on the `"img"`s
uses the *whole* `imgs`s, including the background.
uses the *whole* `"img"`s, including the background.
In other words, these operations aren't *content aware*;
they treat all pixels the same, rather than restricting operations
to the regions that we care about (e.g., the geometric shapes).
We'd like to be to have a bit more control,
for instance subtracting just a where the shapes overlap.
In many cases, however, we might want to have more control,
for instance only subtracting stimulus regions in which the two shapes overlap.

One key in the stimulus-{py:class}`dict`s not addressed yet, is the `mask`.
Just like `"img"`, this too is a {py:class}`numpy.ndarray`
where each entry corresponds to a pixel in `"img"`
For this, we would like to introduce one key feature of `stimupy`: stimulus `"mask"`s.
Just like the `"img"`, the stimulus `"mask"` is a {py:class}`numpy.ndarray` which can be found in the stimulus-{py:class}`dict`.
Each entry of the stimulus `"mask"` corresponds to a pixel in `"img"`
(i.e., it has the same shape as `"img"`).

However, rather the `"mask"` contains only integer-values
Importantly, the `"mask"` contains only integer-values
(compared to the floating point pixel-intensities in `"img"`).
Each integer-value in the mask,
corresponds to a geometric region of interest,
Expand Down Expand Up @@ -251,9 +251,9 @@ plt.show()

## Using masks to alter the simulus after creation

An advantage of having these kinds of `mask`s that index regions
One advantage of having these kinds of `"mask"`s that index regions
(rather than just binary masks)
is that we can the `mask` to selectively alter one region in an existing stimulus
is that we can use the `"mask"` to selectively alter one region in an existing stimulus
without having to recreate the whole image:

```{code-cell}
Expand Down
18 changes: 9 additions & 9 deletions docs/getting_started/first_stim.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ This page can also be launched as an interactive Jupyter Notebook on Binder -- s
## Drawing a basic shape

The most basic stimuli that `stimupy` provides, are basic geometric shapes.
These functions be found in the {py:mod}`stimupy.components.shapes` *module*.
These functions can be found in the {py:mod}`stimupy.components.shapes` *module*.
To be able to access these,
we first have to *import* this module
into our current Python session:
Expand All @@ -50,14 +50,14 @@ This module contains the following functions:
print(f"Available basic shapes: {shapes.__all__}")
```

Each of these is a separate function.
Let's take a look at one of these:
Each of these `str`ings represents a separate function.
Let's take a look at one of them:
```{code-cell}
stim = shapes.rectangle(visual_size=(6,8), ppd=10, rectangle_size=(4,4))
```

This function creates an image, and draws a rectangle inside it.
Everywhere the rectangle isn't, is considered the "background".
Every pixel which is not part of the rectangle, is considered the "background".
It returns a {py:class}`dict`ionary,
mapping `str`ings as *keys*, to all kinds of *values*.

Expand Down Expand Up @@ -90,7 +90,7 @@ The values of the entries in the `"img"` {py:class}`numpy.ndarray` represent the
by default in range $[0,1]$.

## Stimulus parameters
All `stimupy` stimulus-functions require and take a bunch of arguments.
All `stimupy` stimulus-functions require and take multiple arguments.
To see what arguments a given function takes,
and what each of these arguments controls,
you can look at the (online) [function reference](../reference/api.md)
Expand Down Expand Up @@ -198,11 +198,11 @@ The advantages of this are:
% TODO: import in PsychoPy (?)
2. anything that is compliant with this basic structure
can use (some of) `stimupy` tooling,
e.g., {py:func}`plot_stim <stimupy.utils.plotting.plot_stim>`
e.g., {py:func}`plot_stim <stimupy.utils.plotting.plot_stim>`, {py:mod}`exports <stimupy.utils.export>`, or {py:mod}`contrast manipulations <stimupy.utils.contrast_conversions>` to name a few
3. since Python {py:class}`dict`s are *mutable*, you as user can add, create, remove, rename
any of the keys and values.

The main disadvantages, is that there are no controls or guarantees
*after* a stimulus is created,
The main disadvantage is that there are no controls or guarantees
*after* a stimulus is created
for the accuracy of any of its fields,
since the user can change values.
since the user can manually change values at any point in time.
2 changes: 1 addition & 1 deletion docs/getting_started/replicate.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ and thus specific existing parameterizations can be recreated.

For a large selection of the generic {py:mod}`stimupy.stimuli`,
there are specific parameterizations in the published literature.
Some of these are implement in stimupy as well,
In order to make it easier for the community to access and work with these stimuli, we have re-implemented some existing stimulus sets in stimupy,
under the corresponding {py:mod}`stimupy.papers`.

```{code-cell}
Expand Down
14 changes: 6 additions & 8 deletions docs/getting_started/stimulus.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,21 @@ also have 3 overall categories of parameters:

However, some of the stimulus parameters
have different names in {py:mod}`stimuli <stimupy.stimuli>`.
In particular, **all** {py:mod}`stimuli <stimupy.stimuli>`
In particular, many {py:mod}`stimuli <stimupy.stimuli>`
have the concept of a `target` region(s):
image regions that are of some particular scientific interest in this stimulus.
For an SBC stimulus, this would be the rectangular path.
For an SBC stimulus, this would be the rectangle.
Thus, the {py:func}`sbcs.basic <stimupy.stimuli.sbcs.basic>` function takes a
- `target_size`, compared to `rectangle_size`
- `intensity_target`, rather than an `intensity_rectangle`
(with a default intermediate value of `0.5`)
In addition, the output stimulus contains a `target_mask`,
which masks the pixels of the target region.
- In addition, the output stimulus contains a `target_mask`, which masks the pixels of the target region.

For this specific stimulus,
the {py:func}`sbcs.basic <stimupy.stimuli.sbcs.basic>` provides little use over
the base component.
But, realistically, we would show not just this one part of an SBC display.
Instead, this would likely be only half
of a {py:func}`two-sided <stimupy.stimuli.sbsc.two_sized>` display:
But, realistically, we would not show just this one part of a SBC display, but rather
show both sides of the SBC displays as implemented in {py:func}`two_sided <stimupy.stimuli.sbcs.two_sided>`:
```{code-cell}
two_sided_stim = sbcs.two_sided(visual_size=(6,8), ppd=10,
target_size=(2,2))
Expand Down Expand Up @@ -179,7 +177,7 @@ OR as having a [cross-shaped target](todorovics.cross) with adjoining squares.
For a single stimulus parameterization,
these two conceptions may produce perfectly identical images ([see fig, top](fig_todorovics)).
However, when changing parameters,
you would expect different *behavior* from the stimulus fuction
you would expect different *behavior* from the stimulus function
dependent on your conception/interpretation of the stimulus ([see fig, bottom](fig_todorovics)).

```{code-cell}
Expand Down
16 changes: 8 additions & 8 deletions docs/howtos/display.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Display stimuli / integrate in experiments
`stimupy` is a package for stimulus generation,
`stimupy` is a package which is focused on generating stimuli,
separate from stimulus display, use, experimentation, etc.
Instead, `stimupy` is designed agnostic how stimuli are used,
and flexible for a range of uses.
Principally, the actual stimulus image is stored
Hence, `stimupy` is designed agnostic to how stimuli are used after stimulus generation,
which allows for a broad range of uses.
Principally, the stimulus image is stored
as a matrix of intensity values, in a bare {py:obj}`numpy.ndarray`.
Thus, to use a `stimupy` stimulus in an application
just requires being able to input a `numpy.ndarray`.
Thus, using a `stimupy` stimulus in an application
just requires the possibility to input a `numpy.ndarray`.


## PsychoPy-based display
[PsychoPy](https://psychopy.org/) is a leading stimulus display
and experiment development package for the python ecosystem.
and experiment development package for the Python ecosystem.
It provides lots of functionality for running experiments, interfacing with hardware
and some stimulus-drawing capabilities.
Most of the stimulus-drawing is done using an OpenGL backend
Expand Down Expand Up @@ -66,7 +66,7 @@ Screen('DrawTexture', my_window, stim_texture);
```

To use `stimupy` stimuli in PyschoPy experiments then
requires creating the stimuli in, and exporting them from, Python,
requires creating the stimuli in, and exporting them from Python,
and importing them into MATLAB for display:

1. Generate the `stim` using `stimupy` code (Python)
Expand Down
11 changes: 6 additions & 5 deletions docs/howtos/export.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ since JSON syntax is very similar to Python syntax for lists and dicts.
as the whole stimulus-dict ({py:func}`stimupy.utils.export.to_json`)

### MATLAB `.mat`
To use stimuli to a MATLAB environment,
e.g., to use them in a PsychToolBox-based experiment,
For using stimuli in a MATLAB environment,
e.g., in a PsychToolBox-based experiment,
or a computational model that is (only) implemented in MATLAB,
the stimuli have to be exported to a format that MATLAB can interpret.
MATLAB does provide (some) support for JSON files
Expand All @@ -49,12 +49,13 @@ either the whole stimulus-dict ({py:func}`stimupy.utils.export.to_mat`)
or just the bare image-array ({py:func}`stimupy.utils.export.array_to_mat`).

### Image formats
To save/export to other image formats (`.png`, `.jpeg`, etc.)
is not covered by `stimupy` itself.
Instead, one of several image-processing libraries for Python should be used,
For many uses, it can be convenient to just save the stimulus-array (or the mask) as an image.
Hence, `stimupy` provides a function to save/export bare image-arrays to common image formats (`.png`, `.jpeg`, etc).
Alternatively, there exist multiple image-processing libraries for Python which allow for further image processing and exporting,
e.g., [Pillow/PIL](https://pillow.readthedocs.io/en/stable/)
or [OpenCV](https://github.com/opencv/opencv-python)


## Exporting only parameters
In some cases, you may wish to save/export only the stimulus parameters
-- for a given version of `stimupy`,
Expand Down
10 changes: 4 additions & 6 deletions docs/howtos/share.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
# Share & distribute stimuli
A core principle of `stimupy` is sharing and reusing stimuli.
One part of this is the large number of existing stimuli already implement,
One part of this endeavor is the large number of stimuli that are already implemented,
such that you can generate various parameterizations of these
without having to write any custom code.
The other part is that, hopefully, you will share the `stimupy`-stimuli
that you use in your work.

Besides this, we are hoping that people who are using `stimupy` for their stimulus generation want to add and hence share their stimulus implementations with other `stimupy`-users.

## What to share?
To accurately reproduce a stimulus,
Expand Down Expand Up @@ -77,9 +75,9 @@ Thus, you'll need to:
and reproduce the exact stimulus from the provide parameter values.

- provide all parameter-values for this stimulus, ideally by [exporting them](export.md).
For just sharing paramter-values, we recommend sharing the stimulus-`dict`
For just sharing parameter-values, we recommend exporting the stimulus-`dict`
without the `img` and `masks` to a [JSON file](./export.md).
This because JSON files are both human-readable -- so that a non-stimupy / non-Python
The reason for this is because JSON files are both human-readable -- so that a non-stimupy / non-Python
recipient can still evaluate the parameter values -- and safely machine-readable
-- so that a Python / stimupy user can easily load and recreate the stimulus.

Expand Down
4 changes: 2 additions & 2 deletions docs/topic_guides/dimensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ plot_stim(stim)
```

## Distance metric
We term these axes a _`distance_metric`_,
We term these above described axes a _`distance_metric`_,
as they measure distance from some point of origin.
This way of thinking is especially import
This way of thinking is especially important
for wave specifications in {py:mod}`stimupy.components.waves`
and their use in wave-like stimuli in {py:mod}`stimupy.stimuli.waves`.
For the linear metrics (`horizontal`, `vertical`, `oblique`),
Expand Down
37 changes: 17 additions & 20 deletions docs/topic_guides/organization.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ kernelspec:
# How stimupy is organized

Broadly, `stimupy` functions currently fall into the following categories, which are also the toplevel submodules of `stimupy`:
- basic visual stimulus [components](../reference/_api/stimupy.components),
such as basic shapes, wave gratings, Gaussians
- visual stimulus [components](../reference/_api/stimupy.components),
such as shapes, wave / gratings, Gaussians, lines
- visual [noise](../reference/_api/stimupy.noises) textures, of different kinds,
- parameterized visual [stimuli](../reference/_api/stimupy.stimuli)
- Gabors, plaids, edges,
- Gabors, plaids, edges, Mondrians,
- a variety of so-called illusions
(e.g. Simultaneous Brightness Contrast, White's illusion, Hermann grid, Ponzo illusion), and many more
- exact replications of stimuli previously published (e.g. ModelFest)
Expand All @@ -35,23 +35,21 @@ from stimupy.stimuli import ponzos, shapes
will work easily.
:::
::::
In principle, every component can also be considered a stimulus:
it is some visual feature that can be drawn as an image.
There is no objective way to differentiate components from stimuli.
In principle, every component could be considered a stimulus.
The distinctions we make in `stimupy` are:
firstly, that the `components` underly (many) different stimuli,
and are "atomic" in a sense;
secondly, most/all `stimuli` have some concept of one or more *target*(s)
-- a region of special scientific interest.
Thus, most/all `stimuli` come with a `target_mask`
that indicate these targets.
firstly, that the `components` are "atomic" in a sense and hence underlie multiple different stimuli;
secondly, most `stimuli` contain *target*(s)
-- a region of special scientific interest --, and come with a `target_mask`
that indicates these targets.

## Submodules
Further subdividing the overall structure are lots of submodules.
The overall structure of `stimupy` is further subdivided into many submodules.
These submodules are organized along scientific interest,
history, convention, etc., rather than engineering.
Thus, a you should find a stimulus in a submodule
with those stimuli *that is looks like* or *is related to*,
rather than with those stimuli that it shares components or code with
Thus, you will find a stimulus in a submodule
with stimuli that either *look similar* or that are *related to each other*,
rather than with stimuli that it shares components or code with
(although these two criteria can overlap, of course).

Moreover, the submodules all have pluralized names,
Expand All @@ -67,11 +65,10 @@ there may be multiple functions, see next section.

All roads lead to Rome,
and many ways lead to the same stimulus.
For lots of the stimuli provided by `stimupy`,
there are numerous different ways one can draw it.
Often, these different ways of drawing
are informed by the visual and geometric interpretation
of who is doing the drawing.
For some stimuli provided by `stimupy`,
there are multiple ways to generate a specific stimulus.
Typically, these different ways are
informed by visual and geometric interpretations.

A good example of this is the Todorovic Illusion, which one can interpret as
having a [rectangular target](todorovics.rectangle) that is partially occluded by some "covers"
Expand Down
20 changes: 9 additions & 11 deletions docs/topic_guides/waves.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ from stimupy.utils import plot_stimuli
## Interdependence of parameters
Periodic stimuli (e.g., `waves`)
consist of repetitions of some _elements_ or _phases_.
Periodic stimuli (e.g., `waves`)
consist of repetitions of some _elements_ or _phases_.
In a sinewave grating, these are the light and dark phases.
in a squarewave grating, those same phases visually appears as white and black `bars`:
```{code-cell}
Expand Down Expand Up @@ -127,15 +125,15 @@ plot_stimuli({'Sine': sinewave, 'Square': squarewave})
```

## Even, odd or integer number of elements
For some gratings, you want an integer number of phases,
i.e., only "full" bars
-- often this is how think of squarewaves
For other stimuli, you may be fine with an "incomplete" phase at the end.
In some cases, you may be even more specific, and want an _even_ number of phases,
(i.e. a full number of _periods_),
Particularly for gratings, the requirements on the number of elements can be very different depending on the use-case.
In some cases, you may want to ensure that your grating has an integer number of phases,
e.g., if you want to avoid partial bars in a squarewave grating.
For other stimuli, you may be fine with an "incomplete" phase at the end, e.g. if your sinewave grating consists of 7.1 cycles.
In yet other situations, you may want to be even more specific and may want to make sure that you have an _even_ number of phases in your grating,
(i.e. a full number of _periods_, as many bright as dark bars),
or an _odd_ number of phases.
The `period` argument controls this behavior
when `stimupy` resolves the periodity for you.
when `stimupy` resolves the periodicity for you.
it can be `"even"`, `"odd"`, `"either"` (ensures only complete phases), or `"ignore"`:
```{code-cell}
sinewave = waves.sine_linear(visual_size=(10, 10), ppd=10, n_bars=5)
Expand All @@ -162,9 +160,9 @@ for a given sampling rate ($\sim$ ppd)
```
````

`stimupy` tries to handle this gracefully in cases where the given parameter values
If desired (i.e. if _`round_phase_width=True`_, `stimupy` supports the user in cases where the given parameter values
result in a poor periodicity $\times$ resolution combination.
Specifically, it will adjust/round the _periodicty_ parameters to try and accomplish
Specifically, it will adjust/round the _periodicity_ parameters to try and accomplish
the closest possible version of the stimulus, and warn you about this change.
Which way it rounds to, can be determined by the `period` argument:
```{code-cell}
Expand Down

0 comments on commit d8f4211

Please sign in to comment.