Commit e3362639 authored by jayd1860's avatar jayd1860
Browse files

v1.18.7

-- Solved issues with speed and accuracy in detection of low disk space when saving processing. To solve problem used static (persistent in Matlab) class variables which are multi-dimensional matrices for fast processing.
-- Improved Reset() method for resetting processing results. When resetting run or subject proc results it should also delete that element's group and subject proc results but not touch the subject at the same level.
-- Changed reset function in MainGUI to no re-save to groupResults after deleting the procStream.output in memory
parent d5637ab0
Loading
Loading
Loading
Loading
+68 −16
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ classdef DataTreeClass < handle
        reg
        config
        logger
        warningflag        
    end
    
    methods
@@ -64,6 +65,8 @@ classdef DataTreeClass < handle
            
            % Initialize the current processing element within the group
            obj.SetCurrElem(1,1,1);
            
            obj.warningflag = 0;
        end
        
        
@@ -322,7 +325,27 @@ classdef DataTreeClass < handle
            if isempty(obj)
                return;
            end
            nbytes = length(obj.groups) * obj.currElem.MemoryRequired(option);
            
            nbytes = [0,0,0];
            kg = find(obj.groups.GroupsProcFlags==1);
            ks = find(obj.groups.SubjsProcFlags==1);
            kr = find(obj.groups.RunsProcFlags==1);
            
            % We assume for practcal purposes that unprocessed nodes take up zero bytes 
            if ~isempty(kg)
                nbytes(1) = length(kg) * obj.groups(kg(1)).MemoryRequired();
            end
            if ~isempty(ks)
                [iG,iS] = ind2sub(size(obj.groups.SubjsProcFlags), ks);
                nbytes(2) = length(ks) * obj.groups(iG(1)).subjs(iS(1)).MemoryRequired();
            end
            if ~isempty(kr)
                [iG,iS,iR] = ind2sub(size(obj.groups.RunsProcFlags), kr);
                nbytes(3) = length(kr) * obj.groups(iG(1)).subjs(iS(1)).runs(iR(1)).MemoryRequired(option);
            end
                        
            % Add up the bytes. 
            nbytes = sum(nbytes);
        end
        
        
@@ -331,21 +354,35 @@ classdef DataTreeClass < handle
            if ishandle(hwait)
                obj.logger.Write(sprintf('Estimating disk space required to save processing results ...\n'), obj.logger.ProgressBar(), hwait);
            end
            memRequired = obj.currElem.MemoryRequired('disk');
            diskspaceToSpare = (getFreeDiskSpace() - memRequired);   % Disk space to spare in megabytes
            
            % Calculate the amount of disk space already used by groupResults. Add that to free disk space because
            % groupResults will be overwritten 
            freeDiskSpace = 0;
            for ii = 1:length(obj.groups)
                freeDiskSpace = freeDiskSpace + GetFileSize([obj.groups(ii).pathOutput, 'groupResults.mat']);
            end
            
            memRequired = obj.MemoryRequired('disk');
            freeDiskSpace = getFreeDiskSpace() + freeDiskSpace;
            
            diskspaceToSpare = (freeDiskSpace - memRequired);   % Disk space to spare in megabytes
            diskspacePercentRemaining = 100 * diskspaceToSpare/memRequired;
            msg = {};
            obj.logger.Write(sprintf('CheckAvailableDiskSpace:    disk space available = %0.1f MB,    required disk space estimate = %0.1f MB\n', getFreeDiskSpace()/1e6, memRequired/1e6));
            obj.logger.Write(sprintf('CheckAvailableDiskSpace:    disk space available = %0.1f MB,    required disk space estimate = %0.1f MB\n', freeDiskSpace/1e6, memRequired/1e6));
            if diskspaceToSpare < 0
                msg{1} = sprintf('ERROR: Cannot save processing results requiring ~%0.1f MB of disk space on current drive with only %0.1f MB of free space available.\n', ...
                                  memRequired/1e6, getFreeDiskSpace()/1e6);
                                  memRequired/1e6, freeDiskSpace/1e6);
                obj.warningflag = 0;
            elseif diskspacePercentRemaining < 200                
                msg{1} = sprintf('WARNING: Available disk space on the current drive is low (%0.1f MB). This may cause problems saving processing results in the future.', ...
                                  getFreeDiskSpace()/1e6);
                                  freeDiskSpace/1e6);
                msg{2} = sprintf('Consider moving your data set to a drive with more free space\n');
            end            
            if ~isempty(msg)
                if ~obj.warningflag
                    MessageBox([msg{:}]);
                    obj.warningflag = 1;
                end
                obj.logger.Write([msg{:}]);
            end            
        end
