Scheduled service maintenance on November 22


On Friday, November 22, 2024, between 06:00 CET and 18:00 CET, GIN services will undergo planned maintenance. Extended service interruptions should be expected. We will try to keep downtimes to a minimum, but recommend that users avoid critical tasks, large data uploads, or DOI requests during this time.

We apologize for any inconvenience.

stim.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. # this file contains functions used in both the localiser task and main task
  2. import os
  3. from itertools import groupby
  4. import csv
  5. import codecs
  6. import numpy as np
  7. from random import randint
  8. from psychopy import visual
  9. import PIL
  10. # function to make noise images green
  11. def greenify_noise(im):
  12. im_arr = np.array(im, dtype=np.uint8)
  13. im_arr[:, :, [0, 2]] = 127
  14. targ = im_arr[:, :, 1] < 127
  15. im_arr[:, :, 0][targ] = im_arr[:, :, 1][targ]
  16. im_arr[:, :, 2][targ] = im_arr[:, :, 1][targ]
  17. im_gr = PIL.Image.fromarray(np.uint8(im_arr))
  18. return(im_gr)
  19. # function to append a trial's data (in dictionary format) to csv
  20. def write_csv(fileName, thisTrial):
  21. full_path = os.path.abspath(fileName)
  22. directory = os.path.dirname(full_path)
  23. if not os.path.exists(directory):
  24. os.makedirs(directory)
  25. if not os.path.isfile(full_path):
  26. with codecs.open(full_path, 'ab+', encoding='utf8') as f:
  27. csv.writer(f, delimiter=',').writerow(thisTrial.keys())
  28. csv.writer(f, delimiter=',').writerow(thisTrial.values())
  29. else:
  30. with codecs.open(full_path, 'ab+', encoding='utf8') as f:
  31. csv.writer(f, delimiter=',').writerow(thisTrial.values())
  32. # function to get the lengths of consecutive runs (useful for limiting number of consecutive trial types)
  33. def get_consec_lens(x):
  34. return [ len(list(v)) for k, v in groupby(list(x)) ]
  35. # functions for precise frame-wise timing
  36. def ms_2_flips(ms = 100, Hz = 60, round_func = np.round):
  37. return int(round_func(ms / (1/Hz*1000)))
  38. def display_n_flips(win, stim, n_flips = 10, port = None, trigg = None):
  39. for frame_n in range(n_flips):
  40. stim.draw()
  41. if frame_n == 0:
  42. if trigg is not None:
  43. win.callOnFlip(port.setData, data=trigg)
  44. win.flip()
  45. def display_x_ms(win, stim, ms = 100, Hz = 60, round_func = np.round, port = None, trigg = None):
  46. display_n_flips(win, stim, ms_2_flips(ms, Hz, round_func), port, trigg)
  47. def display_jitter_ms(win, stim, min_ms = 100, max_ms = 500, Hz = 60, round_func = np.round, port = None, trigg = None):
  48. flips_min = ms_2_flips(min_ms, Hz, round_func)
  49. flips_max = ms_2_flips(max_ms, Hz, round_func)
  50. n_flips = randint(flips_min, flips_max)
  51. display_n_flips(win, stim, n_flips, port, trigg)
  52. return(n_flips, n_flips*(1/Hz*1000))
  53. def display_list_n_flips(win, stim_list, n_flips = 10, port = None, trigg = None):
  54. for frame_n in range(n_flips):
  55. for stim_i in stim_list:
  56. stim_i.draw()
  57. if frame_n == 0:
  58. if trigg is not None:
  59. win.callOnFlip(port.setData, data=trigg)
  60. win.flip()
  61. def display_list_ms(win, stim_list, ms = 100, Hz = 60, round_func = np.round, port = None, trigg = None):
  62. display_list_n_flips(win, stim_list, ms_2_flips(ms, Hz, round_func), port, trigg)
  63. def display_list_jitter_ms(win, stim_list, min_ms = 100, max_ms = 500, Hz = 60, round_func = np.round, port = None, trigg = None):
  64. flips_min = ms_2_flips(min_ms, Hz, round_func)
  65. flips_max = ms_2_flips(max_ms, Hz, round_func)
  66. n_flips = randint(flips_min, flips_max)
  67. display_list_n_flips(win, stim_list, n_flips, port, trigg)
  68. return(n_flips, n_flips*(1/Hz*1000))
  69. # function that returns a list containing the objects in the Thaler et al. fixation point
  70. # can then draw the list contents in a loop
  71. def thaler_list_fix(win, units='deg', circlesColor=[1,1,1], circlesColorSpace='rgb', outerCircleDiameter=0.6, innerCircleDiameter=0.2, pos = (0, 0)):
  72. crossColor=win.color.tolist()
  73. crossColorSpace=win.colorSpace
  74. outerCircle = visual.Circle(win, units=units, pos=pos, radius=outerCircleDiameter/2, lineColor=circlesColor, fillColor=circlesColor, fillColorSpace=circlesColorSpace, lineColorSpace=circlesColorSpace)
  75. crossVertical = visual.Rect(win, units=units, pos=pos, height=outerCircleDiameter*1.1, width=innerCircleDiameter/2, lineColor=None, fillColor=crossColor, fillColorSpace=crossColorSpace, lineColorSpace=crossColorSpace)
  76. crossHorizontal = visual.Rect(win, units=units, pos=pos, height=innerCircleDiameter/2, width=outerCircleDiameter*1.1, lineColor=None, fillColor=crossColor, fillColorSpace=crossColorSpace, lineColorSpace=crossColorSpace)
  77. innerCircle = visual.Circle(win, units=units, pos=pos, radius=innerCircleDiameter/2, lineColor=circlesColor, fillColor=circlesColor, fillColorSpace=circlesColorSpace, lineColorSpace=circlesColorSpace)
  78. return [outerCircle, crossVertical, crossHorizontal, innerCircle]