Extract the most recent values from appended .CSV in MATLAB - matlab

I have a .csv file which is appended with 3 new values in the row below the previous set:
dlmwrite('MyFile.csv', [MyValue,MyValue2,MyValue3], '-append');
This happens every minute. It happens indefinitely because of a timer i.e it accumulates data over time:
How can I continually copy over the 60 most recent sets of values from the file and store them in a new csv file, say MyFile2.The row number of the .csv file is increasing by 1 with every minute. i.e 60 values stored in 60 minutes but I may have 100 values and want to extract the latest 60 for another file.
Image of the CSV file - 2nd column is time in HOURS:MINUTES without the : separator (ignore the lapse in time between rows 38 and 39 or any lapses elsewhere):
Note: MyValue is added to the file every minute because the script is run every 60 seconds from another script. I.e there is no internal timer in the main script:
Period = 60; % Update period in seconds
tim = timer('Period', Period, 'ExecutionMode', 'fixedRate',...
'TimerFcn', 'TESTINGFINAL');
start(tim)
stop(tim)
runtmp = fullfile('MyScriptLocation','MyScript');
run(runtmp);

If you want to do this continuously while running I'd suggest some sort of circular buffer arrangement so you always have the last 60 values in memory. This will be easier than trying to work out the current length of your continuously logging file. Basic idea (minus the actual timing code):
% initialising buffer
MyValue1 = zeros(60,1);
while true % for certain values of true
% these go once a minute
mv1 = myfunc1(inputs);
MyValue1 = [MyValue1(2:end); mv1];
dlmwrite('MyFile.csv', [mv1], '-append');
% this goes less frequently, I presume
filename = [datestr(now,30),'.csv']; % dynamic filename
dlmwrite(filename, MyValue1);
end
This way you have both your continuously logging file (updated every minute), and a series of smaller files containing what were the last 60 values at the time they were written (updated hourly, or on some other trigger, as required).
With your timer, one way of doing this would appear to be to keep a simple counter of how many times the acquisition script has run and then use the mod function to check for when this hits a multiple of 60.

This is not a full answer, but I do have an idea if I understand you correctly. This means you probably want to run Matlab 24/7? Or at least non-stop for a certain amount of time? If so, you could try out the command clock, it shows and stores the system time. In your case
time=clock;
where
time(4) holds the hour. So as soon as this parameter changes, you should open your .csv file and save the last 60 values.
However, doing it this way I think is highly energy-consuming. And sadly Matlab does not have a sleep command like for example Unix does, so maybe it would be interesting to look into running this program in another programming language?
Please provide me with comments and feedback since I see that this is not a complete answer (yet)!

Related

Write chords using MIDO to a file

I have a hard time writing chords in a MIDI file using MIDO, the MIDI library for Python.
I have a list of 100 chords with notes stored in the list. So each chord in the code below is [60, 63, 67] as in Cmin. The timing of each in seconds is stored in the chordTimes list.
I iterate in the list,
for i in range(1, len(chords)):
chordNotes = chordMidiNotes(chords[i], extraBass= False)[0]
chordSymbol = chordMidiNotes(chords[i], extraBass= False)[1]
for note_value in chordNotes: # result has chord notes
track.append(Message('note_on', note=note_value, velocity=100, time=0))
for note_value in chordNotes: # result has chord notes
track.append(Message('note_off', note=note_value, velocity=127, time=time_in_ticks(chordTimes[i], mo)))
mo.save("songWithChords.mid")
But then when I open the files, the chords start at the same time, however, the top note ends just before last chords, the one below ends before that, the one before the later stops again several beats before it, .... as you see in the image. I am using type 1 midi file.
The MIDO documentation says:
All messages must be tagged with delta time (in ticks). (A delta time is how long to wait before the next message.)
So the delta times of all note-off messages except the first one must be zero.

Reading a changing txt file matlab

I have a text file (5 columns "\t" separated) that's being written to by another software. I need to take the readings from the file and do some calculations. Is there a was to read the new lines added to the file and process it then repeat again for every new set of lines. I don't mind a bit of delay as long as it does the job.
My idea is to start reading the file line by line until the end of file, then it will read from where it stopped last until the new end of file ...etc.
Can this be done in Matlab? Can I specify the starting line for the file reading? can I also update the end of file point?
To prevent the loop from breaking at the eof point, I think I should set my loop to be controlled by time or anything else, while it should check for eof at the end of every iteration.
I've mostly worked with Matlab, but if there is a better option to use for this purpose (that I can reasonably learn) please feel free to guide me.
Edit1: I've tried using dlmread as you suggested, when I read the file outside the loop it reads the file correctly even when I change R1 and with the other software updating the text. However, when I put it in a loop I get this error:
Error using dlmread (line 143)
Empty format string is not supported at the end of a file.
Here is my code to read it multiple times:
clear all
x=0;
R1=0; C1=0;
while(x<10)
M = dlmread('tst_4.txt','\t',R1,C1);
R1=length(M);
x=x+1;
end
Thanks
You can used dlmread(filename,delimiter,R1,C1). Where R1 and C1 are the row and column offset respectively. By setting the row offset to the last row that you have read, you can read the file content excluding what you would have already read.

