Ejemplo n.º 1
0
def save_history(request):
    """
    Save a copy of all ExtraAttrValue (labels, notes, ...) in a HistoryEntry
    :param request: must specify a comment to store with this copy
    :return: name of the zip file created
    :version: 2.0.0
    """
    version = 4
    user = request.user

    comment = get_or_error(request.POST, 'comment')
    database_id = get_or_error(request.POST, 'database')
    backup_type = get_or_error(request.POST, 'type')

    database = get_or_error(Database, dict(id=database_id))
    assert_permission(user, database, DatabasePermission.VIEW)
    assert_values(backup_type, ['labels', 'segmentation'])

    meta = dict(database=database_id,
                user=user.id,
                time=timezone.now(),
                version=version,
                note=comment,
                type=backup_type)

    zip_buffer = io.BytesIO()
    with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_BZIP2,
                         False) as zip_file:
        zip_file.writestr('meta.json', json.dumps(meta))
        zip_file.writestr('root.extraattrvalue.json',
                          'here for checking purpose')

        if backup_type == 'labels':
            save_label_history(database, user, zip_file)
        else:
            save_segmentation_history(database, user, zip_file)

    binary_content = zip_buffer.getvalue()

    he = HistoryEntry.objects.create(user=user,
                                     time=timezone.now(),
                                     database=database,
                                     version=version,
                                     note=comment,
                                     type=backup_type)
    filename = he.filename
    filepath = history_path(filename)
    ensure_parent_folder_exists(filepath)

    with open(filepath, 'wb') as f:
        f.write(binary_content)

    tz_offset = request.session['detected_tz']
    tz = offset_to_timezone(tz_offset)

    _, rows = bulk_get_history_entries([he],
                                       DotMap(user=user,
                                              database=database_id,
                                              tz=tz))
    return rows[0]
    def handle(self, *args, **options):

        tensor_to_dm = {}
        for tensor in FullTensorData.objects.all():
            sids_path = tensor.get_sids_path()
            bytes_path = tensor.get_bytes_path()
            cols_path = tensor.get_cols_path()

            sids = bytes_to_ndarray(sids_path, np.int32)
            data = get_rawdata_from_binary(bytes_path, len(sids))

            dm = DataMatrix.objects.filter(name=tensor.name).first()
            if dm is None:
                dm = DataMatrix.objects.create(
                    database=tensor.database,
                    name=tensor.name,
                    features_hash=tensor.features_hash,
                    aggregations_hash=tensor.aggregations_hash,
                    ndims=data.shape[1])

            dm_sids_path = dm.get_sids_path()
            dm_bytes_path = dm.get_bytes_path()
            dm_cols_path = dm.get_cols_path()

            ensure_parent_folder_exists(dm_sids_path)

            shutil.copy(sids_path, dm_sids_path)
            shutil.copy(bytes_path, dm_bytes_path)
            shutil.copy(cols_path, dm_cols_path)

            tensor_to_dm[tensor] = dm

        for tensor in DerivedTensorData.objects.exclude(dimreduce='none'):
            dm = tensor_to_dm[tensor.full_tensor]
            sids_path = tensor.full_tensor.get_sids_path()
            bytes_path = tensor.get_bytes_path()

            if not os.path.exists(bytes_path):
                bytes_path = tensor.full_tensor.get_bytes_path()

            method = tensor.dimreduce
            ndims = tensor.ndims
            if method.startswith('tsne'):
                ndims = int(method[4:])
                method = 'tsne'

            ord = Ordination.objects.filter(dm=dm, method=method,
                                            ndims=ndims).first()
            if ord is None:
                ord = Ordination.objects.create(dm=dm,
                                                method=method,
                                                ndims=ndims)

            ord_sids_path = ord.get_sids_path()
            ord_bytes_path = ord.get_bytes_path()

            ensure_parent_folder_exists(ord_sids_path)

            shutil.copy(sids_path, ord_sids_path)
            shutil.copy(bytes_path, ord_bytes_path)
def rearrange_spectrogram(apps, schema_editor):
    """
    """
    current_spect_dir = os.path.join(settings.MEDIA_URL, 'spect', 'fft',
                                     'syllable')[1:]
    current_abs_spect_dir = os.path.join(settings.BASE_DIR, current_spect_dir)

    if os.path.isdir(current_abs_spect_dir):
        spect_files = os.listdir(current_abs_spect_dir)
        sys.stdout.write('\n')
        sys.stdout.write('\tFound {} spectrograms'.format(len(spect_files)))
        sys.stdout.flush()

        for spect_file in spect_files:
            try:
                tid = int(spect_file[:-4])
            except ValueError:
                warning('\tFile {} is not named correctly and will be deleted'.
                        format(spect_file))
                continue

            current_path = current_abs_spect_dir + '/' + str(tid) + '.png'
            new_path = get_abs_spect_path(tid)

            try:
                shutil.move(current_path, new_path)
            except FileNotFoundError:
                ensure_parent_folder_exists(new_path)
                shutil.move(current_path, new_path)

        shutil.rmtree(current_abs_spect_dir)
