Pages

Thursday, 20 November 2014

Mea Culpa-PAMGuard Whistle/Moan Detections to Raven Selection Tables

So, I did a bad-bad thing. No, not that kind of bad-bad thing and if it were I certainly wouldn't write about it on the internet.


Bioacoustics Blogger Did a Bad-Bad Thing:
not de-bugging code before releasing it unto the world
No, a few weeks ago I wrote a piece of code that took binary output from the PAMGuard whistle and moan detector and converted it to a selection table for Raven. I was pleased as punch that I had written this nifty piece of code and more so that I could share it with anybody else interested in converting outputs between these two platforms. So pleased was I, in fact, that I didn't remember to thoroughly check the code for bugs. Once I did, I found out it was wrong, not just a little wrong but wildly wrong.


Ah-yuh

So, I had to take it down and fix it (like when The Grinch told Cindy-Lu Hoo he was fixing the lights when he stole her Christmas tree). Anyway, I would like to sincerely apologize who used it, though my inbox isn't full of hate so I think it's probably OK.




Now that I've had some time to address the issues I am re-releasing the code. There are probably a few bugs here and there but it should largely be functional. Plus, there's more documentation in this code (helpful, no?)

Again, for this code to function properly (at all) you will also need the loadWhistleFile and millisToDateNum functions available from the PAMGuard code repository.

Thanks for reading and happy coding (ha ha!)

Matlab Code


function RavenTable=PamGuardWhistleToRavenTable(filnames,fs,fft_length,hop_size,fildir,outputdir)
% This function takes in a all Binary files from PamGuard output and creates 
% a table suitable for opening in Raven
%
% Input:
% filnames - full file names of PAMGuard Day folders
%           filnames=dir(fullfile([Parent_loc '\' SM2M_nums(1).name '\' ...
%           filedays(1).name],'WhistlesMoans_Whistle*pgdf')); 
%           Can be a matrix of detection days.
%
% fs        - sample frequency used by the detector 
%
% fft_length- fft size (points) going into the whistle and moan detector
%
% hop_size  - fft hop size (points) of the FFT generator feeding into the
% w/m detector in PAMGuard
%
% FileLoc   - full file LOCATION of the PAMGuard Whistle Names
%
% outputdir - full file location of the output directory


% Output:
% RavenTable- matlab Table containing necessary components to open
% selection table in Raven. Use writetable() to save as *.txt
%
% Output text files- writes text files in Raven compatable format for all
% file days to the output directory specified in the inputs
%
%
% Notes:
% Data Must be organized as follows:
% All Binary files for a day must be stored together

% File name/dates must be in the following format
% yyyymmdd 
% (e.g. WhistlesMoans_Whistle_and_Moan_Detector_Contours_20130810_220000.pgdf)


% to do: 
%   Get fs and fft_length from PAMGuard settings file. Bribe Doug and Jamie
%   to write the code/tell me how to get those values
%
% KJ Palmer, 20th November 2013
% Contact-Ask google. 



warning('off')
Begin_time=[];
End_time=[];
Freqs=[];
View=[];

% Variable names Raven Expects
varnames=['Selection\tView\tChannel\tBegin Time (s)\tEnd Time (s)\tLowFreq (Hz)\tHigh Freq (Hz)\n'];

% name format that MATLAB can read and not have a canipition
var_out=sprintf(varnames);


for ii=1:length([filnames]) % every file in the day folder
 
 
    FileLoc=[fildir '\' filnames(ii).name];
    [tones fileHeader]=loadWhistleFile(FileLoc);
 
    if (ii == 1)
        All_files_start=fileHeader.dataDate;
        % date (in MATLAB seconds of the start of the file)
    end
   
 
    if ~isempty(tones)
        for kk=1:size(tones,2)
         Freqs=[Freqs; minmax(tones(kk).contour * fs/fft_length)];
         % frequencies (in Hz) are given by tones*fs(going into the fft
         % engine) divided by the fft length
       
     
          % start_time-seconds from the beginning of the filestream (day) 
          % multiply by 24*60*60 to get seconds
          start_time=(millisToDateNum(tones(kk).millis)-All_files_start)*86400;
       
       
       
         % Begin_time is the time in seconds from the beginning of the
         % filestream (e.g. day)
         Begin_time=[Begin_time; start_time];

       
     
         Dur=length(tones(kk).contour)*hop_size/fs;
         % Duration: the length of the contour times the hopsize/fs
       
         End_time=[End_time; start_time+Dur];  
       
         View=[View; 'Spectrogram 1'];
         % View for raven table
       
       
        end
    end
end

  % Selection number for raven table (assumes one channel)
   channel=ones(size(End_time));
 
   % Event number for selection  
     Selection=[1:length(End_time)]';
 
   
   % Combine verything into a table
   RavenTable=table(Selection, View, channel, Begin_time, End_time, Freqs(:,1), Freqs(:,2) );
     
 %Write the files to the export location  
stuff=table2cell(RavenTable);

fname=[outputdir '.txt'];
fid = fopen(fname,'w');

% write the first row of the text file, the variable names
fprintf(fid,var_out);

formatSpec = '%d\t %s\t %d\t %8.2f\t %8.3f\t %6.0f\t %6.0f';
% this is where I got tired of coming up with sensible variable names. Don't judge, I'm a biologist
[nrows,ncols] = size(stuff);
for row = 1:nrows
    fprintf(fid,'\r\n');
    fprintf(fid,formatSpec,(stuff{row,:}));
 
end

fclose(fid);


end

1 comment:

  1. I think you're a fantastic human being

    ReplyDelete

Comment forum rules.
1. Be accurate
2. Cite your sources
3. Be nice

Comments failing to meet these criteria will be removed