@@ -358,14 +395,16 @@ classdef DataTreeClass < handle
                hwait = [];
            end
            
            % Check that there is anough disk space. NOTE: for now we
            % assume that all groups are on the same drive. This should be 
            % changed but for now we simplify. 
            if obj.CheckAvailableDiskSpace(hwait) < 0
                return;
            end
            
            t_local = tic;
            for ii = 1:length(obj.groups)
                obj.logger.Write(sprintf('Saving group %d in %s\n', ii, [obj.groups(ii).pathOutput, 'groupResults.mat']));                
                
                % Check that there is anough disk space
                if obj.CheckAvailableDiskSpace(hwait) < 0
                    continue;
                end
                obj.groups(ii).Save(hwait);
            end
            obj.logger.Write(sprintf('Completed saving groupResults.mat for all groups in %0.3f seconds.\n', toc(t_local)));
@@ -378,6 +417,19 @@ classdef DataTreeClass < handle
        end

        
        % ----------------------------------------------------------
        function ResetCurrElem(obj)
            obj.currElem.Reset();
            idx = obj.currElem.GetIndexID();
            if isa(obj.currElem, 'SubjClass')
                obj.groups(idx(1)).Reset('up')
            elseif isa(obj.currElem, 'RunClass')
                obj.groups(idx(1)).Reset('up')
                obj.groups(idx(1)).subjs(idx(2)).Reset('up')
            end
        end
        
        
        % ----------------------------------------------------------
        function b = IsEmpty(obj)
            b = true;
+62 −17
Original line number Diff line number Diff line
@@ -4,7 +4,6 @@ classdef GroupClass < TreeNodeClass
        version;
        versionStr;
        subjs;
        spaceRequired;
        spacesaver;
        logger
    end
@@ -34,7 +33,6 @@ classdef GroupClass < TreeNodeClass
            
            obj.type    = 'group';
            obj.subjs   = SubjClass().empty;
            obj.spaceRequired = struct('memory',0, 'disk',0);
            obj.spacesaver = false;
            
            if nargin==0
@@ -269,10 +267,54 @@ classdef GroupClass < TreeNodeClass
                return;
            end
            
            nbytes = obj.procStream.MemoryRequired() + length(obj.subjs) * obj.subjs(1).MemoryRequired(option);
            nbytes = [0,0,0];
            ks = find(obj.groups.SubjsProcFlags==1);
            kr = find(obj.groups.RunsProcFlags==1);
            
            % We assume for practcal purposes that unprocessed nodes take up zero bytes 
            if ~isempty(kg)
                nbytes(1) = length(kg) * obj.groups(kg(1)).MemoryRequired();
            end
            if ~isempty(ks)
                [iG,iS] = ind2sub(size(obj.groups.SubjsProcFlags), ks);
                nbytes(2) = length(ks) * obj.groups(iG(1)).subjs(iS(1)).MemoryRequired();
            end
            if ~isempty(kr)
                [iG,iS,iR] = ind2sub(size(obj.groups.RunsProcFlags), kr);
                nbytes(3) = length(kr) * obj.groups(iG(1)).subjs(iS(1)).runs(iR(1)).MemoryRequired(option);
            end
                        
            % Add up the bytes. 
            nbytes = sum(nbytes);
        end
        
        
        % ----------------------------------------------------------------------------------
        function diskspaceToSpare = CheckAvailableDiskSpace(obj, hwait)
            if ishandle(hwait)
                obj.logger.Write(sprintf('Estimating disk space required to save processing results ...\n'), obj.logger.ProgressBar(), hwait);
            end
            memRequired = obj.MemoryRequired('disk');
            diskspaceToSpare = (getFreeDiskSpace() - memRequired);   % Disk space to spare in megabytes
            diskspacePercentRemaining = 100 * diskspaceToSpare/memRequired;
            msg = {};
            obj.logger.Write(sprintf('CheckAvailableDiskSpace:    disk space available = %0.1f MB,    required disk space estimate = %0.1f MB\n', getFreeDiskSpace()/1e6, memRequired/1e6));
            if diskspaceToSpare < 0
                msg{1} = sprintf('ERROR: Cannot save processing results requiring ~%0.1f MB of disk space on current drive with only %0.1f MB of free space available.\n', ...
                                  memRequired/1e6, getFreeDiskSpace()/1e6);
            elseif diskspacePercentRemaining < 200
                msg{1} = sprintf('WARNING: Available disk space on the current drive is low (%0.1f MB). This may cause problems saving processing results in the future.', ...
                                  getFreeDiskSpace()/1e6);
                msg{2} = sprintf('Consider moving your data set to a drive with more free space\n');
            end            
            if ~isempty(msg)
                MessageBox([msg{:}]);
                obj.logger.Write([msg{:}]);
            end            
        end
        
        
            
         % ----------------------------------------------------------------------------------        
        function nbytes = MemoryRequiredExact(obj, option)
            if ~exist('option','var')