Ejemplo n.º 4
0
def convert(conversion_scheme, print_stats=True):
    wav_file_path = conversion_scheme['wav']
    if not os.path.isfile(wav_file_path):
        warning('File {} does not exist, skip.'.format(wav_file_path))
        return

    fmt, filepath = conversion_scheme['other']

    wav_audio = None

    if not os.path.isfile(filepath):
        ensure_parent_folder_exists(filepath)
        wav_audio = pydub.AudioSegment.from_file(wav_file_path)
        wav_audio.export(filepath, format=fmt)

    if print_stats:
        if wav_audio is None:
            wav_audio = pydub.AudioSegment.from_file(wav_file_path)
        wav_size = os.path.getsize(wav_file_path) / 1024 / 1024
        wav_length = len(wav_audio.raw_data) // wav_audio.frame_width
        wav_fs = wav_audio.frame_rate
        file_size = os.path.getsize(filepath) / 1024 / 1024

        converted_file = pydub.AudioSegment.from_file(filepath)
        file_length = len(
            converted_file.raw_data) // converted_file.frame_width
        file_fs = converted_file.frame_rate

        print('Wav size: {:6.2f}, {} size: {:6.2f}'.format(
            wav_size, fmt, file_size))
        print('Wav length: {:6.2f}, {} length: {:6.2f}'.format(
            wav_length, fmt, file_length))
        print('Wav fs: {:6.2f}, {} fs: {:6.2f}'.format(wav_fs, fmt, file_fs))
def extract_spectrogram(audio_file_id):
    """
    Extract raw sepectrograms for all segments (Not the masked spectrogram from Luscinia) of an audio file
    :param audio_file:
    :return:
    """
    audio_file = AudioFile.objects.get(id=audio_file_id)
    segs_info = Segment.objects.filter(audio_file=audio_file).values_list(
        'tid', 'start_time_ms', 'end_time_ms')

    missing_segs_info = []

    for tid, start, end in segs_info:
        seg_spect_path = spect_fft_path(tid, 'syllable')
        ensure_parent_folder_exists(seg_spect_path)
        if not os.path.isfile(seg_spect_path):
            missing_segs_info.append((seg_spect_path, start, end))

    if len(missing_segs_info) > 0:
        filepath = wav_path(audio_file)

        fs, sig = wav_2_mono(filepath)
        duration_ms = len(sig) * 1000 / fs

        _, _, s = signal.stft(sig,
                              fs=fs,
                              window=window,
                              noverlap=noverlap,
                              nfft=window_size,
                              return_onesided=True)
        file_spect = np.abs(s * scale)

        height, width = np.shape(file_spect)
        file_spect = np.flipud(file_spect)

        file_spect = np.log10(file_spect)
        file_spect = ((file_spect - global_min_spect_pixel) / interval64)
        file_spect[np.isinf(file_spect)] = 0
        file_spect = file_spect.astype(np.int)

        file_spect = file_spect.reshape((width * height, ), order='C')
        file_spect[file_spect >= 64] = 63
        file_spect_rgb = np.empty((height, width, 3), dtype=np.uint8)
        file_spect_rgb[:, :, 0] = cm_red[file_spect].reshape(
            (height, width)) * 255
        file_spect_rgb[:, :, 1] = cm_green[file_spect].reshape(
            (height, width)) * 255
        file_spect_rgb[:, :, 2] = cm_blue[file_spect].reshape(
            (height, width)) * 255

        for path, start, end in missing_segs_info:
            roi_start = int(start / duration_ms * width)
            roi_end = int(np.ceil(end / duration_ms * width))

            seg_spect_rgb = file_spect_rgb[:, roi_start:roi_end, :]
            seg_spect_img = Image.fromarray(seg_spect_rgb)

            seg_spect_img.save(path, format='PNG')
Ejemplo n.º 6
0
def store_feature_values(ids, feature, values_arr):
    index_filename = data_path('binary/features',
                               '{}.idx'.format(feature.name),
                               for_url=False)
    value_filename = data_path('binary/features',
                               '{}.val'.format(feature.name),
                               for_url=False)

    ensure_parent_folder_exists(index_filename)
    binstorage.store(ids, values_arr, index_filename, value_filename)
