Matlab vectorisation of loop "tracking value increments" - matlab

I have been breaking my head about trying to optimise a matlab script that needs to process quite long arrays.
Basically, there are 2 arrays: AbsoluteTimeTag and Channel.
AbsoluteTimeTag will hold int values signifying time that are recorded using a 16 bit counter. Since the counter is limited to 2^16 values it will often roll over during the course of the measurement. Channel registers this and when it does, bitand(Channel,2048) will evaluate true.
How these arrays are generated is out of my control and the overflow markers occur "in sync" with the data coming in.
It is now easy to reconstruct the absolute time by doing:
AbsoluteTimeTag(i) = NoOfOverflows * 65536 + TimeTag(i);
In a loop:
for i=1:NumberOfRecords
%Running through all records, if we meet anything other than an
%overflow record, we van just calculate its absolute time based on
%current overflow count and its timetag.
AbsoluteTimeTag(i) = NoOfOverflows * 65536 + TimeTag(i);
% We are running through all records so if we encounter an overflow
% (signified by bitand(..., 2048), we add 1 to the overflow count.
if bitand(Channel(i),2048)
NoOfOverflows = NoOfOverflows + 1;
end;
end;
I have been really breaking my head on how to potentially vectorise this (since Matlab is pretty bad at loops). So far however, I do not see the light for some reason.
Problem is that the number of overflows up to a certain record index along AbsoluteTimeTag can change as you walk the vector from start to end.
I do not know how I could express "count all occurrences of overflow up to this point" in a vectored operation.
Can somebody comment on whether or not this might be feasible at all?
EDIT
Example data would look like this:
TimeTag (each element is an event for which time is counted un a 2^3 register for simplicity):
[ 01 03 04 07 xx 02 03 04 05 xx 01 03 04 07 xx ... ]
overflow:
[ 00 00 00 00 01 00 00 00 00 01 00 00 00 00 01 ... ]
Which would need to yield
[ 01 03 04 07 xx 10 11 12 13 xx 17 19 20 23 xx ... ]
The reason xx is there is because originally, all records, both the events and the overflows are in one large uint32 array where each record holds different types of info on the different bits. The xx locations can undergo any operation but they are further meaningless when considering the TimeTag records. I have a logical array keeping track of what locations hold actual meaningful data.

"count all occurrences of ... to this point" in a vectored operation would be best expressed as cumsum.
Assuming NoOfOverflows is initialized as zero before the start of the loop and AbsoluteTimeTag, Timetag have NumberOfRecords as their number of elements , see if this works for you -
%// Get the overflow for all Channel entries in one go
bitand_all = bitand(Channel,2048)~=0;
%// AbsoluteTimeTag appears to be a cumsum of overflows plus Timetag
AbsoluteTimeTag = [0 ; cumsum(bitand_all(1:end-1).*65536)]+ TimeTag;
%// Get the count of overflows as NoOfOverflows
NoOfOverflows = sum(bitand_all);

Related

Label error in Mariesim, Any advice on how to fix it?

I am having an issue in Marie where it is saying that the error is " A label cannot have 0..9 as its beginning character". How would I go about fixing this?
The image below is the section of code where this error appears. I have never seen this before and my friends nor me can find anything on it. Any advice is appreciated!
START, INPUT
SKIPCOND 800
HALT
OUTPUT
STORE A
SUB Z
SKIPCOND 800
SKIPCOND 000
JUMP START
X, INPUT
STORE B
OUTPUT
SUB A
SKIPCOND 800
JUMP Y
JUMP X
Y, LOAD B
ADD C
STORE S
EVEN, SUB T
SKIPCOND 800
JUMP L
JUMP EVEN
L, SKIPCOND 400
JNS ODD
LOAD S
OUTPUT
LOAD A
SUB S
STORE N
OUTPUT
JUMP START
ODD, OUTPUT S
LOAD S
ADD 0
STORE S
JUMPI ODD
A, DEC 00
B, DEC 00
S, DEC 00
N, DEC 04
C, DEC 04
Z, DEC 94
T, DEC 02
0, DEC 01
END START

Creating a matrix for a given value of a given value - For loop issues

I'm not sure if the title is very clear.
What I am trying to do is analyze a huge amount of data and produce a singular matrix for each ID.
The data comes in the form:
1001 00101 150
1001 00102 146
1001 00103 145
......
1001 19401 178
1001 19402 194
ID(1:4) Day(6:8) Half hour within a 24 hour period (9:10) Usage(12:end)
e.g ID=1001 Day=001 Half Hour=01 Usage=150
The ID, Day and Half hour values follow a strict pattern however the usage is the measured value.
I am trying to output
ID Value - Average usage per half hour
1001 01 150
1001 02 160
1001 03 173
1001 04 194
.... .. ...
1001 48 150
.... .. ...
1100 48 147
I've broken down the data into each specific component, however I am having trouble outputting the data into the average usage for each half hour, constantly getting trapped in for loops with no end product.
My base code currently examines the first line and extracts each component
fid = fopen('test.txt');
tline = fgetl(fid);
ID=tline(1:4);
disp(ID);
Day=tline(6:8);
disp(Day);
HalfHour=tline(9:10);
disp(HalfHour);
Usage=tline(12:end);
disp(Usage);
However I am really struggling to amplify this to the entire data set and produce the specified output.
Any help would be much appreciated.

how to store 00 as 00 instead of 0 only

MATLAB stores 00 and 01 as 0 and 1 respectively. How can I make MATLAB store 00 as 00 and 01 as 01 instead of 0 and 1 only...here is my code.. I am talking about the statements with <-- only..In fact I want to input the result as initial population(chromosome) to a genetic algorithm.
function [x]=abc()
r=randi([0 3],1,20);
for i=1:20
if r(i)==0
x(i)=00; %// <--
elseif r(i)==1
x(i)=01; %// <--
elseif r(i)==2
x(i)=10;
elseif r(i)==3
ex(i)=11;
end
end
end
It looks like you want to store the binary representation of your numbers, so you can use the function dec2bin
and the best thing, you don't even need a loop ;)
r=randi([0 3],1,20);
x = dec2bin(r,2) ;
>> x
x =
10
00
11
11
10
11
10
01
...

Interpolate the time stamped patient data

Question: I am dealing with a patient data, where parameters are recorded at different sampling frequency, so having a different time stamp.
I want to create a matrix where data is interpolated by "Last known value" till the new original value changes in the time. So at the end I have uniform matrix where each parameter have values at every time stamp.
Data is in following format:
Time Hear Rate(Variable)
18:00:00 PM 74
18:02:00 PM 75
18:04:00 PM 85
18:06:00 PM 71
18:08:00 PM 79
18:10:00 PM 72
Time Blood Press. (Variable)
18:01:00 PM 100
18:05:00 PM 120
18:09:00 PM 121
Target :
Time Hear Rate(Variable) Blood Press.
18:00:00 PM 74 NaN
18:01:00 PM 74 100
18:02:00 PM 75 100
18:03:00 PM 75 100
18:04:00 PM 85 100
18:05:00 PM 85 120
18:06:00 PM 71 120
18:07:00 PM 71 120
18:08:00 PM 79 120
18:09:00 PM 79 121
18:10:00 PM 72 121
The Interpolated data in the missing place should be the previous value of the known event and should remain same until next change occurs.
I am currently referring the following thread from MATLAB User Forum
http://www.mathworks.com/matlabcentral/answers/101237-how-can-i-do-1-d-interpolation-with-interp1-to-find-the-nearest-value-to-the-left-of-the-point-i-e
You're essentially trying to do a zero-order hold as you've seen from the link you provided.
Let's call the first set of times t_hr (a cell array of strings) and the second set t_bp (also a cell array of strings). Then call the heart rates hr and the blood pressures bp.
Build a new cell array t by combining t_hr and t_bp:
t = [t_hr; t_bp];
Fill in hr and bp with some NaNs to make them the same length as t. In t, the first part of the vector corresponds to times we know about for hr, and the second half corresponds to bp. Use that knowledge accordingly:
hr = [hr; nan(length(t) - length(hr),1)];
bp = [nan(length(t) - length(bp),1); bp];
Now you've got three vectors: t (okay, that's actually a cell array); hr and bp, and the elements of hr and bp correspond to elements in t, including the NaNs:
t =
'18:00:00 PM'
'18:02:00 PM'
'18:04:00 PM'
'18:06:00 PM'
'18:08:00 PM'
'18:10:00 PM'
'18:01:00 PM'
'18:05:00 PM'
'18:09:00 PM'
hr =
74
75
85
71
79
72
NaN
NaN
NaN
bp =
NaN
NaN
NaN
NaN
NaN
NaN
100
120
121
Now, we can sort t:
[t_sorted, idx] = sort(t);
idx contains the indices of t that got moved around to form t_sorted. In this case, idx == [1 7 2 3 8 4 5 9 6].'. We can use that to sort bp and hr:
hr_sorted = hr(idx)
hr_sorted =
74
NaN
75
85
NaN
71
79
NaN
72
bp_sorted = bp(idx)
bp_sorted =
NaN
100
NaN
NaN
120
NaN
NaN
121
NaN
Then, apply the zero-order hold:
for ii = 2:length(t)
if isnan(hr_sorted(ii))
hr_sorted(ii) = hr_sorted(ii-1);
end
if isnan(bp_sorted(ii))
bp_sorted(ii) = bp_sorted(ii-1);
end
end
and your final vectors become:
hr_sorted =
74
74
75
85
85
71
79
79
72
bp_sorted =
NaN
100
100
100
120
120
120
121
121
Note that your target answer has 11 different times in it, but you only supplied nine. (It's missing 18:03 and 18:07.) You can easily extend this answer by adding extra NaNs to hr and bp, and making t a cell array comprising of, say, t_hr, t_bp, and a cell array t_missing ={'18:03:00 PM', '18:07:00 PM'}.

Matlab code crashing unexpectedly

Does anyone of you have a clue of why the following code is crashing with Index exceeds matrix dimensions. error for N_SUBJ = 17 or N_SUBJ = 14, but not for example for the values 13,15,16?
N_PICS = 7
COLR = hsv;
N_COLR = size(COLR,1);
COLR = COLR(1+[0:(N_PICS-1)]*round(N_COLR/N_PICS),:);
SUBJ_COLR = hsv;
N_SUBJ_COLR = size(SUBJ_COLR,1);
SUBJ_COLR = SUBJ_COLR(1+[0:(N_SUBJ-1)]*round(N_SUBJ_COLR/N_SUBJ),:);
And also, could somebody please explain me what it's doing exactly and how it's working?
When you say crashing, I assume you mean you are seeing the error, Index exceeds matrix dimensions.? If you are seeing this error then the matrix returned by hsv does not have enough rows for the sub-sample operation you are doing.
SUBJ_COLR = SUBJ_COLR(1+[0:(N_SUBJ-1)]*round(N_SUBJ_COLR/N_SUBJ),:);
selects a subset of the original matrix. 1+[0:(N_SUBJ-1)]*round(N_SUBJ_COLR/N_SUBJ) calculates which row to select, and : means all columns.
The matrix SUBJ_COLR is 64-by-3, thus N_SUBJ_COLR is equal to 64. You're indexing into the 64 rows of SUBJ_COLR and in some cases the particular index is greater than the number of row, resulting in a Index exceeds matrix dimensions. error. So the question is really why does this snippet
1+[0:(N_SUBJ-1)]*round(N_SUBJ_COLR/N_SUBJ)
evaluate to numbers greater than 64 for some values of N_SUBJ? This expression can be rewritten as:
1+(0:round(64/N_SUBJ):round(64/N_SUBJ)*(N_SUBJ-1))
or
1:round(64/N_SUBJ):round(64/N_SUBJ)*(N_SUBJ-1)+1
where I've replaced N_SUBJ_COLR by 64 for clarity. This latter expression more clearly shows what the largest index in the vector will be and how it depends on the value of N_SUBJ. You can print out this largest index as a function of N_SUBJ:
N_SUBJ = 1:30;
round(64./N_SUBJ).*(N_SUBJ-1)+1
which returns
ans =
Columns 1 through 13
1 33 43 49 53 56 55 57 57 55 61 56 61
Columns 14 through 26
66 57 61 65 69 55 58 61 64 67 70 73 51
Columns 27 through 30
53 55 57 59
As you can see, there are several values that exceed 64. This nonlinear behavior comes down to the use of round. The integers created by the round part don't appear to get small enough fast enough as they multiply (N_SUBJ-1) which is growing in order to keep the total term less than 64. One option might be to replace round with floor, but there are probably other ways.