|
1 | 1 | """Utilities for working with data and models.""" |
2 | 2 |
|
| 3 | +from itertools import repeat |
| 4 | + |
3 | 5 | import numpy as np |
4 | 6 |
|
5 | 7 | ################################################################################################### |
@@ -60,9 +62,10 @@ def interpolate_spectrum(freqs, powers, interp_range, buffer=3): |
60 | 62 | Frequency values for the power spectrum. |
61 | 63 | powers : 1d array |
62 | 64 | Power values for the power spectrum. |
63 | | - interp_range : list of float |
| 65 | + interp_range : list of float or list of list of float |
64 | 66 | Frequency range to interpolate, as [lowest_freq, highest_freq]. |
65 | | - buffer : int |
| 67 | + If a list of lists, applies each as it's own interpolation range. |
| 68 | + buffer : int or list of int |
66 | 69 | The number of samples to use on either side of the interpolation |
67 | 70 | range, that are then averaged and used to calculate the interpolation. |
68 | 71 |
|
@@ -101,26 +104,35 @@ def interpolate_spectrum(freqs, powers, interp_range, buffer=3): |
101 | 104 | >>> freqs, powers = interpolate_spectrum(freqs, powers, [58, 62]) |
102 | 105 | """ |
103 | 106 |
|
104 | | - # Take a copy of the array, to not change original array |
105 | | - powers = np.copy(powers) |
| 107 | + # If given a list of interpolation zones, recurse to apply each one |
| 108 | + if isinstance(interp_range[0], list): |
| 109 | + buffer = repeat(buffer) if isinstance(buffer, int) else buffer |
| 110 | + for interp_zone, cur_buffer in zip(interp_range, buffer): |
| 111 | + freqs, powers = interpolate_spectrum(freqs, powers, interp_zone, cur_buffer) |
| 112 | + |
| 113 | + # Assuming list of two floats, interpolate a single frequency range |
| 114 | + else: |
| 115 | + |
| 116 | + # Take a copy of the array, to not change original array |
| 117 | + powers = np.copy(powers) |
106 | 118 |
|
107 | | - # Get the set of frequency values that need to be interpolated |
108 | | - interp_mask = np.logical_and(freqs >= interp_range[0], freqs <= interp_range[1]) |
109 | | - interp_freqs = freqs[interp_mask] |
| 119 | + # Get the set of frequency values that need to be interpolated |
| 120 | + interp_mask = np.logical_and(freqs >= interp_range[0], freqs <= interp_range[1]) |
| 121 | + interp_freqs = freqs[interp_mask] |
110 | 122 |
|
111 | | - # Get the indices of the interpolation range |
112 | | - ii1, ii2 = np.flatnonzero(interp_mask)[[0, -1]] |
| 123 | + # Get the indices of the interpolation range |
| 124 | + ii1, ii2 = np.flatnonzero(interp_mask)[[0, -1]] |
113 | 125 |
|
114 | | - # Extract & log the requested range of data to use around interpolated range |
115 | | - xs1 = np.log10(freqs[ii1-buffer:ii1]) |
116 | | - xs2 = np.log10(freqs[ii2:ii2+buffer]) |
117 | | - ys1 = np.log10(powers[ii1-buffer:ii1]) |
118 | | - ys2 = np.log10(powers[ii2:ii2+buffer]) |
| 126 | + # Extract & log the requested range of data to use around interpolated range |
| 127 | + xs1 = np.log10(freqs[ii1-buffer:ii1]) |
| 128 | + xs2 = np.log10(freqs[ii2:ii2+buffer]) |
| 129 | + ys1 = np.log10(powers[ii1-buffer:ii1]) |
| 130 | + ys2 = np.log10(powers[ii2:ii2+buffer]) |
119 | 131 |
|
120 | | - # Linearly interpolate, in log-log space, between averages of the extracted points |
121 | | - vals = np.interp(np.log10(interp_freqs), |
122 | | - [np.median(xs1), np.median(xs2)], |
123 | | - [np.median(ys1), np.median(ys2)]) |
124 | | - powers[interp_mask] = np.power(10, vals) |
| 132 | + # Linearly interpolate, in log-log space, between averages of the extracted points |
| 133 | + vals = np.interp(np.log10(interp_freqs), |
| 134 | + [np.median(xs1), np.median(xs2)], |
| 135 | + [np.median(ys1), np.median(ys2)]) |
| 136 | + powers[interp_mask] = np.power(10, vals) |
125 | 137 |
|
126 | 138 | return freqs, powers |
0 commit comments