Пример #1
0
    def __init__(self, parent=None):
        super(Ui, self).__init__(parent)
        self.setupUi(self)
        self.show()

        self.FDS_R = int(cfg["H_reflex"]["fds_r"])
        sinfo = liesl.get_streaminfos_matching(type="EEG")[0]
        self.buffer = liesl.RingBuffer(sinfo, duration_in_ms=500)
        self.buffer.start()
        self.buffer.await_running()
        time.sleep(1)

        self.addToolBar(NavigationToolbar(self.MplWidget.canvas, self))

        self.download()
        self.intensity_minus_1000.clicked.connect(
            partial(self.decrease_intensity, 1000))
        self.intensity_plus_1000.clicked.connect(
            partial(self.increase_intensity, 1000))
        self.intensity_minus_100.clicked.connect(
            partial(self.decrease_intensity, 100))
        self.intensity_plus_100.clicked.connect(
            partial(self.increase_intensity, 100))
        self.trigger.clicked.connect(self.start_stimulation)
        push("hreflex_start")
Пример #2
0
    def show(self, duration: float = 0, canvas=None, safetime=.2):
        """present all stimuli stored in the cue

        args
        ----
        duration: float
            how many seconds you want to present the visual stimuli on the canvas. Defaults to zero.
            Using zero will result in the function returning immediatly, while
            keeping the visual stimulus maintained on the canvas. In that regard, it resembles presentation forever, (or until another cue is presented). This can confuse Windows 10 if the canvas is moved or resized, as the OS thinks the canvas is `unresponsive`. Any other positive values cause the function to not return and block for the whole duration.
        canvas: :class:`reiz.Canvas`
            In case you decide to present the Cue on a different canvas instead to the one assigned during instantiation. Will be ignored otherwise.
        safetime: float
            continuous presentation causes the canvas to be updated at the flip rate of your screen and grapics cards (usually aroung 60Hz). This hardware limitation means that the duration of presentation
            will be quantizised, i.e. the duration of presentation will be a multiple of 16.6ms for a 60Hz screen. To achieve more accurate duration, the safetime parameters sets how long to the end of the duration we will no longer flip the screen. By default, we won't flip the screen during the last 200ms. This can cause the OS to consider the screen `unresponsive` (see duration above). Please note that this does not improve the timing of the actual drawing on the screen, it just allows the :meth:`~.show` to return at a more accurate time.

        """

        if canvas is not None:
            self.canvas = canvas
        if self.audio is not None:
            self.audio.play()
        if self.marker is not None:
            marker.push(self.marker)

        if duration is not None and self.visual is not None:
            if duration == 0:  # show "forever"
                self.canvas.show(self.visual)
                return 0
            else:  # show for duration
                clk = _Clock()
                dt = clk.now()
                clk.tick()
                self.canvas.show(self.visual)
                while dt <= duration and self.canvas.available:
                    # flipping quantizises the sleep duration, therefore we
                    # don't flip anymore if that would become relevant
                    # we only repeat presentation of the visual stimulus
                    # as audio and markers would be senseless and overlays
                    if abs(duration - dt) > safetime:
                        self.canvas.show(self.visual)
                        clk.sleep_debiased(.1)
                    dt = clk.now()
                return dt
Пример #3
0
def auto_trigger(coil: Coil,
                 lucky,
                 marker: MarkerStreamInlet,
                 buffer: DataRingBuffer,
                 timeout: Seconds = 1):
    """Expect the TMS to be triggered manually
    We wait a certain time for the  response to arrive. If this time has passed,
    we trigger again, assuming that somehow the TCP-IP command was lost in
    transition.
    """
    marker.pull_chunk(
    )  #flush the buffer to be sure we catch the latest sample
    # lucky.trigger_now() #trigger the coil
    lucky.trigger()
    push('TMS_auto_trigger', sanitize=False)
    _, onset_in_ms = marker.pull_sample()
    try:
        response = wait_for_trigger(coil, marker, buffer, onset_in_ms,
                                    timeout)  #wait for the response
    except TimeOutException:
        logger.warning("Timeout,. repeating command to stimulate")
        response = auto_trigger(coil, lucky, marker, buffer, timeout)
    return response
