Skip to content

Commit

Permalink
Merge branch 'release' of https://github.com/psychopy/psychopy into r…
Browse files Browse the repository at this point in the history
…elease
  • Loading branch information
peircej committed May 10, 2023
2 parents f39b744 + a58772f commit d0ac4ea
Show file tree
Hide file tree
Showing 12 changed files with 120 additions and 25 deletions.
2 changes: 1 addition & 1 deletion docs/source/about/testimonials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Testimonials - what do people think of |PsychoPy|?
=====================================================

OK, so we know that `PsychoPy has quite a lot of users <https://www.psychopy.org/usage.php>`_
OK, so we know that `PsychoPy has quite a lot of users <https://usage.psychopy.org>`_

We also know that quite a few people have written `manuscripts that cited |PsychoPy|
<http://scholar.google.co.uk/scholar?cites=18194791051729814045&as_sdt=2005&sciodt=0,5&hl=en>`_
Expand Down
1 change: 0 additions & 1 deletion docs/source/api/visual/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ Shapes (all special classes of :class:`ShapeStim`):

Images and patterns:

* :class:`.ImageStim` to show images
* :class:`.SimpleImageStim` to show images without bells and whistles
* :class:`.GratingStim` to show gratings
* :class:`.RadialStim` to show annulus, a rotating wedge, a checkerboard etc
Expand Down
2 changes: 1 addition & 1 deletion docs/source/resources/vss-workshop.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
VSS 2012 Satellite Event, May 2012
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

PsychoPy is a modern, powerful easy-to-use software package for conducting psychophysics and imaging studies. It's become the package of choice in thousands of labs worldwide (see https://www.psychopy.org/usage.php).
PsychoPy is a modern, powerful easy-to-use software package for conducting psychophysics and imaging studies. It's become the package of choice in thousands of labs worldwide (see https://usage.psychopy.org ).

Using the Python programming language (a more powerful and free alternative to Matlab) PsychoPy can generate your stimuli in real-time and collect responses with high temporal precision.

Expand Down
84 changes: 83 additions & 1 deletion psychopy/CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,92 @@ to run on the same PsychoPy version even where a different version is installed
That setting often even allows PsychoPy to run experiments from versions that have not yet
been installed! If the dependencies haven't changed it will run.


PsychoPy 2023.1
---------------

# Release series 2023.1. Highlights

- **Pavlovia Surveys:** can now be integrated into PsychoPy online studies. You still create your
survey in the Pavlovia Survey Creator (on you Pavlovia Dashboard) but you can then incorporate
them as either a link or an embedded json file into your PsychoJS study. This only works for
online studies at present
- **Panorama Stimuli:** now supported in PsychoPy (lab-based) studies. You can add a photo-sphere
as a stimulus (e.g. create them in Street View app on Android phones) and then insert them into
Builder and explore
- **Plugins and Packages:** You can now add packages to your PsychoPy installation with a GUI that
installs new packages to your user folder (without needing admin rights). Some of PsychoPy's
existing functionality has also moved out to "Plugins"

- For users, plugins mean more control over what functionality you want PsychoPy to support
- For developers, plugins mean keeping more independence over your code and ownership

- **Speech Point:** on TextBox allows a tail to be added giving the impression of a cartoon speech
bubble (lab-based only, currently)
- **MovieStim:** further improvements to performance and fixes