Ejemplo n.º 7
0
def extract_spectrogram(audio_file, segs_info):
    """
    Extract raw sepectrograms for all segments (Not the masked spectrogram from Luscinia) of an audio file
    :param audio_file:
    :return:
    """
    filepath = wav_path(audio_file)

    fs, duration = get_wav_info(filepath)
    if not os.path.isfile(filepath):
        raise CustomAssertionError("File {} not found".format(audio_file.name))

    for tid, start, end in segs_info:
        seg_spect_path = get_abs_spect_path(tid)
        ensure_parent_folder_exists(seg_spect_path)

        sig = read_segment(filepath,
                           beg_ms=start,
                           end_ms=end,
                           mono=True,
                           normalised=True,
                           return_fs=False,
                           retype=True,
                           winlen=window_size)
        _, _, s = signal.stft(sig,
                              fs=fs,
                              window=window,
                              noverlap=noverlap,
                              nfft=window_size,
                              return_onesided=True)
        spect = np.abs(s * scale)

        height, width = np.shape(spect)
        spect = np.flipud(spect)

        spect = np.log10(spect)
        spect = ((spect - global_min_spect_pixel) / interval64)
        spect[np.isinf(spect)] = 0
        spect = spect.astype(np.int)

        spect = spect.reshape((width * height, ), order='C')
        spect[spect >= 64] = 63
        spect_rgb = np.empty((height, width, 3), dtype=np.uint8)
        spect_rgb[:, :, 0] = cm_red[spect].reshape((height, width)) * 255
        spect_rgb[:, :, 1] = cm_green[spect].reshape((height, width)) * 255
        spect_rgb[:, :, 2] = cm_blue[spect].reshape((height, width)) * 255

        # roi_start = int(start / duration_ms * width)
        # roi_end = int(np.ceil(end / duration_ms * width))

        # seg_spect_rgb = file_spect_rgb[:, roi_start:roi_end, :]
        seg_spect_img = Image.fromarray(spect_rgb)

        seg_spect_img.save(seg_spect_path, format='PNG')
        celerylogger.info('spectrogram {} created'.format(seg_spect_path))
Ejemplo n.º 8
0
def import_pcm(song, cur, audio_file, wav_file_path=None, compressed_url=None):
    if wav_file_path is None:
        wav_file_path = wav_path(audio_file)
    if compressed_url is None:
        compressed_url = audio_path(audio_file,
                                    settings.AUDIO_COMPRESSED_FORMAT)

    if not os.path.isfile(wav_file_path):
        # print('Importing {}'.format(song_name))
        song_id = song['songid']
        cur.execute('select wav from wavs where songid={};'.format(song_id))

        data = cur.fetchone()
        raw_pcm = str_to_bytes(data[0])

        nchannels = song['stereo']
        bitrate = int(song['ssizeinbits'])
        fs = int(song['samplerate'])

        byte_per_frame = int(bitrate / 8)
        nframes_all_channel = int(len(raw_pcm) / byte_per_frame)
        nframes_per_channel = int(nframes_all_channel / nchannels)
        length = nframes_per_channel
        ensure_parent_folder_exists(wav_file_path)

        if bitrate == 24:
            array1 = np.frombuffer(raw_pcm, dtype=np.ubyte)
            array2 = array1.reshape((nframes_per_channel, nchannels,
                                     byte_per_frame)).astype(np.uint8)
            wf.write_24b(wav_file_path, fs, array2)
        else:
            data = array.array('i', raw_pcm)
            sound = pydub.AudioSegment(data=data,
                                       sample_width=byte_per_frame,
                                       frame_rate=fs,
                                       channels=nchannels)
            sound.export(wav_file_path, 'wav')
    else:
        fs, length = get_wav_info(wav_file_path)

    if not os.path.isfile(compressed_url):
        ensure_parent_folder_exists(compressed_url)
        sound = pydub.AudioSegment.from_wav(wav_file_path)
        sound.export(compressed_url, format=settings.AUDIO_COMPRESSED_FORMAT)

    return fs, length
