Example #1
0
def initTk(expInfo):
    ## Data host ##
    if not os.path.exists(edfDataFolder):
        os.makedirs(edfDataFolder)
    dataFileName = (expInfo['Subject'] + '.EDF')
    tk.openDataFile(dataFileName)
    # add personalized data file header (preamble text)
    tk.sendCommand("add_file_preamble_text 'Psychopy Waaaaazzzzzzooooo'")
    tk.sendMessage('Subject_No %s' % expInfo["Subject"])

    ## Init parameters
    genv = EyeLinkCoreGraphicsPsychoPy(tk, WIN)
    pylink.openGraphicsEx(genv)
    print("pylink initiated")  # For testing

    tk.setOfflineMode()
    tk.sendCommand('sample_rate 500')
    tk.sendCommand("screen_pixel_coords = 0 0 %d %d" %
                   (scnWIDTH - 1, scnHEIGHT - 1))
    tk.sendMessage("DISPLAY_COORDS = 0 0 %d %d" %
                   (scnWIDTH - 1, scnHEIGHT - 1))
    #tk.sendCommand("hostVer = HV5")
    tk.sendCommand("recording_parse_type = GAZE")

    eyelinkVer = tk.getTrackerVersion()
    if eyelinkVer >= 2:
        tk.sendCommand('select_parser_configuration 0')

    hostVer = 0
    if eyelinkVer == 3:
        tvstr = tk.getTrackerVersionString()
        vindex = tvstr.find("EYELINK CL")
        hostVer = int(float(tvstr[(vindex + len("EYELINK CL")):].strip()))

    tk.sendCommand(
        "file_event_filter = LEFT,RIGHT,FIXATION,SACCADE,BLINK,MESSAGE,BUTTON,INPUT"
    )
    tk.sendCommand(
        "link_event_filter = LEFT,RIGHT,FIXATION,FIXUPDATE,SACCADE,BLINK,BUTTON,INPUT"
    )

    if hostVer >= 4:
        tk.sendCommand(
            "file_sample_data  = LEFT,RIGHT,GAZE,GAZERES,PUPIL,HREF,AREA,STATUS,HTARGET,INPUT"
        )
        tk.sendCommand(
            "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,PUPIL,HREF,AREA,STATUS,HTARGET,INPUT"
        )
    else:
        tk.sendCommand(
            "file_sample_data  = LEFT,RIGHT,GAZE,GAZERES,PUPIL,HREF,AREA,STATUS,INPUT"
        )
        tk.sendCommand(
            "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,PUPIL,HREF,AREA,STATUS,INPUT"
        )

    return dataFileName
