I have a function that is part of an object that I have name TestData. Here are the properties and its constructor:
classdef TestData
properties
metaData = []; % stores meta data in Nx2 array
data = []; % stores data in PxQ array
colLabels = []; % labels columns
colUnits = []; % provides units
temp = []; % temporary to bypass setters while structuring data
end
methods
%% Constructor
function this = TestData(varargin) % Will take in a variable number of inputs
if (nargin == 0)
return;
end
if (nargin == 1 && ischar(varargin{1})) % Case of the input being a file (.txt, .s*p, etc..)
this = readDataFromFile(this, varargin{1});
return;
elseif (nargin == 4) % Case of the input being raw data. Note that the order matters.
this.metaData = varargin{1};
this.colLabels = varargin{2};
this.colUnits = varargin{3};
this.data = varargin{4};
return
else
error('Not enough input arguments.');
end
end
Now, let us say that I have 42 text files that I want to pass into the object. I have created a function for this called extractData that sifts through the data and finds a user input x-axis and y-axis. It does so by first calling a function readDataFromFile, which sets the property arrays that are outlined in the code above. It is a fairly long function and I won't include it for the time being, but I will say that I do know it is working.
The problem: I make an object of the class called myTestData and perform this operation in the CW, myTestData=myTestData.extractData('Tip Type','Tip S/N'). This will look for the Tip Type and Tip S/N. As you can see in the code, the type and S/N are in column 3 of the matrix. If the string is found, it takes the row it was found on, accesses column 3 of that row, and places that value into the temp array. In my case, the type is passive and the S/N is AM66191. It will write this to the temp array, but then on the second iteration of the for loop it will write something else over the first row and the passive and AM66191 will be displayed on the second row. It will do this all the way until the end, where on row 42 I will see the type and S/N, but all the other rows are just garbage. I have attached an image of what the temp array looks like after the second iteration of the for loop. Here is the code for the extractData function:
function this = extractData(this, xAxis, yAxis)
s = dir('*.txt'); % Gather all text files
disp(length(s))
for i=1:length(s) % Loop through and gather data until last element of strcuct
j = 1;
fid = s(i).name; % Open file in read-only mode
this = this.readDataFromFile(fid);
disp(fid)
x = this.metaData(find(contains(this.metaData(:,1), xAxis)),3);
this.temp(i,j) = x;
disp(this.temp(i,j))
j = j+1;
y = this.metaData(find(contains(this.metaData, yAxis)),3); %#ok<*FNDSB>
this.temp(i,j) = y;
disp(this.temp(i,j))
end %for
end %extractData
Related
I'm trying to write a function that iteratively loops through a bunch of .txt files in a directory and processes them individually. After a file has been processed I would like to plot output variables, then on the next iteration plot the new variables on the same graph. My code is shown below however does not seem to be working, it returns a 'output argument 'output1' (and maybe others) not assigned during call to function2.
Currently my code looks something like this:
function [output1, output2, fig] = Processing(Folder_1,Folder_2,Folder_3)
%% Read in all the Data
% Initialise Loop to process each file independently
for i = 1 : length(Text_Files1)
Sorted_Index1 = Indices1(i);
Path1 = fullfile(Folder_1,Text_Files1(Sorted_Index1).name);
Table1 = readtable(Path1);
Sorted_Index2 = Indices2(i);
Path2 = fullfile(Folder_2,Text_Files2(Sorted_Index2).name);
Table2 = readtable(Path2);
Sorted_Index3 = Indices3(i);
Path3 = fullfile(Folder_3,Text_Files3(Sorted_Index3).name);
Table3 = readtable(Path3,'Delimiter',';');
%% Process Data through the Loop
[HR] = function1(processed_data)
[output1 output2] = function2(HR, Time);
hold on
fig = figure('Visible', false);
subplot(10,10,1:90)
plot(output2, output1, 'Color', [0.92 0.47 0.44], 'LineWidth', 1.5);
end
end
%% Function 2:
function [output1, output2] = function2(t, y, z)
segment = 1:z:max(y);
% Iterate through each time segment and calculate average t value
for x = 1:length(segment)-1
SegmentScores = find(y > segment(x) & ...
y < segment(x+1));
output1(x) = mean(y(SegmentScores));
output2(x) = Segment(x+1);
end
end
The problem is that you're calling function2(HR, Time) with two inputs, while it needs three function2(t, y, z).
For that reason, I'm assuming that inside function2 segment is an empty array, and thus the loop for x = 1:length(segment) - 1 is not entered at all.
Since the definition of output1 and output2 is only inside the loop, they will never be created and thus the error.
If you provide three inputs to your function2, the problem will be solved. Just pay attention to the order in which you provide them (for example, I'm assuming your Time input should be the same as t in the function, so it should be the first input to be passed).
I have a set of 501 XYZ files which I load in as
for k = 1:501
% AIS SEC data
AIS_SEC{k} = importdata(['AIS_SEC(' num2str(k) ').xyz']);
end
This generates an 1x501 cell array in which all data are stored (I uploaded this file as in attachment at https://nl.mathworks.com/matlabcentral/answers/486579-how-to-merge-multiple-xyz-files-into-1-large-array). How can I merge all these data to have 1 large XYZ file? The ultimate goal is the have a nx3 array where all of the data from the seperate xyz files are merged in to 1.
For example, to concentrate X data, I tried:
for k = 1:501
my_field = sprintf('X%d', k);
variable.(my_field) = ([AIS_SEC{1,k}.data(:,1)]);
end
BUT: Dot indexing is not supported for variables of this type.
Thanks!
There are several wrong things with your code:
First thing, the error Struct contents reference from a non-struct array object. shows up first at index k=33 because the structure imported has no data field (the import was probably empty or failed).
Checking for the presence of the field let the code run through to completion. You'll then notice that you have 8 rows which are empty.
load('AIS_SEC.mat')
n=numel(AIS_SEC) ;
EmptyRows = false(n,1) ;
for k = 1:n
my_field = sprintf('X%03d', k);
if isfield( AIS_SEC{1,k} , 'data')
variable.(my_field) = AIS_SEC{1,k}.data;
else
variable.(my_field) = [] ;
EmptyRows(k) = true ;
end
end
fprintf('Number of empty rows encountered: %u\n',sum(EmptyRows))
I took the liberty to also remove unnecessary parenthesis, added an empty row index counter, and adjusted the sprintf output format so all your field will have the same length (even the first field will have the leading zeros. 'X001' to 'X500' instead of 'X1' to 'X500').
Also, this was only retrieving the first column out of each structure, so I modified it to retrieve the 3 x,y,z columns. If you really wanted only the first column, just replace variable.(my_field) = AIS_SEC{1,k}.data by variable.(my_field) = AIS_SEC{1,k}.data(:,1).
Now this gives you a long structure with 500 fields (each representing one imported variable). Your question is not clear enough on that point but if you want to have a single array where all the values are merged, then you have 2 options:
1) Directly after the code above, convert your structure to a merged array:
vararray = cell2mat(struct2cell(variable)) ;
2) If the steps above (the final variable structure) is not something you need to keep, then you can avoid it in the first place:
load('AIS_SEC.mat')
n = numel(AIS_SEC) ; % number of field to import
% first pass we count how many data point (if any) each structure has
EmptyRows = false(n,1) ;
npts = zeros(n,1) ;
for k = 1:n
if isfield( AIS_SEC{1,k} , 'data')
npts(k) = size( AIS_SEC{1,k}.data , 1 ) ;
else
EmptyRows(k) = true ;
end
end
% fprintf('Number of empty rows encountered: %u\n',sum(EmptyRows))
% The above allows us to preallocate the output matrix at the right size
cumpts = cumsum(npts) ;
totalNumberOfPoints = cumpts(end) ;
vararray = zeros(totalNumberOfPoints,3) ;
% first field to import
vararray( 1:cumpts(1) , : ) = AIS_SEC{1,1}.data ;
% now all the remaining ones
for k = 2:n
idx = (cumpts(k-1)+1):cumpts(k) ;
if ~isempty(idx)
vararray(idx,:) = AIS_SEC{1,k}.data ;
end
end
In this version there are 2 passes of the loop accross the structure. Counter intuitively this is done for better performances. The first pass is only to count the number of data points in each structure (and also to flag the empty ones). Thanks to the number returned by the first pass, we can preallocate the output matrix before the second pass and assign each structure data to the merged array in the right place without having to resize the output array at each iteration.
My code is below. In the code, I am evaluating only the data in the 'fb2010' file. I want to add other files" 'fb2020', 'fb2030', and 'fb2040' and evaluate their data by the same code. My question is how to apply a for loop and include the other data files. I tried, but I got confused by the for loop.
load('fb2010'); % loading the data
x = fb2010(3:1:1502,:);
% y_filt = filter(b,a,x); % filtering the received signal
y_filt= filter(b,a,x,[],2);
%%%%%%% fourier transform
nfft = length(y_filt);
res = fft(y_filt,nfft,2)/nfft;
res2 = res(:,1:nfft/2+1); %%%% taking single sided spectrum
res3 = fft(res2,[],2);
for i = 3:1:1500 %%%% dividing each row by first row.
resd(i,:) = res3(i,:)./res3(1,:);
end
I'm assuming that your files are MAT-files, not ASCII. You can do this by having load return a struct and using dynamic field referencing:
n = 4;
for i = 1:n
vname = ['fb20' int2str(i) '0']; % Create file/variable name based on index
s = load(vname); % Load data as struct (overwriting previous s)
x = s.(vname)(3:1:1502,:); % Access struct with dynamic field reference
% Rest of your code
...
end
If you're using a plain ASCII file, load won't produce a struct. However, such files are much simpler (see documentation for load/save). The following code would probably work:
n = 4;
for i = 1:n
vname = ['fb20' int2str(i) '0']; % Create file/variable name based on index
s = load(vname); % Load data as matrix (overwriting previous s)
x = s(3:1:1502,:); % Directly index matrix
% Rest of your code
...
end
It would be a good idea to add the file extension to your load command to make your code more readable.
I am implementimg a BTC from matlab to the SHARC ADSP-21369 EZ-Kit to edit parameters for a simple 3-band-EQ during the board's runtime.
I have a class in MatLAB including the methods for accessing, writing and reading the BTC and i have initialized the channels in VisualDSP++ like shown in the getting started example.
My problem is as follows:
I transmit filter coefficients for a biquad filter, so the numerator-coefficients are 3x1 cell array, and the denominator-coeffs are a 2x1 cell array
If i try to send these values through the BTC, the BTC memory window shows me that only one single coefficient of the array is edited, the others get 0. A very interesting point is, that in the 3x1 cell array the 2nd coefficient is edited, the first and the third get zero.
I need to present this work on Monday, so quick solutions are appreciated.
The function code is below.
classdef accessBTC < handle
properties
numChannels = [];
isInitialized = 0; %Logical 0 or 1 to indicate if the class is instantiated to connect to the VisualDSP session
end
properties(SetAccess = private)
channelList = {}; % Array of channel objects
end
methods
function initialize(obj)
a = actxserver('VisualDSP.ADspApplication');
btcPlugin = a.PluginList.invoke('Item','BtcManager');
btcManager = btcPlugin.Open;
btcChannelList = btcManager.ChannelList(int16(0)); % Get the channel list in processor #0 (always INT16)
obj.numChannels = btcChannelList.Count;
disp(['Total Number of Channels: ', num2str(obj.numChannels)]);
% Create the BTC Channel interfaces
for i = 1: obj.numChannels
obj.channelList{i} = btcChannelList.invoke('Item',int32(i-1));
end
obj.isInitialized = 1;
% S=saveobj(obj);
end % End of Method: INITIALIZE
function outVal = read(obj,channelNum,width)
% Default width is 32; other possible values: 16, 8
% Channel num starts frm 0
if nargin ==2
width = 32;
end
widthStr = ['btcWidth',num2str(width)];
btcChan = obj.channelList{channelNum};
out_val = btcChan.Read(widthStr);
outVal = cell2mat(out_val);
end % End of Method: READ
function write(obj, channelNum, val)
% input val needs to be a scalar or a vector of int32 or in16 or
% int8 values
% Channel num starts frm 0
if nargin ~=3
error('WRITE method for accessBTC object needs 2 inputs.')
end
btcChan = obj.channelList{channelNum+1};
btcChan.Write('btcWidth32',num2cell(val));
end %End of Method: WRITE
function reset(obj)
obj.numChannels = [];
obj.isInitialized = 0;
obj.channelList = [];
end %End of Method: RESET
end
so if i sending for example these single arrays
num_1 = [1.324; -1.45; 0.83]
den_1 = [-1.45; 0.74]
i am getting in my BTC memory window as floating point
num_1 = [0.0000000; -1.45; 0.0000000]
den_1 = [-1.45; 0.0000000]
has anybody an idea how to fix this?
i will add some pictures now, that you can cisualize my problem:
matlab-debug
vdsp-debug
thanks a lot and best regards,
markus
I have hit a roadblock where I am trying to iterate through a structure formed in the MATLAB workspace inside an EML (Embedded Matlab) function block in SIMULINK. Here is some example code:
% Matlab code to create workspace structure variables
% Create the Elements
MyElements = struct;
MyElements.Element1 = struct;
MyElements.Element1.var1 = 1;
MyElements.Element1.type = 1;
MyElements.Element2 = struct;
MyElements.Element2.var2 = 2;
MyElements.Element2.type = 2;
MyElements.Element3 = struct;
MyElements.Element3.var3 = 3;
MyElements.Element3.type = 3;
% Get the number of root Elements
numElements = length(fieldnames(MyElements));
MyElements is a Bus type Parameter for the MATLAB Function Block (EML) in SIMULINK. Below is the area I am running into trouble with. I know the number of elements inside my struct and I know the names, but the number of elements can change with any configuration. So I cannot hardcode based on the Element names. I have to iterate through the struct inside the EML block.
function output = fcn(MyElements, numElements)
%#codegen
persistent p_Elements;
% Assign the variable and make persistent on first run
if isempty(p_Elements)
p_Elements = MyElements;
end
% Prepare the output to hold the vars found for the number of Elements that exist
output= zeros(numElements,1);
% Go through each Element and get its data
for i=1:numElements
element = p_Elements.['Element' num2str(i)]; % This doesn't work in SIMULINK
if (element.type == 1)
output(i) = element.var1;
else if (element.type == 2)
output(i) = element.var2;
else if (element.type == 3)
output(i) = element.var3;
else
output(i) = -1;
end
end
Any thoughts on how I can iterate through a struct type in SIMULINK? Also, I cannot use any extrinsic functions like num2str because this is to be compiled on a target system.
I believe you are trying to use dynamic field names for structures. The correct syntax should be:
element = p_Elements.( sprintf('Element%d',i) );
type = element.type;
%# ...