def write_metadata(metadata, sids, headers, filename=None):
    if filename:
        ensure_parent_folder_exists(filename)
        output_stream = open(filename, 'w', encoding='utf-8')
    else:
        output_stream = io.StringIO()

    output_stream.write('\t'.join(headers))
    output_stream.write('\n')
    for sid in sids:
        row = metadata[sid]
        output_stream.write('\n')
        output_stream.write('\t'.join(row))

    if not filename:
        content = output_stream.getvalue()
        output_stream.close()
        return content
    def save(self, *args, **kwargs):
        """
        Save the object and then use its ID to store a pickle file contaning all the attrs as declared
        Pickle file will be stored in user_data/pickle/<class name>/
        :param args:
        :param kwargs:
        :return: None
        """
        super(PicklePersistedModel, self).save(*args, **kwargs)

        fpath = pickle_path(self.id, self.__class__.__name__)
        ensure_parent_folder_exists(fpath)

        mdict = {}
        for attr in self._meta.attrs:
            mdict[attr] = getattr(self, attr)

        with open(fpath, 'wb') as f:
            pickle.dump(mdict, f, pickle.HIGHEST_PROTOCOL)
Ejemplo n.º 11
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 '
                '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()
Ejemplo n.º 12
0
def create_database(request):
    user = request.user
    name = get_or_error(request.POST, 'new-database-name')
    nfft = int(get_or_error(request.POST, 'new-database-fft'))
    noverlap = int(get_or_error(request.POST, 'new-database-overlap'))
    hpf = int(get_or_error(request.POST, 'new-database-hpf'))
    lpf = request.POST.get('new-database-lpf')

    errors = {}

    if not re.match('^[a-zA-Z0-9_-]+$', name):
        errors[
            'new-database-name-error'] = 'Name can only contain alphabets, numbers, dashes and underscores'

    if Database.objects.filter(name__iexact=name).exists():
        errors[
            'new-database-name-error'] = 'Database with name {} already exists.'.format(
                name)

    if lpf:
        lpf = int(lpf)
        if lpf <= hpf:
            errors[
                'new-database-lpf-error'] = 'Low pass filter value must be > high pass value'
    else:
        lpf = None

    has_errors = len(errors) > 0

    if not has_errors:

        database = Database(name=name,
                            nfft=nfft,
                            noverlap=noverlap,
                            hpf=hpf,
                            lpf=lpf)
        database.save()
        dbid = database.id

        media_dir = settings.MEDIA_URL[1:]
        new_wav_dir = os.path.join(settings.BASE_DIR, media_dir, 'audio',
                                   'wav', str(dbid))
        new_compressed_dir = os.path.join(settings.BASE_DIR, media_dir,
                                          'audio',
                                          settings.AUDIO_COMPRESSED_FORMAT,
                                          str(database.id))

        ensure_parent_folder_exists(new_wav_dir)
        ensure_parent_folder_exists(new_compressed_dir)
        os.mkdir(new_wav_dir)
        os.mkdir(new_compressed_dir)

        # Now assign this database to this user, and switch the working database to this new one
        da = DatabaseAssignment(user=user,
                                database=database,
                                permission=DatabasePermission.ASSIGN_USER)
        da.save()

        permission_str = DatabasePermission.get_name(
            DatabasePermission.ASSIGN_USER)

        noverlap = nfft * noverlap // 100
        payload = dict(id=dbid,
                       name=name,
                       permission=permission_str,
                       nfft=nfft,
                       overlap=noverlap,
                       hpf=hpf,
                       lpf=lpf)

    else:
        payload = errors

    return dict(origin='create_database',
                success=not has_errors,
                warning=None,
                payload=payload)
    def handle(self, *args, **options):
        database_name = options['database_name']
        annotator_name = options['annotator_name']
        label_level = options['label_level']
        save_to = options['save_to']
        format = options['format']
        min_occur = options['min_occur']
        num_instances = options['num_instances']
        normalised = options['normalised']

        if num_instances is not None:
            assert num_instances >= min_occur, 'num_instances must be >= min_occur'

        database = get_or_error(Database, dict(name__iexact=database_name))
        annotator = get_or_error(User, dict(username__iexact=annotator_name))
        segments = Segment.objects.filter(audio_file__database=database)

        sids = np.array(list(segments.order_by('id').values_list('id', flat=True)))

        labels, no_label_ids = get_labels_by_sids(sids, label_level, annotator, min_occur)
        if len(no_label_ids) > 0:
            sids, _, labels = exclude_no_labels(sids, None, labels, no_label_ids)

        if num_instances:
            sids, _, labels = select_instances(sids, None, labels, num_instances)

        unique_labels, enum_labels = np.unique(labels, return_inverse=True)
        fold_indices = get_kfold_indices(enum_labels, min_occur)

        segments_info = {sid: (label, label_enum, fold_ind) for sid, label, label_enum, fold_ind in
                         zip(sids, labels, enum_labels, fold_indices)}

        segs = Segment.objects.filter(id__in=sids)

        audio_file_dict = {}
        for seg in segs:
            af = seg.audio_file
            if af in audio_file_dict:
                info = audio_file_dict[af]
            else:
                info = []
                audio_file_dict[af] = info
            info.append((seg.id, seg.start_time_ms, seg.end_time_ms))

        audio_info = []

        bar = Bar('Exporting segments ...', max=len(segs))
        metadata_file_path = os.path.join(save_to, 'metadata.tsv')

        extractor = extractors.get(format, None)

        for af, info in audio_file_dict.items():
            wav_file_path = wav_path(af)
            fullwav = pydub.AudioSegment.from_wav(wav_file_path)

            for id, start, end in info:
                label, label_enum, fold_ind = segments_info[id]

                audio_segment = fullwav[start: end]

                filename = '{}.{}'.format(id, format)

                filepath = os.path.join(save_to, filename)
                ensure_parent_folder_exists(filepath)

                if not os.path.isfile(filepath):
                    if extractor is not None:
                        extractor(wav_file_path, af.fs, start, end, filepath)
                    else:
                        with open(filepath, 'wb') as f:
                            audio_segment.export(f, format=format)

                audio_info.append(
                    (id, filename, label, label_enum, fold_ind)
                )

                bar.next()

        with open(metadata_file_path, 'w') as f:
            f.write('id\tfilename\tlabel\tlabel_enum\tfold\n')
            for id, filename, label, label_enum, fold_ind in audio_info:
                f.write('{}\t{}\t{}\t{}\t{}\n'.format(id, filename, label, label_enum, fold_ind))

        bar.finish()

        if normalised:
            norm_folder = os.path.join(save_to, 'normalised')
            mkdirp(norm_folder)
            global_min, global_max = extract_global_min_max(save_to, format)
            save_global_min_max(norm_folder, global_min, global_max)
            normalise_all(save_to, norm_folder, format, global_min, global_max)
