Multiple outputs with a for loop in praat - loops

I have a script where I have multiple folders each with three audio files in them ID#_1, ID#_2, and ID#_3. The user can input a string of different ID#s, one after the other, and then the script recognizes the different IDs and runs the code for each of them.
I have a for loop set up for this -
form Settings
comment Enter the IDs of the different subjects
sentence subjectIDs
endform
numOfSubjects = length(subjectIDs$)/4
for i from 0 to (numOfSubjects - 1)
subjectID$ = mid$(subjectIDs$, 1 + 4*i, 4 + 4*i)
outFile$ = subjectID$ + "/SubjectResponseOnsets" + subjectID$ + ".txt"
path$ = subjectID$ + "/" + subjectID$
#firstOutput
#secondOutput
#thirdOutput'
Each of these procedures is defined previously in the code, and they basically output certain ranges from the audio files out to a text file.
The code seems to work fine and generate the output file correctly when one ID is given, but when I try to run it with more than one ID at a time, only the text file for the first ID is outputted.
The for loop does not seem to be working well, but the code does work fine in the first run.
I would greatly appreciate any help!

I don't know if I understood well what your script was trying to do, since the snippet you pasted was incomplete. It's best if you provide code that is executable as is. In this case, you were missing the closing endfor, and you were calling some procedures that were not defined in your snippet (not even as placeholders). I had to write some dummy procedures just to make it run.
Since you also didn't say how your script was failing, it was unclear what needed to be fixed. So I took a stab at making it work.
It sounded as if your ID splitting code was giving you some problems. I took the split procedure from the utils plugin available through CPrAN, which makes inputting the IDs easier (full disclosure: I wrote that plugin).
form Settings
comment Enter the IDs of the different subjects
sentence subjectIDs 01 02 03
endform
#split: " ", subjectIDs$
numOfSubjects = split.length
for i to numOfSubjects
subjectID$ = split.return$[i]
path$ = subjectID$
outFile$ = path$ + "/SubjectResponseOnsets" + subjectID$ + ".txt"
# Make sure output directory exists
createDirectory: path$
#firstOutput
#secondOutput
#thirdOutput
endfor
procedure firstOutput ()
appendFileLine: outFile$, "First"
endproc
procedure secondOutput ()
appendFileLine: outFile$, "Second"
endproc
procedure thirdOutput ()
appendFileLine: outFile$, "Third"
endproc
# split procedure from the utils CPrAN plugin
# http://cpran.net/plugins/utils
procedure split (.sep$, .str$)
.seplen = length(.sep$)
.length = 0
repeat
.strlen = length(.str$)
.sep = index(.str$, .sep$)
if .sep > 0
.part$ = left$(.str$, .sep-1)
.str$ = mid$(.str$, .sep+.seplen, .strlen)
else
.part$ = .str$
endif
.length = .length+1
.return$[.length] = .part$
until .sep = 0
endproc
If this is not what you are having trouble with, you'll have to be more specific.

Related

Small Basic: How can I split words in an external text file into a list?

