Exemplo n.º 1
0
def import_syllables(conn):
    """
    :param conn: the database connection
    :return:
    """
    cur = conn.cursor()
    el_cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)

    # Import syllables for all songs
    cur.execute(
        'SELECT sg.name, s.starttime, s.endtime, w.songid FROM syllable s '
        'JOIN wavs w ON s.songid=w.songid '
        'JOIN songdata sg ON w.songid=sg.id ORDER BY w.filename, s.starttime')
    song_syllable_rows = cur.fetchall()
    songs_2_syllables = {}

    # Song #79 PKI_2017_02_25_WHW028_01_M.EX..PipeClicksGrowlcough.wav has more than one syllable at position 1124:1136.
    # Db Syllable #2924

    for row in song_syllable_rows:
        song_name = row[0]
        syl_starttime = row[1]
        syl_endtime = row[2]
        song_id = row[3]

        el_cur.execute(
            'select starttime, timelength from element where songid={} and starttime >= {} '
            'and (starttime + timelength) <= {} order by starttime'.format(
                song_id, syl_starttime, syl_endtime))
        el_rows = el_cur.fetchall()
        if len(el_rows) == 0:
            warning(
                'Syllable with starttime={} endtime={} of song: "{}" doesn\'t enclose any syllable.'
                .format(syl_starttime, syl_endtime, song_name))
            continue

        real_syl_starttime = el_rows[0]['starttime']
        real_syl_endtime = utils.get_syllable_end_time(el_rows)

        syllable = (real_syl_starttime, real_syl_endtime)

        if song_name not in songs_2_syllables:
            syllables = []
            songs_2_syllables[song_name] = syllables
        syllables.append(syllable)

    # delete all existing manual segmentation:
    Segment.objects.filter(
        audio_file__name__in=songs_2_syllables.keys()).delete()

    bar = Bar('Importing syllables ...', max=len(songs_2_syllables))
    for song in songs_2_syllables:
        syllables = songs_2_syllables[song]
        audio_file = AudioFile.objects.filter(name=song).first()
        if audio_file is None:
            warning(
                'File {} has not been imported. Please run import_luscinia_songs again.'
                ' Ignore for now'.format(song))
            continue

        for syllable in syllables:
            segment = Segment()
            segment.start_time_ms = syllable[0]
            segment.end_time_ms = syllable[1]
            segment.audio_file = audio_file
            segment.save()
            segment.tid = segment.id
            segment.save()

        # print('Processed song {}'.format(song))
        bar.next()
    bar.finish()