Ejemplo n.º 14
0
def _import_and_convert_audio_file(database,
                                   file,
                                   max_fs,
                                   real_fs=None,
                                   audio_file=None,
                                   track=None,
                                   start=None,
                                   end=None):

    file_already_exists = False
    if isinstance(file, BufferedWriter):
        file_already_exists = True
        name_ext = os.path.basename(file.name)
    else:
        name_ext = file.name

    if name_ext.lower().endswith('.wav'):
        name_no_ext = name_ext[:-4]
    else:
        name_no_ext = name_ext

    # Need a unique name (database-wide) for new file
    if audio_file is None:
        is_unique = not AudioFile.objects.filter(database=database,
                                                 name=name_no_ext).exists()
        if not is_unique:
            raise CustomAssertionError(
                'File {} already exists'.format(name_no_ext))
    elif audio_file.name != name_no_ext:
        raise CustomAssertionError(
            'Impossible! File name in your table and in the database don\'t match'
        )

    wav_name = data_path('audio/wav/{}'.format(database.id),
                         '{}.wav'.format(name_no_ext))
    name_compressed = data_path(
        'audio/{}/{}'.format(settings.AUDIO_COMPRESSED_FORMAT, database.id),
        '{}.{}'.format(name_no_ext, settings.AUDIO_COMPRESSED_FORMAT))

    fake_wav_name = wav_name + '.bak'

    if not file_already_exists:
        with open(wav_name, 'wb') as wav_file:
            wav_file.write(file.read())

    _fs, length, noc = get_wav_info(wav_name, return_noc=True)

    # If real_fs is provided, it is absolute -- otherwise it is what we can really read from the file
    if real_fs is None:
        real_fs = _fs

    fake_fs = None
    # If real_fs is not what we read from the file, then the file is fake, and we must restore the original file
    # to do that we rename the wav file that we just stored (which is fake) to .bak, then change the sample rate
    # back to the original and store the original file as .wav
    if real_fs != _fs:
        os.rename(wav_name, fake_wav_name)
        change_fs_without_resampling(fake_wav_name, real_fs, wav_name)
        audio = pydub.AudioSegment.from_file(fake_wav_name)
        os.remove(fake_wav_name)

    # Otherwise, if real_fs is more than max_fs, we must create a fake file for the sake of converting to mp3:
    elif real_fs > max_fs:
        fake_fs = max_fs
        change_fs_without_resampling(wav_name, fake_fs, fake_wav_name)
        audio = pydub.AudioSegment.from_file(fake_wav_name)
        os.remove(fake_wav_name)
    # Otherwise the file is ordinary - no need to fake it
    else:
        audio = pydub.AudioSegment.from_file(wav_name)

    ensure_parent_folder_exists(name_compressed)
    audio.export(name_compressed, format=settings.AUDIO_COMPRESSED_FORMAT)

    if audio_file is None:
        if track is None:
            track = AudioTrack.objects.get_or_create(name='TBD')[0]
        individual = Individual.objects.get_or_create(name='TBD')[0]
        audio_file = AudioFile(name=name_no_ext,
                               length=length,
                               fs=real_fs,
                               database=database,
                               track=track,
                               start=start,
                               end=end,
                               fake_fs=fake_fs,
                               added=timezone.now(),
                               noc=noc,
                               individual=individual)
        audio_file.save()
        if track.name == 'TBD':
            track.name = str(audio_file.id)
            track.save()
        individual.name = str(audio_file.id)
        individual.save()
    else:
        audio_file.start = start
        audio_file.end = end
        audio_file.length = length
        audio_file.save()

    return audio_file
