In this document we will be taking a look at creating stimlists for Stekic, Nielsen, & Kovic

Note that this is the basic version of this markdown file- the full version will have a function call and produce multiple stimlists, for all 9 experimental conditions

This experiment will be an extension of the protocol use by Lupyan et al. (2007)

Images

In a previous script, we went from a large number of image seeds down to a set of 40 total images- 20 jagged and 20 curvy.

The data for these files has been saved as a .csv called “ImageStims”, so we have to start by loading that in here

ImageStims <- read.csv("F:/Experiments/Collaborations/Stekic et al/Figures/ChosenImages.csv")

Conditions

Lupyan’s previous work used on a few conditions - these were informative, but not as informative as we would like them to be

So we have conceived of 9 Conditions, but it’s not a totally crossed design (it’s a 2(Category label vs. Systematic individual label) x 3 (Congruent vs. Incongruent vs. Conventional) + 3 (Arbitrary Halfhalf, Arbitrary Full, and No Names)) design

1- Category Label - Congruent 2- Category Label - Incongruent 3- Category Label - Arbitrary

4- Systematic Label - Congruent 5- Systematic Label - Incongruent 6- Systematic Label - Conventional

7- Arbitrary Label (halfhalf) 8- Arbitrary Label (fully)

9- No Labels

Label Stimuli

All labels will be cVcV bisyllables.

Broadly, there are a total of 4 kinds of labels to be created

Curvy Labels Jagged Labels Conventional Labels I Conventional Labels II

To create these words we need sets of phonemes

Minimally we need 8 consonants and 4 vowels, but 8 vowels may be best (as in Nielsen, 2016).

However I understand that Serbian only has 5 basic vowels, so we may need to make due!

SonorantCons <- c('m', 'n', 'l')
PlosiveCons <- c('p', 't', 'k')
Conv1Cons <- c('f', 'v', 'sh')
Conv2Cons <- c('s', 'z', 'h')

Now we want to take all permutations of our consonant sets and vowel sets to produce the sets of syllables that we will need for the experiment

Vowels <- c("a", 'a:')

########
PlosiveSyll1 <- as.vector(outer(PlosiveCons[c(1,2)], Vowels, paste, sep=""))
PlosiveSyll2 <- as.vector(outer(PlosiveCons[c(1,3)], Vowels, paste, sep=""))
PlosiveSyll3 <- as.vector(outer(PlosiveCons[c(2,3)], Vowels[1], paste, sep=""))

PlosiveWords12 <- as.vector(outer(PlosiveSyll1, PlosiveSyll2, paste, sep=''))
PlosiveWords <- as.vector(outer(PlosiveWords12, PlosiveSyll3, paste, sep=''))

PlosiveWords
##  [1] "papata"   "tapata"   "pa:pata"  "ta:pata"  "pakata"   "takata"  
##  [7] "pa:kata"  "ta:kata"  "papa:ta"  "tapa:ta"  "pa:pa:ta" "ta:pa:ta"
## [13] "paka:ta"  "taka:ta"  "pa:ka:ta" "ta:ka:ta" "papaka"   "tapaka"  
## [19] "pa:paka"  "ta:paka"  "pakaka"   "takaka"   "pa:kaka"  "ta:kaka" 
## [25] "papa:ka"  "tapa:ka"  "pa:pa:ka" "ta:pa:ka" "paka:ka"  "taka:ka" 
## [31] "pa:ka:ka" "ta:ka:ka"
###############
SonorantSyll1 <- as.vector(outer(SonorantCons[c(1,2)], Vowels, paste, sep=""))
SonorantSyll2 <- as.vector(outer(SonorantCons[c(1,3)], Vowels, paste, sep=""))
SonorantSyll3 <- as.vector(outer(SonorantCons[c(2,3)], Vowels[1], paste, sep=""))

SonorantWords12 <- as.vector(outer(SonorantSyll1, SonorantSyll2, paste, sep=''))
SonorantWords <- as.vector(outer(SonorantWords12, SonorantSyll3, paste, sep=''))