Пример #4
0
def manual_trigger(coil: Coil, marker: MarkerStreamInlet,
                   buffer: DataRingBuffer):
    """Expect the TMS to be triggered manually

    We therefore also wait forever for the  response to arrive. If examiner
    becomes inpatient as the trigger was swallowed, a manual repetition is
    necessary
    """
    print('wait for manual trigger')
    marker.pull_chunk(
    )  #flush the buffer to be sure we catch the latest sample
    while True:
        marker.pull_chunk()
        didt_catch, onset_in_ms = marker.pull_sample()
        if didt_catch[0][9:13] == 'didt':
            break
    push('TMS_manual_trigger', sanitize=False)
    # wait  forever for the response, because
    response = wait_for_trigger(coil,
                                marker,
                                buffer,
                                onset_in_ms,
                                timeout=FOREVER)
    return response
Пример #5
0
 def closeEvent(self, event):
     push("hreflex_end")
     session.stop_recording()
     app.aboutToQuit.connect(on_close)
Пример #6
0
 def start_stimulation(self):
     push("h_reflex_stim_" + str(self.cur / 1000))
     self.mcs.start_stimulation()
     time.sleep(0.25)
     self.plot_hreflex()
Пример #7
0
def search_hotspot(trials=40,
                   isi=(3.5, 4.5),
                   task_description='Start Hotspot Search',
                   env=None,
                   run_automatic: bool = False):
    print(__file__)
    labels = env.labels
    emg_labels = env.emg_labels
    coil, marker, buffer, lucky = env.coil, env.marker, env.buffer, env.lucky
    task = Message(task_description)
    time.sleep(0.1)

    plt.close('all')

    def create_hotspot_canvas(emg_labels):
        nr, nc = 2, len(emg_labels) // 2
        if len(emg_labels) % 2:  #uneven
            nc += 1
        fig, axes = plt.subplots(nrows=nr, ncols=nc, sharex=True, sharey=True)
        fig.canvas.manager.window.move(-1280, 20)
        fig.canvas.manager.window.resize(1280, 1024)
        fig.tight_layout()
        return fig, axes

    fig, axes = create_hotspot_canvas(emg_labels)

    def show(response, axes, emg_labels, labels):
        xticks, xticklabels, xlim = response.get_xaxis(stepsize=25)
        for ax, lbl in zip(axes.flatten(), emg_labels):
            ax.cla()
            trace = response.get_trace(channel_idx=labels.index(lbl))
            vpp = response.get_vpp(channel_idx=labels.index(lbl))
            ax.plot(trace)
            for pos, val in zip(response.peakpos_in_ms, response.peakval):
                ax.plot([pos, pos], [0, val], color='red', linestyle=':')
            #TG: for test temporary change scale to [-1 1]
            ax.axvline(x=response.pre_in_ms, color='red')
            textstr = 'Vpp = {0:3.2f}'.format(vpp)
            props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)
            ax.text(0.05,
                    0.95,
                    textstr,
                    transform=ax.transAxes,
                    fontsize=14,
                    verticalalignment='top',
                    bbox=props)
            ax.set_title(lbl)
            ax.set_xticks(xticks)
            ax.set_xlim(xlim)
            ax.set_xticklabels(xticklabels)
        plt.show()

    task.play_blocking()

    if coil.amplitude == 0:
        entamp.play_blocking()
        response = manual_trigger(coil, marker, buffer)
        #coil.amplitude = amplitude
        amplitude = coil.amplitude
        amplitude = coil.amplitude
    else:
        amplitude = coil.amplitude
        amplitude = coil.amplitude

    counter = 0
    collection = []
    automatic = False
    has_started = False
    while counter < trials:
        if run_automatic or automatic:
            if counter == 0:
                coil.amplitude = 0
                manual_trigger(coil, marker, buffer)
                coil.amplitude = amplitude
            time.sleep(isi[0] + (random.random() * (isi[1] - isi[0])))
            response = auto_trigger(coil, lucky, marker, buffer)
        else:
            if not has_started:
                ready.play_blocking()
                has_started = True
            coil.amplitude = amplitude
            response = manual_trigger(coil, marker, buffer)
            hotspot_amplitude = coil.amplitude
            hotspot_amplitude = coil.amplitude
            if amplitude != hotspot_amplitude:
                amplitude = hotspot_amplitude
            if run_automatic:
                automatic = True

        response_marker = create_marker(response, coil, emg_labels, labels,
                                        amplitude)
        coil_message = json.loads(
            response.as_json(
                channel_idx=labels.index(env.channel_of_interest)))
        print('before push')
        coil.set_response(mepmaxtime=coil_message['mepmaxtime'],
                          mepamplitude=coil_message['mepamplitude'],
                          mepmin=coil_message['mepmin'],
                          mepmax=coil_message['mepmax'])
        coil.push_marker(json.dumps(response_marker))
        push(json.dumps(response_marker), sanitize=False)
        show(response, axes, emg_labels, labels)
        props = dict(boxstyle='round', facecolor='white', alpha=1)
        counter += 1
        print(f'this is the {counter} trial')
        ax = axes[0, 0]
        ax.text(-.15,
                1.05,
                f'{counter} of {trials}',
                transform=ax.transAxes,
                fontsize=14,
                verticalalignment='top',
                bbox=props)
        collection.append(response_marker)
        plt.pause(0.05)

    run_ended.play_blocking()
    time.sleep(2)
    return collection