def write_config(config, config_file):
    ensure_parent_folder_exists(config_file)

    with open(config_file, 'w+') as f:
        json.dump(config, f, ensure_ascii=False, indent=4)
def ndarray_to_bytes(arr, filename):
    assert isinstance(arr, np.ndarray)

    ensure_parent_folder_exists(filename)
    with open(filename, 'wb') as f:
        arr.tofile(f)
Ejemplo n.º 17
0
def extract_spectrogram():
    """
    Extract raw sepectrograms for all segments (Not the masked spectrogram from Luscinia)
    :return:
    """
    audio_to_segs = {}
    for segment in Segment.objects.all():
        audio_file = segment.audio_file
        if audio_file not in audio_to_segs:
            audio_to_segs[audio_file] = [(segment.id, segment.start_time_ms,
                                          segment.end_time_ms)]
        else:
            audio_to_segs[audio_file].append(
                (segment.id, segment.start_time_ms, segment.end_time_ms))

    n = len(audio_to_segs)
    bar = Bar('Exporting spects ...', max=n)

    for audio_file, seg_list in audio_to_segs.items():
        count = 0
        for seg_id, start, end in seg_list:
            seg_spect_path = spect_fft_path(seg_id, 'syllable')
            if os.path.isfile(seg_spect_path):
                count += 1
        if count == len(seg_list):
            bar.next()
            continue

        filepath = wav_path(audio_file)

        fs, sig = wav_2_mono(filepath)
        duration_ms = len(sig) * 1000 / fs

        _, _, s = signal.stft(sig,
                              fs=fs,
                              window=window,
                              noverlap=noverlap,
                              nfft=window_size,
                              return_onesided=True)
        file_spect = np.abs(s * scale)

        height, width = np.shape(file_spect)
        file_spect = np.flipud(file_spect)

        try:

            file_spect = np.log10(file_spect)
            file_spect = ((file_spect - global_min_spect_pixel) / interval64)
            file_spect[np.isinf(file_spect)] = 0
            file_spect = file_spect.astype(np.int)

            file_spect = file_spect.reshape((width * height, ), order='C')
            file_spect[file_spect >= 64] = 63
            file_spect_rgb = np.empty((height, width, 3), dtype=np.uint8)
            file_spect_rgb[:, :, 0] = cm_red[file_spect].reshape(
                (height, width)) * 255
            file_spect_rgb[:, :, 1] = cm_green[file_spect].reshape(
                (height, width)) * 255
            file_spect_rgb[:, :, 2] = cm_blue[file_spect].reshape(
                (height, width)) * 255

            file_spect_img = Image.fromarray(file_spect_rgb)
            file_spect_path = spect_fft_path(audio_file.id, 'song')
            ensure_parent_folder_exists(file_spect_path)
            if not os.path.isfile(file_spect_path):
                file_spect_img.save(file_spect_path, format='PNG')

            for seg_id, start, end in seg_list:
                roi_start = int(start / duration_ms * width)
                roi_end = int(np.ceil(end / duration_ms * width))

                seg_spect_rgb = file_spect_rgb[:, roi_start:roi_end, :]
                seg_spect_img = Image.fromarray(seg_spect_rgb)
                seg_spect_path = spect_fft_path(seg_id, 'syllable')
                ensure_parent_folder_exists(seg_spect_path)

                if not os.path.isfile(seg_spect_path):
                    seg_spect_img.save(seg_spect_path, format='PNG')

        except Exception as e:
            warning('Error occured at song id: {}'.format(audio_file.id))
            raise e

        bar.next()
    bar.finish()
