vocalpy / hybrid-vocal-classifier

a Python machine learning library for animal vocalizations and bioacoustics
http://hybrid-vocal-classifier.readthedocs.io
BSD 3-Clause "New" or "Revised" License
24 stars 8 forks source link

Bug fix proposal for hvc.extract() for Koumura data format #64

Closed URSUroman closed 6 years ago

URSUroman commented 6 years ago

Hello,

I am trying to use HVC with a data set in the Koumura format ( Koumura, Takuya, and Kazuo Okanoya. "Automatic recognition of element classes and boundaries in the birdsong with variable sequences." PloS one 11.7 (2016): e0159188.)

To see how HVC performs, I took the test data from Koumura at: https://figshare.com/articles/BirdsongRecognition/3470165 I took the Bird0 (135 .wav files plus the Annotation.xml file) data set. For the test I used only the first 11 .wav files (0.wav to 10.wav) and removed the reference to the remaining .wav files from Annotation.xml

Here is my hvc_extract file:

extract: spect_params: ref: koumura segment_params: threshold: 1500 # arbitrary units of amplitude min_syl_dur: 0.01 # ms min_silent_dur: 0.006 # ms

todo_list:

bird_ID : Bird0
file_format: koumura
labelset: 012345678 
feature_group:
  - svm
data_dirs:
  - C:\Users\Roman admin\HVC_Koumura_short

output_dir: C:\Users\Roman admin\HVC_Koumura_out\

when executing hvc.extract in terminal an error appears sayong that the last file 10.wav is not in the list.

I think there is a bug in file koumura.py in the function parse_xml in the for loop after the if(concat_seqs_into_songs) condition. Here is the original piece of code:

if concat_seqs_into_songs:
    song_list = []
    curr_wavFile = seq_list[0].wavFile
    new_seq_obj = seq_list[0]

    for seq in seq_list[1:]:
        if seq.wavFile == curr_wavFile:
            new_seq_obj.length += seq.length
            new_seq_obj.numSyls += seq.numSyls
            new_syls = []
            for syl in seq.syls:
                syl.position += seq.position
            new_seq_obj.syls += seq.syls

        else:
            song_list.append(new_seq_obj)
            new_seq_obj = seq
            curr_wavFile = seq.wavFile

    return song_list

else:    
    return seq_list

I propose that it should be modified by (don't worry to compare, it is a little modification after the for loop at the end):

if concat_seqs_into_songs:
    song_list = []
    curr_wavFile = seq_list[0].wavFile
    new_seq_obj = seq_list[0]

    for seq in seq_list[1:]:
        if seq.wavFile == curr_wavFile:
            new_seq_obj.length += seq.length
            new_seq_obj.numSyls += seq.numSyls
            new_syls = []
            for syl in seq.syls:
                syl.position += seq.position
            new_seq_obj.syls += seq.syls

        else:
            song_list.append(new_seq_obj)
            new_seq_obj = seq
            curr_wavFile = seq.wavFile

# Append last .wav file to the list
    song_list.append(new_seq_obj)

    return song_list

else:    
    return seq_list

That way the last .wav file is also concatenated to the final song.

Best regards, Roman

NickleDave commented 6 years ago

Hey @URSUroman can you reply on this post with the .xml file you made attached? Can you also paste in the lines of code you ran and the text of the exact bug that you get when you run them? Please reply here so I can keep the file and code associated with the bug. Thanks

URSUroman commented 6 years ago

Hi David, here is the Annotation.xml file I used: Annotation.zip

here is file I used as argument for hvc.extract(): Koumura.extract.svm.config.zip

When I run hvc.extract('Koumura.extract.svm.config.yml'), I get:

hvc.extract('Koumura.extract.svm.config.yml') Parsed extract config. Completing item 1 of 1 in to-do list Changing to data directory: C:\Users\Roman admin\Documents\SyllablesClassificati on\Koumura Data Set\HVC_Koumura_short Processing audio file 1 of 11. Processing audio file 2 of 11. Processing audio file 3 of 11. Traceback (most recent call last): File "", line 1, in File "C:\ProgramData\Anaconda3\envs\hvc\lib\site-packages\hvc\featureextract.p y", line 480, in extract _extract(extract_params, calling_function='extract') File "C:\ProgramData\Anaconda3\envs\hvc\lib\site-packages\hvc\featureextract.p y", line 172, in _extract extract_params['segment_params']) File "C:\ProgramData\Anaconda3\envs\hvc\lib\site-packages\hvc\features\extract .py", line 120, in from_file song = Song(filename, file_format, segment_params) File "C:\ProgramData\Anaconda3\envs\hvc\lib\site-packages\hvc\audiofileIO.py", line 637, in init song_dict = koumura.load_song_annot(filename) File "C:\ProgramData\Anaconda3\envs\hvc\lib\site-packages\hvc\koumura.py", lin e 403, in load_song_annot ind = wav_files.index(songfile) ValueError: '10.wav' is not in list

Best regards, Roman

NickleDave commented 6 years ago

Hi Roman,

Thanks for sending the files.

I merged a pull request (in commit 2351d97ec94409523469296aff61dbf87af8b787) that fixes some bugs in the functions hvc.koumura.parse_xml and koumura.load_song_annot.

You should now be able to put whatever .wav files you want in a folder you want, and as long as their respective annotation.xml is in the folder above it, then hvc.extract will be able to run. I tested this using the same files you used and it ran without crashing.

If you want to use hvc with these changes now, the easiest thing to do is install a "bleeding edge" development version as described here: http://hybrid-vocal-classifier.readthedocs.io/en/latest/install.html#install I just edited the instructions today so hopefully it's a little clearer.

Note that you do not have to edit the annotation.xml files in any way. I think it's much better for the program to just know how to parse those files. No sane human being should want to edit .xml files, especially for the purpose of annotating birdsong. I really think a flat plain text format like a .csv file is much cleaner for that purpose, and so I don't want to write anything that requires the user to touch those annotation.xml files directly. Thank you though for suggesting a possible fix.

I really appreciate your bringing this to my attention though. Now that I've fixed this bug, I can use the koumura repositories to test the whole library on .wav files. This will let me address the issues you ran into using hvc.predict on .wav files as well--stay tuned! Also means I should be able to add support for 24-bit wav files like @bradleycolquitt asked for in #44

NickleDave commented 6 years ago

@URSUroman ah I just realized what you pointed out is a separate bug from the ones I fixed. Who wrote this code anyways?! Thank you, I will incorporate your suggestion.

NickleDave commented 6 years ago

Should be fixed by 1a1e44b