Is there any way to output/display information from a MATLAB program without an ending line feed?
My MATLAB program outputs a number a bit now and then. Between outputting the number the program does a lot of other stuff. This is a construct mainly to indicate some kind of progress and it would be nice not to have a line feed each time, just to make it more readable for the user. This is approximately what I'm looking for:
Current random seed:
4 7 1 1
The next output from the program would be on the same row if it is still doing the same thing as before.
I've read the doc on disp, sprintf, and format but haven't found what I'm looking for. This doesn't mean it isn't there. ;)
The fprintf function does not add a line feed unless you explicitly tell it to. Omit the fid argument to have it print to the Command Window.
fprintf('Doing stuff... ');
for i = 1:5
fprintf('%d ', i);
% do some work on that pass...
end
fprintf(' done.\n'); % That \n explicitly adds the linefeed
Using sprintf won't quite work: it creates a string without a line feed, but then if you use disp() or omit the semicolon, disp's own display logic will add a line feed.
Related
I am trying to read the information contained in a small configuration file with Matlab's fscanf function. The content of the file is;
YAcex: 1.000000
YOx: 1.000000
KAce: 1.000000
The matlab code used to parse the file is;
fh = fopen('parameters', 'r');
fscanf(fh, 'YAcex: %f\n')
fscanf(fh, 'YOx: %f\n')
fscanf(fh, 'KAce: %f\n')
fclose(fh);
When this script is invoked, only the "YAcex" line is read correctly; fscanf returns [] for the two other lines. If the YOx and KAce lines are switched (KAce before YOx), all lines are read correctly by fscanf.
Can someone explain this behavior?
supplementary information: The linefeeds in the input file are simple linefeed (\n character, without \r character).
Your problem is that you only want to read one value per call to fscanf, but by default it tries to read as many values as possible. Note this excerpt from the documentation:
The fscanf function reapplies the format throughout the entire file and positions the file pointer at the end-of-file marker. If fscanf cannot match formatSpec to the data, it reads only the portion that matches and stops processing.
This means the first call correctly reads the first line of the file, but then tries to read the next line as well, finding no exact match to its format specifier. It finds a partial match for the next line, where the first Y of YOx: matches the beginning of YAcex: in the format specifier. This partial match places the file pointer directly after the Y in YOx:, causing the next call to fscanf to fail since it is starting at the Ox: .... We can illustrate this with ftell:
fh = fopen('parameters', 'r');
fscanf(fh, 'YAcex: %f\n');
ftell(fh)
ans =
18 % The "O" is the 18th character in the file
When you switch the YOx: and KAce: lines, a partial match of the next line doesn't happen any more, so the file pointer ends up at the beginning of the next line every time and all the reads are successful.
So, how can you get around this? One option is to always specify the size argument so fscanf doesn't reapply the format specifier unnecessarily:
fh = fopen('parameters', 'r');
fscanf(fh, 'YAcex: %f\n', 1);
fscanf(fh, 'YOx: %f\n', 1);
fscanf(fh, 'KAce: %f\n', 1);
fclose(fh);
Another option is to do this all in one line:
fh = fopen('parameters', 'r');
values = fscanf(fh, 'YAcex: %f\n YOx: %f\n KAce: %f\n');
fclose(fh);
And values will be a 3-by-1 array containing the 3 values from the file.
As you already realized, \r or \r\n could cause this kind of behavior. The likely reason is similar to that, for example, there is some invisible characters like space somewhere. You can debug this by reading all as uint8, and take a look at the location where problem occurs:
u8 = fread(fh, inf, '*uint8')';
One stupid way to avoid this kind of issue is to read all as char, and search each keyword:
fh = fopen('parameters');
ch = fread(fh, inf, '*char')'; % read all as char
fclose(fh);
YAcex = regexp(ch, '(?<=YAcex:\s?)[\d\.]+', 'match', 'once'); % parse YAcex
You can parse others accordingly. The advantage of this is that it is less sensitive to a space somewhere, and the order of parameters does not matter.
I have a text file with several HEX values following a format like so:
%
AAAAAAAA
%
AAAAAAAB
and I am trying to use the fgetl() function in MATLAB to obtain the size of the HEX values (for a purpose of which I'm not entirely certain of... if it is important to you, I'll try to decipher what they were doing). Currently, this is what is being attempted:
folder = 'FolderA\hexdata.txt';
fidr = fopen(folder);
while ~feof(fidr)
get = fgetl(fidr);
hexdata=get;
if strncmp(get,'%',1)
time=time+.5;
continue
elseif size(get)<8
continue
end
%Do stuff here
end
For some reason, fgetl is returning -1 every time which I know means the line it is reading only contains the end-of-file marker. Is there something obvious I am doing wrong that I just don't see? I'm not the strongest MATLAB coder by any stretch of the imagination, so it is very possible I am missing something obvious.
Take a look at your filename folder, a seperator is missing. Use fullfile to get a proper path.
kinda new to matlab here, searching the csvwrite tutorial and some of the existing webportals regarding my question couldn't find a way to pass my variables by value to the output file names while exporting in csv; providing my bellow scripts, i would like to have the output files something like output_$aa_$dd.csv which aa and dd are respectively the first and second for counters of the scripts.
for aa=1:27
for dd=1:5
M_Normal=bench(aa,dd).Y;
for j=1:300
randRand=M_Normal(randperm(12000,12000));
for jj = 1:numel(randMin(:,1)); % loops over the rand numbers
vv= randMin(jj,1); % gets the value
randMin(jj,j+1)=min(randRand(1:vv)); % get and store the min of the selction in the matix
end
end
csvwrite('/home/amir/amir_matlab/sprintf(''%d%d',aa, bb).csv',randMin);
end
end
String concatenation in MATLAB is done like a matrix concatenation. For example
a='app';
b='le';
c=[a,b] % returns 'apple'
Hence, in your problem, the full path can be formed this way.
['/home/amir/amir_matlab/',sprintf('%d_%d',aa,bb),'.csv']
Furthermore, it is usually best not to specify the file separator explicitly, so that your code can be implemented in other operating systems. I suggest you write the full path as
fullfile('home','amir','amir_matlab',sprintf('%d_%d.csv',aa,bb))
Cheers.
The HITRAN database is a listing of molecular rotational-vibrational transitions. It is given in a text file where each line is 160 characters, with fixed width fields defining molecule, isotope, etc. The format is well documented, and there is even a program on the MathWorks File Exchange that will read in the database and simulate a portion of the spectrum. However, I need to read in a specific portion of the spectrum and then use it to do some fitting to a measured spectrum, so I need something much more custom.
As given in the comment section of that function, as well as elsewhere, the following line should read each line in properly:
database = which('HITRAN2012.par');
fid = fopen(database);
hitran = textscan(fid,'%2u%1u%12f%10f%10f%5f%5f%10f%4f%8f%15c%15c%15c%15c%6c%12c%1c%7f%7f','delimiter','','whitespace','');
fclose(fid);
The first two fields denote the molecule code, which runs from 1-47, and the isotope code which runs from 1-9.
Unfortunately, molecules 1-9 do not have a leading zero, and no matter what I do, it seems to silently confuse MATLAB. If I load in the entire database and then type
unique(hitran{1})
I do not get the numbers 1-47, but I get 10-92 with a few numbers missing. As far as I can figure, when MATLAB encounters a leading space, it shifts the line over and then pads the end, so that ' 12' becomes '12', but I'm not exactly sure. I have also tried
hitran = textscan(fid,'%160c','delimiter','\n','whitespace','');
and then tried to parse the resulting strings, but that also sometimes gets confused by the first space.
For instance, the first water line looks like
exampleHitranLine = ' 14 0.007002 1.165E-32 2.071E-14.05870.305 818.00670.590.000000 0 0 0 0 0 0 7 5 2 7 5 3 005540 02227 5 2 0 90.0 90.0';
The first bit of code comes across this line and returns '14' instead of ' 1' and '4'. If I just read in a subset that only contains molecule 1 (as in this example), then the second method of reading works fine. If I try to read in the entire database, however, the lines with molecule 1-9 are shifted the the left, which messes up all the other fields.
I should note that I've tried reading the numerical fields both as floats and as integers, and neither gives satisfactory results. The entire database in text form is nearly 700 MB, and so I need something that works as efficiently as possible.
What am I doing wrong?
I have a new file on the FileExchange that will read in HITRAN 2004+ format data. Please try it out and let me know if there are any issues with it.
I don't have an answer as to why this is happening, but I do have a solution. If anyone has an answer as to why, I'd be happy to accept it.
It is the leading space that is screwing things up. MATLAB is being a little too clever, and when textscan encounters a leading space, it decides that it's extra and discards it and moves on to the next two characters. To get it to properly read in the file, I had to go line by line and test whether the first character is a space and then replace it with a leading zero, like this:
database = which('HITRAN2012_First100Lines.par');
fileParams = dir(database);
K = fileParams.bytes/162;
hitran = cell(K,19);
fid = fopen(database);
for k = 1:K
hitranTemp = fgetl(fid);
if abs(hitranTemp(1)) == 32;
hitranTemp(1) = '0';
end
hitran(k,:) = deal(textscan(hitranTemp,'%2u%1u%12f%10f%10f%5f%5f%10f%4f%8f%15c%15c%15c%15c%6c%12c%1c%7f%7f','delimiter','','whitespace',''));
end
fclose(fid);
I'm working in MATLAB 2013a. Should I consider this to be a bug and report it? Is there some reason that the leading space should be gobbled up like this?
Update:
My workaround above was slow, but worked. Then I had to process the HITEMP database, which is several times larger, so I finally did submit a support ticket to MathWorks. The workaround suggested by MathWorks technical support is to read everything in as text and then convert. This saves a lot of disk reads and works.
fileParams = dir(database);
fid = fopen(database);
hitran = textscan(fid,'%2c%1c%12c%10c%10c%5c%5c%10c%4c%8c%15c%15c%15c%15c%6c%12c%1c%7c%7c','delimiter','','whitespace','');
fclose(fid);
moleculeNumber = uint8(str2num(hitran{1}));
isotopologueNumber = uint8(str2num(hitran{2});
vacuumWavenumber = str2num(hitran{3});
...
etc.
Depending on the application, for larger databases one would probably want to do this in chunks rather than all at once.
He also said he would forward the behavior to the development team for consideration in a future update.
I'm curious about the progress of the running program and I print some information about the current iteration such as:
for i = 1:N
...
...
msg = sprintf('Processed %d/%d', i, N);
display(msg)
end
I don't want to print the progress on separate lines, instead, I want the last line to replace the previous one. I don't want to use clc which clears all the content.
I know that '\b' can clear the last character (like backspace) and I can create a function with a for loop which clears the items till the previous new line before the last. But is there a better way to do that? If not, how can I check whether the last character on the command line is a new line or not?
I've looked at the problem, a while ago. And I've noticed that the character \r (used to erase the last line) works with matlab in command-line (-nodesktop) but not with the graphic mode...
The best solution I found is to do something like that:
n=0;
for ...
...
fprintf(repmat('\b',1,n));
fprintf(msg);
n=numel(msg);
end
Yair Altman has a very nice example on his blog of how you can use the backspace control-character (\b) to do what you want but in an easier way than you were considering. Modifying your code to resemble his example, you could do something like this:
reverseStr = '';
for i = 1:N
...
...
msg = sprintf('Processed %d/%d', i, N);
fprintf([reverseStr, msg]);
reverseStr = repmat(sprintf('\b'), 1, length(msg));
end
I use 'dispstat' function just for this purpose. It can update the previous output which is a missing function of default 'disp'. Very simple to use. It can be downloaded from here: http://www.mathworks.com/matlabcentral/fileexchange/44673-overwritable-message-outputs-to-commandline-window
***Sample usage:
dispstat('','init'); % One time only initialization
dispstat(sprintf('Begining the process...'),'keepthis','timestamp');
for i = 97:100
dispstat(sprintf('Progress %d%%',i),'timestamp');
%doing some heavy stuff here
end
dispstat('Finished.','keepprev');
***Output:
11:25:37 Begining the process...
11:25:37 Progress 100%
Finished.
All the best
Is this about what you are looking for
%# create title
fprintf('processed: %03d',0)
for i=1:10
%# delete last three digit number and replace with new
%# loop index
fprintf('\b\b\b\b %03d',i);
%# process here
pause(.5)
end
%# clear line
fprintf('\n');
But if your code displays other results this won't work. and you might want to consider using a message box to update progress.
Another solution that overwrites the entire previous line relies on the \r formatting character,
ctrl=0;
while ctrl<5
fprintf('\rctrl: %i',ctrl);
ctrl=ctrl+1;
pause(2); % To highlight overwrite
end
fprintf('\n'); % Don't forget the newline