Profiler inconsistency

I run some code with Profiler, the code deals with DICOM files, and the dicom... functions in Matlab.
In the main window of the Profiler, I see that dicominfo>parseSequence takes almost all of the running time. Inside this inner function, it seems like that:
You can see here that dicominfo>parseSequence takes total of 241.488 seconds (in the title), and inside it there is a function called dicominfo>processMetadata, that takes 240.801 seconds, 99.7% from the time.
But, when I click it to see its contents, it says that the processMetadata takes only 50.391 seconds! :
How can it be...? Where all my time goes...?
EDIT
I really think that this is a Profiler issue, but for #Tokkot ask, I attach the piece of code that I profiled:
cd ([Fname '\' seq(m).name]);
files=dir; % Names of all files in current sequence
for n=4:length(files)
info=dicominfo([pwd '\' files(n).name]);
info.PatientName=PatientName; % convert the field Name to initials
info.PatientID=''; % delete ID
[X,~]=dicomread([pwd '\' files(n).name]);
dicomwrite(X, sprintf('anon%s', files(n).name), info, 'createmode', 'copy');
delete([pwd '\' files(n).name]);
end

How to get time of creation of a file? (MATLAB)

I want to read an image file in MATLAB and use the time it was created in the system to add a delay for my next command.
For ex if time_created is the system time the image file was created, I want my next command to execute after a delay of (time_now - time_created) + 3 sec. Is this possible?
You can use the information given by dir:
yourFileName = 'myFile.m'
allfiles = dir
filenames = {allfiles(:).name}
[~,idx] = ismember(yourFileName,filenames)
yourFileDate = allfiles(idx).date
which will return a date string:
yourFileDate = 06-Mar-2014 10:53:48
or alternatively:
yourFileDate = allfiles(idx).datenum
which will give you the output in datenum format. (You probably want to work with that)
you could then continue as follows:
timeNow = clock %//current system time as date vector
timeFileCreation = datevec(yourFileDate) %//file creation time as date vector
timeDiff = etime(timeNow,timeFileCreation)
returns the number of seconds between both time vectors.
Note that the matlab 'dir' command does not return the file creation time, but rather the last file modification time. In your use case, the creation time and the modification time are likely the same. But in other circumstances, the modification time may be different than the creation time (e.g. if a user edited a file after it was created). Different operating systems store different file times between the creation, last modification and last access times. Last modification time is the only one that is available in all operating systems that matlab runs on, so it is the only time supported by the matlab 'dir' command. Depending on with OS you're running on, you can access the other file times available on that OS, through (at least) use of the 'system' command and knowledge of the command line functions available in that OS.
With Python now really integrated into MATLAB, this works on both Windows and MacOS:
d1 =datetime(py.os.path.getctime('video_path'),'ConvertFrom','epochtime','TicksPerSecond',1,'Format','dd-MMM-yyyy HH:mm:ss.SSS');

Timer in matlab to repeat segments of code every few minutes

I have the following code which downloads a CSV file from a link and then saves it as a formatted file:
urlwrite('http://xweb.geos.ed.ac.uk/~weather/jcmb_ws/JCMB_2013_Sep.csv','Weather Data.csv');
data= readtext('Weather Data.csv');
I want to download download this file every 5 minutes. The updated data from the file is used in other parts of my script so I also want those calculations and other parts of my program to be automated every 5 minutes with the change in new file information.
The timer feature in matlab calls a function and i'd rather do it as a loop format because my calculations aren't already saved as specific functions.
How can I achieve this as some sort of loop or timer?
The simplest way might be to put in a pause command, pause(t) pauses the script for t seconds, so you could have
while(1)
tic
urlwrite('http://xweb.geos.ed.ac.uk/~weather/jcmb_ws/JCMB_2013_Sep.csv','Weather Data.csv');
data= readtext('Weather Data.csv');
% run the rest of the code that you need to run on the data you have downloaded
T=toc;
pause(300-T)
end
You can terminate the loop by pressing ctrl+c, which will stop the code.
Hope that helps