def process(self, item, file_paths, target_dir=None): if item.form == 'ignore': return if target_dir is None: raise TypeError('"target_dir" must be given') avg_fr = FrequencyResponse(name=item.true_name) avg_fr.raw = np.zeros(avg_fr.frequency.shape) for fp in file_paths: with open(fp, 'r', encoding='utf-8') as fh: s = fh.read() freq = [] raw = [] for line in s.split('\n'): if len(line) == 0 or line[0] == '*': # Skip empty lines and comments if 'C-weighting compensation: On' in line: print(f'C-weighted measurement: {item.false_name}') continue frp = line.split(', ') if len(frp) == 1: frp = line.split('\t') if len(frp) == 1: frp = line.split(' ') if len(frp) == 2: f, r = frp elif len(frp) == 3: f, r, p = frp else: # Must be comment line continue if f == '?' or r == '?': # Skip lines with missing data continue try: freq.append(float(f)) raw.append(float(r)) except ValueError as err: # Failed to convert values to floats, must be header or comment row, skip continue # Create standard fr object fr = FrequencyResponse(name=item.true_name, frequency=freq, raw=raw) fr.interpolate() fr.center() avg_fr.raw += fr.raw avg_fr.raw /= len(file_paths) # Save dir_path = os.path.join(target_dir, avg_fr.name) os.makedirs(dir_path, exist_ok=True) file_path = os.path.join(dir_path, f'{avg_fr.name}.csv') avg_fr.write_to_csv(file_path) print(f'Saved "{avg_fr.name}" to "{file_path}"')
def process(self, item, file_paths): fr = FrequencyResponse(name=item.true_name) fr.raw = np.zeros(fr.frequency.shape) for fp in file_paths: if re.search(r'\.mdat$', fp): # Read mdat file for Gras headphone measurements raise TypeError( 'Crinacle\'s Gras measurements are not supported yet!') else: # Read text file for IEM and Ears-711 headphone measurements with open(fp, 'r', encoding='utf-8') as fh: s = fh.read() freq = [] raw = [] for line in s.split('\n'): if len(line) == 0 or line[0] == '*': # Skip empty lines and comments if 'C-weighting compensation: On' in line: print(f'C-weighted measurement: {item.false_name}') continue frp = line.split(' ') if len(frp) == 1: frp = line.split('\t') if len(frp) == 2: f, r = frp elif len(frp) == 3: f, r, p = frp else: # Must be comment line continue if f == '?' or r == '?': # Skip lines with missing data continue try: freq.append(float(f)) raw.append(float(r)) except ValueError as err: # Failed to convert values to floats, must be header or comment row, skip continue # Create standard fr object _fr = FrequencyResponse(name=item.true_name, frequency=freq, raw=raw) _fr.interpolate() _fr.center() fr.raw += _fr.raw fr.raw /= len(file_paths) # Save dir_path = os.path.join(DIR_PATH, 'data', item.form, fr.name) os.makedirs(dir_path, exist_ok=True) file_path = os.path.join(dir_path, f'{fr.name}.csv') fr.write_to_csv(file_path) print(f'Saved "{fr.name}" to "{file_path}"')
def parse_image(im, model): """Parses graph image downloaded from innerfidelity.com""" # Crop by left and right edges box = (69, 31, 550, 290) im = im.crop(box) px_a_max = 0 px_a_min = im.size[1] # im.show() # X axis f_min = 20 f_max = 20000 f_step = (f_max / f_min)**(1 / im.size[0]) f = [f_min] for _ in range(1, im.size[0]): f.append(f[-1] * f_step) # Y axis a_max = 150 a_min = 66 a_res = (a_max - a_min) / (px_a_min - px_a_max) # Try blue curve _im = im.copy() inspection = _im.load() amplitude, _im, _inspection = ReferenceAudioAnalyzerCrawler.find_curve( _im, inspection, 203, 206, 0.8, 1.0, a_max, a_res) if len([x for x in amplitude if x is None]) >= 0.5 * len(amplitude): # More than half of the pixels were discarded, try green curve _im = im.copy() inspection = _im.load() amplitude, _im, _inspection = ReferenceAudioAnalyzerCrawler.find_curve( _im, inspection, 119, 121, 0.8, 1.0, a_max, a_res) # Inspection image draw = ImageDraw.Draw(_im) x0 = np.log(30 / f_min) / np.log(f_step) x1 = np.log(10000 / f_min) / np.log(f_step) y_0 = px_a_max + 12 / a_res y_1 = px_a_min - 12 / a_res draw.rectangle(((x0, y_0), (x1, y_1)), outline='magenta') draw.rectangle(((x0 + 1, y_0 + 1), (x1 - 1, y_1 - 1)), outline='magenta') # Create frequency response fr = FrequencyResponse(model, f, amplitude) fr.interpolate() if len(fr.frequency) < 2: im.show() raise ValueError(f'Failed to parse image for {fr.name}') fr.smoothen_fractional_octave(window_size=1 / 3, treble_window_size=1 / 3) fr.raw = fr.smoothed.copy() fr.smoothed = np.array([]) fr.center() return fr, _im
def save(df, column, name): fr = FrequencyResponse(name=name, frequency=df['Frequency'], raw=df[column]) fr.interpolate() fr.center() name = name.lower().replace(' ', '_') fr.write_to_csv('compensation/{}.csv'.format(name)) fr.plot_graph(file_path='compensation/{}.png'.format(name), show=False, color=None) ind = np.argmin(fr.raw[:400]) fr.raw[:ind] = fr.raw[ind] fr.write_to_csv('compensation/{}_wo_bass.csv'.format(name)) fr.plot_graph(file_path='compensation/{}_wo_bass.png'.format(name), show=False, color=None)
def main(): dt770 = FrequencyResponse.read_from_csv('headphonecom/data/onear/Beyerdynamic DT770/Beyerdynamic DT770.csv') dt770.interpolate() he400s = FrequencyResponse.read_from_csv('innerfidelity/data/onear/HiFiMAN HE400S/HiFiMAN HE400S.csv') he400s.interpolate() calibration = FrequencyResponse.read_from_csv('calibration/headphonecom_raw_to_innerfidelity_raw.csv') calibration.interpolate() compensation = FrequencyResponse.read_from_csv('innerfidelity/resources/innerfidelity_compensation_2017.csv') compensation.interpolate() dt770_calibrated = FrequencyResponse(name='DT 770 calibrated', frequency=dt770.frequency, raw=dt770.raw) dt770_calibrated.calibrate(calibration) dt770_calibrated.compensate(he400s) #dt770_calibrated.compensate(compensation) dt770_calibrated.center() dt770_calibrated.smoothen() dt770_calibrated.equalize(smoothen=True) dt770_calibrated.plot_graph(a_min=-20, a_max=20)
def main(oe, ie): oe18 = FrequencyResponse.read_from_csv( 'compensation/harman_over-ear_2018.csv') oe18wob = FrequencyResponse.read_from_csv( 'compensation/harman_over-ear_2018_wo_bass.csv') ie17 = FrequencyResponse.read_from_csv( 'compensation/harman_in-ear_2017-1.csv') ie17wob = FrequencyResponse.read_from_csv( 'compensation/harman_in-ear_2017-1_wo_bass.csv') if oe: bass = FrequencyResponse(name='Bass', frequency=oe18.frequency) bass.raw = bass._sigmoid(35, 280, 4, -2.0) fig, ax = oe18.plot_graph(show=False, color=None) oe18wob.plot_graph(fig=fig, ax=ax, show=False, color=None) bass.plot_graph(fig=fig, ax=ax, show=False, color=None) boost = FrequencyResponse(name='Boost', frequency=bass.frequency, raw=bass.raw) boost.center() oe18wob_boosted = FrequencyResponse(name='Boosted OE18', frequency=oe18.frequency, raw=oe18wob.raw + boost.raw) oe18wob_boosted.plot_graph(fig=fig, ax=ax, show=False, color=None) ax.legend(['OE18', 'OE18 w/o bass', 'Bass', 'Boosted']) plt.show() if ie: bass = FrequencyResponse(name='Bass', frequency=ie17.frequency) bass.raw = bass._sigmoid(25, 350, 8, -1.7) fig, ax = ie17.plot_graph(show=False, color=None) ie17wob.plot_graph(fig=fig, ax=ax, show=False, color=None) bass.plot_graph(fig=fig, ax=ax, show=False, color=None) boost = FrequencyResponse(name='Boost', frequency=bass.frequency, raw=bass.raw) boost.center() ie17wob_boosted = FrequencyResponse(name='Boosted IE17', frequency=ie17.frequency, raw=ie17wob.raw + boost.raw) ie17wob_boosted.plot_graph(fig=fig, ax=ax, show=False, color=None) ax.legend(['IE17', 'IE17 w/o bass', 'Bass', 'Boosted']) plt.show()
def main(): fs = 48000 f_res = 60 input_dir = os.path.join('oratory1990', 'data', 'onear') glob_files = glob(os.path.join(input_dir, '**', '*.csv'), recursive=True) for input_file_path in glob_files: fr = FrequencyResponse.read_from_csv(input_file_path) fr.equalization = fr.raw fr.raw = np.array([]) mp = fr.minimum_phase_impulse_response(fs=fs, f_res=f_res, normalize=False) mp = np.concatenate([mp, np.zeros(fs//10 - len(mp))]) f_mp, mp = fft(mp, fs) f_mp[0] = 0.1 mp = FrequencyResponse(name='Minimum phase', frequency=f_mp, raw=mp) mp.center() lp = fr.linear_phase_impulse_response(fs=fs, f_res=f_res, normalize=False) lp = np.concatenate([lp, np.zeros(fs//10 - len(lp))]) f_lp, lp = fft(lp, fs) f_lp[0] = 0.1 lp = FrequencyResponse(name='Linear phase', frequency=f_lp, raw=lp) lp.center() fig, ax = plt.subplots() fig.set_size_inches(15, 10) plt.plot(fr.frequency, fr.equalization) plt.plot(mp.frequency, mp.raw, '.-') plt.plot(lp.frequency, lp.raw, '.-') plt.legend(['Raw', 'Minimum phase', 'Linear phase']) plt.semilogx() plt.xlabel('Frequency (Hz)') plt.xlim([1, 20000]) plt.ylabel('Gain (dBr)') plt.ylim([-20, 20]) plt.title(fr.name) plt.grid(True, which='major') plt.grid(True, which='minor') plt.show()
def equal_loudness_contour(phon): f = [ 20, 25, 31.5, 40, 50, 63, 80, 100, 125, 160, 200, 250, 315, 400, 500, 630, 800, 1000, 1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000, 10000, 12500 ] af = [ 0.532, 0.506, 0.480, 0.455, 0.432, 0.409, 0.387, 0.367, 0.349, 0.330, 0.315, 0.301, 0.288, 0.276, 0.267, 0.259, 0.253, 0.250, 0.246, 0.244, 0.243, 0.243, 0.243, 0.242, 0.242, 0.245, 0.254, 0.271, 0.301 ] Lu = [ -31.6, -27.2, -23.0, -19.1, -15.9, -13.0, -10.3, -8.1, -6.2, -4.5, -3.1, -2.0, -1.1, -0.4, 0.0, 0.3, 0.5, 0.0, -2.7, -4.1, -1.0, 1.7, 2.5, 1.2, -2.1, -7.1, -11.2, -10.7, -3.1 ] Tf = [ 78.5, 68.7, 59.5, 51.1, 44.0, 37.5, 31.5, 26.5, 22.1, 17.9, 14.4, 11.4, 8.6, 6.2, 4.4, 3.0, 2.2, 2.4, 3.5, 1.7, -1.3, -4.2, -6.0, -5.4, -1.5, 6.0, 12.6, 13.9, 12.3 ] Ln = phon Lps = [] for i in range(0, len(f)): Af = 0.00447 * (10.0**(Ln / 40.0) - 1.15) + (10.0**(( (Tf[i] + Lu[i]) / 10.0) - 9.0) / 2.5)**af[i] Lp = ((10.0 / af[i]) * math.log10(Af)) - Lu[i] + 94.0 Lps.append(Lp) Lps = np.array(Lps) fr = FrequencyResponse(name='{} phon Equal Loudness Contour'.format(phon), frequency=f, raw=Lps) fr.interpolate(pol_order=3, f_min=20, f_max=12500) fr.center() return fr
def parse_image(im, model, px_top=800, px_bottom=4400, px_left=0, px_right=2500): """Parses graph image downloaded from innerfidelity.com""" # Crop out everything but graph area (roughly) box = (px_left, px_top, im.size[0] - px_right, im.size[1] - px_bottom) im = im.crop(box) # im.show() # Find graph edges v_lines = ImageGraphParser.find_lines(im, 'vertical') h_lines = ImageGraphParser.find_lines(im, 'horizontal') # Crop by graph edges box = (v_lines[0], h_lines[0], v_lines[1], h_lines[1]) im = im.crop(box) # im.show() # X axis f_min = 10 f_max = 20000 f_step = (f_max / f_min)**(1 / im.size[0]) f = [f_min] for _ in range(1, im.size[0]): f.append(f[-1] * f_step) # Y axis a_max = 30 a_min = -20 a_res = (a_max - a_min) / im.size[1] _im = im.copy() pix = _im.load() amplitude = [] y_legend = 40 / 50 * im.size[1] x0_legend = np.log(70 / f_min) / np.log(f_step) x1_legend = np.log(1000 / f_min) / np.log(f_step) # Iterate each column for x in range(im.size[0]): pxs = [] # Graph pixels # Iterate each row (pixel in column) for y in range(im.size[1]): if y > y_legend and x0_legend < x < x1_legend: # Skip pixels in the legend box continue # Convert read RGB pixel values and convert to HSV h, s, v = colorsys.rgb_to_hsv( *[v / 255.0 for v in im.getpixel((x, y))]) # Graph pixels are colored if 0.7 < s < 0.9 and 20 / 360 < h < 30 / 360: pxs.append(float(y)) else: p = im.getpixel((x, y)) pix[x, y] = (int(0.3 * p[0]), int(255 * 0.7 + 0.3 * p[1]), int(0.3 * p[2])) if not pxs: # No graph pixels found on this column amplitude.append(None) else: # Mean of recorded pixels v = np.mean(pxs) # Convert to dB value v = a_max - v * a_res amplitude.append(v) # Inspection image draw = ImageDraw.Draw(_im) x0 = np.log(20 / f_min) / np.log(f_step) x1 = np.log(10000 / f_min) / np.log(f_step) draw.rectangle(((x0, 10 / a_res), (x1, 40 / a_res)), outline='magenta') draw.rectangle(((x0 + 1, 10 / a_res + 1), (x1 - 1, 40 / a_res - 1)), outline='magenta') fr = FrequencyResponse(model, f, amplitude) fr.interpolate() fr.center() return fr, _im
def parse_image(im, model): """Parses graph image downloaded from innerfidelity.com""" # Crop by left and right edges box = (69, 31, 550, 290) im = im.crop(box) px_a_max = 0 px_a_min = im.size[1] #im.show() # X axis f_min = 20 f_max = 20000 f_step = (f_max / f_min)**(1 / im.size[0]) f = [f_min] for _ in range(1, im.size[0]): f.append(f[-1] * f_step) # Y axis a_max = 150 a_min = 66 a_res = (a_max - a_min) / (px_a_min - px_a_max) # Colors #line_color = np.array([50, 155, 254]) line_color = np.array([0, 135, 0]) _im = im.copy() inspection = _im.load() amplitude = [] # Iterate each column for x in range(im.size[0]): pxs = [] # Graph pixels # Iterate each row (pixel in column) for y in range(im.size[1]): # Convert read RGB pixel values and convert to HSV rgba = im.getpixel((x, y)) # Graph pixels are colored if np.mean(np.abs(line_color - rgba[:3])) < 15: pxs.append(float(y)) else: p = im.getpixel((x, y)) inspection[x, y] = (int(0.3 * p[0]), int(255 * 0.7 + 0.3 * p[1]), int(0 + 0.3 * p[2])) if not pxs: # No graph pixels found on this column amplitude.append(None) else: # Mean of recorded pixels v = np.mean(pxs) # Convert to dB value v = a_max - v * a_res amplitude.append(v) # Inspection image draw = ImageDraw.Draw(_im) x0 = np.log(30 / f_min) / np.log(f_step) x1 = np.log(10000 / f_min) / np.log(f_step) y_0 = px_a_max + 12 / a_res y_1 = px_a_min - 12 / a_res draw.rectangle(((x0, y_0), (x1, y_1)), outline='magenta') draw.rectangle(((x0 + 1, y_0 + 1), (x1 - 1, y_1 - 1)), outline='magenta') # Create frequency response fr = FrequencyResponse(model, f, amplitude) fr.interpolate() fr.center() return fr, _im
def main(): # Read name index name_index = dict() df = pd.read_csv(os.path.join(DIR_PATH, 'name_index.tsv'), sep='\t', header=None) # Replace empty cells with empty strings df = df.fillna('') df.columns = ['name', 'full_name', 'comment'] records = df.to_dict('records') full_names = set() for record in records: if record['full_name'] in full_names: warnings.warn( 'Duplicate entry in name index with full name: "{}".'.format( record['full_name'])) continue name_index[record['name']] = record data = dict() for file_path in glob(os.path.join(DIR_PATH, 'raw_data', '*.txt')): name = os.path.split(file_path)[1] # Remove ".txt" and " R" or " L" suffix name = re.sub('\.txt$', '', name) name = re.sub(' (L|R)', '', name) if name not in name_index: warnings.warn( '"{}" missing from name index, skipping.'.format(name)) continue if name_index[name]['comment'] in [ 'ignore', 'onear' ] or not name_index[name]['full_name']: warnings.warn('Skipping "{}".'.format(name)) continue name = name_index[name]['full_name'] if name not in data: data[name] = [] # Read file with open(file_path, 'r') as f: s = f.read() freq = [] raw = [] for line in s.split('\n'): if len(line) == 0 or line[0] == '*': # Skip empty lines and comments if 'C-weighting compensation: On' in line: warnings.warn('C-weighted measurement: ' + name) continue frp = line.split(' ') if len(frp) == 1: frp = line.split('\t') if len(frp) == 2: f, r = frp elif len(frp) == 3: f, r, p = frp else: # Must be comment line continue if f == '?' or r == '?': # Skip lines with missing data continue try: freq.append(float(f)) raw.append(float(r)) except ValueError as err: # Failed to convert values to floats, must be header or comment row, skip continue # Create standard fr object fr = FrequencyResponse(name=name, frequency=freq, raw=raw) fr.interpolate() fr.center() data[name].append(fr) if not os.path.isdir(os.path.join(DIR_PATH, 'inspection')): os.makedirs(os.path.join(DIR_PATH, 'inspection')) # Iterate all models for name, frs in data.items(): # Average SPL data from all measurements for this model (so Left and Right) raw = np.mean([fr.raw for fr in frs], axis=0) # Save as CSV fr = FrequencyResponse(name=name, frequency=frs[0].frequency, raw=raw) dir_path = os.path.join(DIR_PATH, 'data', 'inear', name) if not os.path.isdir(dir_path): os.makedirs(dir_path) fr.write_to_csv(os.path.join(dir_path, name + '.csv')) # Save inspection image fr.plot_graph(show=False, file_path=os.path.join(DIR_PATH, 'inspection', name + '.png')) plt.close()
def parse_image(im, model, channel): """Parses graph image downloaded from innerfidelity.com""" # Find graph edges v_lines = ImageGraphParser.find_lines(im, 'vertical', line_color=(204, 204, 204)) h_lines = ImageGraphParser.find_lines(im, 'horizontal', line_color=(204, 204, 204)) h_lines = np.array(h_lines) # Crop by left and right edges box = (v_lines[0], h_lines[0], v_lines[-1], im.size[1]) im = im.crop(box) h_lines -= h_lines[ 0] # Cropped to first line, subtract distance from all lines # Add missing horizontal lines 115 - 55 deltas = [] for i in range(1, len(h_lines)): deltas.append(h_lines[i] - h_lines[i - 1]) delta = max(deltas, key=deltas.count) _h_lines = list(h_lines[:1]) for _ in range(12): # First line + 12 additional lines # Estimate where the line should be estimate = _h_lines[-1] + delta # Get original lines which are at most 1 pixel away from the estimate originals = h_lines[np.abs(np.array(h_lines) - estimate) <= 1] if len(originals): # Original line found, use it estimate = originals[0] # Add new line _h_lines.append(estimate) h_lines = _h_lines # Crop bottom box = (0, 0, im.size[0], h_lines[-1]) im = im.crop(box) px_a_max = 0 px_a_min = h_lines[-1] #im.show() # X axis f_min = 20 f_max = 20000 f_step = (f_max / f_min)**(1 / im.size[0]) f = [f_min] for _ in range(1, im.size[0]): f.append(f[-1] * f_step) # Y axis a_max = 115 a_min = 55 a_res = (a_max - a_min) / (px_a_min - px_a_max) # Colors color_left = (79, 129, 189) color_right = (119, 119, 119) _im = im.copy() inspection = _im.load() amplitude = [] # Iterate each column for x in range(im.size[0]): pxs = [] # Graph pixels # Iterate each row (pixel in column) for y in range(im.size[1]): # Convert read RGB pixel values and convert to HSV rgba = im.getpixel((x, y)) r, g, b = rgba[:3] # Graph pixels are colored if (channel == 'left' and (r, g, b) == color_left) or (channel == 'right' and (r, g, b) == color_right): pxs.append(float(y)) else: p = im.getpixel((x, y)) inspection[x, y] = (int(0.3 * p[0]), int(255 * 0.7 + 0.3 * p[1]), int(0 + 0.3 * p[2])) if not pxs: # No graph pixels found on this column amplitude.append(None) else: # Mean of recorded pixels v = np.mean(pxs) # Convert to dB value v = a_max - v * a_res amplitude.append(v) # Inspection image draw = ImageDraw.Draw(_im) x0 = np.log(30 / f_min) / np.log(f_step) x1 = np.log(10000 / f_min) / np.log(f_step) y_0 = px_a_max + 10 / a_res y_1 = px_a_min - 10 / a_res draw.rectangle(((x0, y_0), (x1, y_1)), outline='magenta') draw.rectangle(((x0 + 1, y_0 + 1), (x1 - 1, y_1 - 1)), outline='magenta') # Create frequency response fr = FrequencyResponse(model, f, amplitude) fr.interpolate() fr.center() return fr, _im
def process(self, item, url): json_file = Crawler.download(url, item.true_name, os.path.join(DIR_PATH, 'json')) if json_file is not None: with open(os.path.join(DIR_PATH, 'json', f'{item.true_name}.json'), 'r', encoding='utf-8') as fh: json_data = json.load(fh) fr, target = RtingsCrawler.parse_json(json_data) fr.name = item.true_name else: # No frequency response available, download bass, mid and treble # Bass Crawler.download( url.replace('frequency-response-14.json', 'bass.json'), f'{item.true_name}-bass', os.path.join(DIR_PATH, 'json')) with open(os.path.join(DIR_PATH, 'json', f'{item.true_name}-bass.json'), 'r', encoding='utf-8') as fh: bass_fr, bass_target = self.parse_json(json.load(fh)) # Mid Crawler.download( url.replace('frequency-response-14.json', 'mid.json'), f'{item.true_name}-mid', os.path.join(DIR_PATH, 'json')) with open(os.path.join(DIR_PATH, 'json', f'{item.true_name}-mid.json'), 'r', encoding='utf-8') as fh: mid_fr, mid_target = self.parse_json(json.load(fh)) # Treble Crawler.download( url.replace('frequency-response-14.json', 'treble.json'), f'{item.true_name}-treble', os.path.join(DIR_PATH, 'json')) with open(os.path.join(DIR_PATH, 'json', f'{item.true_name}-treble.json'), 'r', encoding='utf-8') as fh: treble_fr, treble_target = self.parse_json(json.load(fh)) fr = FrequencyResponse( name=item.true_name, frequency=np.concatenate( [bass_fr.frequency, mid_fr.frequency, treble_fr.frequency]), raw=np.concatenate([bass_fr.raw, mid_fr.raw, treble_fr.raw])) target = FrequencyResponse(name=item.true_name, frequency=np.concatenate([ bass_target.frequency, mid_target.frequency, treble_target.frequency ]), raw=np.concatenate([ bass_target.raw, mid_target.raw, treble_target.raw ])) fr.interpolate() if np.std(fr.raw) == 0: # Frequency response data has non-zero target response, use that target.interpolate() target = target print(f'Using target for {fr.name}') elif item.form == 'inear': # Using in-ear target response target = INEAR_TARGET else: # Using on-ear or earbud target response target = ONEAR_TARGET target.center() fr.raw += target.raw fr.center() # Inspection dir_path = os.path.join(DIR_PATH, 'inspection') os.makedirs(dir_path, exist_ok=True) file_path = os.path.join(dir_path, f'{fr.name}.png') fig, ax = fr.plot_graph(file_path=file_path, show=False) plt.close(fig) # Write to file dir_path = os.path.join(DIR_PATH, 'data', item.form, fr.name) os.makedirs(dir_path, exist_ok=True) file_path = os.path.join(dir_path, fr.name + '.csv') fr.write_to_csv(file_path) print(f'Saved "{fr.name}" to "{file_path}"')
def main(): data = dict() for file_path in glob(os.path.join(DIR_PATH, 'raw_data', '*.txt')): # Read name of the IEM from file path _, file_name = os.path.split(file_path) name = '.'.join(file_name.split('.')[:-1]) name = name[:-2] # Remove channel from name if name not in data: data[name] = [] # Read file with open(file_path, 'r') as f: s = f.read() freq = [] raw = [] for line in s.split('\n'): if len(line) == 0 or line[0] == '*': # Skip empty lines and comments if 'C-weighting compensation: On' in line: warnings.warn('C-weighted measurement: ' + name) continue frp = line.split(' ') if len(frp) == 1: frp = line.split('\t') if len(frp) == 2: f, r = frp elif len(frp) == 3: f, r, p = frp else: # Must be comment line continue if f == '?' or r == '?': # Skip lines with missing data continue try: freq.append(float(f)) raw.append(float(r)) except ValueError as err: # Failed to convert values to floats, must be header or comment row, skip continue # Create standard fr object fr = FrequencyResponse(name=name, frequency=freq, raw=raw) fr.interpolate() fr.center() data[name].append(fr) if os.path.exists(os.path.join(DIR_PATH, 'inspection')): os.makedirs(os.path.join(DIR_PATH, 'inspection')) # Iterate all models for name, frs in data.items(): # Average SPL data from all measurements for this model (so Left and Right) raw = np.mean([fr.raw for fr in frs], axis=0) # Save as CSV fr = FrequencyResponse(name=name, frequency=frs[0].frequency, raw=raw) fr.write_to_csv(os.path.join(DIR_PATH, 'data', name + '.csv')) # Save inspection image fr.plot_graph(show=False, file_path=os.path.join(DIR_PATH, 'inspection', name + '.png'))