Reading in numbers between parentheses - matlab

I am trying to import numbers between parentheses in Matlab. I am using the software OpenFoam that produces a file that extract velocity's (u,v,w) at a number of different positions for different time steps. I would like to import these velocity so I could take their average over a certain time intervall. I have about 250 probes in my flow domain, meaning I would like to import 750 different numbers for a number of different time steps. The file looks like this:
Link to file:
https://drive.google.com/file/d/1CuoflLADasUybsR4UJf1PQBUcGD0SsVb/view?usp=sharing
So I would like to import all the numbers in to a matrix with size ((number of time steps) X (probes))
I found a code that does works and imports these numbers, but this is very manual.I would have to write out probexx(i,:) = (str2double(split(out{i,1}{1,xx})))'; manually 250 times to get it to work. I would like to have a more automatic code, so I could change the number of probes easily. Could any one help me?
Thank you in advance!
id = fopen('probe.dat','r');
t = textscan(id,'%s','delimiter',sprintf('\n'));
fclose(id);
out = regexp(t{1,1}(6:end-3), '(?<=\()[^)]*(?=\))', 'match', 'all');
probe0 = zeros(size(out,1),3);
probe1 = zeros(size(out,1),3);
for i = 1:size(out,1)
if ~isempty(out{i,:})
probe0(i,:) = (str2double(split(out{i,1}{1,1})))';
probe1(i,:) = (str2double(split(out{i,1}{1,2})))';
else
probe0(i,:) = [0,0,0];
probe1(i,:) = [0,0,0];
end
end

I would do it like this assuming that each row is uniform after the header lines.
id = fopen('probes.dat','r');
t = textscan(id,'%f','Delimiter',{'(',')',' '},'MultipleDelimsAsOne',true,'headerlines',5);
fclose(id);
numProbes = 254;
temp = reshape(t{1},numProbes*3+1,[]);
outData.time = temp(1,:).';
for ii = 1:numProbes
rowIdx = (ii-1)*3+2:(ii-1)*3+4;
outData.(num2str(ii,'probe%d')) = temp(rowIdx,:).';
end
Basically read all of the numeric data into 1 array. Using the multiple delimiters feature and specifying the number of header lines. Next reshape based on the number of probes (in your example DAT there was 254).
Then loop over the number of probes to assign it to fields of a structure with the variable names that you want (probeXX).
This leaves you with a structure of the form:
outData =
time: [47x1 double]
probe1: [47x3 double]
probe2: [47x3 double]
probe3: [47x3 double]
...
probe254: [47x3 double]

Related

save columns of matrix in vector variables in Matlab

