Skip to content

Commit

Permalink
Merge branch 'TEParsons:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
TEParsons authored Apr 19, 2024
2 parents 4ac50c2 + 0111622 commit 0d8f625
Show file tree
Hide file tree
Showing 14 changed files with 369 additions and 7 deletions.
157 changes: 157 additions & 0 deletions docs_src/builder/components/PatchComponent.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
-------------------------------
PatchComponent
-------------------------------
An event class for presenting image-based stimuli

Categories:
Stimuli
Works in:
PsychoPy

Parameters
-------------------------------

Basic
===============================

Name
Name of this Component (alphanumeric or _, no spaces)

Start type
How do you want to define your start point?

Options:
- time (s)
- frame N
- condition

Stop type
How do you want to define your end point?

Options:
- duration (s)
- duration (frames)
- time (s)
- frame N
- condition

Start
When does the Component start?

Stop
When does the Component end? (blank is endless)

Expected start (s)
(Optional) expected start (s), purely for representing in the timeline

Expected duration (s)
(Optional) expected duration (s), purely for representing in the timeline

Image/tex
The image to be displayed - 'sin','sqr'... or a filename (including path)

Data
===============================

Save onset/offset times
Store the onset/offset times in the data file (as well as in the log file).

Sync timing with screen refresh
Synchronize times with screen refresh (good for visual stimuli and responses based on them)

Testing
===============================

Disable Component
Disable this Component

Validate with...
Name of validator Component/Routine to use to check the timing of this stimulus.

Options are generated live, so will vary according to your setup.

Layout
===============================

Spatial units
Units of dimensions for this stimulus

Options:
- from exp settings
- deg
- cm
- pix
- norm
- height
- degFlatPos
- degFlat

Position [x,y]
Position of this stimulus (e.g. [1,2] )