SonorantWords
##  [1] "mamana"   "namana"   "ma:mana"  "na:mana"  "malana"   "nalana"  
##  [7] "ma:lana"  "na:lana"  "mama:na"  "nama:na"  "ma:ma:na" "na:ma:na"
## [13] "mala:na"  "nala:na"  "ma:la:na" "na:la:na" "mamala"   "namala"  
## [19] "ma:mala"  "na:mala"  "malala"   "nalala"   "ma:lala"  "na:lala" 
## [25] "mama:la"  "nama:la"  "ma:ma:la" "na:ma:la" "mala:la"  "nala:la" 
## [31] "ma:la:la" "na:la:la"
################
Conv1Syll1 <- as.vector(outer(Conv1Cons[c(1,2)], Vowels, paste, sep=""))
Conv1Syll2 <- as.vector(outer(Conv1Cons[c(1,3)], Vowels, paste, sep=""))
Conv1Syll3 <- as.vector(outer(Conv1Cons[c(2,3)], Vowels[1], paste, sep=""))

Conv1Words12 <- as.vector(outer(Conv1Syll1, Conv1Syll2, paste, sep=''))
Conv1Words <- as.vector(outer(Conv1Words12, Conv1Syll3, paste, sep=''))

Conv1Words
##  [1] "fafava"     "vafava"     "fa:fava"    "va:fava"    "fashava"   
##  [6] "vashava"    "fa:shava"   "va:shava"   "fafa:va"    "vafa:va"   
## [11] "fa:fa:va"   "va:fa:va"   "fasha:va"   "vasha:va"   "fa:sha:va" 
## [16] "va:sha:va"  "fafasha"    "vafasha"    "fa:fasha"   "va:fasha"  
## [21] "fashasha"   "vashasha"   "fa:shasha"  "va:shasha"  "fafa:sha"  
## [26] "vafa:sha"   "fa:fa:sha"  "va:fa:sha"  "fasha:sha"  "vasha:sha" 
## [31] "fa:sha:sha" "va:sha:sha"
################
Conv2Syll1 <- as.vector(outer(Conv2Cons[c(1,2)], Vowels, paste, sep=""))
Conv2Syll2 <- as.vector(outer(Conv2Cons[c(1,3)], Vowels, paste, sep=""))
Conv2Syll3 <- as.vector(outer(Conv2Cons[c(2,3)], Vowels[1], paste, sep=""))

Conv2Words12 <- as.vector(outer(Conv2Syll1, Conv2Syll2, paste, sep=''))
Conv2Words <- as.vector(outer(Conv2Words12, Conv2Syll3, paste, sep=''))

Conv2Words
##  [1] "sasaza"   "zasaza"   "sa:saza"  "za:saza"  "sahaza"   "zahaza"  
##  [7] "sa:haza"  "za:haza"  "sasa:za"  "zasa:za"  "sa:sa:za" "za:sa:za"
## [13] "saha:za"  "zaha:za"  "sa:ha:za" "za:ha:za" "sasaha"   "zasaha"  
## [19] "sa:saha"  "za:saha"  "sahaha"   "zahaha"   "sa:haha"  "za:haha" 
## [25] "sasa:ha"  "zasa:ha"  "sa:sa:ha" "za:sa:ha" "saha:ha"  "zaha:ha" 
## [31] "sa:ha:ha" "za:ha:ha"

The only extra bit that we need to do here is eliminate some words that have meanings in Serbian already

Fortunately there are only two of them

ToExclude <- c('papaka', 'pa:paka')
PlosiveWords <- setdiff(PlosiveWords, ToExclude)

And then a tiny bit of code just deleting all of the stored vectors and data frames that we no longer need

rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList, Chosen, Chosen1JC, Chosen1Num, Chosen2JC, Chosen2Num, Chosen3JC, Chosen3Num, Chosen4JC, Chosen4Num, ChosenSplit, Conv1Cons, Conv1Syll1, Conv1Syll2, Conv1Syll3, Conv1Words12, Conv2Cons, Conv2Syll1, Conv2Syll2, Conv2Syll3, Conv2Words12, SonorantCons, SonorantSyll1, SonorantSyll2, SonorantSyll3, SonorantWords12, filelist, FilesToDelete, FilesToKeep, PlosiveCons, PlosiveSyll1, PlosiveSyll2, PlosiveSyll3, PlosiveWords12, list, NewNames, newnames, oldnames, OriginalNames, ToExclude, Vowels)
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'chosen' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen1' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen2' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen3' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen4' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'BalanceList' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen1JC' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen1Num' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen2JC' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen2Num' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen3JC' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen3Num' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen4JC' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'Chosen4Num' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'ChosenSplit' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'filelist' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'FilesToDelete' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'FilesToKeep' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'list' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'NewNames' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'newnames' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'oldnames' not found
## Warning in rm(chosen, Chosen1, Chosen2, Chosen3, Chosen4, BalanceList,
## Chosen, : object 'OriginalNames' not found

Trial Structuring

Each participant uses 16 microbes for Training, 24 microbes total

This means that they need 8 “jagged” and 8 “curvy microbes” for training- 2 of each ‘subtype’ (Overall 12 jagged and 12 curvy, 3 of each subtype)

lister = 1:5

Chosen1 <- sample(lister, 3)
Chosen1 <- c(Chosen1, (Chosen1 +5))

Chosen2 <- sample(lister, 3)
Chosen2 <- c(Chosen2, (Chosen2 +5))

Chosen3 <- sample(lister, 3)
Chosen3 <- c(Chosen3, (Chosen3 +5))

Chosen4 <- sample(lister, 3)
Chosen4 <- c(Chosen4, (Chosen4 +5))

ChosenImages <- ImageStims[c(Chosen1, Chosen2+10, Chosen3+20, Chosen4+30),]

StarterImages <- ChosenImages[c(1,2,4,5,7,8,10,11,13,14,16,17,19,20,22,23),]
SecondaryImages <- ChosenImages[c(3,6,9,12,15,18,21,24),]

We now have all of the images chosen for a given participant

We just need to choose what words will be used for each participant NOTE- When I write this properly as a function call we will need to include a specification of the CONDITION in the function call- because what condition a participant is in determines what words are assigned to what images

As we are writing this basic version for Condition 4 (Systematic + Congruent) we need to select 12 Jagged Words and 12 Curvy Words

PlosiveSelected <- sample(PlosiveWords, 12)
SonorantSelected <- sample(SonorantWords, 12)

PlosiveStarter <- PlosiveSelected[1:8]
PlosiveSecondary <- PlosiveSelected[9:12]
SonorantStarter <- SonorantSelected[1:8]
SonorantSecondary <- SonorantSelected[9:12]

Now we need to pair our Words and our Images

First we

StarterJagged <- subset(StarterImages, Shape == "J" )
StarterCurved <- subset(StarterImages, Shape == "C" )
StarterJagged <- subset(as.data.frame(cbind(StarterJagged, PlosiveStarter)), select = c("NewName", "PlosiveStarter"))
StarterCurved <- subset(as.data.frame(cbind(StarterCurved, SonorantStarter)), select = c("NewName", "SonorantStarter"))
colnames(StarterJagged) <- c('Image', "Label")
colnames(StarterCurved) <- c('Image', "Label")

SecondaryJagged <- subset(SecondaryImages, Shape == "J")
SecondaryCurved <- subset(SecondaryImages, Shape == "C")
SecondaryJagged <- as.data.frame(cbind(SecondaryJagged$NewName, PlosiveSecondary))
SecondaryCurved <- as.data.frame(cbind(SecondaryCurved$NewName, SonorantSecondary))
colnames(SecondaryJagged) <- c('Image', "Label")
colnames(SecondaryCurved) <- c('Image', "Label")

