% Launch the MATLAB EASY console % Updated 240727 Bryan C Roessler to improve file operations and portability function varargout = EASYconsole(varargin) global easyDir global projectName global projectScansDir global easyResultsDir global easyProjectName 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); parentDir=fullfile(parentDir); % ../easy/apps userName=getenv('USER'); dt=datetime; todayStr=char(dt, 'yyyyMMdd'); % This should match the parent workflow script 'hardcode' outDir=fullfile(parentDir, '..','..', 'out'); % This should match the parent workflow script 'hardcode' debug=1; if debug disp('Running in debug mode'); disp('Initialized variables:'); whos; end fprintf('This script name: %s\n', easyFileName); % Allow EASY_DIR env to override hardcoded default EASY directory if ~isempty(getenv('EASY_DIR')) ed=fullfile(getenv('EASY_DIR')); if ~strcmp(easyDir, ed) % sanity check disp("WARNING: EASY_DIR does not match this script's hardcoded EASY location"); disp("This is probably OK but this pathway is not well-tested"); easyDir=ed; end fprintf('Using EASY script directory: %s from environment variable EASY_DIR\n', easyDir); else fprintf('Using EASY script directory: %s from hardcoded default\n', easyDir); end whos % Set projectScansDir intelligently if ~isempty(getenv('PROJECT_SCANS_DIR')) projectScansDir=fullfile(getenv('PROJECT_SCANS_DIR')); if exist(projectScansDir, 'dir') fprintf('Using scans directory: %s from environment variable PROJECT_SCANS_DIR\n', projectScansDir); disp('This usually indicates that we are in module mode'); else disp('WARNING: PROJECT_SCANS_DIR does not exist'); end elseif ~isempty(getenv('PROJECT_NAME')) % for standalone mode projectName=getenv('PROJECT_NAME'); projectScansDir=fullfile(parentDir, '..', '..', 'scans', projectName); fprintf('Using project path: %s from environment variable PROJECT\n', projectScansDir); disp('This usually indicates that we are in standalone mode'); else % TODO Lots of hardcoded logic, this TODO is just a reminder to change this block % when changing EASY and other variables in the parent script fprintf('WARNING: Running in standalone mode without PROJECT or PROJECT_SCANS_DIR environment variables (not recommended)\n'); fprintf('Beginning parent scans directory search\n'); dirsToScan={ fullfile(parentDir, '..', '..', 'scans') fullfile(parentDir, '..', '..', 'ExpJobs') fullfile('mnt','data','scans') fullfile('mnt','data', 'ExpJobs') fullfile(parentDir, '..', '..', 'templates', 'scans-demo') }; for i=1:length(dirsToScan) d=dirsToScan(i); d=char(d); if exist(d, 'dir') matchedDirs={}; subDirs=dir(d); pattern='^\d{6}_.*_.*'; for i=1:length(subDirs) if ~isempty(strmatch(subDirs(i).name, pattern)) matchedDirs{end+1}=subDirs(i).name; end end whos if ~isempty(matchedDirs) fprintf('Using scansDir %s\n', char(d)); end fprintf('Scanning inside %s for a project directory\n', d); sortedMatchedDirs=sortrows(matchedDirs); projectScansDir=fullfile(sortedMatchedDirs{end}); % select the latest dir (by date prefix) fprintf('Using project scans directory: %s\n', char(projectScansDir)); break end end end % Get the name of the project [~, projectName]=fileparts(projectScansDir); % Set the run-specific EASY output directory if ~isempty(getenv('EASY_RESULTS_DIR')) easyResultsDir=fullfile(getenv('EASY_RESULTS_DIR')); fprintf('Using output directory: %s from environment variable EASY_RESULTS_DIR\n', easyResultsDir); else easyProjectName=strcat(todayStr, '_',userName, '_', projectName); easyResultsDir=fullfile(parentDir, '..', '..', 'out', projectName, 'easy', easyProjectName); if exist(easyResultsDir, 'dir') fprintf('WARNING: EASY results dir %s already exists\n', easyResultsDir); disp('Files in this directory may be overwritten') fprintf('Using output directory: %s\n', easyResultsDir); end end % Get the name of the EASY project if ~isempty(getenv('EASY_PROJECT_NAME')) easyProjectName=getenv('EASY_PROJECT_NAME'); else [~, easyProjectName]=fileparts(easyResultsDir); end % User sanity check and warning if ~isempty(getenv('PROJECT_USER')) if ~strcmp(getenv('PROJECT_USER'), userName) disp("WARNING: PROJECT_USER does not match the current namespace"); end end if ~isempty(getenv('MASTER_PLATE_FILE')) masterPlateFile=fullfile(getenv('MASTER_PLATE_FILE')); fprintf('Using drug media file: %s from environment variable MASTER_PLATE_FILE\n', masterPlateFile); else % try to find MasterPlate_ file on our own mp=fullfile(easyResultsDir, strcat('MasterPlate_', projectName,'.xlsx')); if exist(mp, 'file') masterPlateFile=mp; fprintf('Using master plate file: %s from internal logic\n', masterPlateFile); else fprintf('WARNING: Could not find MasterPlate file: %s\n', mp); fprintf('WARNING: Have you created a MasterPlate_ file in %s', easyResultsDir); end end if ~isempty(getenv('DRUG_MEDIA_FILE')) drugMediaFile=fullfile(getenv('DRUG_MEDIA_FILE')); fprintf('Using drug media file: %s from environment variable DRUG_MEDIA_FILE\n', drugMediaFile); else dm=fullfile(easyResultsDir, strcat('DrugMedia_', projectName,'.xlsx')); if exist(dm, 'file') drugMediaFile=dm; fprintf('Using drug media file: %s from internal logic\n', drugMediaFile); else fprintf('WARNING: Have you created a DrugMedia_ file in %s?\n', easyResultsDir); end end matDir=fullfile(easyResultsDir, 'matResults'); matFile=fullfile(matDir,easyProjectName,'.mat'); mpdmFile=fullfile(matDir,'MPDM.mat'); 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'); % Decent time to print some helpful vars if debug disp('Vars at end of main loop:') whos; end % 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); % 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 % 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 global projectScansDir % 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; % Pulled this out of the opening function % Seems better to wait until we have our vars set though? if exist('projectScansDir','var') && ~isempty(projectScansDir) set(fhconsole,'Name', sprintf('EASYconsole - %s', projectScansDir)); else set(fhconsole,'Name','EASYconsole - No Active Experiment.') end end % EASYconsole output % 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 easyProjectName global fhconsole global scan global userName global todayStr % Create a new experiment try questdlg('Name the file and navigate to the directory with the image folders.','File Creation','OK', struct('Default','OK','Interpreter','tex')); [matfile,easyResultsDir]=uiputfile('.mat'); inputFileName=strrep(inputFile,'.mat',''); [~, projectName]=fileparts(easyResultsDir); % Set paths matDir=fullfile(easyResultsDir,'matResults'); matFile=fullfile(matDir, projectName, '.mat'); % Added for 'parfor global' to preallocate 'scan' structure nlist=dir(fullfile(projectScansDir,'*')); 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'}; 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 fprintf('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 projectName global easyResultsDir global easyProjectName global easyPath global fhconsole try questdlg('Load results .mat from ../out/project/','File Creation','OK', struct('Default','OK','Interpreter','tex')); [matDir,matFile]=uigetfile('.mat','Open Experiment folder and data storage .mat file name','MultiSelect','off'); load(matFile); easyResultsDir=fullfile(matDir,'..'); [~, projectName]=fileparts(easyResultsDir); projectScansDir=fullfile(easyResultsDir, '..', '..', 'scans', projectName); % TODO this is pretty hacky and needs something more explicit if isfolder(fullfile(matDir, '..','..','1')) % If Inovation Vrobot Then if load(pointMapsFile); elseif load(fullfile(easyPath,'NImParameters.mat')); % hardcoded default elseif load(fullfile(pointMapsResultsDir,'ImParameters.mat')); elseif load(fullfile(easyPath,'ImParameters.mat')); else disp("Could not load the ImParameters.mat file"); end else disp('WARNING: cannot find project scans'); 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 EASYconsole 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 EASYconsole 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 catch ME fprintf('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