Ejemplo n.º 18
0
def extract_database_measurements(arg=None, force=False):
    if isinstance(arg, int):
        task = get_or_wait(arg)
    else:
        task = arg
    runner = TaskRunner(task)
    try:
        runner.preparing()

        if isinstance(task, Task):
            cls, dm_id = task.target.split(':')
            dm_id = int(dm_id)
            assert cls == DataMatrix.__name__
            dm = DataMatrix.objects.get(id=dm_id)

            if dm.database:
                segments = Segment.objects.filter(
                    audio_file__database=dm.database)
                sids = segments.values_list('id', flat=True)
            else:
                sids = dm.tmpdb.ids
            features_hash = dm.features_hash
            aggregations_hash = dm.aggregations_hash
        else:
            sids = task.sids
            features_hash = task.features_hash
            aggregations_hash = task.aggregations_hash

        features = Feature.objects.filter(id__in=features_hash.split('-'))
        aggregations = Aggregation.objects.filter(
            id__in=aggregations_hash.split('-'))
        aggregators = [aggregator_map[x.name] for x in aggregations]

        # feature to binstorage's files
        f2bs = {}
        # feature+aggregation to binstorage's files
        fa2bs = {}

        for feature in features:
            feature_name = feature.name
            index_filename = data_path('binary/features',
                                       '{}.idx'.format(feature_name),
                                       for_url=False)
            value_filename = data_path('binary/features',
                                       '{}.val'.format(feature_name),
                                       for_url=False)
            f2bs[feature] = (index_filename, value_filename)

            if feature not in fa2bs:
                fa2bs[feature] = {}

            for aggregator in aggregators:
                aggregator_name = aggregator.get_name()
                folder = os.path.join('binary', 'features', feature_name)
                mkdirp(os.path.join(settings.MEDIA_URL, folder)[1:])

                index_filename = data_path(folder,
                                           '{}.idx'.format(aggregator_name),
                                           for_url=False)
                value_filename = data_path(folder,
                                           '{}.val'.format(aggregator_name),
                                           for_url=False)
                fa2bs[feature][aggregator] = (index_filename, value_filename)

        tids, f2tid2fvals = extract_segment_features_for_segments(
            runner, sids, features, f2bs, force)

        for feature, (index_filename, value_filename) in f2bs.items():
            _tids, _fvals = f2tid2fvals.get(feature, (None, None))
            if _tids:
                _tids = np.array(_tids, dtype=np.int32)
                ensure_parent_folder_exists(index_filename)
                binstorage.store(_tids, _fvals, index_filename, value_filename)

        runner.wrapping_up()
        child_task = task.__class__(user=task.user, parent=task)
        child_task.save()
        child_runner = TaskRunner(child_task)
        child_runner.preparing()

        aggregate_feature_values(child_runner, sids, f2bs, fa2bs, features,
                                 aggregators)
        child_runner.complete()

        if isinstance(task, Task):
            full_sids_path = dm.get_sids_path()
            full_bytes_path = dm.get_bytes_path()
            full_cols_path = dm.get_cols_path()

            data, col_inds = extract_rawdata(f2bs, fa2bs, tids, features,
                                             aggregators)

            ndarray_to_bytes(data, full_bytes_path)
            ndarray_to_bytes(np.array(sids, dtype=np.int32), full_sids_path)

            with open(full_cols_path, 'w', encoding='utf-8') as f:
                json.dump(col_inds, f)

            dm.ndims = data.shape[1]
            dm.save()
        runner.complete()

    except Exception as e:
        runner.error(e)
