diff --git a/Utility functions/Local settings utilities/getLocalPrograms.m b/Utility functions/Local settings utilities/getLocalPrograms.m new file mode 100644 index 0000000..151b749 --- /dev/null +++ b/Utility functions/Local settings utilities/getLocalPrograms.m @@ -0,0 +1,140 @@ +function ProgList = getLocalPrograms() + + % [run files, instruments, loggers] + ProgList = struct( ... + 'name', {}, ... + 'title', {}, ... % Display title + 'info', {}, ... + 'type', {}, ... % runfile/instrument/logger + 'run_expr', {}, ... % Expression to run + 'run_bg_expr', {} ... % Expression to run without GUI + ); + + RunFiles = readRunFiles(); + + % Add entries, automatically generated from the InstrumentList + InstrumentList = getLocalSettings('InstrumentList'); + instr_names = fieldnames(InstrumentList); + + j = 1; % Counter for the program list + + for i = 1:length(instr_names) + + % If a run file for instrument was not specified explicitly and if + % all the required fields in InstrList are filled, generate a new + % entry. + nm = instr_names{i}; + + if ismember(nm, {RunFiles.name}) + continue + end + + if isempty(InstrumentList.(nm).control_class) + continue + end + + ProgList(j).name = nm; + ProgList(j).title = nm; + ProgList(j).type = 'instrument'; + + ProgList(j).info = ['% This entry is automatically generated ' ... + 'from InstrumentList']; + + ProgList(j).run_bg_expr = sprintf('runInstrument(''%s'');', nm); + + if ~isempty(InstrumentList.(nm).gui) + + % Add command for running the instrument with gui + ProgList(j).run_expr = ... + sprintf('runInstrumentWithGui(''%s'');', nm); + end + + j = j+1; + + if ismethod(InstrumentList.(nm).control_class, 'createLogger') + + % Add an entry for starting a logger with this instrument + ProgList(j) = struct( ... + 'name', [S.name 'Logger'], ... + 'title', [S.name 'Logger'], ... + 'info', ['Logger for ' S.name], ... + 'type', 'logger', ... + 'run_expr', ['runLogger(' S.name ');'], ... + 'run_bg_expr', ['runLogger(' S.name ', ''instr_gui'', false);'] ... + ); + + j = j+1; + end + end + + ProgList = [RunFiles, ProgList]; +end + +%% Subroutines + +% Read all the files which names start from 'run' from the local base +% directory and add entries, automatically generated from InstrumentList +function RunFiles = readRunFiles(dir) + if ~exist('dir', 'var') + + % Search in the local base directory if directory name is not + % supplied explicitly + dir = getLocalBaseDir(); + end + + % Find all the names of .m files that start with 'run' + all_names = what(dir); + is_run = startsWith(all_names.m, 'run', 'IgnoreCase', false); + run_names = all_names.m(is_run); + + RunFiles = struct( ... + 'name', {}, ... + 'title', {}, ... % Display title + 'info', {}, ... + 'type', {}, ... % runfile/instrument/logger + 'run_expr', {}, ... % Expression to run + 'run_bg_expr', {} ... % Expression to run without GUI + ); + + % Read headers of all the run*.m files + for i = 1:length(run_names) + RunFiles(i).type = 'runfile'; + + name_tok = regexp(run_names{i}, 'run(.*)\.m', 'tokens'); + + % Add information about the file name + RunFiles(i).name = name_tok{1}{1}; + + % By default title is the same as name + RunFiles(i).title = RunFiles(i).name; + + % Make an expression that needs to be evaluated to run the program. + % (just the name of file by default) + [~, run_name, ~] = fileparts(run_names{i}); + RunFiles(i).run_expr = run_name; + + % Read the run file comment header + ParamList = readCommentHeader(fullfile(dir, run_names{i})); + + if isfield(ParamList, 'comment_header') + RunFiles(i).info = ParamList.comment_header; + end + + if isfield(ParamList, 'title') + RunFiles(i).title = ParamList.title; + end + + % Menu title is an old alias for title + if isfield(ParamList, 'menu_title') + RunFiles(i).title = ParamList.menu_title; + end + + if isfield(ParamList, 'run_expr') + RunFiles(i).run_expr = ParamList.run_expr; + end + + if isfield(ParamList, 'run_bg_expr') + RunFiles(i).run_expr = ParamList.run_bg_expr; + end + end +end diff --git a/Utility functions/menuFromRunFiles.m b/Utility functions/Local settings utilities/menuFromRunFiles.m similarity index 100% rename from Utility functions/menuFromRunFiles.m rename to Utility functions/Local settings utilities/menuFromRunFiles.m diff --git a/Utility functions/Local settings utilities/readCommentHeader.m b/Utility functions/Local settings utilities/readCommentHeader.m index be699b1..f9d2a28 100644 --- a/Utility functions/Local settings utilities/readCommentHeader.m +++ b/Utility functions/Local settings utilities/readCommentHeader.m @@ -1,57 +1,62 @@ % Read the header and first code line of a Matlab file, interpreting % 'property'='value' pairs indicated in comments function Info = readCommentHeader(file_name) + + % Parameter-value pairs found in the comment header are added as extra + % fields to this structure Info = struct( ... 'comment_header', '', ... - 'first_code_line', '', ... - 'ParamList', struct() ... % Parameter-value pairs from - ); % the comment header - + 'first_code_line', '' ... + ); + fid = fopen(file_name,'r'); while ~feof(fid) str = fgetl(fid); % Store the entire header Info.comment_header = [Info.comment_header, str, newline]; trimstr = strtrim(str); if isempty(trimstr) % Skip empty strings continue elseif trimstr(1) == '%' % A comment string, try to extract the 'property'='value' % pair match = regexp(trimstr, '[%\s]*(\S*)\s*=(.*)', 'tokens'); try tag = lower(match{1}{1}); - - % Remove leading and trailing whitespaces - val = strtrim(match{1}{2}); - % Try converting to logical or double value - if strcmpi(val, 'true') - val = true; - elseif strcmpi(val, 'false') - val = false; - else - val = str2doubleHedged(val); + if ~ismember(tag, fieldnames(Info)) + + % Remove leading and trailing whitespaces + val = strtrim(match{1}{2}); + + % Try converting to logical or double value + if strcmpi(val, 'true') + val = true; + elseif strcmpi(val, 'false') + val = false; + else + val = str2doubleHedged(val); + end + + Info.ParamList.(tag) = val; end - - Info.ParamList.(tag) = val; catch end else % Stop when the code begins Info.first_code_line = [str, newline]; break end end fclose(fid); end diff --git a/Utility functions/readRunFiles.m b/Utility functions/readRunFiles.m deleted file mode 100644 index 5a3b335..0000000 --- a/Utility functions/readRunFiles.m +++ /dev/null @@ -1,73 +0,0 @@ -% Read all the files which names start from 'run' from the local base -% directory and add entries, automatically generated from InstrumentList - -function RunFiles = readRunFiles(dir) - if ~exist('dir', 'var') - - % Search in the local base directory if directory name is not - % supplied explicitly - dir = getLocalBaseDir(); - end - - % Find all the names of .m files that start with 'run' - all_names = what(dir); - is_run = startsWith(all_names.m,'run','IgnoreCase',false); - run_names = all_names.m(is_run); - RunFiles = struct(); - - % Read headers of all the run*.m files - for i=1:length(run_names) - name_match = regexp(run_names{i},'run(.*)\.m','tokens'); - nm = name_match{1}{1}; - fname = fullfile(dir, run_names{i}); - - % Read the run file comment header - RunFiles.(nm) = readCommentHeader(fname); - if isfield(RunFiles.(nm),'show_in_daq') - RunFiles.(nm).show_in_daq = eval(... - lower(RunFiles.(nm).show_in_daq)); - end - - % Add information about file name - RunFiles.(nm).name = nm; - - % Expression that needs to be evaluated to run the program. In this - % case full name of the file - RunFiles.(nm).fullname = fname; - [~, run_name, ~] = fileparts(fname); - RunFiles.(nm).run_expr = run_name; - end - - % Add entries, automatically generated from the InstrumentList - InstrumentList = getLocalSettings('InstrumentList'); - instr_names = fieldnames(InstrumentList); - for i=1:length(instr_names) - nm = instr_names{i}; - - % If run file for instrument was not specified explicitly and if - % all the required fields in InstrList are filled, add an entry to - % RunFiles - try - add_entry = ~isfield(RunFiles, nm) &&... - ~isempty(InstrumentList.(nm).control_class); - catch - end - if add_entry - RunFiles.(nm) = InstrumentList.(nm); - - % Command for running an instrument without gui - RunFiles.(nm).run_bg_expr = ... - sprintf('runInstrument(''%s'');',nm); - - % Command for running an instrument with gui, added only if gui - % is specified - if ~isempty(InstrumentList.(nm).gui) - RunFiles.(nm).run_expr = ... - sprintf('runInstrumentWithGui(''%s'');',nm); - end - RunFiles.(nm).header = ['% This entry is automatically ',... - 'generated from InstrumentList']; - end - end -end -