Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Next/Prev File Buttons #138

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified DeepSqueak.fig
Binary file not shown.
125 changes: 94 additions & 31 deletions DeepSqueak.m
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,46 @@ function PreviousCall_Callback(hObject, eventdata, handles)
update_fig(hObject, eventdata, handles);


% --- Executes on button press in NextFile.
function NextFile_Callback(hObject, eventdata, handles)
numfiles = length(handles.detectionfiles);
%Make sure we actually have an active Detections folder
if numfiles > 0
handles.current_file_id = get(handles.popupmenuDetectionFiles,'Value');
% Check for a next file
if handles.current_file_id < numfiles
% If confirmed possible, increment to next file
handles.current_file_id = handles.current_file_id + 1;
filename = fullfile(handles.detectionfiles(handles.current_file_id).folder, handles.detectionfiles(handles.current_file_id).name);
% filename argument bypasses the behavior of pressing the LoadCalls button
cancelled = loadcalls_Callback(hObject, eventdata, handles, 'filename', filename);
% Make sure the drop-down matches what's happening internally
if ~cancelled
handles.popupmenuDetectionFiles.Value = handles.current_file_id;
end
end
end

% --- Executes on button press in PrevFile.
function PrevFile_Callback(hObject, eventdata, handles)
numfiles = length(handles.detectionfiles);
%Make sure we actually have an active Detections folder
if numfiles > 0
handles.current_file_id = get(handles.popupmenuDetectionFiles,'Value');
% Check for a previous file
if handles.current_file_id > 1
% If confirmed possible, decrement file
handles.current_file_id = handles.current_file_id - 1;
filename = fullfile(handles.detectionfiles(handles.current_file_id).folder, handles.detectionfiles(handles.current_file_id).name);
% filename argument bypasses the behavior of pressing the LoadCalls button
cancelled = loadcalls_Callback(hObject, eventdata, handles, 'filename', filename);
% Make sure the drop-down matches what's happening internally
if ~cancelled
handles.popupmenuDetectionFiles.Value = handles.current_file_id;
end
end
end

% --- Executes on selection change in Networks Folder Pop up.
function neuralnetworkspopup_Callback(hObject, eventdata, handles)
guidata(hObject, handles);
Expand Down Expand Up @@ -494,11 +534,11 @@ function export_raven_Callback(hObject, eventdata, handles)
end
end
a = cell2table(raventable);
handles.current_file_id = get(handles.popupmenuDetectionFiles,'Value');
current_detection_file = handles.detectionfiles(handles.current_file_id).name;
ravenname=[strtok(current_detection_file,'.') '_Raven.txt'];
[FileName,PathName] = uiputfile(ravenname,'Save Raven Truth Table (.txt)');
writetable(a,[PathName FileName],'delimiter','\t','WriteVariableNames',false);
% Get the name of the output file and save the table
[PathName, FileName, ~] = fileparts(handles.current_detection_file);
ravenName = fullfile(PathName, [FileName '_Raven.txt']);
[FileName,PathName] = uiputfile(ravenName,'Save Raven Truth Table (.txt)');
writetable(a, fullfile(PathName, FileName), 'delimiter', '\t', 'WriteVariableNames', false);
guidata(hObject, handles);

% --------------------------------------------------------------------
Expand Down Expand Up @@ -697,12 +737,22 @@ function backwardButton_Callback(hObject, eventdata, handles)
jumps = floor(handles.data.focusCenter / handles.data.settings.pageSize);
handles.data.windowposition = jumps*handles.data.settings.pageSize;

calls_within_window = find(handles.data.calls.Box(:,1) < handles.data.windowposition + handles.data.settings.pageSize, 1, 'last');
if ~isempty(calls_within_window)
handles.data.currentcall = calls_within_window;
handles.data.current_call_valid = true;
% if we can't page because we're at the beg of the file, make the first call
% the current call
if jumps == 0
if ~isempty(handles.data.calls)
handles.data.currentcall = 1;
handles.data.current_call_valid = true;
end
% Otherwise make the last call in the new page window the current call
% (will not necessarily be in focusWindow)
else
calls_within_window = find(handles.data.calls.Box(:,1) < handles.data.windowposition + handles.data.settings.pageSize, 1, 'last');
if ~isempty(calls_within_window)
handles.data.currentcall = calls_within_window;
handles.data.current_call_valid = true;
end
end

update_fig(hObject, eventdata, handles);


Expand All @@ -718,10 +768,21 @@ function forwardButton_Callback(hObject, eventdata, handles)
% handles.data.focusCenter = max(0, handles.data.windowposition - handles.data.settings.focus_window_size ./ 2);
% get_closest_call_to_focus(hObject, eventdata, handles);

calls_within_window = find(handles.data.calls.Box(:,1) > handles.data.windowposition, 1);
if ~isempty(calls_within_window)
handles.data.currentcall = calls_within_window;
handles.data.current_call_valid = true;
% if we can't page because we're at the end of the file, make the last call
% the current call
if jumps == 0
if ~isempty(handles.data.calls)
handles.data.currentcall = height(handles.data.calls);
handles.data.current_call_valid = true;
end
% Otherwise make the first call in the new page window the current call
% (will not necessarily be in focusWindow)
else
calls_within_window = find(handles.data.calls.Box(:,1) > handles.data.windowposition, 1);
if ~isempty(calls_within_window)
handles.data.currentcall = calls_within_window;
handles.data.current_call_valid = true;
end
end