On top of the [new features added in 2023.1 series](https://github.com/psychopy/psychopy/releases/tag/2023.1.0)

## Fixes

* Fix crash following gamma semi-auto correction (when laying out dialog box) dialog box by @TEParsons in #5452
* Crashing due to outdated `core.getFromNames` in Mouse by @TEParsons in #5474
* Setting Image as a numpy array caused a TypeError by @TEParsons in #5453
* Handle invalid paths when stringifying params by @TEParsons in #5465
* Swap all references to Panorama.altitude with Panorama.elevation by @TEParsons in #5471
* Fix typo in Survey routine - `stauts` rather than `status` by @TEParsons in #5468
* If user requests showing README and there isn't one then show a blank file @TEParsons in #5470
* Fix typos in high contrast theme by @TEParsons in #5504
* Sound files online were playing forever if duration set to <0.5s by @TEParsons in #5466
* Let Builder treat Sound.isPlaying and Sound.status==STARTED as synonymous by @TEParsons in #5428
* Correctly ignore blank columns by @wader in #5406
* Viewport was left as None when checkTiming was unticked by @TEParsons in #5451
* Better handling when a Pavlovia project / plugin avatars in the app @TEParsons in #5458 #5460 #5469

## Documentation fixes by

* @roelofsaj in #5477 #5483 #5484
* @ChenBri in #5478 #5480
* @ChristopheBossens in #5481
* @suelynnmah in #5444

## New Contributors

* @roelofsaj made their first contribution in #5477
* @ChenBri made their first contribution in #5478
* @ChristopheBossens made their first contribution in #5481
* @wader made their first contribution in #5406

**Full Changelog**: https://github.com/psychopy/psychopy/compare/2023.1.1...2023.1.2

PsychoPy 2023.1.1
~~~~~~~~~~~~~~~~~

Fixed:

- Better plugin handling:

- Better handling of plugin dependencies (moved to sub-folders) #5398
- More responsive plugins dialog (not waiting for all plugin info to populate) #5410
- Live info updates as the plugin installs #5399
- Sort package versions newest first #a4987c95f

- Panorama stimulus no longer needs FBO=False on Window
- MovieStim locally opacity was not being honored #094731084
- MovieStim online crashed if using setEveryRepeat #ed484ba17
- Close eyetracker connection if experiment ends early #f9b6f98e4
- README dialog was created twice #5383
- Online Experiments with image sitmuli crashing with unknown resource "default.png"
- Nested loops were crashing
- Fixed various failures to translate #804bfcde2 #b1b611ec1
- Console gave encoding errors when opening MacOS csv files on Windows machines #5396
- Failure to log in to Pavlovia #5382 #5450

PsychoPy 2022.3
---------------

*Highilghts:*
*Highlights:*
- Online: Interface in Pavlovia for building and running online questionnaires! As this is built on top of the
open-source [SurveyJS](https://surveyjs.io/) package it offers a rich feature list right off the bat. The new
Pavlovia Survey component you can insert a survey into your experiment just like you would a Form component.
Expand Down
2 changes: 1 addition & 1 deletion psychopy/app/Resources/tips.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Coder: You can comment/uncomment entire blocks of code with Ctrl-' and Ctrl-Shif
Did your stimulus not appear? Was it really tiny? Setting units='pix' and size=0.1 means it has a size of 0.1 pixels!
The default color values in PsychoPy range from -1 to +1, with 0 being the mean grey of the screen. So black is like the maximum decrement from grey and white is an increment. Right?
Data can be output in many different formats, but it's worth saving the 'psydat' (aka pickle) format as well as the others. Although this isn't "human readable" it stores more information than excel/csv files including an entire copy of your actual experiment!
You can see how many people used PsychoPy this month at https://www.psychopy.org/usage.php
You can see how many people used PsychoPy this month at https://usage.psychopy.org
Builder: You can increase or decrease the display size of the flow using "Ctrl + =" or "Ctrl + -" (like some web browsers). Similarly, you can change the display size of routines using "Ctrl + Shift + =" and "Ctrl + Shift + -". (Use "Cmd" on Mac, not "Ctrl".)
In the Builder, you can display details about the trials and sequences of loops. Press "Ctrl + =" when at the largest view size. To turn off, press "Ctrl + -" from the smallest view size.
Builder: To put a $ symbol in a stimulus, you need to use \$, like this: "You win \$5.00!". (This is only for input boxes, and not for code components.)
Expand Down
2 changes: 1 addition & 1 deletion psychopy/app/Resources/tips_ja_JP.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
 刺激が表示されなくて困っていませんか? 刺激の単位をpixに変更したのにサイズを0.1のままにしていると大きさがたったの0.1ピクセルになってしまいますよ!
 PsychoPyでは色のRGB値を-1.0から1.0で表します。RGB値がすべて0.0なら灰色、-1.0なら黒、1.0なら白です。
 データはさまざまな形式で出力できますが、psydat(pickle形式)ファイルはPythonユーザーにとってはとても便利です。直接エディタで開いて読むことは出来ませんが、実験条件ファイルを含む実験の全ての情報のコピーが保存されています。
 PsychoPyの月別利用者数を https://www.psychopy.org/usage.php で見ることが出来ます。
 PsychoPyの月別利用者数を https://usage.psychopy.org で見ることが出来ます。
 Builderでは Ctrl + = または Ctrl + -でFlowのアイコンの大きさを変更できます。同様に、Ctrl + Shift + =とCtrl + Shift + -でRoutineのアイコンの大きさを変更できます。(Macの人はCtrlの代わりにCmdキーを使いましょう)
 Builderでフローの表示サイズが最大の時にCtrl + =を押すとループやルーチンの詳細が表示されます。表示サイズが最小の時にCtrl + -を押すと表示されなくなります。
 Builderで"You win \$5.00!"のように$記号を含む文字列を表示したい場合は、$の前に\を付けて\$と書くに必要があります。ただしCodeコンポーネントでは必要ありません。
Expand Down
6 changes: 3 additions & 3 deletions psychopy/app/_psychopyApp.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ def onInit(self, showSplash=True, testMode=False, safeMode=False):
for exp in [file for file in args if file.endswith('.psyexp') or file.endswith('.py')]:
self.runner.panel.runFile(exp)

# send anonymous info to www.psychopy.org/usage.php
# send anonymous info to https://usage.psychopy.org
# please don't disable this, it's important for PsychoPy's development
self._latestAvailableVersion = None
self.updater = None
Expand Down Expand Up @@ -1006,10 +1006,10 @@ def quit(self, event=None):
for frame in self.getAllFrames():
try:
frame.closeFrame(event=event, checkSave=False)
# must do this before destroying the frame?
self.prefs.saveAppData()
except Exception:
pass # we don't care if this fails - we're quitting anyway
# must do this before destroying the frame?
self.prefs.saveAppData()
#self.Destroy()

# Reset streams back to default
Expand Down
2 changes: 1 addition & 1 deletion psychopy/app/connections/updates.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ def sendUsageStats():
systemInfo = "win32_v" + platform.version()
else:
systemInfo = platform.system() + platform.release()
u = "https://www.psychopy.org/usage.php?date=%s&sys=%s&version=%s&misc=%s"
u = "https://usage.psychopy.org/submit.php?date=%s&sys=%s&version=%s&misc=%s"
URL = u % (dateNow, systemInfo, v, miscInfo)
try:
req = urllib.request.Request(URL)
Expand Down
2 changes: 1 addition & 1 deletion psychopy/experiment/components/brush/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def writeInitCode(self, buff):
" lineColor={lineColor},\n"
" lineColorSpace={lineColorSpace},\n"
" opacity={opacity},\n"
" buttonRequired={buttonRequired}\n"
" buttonRequired={buttonRequired},\n"
" depth={depth}\n"
")"
).format(**inits)
Expand Down
30 changes: 19 additions & 11 deletions psychopy/experiment/components/keyboard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,15 +257,18 @@ def writeFrameCode(self, buff):
dedentAtEnd += 1
if store == 'first key': # then see if a key has already been pressed
code = ("{name}.keys = _{name}_allKeys[0].name # just the first key pressed\n"
"{name}.rt = _{name}_allKeys[0].rt\n")
"{name}.rt = _{name}_allKeys[0].rt\n"
"{name}.duration = _{name}_allKeys[0].duration\n")
buff.writeIndentedLines(code.format(name=self.params['name']))
elif store == 'last key' or store == "nothing": # If store nothing, save last key for correct answer test
code = ("{name}.keys = _{name}_allKeys[-1].name # just the last key pressed\n"
"{name}.rt = _{name}_allKeys[-1].rt\n")
"{name}.rt = _{name}_allKeys[-1].rt\n"
"{name}.duration = _{name}_allKeys[-1].duration\n")
buff.writeIndentedLines(code.format(name=self.params['name']))
elif store == 'all keys':
code = ("{name}.keys = [key.name for key in _{name}_allKeys] # storing all keys\n"
"{name}.rt = [key.rt for key in _{name}_allKeys]\n")
"{name}.rt = [key.rt for key in _{name}_allKeys]\n"
"{name}.duration = [key.duration for key in _{name}_allKeys]\n")
buff.writeIndentedLines(code.format(name=self.params['name']))

