Display TODO/FIXME report in Matlab's command window - matlab

Using the command
checkcode('function.m')
you can run the code analyzer on an m-file and output the report in the command window.
Is there any way to do this for TODO/FIXME reports? (without having to cd to the folder that contains the function and manually run it on the whole directory)
Bonus: If so, is it also possible to create custom tags? In eclipse, you can create custom TODO tags like "MTODO" and "JTODO" for different purposes/different people and have them displayed separately. Is this possible in Matlab?
Thanks in advance for any help! I will be continuing my google searches and will post the results if I find something.

You can use the internal function dofixrpt. This returns the HTML displayed in the report, rather than displaying the information at the command line, however.
% Run the report and show it
cd('myfolder')
dofixrpt;
% Alternatively, get the HTML of the report directly
html = dofixrpt;
% Write the HTML to a file
filename = tempname;
fid = fopen(filename, 'w');
fprintf(fid, '%s', html);
fclose(fid);
% View the HTML file
web(filename)
Type which dofixrpt or edit dofixrpt to see more details about what it does (it's basically a regular expression search for %.*TODO and %.*FIXME).
In the HTML report, you can find markers other than TODO and FIXME by specifying a custom marker (the default is NOTE). Unfortunately you can specify only one. If you're up to looking within dofixrpt and modifying it very slightly though, it would be very easy to make it look for more.
Finally you could also put in an enhancement request with MathWorks to provide a command similar to checkcode that will just do this for you and return the results at the command line. It seems like that would be very easy for them to do, and I'm surprised they haven't already done it, given that they've done something similar for helprpt, coveragerpt, deprpt etc.
Hope that helps!

I ended up writing my own code checker that calls checkcode on every m file in the specified folders.
fld_list = {pwd, 'folder', 'other_folder'};
nProblems = 0;
for iFld = 1:length(fld_list)
% fprintf('Checking %s...\n', fld_list{n});
files = dir(fullfile(fld_list{iFld}, '*.m'));
for f = 1:length(files)
filename = fullfile(fld_list{iFld}, files(f).name);
customCodeCheck(filename); %custom function
% check code analyzer
codeWarnings = checkcode(filename);
if not(isempty(codeWarnings))
fprintf('Problem found in %s\n', files(f).name);
for iData = 1:length(codeWarnings)
nProblems = nProblems + 1;
% print out link to problem
fprintf('line %d: %s\n', ...
filename, ...
codeWarnings(iData).line, codeWarnings(iData).line, ...
codeWarnings(iData).message);
end
end
end
end
You can add to this a customCodeCheck function that searches for TODO and FIXME and alerts you to their existence
function customCodeCheck(filename)
fileContents = fileread(filename);
toDos = strfind(fileContents, 'TODO');
fixMes = strfind(fileContents, 'FIXME');
% do other stuff
end

Related

Edit an Abaqus input file and Run it from Matlab

I need perform 50 Abaqus simulations, each simulation analyses a certain material property and each differs by changing one parameter. So the idea is to write a Matlab script that:
opens the .inp file
edits the material parameter of interest
prints it into a new file which will be the new .inp file
runs it to perform the simulation
This is what I accomplished so far in a very simplified version:
f= fopen('PRD8_30s.inp');
c = textscan(f,'%s %s %s %s %s ','delimiter',',');
fclose(f) ;
S = [c{1}];
A = {'5e-08'} ;
S(12496) = A ;
fid = fopen('file.inp','w') ;
fprintf(fid,'%s \n',S{:} );
fclose(fid) ;
PRD_8_30s.inp
I manually found out the position of the parameter of interest (A at 12496 hence below the line *Viscoelastic). The code actually changes the parameter I need but there are major problems: it prints a new file with additional lines with respect to the original .inp (12552 vs 8737) and it doesn't print the entire .inp but only the first column.
How can I edit the .inp changing the parameter and obtaining a new .inp with the edited parameter that can be used to run the new simulation?
Thank you in advance for your help!
If your input file is not multiple Gb in size, The following might help.
create a template input and mark the parameter you want to change as, for example para_xxxx
Use the following script:
text=fileread('template.inp');
newtext=replace(text,'para_xxxx',newParameter);
fid=fopen('newcase.inp','w');
fprintf(fid,newtext);
fclose(fid);
The file name 'newcase.inp' should be updated each time in the loop.

Kill Excel process created in Matlab

Given that I write to a workbook, I currently kill all Excel processes so that my code works when I call it in a loop.
xlswrite(path,values);
system('taskkill /F /IM EXCEL.EXE');
This makes me unable to run the code while I am working in another Excel file. How do I make it so that Matlab terminates only the Excel processes that itself created?
This was a "feature" introduced somewhere around R2015b to speed up multiple writes to Excel... not very user/memory friendly!
The xlswrite documentation links to this MathWorks Support Answer to manually write to Excel using actxserver, you can then manually delete the COM object referencing Excel.
You can actually edit xlswrite and see that it uses matlab.io.internal.getExcelInstance, which does the same thing and creates a COM interface with actxserver.
A cheeky option would be to copy xlswrite, add the Excel variable it creates as an output, and Quit and delete it afterwards, as shown below. I don't advocate breaking any of The MathWorks' copyright ownership of that function.
A less cheeky option would be to create a comparable function based on the answer I linked above, for writing data only it would look something like this:
function xlswriteClean( File, Data, Range )
% XLSWRITECELAN writes data like XLSWRITE, but deletes the Excel instance!
% XLSWRITECELAN (FILE,DATA,RANGE) writes the variable in
% DATA to FILE, in the range specified by RANGE.
% RANGE is optional, defaults to "A1"
% Obtain the full path name of the file
% Could handle this more elegantly, i.e.
% this always assumes the current directory, but user might give a full path
file = fullfile(pwd, File);
% Open an ActiveX connection to Excel
h = actxserver('excel.application');
%Create a new work book (excel file)
wb = h.WorkBooks.Add();
% Select the appropriate range
if nargin < 3
Range = 'A1';
end
rng = h.Activesheet.get('Range', Range);
% Write the data to the range
rng.value = Data;
% Save the file with the given file name, close Excel
wb.SaveAs( File );
% Clean up - the point of this function
wb.Close;
h.Quit;
h.delete;
end
You can customise basically everything within the new Excel workbook using the COM object h, so you could add any functionality which you use in xlswrite like sheet naming etc.
You can start the excel process by powershell and get its process id then use the process id to kill the process:
[~, pid] = system('powershell (Start-Process excel.exe -passthru).Id');
% Do your work
% ...
system(['powershell Stop-Process -Id ' pid])

Search and replace variable

I have some 100+ conf files that I am working. I need to find and replace various variable for all these files. For example, I'd like to find the line
Amplitude = 100; and replace it to: Amplitude = 200; for all files.
I've searched in online and found the solution only for one file. I'm looking for a way to do that in Matlab. Any ideas?
If these files can be opened as normal text files then I wouldn't use matlab. Notepad++ has an replace option for as many files as you want, just make sure, you test it out on a backup file first. so have it find "Amplitude = 100" and replace that by what you want.
To see how to do it, look here:
how-to-find-and-replace-lines-in-multiple-files
If you can't do that, put all the files in the same directory (you have to do this anyway). Then load the files in matlab with that directory and run a for loop. However it might be a bit slow./
Basically if you can do 1 file, you could do all of them with a for loop.
If you need help with that I show can some code I used before.
Well, Matlab solution would be to (recursively) open all files in the directory. Here I show example for non-recursive solution (it does not check subfolders), though it would be easy enough to modify it to search subfolders too if needed:
d = dir(yourPath);
for i = 1 : length(d)
if ~(d(i).isdir)
%d(i) is file.
replaceSingleFile(strcat(d(i).folder, d(i).name));
end
end
As you say, you already know how to do replace for a single file, though to have complete answer here, solution could be along the lines (in the function replaceSingleFile).
F = fopen(fileYouWantReplaced);
i = 1;
while (~feof(F))
L = fgetl(F);
L = strrep(L, 'Amplitude = 100;', 'Amplitude = 200;');
Buf{i} = L;
i = i + 1;
end
fclose(F);
%now just write all Buf to the same file again.
F = fopen(file..., 'w'); % Discard contents.
for i = 1 : numel(Buf)
fprintf(F, '%s\n', Buf{i});
end
fclose(F);

Find and replace text file Matlab

I'm writting a Matlab code that generates an array number and it should replace that each number in a text file (that already exists) and replace all instances with that. The number should be in string format. I've achieved this:
ita='"';
for i=1:size(z,2)
word_to_replace=input('Replace? ','s');
tik=input('Replacement? ','s');
coluna=input('Column? ');
files = dir('*.txt');
for i = 1:numel(files)
if ~files(i).isdir % make sure it is not a directory
contents = fileread(files(i).name);
fh = fopen(files(i).name,'w');
val=num2str(z(i,coluna));
word_replacement=strcat(tik,val,ita);
contents = regexprep(contents,'word_to_replace','word_replacement');
fprintf(fh,contents); % write "replaced" string to file
fclose(fh) % close out file
end
end
end
I want the code to open the file#1 ('file.txt'), find and replace all instances 'word_replacement' with 'word_to_replace' and save to the same file. The number of txt files is undefined, it could be 100 or 10000.
Many thanks in advance.
The problem with your code is the following statement:
contents = regexprep(contents,'word_to_replace','word_replacement');
You are using regular expressions to find any instances of word_to_replace in your text files and changing them to word_replacement. Looking at your code, it seems that these are both variables that contain strings. I'm assuming that you want the contents of the variables instead of the actual name of the variables.
As such, simply remove the quotations around the second and third parameters of regexprep and this should work.
In other words, do this:
contents = regexprep(contents, word_to_replace, word_replacement);

saving all variable values in matlab's workspace together with their names

I'd like to save print all my variables in my workspace to a file together with their names in a certain way:
%<*firstVariableName>firstVariableValue(s)%</firstVariableName>
%<*secondVariableName>secondVariableValue(s)%</secondVariableName>
I'd like to save each variable on a new line. I've experimented with the function who, but I can't seem to get it to work.
I also have problem getting it to save as UTF-8, is there a simple encoding setting that could be changed?
The who function will save the names of the variables, but not the data in the variables. If you'd like to save the actual variables, you should use the save function, and save it to a *.mat file.
If you're trying to get a list of the names of the variables formatted in a certain way, I'd recommend doing this:
varlist = who(variables);
varlist is a cell array. You can then fopen to start writing to a file, iterate through the cell array using fwrite, and fclose it when you're done. By the way, when you iterate, you should use varlist{x}, which will return the string (whereas varlist(x) will return the cell).
Hope this helps. :)
This may not work in all cases, but it works well for numeric inputs. It may be modified appropriately as per your use case:
%Clears current workspace.
clear;
%Sample data.
a = 1;
b = [2 3];
new_var = [4;5];
%Relevant code.
my_var_list = who;
fid = fopen('my_var_list.txt','w');
for my_var_ii=1:numel(my_var_list)
my_temp_var = eval(my_var_list{my_var_ii});
my_temp_str = cellstr(strcat(sprintf('%%<*%s>', my_var_list{my_var_ii}), num2str(my_temp_var(:)'), sprintf('%%</%s>', my_var_list{my_var_ii})));
fprintf(fid, '%s\n', my_temp_str{:});
end
fclose(fid);
clear fid;
clear my_temp_var;
clear my_var_ii;
clear my_var_list;
clear my_temp_str;
Now my 'my_var_list.txt' will contain:
%<*a>1%</a>
%<*b>2 3%</b>
%<*new_var>4 5%</new_var>