def create_file(
        station_name, recorder_name, start_time, duration, num_channels=1,
        sample_rate=22050, recorder_channel_nums=(0,),
        mic_outputs=('Mic Output 0',)):
    
    t = datetime.datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S')
    start_time = time_utils.create_utc_datetime(
        t.year, t.month, t.day, t.hour, t.minute, t.second)
    
    h, m, s = duration.split(':')
    delta = datetime.timedelta(hours=int(h), minutes=int(m), seconds=int(s))
    duration = delta.total_seconds()
    length = int(duration * sample_rate)
    
    station = Bunch(name=station_name)
    recorder = Bunch(name=recorder_name)
    
    return Bunch(
        station=station,
        recorder=recorder,
        recorder_channel_nums=recorder_channel_nums,
        mic_outputs=mic_outputs,
        num_channels=num_channels,
        length=length,
        sample_rate=sample_rate,
        start_time=start_time)
Beispiel #2
0
class BunchTests(TestCase):


    def setUp(self):
        
        self.a = Bunch(one=1, two=2)
        self.b = Bunch(three=3, four=4)
        self.c = Bunch(self.a, self.b, five=5)
        
        
    def test_initializer(self):
        
        a = self.a
        self.assertEqual(a.one, 1)
        self.assertEqual(a.two, 2)
        
        b = self.b
        self.assertEqual(b.three, 3)
        self.assertEqual(b.four, 4)
        
        c = self.c
        self.assertEqual(c.one, 1)
        self.assertEqual(c.two, 2)
        self.assertEqual(c.three, 3)
        self.assertEqual(c.four, 4)
        self.assertEqual(c.five, 5)
        
        
    def test_eq(self):
        a = Bunch(one=1, two=2)
        self.assertEqual(a, self.a)
        self.assertNotEqual(a, self.b)
        
        
    def test_contains(self):
        self.assertIn('one', self.a)
        self.assertIn('two', self.a)
        self.assertNotIn('three', self.a)
        
        
    def test_iter(self):
        keys = sorted(k for k in self.a)
        self.assertEqual(keys, ['one', 'two'])
        
        
    def test_get(self):
        self.assertEqual(self.a.get('one'), 1)
        self.assertEqual(self.a.get('two'), 2)
        self.assertIsNone(self.a.get('three'))
        
        
    def test_get_defaults(self):
        self.assertEqual(self.a.get('seventeen'), None)
        self.assertEqual(self.a.get('seventeen', 17), 17)
Beispiel #3
0
def get_recorder_microphone_infos(station, microphone_output):
    
    """
    Gets a mapping from (recorder_id, microphone_output_id) pairs
    to lists of (channel_num, start_time, end_time) bunches.
    
    The bunches are ordered by channel numbers and start times.
    """
    
    # Get recorders that were used at station.
    recorders = station.devices.filter(model__type='Audio Recorder')
    
    rm_infos = defaultdict(list)
    
    for recorder in recorders:
        
        key = (recorder.id, microphone_output.id)
        
        # Get connections from microphone to recorder.
        connections = DeviceConnection.objects.filter(
            output=microphone_output,
            input__device=recorder)
        
        # Remember channel number and time interval of each connection.
        for connection in connections:
            info = Bunch(
                channel_num=connection.input.channel_num,
                start_time=connection.start_time,
                end_time=connection.end_time)
            rm_infos[key].append(info)
            
        rm_infos[key].sort(key=_get_rm_info_sort_key)

    return rm_infos