update_fig(hObject, eventdata, handles);
Expand Down Expand Up @@ -820,30 +881,32 @@ function topRightButton_Callback(hObject, eventdata, handles)

% --- Executes on button press in loadAudioFile.
function loadAudioFile_Callback(hObject, eventdata, handles)
cancelled = checkForUnsavedChanges(hObject, eventdata, handles);
if cancelled
return
end

h = waitbar(0,'Loading Audio Please wait...');
update_folders(hObject, eventdata, handles);
handles = guidata(hObject);

if nargin == 3 % if "Load Calls" button pressed
if isempty(handles.audiofiles)
close(h);
errordlg(['No valid audio files in current audio folder. Select a folder containing audio with '...
'"File -> Select Audio Folder", then choose the desired file in the "Audio Files" dropdown box.'])
return
end
handles.current_file_id = get(handles.AudioFilespopup,'Value');
handles.current_audio_file = handles.audiofiles(handles.current_file_id).name;
if isempty(handles.audiofiles)
close(h);
errordlg(['No valid audio files in current audio folder. Select a folder containing audio with '...
'"File -> Select Audio Folder", then choose the desired file in the "Audio Files" dropdown box.'])
return
end

handles.data.audiodata = audioinfo(fullfile(handles.data.settings.audiofolder,handles.current_audio_file));
current_file_id = get(handles.AudioFilespopup,'Value');
handles.data.audiodata = audioinfo(fullfile(handles.data.settings.audiofolder, handles.audiofiles(current_file_id).name));

% Create a filename for the new detection file
[~, filename, ~] = fileparts(handles.data.audiodata.Filename);
handles.current_detection_file = fullfile(handles.data.settings.detectionfolder, [filename '.mat']);

% Initialize the empty calls variable
handles.data.calls = table(zeros(0,4),[],[],[], 'VariableNames', {'Box', 'Score', 'Type', 'Accept'});

Calls = table(zeros(0,4),[],[],[], 'VariableNames', {'Box', 'Score', 'Type', 'Accept'});
% Calls.Box = [0 0 1 1];
% Calls.Score = 0;
% Calls.Type = categorical({'NA'});
% Calls.Power = 1;
% Calls.Accept = false;
handles.data.calls = Calls;
% Position of the focus window
handles.data.focusCenter = handles.data.settings.focus_window_size ./ 2;
initialize_display(hObject, eventdata, handles);
Expand Down
6 changes: 3 additions & 3 deletions Functions/Batch_Reject_by_Threshold_Callback.m
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ function Batch_Reject_by_Threshold_Callback(hObject, eventdata, handles)
end
close(h);

%update the display
if isfield(handles,'current_detection_file') && any(ismember(handles.detectionfilesnames(selections),handles.current_detection_file))
loadcalls_Callback(hObject, eventdata, handles, handles.current_file_id)
% reload the file if the currently loaded file was modified
if isfield(handles,'current_detection_file') && any(ismember(fullfile(handles.detectionfiles(1).folder,handles.detectionfilesnames(selections)),handles.current_detection_file))
loadcalls_Callback(hObject, eventdata, handles, 'filename', handles.current_detection_file, 'checkForChanges', false)
end
28 changes: 28 additions & 0 deletions Functions/checkForUnsavedChanges.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
function cancelled = checkForUnsavedChanges(hObject, eventdata, handles)
%% Check if the current file has been modified. If it has, prompt the user to save it
% cancelled = false if the user pressed "Yes" or "No"
% cancelled = true if user pressed "Cancel"

cancelled = false;
if ~isempty(handles.data.calls)
if isfile(handles.current_detection_file)
oldCalls = loadCallfile(handles.current_detection_file, handles);
% Check if the "box", "type", and "accept" fields in the currently loaded
% file are the same as the old file. Do this instead of comparing
% all fields because previous versions of DS had additional
% variables, so this prevents compatibility errors.
% isequal doesn't work when categorical variables have undefined
% entries, so test them seperately.
if ~isequal(handles.data.calls(:,{'Box', 'Accept'}), oldCalls(:,{'Box', 'Accept'})) || ~isequal(cellstr(handles.data.calls.Type), cellstr(oldCalls.Type))
response = questdlg('Calls have been modified, save changes?', 'Save changes', 'Yes', 'No', 'Cancel', 'Yes');
switch response
case 'Yes'
cancelled = savesession_Callback(hObject, eventdata, handles);
case 'No'
cancelled = false;
case 'Cancel'
cancelled = true;
end
end
end
end
4 changes: 4 additions & 0 deletions Functions/loadCallfile.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
%% Unpack the data
if isfield(data, 'Calls')
Calls = data.Calls;
% Back Compatability for Files with Power in The Detection File.
if ismember('Power',Calls.Properties.VariableNames)
Calls = removevars(Calls, 'Power');
end
elseif nargout < 3 % If ClusteringData is requested, we don't need Calls
error('This doesn''t appear to be a detection file!')
end
Expand Down
35 changes: 26 additions & 9 deletions Functions/loadcalls_Callback.m
Original file line number Diff line number Diff line change
@@ -1,27 +1,44 @@
% --- Executes on button press in LOAD CALLS.
function loadcalls_Callback(hObject, eventdata, handles, reload_current_file)
function cancelled = loadcalls_Callback(hObject, eventdata, handles, varargin)
% Inputs:
% filename - full path of the file to load. If filename is not given, load the file selected in the dropdown menu.
% checkForChanges - If true, check if the current session matches the saved file
% Outputs
% cancelled - true if the user pressed cancel when prompted to save changes, else false

