"""Subclass of FrontPanel, which is generated by wxFormBuilder."""
import wx
import numpy as np
import MainFrame
from dspToolkit import DspToolkit
# Implementing FrontPanel
class WlFrontPanel(MainFrame.FrontPanel):
def __init__(self, parent):
MainFrame.FrontPanel.__init__(self, parent)
# 初期化
# ファイル
self.input_file = ''
# 信号処理クラスのインスタンス化
self.dsp = DspToolkit()
# ファイルダイアログの戻り値定数(条件分岐用)
self.FLAG_OPEN = 5100
self.FLAG_CANCEL = 5101
self.FLAG_YES = 5103
self.FLAG_NO = 5104
# GUI表示器に初期値を格納
# フーリエ変換設定
self.textCtrl_FrameSize.SetValue(str(self.dsp.frame_size))
self.textCtrl_Overlap.SetValue(str(self.dsp.overlap))
self.textCtrl_dBref.SetValue(str(self.dsp.dbref))
# フィルタ設定
self.textCtrl_lp_freq.SetValue(str(self.dsp.lp_freq))
self.textCtrl_hp_freq.SetValue(str(self.dsp.hp_freq))
self.textCtrl_bp_freq_low.SetValue(str(self.dsp.bp_freq_low))
self.textCtrl_bp_freq_high.SetValue(str(self.dsp.bp_freq_high))
self.textCtrl_bs_freq_low.SetValue(str(self.dsp.bs_freq_low))
self.textCtrl_bs_freq_high.SetValue(str(self.dsp.bs_freq_high))
self.textCtrl_attenuation_pass.SetValue(str(self.dsp.attenuation_pass))
self.textCtrl_attenuation_stop.SetValue(str(self.dsp.attenuation_stop))
def file_selector(self, message, extension):
'''指定した拡張子のファイルパスをダイアログで取得する'''
# ダイアログでファイルオープン
open_dialog = wx.FileDialog(None, message, wildcard=extension)
# FLAG_OPEN=5100, FLAG_CANCEL=5101
file_ans = open_dialog.ShowModal()
if file_ans == self.FLAG_OPEN:
print('User selected file open operation.')
self.input_file = open_dialog.GetPath()
print('Selected path is;', self.input_file)
return self.FLAG_OPEN
else:
print('User canceled file open operation.')
return self.FLAG_CANCEL
def time_data_plot(self, time_x, time_y, length):
'''時間波形をプロットしてタブをTime plot(0)に切り替える'''
time_data = self.ax1_time.plot(time_x, time_y, color='red')
# オートスケールで軸設定する場合
self.ax1_time.set_xlim(0, length)
if np.isnan(np.max(time_y)):
message = 'Time waveform has NaN. It may be caused by wrong filter frequency. Time plot will be restored to original.'
wx.MessageBox(message)
print(message)
self.dsp.time_y = self.dsp.time_y_original
time_y = self.dsp.time_y_original
time_data = self.ax1_time.plot(time_x, time_y, color='red')
self.ax1_time.set_ylim(np.min(time_y), np.max(time_y))
self.canvas_timeplot.draw()
line_time = time_data.pop(0)
line_time.remove()
# タブ(wx.Notebook)の切り替え
self.Tab.SetSelection(0)
def clear_freq_plot(self):
'''周波数波形プロットと平均化回数情報をクリアにする'''
fft_data = self.ax1_fft.plot(0, 0)
self.canvas_fftplot.draw()
line_fft = fft_data.pop(0)
line_fft.remove()
self.textCtrl_Average.SetValue('0')
def clear_spec_plot(self):
'''スペクトログラム表示をクリアにする'''
self.cbar.remove()
self.im.remove()
self.ax1_spec.set_ylim(0, 10)
self.im = self.ax1_spec.imshow(np.zeros((10, 10)),
vmin=-1,
vmax=1,
aspect='auto',
cmap='jet')
self.cbar = self.fig_spec.colorbar(self.im)
self.canvas_specplot.draw()
def freq_data_plot(self):
'''読み込んだ時間波形に対しフーリエ変換をかけて周波数プロットする'''
try:
int(self.textCtrl_FrameSize.Value)
int(self.textCtrl_Overlap.Value)
float(self.textCtrl_dBref.Value)
except ValueError:
# 設定値が計算に使えない値の時はエラーメッセージを表示し、周波数プロット/スペクトログラムクリアと表示器の初期化をする。
message = 'Frequency calculation was ignored. Unusable value(s) were entered into frequency calculation setting.'
code = (1, message)
wx.MessageBox(message)
print(code)
self.clear_freq_plot()
self.clear_spec_plot()
return
# 時間波形をオーバーラップ処理する。
time_array, final_time = self.dsp.calc_overlap()
# オーバーラップ処理した波形リストに窓間数をかける。
time_array = self.dsp.hanning(time_array)
# オーバーラップができない場合は処理を終わらせる。
if time_array == []:
message = 'Overlap calculation was ignored. Frame size was larger than data length.'
code = 1, message
wx.MessageBox(message)
print(code)
self.clear_freq_plot()
self.clear_spec_plot()
return
# 平均化フーリエ変化をする。
self.dsp.fft(time_array)
# 周波数波形にプロットする。
if self.checkBox_dBswitch.Value == True:
# dBrefチェックボックスがONの時は振幅をdB変換する。
self.dsp.fft_mean = self.dsp.db(self.dsp.fft_mean, float(self.textCtrl_dBref.Value))
fft_data = self.ax1_fft.plot(self.dsp.fft_axis, self.dsp.fft_mean, color='red')
# オートスケールで軸設定する場合
self.ax1_fft.set_xlim(0, self.dsp.fft_axis[int((len(self.dsp.fft_axis)-1)/2)]) # ナイキスト周波数までの表示
if np.max(self.dsp.fft_mean) == float('inf'):
message = 'Frequency calculation was ignored because of overflow. It may be caused by wrong filter frequency. Time plot will be restored to original.'
wx.MessageBox(message)
print(message)
self.time_data_plot(self.dsp.time_x, self.dsp.time_y_original, self.dsp.length)
self.dsp.time_y = self.dsp.time_y_original
self.clear_freq_plot()
self.clear_spec_plot()
return
else:
self.ax1_fft.set_ylim(np.min(self.dsp.fft_mean), np.max(self.dsp.fft_mean)*1.1)
self.canvas_fftplot.draw()
line_fft = fft_data.pop(0)
line_fft.remove()
# 平均化回数を表示器に入力する。
self.textCtrl_Average.SetValue(str(self.dsp.averaging))
message = 'Frequency calculation was done successfully.'
code = 0, message
print(code)
# スペクトログラム表示
self.spectrogram_plot(self.dsp.fft_array, final_time)
return
def spectrogram_plot(self, fft_array, final_time):
'''スペクトログラム表示をする'''
# オートスケールで軸設定する場合(x軸はself.imで行う仕様)
self.ax1_spec.set_ylim(0, self.dsp.fft_axis[int((len(self.dsp.fft_axis) - 1) / 2)]) # ナイキスト周波数までの表示
if self.checkBox_dBswitch.Value == True:
fft_array = self.dsp.db(fft_array, self.dsp.dbref)
spec_min = np.min(fft_array)
spec_max = np.max(fft_array)
self.cbar.remove()
self.im.remove()
self.im = self.ax1_spec.imshow(fft_array.T,
vmin=spec_min,
vmax=spec_max,
extent=[0, final_time, 0, self.dsp.sampling],
aspect='auto',
cmap='jet')
self.cbar = self.fig_spec.colorbar(self.im)
self.cbar.set_label('Amp.')
self.canvas_specplot.draw()
# Handlers for FrontPanel events.
def FrontPanelOnClose(self, event):
'''ダイアログボックス選択式のウィンドウクローズ'''
# Yes/Noダイアログを使ってユーザに選択させる。
message_dialog = wx.MessageDialog(None, 'Do you really want to close window?', 'Window close dialog', wx.YES_NO)
ans = message_dialog.ShowModal()
# FLAG_YES=5103, FLAG_NO=5104
if ans == self.FLAG_YES:
print('User selected YES button to close window.')
self.Destroy()
def Button_open_wavOnButtonClick(self, event):
'''wavファイルを開き時間波形を表示させる'''
print('Open.wav was clicked.')
# ファイルダイアログを開きwavファイルのパスを取得する。
ans = self.file_selector(message='Select a wav file.', extension='*.wav')
# Open操作の時のみ操作を実行する。
if ans == self.FLAG_OPEN:
self.dsp.open_wav(self.input_file)
# 時間波形情報をTextCtrlに表示する。
self.textCtrl_dt.SetValue(str('{:.4e}'.format(self.dsp.dt)))
self.textCtrl_Samplingrate.SetValue(str(self.dsp.sampling))
self.textCtrl_length.SetValue(str(np.round(self.dsp.length, 2)))
# 時間波形をプロットする。
self.time_data_plot(self.dsp.time_x, self.dsp.time_y, self.dsp.length)
# フーリエ変換をして周波数波形をプロットする。
self.freq_data_plot()
def Button_open_csvOnButtonClick(self, event):
'''csvファイルを開き時間波形を表示させる'''
print('Open.csv was clicked.')
# ファイルダイアログを開きwavファイルのパスを取得する。
ans = self.file_selector(message='Select a csv file.', extension='*.csv')
# Open操作の時のみ操作を実行する。
if ans == self.FLAG_OPEN:
self.dsp.open_csv(self.input_file)
# 時間波形情報をTextCtrlに表示する。
self.textCtrl_dt.SetValue(str('{:.4e}'.format(self.dsp.dt)))
self.textCtrl_Samplingrate.SetValue(str(self.dsp.sampling))
self.textCtrl_length.SetValue(str(np.round(self.dsp.length, 2)))
# 時間波形をプロットする。
self.time_data_plot(self.dsp.time_x, self.dsp.time_y, self.dsp.length)
# フーリエ変換をして周波数波形をプロットする。
self.freq_data_plot()
def Button_save_wavOnButtonClick(self, event):
# TODO: Implement Button_save_wavOnButtonClick
pass
def Button_save_csvOnButtonClick(self, event):
# TODO: Implement Button_save_csvOnButtonClick
pass
def Button_Save_fft_csvOnButtonClick(self, event):
# TODO: Implement Button_Save_fft_csvOnButtonClick
pass
def textCtrl_FrameSizeOnText(self, event):
print('Set frame size.')
try:
self.dsp.frame_size = int(self.textCtrl_FrameSize.Value)
except ValueError:
pass
def textCtrl_OverlapOnText(self, event):
print('Set overlap ratio.')
try:
self.dsp.overlap = int(self.textCtrl_Overlap.Value)
except ValueError:
pass
def textCtrl_dBrefOnText(self, event):
print('Set dB-reference.')
try:
self.dsp.dbref = float(self.textCtrl_dBref.Value)
except ValueError:
pass
def Button_re_calcOnButtonClick(self, event):
print('User clicked re-calculation button.')
self.freq_data_plot()
def Button_lpOnButtonClick(self, event):
print('User clicked lowpass button.')
try:
float(self.textCtrl_lp_freq.Value)
except ValueError:
pass
return
ret = self.dsp.filter('low')
if ret == -1:
wx.MessageBox('Error! Ignored filter calculation. Frequency range is out of range.')
else:
self.time_data_plot(self.dsp.time_x, self.dsp.time_y, self.dsp.length)
self.freq_data_plot()
def textCtrl_lp_freqOnText(self, event):
print('Set frequency for lowpass.')
try:
self.dsp.lp_freq = float(self.textCtrl_lp_freq.Value)
except ValueError:
pass
def Button_hpOnButtonClick(self, event):
print('User clicked highpass button.')
try:
float(self.textCtrl_lp_freq.Value)
except ValueError:
pass
return
ret = self.dsp.filter('high')
if ret == -1:
wx.MessageBox('Error! Ignored filter calculation. Frequency range is out of range.')
else:
self.time_data_plot(self.dsp.time_x, self.dsp.time_y, self.dsp.length)
self.freq_data_plot()
def textCtrl_hp_freqOnText(self, event):
print('Set frequency for highpass.')
try:
self.dsp.hp_freq = float(self.textCtrl_hp_freq.Value)
except ValueError:
pass
def textCtrl_attenuation_passOnText(self, event):
print('Set attenuation_pass.')
try:
self.dsp.attenuation_pass = float(self.textCtrl_attenuation_pass.Value)
except ValueError:
pass
def textCtrl_attenuation_stopOnText(self, event):
print('Set attenuation_stop.')
try:
self.dsp.attenuation_stop = float(self.textCtrl_attenuation_stop.Value)
except ValueError:
pass
def Button_bpOnButtonClick(self, event):
print('User clicked bandpass button.')
try:
float(self.textCtrl_bp_freq_low.Value)
float(self.textCtrl_bp_freq_high.Value)
except ValueError:
pass
return
ret = self.dsp.filter('band')
if ret == -1:
wx.MessageBox('Error! Ignored filter calculation. Frequency range is out of range.')
else:
self.time_data_plot(self.dsp.time_x, self.dsp.time_y, self.dsp.length)
self.freq_data_plot()
def textCtrl_bp_freq_lowOnText(self, event):
print('Set lower frequency for bandpass.')
try:
self.dsp.bp_freq_low = float(self.textCtrl_bp_freq_low.Value)
except ValueError:
pass
def textCtrl_bp_freq_highOnText(self, event):
print('Set upper frequency for bandpass.')
try:
self.dsp.bp_freq_high = float(self.textCtrl_bp_freq_high.Value)
except ValueError:
pass
def Button_bsOnButtonClick(self, event):
print('User clicked bandstop button.')
try:
float(self.textCtrl_bs_freq_low.Value)
float(self.textCtrl_bs_freq_high.Value)
except ValueError:
pass
return
ret = self.dsp.filter('bandstop')
if ret == -1:
wx.MessageBox('Error! Ignored filter calculation. Frequency range is out of range.')
else:
self.time_data_plot(self.dsp.time_x, self.dsp.time_y, self.dsp.length)
self.freq_data_plot()
def textCtrl_bs_freq_lowOnText(self, event):
print('Set lower frequency for bandstop.')
try:
self.dsp.bs_freq_low = float(self.textCtrl_bs_freq_low.Value)
except ValueError:
pass
def textCtrl_bs_freq_highOnText(self, event):
print('Set upper frequency for bandpass.')
try:
self.dsp.bs_freq_high = float(self.textCtrl_bs_freq_high.Value)
except ValueError:
pass
def Button_original_dataOnButtonClick(self, event):
print('User clicked restore button.')
self.dsp.time_y = self.dsp.time_y_original
self.time_data_plot(self.dsp.time_x, self.dsp.time_y, self.dsp.length)
self.freq_data_plot()
def checkbox_time_fixOnCheckBox(self, event):
# TODO: Implement checkbox_time_fixOnCheckBox
pass
def textCtrl_time_xminOnText(self, event):
# TODO: Implement textCtrl_time_xminOnText
pass
def textCtrl_time_xmaxOnText(self, event):
# TODO: Implement textCtrl_time_xmaxOnText
pass
def textCtrl_time_yminOnText(self, event):
# TODO: Implement textCtrl_time_yminOnText
pass
def textCtrl_ymaxOnText(self, event):
# TODO: Implement textCtrl_ymaxOnText
pass
def checkbox_freq_fixOnCheckBox(self, event):
# TODO: Implement checkbox_freq_fixOnCheckBox
pass
def textCtrl_freq_xminOnText(self, event):
# TODO: Implement textCtrl_freq_xminOnText
pass
def textCtrl_freq_xmaxOnText(self, event):
# TODO: Implement textCtrl_freq_xmaxOnText
pass
def textCtrl_freq_yminOnText(self, event):
# TODO: Implement textCtrl_freq_yminOnText
pass
def textCtrl_freq_ymaxOnText(self, event):
# TODO: Implement textCtrl_freq_ymaxOnText
pass
お世話になっております。大変、参考にさせていただいております。
初めてコメントをさせていただきますので、コメント内容等失礼がありましたら
すみません。質問などは受け付けていますでしょうか?もし受け付けているので
ありましたら、ご教授よろしくお願いいたします。
<質問内容>
“Pythonでテキストファイル内を検索して値を抽出する方法”の
“文字列を一部含むか/行内位置不定で検索(in)”の項目のなかで最終的に
linesというリストを取得することができましたが、何行目を[6, 15, 23]ではなく
linesを使って出力するにはどうしたら良いでしょうか?
print(text_line[6, 15, 23])ではなく、linesなどを使って指示をしたいです。
手動で6, 15, 23を入力するのが、困難だからです。
また、次にその行の何番目の文字を取得するという操作をしたいです。
print(text_line[6][:4])ではなく、linesなどを使って指示をしたいです。
以上、ご指導よろしくお願いいたします。
ご訪問ありがとうございます。
質問は歓迎ですよ。ただどうやらこの記事の質問ではないようです。
「Pythonでテキストファイル内を検索して値を抽出する方法」の記事でコメントしていただけると、他の方からの返信も期待できます。
以下回答です。
○行目、という情報は既にlinesに入っていますので、手動で数値を入力しなくても、lines[i]のようにインデックスを使って抽出することが可能です。
↓例:このコードをサンプルの一番下に書いて実行
for i in range(len(lines)):
print(text_line[lines[i]])
print(text_line[lines[i]][:4])
forループ内1行目がlinesを使って行を抽出する例、
2行目がさらに一定文字を取得する例です。
以上、ちょっと考えてみましたが、もし質問の意図と回答がずれている場合はお知らせください。
よろしくお願い致します。