Beispiel #4
0
 def test_init(self):
     
     channel_count = 2
     waveform_frame_count = 32
     waveform_frame_rate = 16000
     window_size = 16
     hop_size = 8
     dft_size = 16
     
     samples = _get_waveform_samples(
         channel_count, waveform_frame_count, window_size)
     waveform = RamSignal(waveform_frame_rate, samples, False)
     
     window = np.ones(window_size)
     settings = Bunch(window=window, hop_size=hop_size, dft_size=dft_size)        
     gram = Spectrogram(waveform, settings)
     
     gram_frame_count = 1 + (waveform_frame_count - window_size) // hop_size
     gram_frame_rate = waveform_frame_rate / hop_size
     offset = (window_size - 1) / 2 / waveform_frame_rate
     time_axis = TimeAxis(gram_frame_count, gram_frame_rate, offset)
     
     array_shape = ((dft_size // 2) + 1,)
     
     samples = _get_gram_samples(waveform, window, hop_size, dft_size)
     
     SignalTests.assert_signal(
         gram, 'Spectrogram', time_axis, channel_count, array_shape,
         'float64', samples)
Beispiel #5
0
    def _parse_file_path(self, file_path):

        parts = Path(file_path).parts
        file_name = parts[-1]
        dir_names = tuple(reversed(parts[:-1]))

        # Get classification from file parent dir name if name indicates it.
        key = dir_names[0].lower()
        classification = self._classifications.get(key)

        if classification is None:
            self._logger.warning(
                ('Could not find classification for file "{}". Clip will '
                 'be unclassified.').format(file_path))
        else:
            dir_names = dir_names[1:]

        station = self._get_station(dir_names)

        # Get clip detector, start time, and date.
        detector_name, local_start_time = _parse_file_name(file_name)
        detector = self._get_detector(detector_name)
        start_time = station.local_to_utc(local_start_time)
        date = station.get_night(start_time)

        return Bunch(station=station,
                     detector=detector,
                     start_time=start_time,
                     date=date,
                     classification=classification)
def detect_events(audio, config):

    spectrogram = Spectrogram(audio, config.spectrogram_settings)

    x, times = measurements.apply_measurement_to_spectra(
        measurements.entropy,
        spectrogram,
        start_freq=config.start_freq,
        end_freq=config.end_freq,
        denoise=True,
        block_size=1)

    if len(times) < 2:
        return []

    else:
        # spectrogram has at least two frames

        period = times[1] - times[0]
        min_event_length = _to_frames(config.min_event_duration, period)
        max_event_length = _to_frames(config.max_event_duration, period)
        min_event_separation = _to_frames(config.min_event_separation, period)

        detector_config = Bunch(
            typical_background_percentile=config.typical_background_percentile,
            small_background_percentile=config.small_background_percentile,
            bit_threshold_factor=config.bit_threshold_factor,
            min_event_length=min_event_length,
            max_event_length=max_event_length,
            min_event_separation=min_event_separation,
            min_event_density=config.min_event_density)

        selections, _ = _detect(-x, detector_config)

        return [_convert_selection(s, times[0], period) for s in selections]
def parse_csv_file_line(line):

    (station_name, _, recorder_model, recorder_sn, microphone_sn, latitude,
     longitude, elevation, station_name_alias) = line.split(',')

    if recorder_model == 'SM2':
        recorder_model = 'SM2+'

    if recorder_sn == '':
        recorder_sn = create_sn(recorder_model)

    microphone_model = '21c'

    if microphone_sn == '':
        microphone_sn = create_sn(microphone_model)

    return Bunch(station_name=station_name,
                 station_name_alias=station_name_alias,
                 description='',
                 time_zone='US/Mountain',
                 latitude=latitude,
                 longitude=longitude,
                 elevation=elevation,
                 recorder_model=recorder_model,
                 recorder_sn=recorder_sn,
                 microphone_model=microphone_model,
                 microphone_sn=microphone_sn)
Beispiel #8
0
def resample(audio, target_sample_rate):
    
    """
    Resamples audio to a specified sample rate.
    
    This function should only be used for relatively short audio segments,
    say not longer than a second or so. It uses the `scipy.signal.resample`
    method to perform the resampling, which computes a length-M DFT and a
    length-N inverse DFT, where M and N are the input and output length,
    respectively. M and N may not be powers of two, and they may even be
    prime, which can make this function slow if M or N is too large.
    """
    
    
    if audio.sample_rate == target_sample_rate:
        # do not need to resample
        
        return audio
    
    else:
        # need to resample
        
        # We put this import here instead of at the top of this module
        # so  the module can be used in Python environments that don't
        # include SciPy as long as this function is not called.
        import scipy.signal as signal

        ratio = target_sample_rate / audio.sample_rate
        num_samples = int(round(len(audio.samples) * ratio))
        samples = signal.resample(audio.samples, num_samples)
        return Bunch(samples=samples, sample_rate=target_sample_rate)
Beispiel #9
0
def extract_call(audio, selection, config):
    
    samples = audio.samples
    sample_rate = audio.sample_rate

    start_index, end_index = selection
    center_index = (start_index + end_index - 1) // 2
    
    duration = config.call_segment_duration
    length = seconds_to_frames(duration, sample_rate)
    start_index = center_index - length // 2
    
    if start_index < 0:
        return None
    
    else:
        # start index is at least zero
        
        end_index = start_index + length
        
        if end_index > len(samples):
            return None
        
        else:
            return Bunch(
                samples=samples[start_index:end_index],
                sample_rate=sample_rate)
def create_channel_stat_bunch(stat_dicts):
    return Bunch(
        max=np.array(stat_dicts['max']),
        min=np.array(stat_dicts['min']),
        mean=np.array(stat_dicts['mean']),
        mean_abs=np.array(stat_dicts['mean_abs']),
        std=np.array(stat_dicts['std']),
        ampligram=np.stack(stat_dicts['ampligram']))
Beispiel #11
0
def _get_input_device(info, default_index, host_api_names):
    return Bunch(host_api_name=host_api_names[info['hostApi']],
                 index=info['index'],
                 default=info['index'] == default_index,
                 name=info['name'],
                 num_input_channels=info['maxInputChannels'],
                 default_sample_rate=info['defaultSampleRate'],
                 default_low_input_latency=info['defaultLowInputLatency'],
                 default_high_input_latency=info['defaultHighInputLatency'])
Beispiel #12
0
 def _end_recording(self):
     return Bunch(station=self.station,
                  recorder=self.recorder,
                  recorder_channel_nums=self.recorder_channel_nums,
                  mic_outputs=self.mic_outputs,
                  num_channels=self.num_channels,
                  length=self.length,
                  sample_rate=self.sample_rate,
                  start_time=self.start_time,
                  files=self.files)
Beispiel #13
0
    def _test_spectrogram(self, num_channels, dft_size, hop_size, bin_num):

        num_samples = dft_size * 2
        samples = self._create_test_signal(num_channels, num_samples, dft_size,
                                           bin_num)
        audio = Bunch(samples=samples, sample_rate=_SAMPLE_RATE)

        window = RectangularWindow(dft_size)
        settings = Bunch(window=window,
                         hop_size=hop_size,
                         dft_size=dft_size,
                         reference_power=None)

        spectrogram = Spectrogram(audio, settings)
        spectra = spectrogram.spectra

        expected = self._get_expected_spectra(num_channels, num_samples,
                                              hop_size, dft_size, bin_num)

        self.assertTrue(np.allclose(spectra, expected))
        self.assertEqual(spectrogram.freq_spacing, _SAMPLE_RATE / dft_size)
Beispiel #14
0
    def _get_absolute_path_info(self, file_path):

        manager = recording_manager.instance

        try:
            _, rel_path = manager.get_relative_recording_file_path(file_path)

        except ValueError:
            self._handle_bad_recording_file_path(file_path, 'is not in',
                                                 manager)

        return Bunch(absolute_path=file_path, relative_path=rel_path)
Beispiel #15
0
def _parse_file_name(file_name):
    
    m = _FILE_NAME_REGEX.match(file_name)
    
    if m is not None:
        
        m = Bunch(**m.groupdict())
        
        try:
            start_time = time_utils.parse_date_time(
                m.year, m.month, m.day, m.hour, m.minute, m.second)
        except Exception as e:
            raise ValueError(
                'Could not get start time from file name: {}'.format(str(e)))
        
        tenths = datetime.timedelta(microseconds=100000 * int(m.num))
        start_time += tenths
        
        return m.detector_name, start_time
        
    else:
        raise ValueError('Could not parse file name.')
Beispiel #16
0
    def _create_clip(self, dataset):

        attrs = dataset.attrs

        return Bunch(id=attrs['id'],
                     waveform=dataset[:],
                     station=attrs['station'],
                     microphone=attrs['microphone'],
                     detector=attrs['detector'],
                     night=attrs['night'],
                     start_time=attrs['start_time'],
                     original_sample_rate=attrs['original_sample_rate'],
                     classification=attrs['classification'])
Beispiel #17
0
def _parse_file_name(file_name):

    m = _FILE_NAME_REGEX.match(file_name)

    if m is not None:

        m = Bunch(**m.groupdict())

        try:
            start_time = time_utils.parse_date_time(m.year, m.month, m.day,
                                                    m.hour, m.minute, m.second)
        except Exception as e:
            raise ValueError(
                'Could not get start time from file name: {}'.format(str(e)))

        tenths = datetime.timedelta(microseconds=100000 * int(m.num))
        start_time += tenths

        return m.detector_name, start_time

    else:
        raise ValueError('Could not parse file name.')
Beispiel #18
0
def create_data_sets(features, targets, settings):

    num_examples = len(features)

    assert (len(targets) == num_examples)

    train_size = settings.training_set_size
    val_size = settings.validation_set_size
    test_size = settings.test_set_size

    assert (val_size + test_size < num_examples)

    if train_size is None:
        train_size = num_examples - val_size - test_size

    assert (train_size + val_size + test_size <= num_examples)

    # Shuffle examples.
    permutation = numpy_utils.reproducible_permutation(num_examples)
    features = features[permutation]
    targets = targets[permutation]

    test_start = num_examples - test_size
    val_start = test_start - val_size

    train_set = Bunch(name='training',
                      features=features[:val_start],
                      targets=targets[:val_start])

    val_set = Bunch(name='validation',
                    features=features[val_start:test_start],
                    targets=targets[val_start:test_start])

    test_set = Bunch(name='test',
                     features=features[test_start:],
                     targets=targets[test_start:])

    return train_set, val_set, test_set
Beispiel #19
0
def initialize(archive_dir_path, archive_settings):

    global archive_paths

    archive_paths = Bunch(
        archive_dir_path=archive_dir_path,
        clip_dir_path=archive_dir_path / 'Clips',
        deferred_action_dir_path=archive_dir_path / 'Deferred Actions',
        job_log_dir_path=archive_dir_path / 'Logs' / 'Jobs',
        preference_file_path=archive_dir_path / 'Preferences.yaml',
        preset_dir_path=archive_dir_path / 'Presets',
        recording_dir_paths=_create_recording_dir_paths(
            archive_settings, archive_dir_path),
        sqlite_database_file_path=archive_dir_path / 'Archive Database.sqlite')
def create_detector_settings_aux(
        detector_type, parameter_name, parameter_value):
    
    value_string = format_parameter_value(parameter_value)
    name = '{} {}'.format(detector_type, value_string)
    
    base_settings = DETECTOR_BASE_SETTINGS[detector_type]
        
    kwargs = {
        parameter_name: parameter_value,
    }
    
    settings = Bunch(base_settings, **kwargs)
    
    return name, settings
Beispiel #21
0
    def start_job(self, command_spec, user):

        info = Bunch()
        info.command_spec = command_spec
        info.job_id = _create_job(command_spec, user)
        info.archive_lock = archive_lock.get_lock()
        info.stop_event = Event()

        with self._lock:
            self._job_infos[info.job_id] = info

        info.process = Process(target=job_runner.run_job, args=(info, ))
        info.process.start()

        return info.job_id
def _generate_segments(audio, segment_length, hop_size, start_index=0):

    samples = audio.samples
    sample_rate = float(audio.sample_rate)

    n = len(samples)
    i = start_index

    while i + segment_length <= n:

        segment = Bunch(samples=samples[i:i + segment_length],
                        sample_rate=sample_rate,
                        start_time=i / sample_rate)

        yield segment

        i += hop_size
Beispiel #23
0
def _read_header(reader, check_format=True):
    
    p = reader.getparams()
        
    sample_size = p.sampwidth * 8

    if check_format:
        _check_wave_file_format(sample_size, p.comptype)
    
    sample_rate = float(p.framerate)
    
    return Bunch(
        num_channels=p.nchannels,
        length=p.nframes,
        sample_size=sample_size,
        sample_rate=sample_rate,
        compression_type=p.comptype,
        compression_name=p.compname)
def parse_example(data):

    data = [int(d) for d in data]

    clip_id = data[0]
    call_start_index = data[1]
    label = data[2]
    scores = np.array(data[3:])
    max_score = np.max(scores)
    max_score_index = np.argmax(scores)
    correct = max_score_index == label

    return Bunch(clip_id=clip_id,
                 call_start_index=call_start_index,
                 label=label,
                 scores=scores,
                 max_score=max_score,
                 max_score_index=max_score_index,
                 correct=correct)
Beispiel #25
0
    def start_job(self, command_spec, user):
        
        info = Bunch()
        info.command_spec = command_spec
        info.job_id = _create_job(command_spec, user)
        info.archive_lock = archive_lock.get_lock()
        info.stop_event = Event()

        with self._lock:
            self._job_infos[info.job_id] = info
            
        info.process = Process(target=job_runner.run_job, args=(info,))
        info.process.start()
        
        return info.job_id
Beispiel #26
0
    def parse_file(self, file_path):
        """
        Parses the specified recording file for recording information.
        
        Some information is obtained from the file path, while other
        information is obtained from within the file.
        
        :Parameters:
            file_path : `str`
                the path of the file to parse.
                
        :Returns:
            a `Bunch` with the following attributes:
            
            `station` - the `Station` of the recording.
            `recorder` - the `Recorder` of the recording, or `None` if unknown.
            `recorder_channel_nums` - sequence of recorder channel numbers
                indexed by recording channel number, or `None` if unknown.
            `num_channels` - the number of channels of the file.
            `length` - the length of the file in sample frames.
            `sample_rate` - the sample rate of the file in Hertz.
            `start_time` - the UTC start time of the file.
            `path` - the path of the file.
        """

        station, recorder_channel_nums, start_time = \
            self._parse_file_name(file_path)

        num_channels, length, sample_rate = \
            self._get_audio_file_info(file_path)

        return Bunch(station=station,
                     recorder=None,
                     recorder_channel_nums=recorder_channel_nums,
                     num_channels=num_channels,
                     length=length,
                     sample_rate=sample_rate,
                     start_time=start_time,
                     path=file_path)
def extract_clip_segment(clip,
                         segment_duration,
                         segment_source,
                         source_duration=None):

    source = _get_segment_source(clip, segment_source, source_duration)

    if source is None:
        return None

    else:

        source_start_index, source_length = source

        sample_rate = clip.sample_rate
        segment_length = signal_utils.seconds_to_frames(
            segment_duration, sample_rate)

        if source_length < segment_length:
            # source not long enough to extract segment from

            return None

        else:

            # Extract samples from source.
            if source_length == segment_length:
                offset = 0
            else:
                offset = random.randrange(source_length - segment_length)
            start_index = source_start_index + offset
            end_index = start_index + segment_length
            samples = clip_manager.instance.get_samples(clip)
            samples = samples[start_index:end_index]

            return Bunch(samples=samples,
                         sample_rate=clip.sample_rate,
                         start_index=start_index)
Beispiel #28
0
def _create_station_devices(model_stations, device_type):
    
    devices = []
    
    model_names = sorted(model_stations.keys())
    
    for model_name in model_names:
        
        station_names = sorted(model_stations[model_name])
        
        for serial_num, station_name in enumerate(station_names):
            
            name = '{} {}'.format(model_name, serial_num)
            
            device = Bunch(
                name=name,
                model_name=model_name,
                serial_num=serial_num,
                station_name=station_name,
                type=device_type)
            
            devices.append(device)
            
    return devices
Beispiel #29
0
 def get_audio(self, clip):
     samples = self.get_samples(clip)
     sample_rate = clip.sample_rate
     return Bunch(samples=samples, sample_rate=sample_rate)
Beispiel #30
0
 def _create_bunches(self, cls, rows):
     return [Bunch(**dict(zip(cls._fields, r))) for r in rows]
"""
the sample rate of the original Old Bird detectors, in hertz.

The reimplemented detectors can operate on input of a variety of sample
rates. We use the sample rate of the original detectors only to convert
detector settings that were originally specified in units of sample
periods to units of seconds.
"""

_TSEEP_SETTINGS = Bunch(
    filter_f0=6000,  # hertz
    filter_f1=10000,  # hertz
    filter_bw=100,  # hertz
    filter_duration=100 / _OLD_FS,  # seconds
    integration_time=2000 / _OLD_FS,  # seconds
    ratio_delay=.02,  # seconds
    ratio_threshold=2,  # dimensionless
    min_duration=.100,  # seconds
    max_duration=.400,  # seconds
    initial_padding=3000 / _OLD_FS,  # seconds
    suppressor_count_threshold=15,  # clips
    suppressor_period=20  # seconds
)

_THRUSH_SETTINGS = Bunch(
    filter_f0=2800,  # hertz
    filter_f1=5000,  # hertz
    filter_bw=100,  # hertz
    filter_duration=100 / _OLD_FS,  # seconds
    integration_time=4000 / _OLD_FS,  # seconds
    ratio_delay=.02,  # seconds
    ratio_threshold=1.3,  # dimensionless
 def _create_recording_file_bunch(self, f):
     path = self._get_absolute_file_path(f.path)
     return Bunch(path=path, start_index=f.start_index, length=f.length)