import glob import numpy as np import matplotlib.pyplot as plt from thunderhopper.modeltools import load_data, save_data from thunderhopper.filetools import crop_paths from thunderhopper.model import process_signal from IPython import embed # GENERAL SETTINGS: target = 'Omocestus_rufipes' data_paths = glob.glob(f'../data/processed/{target}*.npz') stages = ['raw', 'filt', 'env', 'log', 'inv', 'conv', 'bi', 'feat'] save_path = '../data/inv/full/' # ANALYSIS SETTINGS: example_scales = np.array([0, 0.5, 1, 5, 10]) scales = np.linspace(0, 10, 100) scales = np.unique(np.concatenate((scales, example_scales))) # EXECUTION: for data_path, name in zip(data_paths, crop_paths(data_paths)): print(f'Processing {name}') # Get normalized song recording: data, config = load_data(data_path, files='raw') song, rate = data['raw'], config['rate'] song /= song.std(axis=0) # Get normalized noise: rng = np.random.default_rng() noise = rng.normal(size=song.shape[0]) noise /= noise.std() # Get song segment to be analyzed: time = np.arange(song.shape[0]) / rate start, end = data['songs_0'].ravel() segment = (time >= start) & (time <= end) # Prepare snippet storage: shape_low = (song.shape[0], example_scales.size) shape_high = (song.shape[0], config['k_specs'].shape[0], example_scales.size) snippets = dict( raw=np.zeros(shape_low, dtype=float), filt=np.zeros(shape_low, dtype=float), env=np.zeros(shape_low, dtype=float), log=np.zeros(shape_low, dtype=float), inv=np.zeros(shape_low, dtype=float), conv=np.zeros(shape_high, dtype=float), bi=np.zeros(shape_high, dtype=float), feat=np.zeros(shape_high, dtype=float) ) # Prepare measure storage: shape_low = (scales.size,) shape_high = (scales.size, config['k_specs'].shape[0]) measures = dict( measure_raw=np.zeros(shape_low, dtype=float), measure_filt=np.zeros(shape_low, dtype=float), measure_env=np.zeros(shape_low, dtype=float), measure_log=np.zeros(shape_low, dtype=float), measure_inv=np.zeros(shape_low, dtype=float), measure_conv=np.zeros(shape_high, dtype=float), measure_feat=np.zeros(shape_high, dtype=float) ) # Execute piecewise: for i, scale in enumerate(scales): print('Simulating scale ', scale) # Rescale song and add noise: scaled = song * scale + noise # Process mixture: signals, rates = process_signal(config, returns=stages, signal=scaled, rate=rate) # Store results: for stage in stages: key = f'measure_{stage}' # Log snippet data: if scale in example_scales: scale_ind = np.nonzero(example_scales == scale)[0][0] snippets[stage][:, ..., scale_ind] = signals[stage] # Log "intensity measure" per stage: if stage in ['raw', 'filt', 'env', 'log', 'inv', 'conv']: measures[key][i] = signals[stage][segment, ...].std(axis=0) elif stage == 'feat': measures[key][i] = signals[stage][segment, :].mean(axis=0) / signals[stage][segment, :].std(axis=0) # Relate to smallest scale: base_ind = np.argmin(scales) for stage in stages: if stage == 'bi': continue key = f'measure_{stage}' measures[key] /= measures[key][base_ind, ...] if stage in ['conv', 'feat']: spread = np.zeros((2, scales.size)) spread[0] = np.percentile(measures[key], 25, axis=1) spread[1] = np.percentile(measures[key], 75, axis=1) measures[f'spread_{stage}'] = spread measures[key] = np.median(measures[key], axis=1) # Save analysis results: if save_path is not None: data = dict( scales=scales, example_scales=example_scales, ) data.update(snippets) data.update(measures) save_data(save_path + name, data, config, overwrite=True) print('Done.') embed()