Пример #8
0
def start_intervention(cfg, condition, stim_number, verbose: bool = False):
    RMT = get_RMT(max_percent_RMT=120)
    run_length = int(cfg['main']['run_length'])
    condition_idx = condition['index']
    """Save the condition"""
    condition_order_directory = cfg['main']['recordings_path'] + "\\" + cfg[
        'general']['subject_token'] + '\\condition_%s\\config\\' % condition_idx
    condition_order_file_path = condition_order_directory + 'config.json'
    try:
        with open(condition_order_file_path) as json_file:
            stimuli = json.load(json_file)
        print('Loaded condition file')
        break_idx, timeleft = create_break_idx_timeleft(
            stimuli, condition, run_length)
        stimuli = stimuli[stim_number:]
    except:
        stimuli = create_stim_list(condition, cfg)
        print('create new condition file')
        break_idx, timeleft = create_break_idx_timeleft(
            stimuli, condition, run_length)
        os.makedirs(condition_order_directory)
        with open(condition_order_file_path, 'w') as file:
            file.write(json.dumps(stimuli))  #überschreibt immer
        print('Created new condition file')
    """Check if all streams are available"""
    #    streamargs = [{'name':"localite_marker"},   # comments: make a real list
    #                  {'name':"reiz-marker"},
    #                  {'name':"eego"},
    #                  {'name':"LuckyLoop"},
    #                  {'name':"pupil_capture"},
    #                  {'name':"GDX-RB_0K2002A1"}]

    streamargs = [{'name': "eego"}]

    session = Session(prefix=cfg['general']['subject_token'],
                      streamargs=streamargs)
    """Define stimulation intensity"""
    stimulation_intensity = round(condition['percent_RMT'] * RMT / 100)
    print(f"Stimulation intensity {stimulation_intensity}")
    """"Calculate the time duration for the intervention"""
    #    TMS_stimulus = {'stim_type': 'TMS', 'frequency':condition['frequency'], 'phase':condition['phase_in_deg']}
    #    N = stimuli.count(TMS_stimulus)
    #    expected_duration = (N * 10) / 60
    #    print(f'Expected duration is around {expected_duration:.2f} min')

    #%%
    """Intit Lucky Client"""
    print("Init lucky")
    #lucky = LuckyClient('134.2.117.144')
    """Init Coil"""
    print("Init coil")
    coil = Coil(0)
    time.sleep(.8)
    coil.amplitude = stimulation_intensity
    time.sleep(.8)
    """Init Sandy"""
    print("Init sandy")
    #    sandy_cli = sandy.Arduino(timeout=1.5, version =  'v0.3.1 - StalwartSandy')
    #    sandy_cli.reset()
    #    sandy_cli.set_threshold(150)
    #    sandy_cli.blink(5)
    #sandy_cli.set_threshold(0)
    print("Sandy in standby")
    time.sleep(1)
    """Create the GUI"""
    canvas = Canvas()
    canvas.open()
    labcue = reiz.Cue(canvas, visualstim=reiz.visual.library.logo)
    labcue.show(duration=2)

    #%%
    with session("TMS_intervention"):
        print("Started recording")
        canvas.window.start_run = False
        start_protocol = reiz.Cue(
            canvas, visualstim=Mural(text='Start protocol with F5'))
        print("Waiting for user to start in GUI")

        while not canvas.window.start_run:
            start_protocol.show(duration=1)
        countdown(canvas, 5)
        labcue.show()

        t0 = time.time()
        break_counter = 0
        reaction_times = []
        """ set up phase and frequency parameter """
        phase = condition['phase_in_deg']
        frequency = condition['frequency']
        lucky.phase = phase
        lucky.frequency = frequency

        for single_stimulus in stimuli:
            """get some parameter informations"""
            stimulus_idx = single_stimulus['stimulus_idx']
            stim_type = single_stimulus['stim_type']

            print(f"Stimulation index {single_stimulus['stimulus_idx']}")
            time.sleep(0.5)
            time_setup_trial = time.time()

            # sends current setup as marker
            push(json.dumps({
                'stimulus_idx': str(stimulus_idx),
                'stim_type': stim_type,
                'freq': str(frequency),
                'phase': str(phase)
            }),
                 sanitize=False)
            if verbose:
                print("Start " + stim_type + " for frequency " +
                      str(frequency) + ' and phase ' + str(phase))

            # conditional of stimtype, setup TMS and Arduino this trial
            if stim_type == 'TMS':
                coil.amplitude = stimulation_intensity
                time.sleep(.8)
                t1 = time.time()
                trial_time = t1 - t0
                if verbose:
                    print("\n Trial time: " + str(trial_time))
                # TG: wait and trigger phase and frequency dependent, if next stimuli is TMS, then wait 10s, else wait 5s
                if stimulus_idx < (stimuli[-1]['stimulus_idx']) and stimuli[
                        stimulus_idx - stim_number + 1]['stim_type'] == 'TMS':
                    sleep_time = random_time(min=9.5 - trial_time,
                                             max=10.5 - trial_time)
                else:
                    sleep_time = random_time(min=4.5 - trial_time,
                                             max=5.5 - trial_time)

            if stim_type == 'PVT':
                coil.amplitude = 0
                time.sleep(.8)
                # wait and trigger phase and frequency dependent
                t1 = time.time()
                trial_time = t1 - t0
                if verbose:
                    print("\n Trial time: " + str(trial_time))
                sleep_time = random_time(min=4.5 - trial_time,
                                         max=5.5 - trial_time)
                try:
                    sandy_cli.await_blink()
                    if verbose:
                        print('Sandy is waiting for blink')
                except:
                    raise ConnectionError('Sandy in unclear state')
            print(f"\n Setup: {(time.time()-time_setup_trial):.2f}s")

            if sleep_time < 0.75:
                sleep_time = 0.75
            if True or verbose:
                print(f"\n Sleep_time = {sleep_time:.2f}s")
                print(f"\n ISI = {sleep_time+trial_time:.2f}s\n")
            labcue.show(duration=sleep_time)
            t0 = time.time()

            # conditional on stimtype, wait for keypress
            if stim_type == 'PVT':
                event_list = []
                sandy_cli.receive()
                blink_wait_start = time.time()
                while not (event_list) or len(event_list) == 0:
                    if time.time() - blink_wait_start > 30:
                        raise ConnectionError(
                            f"Sandy could not be triggered for 30 seconds. Stimulus idx: {stimulus_idx}"
                        )
                        break
                    print(f"Wait for blink trigger. Stim: {stimulus_idx}")
                    lucky.trigger()
                    event_list = sandy_cli.receive()
                    print(f"Event list: {event_list}")
                for event in event_list:
                    if event['state-change'] == 'blink-started':
                        time_trigger = int(event['timestamp'])
                time_wait_for_press = time.time()
                print("Waiting for button pressed")
                atleast_one_button_pressed = False
                time_reaction = False
                while time.time() - time_wait_for_press < 1.25:
                    response = sandy_cli.receive()
                    if response:
                        event_list.extend(response)
                    if event_list:
                        for event in event_list:
                            if event:
                                print(event)
                                button_1_pressed = event[
                                    'state-change'] == 'button-1-pressed'
                                button_2_pressed = event[
                                    'state-change'] == 'button-2-pressed'
                                both_buttons_pressed = event[
                                    'state-change'] == 'both-buttons-pressed'
                                atleast_one_button_pressed = button_1_pressed or button_2_pressed or both_buttons_pressed
                                if atleast_one_button_pressed:
                                    time_reaction = int(event['timestamp'])
                                    break
                    if atleast_one_button_pressed:
                        break
                if verbose:
                    print(f"Trigger timestamp= {time_trigger}")

                if time_trigger is not None:  # led was turned on
                    if verbose:
                        print("Reaction timestamp= " + str(time_reaction))
                    if not (
                            time_reaction
                    ) or time_reaction - time_trigger < 0 or time_reaction - time_trigger > 1000:
                        reaction_time = "No reaction"
                        rt = reiz.Cue(canvas,
                                      visualstim=Mural(text=reaction_time))
                    else:
                        reaction_time = time_reaction - time_trigger
                        reaction_times.append(reaction_time)
                        rt = reiz.Cue(
                            canvas,
                            visualstim=Mural(
                                text='{0:3.1f} ms'.format(reaction_time)))
                    if verbose:
                        print('Reaction time: ' + str(reaction_time))

                    push(json.dumps({'reaction_time': str(reaction_time)}),
                         sanitize=False)
                    rt.show(duration=1)
            else:
                # when TMS stimulus
                lucky.trigger()

            try:
                if stimuli[stimulus_idx - stim_number]['stim_type'] == "PVT":
                    coil.amplitude = 0
                    time.sleep(.8)
            except IndexError:
                print("Index error")

            if stimulus_idx in break_idx:  #make a break after cfg.run_length stimuli if experiment is not over
                break_counter += 1
                if break_counter == 1:
                    mean_run_reaction_time = np.mean(
                        reaction_times[:break_idx.index(stimulus_idx)])
                else:
                    mean_run_reaction_time = np.mean(reaction_times[(
                        break_idx[break_idx.index(stimulus_idx) - 1] -
                        stim_number +
                        1):break_idx[break_idx.index(stimulus_idx)]])
                mean_overall_reaction_time = np.mean(reaction_times)
                #displays run reaction time
                v_run_reaction_time = reiz.Cue(
                    canvas,
                    visualstim=Mural(
                        text='Run reaction time = ' +
                        '{0:3.1f} ms'.format(mean_run_reaction_time)))
                v_run_reaction_time.show(duration=2)

                #displays overall reaction time
                v_overall_reaction_time = reiz.Cue(
                    canvas,
                    visualstim=Mural(
                        text='Overall reaction time = ' +
                        '{0:3.1f} ms'.format(mean_overall_reaction_time)))
                v_overall_reaction_time.show(duration=2)

                #calculates and shows the expected duration of the intervention that is  left
                expected_duration_left = timeleft[break_idx.index(
                    stimulus_idx)]
                print(
                    f'Expected duration is around {expected_duration_left} min'
                )
                v_expected_duration_left = reiz.Cue(
                    canvas,
                    visualstim=Mural(
                        text='Expected duration left = ' +
                        '{0:3.1f} min'.format(expected_duration_left)))
                v_expected_duration_left.show(duration=4)

                canvas.window.start_run = False
                nextrun = reiz.Cue(canvas,
                                   visualstim=Mural(text='Continue with F5'))
                while not canvas.window.start_run:
                    nextrun.show(duration=1)
                countdown(canvas, 5)
            labcue.show()

    v_intervention_finished = reiz.Cue(
        canvas,
        visualstim=Mural(
            text='Intervention is finished. Please stop the recording'))
    v_intervention_finished.show(duration=1)