StarterPairs <- rbind(StarterJagged, StarterCurved)
SecondaryPairs <- rbind(SecondaryJagged, SecondaryCurved)

rm(Chosen1J, ChosenImages, ImageStims, ImageStims1, ImageStims2, ImageStims3, ImageStims4, SecondarySonorant, SecondaryImages, SecondaryPlosive, StarterSonorant, StarterImages, StarterPlosive, Type1chosen, Type2chosen, Type3chosen, Type4chosen, Chosen1, Chosen2, Chosen3, Chosen4, SonorantSecondary, SonorantSelected, SonorantStarter, ImageSplit, PlosiveSecondary, PlosiveSelected, PlosiveStarter,lister, x, Conv1Words, Conv2Words, PlosiveWords, SonorantWords)

So now we have our lists of paired Labels and Images… that was a ton of work eh?

Now we can actually set up the trial structure

niiiiiiicee…

There are 9 Training Blocks

In each of the 9 training blocks participants see all 16 of the images (in Randomized Order)

During training they are asked whether they would approach or avoid the microbe. There are four canonical directions that the astrobiologist might approach a microbe from- the left, right, up, or down (and thus, “approaching” is a different response on each type of trial)

The position (and direction of approach) of the astromicrobiologist is counterbalanced - so on a given block each direction of approach is used 4 times

StimList <- rbind((StarterPairs[sample(nrow(StarterPairs)),]),(StarterPairs[sample(nrow(StarterPairs)),]), (StarterPairs[sample(nrow(StarterPairs)),]), (StarterPairs[sample(nrow(StarterPairs)),]), (StarterPairs[sample(nrow(StarterPairs)),]), (StarterPairs[sample(nrow(StarterPairs)),]), (StarterPairs[sample(nrow(StarterPairs)),]), (StarterPairs[sample(nrow(StarterPairs)),]), (StarterPairs[sample(nrow(StarterPairs)),]))
StimList$TrialNum <- 1:144

StimList$TrialType <- "Training"

StimList$Block <- rep(1:9, each=16)

StimList$BlockTrial <- rep(1:16, 9)

Condition <- 4 ## Comment this out or delete it once you functionalise this code
StimList$Condition <- Condition

library(tidyr)
StimList <- separate(data = StimList, col = Image, into = c('ImageSeed', 'ImageShape', "ImageCurviness", "ImageType"), sep = "-", remove = FALSE)

StimList$LabelType <- substring(StimList$Label, 1, 1)

library(plyr)
StimList$LabelType <- mapvalues(StimList$LabelType,
                                from = c('m', 'n', 'p', 't', 'f', 'v', 's', 'z'),
                                to = c('S', 'S', 'P', 'P', 'C1', 'C1', 'C2', 'C2'))
## The following `from` values were not present in `x`: f, v, s, z
Locations <- c('Left', 'Right', 'Up', 'Down')
Locations <- c(Locations, Locations, Locations, Locations)
StimList$Location <- c(sample(Locations), sample(Locations), sample(Locations), sample(Locations), sample(Locations), sample(Locations), sample(Locations), sample(Locations), sample(Locations))

StimList$Approach <- mapvalues(StimList$Location,
                               from = c('Left', 'Right', 'Up', 'Down'),
                               to = c(39, 37, 40, 38))

StimList$Retreat <- mapvalues(StimList$Location,
                               from = c('Left', 'Right', 'Up', 'Down'),
                               to = c(37, 39, 38, 40))

SubConditions <- c('J', 'C')
StimList$SubCondition <- sample(SubConditions, 1)

StimList$CorrectResponse <- ifelse(StimList$ImageShape == StimList$SubCondition, StimList$Approach, StimList$Retreat)

setwd('F:/Experiments/Collaborations/Stekic et al/Data/Stimlists/')
write.csv(StimList, "StimList-Sample.csv")

So, that’s everything that we need for a stimlist, and the stimlist has been saved as a “.csv”, which can be read in by jsPsych.