From 3f1cd6ef0ec087555f208eb906e5eedfd4384ea8 Mon Sep 17 00:00:00 2001 From: Bryan Roessler Date: Fri, 26 Jul 2024 02:53:58 -0400 Subject: [PATCH] EASYconsole.m rewrite --- workflow/templates/easy/EASYconsole.m | 594 ++++++++++++++------------ 1 file changed, 323 insertions(+), 271 deletions(-) diff --git a/workflow/templates/easy/EASYconsole.m b/workflow/templates/easy/EASYconsole.m index a629d32a..5133bc6d 100644 --- a/workflow/templates/easy/EASYconsole.m +++ b/workflow/templates/easy/EASYconsole.m @@ -3,57 +3,134 @@ % Updated 240724 Bryan C Roessler to improve file operations and portability % function varargout = EASYconsole(varargin) - % initialize global variables for function EASYconsole - %global ExpOutmat - %global ExpPath - %global fhconsole - %global resDir - global wCodeDir - %global ImParMat + global startDir + global easyDir + global easySuffix + global scansDir + global easyResultsDir + global easyResultsDirName + global matDir + global matFile + global userName - wCodeDir=pwd; + % Initialize some variables from matlab + startDir=pwd; + easyPath=which(mfilename); + [easyDir,easy_filename]=fileparts(easyPath); + easyDir=fullfile(easyDir) + [parentDir, ~]=fileparts(easyDir); + userName=system('whoami'); - % changing directory to wCodeDir - % returnStartDir + % Set scansDir intelligently (project scans directory) + % Allow users to specify a PROJECT=/mnt/data/ExpJobs/Job directory to analyze with EASY + % This better enables running the new EASY in standalone mode + if exist('PROJECT', 'env') + scansDir=get_env('PROJECT'); + disp(strcat('Using project path: ', scansDir, ' from environment variable PROJECT')); + disp('This usually indicates that we are in standalone mode'); + elseif exist('SCANS_DIR', 'env') + scansDir=get_env('SCANS_DIR'); + disp(strcat('Using scans directory: ', scansDir, ' from environment variable SCANS_DIR')); + disp('This usually indicates that we are in module mode'); + else + scansDir=fullfile(parentDir,'ExpJobs'); % relative to easy script dir + disp(strcat('Using scans directory: ', scansDir, ' from hardcoded default')); + disp('This usually indicates that we are in standalone mode'); + end - disp(getenv('SCANS_DIR')); - - %% GUI INTERFACE DESIGN %% - % beginning of GUI formation & design, see help GUI or help GUIDE in - % command window for more information - gui_Singleton = 1; - gui_State = struct('gui_Name', mfilename, ... - 'gui_Singleton', gui_Singleton, ... - 'gui_OpeningFcn', @EASYconsole_OpeningFcn, ... - 'gui_OutputFcn', @EASYconsole_OutputFcn, ... - 'gui_LayoutFcn', [] , ... - 'gui_Callback', []); - if nargin && ischar(varargin{1}) - gui_State.gui_Callback = str2func(varargin{1}); + % If we don't have the EASY_SUFFIX from the module, generate it from scanDir + if exist('EASY_SUFFIX', 'env') + easySuffix=get_env('EASY_SUFFIX'); + else + [dirName, ~]=fileparts(scansDir); + [date, userNameScans, easySuffix]=strsplit(dirName, '_'); + % The following is handled by the workflow script that calls this module + % Reimplementing here for stand-alone mode + % While the easySuffix directory exists, increment by one and try again + if exist(easySuffix, 'dir') + oldSuffix=easySuffix + while exist(easySuffix, 'dir') + count=1; + easySuffix=strcat(oldSuffix,'.', num2str(count)); + end end - - if nargout - [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); - else - gui_mainfcn(gui_State, varargin{:}); + % Might as well check this too + if userName ~= userNameScans + disp('WARNING: userName does not match userNameScans'); + disp("This usually means that you are attempting to run an EASY analysis on another user's project data scans"); end + % For happiness + if datestr(now, 'yyyymmdd') == date + disp("Early bird gets the worm") + end + end + + % Helpful variables for running in workflow mode that I'll probably have to reimplement in matlab anyways for standalone mode + if exist('EASY_DIR','env') + EASY_DIR=fullfile(get_env('EASY_DIR')) + if easyDir ~= EASY_DIR % sanity check + disp("WARNING: EASY_DIR does not match this script's default EASY location"); + easyDir=EASY_DIR + end + disp(strcat('Using EASY script directory: ', easyDir, ' from environment variable EASY_DIR')); + else + disp(strcat('Using EASY script directory: ', easyDir, ' from hardcoded default')); + end + + if exist('EASY_RESULTS_DIR', 'env') + easyResultsDir=fullfile(get_env('EASY_RESULTS_DIR')); + disp(strcat('Using project prefix: ', easyResultsDir, ' from environment variable EASY_RESULTS_DIR')) + else + easyResultsDirName=strcat('Results_',datestr(now, 'yyyymmdd'),'_',easySuffix); + easyResultsDir=fullfile(scansDir,easyResultsDirName); + scansDir=fullfile(parent_dir,'ExpJobs') % relative to easy script dir + disp(strcat('Using project prefix: ', PROJECT_PREFIX, ' from environment variable PROJECT_PREFIX')) + end + + if exist('PROJECT_USER', 'env') + if get_env('PROJECT_USER') ~= userName % sanity check + disp("WARNING: PROJECT_USER does not match the current namespace"); + end + end + + matDir=fullfile(easyResultsDir,'matResults'); + matFile=fullfile(matDir,strcat(easyResultsDirName,'.mat')); + + % Play around with making some common variables from our input data + % resDirName=fullfile(SCANS_DIR,'Results',strcat(datestr(now, 'yyyymmdd'),'_', PROJECT_SUFFIX); + % resDir=fullfile(SCANS_DIR,resDirName); + % ExpOutmat=fullfile(matDir,strcat(datestr(now,29),newExpfile)); + % ExpPath=fullfile(newExppath); + % ExpFile=fullfile(matDir,) + + % GUI interface design + gui_Singleton=1; + gui_State=struct('gui_Name', mfilename, ... + 'gui_Singleton', gui_Singleton, ... + 'gui_OpeningFcn', @EASYconsole_OpeningFcn, ... + 'gui_OutputFcn', @EASYconsole_OutputFcn, ... + 'gui_LayoutFcn', [] , ... + 'gui_Callback', []); + if nargin && ischar(varargin{1}) + gui_State.gui_Callback=str2func(varargin{1}); + end + + if nargout + [varargout{1:nargout}]=gui_mainfcn(gui_State, varargin{:}); + else + gui_mainfcn(gui_State, varargin{:}); + end end - -% Try to enter WCodeDir +% To remove? +% Try to enter function returnStartDir - global wCodeDir + global try - cd(wCodeDir) + cd(SCANS_DIR) catch - msgbox('Failed to enter selected default directory so starting search at root.'); - if ispc - cd('C:\'); - elseif (isunix || ismac) - cd('/mnt/data'); - else - msgbox('Unknown platform') - end + msgbox('Failed to enter the project directory so starting search from where we started.'); + cd(start_dir) end end @@ -65,40 +142,40 @@ end % handles--structure with handles and user data (see GUIDATA) % varargin--input arguments to EASYconsole (see VARARGIN) function EASYconsole_OpeningFcn(hObject, ~, handles, varargin) - %global ExpOutmat - %global ExpPath - global fhconsole - global resDir - %global ImParMat + global fhconsole + global easyResultsDir - % Choose default command line output for EASYconsole - handles.output = hObject; + % Choose default command line output for EASYconsole + handles.output = hObject; - % Update handles structure - guidata(hObject, handles); + % Update handles structure + guidata(hObject, handles); - %Figure header, Toolbar, etc. Setup - fhconsole=gcf; - set(fhconsole,'Toolbar','none'); - fhconsole=gcf; - - if exist('resDir','var')&&~isempty(resDir) - set(fhconsole,'Name',strcat('EASYconsole- ',char(resDir))); - else - set(fhconsole,'Name','EASYconsole -Exp. Analysis NOT selected.') - end + %Figure header, Toolbar, etc. Setup + fhconsole=gcf; + set(fhconsole,'Toolbar','none'); + fhconsole=gcf; + + % BCR this is set in the global function so I think we're good here + % easyResultsDirName=strcat('Results',datestr(now, 'yyyymmdd'),newExpfilePref); + + if exist('easyResultsDir','var') && ~isempty(easyResultsDir) + set(fhconsole,'Name',strcat('EASYconsole- ',char(easyResultsDir))); + else + set(fhconsole,'Name','EASYconsole -Exp. Analysis NOT selected.') + end end -%% EASYconsole OUTPUT FUNCTION %% +% EASYconsole OUTPUT FUNCTION %% % Outputs from this function are returned to the command line. % varargout--cell array for returning output args (see VARARGOUT); % hObject--handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles--structure with handles and user data (see GUIDATA) function varargout = EASYconsole_OutputFcn(~, ~, handles) - % Get default command line output from handles structure - varargout{1} = handles.output; + % Get default command line output from handles structure + varargout{1} = handles.output; end %% CONSOLE BUTTON INTERFACES %% @@ -114,194 +191,179 @@ end % New Experiment Button Interface function NewExpDat_Callback(~, ~, ~) - global newExpfile - global newExppath - global SWnewExp - global ExpOutmat - global ExpPath - global matDir - global resDir - global fhconsole - global scan + global SWnewExp + global matDir + global matFile + global easyResultsDir + global easyResultsDirName + global fhconsole + global scan + global userName - % put all users on same working directory - %returnStartDir + % Create a new experiment + try + questdlg('\fontsize{20} NAME the file and NAVIGATE to the directory with the image folders.','File Creation','OK', struct('Default','OK','Interpreter','tex')); + [inputFile,inputPath]=uiputfile('.mat'); + SWnewExp=1; - % Create a new experiment - try - questdlg('\fontsize{20} NAME the file and NAVIGATE to the directory with the image folders.','File Creation','OK', struct('Default','OK','Interpreter','tex')); - [newExpfile,newExppath] = uiputfile(' .mat'); - SWnewExp=1; + inputFileName=strrep(inputFile,'.mat',''); + easyResultsDirName=strcat('Results_',datestr(now,'yyyymmdd'),'_',userName,'_',inputFileName); - % Set paths - newExpfilePref= strrep(newExpfile,'.mat',''); - resDir=fullfile(newExppath,resDirName); - matDir=fullfile(newExppath,resDirName,'matResults'); - ExpOutmat=fullfile(matDir,strcat(datestr(now,29),newExpfile)); - ExpPath=fullfile(newExppath); - - %***Added for 'parfor global' to preallocate 'scan' structure 20-0123***** - nlist=dir(fullfile(ExpPath,'*')); - nnn=0; - for n=1:size(nlist,1) - if (~isempty(str2num(nlist(n).name))) - nnn=nnn+1; - PnumLst(nnn)= (str2num(nlist(n).name)); - sl(nnn,1)={(nlist(n).name)}; - end - end - scanSize= size(sl,1); - scanMax= max(str2double(sl)); - clear scan; - scan(scanMax)= struct(); %changed for parfor global 20_0118 - save(ExpOutmat,'scan') + % Set paths + scansDir=fullfile(inputPath); + easyResultsDir=fullfile(scansDir,easyResultsDirName); + matDir=fullfile(easyResultsDir,'matResults'); + matFile=fullfile(matDir,strcat(datestr(now,'yyyymmdd'),'_',userName,'_',inputFile)); + + %***Added for 'parfor global' to preallocate 'scan' structure 20-0123***** + nlist=dir(fullfile(scansDir,'*')); + nnn=0; + for n=1:size(nlist,1) + if (~isempty(str2num(nlist(n).name))) + nnn=nnn+1; + PnumLst(nnn)= (str2num(nlist(n).name)); + sl(nnn,1)={(nlist(n).name)}; + end + end + scanSize=size(sl,1); + scanMax=max(str2double(sl)); + clear scan; + scan(scanMax)=struct(); % changed for parfor global 20_0118 + save(matFile,'scan') - % BCR rewrote these but moved the functionality into the main workflow script - % % create supporting dirs - % dirs = {'PrintResults', 'CFfigs', 'Fotos', 'Fotos/BkUp'}; - % for i = 1:length(dirs) - % d = dirs{i}; - % if ~exist(fullfile(ExpPath, resDirName, d), 'dir') - % mkdir(fullfile(ExpPath, resDirName, d)); - % end - % end - - % % templateDirs are stored in the easy template directory - % templates = {'figs', 'PTmats'} - % for i = 1:length(templates) - % d = dirs{i}; - % if ~exist(fullfile(ExpPath, resDirName, d), 'dir') - % copyfile((fullfile(wCodeDir,d)), (fullfile(ExpPath,resDirName,d))); - % end - % end - - clear sbdg % reduce possible retention of a previous job sdbg - sbdg= cell(1,scanMax); - save((fullfile(resDir,'Fotos','Nbdg')),'sbdg'); - catch ME - % returnStartDir - disp('Error Creating a New Experiment') + % create supporting dirs + % this is also in the workflow script but here for standalone mode + dirs = {'PrintResults', 'CFfigs', 'Fotos', 'Fotos/BkUp'}; + for i = 1:length(dirs) + d = dirs{i}; + if ~exist(fullfile(easyResultsDir, d), 'dir') + mkdir(fullfile(easyResultsDir, d)); + end end - % set the title for fhconsole depending on existence - if exist('resDir','var')&&~isempty(resDir) - set(fhconsole,'Name',strcat('EASYconsole- ',char(resDir))) - else - set(fhconsole,'Name','EASYconsole -Exp. Analysis NOT selected.') + % templateDirs are stored in the easy template directory + templates = {'figs', 'PTmats'} + for i = 1:length(templates) + d = dirs{i}; + if ~exist(fullfile(easyResultsDir, d), 'dir') + copyfile((fullfile(,d)), (fullfile(easyResultsDir,d))); + end end + + clear sbdg % reduce possible retention of a previous job sdbg + sbdg= cell(1,scanMax); + save((fullfile(easyResultsDir,'Fotos','Nbdg')),'sbdg'); + catch ME + % returnStartDir + disp('Error Creating a New Experiment') + end + + % set the title for fhconsole depending on existence + if exist('easyResultsDir','var')&&~isempty(easyResultsDir) + set(fhconsole,'Name',strcat('EASYconsole- ',char(easyResultsDir))) + else + set(fhconsole,'Name','EASYconsole -Exp. Analysis NOT selected.') + end end % Load a previous experiment function LoadDatFile_Callback(~, ~, ~) - global openExpfile - global openExppath - global SWnewExp - global ExpOutmat - global ExpPath - global matDir - global resDir - global fhconsole - %global ImParMat + global SWnewExp + global matDir + global matFile + global easyResultsDir + global easyPath + global fhconsole + %global ImParMat - % TODO this entire try block needs work - try - % TODO this whole block is highly questionable - questdlg('\fontsize{20} Load file from ExpJobs/YourJob/YourResults/matResults','File Creation','OK', struct('Default','OK','Interpreter','tex')); - [openExpfile,openExppath] = uigetfile('.mat','Open Experiment folder and data storage .mat file name','MultiSelect','off'); - SWnewExp=0; - ExpOutmat= fullfile(openExppath,openExpfile); - load(ExpOutmat); - resdir=fullfile('../',openExppath) - ExpPath=fullfile('../../',openExppath) - - if isfolder(fullfile(openExppath, '..','..','1')) %If Inovation Vrobot Then - if exist(fullfile(resDir,'PTmats','NImParameters.mat'), 'file') - load(fullfile(resDir,'PTmats','NImParameters.mat')); - else - curDir=pwd; - returnStartDir - load NImParameters.mat - cd(curDir) - end - else %If Epson 10Plate Scans Then> - if exist(fullfile(resDir,'PTmats','ImParameters.mat'), 'file') - load(fullfile(resDir,'PTmats','ImParameters.mat')); - else - curDir=pwd; - returnStartDir - load ImParameters.mat - cd(curDir) - end - end + try + questdlg('\fontsize{20} Load file from ExpJobs/YourJob/YourResults/matResults','File Creation','OK', struct('Default','OK','Interpreter','tex')); + [inputFile,inputPath]=uigetfile('.mat','Open Experiment folder and data storage .mat file name','MultiSelect','off'); + SWnewExp=0; + matDir=fullfile(inputPath) + matFile=fullfile(inputPath,inputFile); + load(matFile); + easyResultsDir=fullfile(matDir,'..') + scansDir=fullfile(matDir,'..', '..') - mkdir(fullfile(openExppath,'\BkUp')); - - % create supporting dirs - % dirs = {'PrintResults', 'figs', 'CFfigs', 'PTmats', 'Fotos'} - % for i = 1:length(dirs) - % d = dirs{i} - % if ~exist(fullfile(resDir, d), 'dir') - % mkdir(fullfile(resDir, d)); - % end - % end - - catch - returnStartDir + if isfolder(fullfile(matDir, '..','..','1')) % If Inovation Vrobot Then + if exist(fullfile(easyResultsDir,'PTmats','NImParameters.mat'), 'file') + load(fullfile(easyResultsDir,'PTmats','NImParameters.mat')); + else + load(fullfile(easyPath,'NImParameters.mat')); + end + else % If Epson 10Plate Scans Then> + if exist(fullfile(easyResultsDir,'PTmats','ImParameters.mat'), 'file') + load(fullfile(easyResultsDir,'PTmats','ImParameters.mat')); + else + load(fullfile(easyPath,'ImParameters.mat')); + end end - clear scan + mkdir(fullfile(matDir,'BkUp')); - if exist('resDir','var')&&~isempty(resDir) - fhconsole= gcf; - set(fhconsole,'Name',strcat('EASYconsole- ',char(resDir))) - else - set(fhconsole,'Name','EASYconsole -Exp. Analysis NOT selected.') + % Create supporting dirs + dirs = {'PrintResults', 'figs', 'CFfigs', 'PTmats', 'Fotos'} + for i = 1:length(dirs) + d = dirs{i} + if ~exist(fullfile(easyResultsDir, d), 'dir') + mkdir(fullfile(easyResultsDir, d)); + end end + catch + returnStartDir + end + + clear scan + + if exist('easyResultsDir','var') && ~isempty(easyResultsDir) + fhconsole=gcf; + set(fhconsole,'Name',strcat('EASYconsole- ',char(easyResultsDir))) + else + set(fhconsole,'Name','EASYconsole -Exp. Analysis NOT selected.') + end end - %% CALLBACKS %% - % callback for the 'Run' in the dropdown menu function run_Callback(~, ~, ~) - end function runPlateMapPintool_Callback(~, ~, ~) - try - NImapPT - catch ME - returnStartDir - EASYconsole - end + try + NImapPT + catch ME + returnStartDir + EASYconsole + end end function NImCFcombo_Callback(~, ~, ~) - try - par4Gbl_Main8c - catch - returnStartDir - EASYconsole - end + try + par4Gbl_Main8c + catch + returnStartDir + EASYconsole + end end function runPlateImAnal_Callback(~, ~, ~) - try - NImStartupOnly - catch ME - returnStartDir - EASYconsole - end + try + NImStartupOnly + catch ME + returnStartDir + EASYconsole + end end function PlateCFit_Callback(~, ~, ~) - %global ExpOutmat - try - NCstart - catch ME - returnStartDir - end + % global matFile % TODO BCR not sure if needed + try + NCstart + catch ME + returnStartDir + end end function GenPrintouts_Callback(~, ~, ~) @@ -311,83 +373,73 @@ function uploadExcelMP2DB_Callback(~, ~, ~) end function runDMPexcel_Callback(~, ~, ~) - global ExpPath - try - DMPexcel2mat_2024winLinix %DMPexcel2mat_2023winLinix - catch ME - returnStartDir - EASYconsole - end + try + DMPexcel2mat_2024winLinix %DMPexcel2mat_2023winLinix + catch ME + returnStartDir + EASYconsole + end end function runResults_DBcombo_Callback(~, ~, ~) - - try - DgenResults240430 %similar but semicolons removed to restore so cmdLine display info. - %Dgen241010qhtcp %par4global -convert 1x1cell of 384cells to be like previous 1x384 cells CFparameter - catch ME - disp('Error in DgenResults240430') - returnStartDir - EASYconsole - end + try + DgenResults240430 %similar but semicolons removed to restore so cmdLine display info. + %Dgen241010qhtcp %par4global -convert 1x1cell of 384cells to be like previous 1x384 cells CFparameter + catch ME + disp('Error in DgenResults240430') + EASYconsole + end end function Tools_Callback(~, ~, ~) end function runOverlayPlots_Callback(~, ~, ~) - try - DoverlayPlots2 - EASYconsole - catch ME - returnStartDir - EASYconsole - end + try + DoverlayPlots2 + EASYconsole + catch ME + EASYconsole + end end function runFotoStrip_Callback(~, ~, ~) - try - F_NImStartup_CentCir - EASYconsole - catch ME - returnStartDir - EASYconsole - end + try + F_NImStartup_CentCir + EASYconsole + catch ME + EASYconsole + end end function runDisplayFig_Callback(~, ~, ~) - try - UfigDisplay - catch ME - returnStartDir - EASYconsole - end + try + UfigDisplay + catch ME + EASYconsole + end end function runViewParameters_Callback(~, ~, ~) - try - catch ME - returnStartDir - EASYconsole - end + try + catch ME + EASYconsole + end end function QkviewN_Callback(~, ~, ~) - try - QkviewImages - catch ME - returnStartDir - EASYconsole - end + try + QkviewImages + catch ME + EASYconsole + end end function CFdisplay_Callback(~, ~, ~) - try - NCsingleDisplay - returnStartDir - EASYconsole - catch ME - returnStartDir - EASYconsole - end + try + NCsingleDisplay + EASYconsole + catch ME + EASYconsole + end end \ No newline at end of file