diff --git a/bin/name2id.m b/bin/name2id.m index 6dfd4597e1709936474fe5dfdbbafb813e1b3b97..4c1c1798b91392b2f396d238c4d49757de124202 100644 --- a/bin/name2id.m +++ b/bin/name2id.m @@ -1,68 +1,71 @@ -function [species_id,from_language] = name2id(birdnames, from_language, exactfit) - if nargin<3 - exactfit=true; +function [species_id, from_language] = name2id(birdnames, from_language, exactfit) + if nargin < 3 + exactfit = true; end - + allbird_names = evalin('base', 'allbird_names'); - if iscell(birdnames)&&numel(birdnames)==1&&~isempty(strfind(birdnames{1},'{')) - birdnames=birdnames{1}; + if iscell(birdnames) && numel(birdnames) == 1 && ~isempty(strfind(birdnames{1}, '{')) + birdnames = birdnames{1}; end if ischar(birdnames) - if strfind(birdnames,'{')>0 - birdnames=eval(birdnames); + if strfind(birdnames, '{') > 0 + birdnames = eval(birdnames); else - birdnames={birdnames}; + birdnames = {birdnames}; end end - supportedlang = {'species_id','Order','Family','Scientific','English','Catalan',... - 'Chinese','Chinese_Traditional_','Croatian','Czech','Danish','Dutch',... - 'Finnish','French','German','Italian','Japanese','Lithuanian','Norwegian',... - 'Polish','Portuguese_Lusophone_','Portuguese_Portuguese_','Russian',... - 'Serbian','Slovak','Spanish','Swedish','Turkish','Ukrainian','Afrikaans',... - 'Arabic','Belarusian','Bulgarian','Estonian','French_Gaudin_','Greek',... - 'Hebrew','Hungarian','Icelandic','Indonesian','Korean','Latvian','Macedonian',... - 'Malayalam','NorthernSami','Persian','Romanian','Slovenian','Thai','XCname',... - 'en_family','nl_family','family_id','BreedingRange','BreedingSubRange','NonbreedingRange'}; + supportedlang = {'species_id', 'Order', 'Family', 'Scientific', 'English', 'Catalan', ... + 'Chinese', 'Chinese_Traditional_', 'Croatian', 'Czech', 'Danish', 'Dutch', ... + 'Finnish', 'French', 'German', 'Italian', 'Japanese', 'Lithuanian', 'Norwegian', ... + 'Polish', 'Portuguese_Lusophone_', 'Portuguese_Portuguese_', 'Russian', ... + 'Serbian', 'Slovak', 'Spanish', 'Swedish', 'Turkish', 'Ukrainian', 'Afrikaans', ... + 'Arabic', 'Belarusian', 'Bulgarian', 'Estonian', 'French_Gaudin_', 'Greek', ... + 'Hebrew', 'Hungarian', 'Icelandic', 'Indonesian', 'Korean', 'Latvian', 'Macedonian', ... + 'Malayalam', 'NorthernSami', 'Persian', 'Romanian', 'Slovenian', 'Thai', 'XCname', ... + 'en_family', 'nl_family', 'family_id', 'BreedingRange', 'BreedingSubRange', 'NonbreedingRange'}; if isempty(from_language) %auto detect - ndx=ismember(supportedlang,{'species_id','Order','Family','XCname',... - 'en_family','family_id','BreedingRange','BreedingSubRange','NonbreedingRange'}); - supportedlang1=supportedlang(~ndx); - species_id=[]; - for i=1:numel(supportedlang1) - id=name2id(birdnames,supportedlang1{i}); - if numel(id)==numel(birdnames) - from_language=supportedlang1{i}; - species_id=id; - end - end - return; + ndx = ismember(supportedlang, {'species_id', 'Order', 'Family', 'XCname', ... + 'en_family', 'family_id', 'BreedingRange', 'BreedingSubRange', 'NonbreedingRange'}); + supportedlang1 = supportedlang(~ndx); + species_id = []; + for i = 1:numel(supportedlang1) + id = name2id(birdnames, supportedlang1{i}); + if numel(id) == numel(birdnames) + from_language = supportedlang1{i}; + species_id = id; + end + end + return; end - from_language1=regexprep(from_language,'[\(\)]','_'); + from_language1 = regexprep(from_language, '[\(\)]', '_'); %supportedlang = allbird_names.Properties.VariableNames; ndx = strcmpi(from_language1, supportedlang); if ~any(ndx) supportedlang_user = supportedlang(~ismember(supportedlang, {'species_id', 'Order', 'XCname', 'Family'})); - supportedlang_user=regexprep(supportedlang_user,'(.*)_(.*)_','$1($2)'); + supportedlang_user = regexprep(supportedlang_user, '(.*)_(.*)_', '$1($2)'); s = sprintf('''%s'', ', supportedlang_user{:}); error('Language ''%s'' is not supported. supported languages are:\n%s\n', from_language, s); else from_language1 = supportedlang{ndx}; end if isempty(birdnames) - species_id=[]; + species_id = []; elseif exactfit - if numel(birdnames)==1 - ndx=strcmpi(birdnames{1},allbird_names.(from_language1)); - species_id=allbird_names.species_id(ndx); - else - ndx2 = ismember(lower(allbird_names.(from_language1)),lower(birdnames)); - species_id = allbird_names.species_id(ndx2); - end + if numel(birdnames)==1&&any(birdnames{1}==',') + birdnames=regexp(birdnames{1},'[ ]*,[ ]*','split'); + end + ndx2 = matches(allbird_names.(from_language1), birdnames, 'ignorecase', true); + species_id = allbird_names.species_id(ndx2); else - ndx = contains(allbird_names.(from_language1),birdnames,'ignorecase',true); - species_id = allbird_names.species_id(ndx); + %use wildcards like '*mees,koo?mees' + %wildcard symbols: * -any string + % ? -any character + % , -look for different patterns/species + pat = regexpPattern(regexprep(birdnames, {'[ ]*,[ ]*', '*', '?'}, {'|', '.*', '.'}), 'ignorecase', true); + ndx = matches(allbird_names.(from_language1), pat); + species_id = allbird_names.species_id(ndx); end -end \ No newline at end of file +end diff --git a/bin/restore_database.m b/bin/restore_database.m index 20acd5944416196754581876613a90026255e2cd..cd1db6672d8fe3ce7aa2df84db5894e9573a8a74 100644 --- a/bin/restore_database.m +++ b/bin/restore_database.m @@ -12,7 +12,7 @@ function [changedsettings] = restore_database(currfolder) if nargin == 0 currfolder = 'curr'; end - bird_settings = struct('filerec', [], 'selection', [], 'recs', [], 'deletedrecs', [], 'language', 'Dutch', 'currfolder', currfolder); + bird_settings = struct('filerec', [], 'recs', [], 'deletedrecs', [], 'language', 'Dutch', 'currfolder', currfolder); changedsettings = true; end diff --git a/bin/selectrecords.m b/bin/selectrecords.m index 65ea64f6643f46f8e1fe4ef8956281e0f2b4e93c..fdf0e585dbee87fb11c2c0e1e1cb063ced4fc9c4 100644 --- a/bin/selectrecords.m +++ b/bin/selectrecords.m @@ -1,4 +1,4 @@ -function [ndx, recs] = selectrecords(varargin) +function [ndx, recs, opts] = selectrecords(varargin) %first argument can be a struct/table (for instance bird_records) %by default the records of bird_settings are selected. % maxsamp - max sample size of the species in each group; @@ -53,6 +53,10 @@ function [ndx, recs] = selectrecords(varargin) % dvc - device % mic - microphone type % smp - sample rate + % + % ~ before the name is "not", for instance: + % ~id - exclude record ids + %load bird_settings bird_settings; @@ -82,7 +86,13 @@ function [ndx, recs] = selectrecords(varargin) if numel(varargin) > 0 && (rem(numel(varargin), 2) == 1) varargin = ['autodetect', varargin]; end - + + + + if nargin == 0 + ndx = true(size(recs, 1), 1); + return; + end for i = 1:numel(varargin) if isstring(varargin{i}) varargin{i} = cellstr(varargin{i}); @@ -99,26 +109,26 @@ function [ndx, recs] = selectrecords(varargin) end end end - - if nargin == 0 - ndx = true(size(recs, 1), 1); - return; - end - - + allbird_names = evalin('base', 'allbird_names'); - + allbird_names_fields = fieldnames(allbird_names); if ~isstruct(recs) && ~istable(recs) recs_fields = {}; else recs_fields = fieldnames(recs); end - + load localbirds localbirds localbirds_fields = localbirds.Properties.VariableNames.'; opts = reshape(varargin, 2, numel(varargin) / 2); + notincluding = contains(opts(1, :), '~'); + if any(notincluding) + opts(1, :) = regexprep(opts(1, :), '~', ''); + end + opts(3, :) = num2cell(notincluding); validoptions = [{'combine'; 'maxsamp'; 'year'; 'month'; 'hour'; 'language'; 'autodetect'}; recs_fields; allbird_names_fields; localbirds_fields]; + ndx = ~ismember(lower(opts(1, :)), lower(validoptions)); if any(ndx) s = sprintf('%s, ', validoptions{:}); @@ -133,6 +143,7 @@ function [ndx, recs] = selectrecords(varargin) else combfun = @(x)all(x,2); %and end + ndx1 = strcmpi(opts(1, :), 'language'); if any(ndx1) language = opts{2, ndx1}; @@ -186,7 +197,7 @@ function [ndx, recs] = selectrecords(varargin) val1 = {val1}; end switch field1 - case {'id', 'lat', 'lng', 'alt'} + case {'id', 'lat', 'lng', 'alt', 'length', 'bird_seen', 'playback_used', 'auto', 'smp', 'species_id'} ndx(:, i) = numerical_value(val1, recs.(field1)); case {'type', 'sex', 'stage'} ndx(:, i) = ismember_withcomma(val1, recs.(field1), field1); @@ -210,7 +221,7 @@ function [ndx, recs] = selectrecords(varargin) s = id2name(allbird_names.species_id(s), field1); s = unique(s); s = sprintf('''%s'', ', s{:}); - error('birdquiz:selectrecords:notfound', '%s=''%s'' is currently not in the database, valid options are:\n %s', field1, val1{:}, s); + error('birdquiz:selectrecords:notfound', '%s=''%s'' is currently not in the database, valid options are:\n %s\you can also use wildcards *?,\n', field1, val1{:}, s); end %ss = ismember(valids, [recs.species_id]); %valids=valids(ss); @@ -292,6 +303,10 @@ function [ndx, recs] = selectrecords(varargin) ndx(:, i) = ismember(lower(recs.(field1)), lower(val1))'; end end + notincluding = [opts{3, :}]; + if any(notincluding) + ndx(:, notincluding) = ~ndx(:, notincluding); + end ndx = combfun(ndx); if ~isempty(maxsamp) && ~isinf(maxsamp) %maxsamp random samples (if there are enough records @@ -306,10 +321,13 @@ function [ndx, recs] = selectrecords(varargin) ndx(fndx(fndx1)) = false; end end - + end function ndx = ismember_withcomma(val1, crecs, field1) + if iscell(val1) && numel(val1) == 1 && iscell(val1{1}) + val1 = val1{1}; + end ndx = false(size(crecs)); if ~isempty(crecs) for j = 1:numel(val1) diff --git a/bin/selectspecies.m b/bin/selectspecies.m index 432408036eb2499ba68eea8adca83a48a8279e9f..24eaaadef642a4565aaa2a20fdf05aab5583c23a 100644 --- a/bin/selectspecies.m +++ b/bin/selectspecies.m @@ -6,27 +6,20 @@ function selectspecies(varargin) end if isempty(bird_settings) && exist('bird_settings.mat', 'file') load bird_settings bird_settings - % bird_settings.selection=[]; - newselect = struct(varargin{:}); - % if isfield(bird_settings,'selection')&&~isempty(bird_settings.selection)&&isequal(newselect,bird_settings.selection) - % disp('selection not changed'); - % return; - % end - bird_settings.selection = newselect; else - bird_settings = struct('selection', [], 'language', 'Dutch', 'currfolder', 'curr', ... + bird_settings = struct('language', 'Dutch', 'currfolder', 'curr', ... 'filerec', []); end % [bird_settings, deletedids, rec] = updatealldata(bird_settings); restore_database; rec = bird_settings.recs; - bird_settings.selection = struct(varargin{:}); - save bird_settings bird_settings - + % + opts=[]; if nargin > 0 try - ndx = selectrecords(rec, varargin{:}); + [ndx,~,opts] = selectrecords(rec, varargin{:}); + % load bird_settings bird_settings catch err if strcmp(err.identifier, 'birdquiz:selectrecords:notfound') @@ -45,7 +38,7 @@ function selectspecies(varargin) restore_database; rec = bird_settings.recs; - ndx = selectrecords(varargin{:}); + [ndx,~,opts] = selectrecords(varargin{:}); % load bird_settings bird_settings else rethrow(err); @@ -55,6 +48,8 @@ function selectspecies(varargin) else selected = ~ismember([rec.id], bird_settings.deletedrecs); end + + % save bird_settings bird_settings %load bird_settings bird_settings bird_settings.filerec.selected=selected; % c = num2cell(selected); diff --git a/bin/sonogram.m b/bin/sonogram.m index 81005983fc37dfc1228e84af3e3d2de0444dc971..fb27311e6a0e08f2a83ee4e0bded6e7de81ec682 100644 --- a/bin/sonogram.m +++ b/bin/sonogram.m @@ -1,5 +1,5 @@ function res = sonogram(filename, currtime) -global bird_settings + global bird_settings maxtime = 6; if nargin == 1 && isnumeric(filename) currtime = filename; @@ -11,9 +11,9 @@ global bird_settings %if isempty(get(hfig, 'KeyPressFcn')) % set(hfig, 'KeyPressFcn', @keyPress) %end - warning('off','sonogram:toolboxmissing'); + warning('off', 'sonogram:toolboxmissing'); sonogram(res, currtime); - warning('on','sonogram:toolboxmissing'); + warning('on', 'sonogram:toolboxmissing'); else set(findobj(hfig, 'tag', 'timeline'), 'value', currtime); drawnow; @@ -61,17 +61,17 @@ global bird_settings hfig = figwofocus(333); set(hfig, 'userdata', res); %, 'visible', 'off'); - + if ~exist('spectrogram', 'file') - warning('sonogram:toolboxmissing','The Signal Processing Toolbox is needed for creating a spectrogram, now plotting only the power plot '); + warning('sonogram:toolboxmissing', 'The Signal Processing Toolbox is needed for creating a spectrogram, now plotting only the power plot '); ts = res.starttime + [0:numel(y) - 1]' ./ fs; - S=[]; - hax=gca; + S = []; + hax = gca; else [ ~, f, t, S] = ... spectrogram(y, 1000, 400, [], fs, 'yaxis'); S = 10 * log10(abs(S) + eps); %dB - + try hax = findobj(hfig, 'tag', 'subplot(1,1)'); catch @@ -81,11 +81,11 @@ global bird_settings hax = subplot(2, 1, 1); end %hax = subplot(2, 1, 1); - + h = surf(hax, t + res.starttime, f / 1000, S); set(h, 'tag', 'spectrogram'); set(hax, 'view', [0 90]) - + shading(hax, 'flat'); xlim(hax, [min(t + res.starttime) max(t + res.starttime)]) ylabel(hax, 'kHz') @@ -105,7 +105,7 @@ global bird_settings if isempty(hax) hax = subplot(2, 1, 2); end - + end h = plot(hax, ts, y); set(h, 'tag', 'powerplot') @@ -117,10 +117,10 @@ global bird_settings xlim(hax, [min(ts) max(ts)]) % hfig = figwofocus(333); if ~isempty(S) - adjustplot(hfig, '-r') - adjustplot(hfig, '-p', 0.02); - - set(hfig, 'position', [ 0.0219 0.2250 0.4367 0.6150]) + adjustplot(hfig, '-r') + adjustplot(hfig, '-p', 0.02); + + set(hfig, 'position', [ 0.0219 0.2250 0.4367 0.6150]) end % set(hfig, 'visible', 'on'); end @@ -147,12 +147,12 @@ end % stopsound(4); % end % end - -function repeatsound(~, ~) - global quest - set(findobj(quest.h, 'tag', 'repeat'), 'visible', 'off') - play(quest.player); -end +% +% function repeatsound(~, ~) +% global quest +% set(findobj(quest.h, 'tag', 'repeat'), 'visible', 'off') +% play(quest.player); +% end function hfig = figwofocus(nr) try hfig = findobj(groot, 'Number', nr); diff --git a/bin/stopsound.m b/bin/stopsound.m index bc1ab59c8f90404bf01c870da037017cceb8e29e..465daa0d1590d9430b4f7de416b43f2c76d25081 100644 --- a/bin/stopsound.m +++ b/bin/stopsound.m @@ -23,11 +23,13 @@ function stopsound(keuze) if quest.current == keuze quest.ncorrect = quest.ncorrect + 1; h = msgbox(sprintf('Well done! It was indeed %s - %s (score=%d%%)', quest.common_name, quest.rec.type{1}, round(quest.ncorrect / quest.n * 100)), 'Succes'); + drawnow tic; birdquiz('-getnext') pause(2-toc); else h = msgbox(sprintf('Sorry that is not correct! It was %s (score=%d%%)', quest.common_name, round(quest.ncorrect / quest.n * 100)), 'Error', 'error'); + drawnow tic; birdquiz('-getnext'); pause(3-toc); diff --git a/birdquiz.m b/birdquiz.m index 400caef5fa2dd223f73706b550ed193f41a9fdc8..e28875ef1f1543d2348fdf9bddfbf0c2555369e7 100644 --- a/birdquiz.m +++ b/birdquiz.m @@ -45,9 +45,7 @@ function birdquiz(varargin) if restore_database quest = []; - end - - + end if nargin > 0 if nargin == 2 && strcmpi(varargin{1}, 'language') @@ -58,10 +56,7 @@ function birdquiz(varargin) save bird_settings bird_settings else selectspecies(varargin{:}); - % load('bird_settings', 'bird_settings'); end - else - %load('bird_settings', 'bird_settings') end if isempty(quest) diff --git a/makedatabase.m b/makedatabase.m index df29bfd89acb4be61c0be041d2796d4fb7d2cb51..8d19658983d85b124d6a95c990007a77c17a79c9 100644 --- a/makedatabase.m +++ b/makedatabase.m @@ -4,7 +4,7 @@ function makedatabase(varargin) %extra option: %addmode - kind of add mode: % 'reset' (default), removes all existing bird_records (after succesful download) - % 'add' all the bird_records to the existing database + % 'add' add the bird_records to the existing database % 'replace' replace selected species in the database % 'tmp' keep it in a temporary folder, it will be deleted the next time % you run makedatabase @@ -28,7 +28,7 @@ function makedatabase(varargin) if exist('bird_settings.mat', 'file') load bird_settings bird_settings else - bird_settings = struct('selection', [], 'deletedrecs', [], 'language', 'Dutch', 'currfolder', 'curr', ... + bird_settings = struct( 'deletedrecs', [], 'language', 'Dutch', 'currfolder', 'curr', ... 'filerec', []); save bird_settings bird_settings end diff --git a/runbatch.m b/runbatch.m index 19cc1d631499bb1cbdb18b2b9e9a1c693eda3fa7..aab2361e413924a19677c515e4621a4105b1975e 100644 --- a/runbatch.m +++ b/runbatch.m @@ -9,9 +9,7 @@ if true habitatgroups = cell(10, 1); habitats = cell(10, 1); j = 1; - - - + habitats{j} = 'berg'; habitatgroups{j} = {'Slechtvalk', 'Boomleeuwerik', 'Appelvink', 'Fluiter', ... 'Middelste bonte specht', 'Vuurgoudhaan', 'Grauwe klauwier', ... @@ -22,7 +20,7 @@ if true habitats{j} = 'rivier'; habitatgroups{j} = {'Grote zilverreiger','Bergeend', 'Wilde Eend','Kleine zilverreiger', 'Ooievaar', ... 'Blauwe reiger', 'Grauwe gans', 'Brandgans', 'Kolgans','Oeverzwaluw', 'Koperwiek', ... - 'Grote zaagbek', 'Smient', 'IJsvogel', 'Oeverloper','Nijlgans','Knobbelzwaan','Grote Canadese Gans'}; + 'Grote zaagbek','Putter', 'Smient', 'IJsvogel', 'Oeverloper','Nijlgans','Knobbelzwaan','Grote Canadese Gans'}; j = j + 1; habitats{j} = 'stad'; habitatgroups{j} = {'Huismus', 'Kauw', 'Ekster', 'Spreeuw', 'Zwarte kraai', ...