Skip to content

Commit

Permalink
Add two new features:
Browse files Browse the repository at this point in the history
1. One point high resolution global registration. More detail can be found in issue 80 #80

2. Refine global registration during study. More detail can be found in issue 81 #81
  • Loading branch information
qigongFDA committed Sep 7, 2018
1 parent 8a63953 commit 165ab83
Show file tree
Hide file tree
Showing 22 changed files with 250 additions and 51 deletions.
1 change: 1 addition & 0 deletions src/Administrator_Input_Screen.m
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@ function ModeSelectionPopUpMenu_Callback(hObject, eventdata, handles) %#ok<DEFNU
set(hObject_configure_camera, ...
'Enable', 'on', ...
'String', 'Configure Camera');
handles.myData.refineRegistration = 0;
handles.myData.stage = stage_get_pos(handles.myData.stage); %#ok<NASGU>
if handles.myData.stage.Pos == 0
return
Expand Down
Binary file modified src/GUI.fig
Binary file not shown.
155 changes: 125 additions & 30 deletions src/GUI.m
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,11 @@ function Initiate_GUI_Elements(handles)
'BackgroundColor',myData.settings.BG_color,...
'ForegroundColor',myData.settings.FG_color,...
'Visible', 'off');
set(handles.Refine_Register_Button,...
'FontSize', myData.settings.FontSize,...
'BackgroundColor',myData.settings.BG_color,...
'ForegroundColor',myData.settings.FG_color,...
'Visible', 'off');
set(handles.videobutton,...
'FontSize', myData.settings.FontSize,...
'BackgroundColor',myData.settings.BG_color,...
Expand Down Expand Up @@ -483,36 +488,47 @@ function NextButtonPressed(hObj, eventdata, handles) %#ok<DEFNU>
myData=handles.myData;
set(handles.NextButton, 'Enable', 'off');
set(handles.Backbutton, 'Enable', 'on');
st = dbstack;

% Close out current task and record duration for all task except refine
% reigstration
if myData.refineRegistration == 0
taskinfo = myData.tasks_out{myData.iter};
handles.myData.EndTime = clock;
taskinfo.duration = etime(handles.myData.EndTime, handles.myData.StartTime)+taskinfo.duration;
handles.myData.tasks_out{handles.myData.iter} = taskinfo;
guidata(handles.GUI, handles);
% exort output file
if ~strcmp(st(2).name,'Backbutton_Callback')

% Close out current task and record duration
taskinfo = myData.tasks_out{myData.iter};
handles.myData.EndTime = clock;
taskinfo.duration = etime(handles.myData.EndTime, handles.myData.StartTime)+taskinfo.duration;
handles.myData.tasks_out{handles.myData.iter} = taskinfo;
guidata(handles.GUI, handles);
taskinfo.calling_function = st(1).name;
handles.myData.taskinfo = taskinfo;
guidata(handles.GUI, handles);
taskinfo.task_handle(handles.GUI);
handles = guidata(handles.GUI);
exportOutput(handles.GUI);
handles = guidata(handles.GUI);

st = dbstack;
% exort output file
if ~strcmp(st(2).name,'Backbutton_Callback')

taskinfo.calling_function = st(1).name;
handles.myData.taskinfo = taskinfo;
guidata(handles.GUI, handles);
taskinfo.task_handle(handles.GUI);
handles = guidata(handles.GUI);
exportOutput(handles.GUI);
handles = guidata(handles.GUI);

end
% If the completed task was a 'finish' task, then return
switch taskinfo.id
case 'finish'

close all force
return

end
end
% If the completed task was a 'finish' task, then return
switch taskinfo.id
case 'finish'

close all force
return

end

else
handles.myData.refineRegistration = 0;
taskinfo = myData.taskinfo;
taskinfo.calling_function = st(1).name;
handles.myData.taskinfo = taskinfo;
guidata(handles.GUI, handles);
taskinfo.task_handle(handles.GUI);
handles = guidata(handles.GUI);
end

% Begin the next task
handles.myData.iter = handles.myData.iter+1;
guidata(handles.GUI, handles);
Expand Down Expand Up @@ -567,8 +583,12 @@ function NextButtonPressed(hObj, eventdata, handles) %#ok<DEFNU>
% offset_stage was determined during stage allignment
% it compensates for any misalignment between the eyepiece
% cener and the reticle center in stage coordinates
offset = int64(myData.settings.offset_stage);
stage_new = stage_new' - offset;

% eyepiece offset
offset_stage = int64(myData.settings.offset_stage);
% registration refine offset
offset_reg_refine = int64(myData.settings.offset_reg_refine{taskinfo.slot});
stage_new = stage_new' - offset_stage + offset_reg_refine;
end
taskinfo.stage_x = stage_new(1);
taskinfo.stage_y = stage_new(2);
Expand Down Expand Up @@ -787,10 +807,12 @@ function ResetViewButtonPressed(hObj, eventdata, handles) %#ok<DEFNU>
set(handles.NextButton,'enable','off');
set(handles.Fast_Register_Button,'enable','off');
set(handles.Best_Register_Button,'enable','off');
set(handles.Refine_Register_Button,'enable','off');
handles.myData.stage = stage_move(handles.myData.stage,target_pos,handles.myData.stage.handle);
set(handles.NextButton,'enable',currentNextStatus);
set(handles.Fast_Register_Button,'enable','on');
set(handles.Best_Register_Button,'enable','on');
set(handles.Refine_Register_Button,'enable','on');

end

Expand Down Expand Up @@ -1275,4 +1297,77 @@ function exportOutput(hObj)
catch ME
error_show(ME)
end
end
end


% --- Executes on button press in Refine_Register_Button.
function Refine_Register_Button_Callback(hObject, eventdata, handles)
% hObject handle to Refine_Register_Button (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)

myData=handles.myData;
% clean current task elements
taskinfo = myData.taskinfo;
st = dbstack;
taskinfo.calling_function = st(1).name;
handles.myData.taskinfo = taskinfo;
guidata(handles.GUI, handles);
taskinfo.task_handle(handles.GUI);
handles = guidata(handles.GUI);
myData=handles.myData;

% only keep slot ID and create new taskinfo
taskinfo = myData.tasks_out{myData.iter};
slot = taskinfo.slot;
taskinfo = struct;
taskinfo.slot = slot;
taskinfo.calling_function = st(1).name;
taskinfo.rotateback = 0;
taskinfo.task = 'refine registration';
taskinfo.task_handle = str2func('@task_refine_registration');
taskinfo.text = 'Refine registration for this slide';
taskinfo.highMag = 1;
myData.taskinfo = taskinfo;
myData.refineRegistration = 1;
handles.myData = myData;
guidata(handles.GUI, handles);

% load stage data for this slide
wsi_info = myData.wsi_files{taskinfo.slot};
WSIfile=wsi_info.fullname;
temp = textscan(wsi_info.fullname, '%s %s', 'delimiter', '.');
stagedata_file = [char(temp{1}),'.mat'];
load(stagedata_file)
% get WSI and stage position for the first anchor
WSIanchor1 = stagedata.wsi_positions(1,:);
Stageanchor1 = stagedata.stage_positions(1,:);

% extract high resolution WSI anchor
highMagName = [myData.registration_images_dir, num2str(taskinfo.slot), 'HighRes.tif'];
Left = WSIanchor1(1)-400;
Top = WSIanchor1(2)-400;
success = ExtractROI_BIO(wsi_info, WSIfile, highMagName,...
Left, Top, 800, 800,...
800, 800,...
handles.myData.settings.RotateWSI,...
wsi_info.rgb_lut);
taskinfo.highMagName = highMagName;
taskinfo.ROIname = highMagName; % default is high Mag image
taskinfo.Stageanchor1 = Stageanchor1;

% use golbal registration first achor high resolution image as low resolution anchor
lowMagName = [myData.registration_images_dir,'hres_s', num2str(taskinfo.slot), 'p1_thumb.tif'];
taskinfo.lowMagName = lowMagName;

myData.taskinfo = taskinfo;
handles.myData = myData;
guidata(handles.GUI, handles);

% move stage to the anchor
myData.stage = stage_move(myData.stage,Stageanchor1, myData.stage.handle);

% get into refine registration task
taskinfo.task_handle(handles.GUI);
handles = guidata(handles.GUI);
end
Binary file modified src/Stage_Allighment.fig
Binary file not shown.
96 changes: 91 additions & 5 deletions src/Stage_Allighment.m
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ function Stage_Allighment_OpeningFcn(hObject, eventdata, handles, varargin) %#ok
current.cam_extract_w = 0;
current.cam_extract_h = 0;

% Initialize offset_stage_refine
settings.offset_reg_refine{slot_i} = [0,0];

handles.output = hObject;
current.load_stage_data = zeros(1,3);
handles.current = current;
Expand Down Expand Up @@ -791,12 +794,12 @@ function take_stage1_Callback(hObject, eventdata, handles) %#ok<DEFNU>
if handles.current.load_stage_data(1) == 1
display('automatically navigate to position 1')
handles.myData.stage=stage_move(handles.myData.stage,handles.myData.stagedata.stage_positions(1,:));
handles.myData.stagedata.oldStagePosition = handles.myData.stagedata.stage_positions(1,:);
set(handles.take_stage1,'String','Take Stage Position 1');
handles.current.load_stage_data(1) = 2;
guidata(handles.Stage_Allighment,handles);
return
end

set(handles.take_stage1,'Enable','off');
take_stage(hObject, eventdata, handles);
handles = guidata(handles.Stage_Allighment);
Expand All @@ -812,7 +815,9 @@ function take_stage1_Callback(hObject, eventdata, handles) %#ok<DEFNU>
set(handles.current.thumb_image_handle,...
'HitTest','on',...
'ButtonDownFcn', {@thumb_image_ButtonDownFcn,handles});

if handles.current.reg_flag == 1
set(handles.onePointReg,'Enable','on');
end
guidata(handles.Stage_Allighment,handles);

catch ME
Expand Down Expand Up @@ -937,6 +942,7 @@ function take_wsi1_Callback(hObject, eventdata, handles) %#ok<DEFNU>

handles.myData.stagedata.wsi_positions(1,1) = handles.current.roi_x0;
handles.myData.stagedata.wsi_positions(1,2) = handles.current.roi_y0;
handles.myData.stagedata.oldWSIPosition = handles.myData.stagedata.wsi_positions(1,:);
set(handles.wsi_1x,'String',handles.current.roi_x0);
set(handles.wsi_1y,'String',handles.current.roi_y0);

Expand Down Expand Up @@ -1076,8 +1082,88 @@ function take_wsi3_Callback(hObject, eventdata, handles) %#ok<DEFNU>

end

%% One point registration
% --- Executes on button press in onePointReg.
function onePointReg_Callback(hObject, eventdata, handles)
% hObject handle to onePointReg (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
try
if handles.take_wsi_flag==0
desc = 'Please click on the WSI at the location corresponding to the stage position.';
h_errordlg = errordlg(desc,'Take WSI Position 1','modal'); %#ok<NASGU>
return;
end


set(handles.onePointReg,'Enable','off');
set(handles.current.thumb_image_handle,'HitTest','off');
Register_ROI(handles);
handles = guidata(handles.Stage_Allighment);

if handles.current.registration_good==0
% Refresh the image
handles.current.thumb_image_handle = ...
image(handles.current.thumb_image,'Parent',handles.thumb_axes);
axis(handles.thumb_axes,'image');
set(handles.current.thumb_image_handle,'HitTest','off');

% Reset state to repeat registration
handles.take_wsi_flag = 0;
set(handles.take_stage1,'Enable','on');
set(handles.onePointReg,'Enable','off');

guidata(handles.Stage_Allighment,handles);
return;
end
% calculate WSI shift
handles.myData.stagedata.wsi_positions(1,1) = handles.current.roi_x0;
handles.myData.stagedata.wsi_positions(1,2) = handles.current.roi_y0;
WSI_x_dif = handles.myData.stagedata.wsi_positions(1,1) - handles.myData.stagedata.oldWSIPosition(1,1);
WSI_y_dif = handles.myData.stagedata.wsi_positions(1,2) - handles.myData.stagedata.oldWSIPosition(1,2);
% calculate stage shift
stage_x_dif = handles.myData.stagedata.stage_positions(1,1) - handles.myData.stagedata.oldStagePosition(1,1);
stage_y_dif = handles.myData.stagedata.stage_positions(1,2) - handles.myData.stagedata.oldStagePosition(1,2);
% shift WSI second and third points postitons
handles.myData.stagedata.wsi_positions(2,1) = handles.myData.stagedata.wsi_positions(2,1) + WSI_x_dif;
handles.myData.stagedata.wsi_positions(2,2) = handles.myData.stagedata.wsi_positions(2,2) + WSI_y_dif;
handles.myData.stagedata.wsi_positions(3,1) = handles.myData.stagedata.wsi_positions(3,1) + WSI_x_dif;
handles.myData.stagedata.wsi_positions(3,2) = handles.myData.stagedata.wsi_positions(3,2) + WSI_y_dif;
% shift stage second and third points positions
handles.myData.stagedata.stage_positions(2,1) = handles.myData.stagedata.stage_positions(2,1) + stage_x_dif;
handles.myData.stagedata.stage_positions(2,2) = handles.myData.stagedata.stage_positions(2,2) + stage_y_dif;
handles.myData.stagedata.stage_positions(3,1) = handles.myData.stagedata.stage_positions(3,1) + stage_x_dif;
handles.myData.stagedata.stage_positions(3,2) = handles.myData.stagedata.stage_positions(3,2) + stage_y_dif;
stagedata = handles.myData.stagedata;
% update GUI
set(handles.wsi_1x,'String',handles.current.roi_x0);
set(handles.wsi_1y,'String',handles.current.roi_y0);
set(handles.wsi_2x,'String',handles.myData.stagedata.wsi_positions(2,1));
set(handles.wsi_2y,'String',handles.myData.stagedata.wsi_positions(2,2));
set(handles.wsi_3x,'String',handles.myData.stagedata.wsi_positions(3,1));
set(handles.wsi_3y,'String',handles.myData.stagedata.wsi_positions(3,2));
% Save the current stagedata
save(handles.myData.stagedata.stagedata_file,'stagedata');

% Prepare for the next step
% set(handles.refine_registration,'Enable','on');


% Report success to Admin_Input
handles_old = guidata(handles.Administrator_Input_Screen);
handles_old.current.success(handles.current.slot_i) = 1;
handles_old.myData = handles.myData;
guidata(handles.Administrator_Input_Screen,handles_old);
% Close the image preview figure
close(handles.cam_figure)
delete(handles.cam)

close(handles.Stage_Allighment);
return

catch ME
error_show(ME)
end
end


%% -------- Abort button callback
Expand Down Expand Up @@ -1371,7 +1457,7 @@ function adjust_camera_color(handles)
'Style', 'pushbutton',...
'Units', 'characters',...
'Position', position,...
'String', 'Feature Centered in Eyepiece',...
'String', 'Adjust color',...
'Callback', @adjustColor_callback);
adjusting_color(handles.cam);
catch ME
Expand Down Expand Up @@ -1434,4 +1520,4 @@ function adjusting_color(cam)
close(waitingBar);
end
end
end
end
3 changes: 2 additions & 1 deletion src/tasks/task_checkMof4.m
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ function task_checkMof4(hObj)

case {'NextButtonPressed', ...
'PauseButtonPressed',...
'Backbutton_Callback'} % Clean up the task elements
'Backbutton_Callback',...
'Refine_Register_Button_Callback'} % Clean up the task elements