Exemplo n.º 2
0
def import_signal_mask(conn):
    """
    Export pictures of the syllable with fundamentals
    :param conn:
    :return:
    """
    cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
    cur.execute('select id, name, maxfreq, dy from songdata s')

    songs_data = cur.fetchall()
    song_info = {}

    for song in songs_data:
        song_name = song['name']
        song_info[song_name] = (song['id'], song['maxfreq'], song['dy'])

    segments_info = Segment.objects \
        .filter(audio_file__name__in=song_info.keys()) \
        .values_list('id', 'audio_file__name', 'start_time_ms', 'end_time_ms')

    n = len(segments_info)
    bar = Bar('Importing segments ...', max=n)

    for seg_id, song_name, start, end in segments_info:
        if song_name not in song_info:
            continue
        song_id, nyquist, fbin = song_info[song_name]

        cur.execute(
            'select starttime, endtime, songid from syllable where songid={} and starttime<={} and endtime>={}'
            ' order by starttime'.format(song_id, start, end))
        syl_rows = cur.fetchall()

        if len(syl_rows) == 0:
            warning('Song #{} {} doesn\'t have a syllable at position {}:{}'.
                    format(song_id, song_name, start, end))
            continue

        if len(syl_rows) > 1:
            warning(
                'Song #{} {} has more than one syllable at position {}:{}. Db Syllable #{}'
                .format(song_id, song_name, start, end, seg_id))

        for syl_idx, syl_row in enumerate(syl_rows):
            syl_starttime = syl_row['starttime']
            syl_endtime = syl_row['endtime']

            cur.execute(
                'select starttime, timelength, fundfreq, gapbefore, gapafter, maxf, dy,'
                'overallpeakfreq1, overallpeakfreq2, signal '
                'from element where songid={} and starttime >= {} and (starttime + timelength) <= {}'
                .format(song_id, syl_starttime, syl_endtime))
            el_rows = cur.fetchall()

            if len(el_rows) == 0:
                warning(
                    'Syllable #{} starttime={} endtime={} of song: "{}" doesn\'t enclose any syllable.'
                    .format(1, syl_starttime, syl_endtime, song_name))
                continue

            syl_starttime = el_rows[0]['starttime']
            syl_endtime = get_syllable_end_time(el_rows)

            if nyquist == 0:
                nyquist = el_rows[0]['maxf']
            if fbin == 0:
                fbin = el_rows[0]['dy']

            width = int(syl_endtime - syl_starttime) + 1
            height = int(nyquist / fbin)

            img_data_rgb = np.ones((height, width, 3), dtype=np.uint8) * 255

            syl_max_ff = 0
            syl_min_ff = 999999
            syl_combined_ff = None

            for el_idx, el in enumerate(el_rows):
                signal = list(map(int, el['signal'].strip().split(' ')))
                fundfreq = np.array(el['fundfreq'].strip().split(' '),
                                    dtype='|S32').astype(np.float)
                el_max_ff = fundfreq[0]
                el_min_ff = fundfreq[1]

                # the first 4 numbers of fundfreq are: max, min, ? (no idea) and ? (no idea), so we ignore them
                fundfreq = fundfreq[4:]
                if el_idx == 0:
                    syl_combined_ff = fundfreq
                else:
                    syl_combined_ff = np.concatenate(
                        (syl_combined_ff, fundfreq))

                fundfreq = (fundfreq / nyquist * height).astype(np.int)

                i = 0
                ff_row_idx = 0
                while i < len(signal):
                    num_data = signal[i]
                    img_col_idx = signal[i + 1] - syl_starttime

                    # Draw the mask
                    for j in range(2, num_data, 2):
                        _signal_segment_end = signal[i + j]
                        _signal_segment_start = signal[i + j + 1]
                        img_data_rgb[_signal_segment_start:_signal_segment_end, img_col_idx, :] \
                            = COLOURS[el_idx % len(COLOURS)]

                    # Add the fundamental (red lines)
                    if ff_row_idx < len(fundfreq):
                        img_row_idx = height - fundfreq[ff_row_idx] - 1

                        img_row_idx_padded_low = max(0, img_row_idx - 2)
                        img_row_idx_padded_high = img_row_idx + 4 - (
                            img_row_idx - img_row_idx_padded_low)
                        img_data_rgb[
                            img_row_idx_padded_low:img_row_idx_padded_high,
                            img_col_idx, :] = FF_COLOUR
                    ff_row_idx += 1
                    i += (num_data + 1)

                syl_max_ff = max(syl_max_ff, el_max_ff)
                syl_min_ff = min(syl_min_ff, el_min_ff)
            syl_mean_ff = np.mean(syl_combined_ff)

            Segment.objects.filter(id=seg_id).update(mean_ff=syl_mean_ff)
            Segment.objects.filter(id=seg_id).update(max_ff=syl_max_ff)
            Segment.objects.filter(id=seg_id).update(min_ff=syl_min_ff)

            img = Image.fromarray(img_data_rgb)
            thumbnail_width = int(img.size[0])
            thumbnail_height = int(img.size[1] * 0.3)

            img = img.resize((thumbnail_width, thumbnail_height))

            if syl_idx > 0:
                warning('Syl_idx > 0')
                file_path = spect_mask_path('{}_{}'.format(seg_id, syl_idx))
            else:
                file_path = spect_mask_path(seg_id)
            ensure_parent_folder_exists(file_path)

            img.save(file_path, format='PNG')
        bar.next()
    bar.finish()