Example #2
0
def block(expInfo, practice, block_number):
    ################ Block structure (after choosing a card) ################
    ##Preparing the next trials
    if not dummyMode:  #if not (dummyMode or practice):
        present_message("calibration")
        #waitForKey(variables.ser)
        tk.doTrackerSetup()  #Calibrating the eyetracker
    core.wait(0.5)
    # io.clearEvents(device_label='all')  #Flushing the buffer. In the final experiment to be replaced by the following line
    variables.ser.reset_input_buffer()

    ## Presenting the "remember: the instructions are..." message (according to mapping)
    if variables.Mapping["KeyYes"] == 'r':
        present_message("explanation_remember_yes_right")
    else:
        present_message("explanation_remember_yes_left")

    core.wait(0.5)
    waitForKey(variables.ser)
    variables.ser.reset_input_buffer()

    ##Creating a randomized List of questions for one block
    card_number = (card_input['card_selected'])
    questionlist = Cards[int(
        card_number
    )]["questions_asked"]  # Getting the List of questions according to the card selected as defined in the dictionary
    random.shuffle(questionlist)  # Randomizing the list
    print(card_input['card_selected'])  #For testing only

    ## Setting number of initial trial to 1
    trial_number = 1

    present_message(
        "start_ready")  # "Einrichtung abgeschlossen. Zum STARTEN: RECHTS"
    waitForKey(variables.ser)
    variables.ser.reset_input_buffer()
    wordlist = []  # flushing wordlist used later for intentionality check
    blockData = []  # For storing data of ALL trials within the block

    ##Setting up a trial-counter and a loop for a block of 10 trials
    while trial_number <= trial_max:
        '''thr1 = Thread(target=readSer)
        thr1.daemon = True
        thr1.start()'''

        ##Defining the word used in the respective trial from the randomized wordlist
        word_number = questionlist[int(
            trial_number - 1
        )]  # Choosing the 1st, 2nd 3rd... word from the (randomized) list. This variable could also be just the variable "word" used below but I defined an extra variable for more clarity.
        word = Questions[int(
            word_number
        )]["text"]  # The translation of the words number into actual text (according to the "Questions" dictionary)
        wordlist.append(word)
        # print(word) #for testing only
        core.wait(0.05)

        tk.setOfflineMode()
        pylink.pumpDelay(50)
        err = tk.startRecording(1, 1, 1, 1)
        pylink.pumpDelay(50)
        eyeTracked = tk.eyeAvailable()
        if eyeTracked == 2:
            eyeTracked = 1

        ##Writing information on the trial into a data dictionary
        trialData = {
            "Subject_No": expInfo['Subject'],
            "BlockNumber": block_number,
            "TrialNumber": trial_number,
            "ITIoffset": round(variables.ITI500, 4),
            "CardNumber": card_number,
            **variables.Mapping  # Adds informations concerning the mapping of the keys for yes/no and the colors of the effects (circles)
        }
        trialData.update(
            trial(word, variables.Mapping["DelayEffectLeft"],
                  variables.Mapping["DelayEffectRight"])
        )  # Calling trial function and appending data from this trial to data dictionary.
        trialData.update(
            {
                "ResponseCorrect":
                checkCorrectness(word_number, card_number, trialData,
                                 variables.Mapping)
            }
        )  # Checking whether response was correct and appending this information (boolean) to data
        trialData.update({
            "TrueResponseWouldBe":
            checkTrueResponse(word_number, card_number, variables.Mapping)
        })
        trialData.update({
            "DelayEffectLeft":
            variables.Mapping["DelayEffectLeft"],
            "DelayEffectRight":
            variables.Mapping["DelayEffectRight"]
        })
        tk.sendCommand('clear_screen 0')
        if not practice:
            #sendBehavData(data)  # Writing data to the behaviour-file and sending it (if not in dummy mode) to the eyetracker.
            blockData.append(trialData)
        tk.stopRecording()
        tk.sendMessage('TRIAL_RESULT')
        pylink.pumpDelay(50)

        trial_number = trial_number + 1

        variables.ser.reset_input_buffer()  # flush the input buffer
        #variables.q.queue.clear()  # flushing the queue

    ## sequence of showing the cards image and asking whether it was the correct one ##
    present_message("card_image")  # Your card was probably:
    core.wait(4)
    image_presented = show_cardimage(card_number,
                                     block_number)  # Present image of card
    core.wait(5)
    if variables.Mapping['KeyYes'] == 'r':
        present_message("card_correct_right")
    else:
        present_message("card_correct_left")
    decision = waitForDecision(variables.ser)
    '''
    ## sequence asking whether there were any unintentional reactions and if so which ##
    if variables.Mapping['KeyYes'] == 'r':
        present_message("unintentional_response_right")
    else:
        present_message("unintentional_response_left")
    core.wait(0.7)
    anyUnintentional = checkMeaning(waitForDecision(variables.ser))
    if anyUnintentional == True:
        #whichUnintentional = "TEST123" # for testing ONLY. Must not be activre oin final experiment
        whichUnintentional = formUnintentional(wordlist)  # Present form asking for which responses were unintentional
    else:
        whichUnintentional = "None"
    '''

    whichTrue = formTrue(
        wordlist)  # Present form asking for which responses were unintentional

    WIN.mouseVisible = False

    if not practice:
        for storedTrialData in blockData:
            storedTrialData.update(
                {
                    "CardImagePresented":
                    image_presented,
                    "CardImageReportedlyCorrect":
                    checkMeaning(decision),
                    # "AnyUnintentionalReactions": anyUnintentional,
                    "whichUnintentionalReactions(form)":
                    whichTrue[blockData.index(storedTrialData)]
                }
            )  # Appending information  to data on the presented card image (int) and whether participant evaluated it to be the correct card (boolean)
            sendBehavData(
                storedTrialData
            )  # Writing data to the behaviour-file and sending it (if not in dummy mode) to the eyetracker.
        #sendBehavData("ENDofBLOCK")
        print(len(blockData))  # For Testing only
