MATLAB: ??? In an assignment A(I) = B, the number of elements in B and I must be the same - matlab

I'm doing a project modelling the flow of sauce around pasta, using a BEMLIB code for stokes flow called prtcl_3d_ss_visualize.m which is available from "http://dehesa.freeshell.org/BEMLIB/". Here is the code:
%---
file2 = fopen('prtcl_3d_ss_visualize.m')
Npnt = fscanf(file2,'%f',[1,1])
Nvert = fscanf(file2,'%f',[1,1])
Nface = fscanf(file2,'%f',[1,1])
vert = fscanf(file2,'%f',[3,Nvert]);
wall = fscanf(file2,'%f',[1,1])
fclose(file2)
%---
for i=1:Nvert
save = vert(2,i);
vert(2,i) = vert(3,i);
vert(3,i) = save;
end
Ic=0;
for i=1:Nface
for j=1:Npnt
Ic=Ic+1;
fac(j,i) = Ic;
end
end
patch('faces',Nfac’,'vertices',vert’,...
'FaceColor','y',...
'FaceLighting','phong',...
'BackFaceLighting','lit')
%light('Position',[1 3 2]);
%light('Position',[-3 -1 3]);
%material dull
%material shiny
%axis vis3d off
axis([-1.5 1.5 -1.5 1.5 -0.5 2.5 ])
%view(45,34)
xlabel('x')
ylabel('z')
zlabel('y')
xw(1)=-1.5; zw(1)=-1.5; yw(1)=wall;
xw(2)= 1.5; zw(2)=-1.5; yw(2)=wall;
xw(3)= 1.5; zw(3)= 1.5; yw(3)=wall;
xw(4)=-1.5; zw(4)= 1.5; yw(4)=wall;
xw(5)=-1.5; zw(5)=-1.5; yw(5)=wall;
patch(xw,zw,yw,yw);
hold off
I have encountered several errors when inputing the code in matlab, the first of which i solved changing fopen('prtcl_3d') to fopen('partcl_3d_ss_visualize.m') which is the name of he file.
The second error I came up against was where I input
patch('faces',Nfac’,'vertices',vert’,...
'FaceColor','y',...
'FaceLighting','phong',...
'BackFaceLighting','lit')
Nfac' was orighinally fac'but i got error "??? Undefined function or variable fac" so I changed it to an already defined variable Nfac.
The problems I am now faced with the last part of the code. When I enter the first line
xw(1)=-1.5; zw(1)=-1.5; yw(1)=wall;
I get the error message: "??? In an assignment A(I) = B, the number of elements in B and I must be the same."
I get this for the rest of the xw,zw,yw inputs too, what am I doing wrong?

I solved changing fopen('prtcl_3d') to
fopen('partcl_3d_ss_visualize.m') which is the name of he file.
No, you didn't solve it, you broke it. In the original script, partcl_3d_ss_visualize.m (or the version I found on the internets, at least), we have these lines:
file2 = fopen('prtcl_3d.net')
Npnt = fscanf(file2,'%f',[1,1])
Nvert = fscanf(file2,'%f',[1,1])
Nface = fscanf(file2,'%f',[1,1])
vert = fscanf(file2,'%f',[3,Nvert]);
wall = fscanf(file2,'%f',[1,1])
fclose(file2)
This opens some sort of data file prtcl_3d.net, and loads in some required values (this file is presumably included somewhere in the code you downloaded). What you are making it do is make the script load itself and try and find some non-existent floating point numbers at the start of the file.
Having done this, it is likely that the output of wall is empty. Therefore yw(1) (1 element) and wall (zero elements) have different sizes and when you try to assign one to the other you get an error.
Important Note: It won't error earlier because it was able to open the file and try to read something - it is your job to check if what was read in is correct. In this case, just manually looking at your workspace would have been enough. In other cases, error checking can be done using functions such as isempty, isnumeric, size, and so on depending on what sort of output you're expecting.
Regarding fac/Nfac, I imagine that this script does not stand alone and you are supposed to run another script or function before this one that creates the correct variables.
It says on that website:
BEMLIB is a boundary-element software library of Fortran 77 (compatible with Fortran 90) and Matlab codes accompanying the book by C. Pozrikidis, A Practical Guide to Boundary Element Methods with the software library BEMLIB,'' Champan & Hall/CRC, (2002). Chapters 8-12 of the book contain the BEMLIB User Guide
I suggest you need the BEMLIB User Guide to help you understand what the code does and how to use it, and until you do understand that you shouldn't be making any changes to it.