I'm trying to bring in a simple list of 10 words (without commas) on 10 lines and save them as a list or array in Small Basic.
I know I need to loop through all the lines in the file but I can only get it to do it with individual letters.
I've got this far so far
OpenFile = File.ReadContents("example.txt")
For i = 1 To Text.GetLength(OpenFile)
WordList[i] = Text.GetSubText(OpenFile, i, 5)
EndFor
TextWindow.Write(WordList)
I haven't got any further than this and not sure where to go to from here.
YOu could use readline to get all the characters/words/sentence in a line, this is an example, its not complete but it gives the idea of what it is you need,
'SAVE THE PROGRAM FIRST!!!!!
'DO NOT RUN UNTIL YOU DO THAT.
makesaves()
getsaves()
printsaves()
Sub makesaves ' where you make saves. its reusable.
PATH = Program.Directory + "\animals\" ' SAVE THIS IN A FOLDER YOU WILL FIND IN
'ELSE IT WILL SAVE IN A DUMP FOLDER WHICH IS NEARLY IMPOSSIBLE TO FIND
NAME = "Animal"
EXT = ".txt"
filesave["1"] = "Cheetah"
filesave[2] = "horse"
filesave[3] = "dog"
filesave[4] = "cat"
filesave[5] = "mouse"
filesave[6] = "turtle"
filesave[7] ="Bird"
filesave[8] = "snake"
filesave[9] = "snail"
filesave[10] = "Rat"
'makes the saves
File.CreateDirectory(PATH) ' makes the path.
File.WriteContents(PATH+NAME+EXT, filesave)
filesave = "" ' cleans the file so you dont get repeats. e.i. - save dog. read dog, save dog, read dog dog.
'this makes it so you see dog once. its an override.
filesave = File.ReadContents(PATH + NAME + EXT) 'reads the content
endsub
Sub getsaves
filesave = File.ReadContents(PATH+NAME+EXT) ' how this writes is cheetah; horse;
cheetah = filesave[1]
horse = filesave[2]
dog = filesave[3]
cat = filesave[4]
mouse = filesave[5] 'mouse and turtle as different color because they can be used as functions. ignore
turtle = filesave[6]
bird = filesave[7]
snake = filesave[8]
snail = filesave[9]
rat = filesave[10]
EndSub
Sub printsaves
i = 1
While i < 11
TextWindow.WriteLine(filesave[i])
i = i+1
endwhile
endsub
I know I'm probably much too late but in case you're still going (and yes, I'm going to assume that you're not taking an AQA GCSE in Computer Science but instead like to code in Small Basic for fun), but you should be looking at using this code instead as this is much more efficient.
fpath = "\\Downloads\file.txt"
For i = 1 To 10
line[i] = File.ReadLine(fpath, i)
EndFor
For i = 1 To 10
TextWindow.WriteLine("Line " + i + " contains: " + line[i])
EndFor
(You'll need to change the fpath variable to wherever your file is). This then also prints out the array just to check but for your task you'll need to get rid of that.

Python Simple PiggyBank Program

This is my Python Program that I have been having some issues with:
-- coding: cp1252 --
from time import gmtime, strftime
print("Welcome to the PiggyBank version 1.")
num_write = int(input("How much money would you like to store in your PiggyBank?"))
f = open("PiggyBanks_Records.txt", "w")
current_time = strftime("%Y-%m-%d %H:%M:%S", gmtime())
convert_1 = str(current_time)
convert_2 = str(int(num_write))
add_1 = ("\n" + convert_1 + " £" + convert_2)
add_2 = ("\n" + add_1) #Tried to make it so new line is added every time the program is run
final_record = str(add_2)
print("Final file written to the PiggyBank: " + final_record)
#Write to File
f.write(final_record)
f.close()
Right now whenever the program writes to the file it over-writes. I would preferably would like to keep, like a history of the amounts added. If anyone can help so the string that needs to be written to the .txt file goes down by one line and essentially keeps going for ever. I am also open to any suggestion on how I can shorten this code.
You need to open your file with append mode :
f = open("PiggyBanks_Records.txt", "a")
Using the 'w' write option with open automatically looks for the specified file, and deletes its contents if it already exists (which you can read about here) or creates it if it doesn't. Use 'a' instead to add / append to the file.

Read from text file and assign data to new variable

Python 3 program allows people to choose from list of employee names.
Data held on text file look like this: ('larry', 3, 100)
(being the persons name, weeks worked and payment)
I need a way to assign each part of the text file to a new variable,
so that the user can enter a new amount of weeks and the program calculates the new payment.
Below is my code and attempt at figuring it out.
import os
choices = [f for f in os.listdir(os.curdir) if f.endswith(".txt")]
print (choices)
emp_choice = input("choose an employee:")
file = open(emp_choice + ".txt")
data = file.readlines()
name = data[0]
weeks_worked = data[1]
weekly_payment= data[2]
new_weeks = int(input ("Enter new number of weeks"))
new_payment = new_weeks * weekly_payment
print (name + "will now be paid" + str(new_payment))
currently you are assigning the first three lines form the file to name, weeks_worked and weekly_payment. but what you want (i think) is to separate a single line, formatted as ('larry', 3, 100) (does each file have only one line?).
so you probably want code like:
from re import compile
# your code to choose file
line_format = compile(r"\s*\(\s*'([^']*)'\s*,\s*(\d+)\s*,\s*(\d+)\s*\)")
file = open(emp_choice + ".txt")
line = file.readline() # read the first line only
match = line_format.match(line)
if match:
name, weeks_worked, weekly_payment = match.groups()
else:
raise Exception('Could not match %s' % line)
# your code to update information
the regular expression looks complicated, but is really quite simple:
\(...\) matches the parentheses in the line
\s* matches optional spaces (it's not clear to me if you have spaces or not
in various places between words, so this matches just in case)
\d+ matches a number (1 or more digits)
[^']* matches anything except a quote (so matches the name)
(...) (without the \ backslashes) indicates a group that you want to read
afterwards by calling .groups()
and these are built from simpler parts (like * and + and \d) which are described at http://docs.python.org/2/library/re.html
if you want to repeat this for many lines, you probably want something like:
name, weeks_worked, weekly_payment = [], [], []
for line in file.readlines():
match = line_format.match(line)
if match:
name.append(match.group(1))
weeks_worked.append(match.group(2))
weekly_payment.append(match.group(3))
else:
raise ...

Looping through A Folder and all its subdirectories

Ok. Many trouble shooting hours ...and many error "dings" later, I'm still having the same problem. Due to my beginner skills I'm having problems achieving the following segment of my project:
I will be as detailed as possible so I can hopefully nail it this time:
On my computer i have a folder C:\data which contains many different subfolders.
The subfolders are named by dates in a MMDDYY fashion. For example "040312"
In each subfolder are excel files named after Baseball teams. each subfolder may contain a different combination of xls files.
I am trying to write code that achieves the following objectives:
1.) Loops through all the subfolders of the C:\data folder looking for xls files that have the filenames: Angles.xls, Diamondbacks.xls, etc.
2.) If the files are found in each subfolder import the spreadsheet data and generate a plot of the data titled "Score" and "Allow".
3.) If the file is not found any given subfolder skip and continue to the next file to be located.
4.)Then save the generated plot in the same folder that the spreadsheet was imported from as a .fig and a .bmp file.
I've gotten hints to use various functions like: genpath, dir, but the code I've been fumbling through isn't able to achieve my goals.
a) the script doesn't import the excel files from all the subfolders
b) the script wont save the .fig or .bmp file in the associated subfolder
Here is the code I have been fumbling through:
%I know all of this is wrong wrong wrong. Please help to adjust my code to %achieve the objectives outlined above!
addpath(genpath('c:\data'))
folder = 'c:\data';
subdirs = dir(folder);
subdirs(~[subdirs.isdir]) = [] ;
numberOfFolders = length(subdirs);
if numberOfFolders <= 0
uiwait(warndlg('Number of folders = 0!'))
end
wantedfiles = {'Angels' 'Diamondbacks' 'Orioles' 'Royals' 'Yankees' 'Mets' 'Giants'};
for K = 1 : numberOfFolders
thissubdir = subdirs(K).name;
if strcmp(thissubdir, '.') || strcmp(thissubdir, '..')
continue;
end
subdirpath = [folder '\' thissubdir];
for L = 1 : length(wantedfiles)
for wantedfiles = {'Angels' 'Diamondbacks' 'Orioles' 'Royals' 'Yankees' 'Mets' 'Giants'};
folder = '';
fileToRead1 = [wantedfiles{1} '.xls'];
sheetName='Sheet1';
if exist(fileToRead1, 'file') == 0
% File does not exist
% Skip to bottom of loop and continue with the loop
continue;
end
%This is to import the data and organize it
% All of this code I had auto-generated from importing files manually
[numbers, strings, raw] = xlsread(fileToRead1, sheetName);
if ~isempty(numbers)
newData1.data = numbers;
end
if ~isempty(strings) && ~isempty(numbers)
[strRows, strCols] = size(strings);
[numRows, numCols] = size(numbers);
likelyRow = size(raw,1) - numRows;
% Break the data up into a new structure with one field per column.
if strCols == numCols && likelyRow > 0 && strRows >= likelyRow
newData1.colheaders = strings(likelyRow, :);
end
end
% Create new variables in the base workspace from those fields.
for i = 1:size(newData1.colheaders, 2)
assignin('base', genvarname(newData1.colheaders{i}), newData1.data(:,i));
end
% Now I execute the plotting of data
subplot (2,1,1), plot(Score,Allow)
title([wantedfiles{1} 'Testing to see if it works']);
subplot (2,1,2), plot(Allow,Score)
title('Well, did it?');
% here I save the generated plots, but they don't save where I want them to
saveas(gcf,[wantedfiles{1} ' did it work.fig']);
saveas(gcf,[wantedfiles{1} ' did it work.bmp']);
end
end
end
%At the end of the script I still was unable to loop over the files that I wanted
rmpath(genpath('c:\data'));

Way to assign multiple files to set variable names?

Is there a way to assign file names to set varibles using a GUI? Say I have 6 file sets which contain 4 colors each (blue, green, nir, red). There are 24 files in total, so i'd need 24 variables. And I want the set varialbes to be something like
blue1
green1
nir1
red1
blue2
green2
nir2
red2
etc...
Currently I'm trying to use GUIDE to creat a custom GUI that will allow the user to select the files they wish and have them assigned to certain variables. I am thinking something along the lines of having 24 popupmenus that are attached to a file directory and allows the user to select which file they want, and then it will assign that file and it's path to a variable (blue1 for example) I also want 24 check boxes to associate with an if statement
Let's say popupmenu1 is associated with the variable blue1 and checkbox1
if checkbox1 == checked
do import
elseif checkbox1 == unchecked
fill with zeros
I have the basic frame of the GUI created, I am just unclear on how to apply the file select and then associate the if statements, etc...
If you know the variable files in advance, it's bad practice (look also here and here) to use string defined variable names like this:
var1name = 'blue';
var2name = 'red';
% etc.
% load data
datablue=rand(4,1);
datared =rand(4,1);
% assign
eval([var1name '1 = datablue(1);']);
eval([var2name '1 = datared (1);']);
% etc.
eval([var1name '2 = datablue(2);']);
eval([var2name '1 = datared (2);']);
% etc
It's much easier and better to just use an ordinary array, given the variable name is not changing or application dependend, which in my example I already have as datablue and datared.
Another option if you'd like user defined variable names is to use an array of structs:
var1name = 'blue';
var2name = 'red';
sample(1).(var1name) = datablue(1);
sample(1).(var2name) = datared (1);
% ...
sample(2).(var1name) = datablue(2);
sample(2).(var2name) = datared (2);
Try some of these out, and only if you have a very good reason, resort to eval!
for k = 1:6
blue(k) = sprintf('blue%d', k);
green(k) = sprintf('green%d', k);
nir(k) = sprintf('nir%d', k);
red(k) = sprintf('red%d', k);
end
This will create the variable names for you. Then you can use assignin (i believe) or eval to set the values to the variable names.

Resources