Example #3
0
def sendBehavData(data):
    print(
        data, file=behaviour
    )  # prints data to the console and appends it to magic_cards_behaviour.txt
    if not dummyMode:
        tk.sendMessage('TRIALID')
        tk.sendCommand("record_status_message 'Block: %s Trial number: %s'" %
                       (data["BlockNumber"], data["TrialNumber"]))
        tk.sendMessage('!V TRIAL_VAR CardNumber %s' % data["CardNumber"])
        tk.sendMessage('!V TRIAL_VAR TooEarly %s' % data["TooEarly"])
        tk.sendMessage('!V TRIAL_VAR TooSlow %s' % data["TooLate"])
        tk.sendMessage('!V TRIAL_VAR InTime %s' % data["InTime"])
        tk.sendMessage('!V TRIAL_VAR Response %s' % data["Response"])
        tk.sendMessage('!V TRIAL_VAR Stimulus %s' % data["Stimulus"])
        tk.sendMessage('!V TRIAL_VAR RT %s' % data["RTTime"])
        tk.sendMessage('!V TRIAL_VAR Correct %s' % data["ResponseCorrect"])
    else:
        pass
Example #4
0
def noButtonTrial(word, delayEffectLeft, delayEffectRight):
    ## setting variables to their initial values
    tooEarly = False
    inTime = False
    tooLate = False
    key = ""
    timestamp_reaction = 0  # to make sure the value from the last trial is not carried over if no reaction in this one
    timestamp_effect = 0  # to make sure the value from the last trial is not carried over if no reaction in this one
    button_pressed = False
    durationFixation = random.uniform(
        *config_experiment.DURATION_SPAN_FIXATION
    )  # Determining the random fixation period, within the predifined span

    ##Presenting the fixation cross
    present_message("blackscreen")  # Blackscreen
    core.wait(config_experiment.DELAY_INITIAL)
    variables.io.clearEvents(device_label='all')  #Flushing the buffer.
    tk.sendMessage('Fixation_Onset')
    effects.cross()  # Displaying a fixation cross
    variables.timer.reset(newT=0.0)
    timestampFixation = variables.timer.getTime()

    keyInput = []
    while True:
        #i = i + 1  # for testing only
        keyboardActivity = variables.io.devices.keyboard.getKeys()
        if keyboardActivity != []:
            keyInput = keyboardActivity[0].key

        if keyInput in ['s', 'l'] and variables.timer.getTime() < (
                timestampFixation + durationFixation):
            tk.sendMessage('tooEarly_Onset')
            WIN.flip()
            event.clearEvents()
            present_message("early")  # "Too early"
            tooEarly = True
            core.wait(config_experiment.DURATION_MESSAGE_TOOEARLY)
            tk.sendMessage('tooEarly_Offset')
            #print(i)  # For testing only
            break

        if variables.timer.getTime() > (timestampFixation +
                                        durationFixation):  # q.empty():
            event.clearEvents()
            #print(i)  # For testing only
            tk.sendMessage('Fixation_Offset')
            break

    if not tooEarly:
        target = visual.TextStim(
            WIN, text=word, pos=[0, 0],
            alignHoriz='center')  # stimulus (i.e. the word)
        target.draw()
        variables.io.clearEvents(device_label='all')  # Flushing the buffer.
        core.wait(config_experiment.DELAY_TARGET)
        #q.queue.clear()  # flushing the queue
        variables.timer.reset(newT=0.0)
        print(word)  # for testing only
        timestamp_target = variables.timer.getTime()
        tk.sendMessage('%d TargetOnset' % timestamp_target)
        WIN.flip()  # display the stimulus
        screenRefreshed = False
        #i = 0  # for testing only

        keyInput = []
        while True:
            #i = i + 1  # for testing only
            keyboardActivity = variables.io.devices.keyboard.getKeys()
            if keyboardActivity != []:
                keyInput = keyboardActivity[0].key

            if screenRefreshed == False and variables.timer.getTime() > (
                    timestamp_target + config_experiment.DURATION_TARGET
            ):  # q.empty():  # Value to be adjusted for final experiment
                screenRefreshed = True
                WIN.flip()
                tk.sendMessage('Target_Offset')
                event.clearEvents()
                #print(i)  # For testing only
                pass

            if keyInput in ['s', 'l']:  # If any button is pressed
                print("button pressed")  # For testing
                button_pressed = True
                timestamp_reaction = variables.timer.getTime()
                tk.sendMessage('Reaction')
                ##If the reaction is so early that no target-specific reaction can be assumed -> "Too early"
                if keyInput == 's':
                    key = 'l'
                    core.wait(delayEffectLeft)
                if keyInput == 'l':
                    key = 'r'
                    core.wait(delayEffectRight)
                #WIN.flip()
                timestamp_effect = variables.timer.getTime()
                tk.sendMessage('Effect_Onset')
                effects.reaction(key)
                tk.sendMessage('Effect_Offset')
                inTime = True

                print(key)  # For testing
                #print(i)  # For testing only
                inTime = True
                break

            ##If there is no response within the given timeframe -> "Too late"
            if variables.timer.getTime() > (
                    timestamp_target + config_experiment.TIME_TOOLATE
            ):  #and not button_pressed:  # q.empty():
                event.clearEvents()
                present_message("late")  # "Too late"
                tk.sendMessage('tooLate_Onset')
                tooLate = True
                core.wait(config_experiment.DURATION_MESSAGE_TOOLATE)
                tk.sendMessage('tooLate_Offset')
                #print(i)  # For testing only
                break

        ### writing the data of the trial into the data dictionary ###
        trial_data = {
            "Stimulus": word,
            "Response": key,
            "RTTime": round((timestamp_reaction - timestamp_target), 4),
            "ActionEffectOnsetTime": round(timestamp_effect, 4),
            "TooEarly": tooEarly,
            "TooLate": tooLate,
            "InTime": inTime,
            "DurationFixation": durationFixation
        }

    else:  # If tooEarly == True
        ### writing the data of the trial into the data dictionary ###
        trial_data = {
            "Stimulus": word,
            "Response": key,
            "RTTime": "none",
            "ActionEffectOnsetTime": "none",
            "TooEarly": tooEarly,
            "TooLate": tooLate,
            "InTime": inTime,
            "DurationFixation": durationFixation
        }

    return trial_data