Related

Displaying Data as a String in Simulink RT Display Port

My issue involves using the RS-232 Simulink RT blocks.
A model is uploaded to the target PC (xPC) and it transmits and receives data from a variable frequency drive (VFD) that controls a motor. The issue arises on the receiving end when I take data and try to send that data to a display block in my model as a string. Code would be helpful here:
disp = uint8(zeros(1,24));
display = uint8(zeros(1,length(disp)));
cmd = 0;
status = stat_lb;
%% Start-Up
% Initialization Period
if (status == 0 || status == 1)
cmd = 0;
msg = uint8('Start up');
display = [msg uint8(zeros( 1, length(disp)- length(msg) ))];
end
...
%Multiple status cases with unique displays.
...
disp = display
So, here the cmd portion functions as expected. As noted above, I want to display the display string on a display block in my Simulink model. As you can see, though, it is of type uint8, so I need to convert it to type string; however, when I pass it through either the ascii2str Simulink block or just place it in the function call (e.g. display = ascii2str(display)) I get the following error message:
Executing the 'CheckData' command produced the following error: Invalid parameter/value pair arguments
My thought is that this has something to do with the fact that I am using MEX and this function (ascii2str) is not supported. Anyways, I am wondering if anyone knows why I receive this error and if there is anything I can do to resolve it.
Oh, and one last thing: I can get the display to work if I just remove the ascii2str; however, the only problem with this is that the display is in uint8 form and not really helpful. So, if there is any other way that I can decode the uint8 to a string I am all ears.
Thanks!
I have found that there is no support for this feature in Simulink RT. One option is to use external functions, but I found it better for my application to simply output a number and have a table in the simulation that explained what each number meant.

Simulink-Simulation with parfor (Parallel Computing)

I asked today a question about Parallel Computing with Matlab-Simulink. Since my earlier question is a bit messy and there are a lot of things in the code which doesnt really belong to the problem.
My problem is
I want to simulate something in a parfor-Loop, while my Simulink-Simulation uses the "From Workspace" block to integrate the needed Data from the workspace into the simulation. For some reason it doesnt work.
My code looks as follows:
load DemoData
path = pwd;
apool = gcp('nocreate');
if isempty(apool)
apool = parpool('local');
end
parfor k = 1 : 2
load_system(strcat(path,'\DemoMDL'))
set_param('DemoMDL/Mask', 'DataInput', 'DemoData')
SimOut(k) = sim('DemoMDL')
end
delete(apool);
My simulation looks as follows
The DemoData-File is just a zeros(100,20)-Matrix. It's an example for Data.
Now if I simulate the Script following error message occures:
Errors
Error using DemoScript (line 9)
Error evaluating parameter 'DataInput' in 'DemoMDL/Mask'
Caused by:
Error using parallel_function>make_general_channel/channel_general (line 907)
Error evaluating parameter 'DataInput' in 'DemoMDL/Mask'
Error using parallel_function>make_general_channel/channel_general (line 907)
Undefined function or variable 'DemoData'.
Now do you have an idea why this happens??
The strange thing is, that if I try to acces the 'DemoData' inside the parfor-Loop it works. For excample with that code:
load DemoData
path = pwd;
apool = gcp('nocreate');
if isempty(apool)
apool = parpool('local');
end
parfor k = 1 : 2
load_system(strcat(path,'\DemoMDL'))
set_param('DemoMDL/Mask', 'DataInput', 'DemoData')
fprintf(num2str(DemoData))
end
delete(apool);
Thats my output without simulating and displaying the Data
'>>'DemoScript
00000000000000000 .....
Thanks a lot. That's the original question with a lot more (unnecessary) details:
EarlierQuestion
I suspect the issue is that when MATLAB is pre-processing the parfor loop to determine what variables need to be passed to the workers it does not know what DemoData is. In your first example it's just a string, so no data gets sent over. In your second example it explicitly knows about the variable and hence does pass it over.
You could try either using the Model Workspace, or perhaps just inserting the line
DemoData = DemoData;
in the parfor loop code.
Your error is because workers did not have access to DemoData in the client workspace.
When running parallel simulations with Simulink it would be easier to manage data from workspace if you move them to model workspace. Then each worker can access this data from its model workspace. You can load a MAT file or write MATLAB code to initialize data in model workspace. You can access model workspace using the Simulink model menu View->Model Explorer->Model Workspace.
Also see documentation at http://www.mathworks.com/help/simulink/ug/running-parallel-simulations.html that talks about "Resolving workspace access issues".
You can also move the line
load DemoData
to within the parfor loop. Doing this, you assure that the data will be available in each worker base workspace, wich is accessible to the model, instead of the client workspace.

