1+ function out = band_aggregate(spsdl , octave , fmin , fmax , method )
2+
3+ % Reorganizes spectral density level frequency tensor into
4+ % fractional octave bands and applies a function to them.
5+ %
6+ % Parameters
7+ % ----------
8+ % spsdl: struct
9+ % Mean square sound pressure spectral density level in dB rel 1 uPa^2/Hz
10+ % octave: [int, int]
11+ % Octave and octave base to subdivide spectral density level by. Set to
12+ % octave base to 2 for the true octave band; set to base 10 for
13+ % the decidecade octave band.
14+ % Default = [3, 2] (true third octave)
15+ % fmin: int
16+ % Lower frequency band limit (lower limit of the hydrophone). Default: 10 Hz
17+ % fmax: int
18+ % Upper frequency band limit (Nyquist frequency). Default: 100000 Hz
19+ % method:
20+ % Method to run on the binned data. Can be a string (e.g., "median") or a dict
21+ % where the key is the method and the value is its argument (e.g., {"quantile": 0.25}).
22+ % Options: [median, mean, min, max, sum, quantile, std, var, count, map]
23+ %
24+ % Returns
25+ % -------
26+ % out: struct
27+ % Frequency band-averaged sound pressure spectral density level [dB re 1 uPa^2/Hz]
28+ % indexed by time and frequency
29+
30+
31+ arguments (Input )
32+ spsdl struct
33+ octave {mustBeVector } = [3 ,2 ]
34+ fmin {mustBeNumeric } = 10
35+ fmax {mustBeNumeric } = 100000
36+ method = " median"
37+ end
38+
39+ arguments (Output )
40+ out struct
41+ end
42+
43+ if ~isnumeric(octave ) || numel(octave ) ~= 2
44+ error(" 'octave' must be a vector of two positive integers." );
45+ end
46+ if any(octave <= 0 )
47+ error(" 'octave' must contain positive integers." );
48+ end
49+ if ~isnumeric(fmin ) || fmin <= 0
50+ error(" 'fmin' must be a positive integer." );
51+ end
52+ if ~isnumeric(fmax ) || fmax <= fmin
53+ error(" 'fmax' must be greater than 'fmin'." );
54+ end
55+
56+ fmax = fmax_warning(spsdl .fs/ 2 , fmax );
57+
58+ % validate method
59+ [method_name , method_arg ] = validate_method(method );
60+ if isempty(method_arg )
61+ mfunc = str2func(method_name );
62+ elseif method_arg == " quantile"
63+ mfunc = @(x )quantile(x ,method_arg );
64+ else
65+ mfunc = method_arg ;
66+ end
67+
68+ % derive octave bins
69+ [octave_bins , band ] = create_frequency_bands(octave(1 ),octave(2 ),fmin ,fmax );
70+
71+ % groupby and apply method
72+ idx_bin = discretize(spsdl .freq, octave_bins );
73+ temp = zeros(length(band .center_freq), length(spsdl .time));
74+ for x= 1 : length(spsdl .time)
75+ temp(: ,x ) = splitapply(mfunc ,spsdl .data(: ,x ),idx_bin );
76+ end
77+
78+ out.data = temp ;
79+ out.freq = band .center_freq(min(idx_bin ): max(idx_bin ));
80+ out.time = spsdl .time;
81+ out.name = spsdl .name;
82+ out.units = spsdl .units;
83+
84+ end
0 commit comments