if storeCorr:
Expand Down Expand Up @@ -399,15 +402,18 @@ def writeFrameCodeJS(self, buff):
# how do we store it?
if store == 'first key': # then see if a key has already been pressed
code = ("{name}.keys = _{name}_allKeys[0].name; // just the first key pressed\n"
"{name}.rt = _{name}_allKeys[0].rt;\n")
"{name}.rt = _{name}_allKeys[0].rt;\n"
"{name}.duration = _{name}_allKeys[0].duration;\n")
buff.writeIndentedLines(code.format(name=self.params['name']))
elif store == 'last key' or store =='nothing':
code = ("{name}.keys = _{name}_allKeys[_{name}_allKeys.length - 1].name; // just the last key pressed\n"
"{name}.rt = _{name}_allKeys[_{name}_allKeys.length - 1].rt;\n")
"{name}.rt = _{name}_allKeys[_{name}_allKeys.length - 1].rt;\n"
"{name}.duration = _{name}_allKeys[_{name}_allKeys.length - 1].duration;\n")
buff.writeIndentedLines(code.format(name=self.params['name']))
elif store == 'all keys':
code = ("{name}.keys = _{name}_allKeys.map((key) => key.name); // storing all keys\n"
"{name}.rt = _{name}_allKeys.map((key) => key.rt);\n")
"{name}.rt = _{name}_allKeys.map((key) => key.rt);\n" \
"{name}.duration = _{name}_allKeys.map((key) => key.duration);\n")
buff.writeIndentedLines(code.format(name=self.params['name']))

