Taiga commited on
Commit
964e88e
·
unverified ·
2 Parent(s): f470699f10a868

Merge pull request #14 from moriyalab/add_stft

Browse files
Files changed (2) hide show
  1. app.py +10 -5
  2. lab_tools/{wavelet.py → spectrogram.py} +37 -19
app.py CHANGED
@@ -1,6 +1,6 @@
1
  import gradio as gr
2
  from moviepy.editor import VideoFileClip
3
- from lab_tools import wavelet
4
  from lab_tools import labutils
5
  from lab_tools import analyze1f
6
  from lab_tools import ytutil
@@ -45,10 +45,15 @@ def update_slidar_range_video_file(file_path):
45
 
46
 
47
  with gr.Blocks() as main_ui:
48
- with gr.Tab("Wavelet"):
49
  with gr.Row():
50
  with gr.Column():
51
  file_input = gr.File(label="CSVファイルをアップロードしてください。", file_count="single", file_types=["csv"])
 
 
 
 
 
52
  fs_slider = gr.Slider(minimum=0, maximum=10000, value=1000, label="サンプリング周波数", step=10, info="単位はHz。")
53
  fmax_slider = gr.Slider(minimum=0, maximum=200, value=60, label="wavelet 最大周波数", step=10, info="単位はHz。")
54
  column_dropdown = gr.Dropdown(["Fp1", "Fp2", "T7", "T8", "O1", "O2"], value="Fp2", label="使用する信号データ", allow_custom_value=True, info="使用する信号データを選んでください。デフォルトはFp2です。")
@@ -76,13 +81,13 @@ with gr.Blocks() as main_ui:
76
  wavelet_image = gr.Image(type="filepath", label="Wavelet")
77
  signal_image = gr.Image(type="filepath", label="Signal")
78
 
79
- submit_button.click(wavelet.wavelet_ui, inputs=[
80
- file_input,
81
  fs_slider, fmax_slider, column_dropdown, start_time, end_time,
82
  filter_setting, fp_hp, fs_hp, gpass, gstop],
83
  outputs=[wavelet_image, signal_image])
84
 
85
- with gr.Tab("1f Noise Search"):
86
  with gr.Row():
87
  with gr.Column():
