Ideas / best practices for verbosity management in matlab functions

Let's say I have some_fun that does some hard work.

function foo = some_complicated_fun(x,y,z,verbosity) 

I wrote a good debugging fingerprint in this code, but the avg user may not be interested to see all this if it works. Error operators (not enough arguments, etc.) Will print independently.

My current method of writing a function:

 function foo = some_complicated_fun(x,y,z,verbosity) (x,y,z,verbosity) = parse_args(x,y,z,verbosity); % parse args, check nargin, etc for i=1:5, % whatever % do some work with x,y,z % blah blah if verbosity fprintf('Now on iteration %i\n',i); % basic print end % or, with mutiple levels: if verbosity == 1; fprintf('Now on iteration %i\n',i); % basic print end if verbosity == 2; fprintf('x = %f,y = %f,z=%f %i\n',x,y,z); % more information end % do more work end 

I don't like doing this with if statements because it is cluttering up the code, but I can't think of anything else. One liner is better and worse:

 if verbosity; fprintf('Iteration %i\n',i); end 

Better because it is smaller, worse because single-line users are less readable than the same thing in three lines.

What I want is a simple, more elegant way to control verbosity.

Does it exist?

+6
source share
5 answers

I created a method for managing verbose log output. This is not finished yet, but after this question popped up, I uploaded it to:

This link to Matlab file hosting.

It works by setting the global output log to the desired level and displays a message in the following format:

 OUTPUT_LEVEL: function_which_called_message Your_Message. 

However, it will only output messages that exceed the set output level. By default, only INFO or higher messages are displayed, so it will not display DEBUG and VERBOSE messages. If you want to see debug messages, then you set:

 Output.level(Output.DISP_DEBUG) 

Output Methods:

 Output.VERBOSE Output.DEBUG Output.INFO Output.WARNING Output.ERROR 

You select the messages that will be displayed in your functions by doing Output.'DESIRED_LEVEL'('message',input_1,input2) , as in sprintf or fprintf matlab format. Ie, Output.INFO('The variable value is %d',variable) . For WARNING and ERROR messages, you can also specify an identifier like "PACK: METHOD: ERROR_ID", and thus the output will be in the matlab warning and error functions. Ie Output.WARNING('MY_PACKAGE:MY_METHOD:MY_ID','Something wrong happened here!') .

The following output levels are available:

 Output.level(Output.DISP_VERBOSE) % Show all messages Output.level(Output.DISP_DEBUG) % Show debug info warning errors Output.level(Output.DISP_INFO) % Show info warning errors Output.level(Output.DISP_WARNING) % Show warning errors Output.level(Output.DISP_MUTE) % Show only errors. 

You can also specify the output to the log file using

 Output.place('file_path') 

And replace the log file (you can also use it to reset the current log):

 Output.place('file_path',true) 

Or reset on screen

 Output.place(1) 

The following is an example of output using the DISP_VERBOSE output level:

 >> nilmContainer = NilmFileContainer.newRun('inputFolder','sim_real/','runName','RealHouse','samplesPerFile',60*60*60); VERBOSE: getFilesOnFolder Found 2 files on folder 'data/sim_real/'. They are the following: VERBOSE: getFilesOnFolder [1]:data/sim_real/240AM000.csv VERBOSE: getFilesOnFolder [2]:data/sim_real/240AM001.csv DEBUG: NilmFileContainer.setRunName Updating run name to RealHouse_Run5. INFO: newRun Reading file data/sim_real/240AM000.csv. VERBOSE: csv_data Reading samples (Ignored:0,Read:216000,Remaining:2422014) at file: data/sim_real/240AM000.csv. DEBUG: addFiles Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_1-19:12:46-30_10_2012.mat' VERBOSE: csv_data Reading samples (Ignored:216000,Read:216000,Remaining:2206014) at file: data/sim_real/240AM000.csv. DEBUG: addFiles Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_2-20:12:45-30_10_2012.mat' VERBOSE: csv_data Reading samples (Ignored:432000,Read:216000,Remaining:1990014) at file: data/sim_real/240AM000.csv. DEBUG: addFiles Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_3-21:12:45-30_10_2012.mat' VERBOSE: csv_data Reading samples (Ignored:648000,Read:216000,Remaining:1774014) at file: data/sim_real/240AM000.csv. DEBUG: addFiles Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_4-22:12:45-30_10_2012.mat' VERBOSE: csv_data Reading samples (Ignored:864000,Read:216000,Remaining:1558014) at file: data/sim_real/240AM000.csv. DEBUG: addFiles Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_5-23:12:45-30_10_2012.mat' VERBOSE: csv_data Reading samples (Ignored:1080000,Read:216000,Remaining:1342014) at file: data/sim_real/240AM000.csv. DEBUG: addFiles Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_6-00:12:44-31_10_2012.mat' VERBOSE: csv_data Reading samples (Ignored:1296000,Read:216000,Remaining:1126014) at file: data/sim_real/240AM000.csv. DEBUG: addFiles Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_7-01:12:43-31_10_2012.mat' VERBOSE: csv_data Reading samples (Ignored:1512000,Read:216000,Remaining:910014) at file: data/sim_real/240AM000.csv. DEBUG: addFiles Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_8-02:12:43-31_10_2012.mat' VERBOSE: csv_data Reading samples (Ignored:1728000,Read:216000,Remaining:694014) at file: sim_real/240AM000.csv. DEBUG: addFiles Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_9-03:12:43-31_10_2012.mat' VERBOSE: csv_data Reading samples (Ignored:1944000,Read:216000,Remaining:478014) at file: data/sim_real/240AM000.csv. DEBUG: addFiles Writing file 'NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_10-04:12:42-31_10_2012.mat' VERBOSE: csv_data Reading samples (Ignored:2160000,Read:216000,Remaining:262014) at file: data/sim_real/240AM000.csv. DEBUG: addFiles Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_11-05:12:41-31_10_2012.mat' VERBOSE: csv_data Reading samples (Ignored:2376000,Read:216000,Remaining:46014) at file: data/sim_real/240AM000.csv. DEBUG: addFiles Writing file 'data/NILM_DATA/RealHouse_Run5/RealHouse_Run5-File_12-06:12:41-31_10_2012.mat' VERBOSE: csv_data Reading samples (Ignored:2592000,Read:46014,Remaining:0) at file: data/sim_real/240AM000.csv. VERBOSE: csv_data Reading samples (Ignored:0,Read:169986,Remaining:2799058) at file: data/sim_real/240AM001.csv. INFO: readFile Found discontinuity while changing from file 'data/sim_real/240AM000.csv' to 'data/sim_real/240AM001.csv'. 