p = inputParser;
addParameter(p, 'filename', []);
addParameter(p, 'checkForChanges', true);
parse(p, varargin{:});


cancelled = false;
if p.Results.checkForChanges
cancelled = checkForUnsavedChanges(hObject, eventdata, handles);
end
if cancelled
return
end

h = waitbar(0,'Loading Calls Please wait...');
update_folders(hObject, eventdata, handles);
handles = guidata(hObject);
if nargin == 3 % if "Load Calls" button pressed, load the selected file, else reload the current file
if isempty(p.Results.filename) % if "Load Calls" button pressed, load the selected file, else reload the current file
if isempty(handles.detectionfiles)
close(h);
errordlg(['No valid detection files in current folder. Select a folder containing detection files with '...
'"File -> Select Detection Folder", then choose the desired file in the "Detected Call Files" dropdown box.'])
return
end
handles.current_file_id = get(handles.popupmenuDetectionFiles,'Value');
handles.current_detection_file = handles.detectionfiles(handles.current_file_id).name;
handles.current_detection_file = fullfile(handles.detectionfiles(handles.current_file_id).folder, handles.detectionfiles(handles.current_file_id).name);
elseif isfile(p.Results.filename)
handles.current_detection_file = p.Results.filename;
end

handles.data.calls = [];
handles.data.audiodata = [];
[handles.data.calls, handles.data.audiodata] = loadCallfile(fullfile(handles.detectionfiles(handles.current_file_id).folder, handles.current_detection_file), handles);

%% Back Compatability for Files with Power in The Detection File.
if ismember('Power',handles.data.calls.Properties.VariableNames)
handles.data.calls = removevars(handles.data.calls,'Power');
end
[handles.data.calls, handles.data.audiodata] = loadCallfile(handles.current_detection_file, handles);

% Position of the focus window to the first call in the file
handles.data.focusCenter = handles.data.calls.Box(1,1) + handles.data.calls.Box(1,3)/2;
Expand Down
28 changes: 11 additions & 17 deletions Functions/savesession_Callback.m
Original file line number Diff line number Diff line change
@@ -1,28 +1,22 @@
function savesession_Callback(hObject, eventdata, handles)
function cancelled = savesession_Callback(hObject, eventdata, handles)
% cancelled = false if saved successfully, else success = true
cancelled = false;

handles.v_det = get(handles. popupmenuDetectionFiles,'Value');
if isfield(handles,'current_detection_file')
handles.SaveFile = handles.detectionfiles(handles.v_det).name;
handles.SaveFile = handles.current_detection_file;
else
handles.SaveFile = [strtok(handles.audiofiles(handles.v_det).name,'.') '.mat'];
if isempty(handles.data.calls)
disp('Can''t save session, no calls are loaded')
return
end

% temp = handles.data.audiodata.samples;
% handles.data.audiodata.samples = [];
guidata(hObject, handles);

Calls = handles.data.calls;
audiodata = handles.data.audiodata;
[FileName, PathName] = uiputfile(fullfile(handles.data.settings.detectionfolder, handles.SaveFile), 'Save Session (.mat)');
[FileName, PathName] = uiputfile(handles.current_detection_file, 'Save Session (.mat)');
if FileName == 0
cancelled = true;
return
end
h = waitbar(0.5, 'saving');


save(fullfile(PathName, FileName), 'Calls','audiodata', '-v7.3');
% handles.data.audiodata.samples = temp;
h = waitbar(0.5, 'saving');
save(fullfile(PathName, FileName), 'Calls','audiodata', '-append');
update_folders(hObject, eventdata, handles);
guidata(hObject, handles);
close(h);

4 changes: 2 additions & 2 deletions Functions/set_static_box_height_Callback.m
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ function set_static_box_height_Callback(hObject, eventdata, handles)
guidata(hObject, handles);

%% Update display
if isfield(handles,'current_detection_file') && any(contains(fname, handles.current_detection_file))
loadcalls_Callback(hObject, eventdata, handles, true)
if isfield(handles,'current_detection_file') && any(ismember(fullfile(fpath, fname), handles.current_detection_file))
loadcalls_Callback(hObject, eventdata, handles, 'filename', handles.current_detection_file, 'checkForChanges', false)
end