% Hide image and management buttons
taskmgt_default(handles, 'off');
Expand Down
3 changes: 2 additions & 1 deletion src/tasks/task_count.m
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ function task_count(hObj)

case {'NextButtonPressed', ...
'PauseButtonPressed',...
'Backbutton_Callback'} % Clean up the task elements
'Backbutton_Callback',...
'Refine_Register_Button_Callback'} % Clean up the task elements

% Hide image and management buttons

Expand Down
3 changes: 2 additions & 1 deletion src/tasks/task_count2_imagescope.m
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ function task_count2_imagescope(hObj)
uicontrol(handles.editCount);
case {'NextButtonPressed',...
'PauseButtonPressed',...
'Backbutton_Callback'} % Clean up the task elements
'Backbutton_Callback',...
'Refine_Register_Button_Callback'} % Clean up the task elements

% Hide image and management buttons

Expand Down
3 changes: 2 additions & 1 deletion src/tasks/task_count_imagescope.m
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ function task_count(hObj)

case {'NextButtonPressed', ...
'PauseButtonPressed',...
'Backbutton_Callback'} % Clean up the task elements
'Backbutton_Callback',...
'Refine_Register_Button_Callback'} % Clean up the task elements

% Hide image and management buttons

Expand Down
Loading

0 comments on commit 165ab83

Please sign in to comment.