88
  mode_setting = gr.Radio(
 
1
  import gradio as gr
2
  from moviepy.editor import VideoFileClip
3
+ from lab_tools import spectrogram
4
  from lab_tools import labutils
5
  from lab_tools import analyze1f
6
  from lab_tools import ytutil
 
45
 
46
 
47
  with gr.Blocks() as main_ui:
48
+ with gr.Tab("Spectrogram analyze"):
49
  with gr.Row():
50
  with gr.Column():
51
  file_input = gr.File(label="CSVファイルをアップロードしてください。", file_count="single", file_types=["csv"])
52
+ analysis_method = gr.Radio(
53
+ ["Short-Time Fourier Transform", "Wavelet"],
54
+ label="Analysis method",
55
+ value="Short-Time Fourier Transform",
56
+ )
57
  fs_slider = gr.Slider(minimum=0, maximum=10000, value=1000, label="サンプリング周波数", step=10, info="単位はHz。")
58
  fmax_slider = gr.Slider(minimum=0, maximum=200, value=60, label="wavelet 最大周波数", step=10, info="単位はHz。")
59
  column_dropdown = gr.Dropdown(["Fp1", "Fp2", "T7", "T8", "O1", "O2"], value="Fp2", label="使用する信号データ", allow_custom_value=True, info="使用する信号データを選んでください。デフォルトはFp2です。")
 
81
  wavelet_image = gr.Image(type="filepath", label="Wavelet")
82
  signal_image = gr.Image(type="filepath", label="Signal")
83
 
84
+ submit_button.click(spectrogram.spectrogram_ui, inputs=[
85
+ file_input, analysis_method,
86
  fs_slider, fmax_slider, column_dropdown, start_time, end_time,
87
  filter_setting, fp_hp, fs_hp, gpass, gstop],
88
  outputs=[wavelet_image, signal_image])
89
 
90
+ with gr.Tab("1f noise analyze"):
91
  with gr.Row():
92
  with gr.Column():
93
  mode_setting = gr.Radio(
lab_tools/{wavelet.py → spectrogram.py} RENAMED
@@ -1,14 +1,12 @@
1
  import numpy as np
2
  import matplotlib.pyplot as plt
3
- import math
4
- import tempfile
5
-
6
  from lab_tools import labutils
7
  from lab_tools import filter
 
8
 
9
 
10
- # モルレーウェーブレット関数
11
- def morlet(x, f, width):
12
  sf = f / width
13
  st = 1 / (2 * math.pi * sf)
14
  A = 1 / (st * math.sqrt(2 * math.pi))
@@ -17,7 +15,6 @@ def morlet(x, f, width):
17
  return A * np.exp(co1) * np.exp(h)
18
 
19
 
20
- # 連続ウェーブレット変換
21
  def continuous_wavelet_transform(Fs, data, fmax, width=48, wavelet_R=0.5):
22
  Ts = 1 / Fs
23
  wavelet_length = np.arange(-wavelet_R, wavelet_R, Ts)
@@ -25,13 +22,12 @@ def continuous_wavelet_transform(Fs, data, fmax, width=48, wavelet_R=0.5):
25
  cwt_result = np.zeros([fmax, data_length])
26
 
27
  for i in range(fmax):
28
- conv_result = np.convolve(data, morlet(wavelet_length, i + 1, width), mode='same')
29
  cwt_result[i, :] = (2 * np.abs(conv_result) / Fs) ** 2
30
 
31
  return cwt_result
32
 
33
 
34
- # 連続ウェーブレット変換結果をカラーマップとしてプロット
35
  def plot_cwt(cwt_result, time_data, fmax):
36
  plt.imshow(cwt_result, cmap='jet', aspect='auto',
37
  extent=[time_data[0], time_data[-1], fmax, 0],
@@ -43,9 +39,23 @@ def plot_cwt(cwt_result, time_data, fmax):
43
  plt.gca().invert_yaxis()
44
 
45
 
46
- # グラフ描画とCWTの処理を行う関数
47
- def wavelet_ui(
48
- uploaded_file,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  Fs, fmax, column_name, start_time, end_time,
50
  filter_setting, fp_hp, fs_hp, gpass, gstop):
51
  filepath = uploaded_file.name
@@ -71,19 +81,27 @@ def wavelet_ui(
71
  signal = signal[start_idx:end_idx]
72
  t_data = t_data[start_idx:end_idx]
73
 
74
- signal_filename = tempfile.NamedTemporaryFile(delete=False, suffix='.png').name
75
  plt.figure(dpi=200)
76
  plt.title("Signal")
77
  plt.plot(t_data, signal)
78
  plt.xlim(start_time, end_time)
79
  plt.xlabel("Time [sec]")
80
  plt.ylabel("Voltage [uV]")
 
81
  plt.savefig(signal_filename)
82
 
83
- cwt_signal_filename = tempfile.NamedTemporaryFile(delete=False, suffix='.png').name
84
- cwt_signal = continuous_wavelet_transform(Fs=Fs, data=signal, fmax=fmax)
85
- plt.figure(dpi=200)
86
- plot_cwt(cwt_signal, t_data, fmax)
87
- plt.savefig(cwt_signal_filename)
88
-
89
- return cwt_signal_filename, signal_filename
 
 
 
 
 
 
 
 
1
  import numpy as np
2
  import matplotlib.pyplot as plt
3
+ import scipy.signal as signal
 
 
4
  from lab_tools import labutils
5
  from lab_tools import filter
6
+ import math
7
 
8
 
9
+ def morlet_wavelet(x, f, width):
 
10
  sf = f / width
11
  st = 1 / (2 * math.pi * sf)
12
  A = 1 / (st * math.sqrt(2 * math.pi))
 
15
  return A * np.exp(co1) * np.exp(h)
16
 
17
 
 
18
  def continuous_wavelet_transform(Fs, data, fmax, width=48, wavelet_R=0.5):
19
  Ts = 1 / Fs
20
  wavelet_length = np.arange(-wavelet_R, wavelet_R, Ts)
 
22
  cwt_result = np.zeros([fmax, data_length])
23
 
24
  for i in range(fmax):
25
+ conv_result = np.convolve(data, morlet_wavelet(wavelet_length, i + 1, width), mode='same')
26
  cwt_result[i, :] = (2 * np.abs(conv_result) / Fs) ** 2
27
 
28
  return cwt_result
29
 
30
 
 
31
  def plot_cwt(cwt_result, time_data, fmax):
32
  plt.imshow(cwt_result, cmap='jet', aspect='auto',
33
  extent=[time_data[0], time_data[-1], fmax, 0],
 
39
  plt.gca().invert_yaxis()
40
 
41
 
42
+ def stft_plot_spectrogram(data, Fs, N, freq_limit=None):
43
+ freqs, times, Zxx = signal.stft(data, fs=Fs, window='hann', nperseg=N, noverlap=None)
44
+ amp = np.abs(Zxx)
45
+ amp[amp == 0] = np.finfo(float).eps
46
+ fig, ax = plt.subplots(figsize=(12, 6))
47
+ spectrogram = ax.pcolormesh(times, freqs, np.log10(amp), shading="auto", vmin=0, vmax=5)
48
+ fig.colorbar(spectrogram, ax=ax, orientation="vertical").set_label("Amplitude (dB)")
49
+ ax.set_xlabel("Time [s]")
50
+ ax.set_ylabel("Frequency [Hz]")
51
+ if freq_limit:
52
+ ax.set_ylim([0, freq_limit])
53
+ plt.show()
54
+
55
+
56
+ # グラフ描画とスペクトログラムの処理を行う関数
57
+ def spectrogram_ui(
58
+ uploaded_file, analysis_method,
59
  Fs, fmax, column_name, start_time, end_time,
60
  filter_setting, fp_hp, fs_hp, gpass, gstop):
61
  filepath = uploaded_file.name
 
81
  signal = signal[start_idx:end_idx]
82
  t_data = t_data[start_idx:end_idx]
83
 
84
+ # 信号をプロットして保存
85
  plt.figure(dpi=200)
86
  plt.title("Signal")
87
  plt.plot(t_data, signal)
88
  plt.xlim(start_time, end_time)
89
  plt.xlabel("Time [sec]")
90
  plt.ylabel("Voltage [uV]")
91
+ signal_filename = "signal_plot.png"
92
  plt.savefig(signal_filename)
93
 
94
+ # スペクトログラムをプロットして保存
95
+ if analysis_method == "Short-Time Fourier Transform":
96
+ plt.figure(dpi=200)
97
+ stft_plot_spectrogram(data=signal, Fs=Fs, N=256, freq_limit=fmax)
98
+ spectrogram_filename = "stft_spectrogram_plot.png"
99
+ plt.savefig(spectrogram_filename)
100
+ else:
101
+ spectrogram_filename = "wavelet_spectrogram_plot.png"
102
+ cwt_signal = continuous_wavelet_transform(Fs=Fs, data=signal, fmax=fmax)
103
+ plt.figure(dpi=200)
104
+ plot_cwt(cwt_signal, t_data, fmax)
105
+ plt.savefig(spectrogram_filename)
106
+
107
+ return spectrogram_filename, signal_filename