@@ -497,10 +539,9 @@ classdef GroupClass < TreeNodeClass
                obj.updateParentGui('DataTreeClass', [obj.iGroup, obj.iSubj, obj.iRun]);
            end
            
            % Reset space required to zero so it will be recalculated in
            % the Save() method 
            obj.spaceRequired.memory = 0;
            obj.spaceRequired.disk = 0;
            % Mark this Group as having processed data thereby taking up
            % memory
            obj.GroupsProcFlags(obj.iGroup, 1);
        end
        
        
@@ -533,12 +574,18 @@ classdef GroupClass < TreeNodeClass
        % ----------------------------------------------------------------------------------
        % Deletes derived data in procStream.output
        % ----------------------------------------------------------------------------------
        function Reset(obj)
        function Reset(obj, option)
            if ~exist('option','var')
                option = 'down';
            end
            obj.procStream.output = ProcResultClass();            
            if strcmp(option, 'down')
                for jj=1:length(obj.subjs)
                    obj.subjs(jj).Reset();
                end
            end
            obj.GroupsProcFlags(obj.iGroup, 0);
        end
        
        
        % ----------------------------------------------------------------------------------
@@ -569,8 +616,6 @@ classdef GroupClass < TreeNodeClass
            if isempty(obj)
                return;
            end
            obj.spaceRequired.memory = 0;
            obj.spaceRequired.disk = 0;
            
            group = [];
            if exist([obj.path, 'groupResults.mat'],'file')
+13 −0
Original line number Diff line number Diff line
@@ -508,6 +508,19 @@ classdef ProcResultClass < handle
        end
        
        
        % ----------------------------------------------------------------------------------
        function b = IsEmpty(obj)
            b=0;
            if obj.HaveTimeCourseOutput()
                return;
            end
            if obj.HaveBlockAvgOutput()
                return;
            end
            b=1;
        end
        
        
        % ----------------------------------------------------------------------------------
        function n = GetNumChForOneCondition(obj, iBlk)
            n = 0;
+4 −0
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ classdef RunClass < TreeNodeClass
        % ----------------------------------------------------------------------------------
        function Reset(obj)
            obj.procStream.output = ProcResultClass();
            obj.RunsProcFlags(obj.iGroup, obj.iSubj, obj.iRun, 0);
        end
        
        
@@ -224,6 +225,9 @@ classdef RunClass < TreeNodeClass
                fprintf('\n')
            end
            
            % Mark this run as having processed data thereby taking up
            % memory
            obj.RunsProcFlags(obj.iGroup, obj.iSubj, obj.iRun, 1);
        end


+14 −12
Original line number Diff line number Diff line
@@ -148,12 +148,18 @@ classdef SubjClass < TreeNodeClass
        % ----------------------------------------------------------------------------------
        % Deletes derived data in procResult
        % ----------------------------------------------------------------------------------
        function Reset(obj)
        function Reset(obj, option)
            if ~exist('option','var')
                option = 'down';
            end
            obj.procStream.output = ProcResultClass();
            if strcmp(option, 'down')
                for jj=1:length(obj.runs)
                    obj.runs(jj).Reset();
                end
            end
            obj.SubjsProcFlags(obj.iGroup, obj.iSubj, 0);
        end
        
        
        % ----------------------------------------------------------------------------------
@@ -231,6 +237,11 @@ classdef SubjClass < TreeNodeClass
                obj.updateParentGui('DataTreeClass', [obj.iGroup, obj.iSubj, obj.iRun]);
            end
            pause(.5);
            
            % Mark this subject as having processed data thereby taking up
            % memory
            obj.SubjsProcFlags(obj.iGroup, obj.iSubj, 1);
            
        end
                
        
@@ -414,15 +425,6 @@ classdef SubjClass < TreeNodeClass
        end
                

        % ----------------------------------------------------------------------------------        
        function nbytes = MemoryRequired(obj, option)
            if ~exist('option','var')
                option = 'disk';
            end
            nbytes = obj.procStream.MemoryRequired() + length(obj.runs) * obj.runs(1).MemoryRequired(option);
        end

        
        % ----------------------------------------------------------------------------------        
        function nbytes = MemoryRequiredExact(obj, option)
            if ~exist('option','var')
Loading