psychopy.org | Reference | Downloads | Github

Code Component Translation to JS

I have a code segment in my project that is set to Auto → JS because I am trying to get my study online to pavlovia. However, I am getting the error “/* Syntax Error: Fix Pyth code */”. I know that the issue is with the tuple code ’ for word,tag in pairs: ’ but I don’t know how to write the respective code in JS. Does anyone know how to do this in JS?

Here is the code:

thisExp.addData("typedWord", text_6.text)

displayed_text = text_6.text
print(displayed_text)

sentences = nltk.word_tokenize(displayed_text)
words = [nltk.word_tokenize(word) for word in sentences]
tagged_words = [nltk.pos_tag(sent) for sent in words] #tagged_words is a list of lists of tuples (ordered pairs basically)
print(tagged_words)

#make an empty freqDist object
tags = nltk.FreqDist()
        
#for each list in tagged words, get the (word, tag) tuple, ex. (action, 'NN')
# 'NN' is the tag in this case
for pairs in tagged_words:
    for word,tag in pairs:
        #add 1 to the counts for each tag
        tags[tag] += 1
        
#how to get (and print) the frequency of 'NN's
print(tags.freq('CC'))
        
#how to print the FreqDist object
print(tags.most_common())
        
#sums up the desired frequencies, k is the 'NN' or 'VRB' or whatever
freq_sum = 0

for k in tags:
    #if it starts with capital n, its a noun, change this to 'V' if u want verbs
    if(k.startswith('CC')):
        freq_sum += tags.freq(k)
print("Frequency: ", freq_sum)
print("Frequency (as %): ", round((freq_sum*(100)),2))
    
if hcount <= 3 and freq_sum >= 0.1:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <=6 and freq_sum >= 0.15:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <=9 and freq_sum >= 0.2:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <=12 and freq_sum >= 0.25:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <=15 and freq_sum >= 0.3:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <= 18 and freq_sum >= 0.35:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <= 21 and freq_sum >= 0.4:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <= 24 and freq_sum >= 0.45:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <= 27 and freq_sum >= 0.5:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <= 30 and freq_sum >= 0.55:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <= 33 and freq_sum >= 0.6:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <= 36 and freq_sum >= 0.65:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <= 39 and freq_sum >= 0.7:
    nextRoutineNreps = 1
    hcount+=1
else:
    nextRoutineNreps = 0

What does for word,tag in pairs: do in Python?

It uses the natural language toolkit documentation which can be found here: (Installing NLTK Data — NLTK 3.5 documentation) and returns each word the participant types followed by the tagged part of speech of the word. For example, if the participant writes, “running”, the output would be ‘running’, ‘VB’ (VB = verb). We are using these tags and evaluating them in order to present reinforcement if the participant uses a certain threshold of verbs or adjectives (changes based on the condition).

Aha. OK, I first was thinking of giving some tips on how to write that loop in JS, but I guess you’ve got a bigger nut to crack: that NLTK library is in Python, not JS, so I won’t run in your browser out-of-the-box right?

1 Like

You’re probably right, we hadn’t even thought about that… we will have to find a way to workaround that issues. One of the other versions of our experiment does not use NLTK and is also exhibiting a similar error code, would you be able to help with that? For this code, I know the error is in the line: ‘average_word_length = sum(len(word) for word in words) / len(words)’

thisExp.addData("typedWord", text_8.text)

displayed_text = text_8.text
words = displayed_text.split()

if len(words) >= 1:
    average_word_length = sum(len(word) for word in words) / len(words)
    print(average_word_length)
else: 
    average_word_length = 0

if hcount <= 3 and average_word_length <= 4 and average_word_length>=1:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <=6 and average_word_length <= 3.75 and average_word_length>=1:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <=9 and average_word_length <= 3.5 and average_word_length>=1:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <=12 and average_word_length <= 3.25 and average_word_length>=1:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <=15 and average_word_length <= 3 and average_word_length>=1:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <=18 and average_word_length <= 2.75 and average_word_length>=1:
    nextRoutineNreps = 1
    hcount+=1
elif hcount <=21 and average_word_length <= 2.5 and average_word_length>=1:
    nextRoutineNreps = 1
    hcount+=1
else:
    nextRoutineNreps = 0

If you write the loop like this translation will probably work out:

for word in words:
print('something here')

If you mean put that code before the if len(words) >= 1 line, that did not work.

In this line…
sum(len(word) for word in words) / len(words)

You’re trying to calculate an average via a loop. Instead of writing the loop like that, writing it like this should work:

for word in words:
  print('here we are looping')

Now, for how you’d exactly use a loop like this to calculate an average, I refer to DuckDuckGo :wink:

I tried this method with the following code:

if len(words) >= 1:
    for word in words:
        average_word_length = sum(len(word)) / len(words)
    print(average_word_length)
else: 
    average_word_length = 0

However, now I am getting the error: TypeError: ‘int’ object is not iterable

Try

print(words)

totalLength=0
averageLength=0
if len(words):
     for word in words:
          totalLength+=len(word)
     averageLength=totalLength/len(words)


That worked! Thank you for the help.

1 Like

Hi, I ended up using the following JS code that is attached below. It solved the errors, but when piloting the experiment, I realized it was counting all the characters in the entire text the participant typed, instead of calculating the average word length within the text they submitted. Any suggestions?

totalLength = 0;
if ((words.length >= 1)) {
    for (var word, _pj_c = 0, _pj_a = words, _pj_b = _pj_a.length; (_pj_c < _pj_b); _pj_c += 1) {
        word = _pj_a[_pj_c];
        totalLength += word.length;
    }
    average_word_length = (totalLength / words.length);
} else {
    average_word_length = 0;
}

I think that your issue is that you aren’t telling PsychoPy to split by spaces. Try .split(“ “) as per my crib sheet.