% Launch the MATLAB EASY console % % Updated 240724 Bryan C Roessler to improve file operations and portability % function varargout = EASYconsole(varargin) global easyDir global easySuffix global scansDir global easyResultsDir global easyResultsDirName global fotosResultsDir global figsResultsDir global pointMapsResultsDir global pointMapsFile global printResultsDir global matDir global matFile global drugMediaFile global masterPlateFile global mpdmFile global userName global srchRange global searchRangeFile % Initialize some variables from matlab easyPath=which(mfilename); [easyDir,easyFileName]=fileparts(easyPath); easyDir=fullfile(easyDir); [parentDir, ~]=fileparts(easyDir); userName=system('whoami'); todayStr=datetime('now', 'Format', 'yyyyMMdd'); % This should match the parent workflow script disp(sprintf('This script name: %s\n', easyFileName)) % 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', 'var') && ~isempty(getenv('PROJECT')) scansDir=getenv('PROJECT') disp(sprintf('Using project path: %s from environment variable PROJECT\n', scansDir)); disp('This usually indicates that we are in standalone mode'); elseif exist('SCANS_DIR', 'var') && ~isempty(getenv('SCANS_DIR')) scansDir=getenv('SCANS_DIR'); disp(sprintf('Using scans directory: %s from environment variable SCANS_DIR\n', scansDir)); disp('This usually indicates that we are in module mode'); else dirToScan = fullfile(parentDir,'ExpJobs'); % hardcoded relative to easy script dir TODO: if we change pj layout this will change if exist(dirToScan, 'dir') dirs=dir(fullfile(dirToScan, 'dir')); % filter for dirs only [~, sortedIndices]=sort(datenum({dirs.date}), 'descend'); % sort by newest first sortedDirs=dirs{sortedIndices}; scansDir=sortedDirs{1}; disp('Beginning in newest project scans directory'); disp(sprintf('Using scans directory: %s from hardcoded relative path\n', scansDir)); disp('This usually indicates that we are in stand-alone mode without PROJECT or SCANS_DIR environment variables'); else scansDir=fullfile('/mnt/data/ExpJobs/demo') if exist(scansDir, 'dir') disp(sprintf('Using scans directory: %s from hardcoded absolute path to demo\n', scansDir)); else disp(sprintf('Error: scansDir %s does not exist\n', scansDir)); end end end % If we don't have the EASY_SUFFIX from the module, generate it from scansDir if exist('EASY_SUFFIX', 'var') && ~isempty(getenv('EASY_SUFFIX')) easySuffix=get_env('EASY_SUFFIX'); else [dirName, ~]=fileparts(scansDir); [scansDate, scansUserName, 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 % Might as well check this too if userName ~= scansUserName disp('WARNING: userName does not match scansUserName'); disp("This usually means that you are attempting to run an EASY analysis on another user's project data scans"); end % For happiness if todayStr == scansDate 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','var') && ~isempty(getenv('EASY_DIR')) EASY_DIR=fullfile(get_env('EASY_DIR')); if easyDir ~= EASY_DIR % sanity check disp("WARNING: EASY_DIR does not match this script's hardcoded EASY location"); disp("This is probably OK but if strange beahvior arises, we'll need to fix it in code"); easyDir=EASY_DIR; end disp(sprintf('Using EASY script directory: %s from environment variable EASY_DIR\n', easyDir)); else disp(sprintf('Using EASY script directory: %s from hardcoded default\n', easyDir)); end if exist('PROJECT_USER', 'var') && ~isempty(getenv('PROJECT_USER')) if get_env('PROJECT_USER') ~= userName % sanity check disp("WARNING: PROJECT_USER does not match the current namespace"); end end if exist('EASY_RESULTS_DIR', 'var') && ~isempty(getenv('EASY_RESULTS_DIR')) easyResultsDir=fullfile(get_env('EASY_RESULTS_DIR')); disp(sprintf('Using output directory: %s from environment variable EASY_RESULTS_DIR\n', easyResultsDir)) else easyResultsDirName=strcat('Results_',todayStr,'_',userName,'_',easySuffix); easyResultsDir=fullfile(scansDir,easyResultsDirName); disp(sprintf('Using output directory: %s\n', PROJECT_PREFIX)) end if exist('MASTER_PLATE_FILE', 'var') && ~isempty(getenv('MASTER_PLATE_FILE')) masterPlateFile=fullfile(get_env('MASTER_PLATE_FILE')); disp(sprintf('Using drug media file: %s from environment variable MASTER_PLATE_FILE\n', masterPlateFile)) else % Try to find MasterPlate_ file on our own mp=fullfile(scansDir,'MasterPlateFiles',strcat('MasterPlate_', easySuffix,'.xlsx')); if exist(mp, 'file') masterPlateFile=mp; disp(sprintf('Using drug media file: %s from internal logic\n', masterPlateFile)) else disp("WARNING: Have you created a MasterPlate_ file?") end end if exist('DRUG_MEDIA_FILE', 'var') && ~isempty(getenv('DRUG_MEDIA_FILE')) drugMediaFile=fullfile(get_env('DRUG_MEDIA_FILE')); disp(sprintf('Using drug media file: %s from environment variable DRUG_MEDIA_FILE\n', drugMediaFile)) else % Try to find MasterPlate_ file on our own dm=fullfile(scansDir,'MasterPlateFiles',strcat('DrugMedia_', easySuffix,'.xlsx')); if exist(mp, 'file') drugMediaFile=dm; disp(sprintf('Using drug media file: %s from internal logic\n', drugMediaFile)) else disp("WARNING: Have you created a DrugMedia_ file?") end end matDir=fullfile(easyResultsDir,'matResults'); if ~exist(matDir, 'dir') mkdir(matDir); end matFile=fullfile(matDir,strcat(easyResultsDirName,'.mat')); % Pulled these out of par4GblFnc8c printResultsDir=fullfile(easyResultsDir,'PrintResults'); fotosResultsDir=fullfile(easyResultsDir,'Fotos'); figsResultsDir=fullfile(easyResultsDir,'figs'); pointMapsResultsDir=fullfile(easyResultsDir,'PTmats'); pointMapsFile=fullfile(pointMapsResultsDir,'NImParameters.mat'); oldPointMapsFile=fullfile(pointMapsResultsDir,'ImParameters.mat'); searchRangeFile=fullfile(fotosResultsDir,'CSearchRange.mat'); mpdmFile=fullfile(matDir,'MPDM.mat'); % This can be removed, I think it should add the previous search range? % Might be nice feature but can remove if it causes issues % We are using searchRangeNum to hold old CSrchRange value(s) if exist(searchRangeFile, 'file') searchRangeNum=load(searchRangeFile); end % Add easyDir to the MATLAB path % I have not idea if this is necessary or works but theoretically should % reduce directory scoping issues when calling scripts w/o a path addpath(easyDir); % Pulled this out of the opening function % Seems better to wait until we have our ars set if exist('scansDir','var') && ~isempty(scansDir) set(fhconsole,'Name',sprintf('EASYconsole - %s', scansDir)); else set(fhconsole,'Name','EASYconsole - No Active Experiment.') end % 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 % To remove? % Try to enter % function returnStartDir % global scansDir % global startDir % try % cd(scansDir) % catch % msgbox('Failed to enter the project directory so starting search from where we started.'); % cd(startDir) % end % end % GUI % Easyconcole_OpeningFcn executes just before the EASYconsole GUI is made visible. % This function has no output args, see OutputFcn. % hObject--handle to figure % eventdata reserved - to be defined in a future version of MATLAB % handles--structure with handles and user data (see GUIDATA) % varargin--input arguments to EASYconsole (see VARARGIN) function EASYconsole_OpeningFcn(hObject, ~, handles, varargin) global fhconsole % Choose default command line output for EASYconsole handles.output=hObject; % Update handles structure guidata(hObject, handles); %Figure header, Toolbar, etc. Setup fhconsole=gcf; set(fhconsole,'Toolbar','none'); fhconsole=gcf; end % 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; end %% CONSOLE BUTTON INTERFACES %% % File Button Interface function FileMenu_Callback(~, ~, ~) %returnStartDir end % Load Experiment Button Interface function LoadExp_Callback(~, ~, ~) %returnStartDir end % New Experiment Button Interface function NewExpDat_Callback(~, ~, ~) global matDir global matFile global easyResultsDir global easyResultsDirName global fhconsole global scan global userName % 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'); inputFileName=strrep(inputFile,'.mat',''); easyResultsDirName=strcat('Results_',todayStr,'_',userName,'_',inputFileName); % Set paths scansDir=fullfile(inputPath); easyResultsDir=fullfile(scansDir,easyResultsDirName); matDir=fullfile(easyResultsDir,'matResults'); matFile=fullfile(matDir,strcat(todayStr,'_',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') % 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 % 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(easyDir,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 disp(sprintf('ERROR: %s\n', ME.message)); end % set the title for fhconsole depending on existence if exist('easyResultsDir','var')&&~isempty(easyResultsDir) set(fhconsole,'Name',sprintf('EASYconsole - %s', easyResultsDir)); else set(fhconsole,'Name','EASYconsole - Master Plate directory not selected.'); end end % Load a previous experiment function LoadDatFile_Callback(~, ~, ~) global matDir global matFile global easyResultsDir global easyPath global fhconsole 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'); matDir=fullfile(inputPath); matFile=fullfile(inputPath,inputFile); load(matFile); easyResultsDir=fullfile(matDir,'..'); scansDir=fullfile(matDir,'..', '..'); point % TODO this is pretty hacky and needs something more explicit if isfolder(fullfile(matDir, '..','..','1')) % If Inovation Vrobot Then try exist(pointMapsFile, 'file') load(pointMapsFile); catch try load(fullfile(easyPath,'NImParameters.mat')); % hardcoded default catch disp("Could not load the NImParameters.mat file") end end else % If Epson 10Plate Scans Then> if exist(fullfile(pointMapsResultsDir,'ImParameters.mat'), 'file') load(fullfile(pointMapsResultsDir,'ImParameters.mat')); else try load(fullfile(easyPath,'ImParameters.mat')); catch disp("Could not load the ImParameters.mat file") end end end bkupDir=fullfile(matDir,'BkUp'); if ~exist(bkupDir, 'dir') mkkdir(bkupDir); end % 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 end clear scan if exist('easyResultsDir','var') && ~isempty(easyResultsDir) fhconsole=gcf; set(fhconsole,'Name',sprintf('EASYconsole - %s', easyResultsDir)); else set(fhconsole,'Name','EASYconsole -Exp. Analysis NOT selected.'); end end % Callbacks % 'Run' in the dropdown menu function run_Callback(~, ~, ~) end function runPlateMapPintool_Callback(~, ~, ~) try NImapPT catch EASYconsole end end function NImCFcombo_Callback(~, ~, ~) try par4Gbl_Main8c catch EASYconsole end end function runPlateImAnal_Callback(~, ~, ~) try NImStartupOnly catch EASYconsole end end function PlateCFit_Callback(~, ~, ~) % global matFile % TODO BCR not sure if needed try NCstart catch end end function GenPrintouts_Callback(~, ~, ~) end function uploadExcelMP2DB_Callback(~, ~, ~) end function runDMPexcel_Callback(~, ~, ~) try DMPexcel2mat catch EASYconsole end end function runResults_DBcombo_Callback(~, ~, ~) try DgenResults %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(sprintf('Error in DgenResults: %s\n', ME.message)); EASYconsole end end function Tools_Callback(~, ~, ~) end function runOverlayPlots_Callback(~, ~, ~) try DoverlayPlots2 EASYconsole catch EASYconsole end end function runFotoStrip_Callback(~, ~, ~) try F_NImStartup_CentCir EASYconsole catch EASYconsole end end function runDisplayFig_Callback(~, ~, ~) try UfigDisplay catch EASYconsole end end function runViewParameters_Callback(~, ~, ~) try catch EASYconsole end end function QkviewN_Callback(~, ~, ~) try QkviewImages catch EASYconsole end end function CFdisplay_Callback(~, ~, ~) try NCsingleDisplay EASYconsole catch EASYconsole end end