Skip to content

Commit

Permalink
added vr support for p300 and ssvep
Browse files Browse the repository at this point in the history
  • Loading branch information
pellet committed Nov 2, 2023
1 parent ef1e9b7 commit 67d6278
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 16 deletions.
4 changes: 2 additions & 2 deletions eegnb/experiments/visual_p300/p300.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
class VisualP300(Experiment.BaseExperiment):

def __init__(self, duration=120, eeg: Optional[EEG]=None, save_fn=None,
n_trials = 2010, iti = 0.4, soa = 0.3, jitter = 0.2):
n_trials = 2010, iti = 0.4, soa = 0.3, jitter = 0.2, use_vr = False):

exp_name = "Visual P300"
super().__init__(exp_name, duration, eeg, save_fn, n_trials, iti, soa, jitter)
super().__init__(exp_name, duration, eeg, save_fn, n_trials, iti, soa, jitter, use_vr)

def load_stimulus(self):

Expand Down
41 changes: 27 additions & 14 deletions eegnb/experiments/visual_ssvep/ssvep.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,20 @@

class VisualSSVEP(Experiment.BaseExperiment):

def __init__(self, duration=120, eeg: Optional[EEG]=None, save_fn=None, n_trials = 2010, iti = 0.5, soa = 3.0, jitter = 0.2):
def __init__(self, duration=120, eeg: Optional[EEG]=None, save_fn=None, n_trials = 2010, iti = 0.5, soa = 3.0, jitter = 0.2, use_vr=False):

self.use_vr = use_vr
exp_name = "Visual SSVEP"
super().__init__(exp_name, duration, eeg, save_fn, n_trials, iti, soa, jitter)
super().__init__(exp_name, duration, eeg, save_fn, n_trials, iti, soa, jitter, use_vr)

def load_stimulus(self):

self.grating = visual.GratingStim(win=self.window, mask="circle", size=80, sf=0.2)
grating_sf = 400 if self.use_vr else 0.2
self.grating = visual.GratingStim(win=self.window, mask="circle", size=80, sf=grating_sf)
self.grating_neg = visual.GratingStim(win=self.window, mask="circle", size=80, sf=grating_sf, phase=0.5)

self.grating_neg = visual.GratingStim(win=self.window, mask="circle", size=80, sf=0.2, phase=0.5)

fixation = visual.GratingStim(win=self.window, size=0.2, pos=[0, 0], sf=0.2, color=[1, 0, 0], autoDraw=True)
self.fixation = visual.GratingStim(win=self.window, pos=[0, 0], sf=grating_sf, color=[1, 0, 0])
self.fixation.size = 0.02 if self.use_vr else 0.2

# Generate the possible ssvep frequencies based on monitor refresh rate
def get_possible_ssvep_freqs(frame_rate, stim_type="single"):
Expand Down Expand Up @@ -65,7 +67,10 @@ def init_flicker_stim(frame_rate, cycle, soa):
return {"cycle": cycle, "freq": stim_freq, "n_cycles": n_cycles}

# Set up stimuli
frame_rate = np.round(self.window.getActualFrameRate()) # Frame rate, in Hz

# Frame rate, in Hz
# GetActualFrameRate() crashes in psychxr due to 'EndFrame called before BeginFrame'
frame_rate = np.round(self.window.displayRefreshRate if self.use_vr else self.window.getActualFrameRate())
freqs = get_possible_ssvep_freqs(frame_rate, stim_type="reversal")
self.stim_patterns = [
init_flicker_stim(frame_rate, 2, self.soa),
Expand Down Expand Up @@ -101,14 +106,22 @@ def present_stimulus(self, idx, trial):

# Present flickering stim
for _ in range(int(self.stim_patterns[ind]["n_cycles"])):
self.grating.setAutoDraw(True)

for _ in range(int(self.stim_patterns[ind]["cycle"][0])):
if self.use_vr:
tracking_state = self.window.getTrackingState()
self.window.calcEyePoses(tracking_state.headPose.thePose)
self.window.setDefaultView()
self.grating.draw()
self.fixation.draw()
self.window.flip()
self.grating.setAutoDraw(False)
self.grating_neg.setAutoDraw(True)

for _ in range(self.stim_patterns[ind]["cycle"][1]):
if self.use_vr:
tracking_state = self.window.getTrackingState()
self.window.calcEyePoses(tracking_state.headPose.thePose)
self.window.setDefaultView()
self.grating_neg.draw()
self.fixation.draw()
self.window.flip()
self.grating_neg.setAutoDraw(False)
pass

self.window.flip()
pass
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ keyboard==0.13.5
airium>=0.1.0
attrdict>=2.0.1
attrdict3
# Oculus/Quest VR support - currently only supported on Windows.
psychxr; platform_system == "Windows"

# This might try to build from source on linux (since there are no wheels for Linux on PyPI) .
# You can pass `--find-links=https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-20.04/` your `pip install` to use the prebuilt wheels at the link.
Expand Down

0 comments on commit 67d6278

Please sign in to comment.