Example #5
0
def main():
    ###################Experiment starting sequence###########################
    tk.sendMessage('%d ITIoffset' % 0)

    ## Initializing serial connection to Arduino ##
    initSer()  ## stored in variables.ser
    print(variables.ser)  # For testing

    ## Basic info dialog, defining participants number, dominant eye & hand, basic demografics ##
    expInfo = variables.infoBuffer
    print(expInfo, file=behaviour)

    ## Initializing Eyetracker ##
    dataFileName = initTk(
        expInfo
    )  # inits the eyetracker and returns the name of the eyetracker-data file

    ## Initializing randomization of response keys and effect colors ##
    initMapping(
    )  # Randomized assignment of effect colors and key for yes/no (stored in variables.RandomMapping)
    print(variables.Mapping)  # For testing
    print("variable mapping defined")  # For testing

    ################################# Experiment ###########################################

    if not dummyMode:
        print("tracker setup started")
        tk.doTrackerSetup()
    print("tracker setup done")  # for testing

    #######Wellcoming message#######
    present_message("welcome")
    core.wait(0.5)
    waitForKey(variables.ser)
    #variables.ser.reset_input_buffer()

    present_message("welcome_2")
    core.wait(0.5)
    waitForKey(variables.ser)
    #variables.ser.reset_input_buffer()

    present_message("welcome_3")
    core.wait(0.5)
    waitForKey(variables.ser)
    #variables.ser.reset_input_buffer()

    present_message("welcome_4")
    core.wait(0.5)
    waitForKey(variables.ser)
    #variables.ser.reset_input_buffer()

    ######

    ##Explanations of what to do
    present_message("explanation_initial_general")
    core.wait(0.5)
    waitForKey(variables.ser)
    #variables.ser.reset_input_buffer()

    if variables.Mapping["KeyYes"] == 'r':
        present_message("explanation_initial_yes_right")
    else:
        present_message("explanation_initial_yes_left")
    core.wait(0.5)
    waitForKey(variables.ser)
    #variables.ser.reset_input_buffer()

    ##important
    present_message("explanation_initial_important")
    core.wait(0.5)
    waitForKey(variables.ser)
    #variables.ser.reset_input_buffer()

    ##Explanations of what to do
    present_message("explanation_initial_procedure")
    core.wait(0.5)
    waitForKey(variables.ser)
    #variables.ser.reset_input_buffer()

    ##Explanations of what to do
    present_message("explanation_initial_procedure_2")
    core.wait(0.5)
    waitForKey(variables.ser)
    #variables.ser.reset_input_buffer()

    ######

    ###### Practice #####
    ##First some questions for practice
    present_message("practice")
    waitForKey(variables.ser)
    variables.ser.reset_input_buffer()

    ################ Block Structure ################
    ## Setting up a block-counter and a loop of 10 blocks ##
    block_number = 1
    while block_number <= block_max:  # Set block_max in the config_experiment file in order to run more or less blocks
        if block_number == 0:
            practice = True
        else:
            practice = False

        ## Choosing a (new) card and running a block ##
        if practice:
            present_message(
                "practice_ready"
            )  # "Please advice the researcher when you are ready"
        else:
            present_message(
                "choose_ready"
            )  # "Choose a new card and advice the researcher when you are ready"
        core.wait(0.5)
        waitForKey(variables.ser)
        variables.ser.reset_input_buffer()

        ## Presenting a message about some initialization
        present_message("initialization")
        chooseCard(
        )  # At this point the researcher gives input on the chosen card via the Arduino's numpad

        block(expInfo, practice, block_number)  # Runs a block of 10 trials

        if practice:
            present_message("practice_finished")
            core.wait(0.5)
            waitForKey(variables.ser)
            #variables.ser.reset_input_buffer()

        block_number += 1  # raises the block_number after each block by one

    ## Receiving data from the eyetracker (if not in dummy mode) ##
    if not dummyMode:
        receiveData(dataFileName)
    else:
        print(
            "No eyetracker data received because you are running the experiment in dummy mode"
        )

    ################  Thank you message and end sequence  ################
    present_message("thanks")
    core.wait(0.5)
    waitForKey(variables.ser)
    event.clearEvents()
    print("experiment completed", file=behaviour)
    #############################################################################

    # make sure everything is closed down
    behaviour.close()
    tk.close()
    variables.ser.close()
    WIN.close()
    core.quit()