if storeCorr:
Expand Down Expand Up @@ -482,10 +488,11 @@ def writeRoutineEndCode(self, buff):
(currLoop.params['name'], name, name))

# only add an RT if we had a response
code = ("if %(name)s.keys != None: # we had a response\n" %
self.params +
" %s.addData('%s.rt', %s.rt)\n" %
(currLoop.params['name'], name, name))
code = (
"if %(name)s.keys != None: # we had a response\n" % self.params +
" %s.addData('%s.rt', %s.rt)\n" % (currLoop.params['name'], name, name) +
" %s.addData('%s.duration', %s.duration)\n" % (currLoop.params['name'], name, name)
)
buff.writeIndentedLines(code)

# get parent to write code too (e.g. store onset/offset times)
Expand Down Expand Up @@ -549,7 +556,8 @@ def writeRoutineEndCodeJS(self, buff):

# only add an RT if we had a response
code = ("if (typeof {name}.keys !== 'undefined') {{ // we had a response\n"
" psychoJS.experiment.addData('{name}.rt', {name}.rt);\n")
" psychoJS.experiment.addData('{name}.rt', {name}.rt);\n"
" psychoJS.experiment.addData('{name}.duration', {name}.duration);\n")
if forceEnd:
code += (" routineTimer.reset();\n"
" }}\n\n")
Expand Down
9 changes: 7 additions & 2 deletions psychopy/experiment/components/polygon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,14 @@ def writeInitCodeJS(self, buff):
code = ("{name} = new visual.ShapeStim ({{\n"
" win: psychoJS.window, name: '{name}', {unitsStr}\n"
" vertices: 'arrow', size:{size},\n")
else:
elif self.params['shape'] == 'regular polygon...':
code = ("{name} = new visual.Polygon ({{\n"
" win: psychoJS.window, name: '{name}', {unitsStr}\n"
" edges: {nVertices}, size:{size},\n")
else:
code = ("{name} = visual.ShapeStim({{\n" +
" win: psychoJS.window, name: '{name}', {unitsStr}, \n"
" vertices={vertices}, size={size},\n")

depth = -self.getPosInRoutine()

Expand Down Expand Up @@ -303,5 +307,6 @@ def writeInitCodeJS(self, buff):
opacity=inits['opacity'],
depth=depth,
interpolate=interpolate,
nVertices=inits['nVertices']
nVertices=inits['nVertices'],
vertices=inits['vertices']
))
3 changes: 2 additions & 1 deletion psychopy/hardware/keyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ def waitKeys(self, maxWait=float('inf'), keyList=None, waitRelease=True,
return None

def clearEvents(self, eventType=None):
""""""
"""Clear the events from the Keyboard such as previous key presses"""
if Keyboard._backend == 'ptb':
for buffer in self._buffers.values():
buffer.flush() # flush the device events to the soft buffer
Expand All @@ -408,6 +408,7 @@ def clearEvents(self, eventType=None):
else:
global event
event.clearEvents(eventType)
logging.info("Keyboard events cleared", obj=self)


class KeyPress(object):
Expand Down

0 comments on commit d0ac4ea

Please sign in to comment.