As I said, this is not in the final version, but you can help me improve it! x)

+1
source

Define a function to replace fprintf containing the if and the actual print. And declare verbosity as a global variable so as not to pass it as an argument every time.

+2
source

Here is what I did.

I wrote a function (I called it vprintf, but there are better names.)

I'm not sure I want to make global variables, but that's the thought.

 function vprintf(v,l,varargin) % VPRINTF(verbosity, verbosity_level_of_statement,sprintf_style_arguments % % % example: % % verbosity = 1; % vprintf(verbosity,1,'This will print if verbosity is at least 1\n Verbosity = %i\n',verbosity); if nargin<3 error('not enough arguments'); end if v>=l % if verbosity level is >= level of this statment % keyboard; fprintf(varargin{:}); end 
+1
source

As an improvement to the answers from Frederick and Louis Mendo, you can define your vprintf as a nested function at the end of your function. It will have access to the verbosity argument and you will not need a global variable. Your code will look like this:

 function foo = some_complicated_fun(x,y,z,verbosity) [x,y,z,verbosity] = parse_args(x,y,z,verbosity); % parse args, check nargin, etc for i=1:5, % whatever % do some work with x,y,z % blah blah vprintf(1,'Now on iteration %i\n',i); % basic print % or, with mutiple levels: vprintf(1,'Now on iteration %i\n',i); % basic print vprintf(2,'x = %f,y = %f,z=%f %i\n',x,y,z); % more information % do more work end % time to define vprintf function vprintf(l,varargin) % VPRINTF(verbosity, verbosity_level_of_statement,sprintf_style_arguments % % % example: % % verbosity = 1; % vprintf(1,'This will print if verbosity is at least 1\n Verbosity = %i\n',verbosity); if nargin<2 error('not enough arguments'); end if verbosity>=l % if verbosity level is >= level of this statment % keyboard; fprintf(varargin{:}); end end 

EDIT To overcome the maintainability problem described by Gunerson Struyf in the comments, you can save the verbosity value in a constant variable in vprintf and set it on the first call.

 function vprintf(vl,varargin) % VPRINTF(verbosity); % VPRINTF(verbosity_level_of_statement,sprintf_style_arguments); persistent verbosity if nargin==1 verbosity = vl; elseif isempty(verbosity) error('verbosity level not set'); end if verbosity>=vl % if verbosity level is >= level of this statment % keyboard; fprintf(varargin{:}); end 

Then in foo function sets it at the beginning and uses it in subsequent operations. It may be good practice to clear the value in the output using vprintf([]);

 function foo = some_complicated_fun(x,y,z,verbosity) [x,y,z,verbosity] = parse_args(x,y,z,verbosity); % parse args, check nargin, etc vprintf(verbosity); for i=1:5, % whatever % do some work with x,y,z % blah blah vprintf(1,'Now on iteration %i\n',i); % basic print % or, with mutiple levels: vprintf(1,'Now on iteration %i\n',i); % basic print vprintf(2,'x = %f,y = %f,z=%f %i\n',x,y,z); % more information % do more work end vprintf([]); 
+1
source

If I wanted to do this, I would create a Logger class similar to this with functions such as logDebug , logInfo , logWarning and logError . (I really did it for lua here ).

You will need to set the loglevel level at creation, and access to the full functions and functions can be obtained within the Logger object (so global pollution of the area and simple implementation in several m files) will not.

Thus, the final use of this class will look like this:

 %% my fancy script % init logger = Logger(Logger.LOGDEBUG) logger.logDebug('script initialized'); % plot some stuff logger.logDebug('commencing plot'); plot(rand(4)); logger.logInfo('fancy script ended'); 
0
source

Source: https://habr.com/ru/post/950732/


All Articles