I'd like to perform metrics on the contents of an array that do NOT fall within certain ranges.
For example, I have an array with 1000 rows and 2 columns. I'd like to perform a mean() calculation on all the elements in one column (let's say column #2) that don't fall in rows 50-150, 250-300, 400-700 and 900-950.
Thus, the mean should be calculated based on rows 1-49, 151-249, 301-399, 701-899 and 951-1000.
Any ideas how to go about this?
Edit: I should point out that those items which are included will change each time the program is run. Therefore, I can't just hard-code the inclusions in; they need to be worked out based on the exclusions.
How about:
M = rand(1000,2);
idx = setdiff(1:size(M,1), [50:150, 250:300, 400:700, 900:950]);
MM = M(idx,:)
Now apply any function to the filtered matrix:
mean(MM,1)
You can define the exclusion ranges and then use logical addressing:
LowerLimit1 = 1;
UpperLimit1 = 50;
LowerLimit2 = 151;
UpperLimit2 = 249;
LowerLimit3 = 301;
UpperLimit3 = 399;
LowerLimit4 = 701;
UpperLimit4 = 899;
LowerLimit5 = 951;
UpperLimit5 = 1000;
MyVector = MyMatrix(:,2);
MeanValue = mean(MyVector(~(MyVector > LowerLimit1 & MyVector < UpperLimit1) | (MyVector > LowerLimit2 & MyVector < UpperLimit2) | (MyVector > LowerLimit3 & MyVector < UpperLimit3) | (MyVector > LowerLimit4 & MyVector < UpperLimit4) | (MyVector > LowerLimit5 & MyVector < UpperLimit5)));
Related
How can I collapse the values of "deep" struct fields into arrays by just indexing?
In the example below, I can only do it for the "top-most" level, and for "deeper" levels I get the error:
"Expected one output from a curly brace or dot indexing expression, but there were XXX results."
The only workaround I found so far is to unfold the operation into several steps, but the deeper the structure the uglier this gets...
clc; clear variables;
% Dummy data
my_struc.points(1).fieldA = 100;
my_struc.points(2).fieldA = 200;
my_struc.points(3).fieldA = 300;
my_struc.points(1).fieldB.subfieldM = 10;
my_struc.points(2).fieldB.subfieldM = 20;
my_struc.points(3).fieldB.subfieldM = 30;
my_struc.points(1).fieldC.subfieldN.subsubfieldZ = 1;
my_struc.points(2).fieldC.subfieldN.subsubfieldZ = 2;
my_struc.points(3).fieldC.subfieldN.subsubfieldZ = 3;
my_struc.info = 'Note my_struc has other fields besides "points"';
% Get all fieldA values by just indexing (this works):
all_fieldA_values = [my_struc.points(:).fieldA]
% Get all subfieldM values by just indexing (doesn't work):
% all_subfieldM_values = [my_struc.points(:).fieldB.subfieldM]
% Ugly workaround:
temp_array_of_structs = [my_struc.points(:).fieldB];
all_subfieldM_values = [temp_array_of_structs.subfieldM]
% Get all subsubfieldZ values by just indexing (doesn't work):
% all_subsubfieldZ_values = [my_struc.points(:).fieldC.subfieldN.subsubfieldZ]
% Ugly workaround:
temp_array_of_structs1 = [my_struc.points(:).fieldC];
temp_array_of_structs2 = [temp_array_of_structs1.subfieldN];
all_subsubfieldZ_values = [temp_array_of_structs2.subsubfieldZ]
Output:
all_fieldA_values =
100 200 300
all_subfieldM_values =
10 20 30
all_subsubfieldZ_values =
1 2 3
Thanks for any help!
You can use arrayfun to have acces to each individual 'point', and then acces its data. This will return an array with the same dimensions as my_struc.points:
all_subfieldM_values = arrayfun(#(in) in.fieldB.subfieldM, my_struc.points)
all_subsubfieldZ_values = arrayfun(#(in) in.fieldC.subfieldN.subsubfieldZ, my_struc.points)
Not optimal, but at least it's one line.
In one of my GUIs I load DICOM images. Sometimes they are just a volume and another dimension and when I load them in Matlab everything ends up where I want it.
handles.inf = dicominfo([filepath filename]);
handles.dat = dicomread(handles.inf);
size(handles.dat)
ans = 128 128 128 512
For an 128 by 128 by 128 volume at 512 timepoints for example (actually the third dimension would not even be 128, the third dimension is stacks, of which I don't know what it is). However sometimes There are more dimensions in the dicom, but the reader just puts all of them in the fourth dimension.
handles.inf = dicominfo([filepath filename]);
handles.dat = dicomread(handles.inf);
size(handles.dat)
ans = 128 128 1 4082
For a single 128 by 128 slice with 512 timepoints, two echoes and magnitude, phase, real and imaginary data for example.
It is then very hard to unscramble them. Manually I can do this for every DICOM I load but when in a GUI I would want to have a general approach that just creates a dimension in the array for each dimension in the dicom.
This is especially important not just for data-analysis, but also to transform the coordinates from image space to patient space. My own approach was to look at the header, but there's no guarantee that certain entries will work, and the order in which they are applied I can't find. The header entries I found so far:
inf.Rows;%inf.width;%inf.MRAcquisitionFrequencyEncodingSteps;%inf.MRAcquisitionPhaseEncodingStepsInPlane
inf.Columns;% inf.height; % inf.NumberOfKSpaceTrajectories;
inf.MRSeriesNrOfSlices
inf.MRSeriesNrOfEchoes
inf.MRSeriesNrOfDynamicScans
inf.MRSeriesNrOfPhases
inf.MRSeriesReconstructionNumber % not sure about this one
inf.MRSeriesNrOfDiffBValues
inf.MRSeriesNrOfDiffGradOrients
inf.MRSeriesNrOfLabelTypes
reshapeddat = reshape(dat, [all dimension sizes from header here]);
I'm not sure how to check if I've got all variables and what the right order for the reshape. Anybody knows of a sure-fire way to get all dimension sizes from the DICOM header and the order in which they are stacked?
Ok so I now manually go by all possible dimensions. When a stack also contains reconstructed data which has less dimensions than the rest, remove those first.
This is how I check the dimensions:
info = dicominfo(filename);
datorig = dicomread(filename);
%dimension sizes per frame
nrX = double(info.Rows); %similar nX;% info.width;% info.MRAcquisitionFrequencyEncodingSteps;% info.MRAcquisitionPhaseEncodingStepsInPlane
nrY = double(info.Columns); %similar nY;% info.height;% info.NumberOfKSpaceTrajectories;
%dimensions between frames
nrEcho = double(info.MRSeriesNrOfEchoes);
nrDyn = double(info.MRSeriesNrOfDynamicScans);
nrPhase = double(info.MRSeriesNrOfPhases);
nrSlice = double(info.MRSeriesNrOfSlices); %no per frame struct entry, calculate from offset.
%nr of frames
nrFrame = double(info.NumberOfFrames);
nrSeq = 1; % nSeq not sure how to interpret this, wheres the per frame struct entry?
nrBval = double(info.MRSeriesNrOfDiffBValues); % nB
nrGrad = double(info.MRSeriesNrOfDiffGradOrients); % info.MRSeriesNrOfPhaseContrastDirctns;%similar nGrad?
nrASL = 1; % info.MRSeriesNrOfLabelTypes;%per frame struct entry?
imtype = cell(1, nrFrame);
for ii = 1:nrFrame
%imtype(ii) = eval(sprintf('info.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.MRImageTypeMR', ii));
imtype{ii} = num2str(eval(sprintf('info.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.MRImageTypeMR', ii)));
end
imType = unique(imtype, 'stable');
nrType = length(imType);
This is how I reformat the dimensions:
%% count length of same dimension positions from start
if nrEcho > 1
for ii = 1:nrFrame
imecno(ii) = eval(sprintf('inf.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.EchoNumber', ii));
end
lenEcho = find(imecno ~= imecno(1), 1, 'first') - 1;
else
lenEcho = nrFrame;
end
if nrDyn > 1
for ii = 1:nrFrame
imdynno(ii) = eval(sprintf('inf.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.TemporalPositionIdentifier', ii));
end
lenDyn = find(imdynno ~= imdynno(1), 1, 'first') - 1;
else
lenDyn = nrFrame;
end
if nrPhase > 1
for ii = 1:nrFrame
imphno(ii) = eval(sprintf('inf.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.MRImagePhaseNumber', ii));
end
lenPhase = find(imphno~=imphno(1), 1, 'first') - 1;
else
lenPhase = nrFrame;
end
if nrType > 1
q = 1;
imtyno(1, 1) = q;
for ii = 2:nrFrame
if imtype{:, ii-1} ~= imtype{:, (ii)}
q = q+1;
end
imtyno(1, ii) = q;
%for jj = 1:nrType
%if imtype{:,ii} == imType{:,jj}
% imtyno(1, ii) = jj;
%end
%end
end
if q ~= nrType
nrType = q;
end
lenType = find(imtyno ~= imtyno(1), 1, 'first') - 1;
else
lenType = nrFrame;
end
% slices are not numbered per frame, so get this indirectly from location
% currently not sure if working for all angulations
for ii = 1:nrFrame
imslice(:,ii) = -eval(['inf.PerFrameFunctionalGroupsSequence.Item_',sprintf('%d', ii),'.PlanePositionSequence.Item_1.ImagePositionPatient']);
end
% stdsl = std(imslice,[],2); --> Assumption
% dirsl = max(find(stdsl == max(stdsl)));
imslices = unique(imslice', 'rows')';
if nrSlice > 1
for ii = 1:nrFrame
for jj = 1:nrSlice
if imslice(:,ii) == imslices(:,nrSlice - (jj-1)); %dirsl or :?
imslno(1, ii) = jj;
end
end
end
lenSlice = find(imslno~=imslno(1), 1, 'first')-1;
else
lenSlice = nrFrame;
end
if nrBval > 1
for ii = 1:nrFrame
imbno(ii) = eval(sprintf('inf.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.MRImageDiffBValueNumber', ii));
end
lenBval = find(imbno~=imbno(1), 1, 'first') - 1;
else
lenBval = nrFrame;
end
if nrGrad > 1
for ii = 1:nrFrame
imgradno(ii) = eval(sprintf('inf.PerFrameFunctionalGroupsSequence.Item_%d.PrivatePerFrameSq.Item_1.MRImageGradientOrientationNumber', ii));
end
lenGrad = find(imgradno~=imgradno(1), 1, 'first')-1;
else
lenGrad = inf.NumberOfFrames;
end
lenSeq = nrFrame; % dont know how to get this information per frame, in my case always one
lenASL = nrFrame; % dont know how to get this information per frame, in my case always one
%this would have been the goal format
goaldim = [nrSlice nrEcho nrDyn nrPhase nrType nrSeq nrBval nrGrad nrASL]; % what we want
goallen = [lenSlice lenEcho lenDyn lenPhase lenType lenSeq lenBval lenGrad lenASL]; % what they are
[~, permIX] = sort(goallen);
dicomdim = zeros(1, 9);
for ii = 1:9
dicomdim(1, ii) = goaldim(permIX(ii));
end
dicomdim = [nrX nrY dicomdim];
%for any possible zero dimensions from header use a 1 instead
dicomdim(find(dicomdim == 0)) = 1;
newdat = reshape(dat, dicomdim);
newdim = size(newdat);
newnonzero = length(newdim(3:end));
goalnonzero = permIX(1:newnonzero);
[dummyy, goalIX] = sort(goalnonzero);
goalIX = [1 2 goalIX+2];
newdat = permute(newdat, goalIX);
newdat = reshape(newdat, [nrX nrY goaldim]);
When Ive used this as a function for a longer period and debugged it a bit I might post in on the file exchange of mathworks.
I have a cell array containing strings and cells, similar to this:
theCellArray = {{'aa1' {'bb'; 'cc'}}; {'aa2' {'dd'; 'ee'}}};
Now I would like to be able to concatenate the names and get something similar to this :
aa1.bb
aa1.cc
aa2.dd
aa2.ee
The number of element might change (so for aa1, there might be bb, cc, dd, ee, etc).
I tried various things, but I'm always unable to make Matlab evaluate the second step of string (the one containing bb, cc...). Any ideas?
EDIT:
There might be more than 2 levels, so theCellArray could be :
theCellArray = {{'aa1' {'bb' {'b1' {'b11' 'b12'} 'b2'}; 'cc'}}; {'aa2' {'dd'; 'ee'}}};
theCellArray is like a tree, so the number of level is unknown.
Here is a recursive solution:
function t = recCat(s)
if ~iscell(s)
t = s;
elseif size(s,1) > 1,
t = [recCat(s(1,:)); recCat(s(2:end,:))];
elseif size(s,2) > 1,
t0 = cellfun(#(x) strcat('.', x), ...
cellfun(#recCat, s(2:end), 'UniformOutput', false), ...
'UniformOutput', false);
t = strcat(s{1}, t0{:});
elseif ischar(s{1})
t = s;
else
t = recCat(s{1});
end
end
Here is the result for first example:
>> theCellArray = {{'aa1' {'bb'; 'cc'}}; {'aa2' {'dd'; 'ee'}}};
>> recCat(theCellArray)
ans =
'aa1.bb'
'aa1.cc'
'aa2.dd'
'aa2.ee'
The second, as it stands now fails because of dimension issues in concatenation. I put 'bb' {'b1' {'b11' 'b12'} 'b2'} into another cell so that it has the same number of columns as 'cc' then you get
>> theCellArray = {{'aa1' {{'bb' {'b1' {'b11' 'b12'} 'b2'}}; 'cc'}}; {'aa2' {'dd'; 'ee'}}};
>> recCat(theCellArray)
ans =
'aa1.bb.b1.b11.b12.b2'
'aa1.cc'
'aa2.dd'
'aa2.ee'
However, you probably meant b11 and b12 to be on the same column not row so in that case:
>> theCellArray = {{'aa1' {{'bb' {'b1' {'b11';'b12'} 'b2'}}; 'cc'}}; {'aa2' {'dd'; 'ee'}}};
>> recCat(theCellArray)
ans =
'aa1.bb.b1.b11.b2'
'aa1.bb.b1.b12.b2'
'aa1.cc'
'aa2.dd'
'aa2.ee'
Here's a sweet one:
out = cellfun(#(y) cellfun(#(x) [ y{1} '.' x],y{2},'UniformOutput',false),theCellArray,'UniformOutput',false)
out{:}
ans =
'aa1.bb'
'aa1.cc'
ans =
'aa2.dd'
'aa2.ee'
Super One liner! (but not very efficient) And only works with original pose of question with 2 levels of cell strings.
I have a little problem with the performance of one of my applications, basically:
An external system gives me a big structure as an Object(,).
This structure only has an column per row.
MyData(0,0) = 'COL1-ROW1 | COL2-ROW1 | COL3-ROW1'
MyData(1,0) = 'COL1-ROW2 | COL2-ROW2 | COL3-ROW2'
MyData(2,0) = 'COL1-ROW3 | COL2-ROW3 | COL3-ROW3'
MyData(3,0) = 'COL1-ROW4 | COL2-ROW4 | COL3-ROW4'
MyData(0,1) ' Doesn't exists.
There are some method in LINQ to convert this structure to an one dimensional array of strings?
It would be awesome if you could divide by columns, given a specific character.
Something like this:
NewData(0,0) = COL1-ROW1
NewData(0,1) = COL2-ROW1
NewData(0,2) = COL3-ROW1
NewData(1,0) = COL1-ROW2
...
NewData(3,2) = COL3-ROW3
Seems I found the answer from myself; here my solution:
Dim vMyData(1000, 0) As Object
For x = 0 To 1000
vMyData(x, 0) = String.Format("ROW{0}COL1|ROW{0}COL2|ROW{0}COL3|ROW{0}COL4", x)
Next
Dim vQuery = From TempResult In vMyData
Select Value = TempResult.ToString.Split("|")
Dim vMyNewArray As New ArrayList(vQuery.ToArray)
Now; exists some method to trim each value of the Split("|")?
[UPDATE TO THE PREVIOUS QUESTION]:
From TempResult In vMyData Select Value = Array.ConvertAll(TempResult.ToString.Split("|"), Function(vVal) vVal.ToString.Trim)
I have an array:
step1 = [0,0;
0,1;
1,1;
2,3;
3,4;
3,5;
3,6;
3,7;
4,7;
5,7;
6,7;
6,6;
6,5;
6,4;
6,3;
6,2;
5,1];
I want to step through this array and create new arrays for the row and column that increment by 0.1 from one row to another. This is what I did:
z=1;
u=length(step1);
step_b4X = zeros(u,1);
step_b4Y = zeros(u,1);
while z <= length(step1)
step_b4X = step_presentX;
step_presentX(z,1) = step1(z,1);
step_b4Y = step_presentX;
step_presentY(z,1) = step1(z,2);
pathX = step_b4X:0.1:step_presentX;
pathY = step_b4Y:0.1:step_presentY;
z = z+1;
end
I get zeros.
I want pathX = 0:0.1:0....pathY = 0:0.1:1
next pathX = 0:0.1:1....pathY = 1:0.1:1... and so on
If you do
start:increment:end
where start == end, you'll get a scalar equal to start (which is logical).
If you want pathX and pathY to have the same length at each iteration, you'll have to do this:
z = 1;
while z <= length(step1)
currentX = step(z,1); nextX = step(z+1,1);
currentY = step(z,2); nextY = step(z+1,2);
pathX = currentX : 0.1 : nextX;
pathY = currentY : 0.1 : nextY;
if numel(pathX) == 1
pathX = repmat(pathX, numel(pathY),1); end
if numel(pathY) == 1
pathY = repmat(pathY, numel(pathX),1); end
z = z+1;
end
Now you'll have the right arrays at each iteration, that you'll use directly or save in a cell-array for later. If you want everything in one big array, add this to the end of the loop:
pathX_final = [pathX_final; pathX];
pathY_final = [pathY_final; pathY];
and initialize them as empty before the loop, of course.
Alternatively (much cleaner and possibly a bit faster), ditch the whole loop and use interp1:
x = step1(:,1);
y = step1(:,2);
xx = interp1(1:numel(x), x, 1:0.1:numel(x));
yy = interp1(1:numel(y), y, 1:0.1:numel(y));