Can't open matlab file

I have a ".mat" file supposedly containing a [30720000x4 double] matrix (values from accelerometers). When I try to open this file with "Import data" in Matlab I get the following error:
Error using load
Can't read file F:\vibration_exp_2\GR_UB50n\bearing1\GR_UB50n_1_2.mat.
Error using load
Unknown text on line number 1 of ASCII file
F:\vibration_exp_2\GR_UB50n\bearing1\GR_UB50n_1_2.mat
"MATLAB".
Error in uiimport/runImportdata (line 456)
datastruct = load('-ascii', fileAbsolutePath);
Error in uiimport/gatherFilePreviewData (line 424)
[datastruct, textDelimiter, headerLines]= runImportdata(fileAbsolutePath,
type);
Error in uiimport (line 240)
[ctorPreviewText, ctorHeaderLines, ctorDelim] = ...
The filesize is 921MB which is the same as my other files that do open. I also tried opening the file using python, but no success. Any suggestions? I use MATLAB R2013b .
More info:
How the file was create:
%% acquisition of vibration data
% input:
% sample rate in Hz (max. 51200 Hz, should be used as bearing
% faults are high-frequent)
% time in seconds, stating the duration of the measurement
% (e.g. 600 seconds = 10 minutes)
% filename for the file to be saved
%
% examples:
% data = DAQ(51200, 600, 'NF1_1.mat');
% data = DAQ(51200, 600, 'NF1_2.mat');
function data = DAQ(samplerate,time,filename)
s = daq.createSession('ni'); % Creates the DAQ session
%%% Add the channels as accelerometer channels (meaning IEPE is turned on)
s.addAnalogInputChannel('cDAQ1Mod1','ai0','Accelerometer');
s.addAnalogInputChannel('cDAQ1Mod1','ai1','Accelerometer');
s.addAnalogInputChannel('cDAQ1Mod1','ai2','Accelerometer');
s.addAnalogInputChannel('cDAQ1Mod1','ai3','Accelerometer');
%s.addAnalogInputChannel('cDAQ1Mod2','ai0','Accelerometer');
s.Rate = samplerate;
s.NumberOfScans = samplerate*time;
%%% Defining the Sensitivities in V/g
s.Channels(1).Sensitivity = 0.09478; %31965, top outer
s.Channels(2).Sensitivity = 0.09531; %31966, back outer
s.Channels(3).Sensitivity = 0.09275; %31964, top inner
s.Channels(4).Sensitivity = 0.09363; %31963, back inner
data = s.startForeground(); %Acquiring the data
save(filename, 'data');
More info:
When I open the file using a simple text editor I can see a lot of characters that do not make sense​ but also the first line:
MATLAB 5.0 MAT-FILE, Platform: PCWIN64, Created on: Thu Apr 30
16:29:07 2015
More info:
The file itself: https://www.dropbox.com/s/r7mavil79j47xa2/GR_UB50n_1_2.mat?dl=0
It is 921MB.
EDIT:
How can I recover my data?
I've tried this, but got memory errors.
I've also tried this, but it did not work.
I fear I can't add many good news to what you know already, but it hasn't been mentioned yet.
The reason the .mat-file can't be load is due to the data beeing corrupted. What makes it 'unrecoverable' is the way it is stored internally. The exact format is specified in the MAT-File Format Documentation. So I decided to manually construct a simple reader to specifically read your .mat file.
It makes sense, that the splitmat.m can't recover anything, as it will basicly split the data into chunks, one stored variable per chunk, however in this case there is only 1 variable stored and thus only one chunk, which happens to be the corrupted one.
In this case, the data is stored as a miCOMPRESSED, which is a normal matlab array compressed using gzip. (Which, as a side note, doesn't seem like a good fit for 'random' vibration data.) This might explain previous comments about the smaller file size then the full data, as the filesize matches exatly with the internally stored value.
I extracted the compressed archive and tried to uncompress it in a variety of ways. Basicly it is a '.gz' without the header, that can be appended manually. Unfortunatly there seems to be a corrupted block near the start of the dataset. I am by no means an expert on gzip, but as far as I know the dictionary (or decryption key) is stored dynamicly which makes all data useless from the point the block is corrupted. If you are really eager, there seems to be a way to recover data even behind the point where data is corrupted, but that method is massively timeconsuming. Also the only way to validate data of those sections is manual inspection, which in your case might proof very difficult.
Below is the code, that I used to extract the .gz-file, so if you want to give it a try, this might get you started. If you manage to decrypt the data, you can read it as described in the MAT-File Format, 13f.
corrupted_file_id = fopen('corrupt.mat','r');
%% some header data
% can be skipped replacing this block with
% fread(id,132);
%header of .mat file
header_text = char(fread(corrupted_file_id,116,'char')');
subsystem_data_offset = fread(corrupted_file_id,8,'uint8');
version = fread(corrupted_file_id,1,'int16');
endian_indicator = char(fread(corrupted_file_id,2,'int8')');
data_type = fread(corrupted_file_id,4,'uint8');
%data_type is 15, so it is a compressed matlab array
%% save te content
data_size = fread(corrupted_file_id,1,'uint32');
gz_file_id = fopen('compressed_array.gz','w');
% first write a valid gzip head
fwrite(gz_file_id,hex2dec('1f8b080000000000'),'uint64',0,'b');
% then write the data sequentialy
step = 1:1e3:data_size;% 1MB steps
for idx = step
fwrite(gz_file_id,fread(corrupted_file_id,1e3,'uint8'));
end
step = step(end):data_size;% 1B steps
for idx = step
fwrite(gz_file_id,fread(corrupted_file_id,1,'uint8'));
end
fclose(gz_file_id);
fclose(corrupted_file_id);
To answer literally to the question, my suggestion would be to make sure first that the file is okay. This tool on File Exchange apparently knows how to diagnose corrupted .MAT files starting with version V5 (R8):
http://www.mathworks.com/matlabcentral/fileexchange/6893-matcat-mat-file-corruption-analysis-tool
The file's size (indices going out of range) seems to be a problem. Octave, which should read .mat files, gives the error
memory exhausted or requested size too large for range of Octave's index type
To find out what is wrong you may need to write a test program outside MatLab, where you have more control over memory management. Examples are here, including instructions on how to build them on your own platform. These stand-alone programs may not have the same memory issues. The program matdgns.c is specifically made to check .mat files for errors.

Trouble with running a parallelized script from a driver script

I'm trying to parallelize my code, and I finally got the parfor loops set up such that Matlab doesn't crash every time. However, I've now got an error that I can't seem to figure out.
I have a driver script (Driver12.m) that calls the script that I'm trying to parallelize (Worker12.m). If I run Worker12.m directly, it usually finishes with no problem. However, every time I try to run it from Driver12.m, it either 1) causes Matlab to crash, or 2) throws a strange error at me. Here's some of my code:
%Driver script
run('(path name)/Worker12.m');
%Relevant worker script snippet
parfor q=1:number_of_ranges
timenumber = squeeze(new_TS(q,:,:));
timenumber_shift = circshift(timenumber, [0 1]);
for m = 1:total_working_channels
timenumberm = timenumber(m,:);
for n = 1:total_working_channels
R_P(m,n,q) = mean(timenumberm.*conj(timenumber(n,:)),2);
R_V(m,n,q) = mean(timenumberm.*conj(timenumber_shift(n,:)),2);
end
end
end
Outcome #1: "Matlab has encountered an unexpected error and needs to close."
Outcome #2: "An UndefinedFunction error was thrown on the workers for ''. This might be because the file containing '' is not accessible on the workers. Use addAttachedFiles(pool, files) to specify the required files to be attached. See the documentation for 'parallel.Pool/addAttachedFiles' for more details. Caused by: Undefined function or variable ""."
However, if I run Worker12.m directly, it works fine. It's only when I run it from the driver script that I get issues. Obviously, this error message from Outcome #2 isn't all that useful. Any suggestions?
Edit: So I created a toy example that reproduces an error, but now both my toy example and the original code are giving me a new, 3rd error. Here's the toy example:
%Driver script
run('parpoolexample.m')
%parpoolexample.m
clear all
new_TS = rand([1000,32,400]);
[number_of_ranges,total_working_channels,~] = size(new_TS);
R_P = zeros(total_working_channels,total_working_channels,number_of_ranges);
R_V = zeros(total_working_channels,total_working_channels,number_of_ranges);
parfor q=1:number_of_ranges
timenumber = squeeze(new_TS(q,:,:));
timenumber_shift = circshift(timenumber, [0 1]);
for m = 1:total_working_channels
timenumberm = timenumber(m,:);
for n = 1:total_working_channels
R_P(m,n,q) = mean(timenumberm.*conj(timenumber(n,:)),2);
R_V(m,n,q) = mean(timenumberm.*conj(timenumber_shift(n,:)),2);
end
end
end
Outcome #3: "Index exceeds matrix dimensions (line 7)."
So, at the 'parfor' line, it's saying that I'm exceeding the matrix dimensions, even though I believe that should not be the case. Now I can't even get my original script to recreate Outcomes #1 or #2.
Don't use run with parallel language constructs like parfor and spmd. Unfortunately it doesn't work very well. Instead, use cd or addpath to let MATLAB see your script.

How to deselect cells in uitable / how to disable cell selection highlighting?

I created the following uitable:
actually every single row is an indpendent uitable, so the figure shown contains 5 uitables besides the header. Why I'm doing that was the issue of my last question, resulting in the shown table. Fully executable code you can find in the answer here (or a minimal example below). Solutions using a general GUI are also there, but it would blow up the code too much, and actually it just seems to be a kind of bug.
It can be seen that everytime I jump to the next row, therefore to another uitable, the last selection remains highlighted, which looks stupid, though it doesn't matter for the functionality.
There is the 'SelectionHighlight' property for uitables, sounds like a solution, but it is not changing anything. I used it as following:
set(src,'SelectionHighlight','off') %where src is the handle of the current uitable
at various places: at the end of a 'CellSelectionCallback', at the end of a 'CellEditCallback' and as global property. But everytime the last cell remains selected. Actually I don't need selection at all.
How can I disable the whole selection or selection highlighting property for all my uitables?
How do I have to use this property, that it has an effect?
Alternatively: how can I change the "highlighting" color (and therefore text-color) so the highlighting is just not visible anymore?
Apparently this issue appears also in other contexts.
I created a minimum executable example, where one can select a number between 1 and 3 in every row.
function minimalTable
%basic properties
line_height = 21.32;
table_height = 3*line_height;
lh = line_height/table_height;
h = figure('Position',[200 100 202 table_height],'numbertitle','off','MenuBar','none');
% addrow(figurehandle,number of row, percentage lineheight)
% every function call creates a new row, later dynamically
addRow(h,1,lh);
addRow(h,2,lh);
addRow(h,3,lh);
end
function modifySelection(src,~)
set(src,'SelectionHighlight','off')
waitfor(src)
end
function [th] = addRow(fh,k,lhp)
selector = { '1'; '2' ; '3' };
defaultData = {'select number...'};
columnformat = { {selector{:}} };
columneditable = true;
th = uitable(fh,'Units','normalized','Position',[0 1-k*lhp 1 lhp],...
'Data', defaultData,...
'ColumnName', [],...
'ColumnWidth', {200},...
'ColumnEditable', columneditable,...
'ColumnFormat', columnformat,...
'RowName',[],...
'SelectionHighlight','off',...
'CellEditCallback',#modifySelection);
end
results in:
After some deeper research I found out, that the Matlab Support comes out with the following solution:
%overwrite data with a dummy and restore the old data afterwards, to force deselection
function modifySelection(src,~)
...
temp = get(src,'Data')
set(src,'Data',{ 'dummy' });
set(src,'Data', temp );
end
Doing this the blue highlighting is gone, BUT the dotted line around the last selected cell remains!
But I found a solution resolving this, which also makes the first part dispensable.
function modifySelection(src,evt)
...
fh = get(src,'parent'); % get parent figure handle
copyobj(src,fh); % copy uitable to parent figure
delete(src); % delete current uitable
end
Which results in the desired behaviour:
Drawback of the second solution: it lags a little (probably just on slow machines), because of the creation of a new object.
Allright, I found a solution for deselecting cells:
First of all, this requires some Java. But dont worry, it will still look like Matlab :)
1. You will need the script findjobj by Yair Altman: TMW File-Exchange: findjobj
2. You need the handle of your table, lets call it mtable. Then you need the underlying Java-table and do some stuff to get the right objects and set some properties. You can do this by:
jscroll=findjobj(mtable);
h=jscroll.getComponents;
viewport=h(1);
a=viewport.getComponents;
jtable=a(1); %com.mathworks.hg.peer.ui.UITablePeer
jtable.setRowSelectionAllowed(0);
jtable.setColumnSelectionAllowed(0);
3. Now the more tricky part (at least it was for me): If you have some Callback for CellSelectionChanged, but you dont want to excecute this now, you have to turn it off temporary:
set(mtable, 'CellSelectionCallback', []);
Now you can change the selection by:
jtable.changeSelection(row-1,col-1, false, false);
%Java-> zero ^= one <-Matlab
And now, I was expecting, when setting the CellSelectionCallback back to its original function, everything would be fine. Nope, it was excecuting the Callback. I still dont know the exact reason, but it seems to me, that calling jtable.changeSelection() the selection changes and then is calling the specified Callback, but the caller function is not waiting while this process is running. So what I tried (and I dont know if this is the best way to do it, but it is working very well) is to just pause for a second and then set the Callabck back:
pause(1)
set(mtable, 'CellSelectionCallback', #myOriginalFunction);
4. Now just one more thing: My purpose was just to change the selection to some other cell. Yours is to deselect. I dont know anything about the Java components, but I succeeded by just setting the row/column parameter to -1:
jtable.changeSelection(-1,-1, false, false);
Finally I managed to solve this problem by using many things explained on undocumentedmatlab.com and other posts. I am not sure if all the lines are necessary to call. Note, that this will only be available for the documented Matlab-uitable which appears first in Version 2008 (a or b, I'm not sure about that).
EDIT there are a lot of other functions/parameters etc. you can use, that are undocumented. Just to see what is possible, you can take a look with the autocomplete. Just use it on the jtable. and Tab will display them. For a documentation on those elements you should probably search for a Java-doc.
Just a small "dynamic" minimal example (wait 3 seconds to see a change ;-) ):
function startUitable()
xDat=ones(5,3);
h=figure('Tag','TestFigure');
mtable=uitable('Tag','TestUITABLE');
rowField=uicontrol('units','normalized','Style','edit','Position',[0.4 0.9 0.1 0.1],'parent',h,'Tag','rowField');
colField=uicontrol('units','normalized','Style','edit','Position',[0.6 0.9 0.1 0.1],'parent',h,'Tag','colField');
set(mtable, 'Units','normalized','Position',...
[0.01 0.01 0.8 0.8], 'Data', xDat,...
'ColumnEditable', [false, false,false],...
'ColumnWidth', 'auto')
myButton=uicontrol('units','normalized','Style','pushbutton','parent',h,'Position',[0.04 0.9 0.3 0.1],'String','change Selection')
set(myButton,'Callback',#changeSelection)
end
function changeSelection(~,~,~)
mtable=findobj('Tag','TestUITABLE');
jscroll=findjobj(mtable);
h=jscroll.getComponents;
viewport=h(1);
a=viewport.getComponents;
jtable=a(1); %com.mathworks.hg.peer.ui.UITablePeer
% jtable.setRowSelectionAllowed(0);
% jtable.setColumnSelectionAllowed(0);
row=str2num(get(findobj('Tag','rowField'),'String'));
col=str2num(get(findobj('Tag','colField'),'String'));
jtable.changeSelection(row-1,col-1, false, false);
end