From 4af84b4eaa3d0a4e9893ecb8a3ef2143de45ae02 Mon Sep 17 00:00:00 2001 From: Mark Winter <mwinter@drexel.edu> Date: Wed, 20 Jan 2021 15:24:04 +0100 Subject: [PATCH] Graphical tool for identifying regions for phalloidin/myosin comparison --- urchin_compare/+Dev/VersionInfo.m | 10 + urchin_compare/.gitignore | 6 + urchin_compare/compile_urchin.m | 46 ++ urchin_compare/helpdlg.fig | Bin 0 -> 7021 bytes urchin_compare/helpdlg.m | 86 ++ urchin_compare/settings.json | 8 + urchin_compare/toolsdlg.fig | Bin 0 -> 41989 bytes urchin_compare/toolsdlg.m | 537 +++++++++++++ urchin_compare/urchin_compare.m | 1232 +++++++++++++++++++++++++++++ urchin_compare/version.json | 12 + 10 files changed, 1937 insertions(+) create mode 100644 urchin_compare/+Dev/VersionInfo.m create mode 100644 urchin_compare/.gitignore create mode 100644 urchin_compare/compile_urchin.m create mode 100644 urchin_compare/helpdlg.fig create mode 100644 urchin_compare/helpdlg.m create mode 100644 urchin_compare/settings.json create mode 100644 urchin_compare/toolsdlg.fig create mode 100644 urchin_compare/toolsdlg.m create mode 100644 urchin_compare/urchin_compare.m create mode 100644 urchin_compare/version.json diff --git a/urchin_compare/+Dev/VersionInfo.m b/urchin_compare/+Dev/VersionInfo.m new file mode 100644 index 0000000..2002fa5 --- /dev/null +++ b/urchin_compare/+Dev/VersionInfo.m @@ -0,0 +1,10 @@ +% versionInfo = VersionInfo() +% Return the version info structure +% +% Note: This file is autogenerated by build script DO NOT MODIFY!! + +function versionInfo = VersionInfo() + jsonVer = '{"name":"urchin_compare","majorVersion":2,"minorVersion":0,"branchName":"master","buildNumber":"2020.12.07.07","buildMachine":"bioimage28","commitHash":[" : 15410c6b7251a6890057e04366431f0286b90d70"," : 07f725fe7b1c500a2743e016d119a7b0f059561e"]}'; + + versionInfo = Utils.ParseJSON(jsonVer); +end diff --git a/urchin_compare/.gitignore b/urchin_compare/.gitignore new file mode 100644 index 0000000..4051d2a --- /dev/null +++ b/urchin_compare/.gitignore @@ -0,0 +1,6 @@ +# Ignore matlab data files +*.mat + +# Ignore some image formats +*.jpg +*.nd2 \ No newline at end of file diff --git a/urchin_compare/compile_urchin.m b/urchin_compare/compile_urchin.m new file mode 100644 index 0000000..b1e40b6 --- /dev/null +++ b/urchin_compare/compile_urchin.m @@ -0,0 +1,46 @@ +function compile_urchin() + %% General compiler setup: Deals with version updates and pulls external dependencies + initStruct = Dev.InitCompiler('urchin_compare','2.0'); + if ( isempty(initStruct) ) + % User exited the build due to error or uncommited dependencies. + return; + end + + compileMATLAB('urchin_compare','urchin_compare','', initStruct.javaList, initStruct.toolboxList); +end + +function outputFile = compileMATLAB(projectName, mainscript, outputdir, extrasList, toolboxList) + compileTime = tic(); + + outputFile = [projectName '.exe']; + + if ( ~exist('extrasList','var') ) + extrasList = {}; + end + + extraCommand = ''; + if ( ~isempty(extrasList) ) + extraElems = cellfun(@(x)([' -a ' x]),extrasList, 'UniformOutput',0); + extraCommand = [extraElems{:}]; + end + + if ( ~exist('toolboxList','var') ) + toolboxList = {}; + end + + toolboxAddCommand = ''; + if ( ~isempty(toolboxList) ) + toolboxElems = cellfun(@(x)([' -p "' x '"']), toolboxList, 'UniformOutput',0); + toolboxAddCommand = ['-N' toolboxElems{:}]; + end + + fprintf('\nMATLAB Compiling: %s...\n', outputFile); + result = system(['mcc -v -R -startmsg -m ' mainscript '.m -o ' projectName ' ' toolboxAddCommand extraCommand]); + if ( result ~= 0 ) + error([projectName ': MATLAB compile failed.']); + end + + system(['copy ' projectName '.exe ' fullfile(outputdir,'.')]); + + fprintf('Done (%f sec)\n', toc(compileTime)); +end diff --git a/urchin_compare/helpdlg.fig b/urchin_compare/helpdlg.fig new file mode 100644 index 0000000000000000000000000000000000000000..e48d4f55d39dda373ec42b2bf8b1e20511c2e014 GIT binary patch literal 7021 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 literal 0 HcmV?d00001 diff --git a/urchin_compare/helpdlg.m b/urchin_compare/helpdlg.m new file mode 100644 index 0000000..c58ee28 --- /dev/null +++ b/urchin_compare/helpdlg.m @@ -0,0 +1,86 @@ +function varargout = helpdlg(varargin) +% HELPDLG MATLAB code for helpdlg.fig +% HELPDLG, by itself, creates a new HELPDLG or raises the existing +% singleton*. +% +% H = HELPDLG returns the handle to a new HELPDLG or the handle to +% the existing singleton*. +% +% HELPDLG('CALLBACK',hObject,eventData,handles,...) calls the local +% function named CALLBACK in HELPDLG.M with the given input arguments. +% +% HELPDLG('Property','Value',...) creates a new HELPDLG or raises the +% existing singleton*. Starting from the left, property value pairs are +% applied to the GUI before helpdlg_OpeningFcn gets called. An +% unrecognized property name or invalid value makes property application +% stop. All inputs are passed to helpdlg_OpeningFcn via varargin. +% +% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one +% instance to run (singleton)". +% +% See also: GUIDE, GUIDATA, GUIHANDLES + +% Edit the above text to modify the response to help helpdlg + +% Last Modified by GUIDE v2.5 18-Jun-2019 03:23:18 + +% Begin initialization code - DO NOT EDIT +gui_Singleton = 1; +gui_State = struct('gui_Name', mfilename, ... + 'gui_Singleton', gui_Singleton, ... + 'gui_OpeningFcn', @helpdlg_OpeningFcn, ... + 'gui_OutputFcn', @helpdlg_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 initialization code - DO NOT EDIT + + +% --- Executes just before helpdlg is made visible. +function helpdlg_OpeningFcn(hObject, eventdata, handles, varargin) +% 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 command line arguments to helpdlg (see VARARGIN) + +% Choose default command line output for helpdlg +handles.output = hObject; + +% Update handles structure +guidata(hObject, handles); + +% UIWAIT makes helpdlg wait for user response (see UIRESUME) +% uiwait(handles.help_fig); + + +% --- Outputs from this function are returned to the command line. +function varargout = helpdlg_OutputFcn(hObject, eventdata, handles) +% 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) + +% Get default command line output from handles structure +varargout{1} = handles.output; + + +% --- Executes on key press with focus on help_fig and none of its controls. +function help_fig_KeyPressFcn(hObject, eventdata, handles) +% hObject handle to help_fig (see GCBO) +% eventdata structure with the following fields (see MATLAB.UI.FIGURE) +% Key: name of the key that was pressed, in lower case +% Character: character interpretation of the key(s) that was pressed +% Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed +% handles structure with handles and user data (see GUIDATA) +if ( strcmpi(eventdata.Key,'escape') ) + close(hObject); +end diff --git a/urchin_compare/settings.json b/urchin_compare/settings.json new file mode 100644 index 0000000..0a04ea2 --- /dev/null +++ b/urchin_compare/settings.json @@ -0,0 +1,8 @@ +{ + "imagePath" : "H:\\Smadar\\2020-10-Phallodin_Myo", + "dataPath" : "H:\\Smadar\\2020-10-Phallodin_Myo", + "channelColors" : [ + [0, 1, 0], + [1, 0, 0] + ] +} diff --git a/urchin_compare/toolsdlg.fig b/urchin_compare/toolsdlg.fig new file mode 100644 index 0000000000000000000000000000000000000000..be3cc86a14f3b050d531c93ae21c3d150b0c3cd6 GIT binary patch literal 41989 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 GH#-34!ccAi literal 0 HcmV?d00001 diff --git a/urchin_compare/toolsdlg.m b/urchin_compare/toolsdlg.m new file mode 100644 index 0000000..4c21517 --- /dev/null +++ b/urchin_compare/toolsdlg.m @@ -0,0 +1,537 @@ +function varargout = toolsdlg(varargin) +% TOOLSDLG MATLAB code for tools.fig +% TOOLSDLG, by itself, creates a new TOOLSDLG or raises the existing +% singleton*. +% +% H = TOOLSDLG returns the handle to a new TOOLSDLG or the handle to +% the existing singleton*. +% +% TOOLSDLG('CALLBACK',hObject,eventData,handles,...) calls the local +% function named CALLBACK in TOOLSDLG.M with the given input arguments. +% +% TOOLSDLG('Property','Value',...) creates a new TOOLSDLG or raises the +% existing singleton*. Starting from the left, property value pairs are +% applied to the GUI before toolsdlg_OpeningFcn gets called. An +% unrecognized property name or invalid value makes property application +% stop. All inputs are passed to toolsdlg_OpeningFcn via varargin. +% +% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one +% instance to run (singleton)". +% +% See also: GUIDE, GUIDATA, GUIHANDLES + +% Edit the above text to modify the response to help toolsdlg + +% Last Modified by GUIDE v2.5 01-Dec-2020 18:35:44 + +% Begin initialization code - DO NOT EDIT +gui_Singleton = 1; +gui_State = struct('gui_Name', mfilename, ... + 'gui_Singleton', gui_Singleton, ... + 'gui_OpeningFcn', @toolsdlg_OpeningFcn, ... + 'gui_OutputFcn', @toolsdlg_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 initialization code - DO NOT EDIT + + +% --- Executes just before toolsdlg is made visible. +function toolsdlg_OpeningFcn(hObject, eventdata, handles, varargin) +% 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 command line arguments to toolsdlg (see VARARGIN) + +% Choose default command line output for toolsdlg +handles.output = hObject; + +% Update handles structure +guidata(hObject, handles); + +% UIWAIT makes toolsdlg wait for user response (see UIRESUME) +% uiwait(handles.tools_fig); + + +% --- Outputs from this function are returned to the command line. +function varargout = toolsdlg_OutputFcn(hObject, eventdata, handles) +% 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) + +% Get default command line output from handles structure +varargout{1} = handles.output; + +% Helpers for updating editbox/sliders +function v = clamp(v, minv,maxv) + v = max(minv, min(v, maxv)); + +% --- Executes on slider movement. +function update_editbox(hTxt,hSlider) + val = get(hSlider, 'Value'); + if ( ~isempty(hTxt) ) + set(hTxt, 'String',num2str(val)); + end + +% --- Executes on slider movement. +function update_slider(hTxt,hSlider) + strval = get(hTxt, 'String'); + val = str2double(strval); + if ( ~isempty(hSlider) ) + val = clamp(val, get(hSlider,'Min'),get(hSlider,'Max')); + set(hSlider, 'Value',val); + end + +% --- Executes on slider movement. +function contrast_ch2_Callback(hObject, eventdata, handles) +% hObject handle to contrast_ch2 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'Value') returns position of slider +% get(hObject,'Min') and get(hObject,'Max') to determine range of slider +global UIInfo +hTxt = findobj('Tag','contrast_ch2_edit'); +update_editbox(hTxt,hObject); +UIInfo.updateFcn(); + + +% --- Executes during object creation, after setting all properties. +function contrast_ch2_CreateFcn(hObject, eventdata, handles) +% hObject handle to contrast_ch2 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: slider controls usually have a light gray background. +if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor',[.9 .9 .9]); +end + + +% --- Executes on slider movement. +function bright_ch2_Callback(hObject, eventdata, handles) +% hObject handle to bright_ch2 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'Value') returns position of slider +% get(hObject,'Min') and get(hObject,'Max') to determine range of slider +global UIInfo +hTxt = findobj('Tag','bright_ch2_edit'); +update_editbox(hTxt,hObject); +UIInfo.updateFcn(); + + +% --- Executes during object creation, after setting all properties. +function bright_ch2_CreateFcn(hObject, eventdata, handles) +% hObject handle to bright_ch2 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: slider controls usually have a light gray background. +if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor',[.9 .9 .9]); +end + + +% --- Executes on button press in color_ch2. +function color_ch2_Callback(hObject, eventdata, handles) +% hObject handle to color_ch2 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +global UIInfo +newC = uisetcolor(get(hObject, 'BackgroundColor')); +set(hObject, 'BackgroundColor', newC); +UIInfo.updateFcn(); + + +% --- Executes on button press in color_ch1. +function color_ch1_Callback(hObject, eventdata, handles) +% hObject handle to color_ch1 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +global UIInfo +newC = uisetcolor(get(hObject, 'BackgroundColor')); +set(hObject, 'BackgroundColor', newC); +UIInfo.updateFcn(); + + +% --- Executes on slider movement. +function bright_ch1_Callback(hObject, eventdata, handles) +% hObject handle to bright_ch1 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'Value') returns position of slider +% get(hObject,'Min') and get(hObject,'Max') to determine range of slider +global UIInfo +hTxt = findobj('Tag','bright_ch1_edit'); +update_editbox(hTxt,hObject); +UIInfo.updateFcn(); + + +% --- Executes during object creation, after setting all properties. +function bright_ch1_CreateFcn(hObject, eventdata, handles) +% hObject handle to bright_ch1 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: slider controls usually have a light gray background. +if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor',[.9 .9 .9]); +end + + +% --- Executes on slider movement. +function contrast_ch1_Callback(hObject, eventdata, handles) +% hObject handle to contrast_ch1 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'Value') returns position of slider +% get(hObject,'Min') and get(hObject,'Max') to determine range of slider +global UIInfo +hTxt = findobj('Tag','contrast_ch1_edit'); +update_editbox(hTxt,hObject); +UIInfo.updateFcn(); + + +% --- Executes during object creation, after setting all properties. +function contrast_ch1_CreateFcn(hObject, eventdata, handles) +% hObject handle to contrast_ch1 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: slider controls usually have a light gray background. +if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor',[.9 .9 .9]); +end + + +% --- Executes on button press in show_regions. +function show_regions_Callback(hObject, eventdata, handles) +% hObject handle to show_regions (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hint: get(hObject,'Value') returns toggle state of show_regions +global UIInfo +UIInfo.updateFcn(); + + +% --- Executes on button press in show_ch1px. +function show_ch1px_Callback(hObject, eventdata, handles) +% hObject handle to show_ch1px (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hint: get(hObject,'Value') returns toggle state of show_ch1px +global UIInfo +UIInfo.updateFcn(); + + +% --- Executes on button press in show_ch2px. +function show_ch2px_Callback(hObject, eventdata, handles) +% hObject handle to show_ch2px (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hint: get(hObject,'Value') returns toggle state of show_ch2px +global UIInfo +UIInfo.updateFcn(); + + +% --- Executes on slider movement. +function ch1_thresh_Callback(hObject, eventdata, handles) +% hObject handle to ch1_thresh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'Value') returns position of slider +% get(hObject,'Min') and get(hObject,'Max') to determine range of slider +global UIInfo +hTxt = findobj('Tag','ch1_thresh_edit'); +update_editbox(hTxt,hObject); +UIInfo.updateThresh(); + + +% --- Executes during object creation, after setting all properties. +function ch1_thresh_CreateFcn(hObject, eventdata, handles) +% hObject handle to ch1_thresh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: slider controls usually have a light gray background. +if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor',[.9 .9 .9]); +end + + +% --- Executes on slider movement. +function ch2_thresh_Callback(hObject, eventdata, handles) +% hObject handle to ch2_thresh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'Value') returns position of slider +% get(hObject,'Min') and get(hObject,'Max') to determine range of slider +global UIInfo +hTxt = findobj('Tag','ch2_thresh_edit'); +update_editbox(hTxt,hObject); +UIInfo.updateThresh(); + + +% --- Executes during object creation, after setting all properties. +function ch2_thresh_CreateFcn(hObject, eventdata, handles) +% hObject handle to ch2_thresh (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: slider controls usually have a light gray background. +if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor',[.9 .9 .9]); +end + + +% --- Executes when selected cell(s) is changed in cells_table. +function cells_table_CellSelectionCallback(hObject, eventdata, handles) +% hObject handle to cells_table (see GCBO) +% eventdata structure with the following fields (see MATLAB.UI.CONTROL.TABLE) +% Indices: row and column indices of the cell(s) currently selecteds +% handles structure with handles and user data (see GUIDATA) +global UIInfo + +regionID = -1; +if ( ~isempty(eventdata.Indices) ) + Data = get(hObject, 'Data'); + regionID = Data{eventdata.Indices(1),1}; +end + +UIInfo.updateRegionSelect(regionID); + + +% --- Executes when entered data in editable cell(s) in cells_table. +function cells_table_CellEditCallback(hObject, eventdata, handles) +% hObject handle to cells_table (see GCBO) +% eventdata structure with the following fields (see MATLAB.UI.CONTROL.TABLE) +% Indices: row and column indices of the cell(s) edited +% PreviousData: previous data for the cell(s) edited +% EditData: string(s) entered by the user +% NewData: EditData or its converted form set on the Data property. Empty if Data was not changed +% Error: error string when failed to convert EditData to appropriate value for Data +% handles structure with handles and user data (see GUIDATA) +global UIInfo + +Data = get(hObject, 'Data'); + +editData = eventdata.EditData; +if ( ischar(editData) ) + %% Support empty if space-bar is used + editData = strtrim(editData); +end + +if ( isempty(editData) ) + %% Allow user to set empty data + Data{eventdata.Indices(1),eventdata.Indices(2)} = []; + set(hObject, 'Data',Data); +end +% % User modifiable count variable +% cellID = Data{eventdata.Indices(1),1}; +% newCount = Data{eventdata.Indices(1),eventdata.Indices(2)}; + +% UIInfo.updateCellCount(cellID,newCount); + + +% --- Executes when user attempts to close tools_fig. +function tools_fig_CloseRequestFcn(hObject, eventdata, handles) +% hObject handle to tools_fig (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hint: delete(hObject) closes the figure +global UIInfo +set(hObject, 'Visible','off'); +UIInfo.updateMenu(); + + + +function ch1_thresh_edit_Callback(hObject, eventdata, handles) +% hObject handle to ch1_thresh_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of ch1_thresh_edit as text +% str2double(get(hObject,'String')) returns contents of ch1_thresh_edit as a double +global UIInfo +hSlider = findobj('Tag','ch1_thresh'); +update_slider(hObject,hSlider); +UIInfo.updateThresh(); + + +% --- Executes during object creation, after setting all properties. +function ch1_thresh_edit_CreateFcn(hObject, eventdata, handles) +% hObject handle to ch1_thresh_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end +hSlider = findobj('Tag','ch1_thresh'); +update_editbox(hObject,hSlider); + + + +function ch2_thresh_edit_Callback(hObject, eventdata, handles) +% hObject handle to ch2_thresh_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of ch2_thresh_edit as text +% str2double(get(hObject,'String')) returns contents of ch2_thresh_edit as a double +global UIInfo +hSlider = findobj('Tag','ch2_thresh'); +update_slider(hObject,hSlider); +UIInfo.updateThresh(); + + +% --- Executes during object creation, after setting all properties. +function ch2_thresh_edit_CreateFcn(hObject, eventdata, handles) +% hObject handle to ch2_thresh_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end +hSlider = findobj('Tag','ch2_thresh'); +update_editbox(hObject,hSlider); + + + +function bright_ch2_edit_Callback(hObject, eventdata, handles) +% hObject handle to bright_ch2_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of bright_ch2_edit as text +% str2double(get(hObject,'String')) returns contents of bright_ch2_edit as a double +global UIInfo +hSlider = findobj('Tag','bright_ch2'); +update_slider(hObject,hSlider); +UIInfo.updateFcn(); + + +% --- Executes during object creation, after setting all properties. +function bright_ch2_edit_CreateFcn(hObject, eventdata, handles) +% hObject handle to bright_ch2_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end +hSlider = findobj('Tag','bright_ch2'); +update_editbox(hObject,hSlider); + + + +function contrast_ch2_edit_Callback(hObject, eventdata, handles) +% hObject handle to contrast_ch2_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of contrast_ch2_edit as text +% str2double(get(hObject,'String')) returns contents of contrast_ch2_edit as a double +global UIInfo +hSlider = findobj('Tag','contrast_ch2'); +update_slider(hObject,hSlider); +UIInfo.updateFcn(); + + +% --- Executes during object creation, after setting all properties. +function contrast_ch2_edit_CreateFcn(hObject, eventdata, handles) +% hObject handle to contrast_ch2_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end +hSlider = findobj('Tag','contrast_ch2'); +update_editbox(hObject,hSlider); + + +function bright_ch1_edit_Callback(hObject, eventdata, handles) +% hObject handle to bright_ch1_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of bright_ch1_edit as text +% str2double(get(hObject,'String')) returns contents of bright_ch1_edit as a double +global UIInfo +hSlider = findobj('Tag','bright_ch1'); +update_slider(hObject,hSlider); +UIInfo.updateFcn(); + + +% --- Executes during object creation, after setting all properties. +function bright_ch1_edit_CreateFcn(hObject, eventdata, handles) +% hObject handle to bright_ch1_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end +hSlider = findobj('Tag','bright_ch1'); +update_editbox(hObject,hSlider); + + + +function contrast_ch1_edit_Callback(hObject, eventdata, handles) +% hObject handle to contrast_ch1_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of contrast_ch1_edit as text +% str2double(get(hObject,'String')) returns contents of contrast_ch1_edit as a double +global UIInfo +hSlider = findobj('Tag','contrast_ch1'); +update_slider(hObject,hSlider); +UIInfo.updateFcn(); + + +% --- Executes during object creation, after setting all properties. +function contrast_ch1_edit_CreateFcn(hObject, eventdata, handles) +% hObject handle to contrast_ch1_edit (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles empty - handles not created until after all CreateFcns called + +% Hint: edit controls usually have a white background on Windows. +% See ISPC and COMPUTER. +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end +hSlider = findobj('Tag','contrast_ch1'); +update_editbox(hObject,hSlider); diff --git a/urchin_compare/urchin_compare.m b/urchin_compare/urchin_compare.m new file mode 100644 index 0000000..d38f4ab --- /dev/null +++ b/urchin_compare/urchin_compare.m @@ -0,0 +1,1232 @@ +function urchin_compare() + init_globals(); + load_config(); + + ui_initialize_main(); +end + +function init_globals() + global CONSTANTS UIInfo RegionInfo imC bwCh + + imC = []; + bwCh = []; + + RegionInfo = []; + CONSTANTS = []; + + UIInfo.mainFig = figure(); + UIInfo.toolFig = []; + + reset_ui_fields(); +end + +function reset_ui_fields() + global UIInfo + + UIInfo.pad = zeros(1,2); + UIInfo.padDelta = zeros(1,2); + + UIInfo.mousePt = zeros(1,2); + UIInfo.zoom = 0; + UIInfo.selectedRegion = -1; + + UIInfo.edited = false; + UIInfo.panning = false; + + clf(UIInfo.mainFig); +end + +function imPath = get_image_path(rootDir) + imPath = ''; + + [filename,pathname] = uigetfile(fullfile(rootDir, '*.*'), 'Open image file'); + if ( filename == 0 ) + return; + end + + imPath = fullfile(pathname,filename); +end + +function [im,imD] = fixup_im_channels(im,imD) + chNames = {}; + if ( isfield(imD,'ChannelNames') ) + chNames = imD.ChannelNames; + end + + if ( ~isempty(chNames) ) + keepNames = {'Alexa 488'; 'Cy3.5'}; + sidx = zeros(length(chNames),1); + for i=1:length(keepNames) + bkn = startsWith(chNames, keepNames{i}); + sidx(bkn) = i; + end + + srtCh = zeros(length(keepNames),1); + for i=1:length(keepNames) + srtCh(i) = find(sidx==i,1,'first'); + end + + imD.ChannelNames = chNames(srtCh); + else + srtCh = [1;2]; + end + + imD.NumberOfChannels = 2; + im = im(:,:,:,srtCh,:); +end + +function [im,imD,imPath] = load_image(imPath) + im = []; + + [pathname,filename,fext] = fileparts(imPath); + imD = MicroscopeData.Original.ReadMetadata(pathname,[filename fext]); + if ( isempty(imD) ) + return; + end + + im = MicroscopeData.Original.ReadImages(pathname,[filename fext], [], 'zList',[1]); + if ( isempty(im) ) + return; + end + + [im,imD] = fixup_im_channels(im,imD); +end + +%% ---- Size compat-helper +function sz_dims = size_dims(A, dims) + sz_dims = arrayfun(@(x)(size(A,x)), dims); +end + +%% ---- Config handling ---- +function load_config() + global Config + + Config = struct('imagePath',{''},... + 'dataPath',{''},... + 'channelColors',{[0,1,0; 1,0,0]}); + + % Check for a valid settings file + if ( ~exist('settings.json','file') ) + return; + end + + jsonData = fileread('settings.json'); + settings = jsondecode(jsonData); + + if ( isempty(settings) ) + return; + end + + fields = fieldnames(settings); + for i=1:length(fields) + Config.(fields{i}) = settings.(fields{i}); + end +end + +function save_config() + global Config + + jsonData = Utils.CreateJSON(Config); + fid = fopen('settings.json','wt'); + if ( fid >= 0 ) + fprintf(fid, '%s\n', jsonData); + fclose(fid); + end +end + +function set_datapath(datapath) + global Config + + pathname = fileparts(datapath); + Config.dataPath = pathname; +end + +function set_imagepath(imagepath) + global Config + + pathname = fileparts(imagepath); + Config.imagePath = pathname; +end + + +%% ---- Draw Functions ---- +function draw_image() + global imC UIInfo + + if ( isempty(imC) ) + return; + end + + imR = im_composite_channels(imC, UIInfo.Cmap,UIInfo.Tfn); + + render_image(UIInfo.mainFig, imR); + draw_regions(); +end + +function xor_cmap = color_xor(cmap) + xor_cmap = sum(cmap,1); + while ( any(xor_cmap > 1.0) ) + bgo = (xor_cmap > 1.0); + xor_cmap(bgo) = xor_cmap(bgo) - 1.0; + end +end + +function draw_regions() + global UIInfo RegionInfo + + curAx = get(UIInfo.mainFig, 'CurrentAxes'); + + if ( UIInfo.bShowRegions ) + for i=1:length(RegionInfo) + if ( isempty(RegionInfo(i).id) ) + continue; + end + + [~,uridx] = sortrows(RegionInfo(i).pts); + + drawStyle = '-'; + if ( UIInfo.selectedRegion == i ) + drawStyle = ':'; + end + plot(RegionInfo(i).pts(:,1),RegionInfo(i).pts(:,2), 'w',... + 'LineWidth',2,... + 'LineStyle',drawStyle,... + 'Parent',curAx,... + 'ButtonDownFcn',@(src,evt)(set_region_select(i))); + + text(curAx,... + RegionInfo(i).pts(uridx(end),1)+1,... + RegionInfo(i).pts(uridx(end),2)+1,... + num2str(RegionInfo(i).id),... + 'Color','w',... + 'VerticalAlignment','top'); + end + end + + % Figure out a distinctive overlap color (if all channels on) + bShowCh = [UIInfo.bShowChPx, any(UIInfo.bShowChPx)]; + % NOTE/HACK: color_xor runs across all channels passed in so it's important to start with [0,0,0] for overlap + pxCmap = [UIInfo.Cmap; 0 0 0]; + pxCmap(3,:) = color_xor(pxCmap(bShowCh,:)); + for c=1:3 + if ( ~bShowCh(c) ) + continue; + end + + for i=1:length(RegionInfo) + if ( isempty(RegionInfo(i).id) ) + continue; + end + + if ( isempty(RegionInfo(i).chPts{c}) ) + continue; + end + + plot(RegionInfo(i).chPts{c}(:,1),RegionInfo(i).chPts{c}(:,2), '.',... + 'Color',pxCmap(c,:),... + 'Parent',curAx,... + 'ButtonDownFcn',@(src,evt)(set_region_select(i))); + end + end + + drawnow(); +end + +function render_image(hFig, imRender) + global UIInfo + + %% Compute padding info + imSize = size(imRender); + imPad = pad_image(imRender, UIInfo.pad); + + imLims = [1-UIInfo.pad(2) imSize(2)+UIInfo.pad(2); + 1-UIInfo.pad(1) imSize(1)+UIInfo.pad(1)]; + + %% Setup current image axis and get limits + xl = []; + yl = []; + + curAx = get(hFig, 'CurrentAxes'); + if ( isempty(curAx) ) + curAx = axes('Parent', hFig); + set(hFig, 'CurrentAxes',curAx); + else + %% Get current axis limit sets + xl = xlim(curAx); + yl = ylim(curAx); + + im_xy = (imLims(:,2)-imLims(:,1)); + prevIm_xy = im_xy - 2*[UIInfo.padDelta(2);UIInfo.padDelta(1)]; + + view_xy = [xl(2)-xl(1); yl(2)-yl(1)]; + + ssrd_xy = 0.5 * view_xy .* (im_xy - prevIm_xy) ./ prevIm_xy; + + xl = xl + [-ssrd_xy(1), ssrd_xy(1)]; + yl = yl + [-ssrd_xy(2), ssrd_xy(2)]; + end + + % Reset pad delta + UIInfo.padDelta = zeros(1,2); + + %% render image + hold(curAx, 'off'); + hIm = imagesc(imLims(1,:),imLims(2,:),imPad, 'Parent',curAx, [0 1]); + set(hIm, 'ButtonDownFcn', @click_down_event); + + %% Axis positions + set(curAx, 'Position',[0 0 1 1]); + + %% Setup axis defaults + axis(curAx, 'off'); + axis(curAx, 'fill'); + axis(curAx, 'ij'); + zoom(hFig, 'reset'); + + %% Reset limits + if ( ~isempty(xl) ) + xlim(curAx, xl); + ylim(curAx, yl); + end + + %% Hold for further drawing + hold(curAx, 'all'); +end + + +%% ---- Handle aspect-ratio padding +function imPad = pad_image(im, pad) + imSize = size(im); + imPad = zeros(imSize + 2*[pad, 0]); + + imX = pad(2) + (1:imSize(2)); + imY = pad(1) + (1:imSize(1)); + + imPad(imY,imX,:) = im; +end + +function [pad,finalAR] = compute_pad(hFig, im) + imSize = size(im); + pos = get(hFig, 'Position'); + + fAR = pos(3) / pos(4); + imAR = imSize(2) / imSize(1); + + pad = zeros(1,2); + if ( imAR <= fAR ) + pad(2) = ceil((fAR * imSize(1) - imSize(2)) / 2); + else + pad(1) = ceil((imSize(2) / fAR - imSize(1)) / 2); + end + + finalAR = (imSize(2) + 2*pad(2)) / (imSize(1) + 2*pad(1)); +end + +%% ---- Image rendering functions +function imRender = im_composite_channels(imC, cmap,tfn) + imSize = size_dims(imC, 1:4); + + %% Create normalized images + imNrm = zeros([imSize(1:2), imSize(4)]); + for c=1:imSize(4) + imNrm(:,:,c) = mat2gray(imC(:,:,1,c)); + end + + %% Transform channels + imT = im_apply_tfn(imNrm, tfn); + + % Use a default alpha and normalize at the end + % NOTE: Alpha = 0.1 makes all channels pretty transparent + alpha = 0.1; + %% Composite colors + imRender = zeros([imSize(1:2), 3]); + imTrn = ones([imSize(1:2), 1]); + for c=imSize(4):-1:1 + oppacity = alpha * imT(:,:,c); + + imPremul = oppacity .* repmat(reshape(cmap(c,:),[1,1,3]), [imSize(1:2), 1]); + imRender = (1-oppacity).*imRender + imPremul; + imTrn = imTrn .* (1-oppacity); + end + + imRender = clamp(imRender ./ alpha, 0.0,1.0); +end + +function imT = im_apply_tfn(im,tfn) + alpha = tfn(:,1).'; + beta = tfn(:,2).'; + % gamma = tfn(:,3).'; + + imR = reshape(im, [size(im,1)*size(im,2), size(im,3)]); + imTl = clamp(alpha .* (clamp(imR + beta,0.0,1.0) - 0.5) + 0.5, 0.0, 1.0); +% imTl = clamp(clamp(alpha .* ((imR.^gamma) - 0.5),-0.5,0.5) + 0.5 + beta, 0.0, 1.0); + + imT = reshape(imTl, size(im)); +end + +function outV = clamp(inV, minV, maxV) + outV = min(max(inV, minV), maxV); +end + + +%% ---- UI Init Functions ---- +function ui_initialize_main() + global UIInfo + + set(UIInfo.mainFig,... + 'SizeChangedFcn', @resize_event,... + 'WindowScrollWheelFcn', @scroll_event,... + 'WindowButtonMotionFcn',@move_event,... + 'KeyPressFcn', @key_event,... + 'CloseRequestFcn', @close_event,... + 'Menu', 'none',... + 'ToolBar', 'none',... + 'BusyAction', 'cancel',... + 'Interruptible', 'off',... + 'NumberTitle', 'off',... + 'Name', 'Sea Urchin Calcein Counter'); + + ui_create_menubar(UIInfo.mainFig); +end + +function ui_create_menubar(hFig) + global UIInfo + + fileMenu = uimenu(... + 'Parent', hFig,... + 'Label', 'File',... + 'HandleVisibility', 'callback'); + + toolsMenu = uimenu(... + 'Parent', hFig,... + 'Label', 'Tools',... + 'HandleVisibility', 'callback'); + + helpMenu = uimenu(... + 'Parent', hFig,... + 'Label', 'Help',... + 'HandleVisibility', 'callback',... + 'Callback', @(src,evt)(helpdlg())); + + uimenu(... + 'Parent', fileMenu,... + 'Label', 'Open Image',... + 'HandleVisibility', 'callback', ... + 'Callback', @open_image_event,... + 'Accelerator', 'o'); + + uimenu(... + 'Parent', fileMenu,... + 'Label', 'Save Data',... + 'HandleVisibility', 'callback', ... + 'Callback', @save_data_event,... + 'Accelerator', 's',... + 'Separator', 'on'); + + uimenu(... + 'Parent', fileMenu,... + 'Label', 'Load Data',... + 'HandleVisibility', 'callback',... + 'Callback', @open_data_event,... + 'Accelerator', 'l'); + + showTools = uimenu(... + 'Parent', toolsMenu,... + 'Label', 'Show Tools',... + 'HandleVisibility', 'callback',... + 'Callback', @(src,evt)(ui_toggle_tools()),... + 'Accelerator', 't',... + 'Enable', 'off',... + 'Checked', 'off'); + + UIInfo.handles.showTools = showTools; +end + +function ui_update_title() + global CONSTANTS UIInfo + + datasetName = CONSTANTS.imageData.DatasetName; + + title = datasetName; + if ( is_edited() ) + title = [title ' *']; + end + + set(UIInfo.mainFig, 'NumberTitle','off'); + set(UIInfo.mainFig, 'Name',title); +end + +function ui_create_tooldlg() + global UIInfo + + if ( ~check_valid_handle(UIInfo.toolFig) ) + UIInfo.toolFig = toolsdlg(); + UIInfo.updateMenu = @ui_update_toolsmenu; + UIInfo.updateFcn = @ui_update_fcn; + UIInfo.updateThresh = @ui_update_thresh_fcn; + UIInfo.updateRegionSelect = @set_region_select; + % UIInfo.updateCellCount = @ui_update_cellcount; + end + + ui_setup_toolhandles(); + ui_set_channel_names(); + + ui_update_region_table(); + ui_init_chthresh(); + + ui_update_from_info(); + ui_update_toolsmenu(); +end + +function ui_toggle_tools() + global UIInfo + + if ( check_valid_handle(UIInfo.toolFig) ) + visible = get(UIInfo.toolFig, 'Visible'); + if ( strcmpi(visible,'on') ) + set(UIInfo.toolFig, 'Visible','off'); + else + set(UIInfo.toolFig, 'Visible','on'); + end + else + ui_create_tooldlg(); + end + + ui_update_toolsmenu(); +end + +function ui_update_toolsmenu() + global UIInfo CONSTANTS + + strEn = 'off'; + if ( ~isempty(CONSTANTS) ) + strEn = 'on'; + end + + if ( check_valid_handle(UIInfo.toolFig) ) + strCh = get(UIInfo.toolFig, 'Visible'); + end + + set(UIInfo.handles.showTools, 'Checked',strCh); + set(UIInfo.handles.showTools, 'Enable',strEn); +end + +function bValid = check_valid_handle(chkHandle) + bValid = false; + if ( isempty(chkHandle) ) + return; + end + + if ( ~isvalid(chkHandle) ) + return; + end + + bValid = true; +end + + +%% ---- Tools UI Helpers ---- +function ui_update_fcn() + ui_update_tool_values(); + draw_image(); +end + +function ui_update_tool_values() + ui_load_colors(); + ui_load_display_settings(); + ui_compute_transferfcn(); +end + +function ui_update_thresh_fcn() + ui_update_chthresh(); + + edit_op(@update_region_chbw); + ui_update_region_table(); + draw_image(); +end + +function ui_setup_toolhandles() + global CONSTANTS UIInfo + + UIInfo.tools = []; + UIInfo.tools.hShowCh = findobj(UIInfo.toolFig, 'Tag','show_regions'); + + minChan = min(2,CONSTANTS.imageData.NumberOfChannels); + + UIInfo.tools.hChColor = zeros(1,minChan); + UIInfo.tools.hChBright = zeros(1,minChan); + UIInfo.tools.hChContrast = zeros(1,minChan); + + for c=1:minChan + UIInfo.tools.hChColor(c) = findobj(UIInfo.toolFig, 'Tag',['color_ch' num2str(c)]); + UIInfo.tools.hChBright(c) = findobj(UIInfo.toolFig, 'Tag',['bright_ch' num2str(c)]); + UIInfo.tools.hChContrast(c) = findobj(UIInfo.toolFig, 'Tag',['contrast_ch' num2str(c)]); + + UIInfo.tools.hShowChPx(c) = findobj(UIInfo.toolFig, 'Tag',['show_ch' num2str(c) 'px']); + UIInfo.tools.hChThresh(c) = findobj(UIInfo.toolFig, 'Tag', ['ch' num2str(c) '_thresh']); + end + + UIInfo.tools.hRegionTable = findobj(UIInfo.toolFig, 'Tag','cells_table'); +end + +function ui_set_channel_names() + global CONSTANTS UIInfo + + for c=1:2 + hChPanel = findobj(UIInfo.toolFig, 'Tag',['uipanel_ch' num2str(c)]); + if ( ~isempty(hChPanel) && ~isempty(CONSTANTS.imageData.ChannelNames{c}) ) + set(hChPanel, 'Title',CONSTANTS.imageData.ChannelNames{c}); + end + end +end + +function ui_init_chthresh() + ui_update_chthresh(); + update_bw_ch(); +end + +function ui_set_channel_colors() + global UIInfo Config CONSTANTS + + if ( isfield(CONSTANTS.imageData,'ChannelColors') && ~isempty(CONSTANTS.imageData.ChannelColors) ) + UIInfo.Cmap = CONSTANTS.imageData.ChannelColors; + else + UIInfo.Cmap = Config.channelColors; + end +end + +function ui_reset_display_settings() + global UIInfo + + UIInfo.bShowRegions = true; + UIInfo.bShowChPx = [true, true]; + + UIInfo.ThrScale = [1.0, 1.0]; + + UIInfo.Tfn(1,:) = [1,0,1]; + UIInfo.Tfn(2,:) = [1,0,1]; + + ui_set_channel_colors(); +end + +function ui_update_from_info() + global UIInfo + + %% Setup display settings + set(UIInfo.tools.hShowCh, 'Value',UIInfo.bShowRegions); + for c=1:length(UIInfo.tools.hShowChPx) + set(UIInfo.tools.hShowChPx(c), 'Value',UIInfo.bShowChPx(c)); + end + + %% Setup colors + for c=1:size(UIInfo.Cmap,1) + set(UIInfo.tools.hChColor(c), 'BackgroundColor',UIInfo.Cmap(c,:)); + end + + %% Setup transfer functions + for c=1:size(UIInfo.Tfn,1) + alpha = UIInfo.Tfn(c,1); + beta = UIInfo.Tfn(c,2); + + vBr = beta; + vCon = 1-2.^(-alpha); + + set(UIInfo.tools.hChBright(c), 'Value',vBr); + set(UIInfo.tools.hChContrast(c), 'Value',vCon); + end + + %% Setup threshold + for c=1:length(UIInfo.tools.hChThresh) + tSc = UIInfo.ThrScale(c); + vCt = 1-2.^(-tSc); + set(UIInfo.tools.hChThresh(c), 'Value',vCt); + end +end + +function ui_load_display_settings() + global UIInfo + + UIInfo.bShowRegions = (get(UIInfo.tools.hShowCh, 'Value') > 0.0); + for c=1:length(UIInfo.tools.hShowChPx) + UIInfo.bShowChPx(c) = (get(UIInfo.tools.hShowChPx(c), 'Value') > 0.0); + end +end + +function ui_load_colors() + global UIInfo Config + cmap = [1,0,0; 0,1,0]; + + for c=1:length(UIInfo.tools.hChColor) + cmap(c,:) = get(UIInfo.tools.hChColor(c), 'BackgroundColor'); + end + + UIInfo.Cmap = cmap; + Config.channelColors = cmap; +end + +function ui_compute_transferfcn() + global UIInfo + gamma = 1.2; + tfn = [1,0,gamma;1,0,gamma]; + + for c=1:length(UIInfo.tools.hChBright) + vBr = get(UIInfo.tools.hChBright(c), 'Value'); + vCon = get(UIInfo.tools.hChContrast(c), 'Value'); + + alpha = -log2(1-vCon); + beta = vBr; + + tfn(c,:) = [alpha,beta,1]; + end + + UIInfo.Tfn = tfn; +end + +function ui_update_chthresh() + global UIInfo + + thrScale = zeros(1,2); + for c=1:length(UIInfo.tools.hChThresh) + tVal = get(UIInfo.tools.hChThresh(c), 'Value'); + thrScale(c) = -log2(1-tVal); + end + + UIInfo.ThrScale = thrScale; +end + + +%% ---- Partial region (drawing) handling ---- +function update_cell_edge(point_xy) + global PartialCell + + updateLine = PartialCell.lines(end); + set(updateLine, 'XData', [PartialCell.pts(end,1) point_xy(1)]); + set(updateLine, 'YData', [PartialCell.pts(end,2) point_xy(2)]); +end + +function start_cell(curAx, point_xy) + global PartialCell + + PartialCell = []; + PartialCell.pts = point_xy; + + newLine = line([PartialCell.pts(end,1) point_xy(1)], [PartialCell.pts(end,2) point_xy(2)], 'Parent',curAx, 'color','w'); + PartialCell.lines = newLine; +end + +function chk_next_edge(curAx, point_xy) + global PartialCell + + if ( isempty(PartialCell) ) + return; + end + + if ( sum((PartialCell.pts(end,:) - point_xy).^2,1) < 0.6 ) + return; + end + + next_cell_edge(curAx, point_xy); +end + +function next_cell_edge(curAx, point_xy) + global PartialCell + + if ( isempty(PartialCell) ) + return; + end + + PartialCell.pts = [PartialCell.pts; point_xy]; + + newLine = line([PartialCell.pts(end,1) point_xy(1)], [PartialCell.pts(end,2) point_xy(2)], 'Parent',curAx, 'color','w'); + PartialCell.lines = [PartialCell.lines; newLine]; +end + +function delete_partial_cell() + global PartialCell + + if ( ~isempty(PartialCell) ) + for i=1:length(PartialCell.lines) + delete(PartialCell.lines(i)); + end + end + + PartialCell = []; +end + + +%% ---- Region handling ---- +function ui_update_region_table() + global RegionInfo UIInfo + + data = {}; + if ( isempty(RegionInfo) ) + set(UIInfo.tools.hRegionTable, 'Data',data); + else + bValidRegions = arrayfun(@(x)(~isempty(x.id)), RegionInfo); + validRegions = RegionInfo(bValidRegions); + + % Channel counts 1x3 array: [ch1Count,ch2Count,overlapCount] + % NOTE: The channel 1/2 counts are only the disjoint non-overlapping pixels so we add 3 to both + chCounts = arrayfun(@(x)([x.chCount(1) x.chCount(2) 0] + x.chCount(3)), validRegions, 'UniformOutput',false); + chCounts = vertcat(chCounts{:}); + + data = cell(length(validRegions),5); + [data{:,1}] = deal(validRegions.id); + [data{:,2}] = deal(validRegions.area); + data(:,3) = num2cell(chCounts(:,1)); + data(:,4) = num2cell(chCounts(:,2)); + data(:,5) = num2cell(chCounts(:,3)); + + set(UIInfo.tools.hRegionTable, 'Data',data); + end +end + +function update_region_chpoints(regionIDs) + global RegionInfo bwCh + + %% Get above-threshold points for each region (handle overlap as well) + pts = []; + chansz = zeros(1,3); + bOverlap = all(bwCh,3); + % These are disjoint (non-overlapping points) + for ch=1:size(bwCh,3) + [r,c] = find(bwCh(:,:,ch) & ~bOverlap); + + pts = [pts; c,r]; + chansz(ch) = size(r,1); + end + % Handle overlap points + [ro,co] = find(bOverlap); + pts = [pts; co,ro]; + chansz(3) = size(ro,1); + % Starts for channel/overlap points + startidx = [0,cumsum(chansz)]; + % Make a bool map for point sets + bChPx = false(sum(chansz),3); + for i=1:3 + bChPx(startidx(i)+(1:chansz(i)),i) = true; + end + + %% Compute counts and channel points for all valid regions in region list + for i=1:length(regionIDs) + idx = regionIDs(i); + if ( isempty(RegionInfo(idx).id) ) + continue; + end + + bInR = inpolygon(pts(:,1),pts(:,2), RegionInfo(idx).pts(:,1),RegionInfo(idx).pts(:,2)); + RegionInfo(idx).chCount = zeros(1,3); + for ch=1:3 + bch = bInR & bChPx(:,ch); + chPts = pts(bch,:); + + RegionInfo(idx).chPts{ch} = chPts; + RegionInfo(idx).chCount(ch) = size(chPts,1); + end + end +end + +function update_region_chbw() + global RegionInfo + + update_bw_ch(); + update_region_chpoints(1:length(RegionInfo)); +end + +function update_bw_ch() + global UIInfo imC bwCh + + bwCh = false(size_dims(imC,[1,2,4])); + for c=1:size(imC,4) + imN = mat2gray(imC(:,:,1,c)); + mt = multithresh(imN(:),2); + thresh = UIInfo.ThrScale(c) * mt(2); + + bwCh(:,:,c) = (imN >= thresh); + end +end + +function create_region(partialRegion) + global RegionInfo + + if ( isempty(partialRegion) ) + return; + end + + newID = 1; + if ( ~isempty(RegionInfo) ) + newID = size(RegionInfo,1) + 1; + end + + newRegion = make_empty_cell(); + newRegion.id = newID; + newRegion.pts = [partialRegion.pts; partialRegion.pts(1,:)]; + newRegion.area = polyarea(newRegion.pts(:,1),newRegion.pts(:,2)); + + RegionInfo = [RegionInfo; newRegion]; + update_region_chpoints(newID); + + ui_update_region_table(); +end + +function delete_region(cellID) + global RegionInfo + + RegionInfo(cellID) = make_empty_cell(); +end + +function cellStruct = make_empty_cell() + cellStruct = struct('id',{[]}, 'pts',{[]}, 'area',{[]}, 'chPts',{[]},'chCount',{[]}, 'count',{[]}); +end + +function regionID = check_region_select(point_xy) + global RegionInfo + + bValidRegions = arrayfun(@(x)(~isempty(x.id)), RegionInfo); + validRegions = RegionInfo(bValidRegions); + + regionID = -1; + for i=1:length(validRegions) + [bIn,bOn] = inpolygon(point_xy(1),point_xy(2), validRegions(i).pts(:,1),validRegions(i).pts(:,2)); + if ( any(bIn | bOn) ) + regionID = validRegions(i).id; + return + end + end +end + +%% ---- Editor support ---- +function edit_op(editfcn, varargin) + editfcn(varargin{:}); + set_edited(true); +end + +function bEdited = is_edited() + global UIInfo + bEdited = UIInfo.edited; +end + +function set_edited(bEdited) + global UIInfo + + UIInfo.edited = bEdited; + ui_update_title(); +end + + +%% ---- Menu Events ---- +function open_image_event(hSrc,evt) + global CONSTANTS Config imC + + chk_const = []; + if ( ~check_continue_unsaved() ) + return; + end + + imPath = get_image_path(Config.imagePath); + if ( isempty(imPath) ) + return; + end + + [imC,chk_const.imageData] = load_image(imPath); + if ( isempty(imC) ) + msgbox('Unable to read image data from file', 'Error reading image', 'warn'); + return; + end + + chk_const.imagePath = imPath; + chk_const.dataPath = ''; + + CONSTANTS = chk_const; + + set_imagepath(imPath); + set_datapath(imPath); + + clear_data(); + reset_ui_fields(); + + ui_update_title(); + ui_reset_display_settings(); + ui_create_tooldlg(); + + resize_padding(); + draw_image(); +end + +function open_data_event(hSrc,evt) + global CONSTANTS Config + + if ( ~check_continue_unsaved() ) + return; + end + + [filename,pathname] = uigetfile(fullfile(Config.dataPath,'*.mat')); + if ( filename == 0 ) + return; + end + + datapath = fullfile(pathname,filename); + + open_data(datapath) + CONSTANTS.dataPath = datapath; + + ui_create_tooldlg(); + draw_image(); +end + +function save_data_event(hSrc,evt) + global CONSTANTS Config + + if ( isempty(CONSTANTS) ) + return; + end + + if ( isempty(CONSTANTS.dataPath) ) + [filename,pathname] = uiputfile(fullfile(Config.dataPath,'*.mat')); + if ( filename == 0 ) + return; + end + + CONSTANTS.dataPath = fullfile(pathname,filename); + end + + save_data(CONSTANTS.dataPath); +end + + +function bContinue = check_continue_unsaved() + bContinue = true; + if ( is_edited() ) + bContinue = unsaved_verify(); + end +end + +function bContinue = unsaved_verify() + userSel = questdlg('You have unsaved data, are you sure you wish to continue without saving?','Unsaved Data','Continue','Cancel','Cancel'); + bContinue = ~strcmpi(userSel,'Cancel'); +end + +%% ---- Data handling ---- +function clear_data() + global RegionInfo + + RegionInfo = []; +end + +function open_data(datapath) + global CONSTANTS RegionInfo UIInfo imC + + s = load(datapath); + CONSTANTS = s.CONSTANTS; + RegionInfo = s.RegionInfo; + + imC = s.CONSTANTS.im; + + %% Update from ui after load + fields = fieldnames(s.displayInfo); + for i=1:length(fields) + UIInfo.(fields{i}) = s.displayInfo.(fields{i}); + end + + set_edited(false); + set_datapath(datapath); +end + +function save_data(datapath) + global CONSTANTS RegionInfo UIInfo imC + + CONSTANTS.im = imC; + displayInfo = struct('Tfn',{UIInfo.Tfn}, 'Cmap',{UIInfo.Cmap},... + 'ThrScale',{UIInfo.ThrScale},... + 'bShowRegions',{UIInfo.bShowRegions},... + 'bShowChPx',{UIInfo.bShowChPx}); + + save(datapath, 'CONSTANTS','RegionInfo','displayInfo'); + + set_edited(false); + set_datapath(datapath); +end + + +%% ---- UI Events ---- +function click_down_event(hSrc,evt) + global UIInfo PartialCell + curAx = get(UIInfo.mainFig, 'CurrentAxes'); + currentPoint = get(curAx, 'CurrentPoint'); + point_xy = currentPoint(1,1:2); + + selectType = get(UIInfo.mainFig, 'SelectionType'); + cellID = check_region_select(point_xy); + + set_region_select(cellID); + + if ( isempty(PartialCell) && strcmpi(selectType,'normal') && (cellID < 0) ) + start_cell(curAx, point_xy); + set(UIInfo.mainFig, 'WindowButtonUpFcn',@click_up_event); + elseif ( strcmpi(selectType,'alt') ) + UIInfo.panning = true; + set(UIInfo.mainFig, 'WindowButtonUpFcn',@click_up_event); + end +end + +function click_up_event(hSrc,evt) + global UIInfo PartialCell + + UIInfo.panning = false; + set(UIInfo.mainFig, 'WindowButtonUpFcn',''); + + if ( ~isempty(PartialCell) ) + %% Don't create a cell if it's only a local click + if ( size(PartialCell.pts,1) > 2 ) + edit_op(@create_region, PartialCell); + end + + delete_partial_cell(); + draw_image(); + end +end + +function set_region_select(regionID) + global UIInfo + + if ( UIInfo.selectedRegion ~= regionID ) + UIInfo.selectedRegion = regionID; + draw_image(); + end +end + +function move_event(hSrc,evt) + global UIInfo PartialCell + + curAx = get(hSrc, 'CurrentAxes'); + if ( UIInfo.panning ) + stable_mouse_xlat(curAx); + end + + if ( ~isempty(curAx) ) + curPt = get(curAx, 'CurrentPoint'); + UIInfo.mousePt = curPt(1,1:2); + end + + if ( ~isempty(PartialCell) ) + update_cell_edge(UIInfo.mousePt); + chk_next_edge(curAx,UIInfo.mousePt); + end +end + +function key_event(hSrc,evt) + global UIInfo + + if ( strcmpi(evt.Key,'escape') ) + delete_partial_cell(); + set(UIInfo.mainFig, 'WindowButtonUpFcn',''); + elseif ( strcmpi(evt.Key,'backspace') || strcmpi(evt.Key,'delete') ) + if ( UIInfo.selectedRegion > 0 ) + edit_op(@delete_region, UIInfo.selectedRegion) + + UIInfo.selectedRegion = -1; + ui_update_region_table(); + draw_image(); + end + end +end + +function scroll_event(hSrc,evt) + global UIInfo + + zBase = 1.4; + + curAx = get(UIInfo.mainFig, 'CurrentAxes'); + if ( isempty(curAx) ) + return; + end + + currentPoint = get(curAx, 'CurrentPoint'); + point_xy = currentPoint(1,1:2); + + wheelDelta = -evt.VerticalScrollCount; + newZoom = clamp(wheelDelta + UIInfo.zoom, 0, 10); + zoomDelta = newZoom - UIInfo.zoom; + + if ( abs(zoomDelta) > 0 ) + xl = xlim(curAx); + yl = ylim(curAx); + + UIInfo.zoom = UIInfo.zoom + zoomDelta; + zoomFactor = zBase ^ zoomDelta; + + lims_xy = [xl.', yl.']; + zoomlims_xy = compute_smooth_zoom(zoomFactor, lims_xy, point_xy); + + xlim(curAx, zoomlims_xy(:,1)); + ylim(curAx, zoomlims_xy(:,2)); + elseif ( wheelDelta < 0 ) + UIInfo.zoom = 0; + zoom(curAx, 'out') + end +end + +function zm_lims_xy = compute_smooth_zoom(zoomFactor, lims_xy, point_xy) + %% Compute zoomed xy-limits such that point_xy is fixed (doesn't move) + % NOTE: lims_xy = [xmin ymin + % xmax ymax] + + loc_xy = point_xy - lims_xy(1,:); + vsz_xy = lims_xy(2,:) - lims_xy(1,:); + + delta_xy = loc_xy - (loc_xy / zoomFactor); + zoomsz_xy = vsz_xy / zoomFactor; + + zm_lims_xy = [lims_xy(1,:); lims_xy(1,:) + zoomsz_xy] + delta_xy; +end + +function stable_mouse_xlat(curAx) + global UIInfo + + xl = xlim(curAx); + yl = ylim(curAx); + + currentPoint = get(curAx, 'CurrentPoint'); + point_xy = currentPoint(1,1:2); + + delta_xy = UIInfo.mousePt - point_xy; + xl = xl + delta_xy(1); + yl = yl + delta_xy(2); + + xlim(curAx, xl); + ylim(curAx, yl); +end + +function resize_padding() + global UIInfo imC + + if ( isempty(imC) ) + return; + end + + padding = compute_pad(UIInfo.mainFig, imC); + + UIInfo.padDelta = padding - UIInfo.pad; + UIInfo.pad = padding; +end + +function resize_event(hFig,evt) + resize_padding(); + draw_image(); +end + +function close_event(hFig,evt) + global UIInfo + + if ( ~check_continue_unsaved() ) + return; + end + + save_config(); + + if ( check_valid_handle(UIInfo.toolFig) ) + delete(UIInfo.toolFig); + end + + delete(hFig); +end diff --git a/urchin_compare/version.json b/urchin_compare/version.json new file mode 100644 index 0000000..ff8f7bf --- /dev/null +++ b/urchin_compare/version.json @@ -0,0 +1,12 @@ +{ + "name" : "urchin_compare", + "majorVersion" : 2, + "minorVersion" : 0, + "branchName" : "master", + "buildNumber" : "2020.12.07.07", + "buildMachine" : "bioimage28", + "commitHash" : [ + " : 15410c6b7251a6890057e04366431f0286b90d70", + " : 07f725fe7b1c500a2743e016d119a7b0f059561e" + ] +} -- GitLab