/*
    File:               vpl_data.c
    Author:             michael stevens
    Experiment:         Viewing position effect (letters in string)
                        Stevens & Grainger 2003, Xpt. 1

        Data-management and randomization

            Between:    String length (5/7)
                        Mask type (for 7-letter strings)
                        Mask order (for 5-letter strings)
                        Stimulus duration (determined in the practice phase using a tracking procedure)
            
            Within:     Mask type (for 5-letter strings (block variable))
                        Position letter in string (5/7) - relative to centre of string
                        Location string on screen (5/7)
                        Target letter (15)
            
            Derived variables:
                        Position target letter in string (relative to 1st letter)
                        Fixation position
                        Location target letter on screen (5/7 * 2 - 1)
            
            Measured variables:
                        Response                         
                        (Reaction time)
            
            Tracking procedure practice trials:
                        only the 3 central fixation and letter positions are used
                        every 9 trials ther presentation duration can be adjusted
                            >70% correct identification: presentation duration -= 16ms (min 50ms)
                            <60%: presentation duration += 16ms (max 100ms)
                        if presentation time is stable for 4 blocks -> end of the practice
                        maximum duration practice phase: 15 * 9 trials
                        
*/

#include <tscope.h>

// number of levels of each variable
#define SLEN        2
#define MASK        2
#define MASK1       2

#define LP5         5
#define LP7         7
#define LPPRACT     3

#define SL5         5
#define SL7         7
#define SLPRACT     3

#define TARGET     15

// number of trials
#define CELLS5      (LP5*SL5*TARGET)
#define NTRIALS5    (CELLS5*MASK)
#define CELLS7      (LP7*SL7*TARGET)
#define NTRIALS7    (CELLS7)

#define CELLSPRACT    (LPPRACT*SLPRACT)
#define NBLOCKPRACT    15
#define NTRIALSPRACT  (CELLSPRACT*NBLOCKPRACT)

#define MAXTRIALS   (NTRIALSPRACT+NTRIALS5) // more trials in the 5 letter condition


// data structure with all trial variables
struct {
    int session;
    int subj;

    enum { FIVE, SEVEN } slen;
    enum mtype { SMALL, LARGE } mask1;  // mask type 1st block

    int stime;                  // stimulus duration

    enum { PRACT, EXP } phase;
    int block;                  // 2 blocks in 5letter-exp
    enum mtype mask;            // mask type in this block

    int lpos;                   // position letter in string (relative to centre of string)
    int sloc;                   // location string on screen (relative to fixation point)
    int lnr;                    // position letter in string (relative to 1st letter)
    int fpos;                   // fixation position on screen
    int lloc;                   // location target letter on screen (relative to fixation)
    int targetno;
    char target;

    char r;                     // response
    enum { E, C } corr;         // feedback

    int rt, re;                 // rt and measurement error

} data[MAXTRIALS];


// all possible targets 
char alltargets[15] =
    { 'B', 'C', 'D', 'F', 'H', 'G', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S',
    'T'
};

void initdata()
{
    int i;
    for (i = 0; i < MAXTRIALS; i++) {
        data[i].session = -1;
        data[i].subj = -1;
        data[i].slen = -1;
        data[i].mask1 = -1;
        data[i].stime = -1;
        data[i].phase = -1;
        data[i].block = -1;
        data[i].mask = -1;
        data[i].lpos = -1;
        data[i].sloc = -1;
        data[i].lnr = -1;
        data[i].fpos = -1;
        data[i].lloc = -1;
        data[i].targetno = -1;
        data[i].target = 'X';
        data[i].r = 'Y';
        data[i].corr = -1;
        data[i].rt = -1;
        data[i].re = -1;
    }
}


// write data
void writedata()
{
    // use session nr to determine filename
    char fname[40];
    sprintf(fname, "vpl%03d.dat", data[0].session);

    // open file
    FILE *fp;
    fp = fopen(fname, "a+");

    if (fp == NULL) {
        printf("error opening output file %s.\n", fname);
        exit(EXIT_FAILURE);
    }
    // determine length data file
    int ntrials;
    if (data[0].slen == FIVE)
        ntrials = NTRIALSPRACT + NTRIALS5;
    else
        ntrials = NTRIALSPRACT + NTRIALS7;

    // write trial info
    int i;
    for (i = 0; i < ntrials; i++) {

        fprintf(fp, "%d ", data[i].session);
        fprintf(fp, "%d ", data[i].subj);
        fprintf(fp, "%d \t", data[i].slen);

        fprintf(fp, "%d ", data[i].mask1);
        fprintf(fp, "%d \t", data[i].stime);

        fprintf(fp, "%03d ", i);
        fprintf(fp, "%d ", data[i].phase);
        fprintf(fp, "%d ", data[i].block);
        fprintf(fp, "%d \t", data[i].mask);

        fprintf(fp, "%+d ", data[i].lpos);
        fprintf(fp, "%+d ", data[i].sloc);
        fprintf(fp, "%d ", data[i].lnr);
        fprintf(fp, "%d ", data[i].fpos);
        fprintf(fp, "%+d ", data[i].lloc);
        fprintf(fp, "%2d ", data[i].targetno);
        fprintf(fp, "%c ", data[i].target);

        fprintf(fp, "%c \t", data[i].r);
        fprintf(fp, "%d ", data[i].corr);
        fprintf(fp, "%d ", data[i].rt);
        fprintf(fp, "%d ", data[i].re);

        fprintf(fp, "\n");
    }

    // close file
    fclose(fp);
}


