List Sorting Tutorial (Millisecond Software)

Expert (1K reputation)Expert (1K reputation)Expert (1K reputation)Expert (1K reputation)Expert (1K reputation)Expert (1K reputation)Expert (1K reputation)Expert (1K reputation)Expert (1K reputation)
Group: Moderators
Posts: 6, Visits: 66
Some calculations, such as the calculation of medians require a sorted array of numerical values. And while Inquisit offers several built-in functions to calculate medians (e.g. trial.trialname.medianlatency)  these functions don't allow yet to distinguish between latencies of correct and incorrect responses.

The attached Millisecond tutorial script (ListSorting.iqx) offers one solution to this problem. The basic idea is to store all latencies of correct responses in an unsorted list (list.unsortedlist) and use a simple list sorting procedure to sort the list in ascending order into a sorted one (list.sortedlist). Once the list is sorted, the median can be calculated. In principle, script ListSorting.iqx could be used for any situation in which an ordered list of numerical values is necessary (not just for median calculations). Good news for Inquisit 5: Inquisit 5 will offer a built-in sorting function for lists!

(1) How to use ListSorting.iqx (does not require knowledge of the underlying sorting procedure)
Script "ListSorting.iqx" is written as an include script. Via the <include> element it can be included into any other script which makes its code accessible.

Example:  SimpleDemo.iqx, the second script in the attached zipfile. It includes script "ListSorting.iqx" via the <include> element.

/file = "ListSorting.iqx"

By including script ListSorting.iqx (has to be stored in the same folder) all elements of ListSorting.iqx are available to script SimpleDemo.iqx
and the code does not have to be rewritten.

The sample task of SimpleDemo.iqx is simple:
press 'R' on your keyboard if you see a red circle
press 'O' for any other color

Two trials are responsible for presenting the circles: trial.redcircle and trial.othercircle (not shown).

<trial redcircle>
/stimulusframes = [1 = redcircle]
/validresponse = (19, 24)
/correctresponse = (19)
/ontrialend = [if (trial.redcircle.correct) list.unsortedlist.insertitem(trial.redcircle.latency, 1)]

Trial.redcircle presents the red circles in this demo. Only if the response is correct (aka the R-key with scancode 19 is pressed), is the response latency stored in list.unsortedlist (the current latency is simply pushed into the first slot of the list).
/ontrialend = [if (trial.redcircle.correct) list.unsortedlist.insertitem(trial.redcircle.latency, 1)]

Even though list.unsortedlist was not explicitly defined in SimpleDemo.iqx, it can be used because script ListSorting.iqx was included via <include>.

Both trial.redcircle and trial.othercircle are called by block.categorization which calls 10 of each in random order:
<block categorization>
/trials = [1-20 = noreplace(redcircle, othercircle)]

The <expt> element calls block.categorization, followed by block.sorting. Again, even though block.sorting was not explicitly defined in SimpleDemo.iqx, it can be used because script List.Sorting.iqx was included via <include>.
<expt >
/blocks = [1 = categorization; 2 = sorting]

Note: Block.sorting is run only after all trials have been run - there is no trial by trial updating of list.sortedlist. With a little tweaking, this would also be possible.

Block.sorting runs the sorting algorithm that sorts the unordered latencies in ascending order (if interested in the idea underlying the sorting procedure check out "Implementation of Sorting Procedure" below). Using the sorted list, script.listsorting then further calculates the median latency of correct responses (expressions.medianRT) which is accessible to SimpleDemo.iqx and can be used in its <summarydata> element:
<summarydata >
/file = "ListSorting_summary.iqdat"
/columns = [script.startdate, script.starttime, script.subjectid, script.groupid, script.elapsedtime,
block.categorization.medianlatency, expressions.medianRT, expressions.maxRT, expressions.minRT]

block.categorization.medianlatency (built-in function) stores the median latency based on correct and incorrect responses and
expressions.medianRT stores the median latency of correct responses only.

(2) Implementation of the List Sorting Procedure in ListSorting.iqx
The actual procedure to sort the unordered list (list.unordered) of latencies is carried out by two trials in ListSorting.iqx
<trial sortingA>
/ontrialbegin = [values.j += 1]
/ontrialbegin = [values.sortitem = list.unsortedlist.nextvalue]
/trialduration = 0
/branch = [if (values.j <= list.unsortedlist.itemcount) {values.i = 0; trial.sortingB}]
/recorddata = false

Trial.sortingA picks the next value from list.unsortedlist (values.sortitem) and calls trial.sortingB to find its sorted position in list.sorted.

<trial sortingB>
/ontrialbegin = [values.i += 1]
/branch = [if (list.sortedlist.itemcount == 0) {list.sortedlist.insertitem(values.sortitem, 1); trial.sortinga}]
/branch = [if (values.sortitem <= list.sortedlist.item(values.i)) {list.sortedlist.insertitem(values.sortitem, values.i); trial.sortinga}]
/branch = [if (values.i < list.sortedlist.itemcount) trial.sortingb]
/branch = [{list.sortedlist.insertitem(values.sortitem, list.sortedlist.itemcount + 1); trial.sortinga}]
/trialduration = 0
/recorddata = false

Trial.sortingB retrieves the first item from list.sorted and compares it to values.sortitem. If values.sortitem is bigger, trial.sortingB calls itself once more retrieving the second item from list.sorted and so on until its correct position is found.
Once that position is found, trial.sortingA is called again to retrieve the next item from list.unsorted (if any is left) and the process is started over until all items of list.unsorted are correctly sorted into list.sorted.

Please, let us know if you have any questions.

katja from Millisecond Software

Attachments (443 views, 3.00 KB)
Edited 8 Years Ago by katbo

Merge Selected

Merge into selected topic...

Merge into merge target...

Merge into a specific topic ID...

Reading This Topic