diff --git a/@MyLogger/MyLogger.m b/@MyLogger/MyLogger.m deleted file mode 100644 index 6841cec..0000000 --- a/@MyLogger/MyLogger.m +++ /dev/null @@ -1,321 +0,0 @@ -% Generic logger that executes measFcn according to MeasTimer, stores the -% results and optionally continuously saves them. -% measFcn should be a function with no arguments. -% measFcn need to return a row vector of numbers in order to save the log -% in text format or display it. With other kinds of returned values the -% log can still be recorded, but not saved or dispalyed. - -classdef MyLogger < handle - - properties (Access = public, SetObservable = true) - - % Timer object - MeasTimer = timer.empty() - - % Function that provides data to be recorded - measFcn = @()0 - - % MyLog object to store the recorded data - Record = MyLog.empty() - - % Format for displaying readings (column name: value) - disp_fmt = '\t%15s:\t%.5g' - - % Option for daily/weekly creation of a new log file - FileCreationInterval = duration.empty() - end - - properties (SetAccess = protected, GetAccess = public) - - % If last measurement was succesful - % 0-false, 1-true, 2-never measured - last_meas_stat = 2 - end - - properties (Access = protected) - Metadata = MyMetadata.empty() - end - - events - - % Event that is triggered each time measFcn is successfully - % executed - NewMeasurement - - % Event for transferring data to the collector - NewData - end - - methods (Access = public) - function this = MyLogger(varargin) - P = MyClassParser(this); - addParameter(P, 'log_opts', {}, @iscell); - processInputs(P, this, varargin{:}); - - this.Record = MyLog(P.Results.log_opts{:}); - - % Create and confitugure timer - this.MeasTimer = timer(); - this.MeasTimer.BusyMode = 'drop'; - - % Fixed spacing mode of operation does not follow the - % period very well, but is robust with respect to - % function execution delays - this.MeasTimer.ExecutionMode = 'fixedSpacing'; - this.MeasTimer.TimerFcn = @this.loggerFcn; - end - - function delete(this) - - % Stop and delete the timer - try - stop(this.MeasTimer); - catch ME - warning(['Could not stop measurement timer. Error: ' ... - ME.message]); - end - - try - delete(this.MeasTimer); - catch ME - warning(['Could not delete measurement timer. Error: ' ... - ME.message]); - end - end - - % Redefine start/stop functions for the brevity of use - function start(this) - if ~isempty(this.FileCreationInterval) && ... - isempty(this.Record.FirstSaveTime) - - % If run in the limited length mode, extend the record - % file name - createLogFileName(this); - end - - start(this.MeasTimer); - end - - function stop(this) - stop(this.MeasTimer); - end - - function bool = isrunning(this) - try - bool = strcmpi(this.MeasTimer.running, 'on'); - catch ME - warning(['Cannot check if the measurement timer is on. '... - 'Error: ' ME.message]); - - bool = false; - end - end - - % Trigger an event that transfers the data from one log channel - % to Daq - function triggerNewData(this, varargin) - - % Since the class does not have Trace property, a Trace must be - % supplied explicitly - Trace = toTrace(this.Record, varargin{:}); - EventData = MyNewDataEvent('Trace',Trace, 'new_header',false); - notify(this, 'NewData', EventData); - end - - % Display reading - function str = printReading(this, ind) - if isempty(this.Record.timestamps) - str = ''; - return - end - - % Print the last reading if index is not given explicitly - if nargin()< 2 - ind = length(this.Record.timestamps); - end - - switch ind - case 1 - prefix = 'First reading '; - case length(this.Record.timestamps) - prefix = 'Last reading '; - otherwise - prefix = 'Reading '; - end - - str = [prefix, char(this.Record.timestamps(ind)), newline]; - data_row = this.Record.data(ind, :); - - for i=1:length(data_row) - if length(this.Record.data_headers)>=i - lbl = this.Record.data_headers{i}; - else - lbl = sprintf('data%i', i); - end - str = [str,... - sprintf(this.disp_fmt, lbl, data_row(i)), newline]; %#ok - end - end - - % Generate a new file name for the measurement record - function createLogFileName(this, path, name, ext) - [ex_path, ex_name, ex_ext] = fileparts(this.Record.file_name); - - if ~exist('path', 'var') - path = ex_path; - end - - if ~exist('name', 'var') - name = ex_name; - end - - if ~exist('ext', 'var') - if ~isempty(ex_ext) - ext = ex_ext; - else - ext = this.Record.data_file_ext; - end - end - - % Remove the previous time stamp from the file name if exists - token = regexp(name, ... - '\d\d\d\d-\d\d-\d\d \d\d-\d\d (.*)', 'tokens'); - if ~isempty(token) - name = token{1}{1}; - end - - % Prepend a new time stamp - name = [datestr(datetime('now'),'yyyy-mm-dd HH-MM '), name]; - - file_name = fullfile(path, [name, ext]); - - % Ensure that the generated file name is unique - file_name = createUniqueFileName(file_name); - - this.Record.file_name = file_name; - end - - function Mdt = readSettings(this) - if isempty(this.Metadata) - this.Metadata = MyMetadata('title', class(this)); - - addParam(this.Metadata, 'meas_period', [], 'comment', ... - 'measurement period (s)'); - - addParam(this.Metadata, 'save_cont', [], 'comment', ... - 'If measurements are continuously saved (true/false)'); - - addParam(this.Metadata, 'file_creation_interval', [], ... - 'comment', ['The interval over which new data ' ... - 'files are created when saving continuously ' ... - '(days:hours:min:sec)']); - - addParam(this.Metadata, 'log_length_limit', [], ... - 'comment', ['The maximum number of points kept ' ... - 'in the measurement record']); - end - - % Update parameter values - this.Metadata.ParamList.meas_period = this.MeasTimer.Period; - this.Metadata.ParamList.save_cont = this.Record.save_cont; - this.Metadata.ParamList.file_creation_interval = ... - char(this.FileCreationInterval); - this.Metadata.ParamList.log_length_limit = ... - this.Record.length_lim; - - Mdt = copy(this.Metadata); - end - - % Configure the logger settings from metadata - function writeSettings(this, Mdt) - - % Stop the logger if presently running - stop(this); - - if isparam(Mdt, 'meas_period') - this.MeasTimer.Period = Mdt.ParamList.meas_period; - end - - if isparam(Mdt, 'save_cont') - this.Record.save_cont = Mdt.ParamList.save_cont; - end - - if isparam(Mdt, 'file_creation_interval') - this.FileCreationInterval = ... - duration(Mdt.ParamList.file_creation_interval); - end - - if isparam(Mdt, 'log_length_limit') - this.Record.length_lim = Mdt.ParamList.log_length_limit; - end - end - end - - methods (Access = protected) - - % Perform measurement and append point to the log - function loggerFcn(this, ~, event) - Time = datetime(event.Data.time); - try - meas_result = this.measFcn(); - this.last_meas_stat = 1; % last measurement ok - catch ME - warning(['Logger cannot take measurement at time = ',... - datestr(Time) '.\nError: ' ME.message]); - this.last_meas_stat = 0; % last measurement not ok - return - end - - if this.Record.save_cont && ... - ~isempty(this.FileCreationInterval) && ... - ~isempty(this.Record.FirstSaveTime) && ... - (Time - this.Record.FirstSaveTime) >= ... - this.FileCreationInterval - - % Switch to a new data file - createLogFileName(this); - end - - % Append measurement result together with time stamp - appendData(this.Record, Time, meas_result); - notify(this, 'NewMeasurement'); - - % Wait for any changes in data display to take an effect, this - % is needed to prevent an infinite accumulation of callbacks - % in case of slow graphics update - drawnow(); - end - end - - %% Set and get functions - methods - function set.measFcn(this, val) - assert(isa(val, 'function_handle'), ... - '''measFcn'' must be a function handle.'); - this.measFcn = val; - end - - function set.Record(this, val) - assert(isa(val, 'MyLog'), '''Record'' must be a MyLog object') - this.Record = val; - end - - function set.MeasTimer(this, val) - assert(isa(val, 'timer'), ... - '''MeasTimer'' must be a timer object') - this.MeasTimer = val; - end - - function set.FileCreationInterval(this, Val) - assert(isa(Val, 'duration'), ['''FileCreationInterval'' ' ... - 'must be a duration object.']) - - if ~isempty(Val) - Val.Format = 'dd:hh:mm:ss'; - end - - this.FileCreationInterval = Val; - end - end -end - diff --git a/@MyNewportUsbComm/MyNewportUsbComm.m b/@MyNewportUsbComm/MyNewportUsbComm.m deleted file mode 100644 index 28d5aac..0000000 --- a/@MyNewportUsbComm/MyNewportUsbComm.m +++ /dev/null @@ -1,104 +0,0 @@ -classdef MyNewportUsbComm < MySingleton - - properties (GetAccess = public, SetAccess = private) - - % Driver in use - isbusy = false - end - - properties (Access = public) - - % An instance of Newport.USBComm.USB class - Usb - end - - methods (Access = private) - - % The constructor of a singleton class should only be invoked from - % the instance method. - function this = MyNewportUsbComm() - disp(['Creating a new instance of ' class(this)]) - loadLib(this); - end - end - - methods (Access = public) - - % Load dll - function loadLib(this) - dll_path = which('UsbDllWrap.dll'); - if isempty(dll_path) - error(['UsbDllWrap.dll is not found. This library ',... - 'is a part of Newport USB driver and needs ',... - 'to be present on Matlab path.']) - end - NetAsm = NET.addAssembly(dll_path); - - % Create an instance of Newport.USBComm.USB class - Type = GetType(NetAsm.AssemblyHandle,'Newport.USBComm.USB'); - this.Usb = System.Activator.CreateInstance(Type); - end - - function str = query(this, addr, cmd) - - % Check if the driver is already being used by another process. - % A race condition with various strange consequences is - % potentially possible if it is. - assert(~this.isbusy, 'NewportUsbComm is already in use.') - - this.isbusy = true; - - % Send query using QueryData buffer. A new buffer needs to be - % created every time to ensure the absence of interference - % between different queries. - QueryData = System.Text.StringBuilder(64); - - stat = Query(this.Usb, addr, cmd, QueryData); - - if stat ~= 0 - warning(['Query to Newport usb driver was unsuccessful.'... - errorCodeToMessage(this, stat)]); - end - - str = char(ToString(QueryData)); - - this.isbusy = false; - end - end - - methods (Access = private) - - % Convert the code returned by read/write/query functions to - % a message - function str = errorCodeToMessage(~, stat) - switch stat - case 0 - - % No error - str = ''; - case -2 - str = 'Error: Device timeout'; - case 1 - str = 'Error: Duplicate USB address'; - otherwise - str = sprintf('Error Code = %i', stat); - end - end - end - - methods (Static) - - % Concrete implementation of the singleton constructor. - function this = instance() - persistent UniqueInstance - - if isempty(UniqueInstance) || ~isvalid(UniqueInstance) - this = MyNewportUsbComm(); - UniqueInstance = this; - else - this = UniqueInstance; - end - end - end -end - diff --git a/GUIs/GuiTlb.mlapp b/GUIs/GuiTlb.mlapp deleted file mode 100644 index c4c73d2..0000000 Binary files a/GUIs/GuiTlb.mlapp and /dev/null differ