#define RNDTEST 0
void randomize(int subj, int slen)
{
    // initialize
    initdata();

    // determine length data file
    int ntrials;
    if (slen == FIVE)
        ntrials = NTRIALSPRACT + NTRIALS5;
    else
        ntrials = NTRIALSPRACT + NTRIALS7;

    // random list
    int i, tmplist[MAXTRIALS];


    if (RNDTEST) {              // predictable list during programming
        for (i = 0; i < NTRIALSPRACT; i++)
            tmplist[i] = i % CELLSPRACT;
        for (i = NTRIALSPRACT; i < ntrials; i++) {
            if (slen == FIVE)
                tmplist[i] = i - NTRIALSPRACT % CELLS5;
            else
                tmplist[i] = i - NTRIALSPRACT % CELLS7;
        }
    } else {                    // random list for the real exp
        // practice: 15 blocks of 9 trials
        for (i = 0; i < NBLOCKPRACT; i++)
            ts_rlist(CELLSPRACT, 1, &tmplist[0 + i * CELLSPRACT]);

        if (slen == 5) {
            ts_rlist(CELLS5, 1, &tmplist[NTRIALSPRACT]);
            ts_rlist(CELLS5, 1, &tmplist[NTRIALSPRACT + CELLS5]);
        } else {
            ts_rlist(CELLS7, 1, &tmplist[NTRIALSPRACT]);
        }
    }

    for (i = 0; i < ntrials; i++) {
        data[i].session = slen * 100 + subj;
        data[i].subj = subj;
        data[i].slen = slen;
        data[i].mask1 = slen % MASK;
        data[i].stime = 6;      // 6 syncs (@ 60Hz -> 100ms)

        // phase
        if (i < NTRIALSPRACT)
            data[i].phase = PRACT;
        else
            data[i].phase = EXP;

        // block
        if (i < NTRIALSPRACT)
            data[i].block = 0;
        else {
            if (slen == 7)
                data[i].block = 1;
            if (slen == 5 && i - NTRIALSPRACT < CELLS5)
                data[i].block = 1;
            else
                data[i].block = 2;
        }

        // mask
        if (data[i].block < 2)
            data[i].mask = data[i].mask1;
        else
            data[i].mask = !data[i].mask1;

        // lpos and sloc
        if (data[i].phase == PRACT) {
            data[i].lpos = (tmplist[i] % LPPRACT) - 1;
            data[i].sloc = ((tmplist[i] / LPPRACT) % SLPRACT) - 1;
            int t = ts_rint(TARGET);
            data[i].target = alltargets[t];
        } else {
            if (data[i].slen == 5) {
                data[i].lpos = (tmplist[i] % LP5) - 2;
                data[i].sloc = ((tmplist[i] / LP5) % SL5) - 2;
                data[i].lnr = data[i].lpos + 3;
                data[i].fpos = -data[i].sloc + 3;
                data[i].targetno = ((tmplist[i] / LP5 / SL5) % TARGET) + 1;
                data[i].target = alltargets[data[i].targetno - 1];
            } else {
                data[i].lpos = (tmplist[i] % LP7) - 3;
                data[i].sloc = ((tmplist[i] / LP7) % SL7) - 3;
                data[i].lnr = data[i].lpos + 4;
                data[i].fpos = -data[i].sloc + 4;
                data[i].targetno = ((tmplist[i] / LP7 / SL7) % TARGET) + 1;
                data[i].target = alltargets[data[i].targetno - 1];
            }
        }

        //lloc
        data[i].lloc = data[i].lpos + data[i].sloc;
    }
}

// adjust stimulus time
// function has to be called *before* the trial

#define CONTINUE 0
#define STOP 1

int adjust_stime(int i)
{
    static int same_stime = 1;
    if (i % CELLSPRACT == 0 && i > 0 && i < NTRIALSPRACT) {
        int j, corr = 0, new_stime;

        for (j = i - 9; j < i; j++)
            corr += data[i].corr;

        if (corr > 6)           // 70% out of 9 = 6.3
            new_stime = data[i - 1].stime--;

        if (corr < 6)           // 60% out of 9 = 5.4
            new_stime = data[i - 1].stime++;

        if (new_stime > 6)
            new_stime = 6;

        if (new_stime < 3)
            new_stime = 3;

        if (new_stime == data[i - 1].stime)
            same_stime++;
        else
            same_stime = 1;

        // adjust stimulus time for future trials
        for (j = i; j < MAXTRIALS; j++)
            data[j].stime = new_stime;
    }

    if (same_stime >= 4)
        return STOP;
    else
        return CONTINUE;
}


// test-function that generates 1 data file
#ifndef VPL_TRIAL_C
int main()
{
    randomize(0, 5);
    writedata();
    return 0;
}

END_OF_MAIN();
#endif                          // VPL_TRIAL_C


top
Persoonlijke pagina Universiteit GentTscope
Allegro | Cygwin | Gcc
© See license.html for copyright information