Behavioural task score

PennController for IBEX Forums Support Behavioural task score

This topic contains 9 replies, has 2 voices, and was last updated by Avatar zoe_f 7 hours ago.

Viewing 10 posts - 1 through 10 (of 10 total)
  • Author
    Posts
  • #5260
    Avatar
    zoe_f
    Participant

    Hello again!

    I’d like to tell my participants their score on a task in my experiment. Their response will be recorded via a Key press (one of three options) as shown below.

    Template("presentedWords.csv",
        row => 
        newTrial("recall",
        newText(row.item)
            .print()
        ,
        newText("In which condition of the experiment did you encounter this word?")
        ,
        newText("Press the F KEY for INNER, the J KEY for OUTER, and the SPACEBAR for NEW WORD")
        ,
        newKey("question1", "FJ ")
            .log()
            .wait()
        )
        .log(row.item)
        .log(row.list)
        .log(row.condition)
    )

    My instinct is to create an if statement, as I’m a bit more familiar with R and Python, but I don’t know if that’s the most efficient way to achieve this in Java and/or within the PCIbex platform.

    Would the if statement go at the end of the trial code (i.e., just before the trial-closing bracket)? And would one create a numeric variable, let’s say correctnum == 0, and then just add to it along the way (and then at the end divide by the number of trials), as below? The other potential hiccough is that I will have multiple blocks separated by breaks, and will therefore need to add to this numeric value continuously across the blocks…maybe this is not achievable…

    if (getKey("question1") == row.correctKey) {
            correctnum == correctnum + 1;
        }
        )

    (then the trial close bracket ) then all the .log info).

    Thank you!

    #5261
    Jeremy
    Jeremy
    Keymaster

    Hello,

    The PennController counterparts of the if-else statements are the .test commands and their associated .success and .failure subcommands. You’ll also want to keep track of the score across trials, so you’ll need to use a global Var element:

    Template("presentedWords.csv",
        row => 
        newTrial("recall",
        newVar("score", 0).global() // Will initialize with 0 if Var doesn't exist yet
        ,
        newText(row.item)
            .print()
        ,
        newText("In which condition of the experiment did you encounter this word?")
        ,
        newText("Press the F KEY for INNER, the J KEY for OUTER, and the SPACEBAR for NEW WORD")
        ,
        newKey("question1", "FJ ")
            .log()
            .wait()
            .test.pressed( row.correctKey ) // Set value to v+1
            .success( getVar("score").set(v=>v+1) )
        ,
        newText("Your current score is: ")
            .after( newText("").text(getVar("score")) )
            .print()
        ,
        newButton("Next").print().wait()
        )
        .log(row.item)
        .log(row.list)
        .log(row.condition)
    )

    Jeremy

    #5275
    Avatar
    zoe_f
    Participant

    Dear Jeremy,

    I see, creating a global variable that can be referenced in whatever set of trials/block in the future. Thank you so much!

    Best wishes,

    Zoë

    #5401
    Avatar
    zoe_f
    Participant

    Hello there!

    I’m still wrestling with this bit of code. Basically, I want to display the score variable after all trials, not at the end of each. So the code below is the task where the score variable is referenced and updated (‘recall’ Template) and the one-off ‘score_time’ Trial which displays the score variable.

    The problems are twofold, and related: 1) where to put the score variable, and 2) how to access the score variable. I launch ‘score’ as a global variable every time, but:
    – when I launch the score variable inside the ‘recall’ Template, it is not referenced later in the ‘score_time’ Trial, and ‘score_time’ only displays: ‘Your score on the recall task was: ‘ with no number (so I guess it didn’t find the ‘score’ Variable)
    – when I launch the score variable outside the ‘recall’ Template, the recall score always prints as 0 in the ‘score_time’ Trial (no matter how many correct Keys I press in the trials). So I guess my code under the “question1” Key for test.pressed is not working.

    Given this, it seems that launching the global score variable outside the ‘recall’ Template will at least get that variable accessible, but then I must do something that allows its value to be changed trial-by-trial, and displayed in its final, updated form at the very end. Any errors you can spot below, or any guidance you have, would be very much appreciated. Thank you so much!

    Template("recall_practice_stimuli.csv",
        row => newTrial("recall-"+row.block,
        newVar("score", 0).global(), // score variable
        newText(row.item)
            .center()
            .css("font-size", "2em")
    	.css("font-family", "verdana")
            .print()
        ,
        newText("instruction", "Which condition did you encounter this word experiment? Press the F KEY for INNER, the J KEY for OUTER, and the SPACEBAR for NEW WORD")
            .print()
        ,
        newTimer("window", 5000)
            .start()
        ,
        newKey("question1", "FJ ")
            .log()
            .test.pressed(row.correctKey)
                .success(getVar("score").set(v=>v+1))
            .callback(getText(row.item).remove())
            .callback(getText("instruction").remove())
            .callback( getTimer("window").stop() )
        ,
        getTimer("window")
            .wait()
        )
        .log(row.item)
        .log(row.Group)
        .log(row.condition)
        .log(row.correctKey)
        .log("score", getVar("score"))
    );
    
    newTrial("score_time",
        newText("Your score on the recall task was: ")
            .after(newText("").text(getVar("score")))
            .print()
            .wait()
    );

    (P.S. thank you so much for the server update – everything is running and loading so fast now!)

    #5403
    Jeremy
    Jeremy
    Keymaster

    Hello Zoë,

    Your script runs the test on your Key element as soon as it creates it (well, just after setting it to log) so it will always fail: there’s no time to press any key in the millisecond(s) between the creation of the Key element and the evaluation of the test. You want to run that test in the callback, whose content is evaluated after a keypress (you can pass a series of commands in a callback):

        newKey("question1", "FJ ")
            .log()
            .callback(
                getText(row.item).remove(),
                getText("instruction").remove(),
                getTimer("window").stop(),
                getKey("question1").test.pressed(row.correctKey)
                    .success(getVar("score").set(v=>v+1))
            )

    About the Var element, I reckon things are tricky there, and actually I should probably change that, but technically within a trial you cannot refer to a named element that hasn’t been declared in that same trial. In other words, any get* command must be preceded by a corresponding new* command. So here is what you should do for your score_time trial:

    newTrial("score_time",
        newVar("score").global()
        ,
        newText("Your score on the recall task was: ")
            .after(newText("").text(getVar("score")))
            .print()
            .wait()
    )

    Jeremy

    #5445
    Avatar
    zoe_f
    Participant

    Hello Jeremy,

    Thank you so much for your response. That really does clarify why my .test.pressed wouldn’t be evaluated…there’s no time!

    However, I’ve tried implementing this, and the problem is that it still won’t read the .test.pressed line. Here’s my code: I implemented the .callback that you provided, and to narrow down what the problem was, I simplified the test.pressed to test for “F” and print a message when that is done.

    Template("recall_practice_stimuli.csv",
        row => 
        newTrial("recall-"+row.block,
        newVar("score", 0).global(), 
        newText(row.item)
            .center()
            .css("font-size", "2em")
    	.css("font-family", "verdana")
            .print()
        ,
        newText("instruction", "In which condition did you encounter this word in the experiment? Press the F KEY for INNER, the J KEY for OUTER, and the SPACEBAR for NEW WORD")
            .print()
        ,
        newTimer("window", 5000)
            .start()
        ,
        newKey("question1", "FJ ")
            .log()
            .callback(
                getText(row.item).remove()
                ,
                getText("instruction").remove()
                ,
                getKey("question1")
                    .test.pressed("F")
                    .success(newText("Good job!").print())
                ,
                getTimer("window").stop()
                )
        ,
        getTimer("window")
            .wait()
        )
        .log(row.item)
        .log(row.Group)
        .log(row.condition)
        .log(row.correctKey)
    );

    So, the problem is that when I press “F” at the Key Press, it just takes me to the next trial with no ‘Good job!’ output. I must be doing something wrong with the .callback element (I suspect I may be using the Timer element wrong which in turn impacts .callback?); any insight would be appreciated.

    Thank you so much for your replies so far!

    Best wishes, Zoë

    #5446
    Jeremy
    Jeremy
    Keymaster

    Hi Zoë,

    You Text element does get printed onto the page, but notice that you’re also ending the Timer element (early) at the same time, and there’s nothing left to do in your trial once the Timer has ended, so your script immediately goes to the next trial. Maybe this would make more sense:

    Template("recall_practice_stimuli.csv",
        row => 
        newTrial("recall-"+row.block,
        newVar("score", 0).global(), 
        newText(row.item)
            .center()
            .css("font-size", "2em")
    	.css("font-family", "verdana")
            .print()
        ,
        newText("instruction", "In which condition did you encounter this word in the experiment? Press the F KEY for INNER, the J KEY for OUTER, and the SPACEBAR for NEW WORD")
            .print()
        ,
        newTimer("window", 5000)
            .start()
        ,
        newKey("question1", "FJ ")
            .log()
            .callback(
                getText(row.item).remove()
                ,
                getText("instruction").remove()
                ,
                getTimer("window").stop()
            )
        ,
        getTimer("window")
            .wait()
        ,
        getKey("question1")
            .test.pressed("F")
            .success(
                newText("Good job!").print()
                ,
                newTimer(1000).start().wait()
            )
        )
        .log(row.item)
        .log(row.Group)
        .log(row.condition)
        .log(row.correctKey)
    );

    This way you leave 1s for your participant to read the “Good job!” feedback

    Jeremy

    #5542
    Avatar
    zoe_f
    Participant

    Hello again Jeremy,

    Thank you for this response.

    Unfortunately and mysteriously, the code above does not run as expected. It still goes directly to the next trial after pressing a valid key, meaning that even when outside of the .callback element, the getKey(“question1”) test does not run and no text is printed. (Like I mentioned in my last post, the text printing isn’t actually what I want to do, I’m just using it as a toy example to make it clearer what code should be running when. Eventually the ‘success’ test that I want to implement is whether they pressed the correct key, and then update the ‘score’ variable. But first I have to get a test command to actually run!).

    I must be using a Timer element wrong. The the only way I can get the test to run and the text to print (code below) is if I remove the getTimer(“window”).stop() from the .callback function, but then of course the trial continues for 5s even if a valid key is pressed, and of course it’s at the end of this 5s that the text prints (putting the getTimer(“window”).wait() after the getKey().test.pressed call also, naturally, results in no evaluation of the test.pressed function and immediately starts the next trial when a valid key is pressed, the same as the code in your last response).

    In any case, you’ve given quite a few responses to this so far, I totally understand if you don’t have time to give another response. I just figured I should give an update on what was/wasn’t working. I guess I’ll need to bump around the Timer commands and see what gives.

    Thank you so much!

    Zoë

    Template("recall_practice_stimuli.csv",
        row => 
        newTrial("recall-"+row.block,
        newVar("score", 0).global(),
        newText(row.item)
            .center()
            .css("font-size", "2em")
    	    .css("font-family", "verdana")
            .print()
        ,
        newText("instruction", "Which condition did you encounter this word experiment? Press the F KEY for INNER, the J KEY for OUTER, and the SPACEBAR for NEW WORD")
            .print()
        
        ,
        newTimer("window", 5000).start()
        ,
        newKey("question1", "FJ ")
            .log()
            .callback(
                getText(row.item).remove()
                ,
                getText("instruction").remove()
                
            )
         ,
        getTimer("window")
            .wait()    
        ,
        getKey("question1")
            .test.pressed("F")
            .success(
                newText("Good job!").print()
                ,
                newTimer(1000).start().wait()
        
            )
        )
        .log(row.item)
        .log(row.Group)
        .log(row.condition)
        .log(row.correctKey)
        .log("score", getVar("score"))
    );
    #5545
    Jeremy
    Jeremy
    Keymaster

    Hi Zoë,

    You code indeed shows the feedback text for me, but the code I gave also does so. Did you make sure to update to PennController 1.8? There was a bug with testing non-waitedKey elements in prior versions.

    And as you said, all of this is just to make sure you see the feedback text, but the code in this message still increments the Var element as expected (with 1.8 at least)

    Jeremy

    #5546
    Avatar
    zoe_f
    Participant

    Dear Jeremy,

    You are absolutely right, this was the problem! Thank you so much. My apologies for wasting your time on such a trivial fix; the update to 1.8 (which I thought I’d synced, but evidently not) was the issue, and indeed now the test runs, and the ‘score’ variable updates and prints perfectly.

    Thanks again,

    Zoë

Viewing 10 posts - 1 through 10 (of 10 total)

You must be logged in to reply to this topic.