Ejemplo n.º 19
0
def import_audio_file(request):
    """
    Store uploaded file (only wav is accepted)
    :param request: must contain a list of files and the id of the database to be stored against
    :return:
    """
    user = request.user
    f = request.FILES['file']

    database_id = get_or_error(request.POST, 'database-id')
    item = json.loads(get_or_error(request.POST, 'item'))
    track_id = get_or_error(request.POST, 'track-id')

    database = get_or_error(Database, dict(id=database_id))
    track = get_or_error(AudioTrack, dict(id=track_id))
    assert_permission(user, database, DatabasePermission.ADD_FILES)

    start = item['start']
    end = item['end']
    song_id = item['id']

    file = File(file=f)
    name = file.name
    if name.lower().endswith('.wav'):
        name = name[:-4]

    audio_file = None
    need_unique_name = True
    if not isinstance(song_id, str) or not song_id.startswith('new:'):
        audio_file = AudioFile.objects.filter(id=song_id).first()
        if audio_file and audio_file.name == name:
            need_unique_name = False

    if need_unique_name:
        is_unique = not AudioFile.objects.filter(database=database,
                                                 name=name).exists()
        if not is_unique:
            raise CustomAssertionError('File {} already exists'.format(name))

    name_wav = data_path('audio/wav/{}'.format(database.id),
                         '{}.wav'.format(name))
    name_compressed = data_path(
        'audio/{}/{}'.format(settings.AUDIO_COMPRESSED_FORMAT, database.id),
        '{}.{}'.format(name, settings.AUDIO_COMPRESSED_FORMAT))

    with open(name_wav, 'wb') as wav_file:
        wav_file.write(file.read())

    audio = pydub.AudioSegment.from_file(name_wav)

    ensure_parent_folder_exists(name_compressed)
    audio.export(name_compressed, format=settings.AUDIO_COMPRESSED_FORMAT)
    fs = audio.frame_rate
    length = audio.raw_data.__len__() // audio.frame_width

    if audio_file is None:
        audio_file = AudioFile(name=name,
                               length=length,
                               fs=fs,
                               database=database,
                               track=track,
                               start=start,
                               end=end)
    else:
        if audio_file.name != name:
            AudioFile.set_name([audio_file], name)
        audio_file.start = start
        audio_file.end = end
        audio_file.length = length
        audio_file.save()

    quality = item.get('quality', None)
    individual_name = item.get('individual', None)
    note = item.get('note', None)
    type = item.get('type', None)
    sex = item.get('sex', None)

    if individual_name is not None:
        individual = Individual.objects.filter(name=individual_name).first()
        if individual is None:
            individual = Individual.objects.create(name=individual_name,
                                                   gender=sex)
        elif sex is not None:
            individual.gender = sex
            individual.save()

        audio_file.individual = individual

    if quality:
        audio_file.quality = quality

    audio_file.save()
    audio_file_attrs = settings.ATTRS.audio_file
    if note:
        extra_attr_value = ExtraAttrValue.objects.filter(
            user=user, owner_id=audio_file.id, attr=audio_file_attrs.note)
        extra_attr_value.value = note

    if type:
        extra_attr_value = ExtraAttrValue.objects.create(
            user=user, owner_id=audio_file.id, attr=audio_file_attrs.type)
        extra_attr_value.value = type

    return dict(id=audio_file.id, name=audio_file.name)
Ejemplo n.º 20
0
def import_audio_files(request):
    """
    Store uploaded files (only wav is accepted)
    :param request: must contain a list of files and the id of the database to be stored against
    :return:
    """
    user = request.user
    files = request.FILES.values()

    database_id = get_or_error(request.POST, 'database')
    database = get_or_error(Database, dict(id=database_id))
    assert_permission(user, database, DatabasePermission.ADD_FILES)

    added_files = []
    not_importable_filenames = []
    importable_files = []

    for f in files:
        file = File(file=f)
        name = file.name
        if name.lower().endswith('.wav'):
            name = name[:-4]

        is_unique = not AudioFile.objects.filter(database=database,
                                                 name=name).exists()

        if not is_unique:
            not_importable_filenames.append(name)
        else:
            importable_files.append(file)

    if len(not_importable_filenames) > 0:
        raise CustomAssertionError(
            'Error: No files were imported because the following files already exist: {}'
            .format(', '.join(not_importable_filenames)))
    else:
        for file in importable_files:
            name = file.name
            if name.lower().endswith('.wav'):
                name = name[:-4]

            name_wav = data_path('audio/wav/{}'.format(database.id),
                                 '{}.wav'.format(name))
            name_compressed = data_path(
                'audio/{}/{}'.format(settings.AUDIO_COMPRESSED_FORMAT,
                                     database.id),
                '{}.{}'.format(name, settings.AUDIO_COMPRESSED_FORMAT))

            with open(name_wav, 'wb') as wav_file:
                wav_file.write(file.read())

            audio = pydub.AudioSegment.from_file(name_wav)

            ensure_parent_folder_exists(name_compressed)
            audio.export(name_compressed,
                         format=settings.AUDIO_COMPRESSED_FORMAT)

            fs = audio.frame_rate
            length = audio.raw_data.__len__() // audio.frame_width
            audio_file = AudioFile(name=name,
                                   length=length,
                                   fs=fs,
                                   database=database)
            added_files.append(audio_file)

        AudioFile.objects.bulk_create(added_files)
        added_files = AudioFile.objects.filter(
            database=database, name__in=[x.name for x in added_files])
        _, rows = get_sequence_info_empty_songs(added_files)
        return rows