Size [w,h]
Size of this stimulus (either a single value or x,y pair, e.g. 2.5, [1,2]

Orientation
Orientation of this stimulus (in deg)

Options:
- -360
- 360

Appearance
===============================

Foreground color
Foreground color of this stimulus (e.g. $[1,1,0], red )

Color space
In what format (color space) have you specified the colors? (rgb, dkl, lms, hsv)

Options:
- rgb
- dkl
- lms
- hsv

Fill color
Fill color of this stimulus (e.g. $[1,1,0], red )

Border color
Border color of this stimulus (e.g. $[1,1,0], red )

Opacity
Opacity of the stimulus (1=opaque, 0=fully transparent, 0.5=translucent). Leave blank for each color to have its own opacity (recommended if any color is None).

Contrast
Contrast of the stimulus (1.0=unchanged contrast, 0.5=decrease contrast, 0.0=uniform/no contrast, -0.5=slightly inverted, -1.0=totally inverted)

Texture
===============================

Mask
An image to define the alpha mask (ie shape)- gauss, circle... or a filename (including path)

Spatial frequency
Spatial frequency of image repeats across the patch, e.g. 4 or [2,3]

Phase (in cycles)
Spatial positioning of the image on the patch (in range 0-1.0)

Texture resolution
Resolution of the texture for standard ones such as sin, sqr etc. For most cases a value of 256 pixels will suffice

Options:
- 32
- 64
- 128
- 256
- 512

Interpolate
How should the image be interpolated if/when rescaled

Options:
- linear
- nearest

2 changes: 1 addition & 1 deletion docs_src/coder/MovieStim3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ To import MovieStim3, you can either use::
from psychopy_legacy.visual.movie3 import MovieStim3

or, any time after `psychopy.plugins.activatePlugins` has been called::

from psychopy.visual import MovieStim3

.. autoclass:: psychopy_legacy.visual.movie3.MovieStim3
Expand Down
2 changes: 1 addition & 1 deletion docs_src/coder/PatchStim.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ PatchStim
===============================

To import PatchStim, you can either use::

from psychopy_legacy.visual.patch import PatchStim

or, any time after `psychopy.plugins.activatePlugins` has been called::
Expand Down
2 changes: 1 addition & 1 deletion docs_src/coder/RatingScale.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ To import RatingScale, you can either use::
from psychopy_legacy.visual.ratingscale import RatingScale

or, any time after `psychopy.plugins.activatePlugins` has been called::

from psychopy.visual import RatingScale

.. autoclass:: psychopy_legacy.visual.ratingscale.RatingScale
Expand Down
121 changes: 121 additions & 0 deletions psychopy_legacy/components/patch/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Part of the PsychoPy library
# Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2024 Open Science Tools Ltd.
# Distributed under the terms of the GNU General Public License (GPL).

from pathlib import Path
from psychopy.experiment.components import BaseVisualComponent, Param, getInitVals, _translate


class PatchComponent(BaseVisualComponent):
"""An event class for presenting image-based stimuli"""

categories = ['Stimuli']
targets = ['PsychoPy']
iconFile = Path(__file__).parent / 'patch.png'
tooltip = _translate('Patch: present images (bmp, jpg, tif...) or textures '
'like gratings')

def __init__(self, exp, parentName, name='patch', image='sin', mask='None',
sf='None', interpolate='linear',
units='from exp settings', color='$[1,1,1]', colorSpace='rgb',
pos=(0, 0), size=(0.5, 0.5), ori=0, phase=0.0, texRes='128',
startType='time (s)', startVal=0.0,
stopType='duration (s)', stopVal=1.0,
startEstim='', durationEstim=''):
super(PatchComponent, self).__init__(
exp, parentName, name=name, units=units,
color=color, colorSpace=colorSpace,
pos=pos, size=size, ori=ori,
startType=startType, startVal=startVal,
stopType=stopType, stopVal=stopVal,
startEstim=startEstim, durationEstim=durationEstim)

self.type = 'Patch'
self.url = "https://www.psychopy.org/builder/components/patch.html"
# params

msg = _translate("The image to be displayed - 'sin','sqr'... or a "
"filename (including path)")
self.params['image'] = Param(
image, valType='file', inputType="file", allowedTypes=[], categ='Basic',
updates='constant',
allowedUpdates=['constant', 'set every repeat', 'set every frame'],
hint=msg,
label=_translate("Image/tex"))

msg = _translate("An image to define the alpha mask (ie shape)- "
"gauss, circle... or a filename (including path)")
self.params['mask'] = Param(
mask, valType='str', inputType="single", allowedTypes=[], categ='Texture',
updates='constant',
allowedUpdates=['constant', 'set every repeat', 'set every frame'],
hint=msg,
label=_translate("Mask"))

msg = _translate("Spatial frequency of image repeats across the "
"patch, e.g. 4 or [2,3]")
self.params['sf'] = Param(
sf, valType='list', inputType="single", allowedTypes=[], categ='Texture',
updates='constant',
allowedUpdates=['constant', 'set every repeat', 'set every frame'],
hint=msg,
label=_translate("Spatial frequency"))

msg = _translate(
"Spatial positioning of the image on the patch (in range 0-1.0)")
self.params['phase'] = Param(
phase, valType='num', inputType="single", allowedTypes=[], categ='Texture',
updates='constant',
allowedUpdates=['constant', 'set every repeat', 'set every frame'],
hint=msg,
label=_translate("Phase (in cycles)"))

msg = _translate(
"Resolution of the texture for standard ones such as sin, sqr "
"etc. For most cases a value of 256 pixels will suffice")
self.params['texture resolution'] = Param(
texRes, valType='num', inputType="choice", categ='Texture',
allowedVals=['32', '64', '128', '256', '512'],
updates='constant', allowedUpdates=[],
hint=msg,
label=_translate("Texture resolution"))

msg = _translate(
"How should the image be interpolated if/when rescaled")
self.params['interpolate'] = Param(
interpolate, valType='str', inputType="choice", allowedVals=['linear', 'nearest'], categ='Texture',
updates='constant', allowedUpdates=[],
hint=msg,
label=_translate("Interpolate"))

def writeInitCode(self, buff):
# do we need units code?
if self.params['units'].val == 'from exp settings':
unitsStr = ""
else:
unitsStr = "units=%(units)s, " % self.params
# replaces variable params with defaults
inits = getInitVals(self.params)

code = ("%s = visual.PatchStim(\n" % inits['name'] +
" win=win, name='%s',%s\n" % (inits['name'], unitsStr))

code += (" tex=%(image)s, mask=%(mask)s,\n"
" ori=%(ori)s, pos=%(pos)s, size=%(size)s, sf=%(sf)s, phase=%(phase)s,\n"
" color=%(color)s, colorSpace=%(colorSpace)s, opacity=%(opacity)s,\n"
# no newline - start optional parameters
" texRes=%(texture resolution)s" %
inits)

buff.writeIndentedLines(code)

if self.params['interpolate'].val == 'linear':
buff.write(", interpolate=True")
else:
buff.write(", interpolate=False")

depth = -self.getPosInRoutine()
buff.write(", depth=%.1f)\n" % depth) # finish with newline
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 psychopy_legacy/components/patch/dark/patch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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 psychopy_legacy/components/patch/light/patch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ tests = [

[project.entry-points."psychopy.experiment.components"]
RatingScaleComponent = "psychopy_legacy.components.ratingScale:RatingScaleComponent"
PatchComponent = "psychopy_legacy.components.patch:PatchComponent"

[project.entry-points."psychopy.visual"]
MovieStim2 = "psychopy_legacy.visual.movie2:MovieStim2"
Expand Down
5 changes: 5 additions & 0 deletions tests/test_builder/test_PatchComponent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from psychopy_legacy.components.patch import PatchComponent
from psychopy.tests.test_experiment.test_components.test_base_components import BaseComponentTests

class TestRatingScaleComponent(BaseComponentTests):
comp = PatchComponent
4 changes: 0 additions & 4 deletions tests/test_builder/test_RatingScaleComponent.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
"""
Tests for the ExampleComponent class, essentially showcases how to implement basic tests on a Component.
"""

from psychopy_legacy.components.ratingScale import RatingScaleComponent
from psychopy.tests.test_experiment.test_components.test_base_components import BaseComponentTests

Expand Down
Loading

0 comments on commit 0d8f625

Please sign in to comment.