In Matlab (R2021b) I am using some given function, which reads time-dependent values of several variables and returns them in a combined matrix together with a time vector. In the data matrix each column represents one vector of time-dependent values for one variable.
[data,time] = function_reading_data_of_several_values('filename');
For readability of the following code where the variables are further processed, I would like to store these columns in separate vector variables. I am doing it like that:
MomentX = data(1,:);
MomentY = data(2,:);
MomentZ = data(3,:);
ForceX = data(4,:);
ForceY = data(5,:);
ForceZ = data(6,:);
That is working. But is there some simpler (or shorter) way of assigning the column of the matrix to individual vectors? I am asking because in real program I have more than the 6 columns as in the example. Code is getting quite long. I was thinking of something similar to the line below, but that does not work:
[MomentX,MomentY,MomentZ,ForceX,ForceY,ForceZ] = data; %does not work
Do you have any idea? Thanks for help!
Update:
Thanks to the hint here in the group to use tables, a solution could be like this:
...
[data,time] = function_reading_data_of_several_values('filename');
% data in matrix. Each column representing a stime dependent variable
varNames = {'MomentX', 'MomentX',...}; % Names of columns
T=array2table(data','VariableNames',varNames); % Transform to Table
Stress = T.MomentX/W + T.ForceY/A %accesing table columns
...
This seems to work fine and readable to me.
Solution 1: In industrial solutions like dSpace, it is very common to do it in struct arrays:
mydata.X(1).time = [0.01 0.02 0.03 0.04];
mydata.Y(1).name = 'MomentX';
mydata.Y(1).data = [1 2 3 4];
mydata.Y(2).name = 'MomentY';
mydata.Y(2).data = [2 3 4 5];
Solution 2: It is also very common to create tables
See: https://de.mathworks.com/help/matlab/ref/table.html
As already commented, it is probably better to use a table instead of separate variables may not be a good idea. But if you want to, it can be done this way:
A = magic(6): % example 6-column matrix
A_cell = num2cell(A, 1); % separate columns in cells
[MomentX, MomentY, MomentZ, ForceX, ForceY, ForceZ] = A_cell{:};
This is almost the same as your
[MomentX,MomentY,MomentZ,ForceX,ForceY,ForceZ] = data; %does not work
except that the right-hand side needs to be a comma-separated list, which in this case is obtained from a cell array.

How do I find out in which strucutre my matlab variable is stored in?

I have raw data in a .mat format. The Data is comprised of a bunch of Structures titled 'TimeGroup_XX' where xx is just a random number. Each one of these structures contains a bunch of signals and their corresponding time steps.
It looks something like this
TimeGroup_45 =
time45: [34069x1 double]
Current_Shunt_5: [34069x1 double]
Voltage_Load_5: [34069x1 double]
This is simply unusable, as I simply do not know where the variable I am looking for is hiding in 100's of the structures contained in the raw data. I just know that I am looking for 'Current_Shut_3' for example!
There has to be a way that would allow me to do the following
for all variables in Work space
I_S3 = Find(Current_Shut_3)
end for
Basically I do not want to manually click through every structure to find my variable and just want it to be saved in a normal time series instead of it being hidden in a random structure! Any suggestion on how to do it? There has to be a way!
I have tried using the 'whos' command, but did not get far, as it only returns a list of the stored strucutres in the workspace. I cannot convert that text to a variable and tell it to search for all the fields.
Thanks guys/girls!
This is a great example of why you shouldn't iterate variable names when there are plenty of adequate storage methods that don't require code gymnastics to get data back out of. If you can change this, do that and don't even bother reading the rest of this answer.
Since everything is apparently contained in one *.mat file, specify an output to load so it's output into a unified structure and use fieldnames to iterate.
Using the following data set, for example:
a1.Current_Shunt_1 = 1;
a2.Current_Shunt_2 = 2;
a5.Current_Shunt_5 = 5;
b1.Current_Shunt_5 = 10;
save('test.mat')
We can do:
% Load data
alldata = load('test.mat');
% Get all structure names
datastructs = fieldnames(alldata);
% Filter out all but aXX structures and iterate through
adata = regexpi(datastructs, 'a\d+', 'Match');
adata = [adata{:}];
queryfield = 'Current_Shunt_5';
querydata = [];
for ii = 1:numel(adata)
tmp = fieldnames(alldata.(adata{ii}));
% See if our query field is present
% If yes, output & break out of loop
test = intersect(queryfield, tmp);
if ~isempty(test)
querydata = alldata.(adata{ii}).(queryfield);
break
end
end
which gives us:
>> querydata
querydata =
5

Import numbers between parentheses

I have made a datafile from OpenFoam that extracts velocity at a certain location in time. I would like to extract two of these velocity and take there time average. For example I would like to extract the numbers: 0.0539764,0.0104665,0.00201741 and so on from probe 0. And extract the numbers: 0.690374, 0.711402, 0.699848 and so on from probe 1. How can this be done in Matlab?
I have done something similar before, but then the probes only consisted of 1 number (without the parentheses), now it consist of 3 numbers inscribed in a parentheses, I don't know what I am supposed to do.
Help is much appreciated.
Link to the whole file: https://drive.google.com/file/d/0B9CEsYCSSZUSdjFzYXVFc1RhM0k/view?usp=sharing
This will create two matrices probe0 & probe1. You can index just the first column of each if that is all you are after.
id = fopen('testprobe.txt','r');
t = textscan(id,'%s','delimiter',sprintf('\n'));
fclose(id);
out = regexp(t{1,1}(6:end-3), '(?<=\()[^)]*(?=\))', 'match', 'all');
probe0 = zeros(size(out,1),3);
probe1 = zeros(size(out,1),3);
for i = 1:size(out,1)
if ~isempty(out{i,:})
probe0(i,:) = (str2double(split(out{i,1}{1,1})))';
probe1(i,:) = (str2double(split(out{i,1}{1,2})))';
else
probe0(i,:) = [0,0,0];
probe1(i,:) = [0,0,0];
end
end

How to apply an equation to multiple columns separately in a matrix?

I have 4 different lengths of data (in rows) and they all have a differing ammount of columns. I need to apply an equation to each of these columns and then extract the max value from each of them.
The equation I am trying to use is:
averg = mean([interpolate(1:end-2),interpolate(3:end)],2); % this is just getting your average value.
real_num = interpolate(2:end-1);
streaking1 = (abs(real_num-averg)./averg)*100;
An example of one of my data sets is 5448 rows by 13 columns
EDIT
This is the current adapation of Ben A.'s Solution and it is working.
A = interpolate;
averg = (A(1:end-2,:) + A(3:end,:))/2;
center_A = A(2:end-1,:);
streaking = [];
for idx = 1:size(A,2)
streaking(:,idx) = (abs(center_A(idx,:)-averg(idx,:))./averg(idx,:))*100;
end
I'm not entirely sure that I fully follow what you're doing in each step, but here is a stab at it:
A = interpolate;
averg = (A(1:end-2,:) + A(3:end,:))/2;
center_A = A(2:end-1,:);
streaking = [];
for idx = 1:size(A,2)
streaking(:,idx) = (abs(center_A(idx,:)-averg(idx,:))./averg(idx,:))*100;
end
Averg will be a vector of means for each column. I just use the values in the given column as the real_num variable that you had before. I'm not clear why you would need to index that the way you are as nothing is at risk of breaking index rules.
If this helps, great! If not let me know and I'll see if I can revise somewhat.

matlab averages of cell array

I have the following script for importing text files into matlab which include hourly data, where I am then trying to convert them into daily averages:
clear all
pathName = ...
TopFolder = pathName;
dirListing = dir(fullfile(TopFolder,'*.txt'));%Lists the folders in the directory specified by pathName.
for i = 1:length(dirListing);
SubFolder{i} = dirListing(i,1).name;%obtain the name of each folder in
%the specified path.
end
%import data
for i=1:length(SubFolder);
rawData1{i} = importdata(fullfile(pathName,SubFolder{i}));
end
%convert into daily averages
rawData2=cell2mat(rawData1);
%create one matrix for entire data set
altered=reshape(rawData2,24,(size(rawData2,2)*365));
%convert into daily values
altered=mean(altered)';
%take the average for each day
altered=reshape(altered,365,size(rawData2,2));
%convert back into original format
My problem lies in trying to convert the data back into the same format as 'rawData1' which was a cell for each variable (where each variable is denoted by 'SubFolder'. The reason for doing this is that all but one of the variables are vectors, where the remaining variable is a matrix (8760*11).
So, an example of this would be:
clear all
cell_1 = rand(8760,1);
cell_2 = rand(8760,1);
cell_3 = rand(8760,1);
cell_4 = rand(8760,1);
cell_5 = rand(8760,1);
cell_6 = rand(8760,11);
cell_7 = rand(8760,1);
cell_8 = rand(8760,1);
cell_9 = rand(8760,1);
data = {cell_1,cell_2,cell_3,cell_4,cell_5,cell_6,cell_7,cell_8,cell_9};
Where I need to convert each cell in 'data' from hourly values into daily averages (i.e. 365 rows).
Any advice would be much appreciated.
I think this does what you want.
data = cellfun(#(x) reshape(mean(reshape(x,24,[]))',365,[]),data,'uniformoutput',false);
However that is kind of confusing so I will explain a little.
This part mean(reshape(x,24,[]))' inside of the cellfun will reshape each cell in data into a 24 by 365, compute the mean, then turn it back into a single column. This works fine when the original data only has 1 column ... but for cell_6 with 11 columns it puts all the data end to end. So I added an addition reshape(...) wrapper around the mean(...) part to put it back into the original 11 columns ... or more precises N columns that are 365 rows in length.
Note: This is going to give you errors if you ever have data sets dimensions are not 8760 by X.