taigatakano commited on
Commit
dd35a1d
·
1 Parent(s): 146c081

THE UPDATE

Browse files
Files changed (4) hide show
  1. app.py +12 -2
  2. lab_tools/labutils.py +26 -0
  3. lab_tools/spectrogram.py +200 -72
  4. unit_test.py +45 -0
app.py CHANGED
@@ -84,6 +84,14 @@ with gr.Blocks() as main_ui:
84
  )
85
  fs_slider = gr.Slider(minimum=0, maximum=10000, value=1000, label="サンプリング周波数", step=10, info="単位はHz。")
86
  column_dropdown = gr.Dropdown(["Fp1", "Fp2", "T7", "T8", "O1", "O2"], value="Fp2", label="使用する信号データ", allow_custom_value=True, info="使用する信号データを選んでください。デフォルトはFp2です。")
 
 
 
 
 
 
 
 
87
 
88
  submit_button = gr.Button("計算開始")
89
 
@@ -94,6 +102,7 @@ with gr.Blocks() as main_ui:
94
  )
95
 
96
  with gr.Column():
 
97
  wavelet_image = gr.Image(type="filepath", label="Spectrogram")
98
  band_intensity = gr.Image(type="filepath", label="Band Intensity")
99
  signal_image = gr.Image(type="filepath", label="Signal")
@@ -101,8 +110,9 @@ with gr.Blocks() as main_ui:
101
  submit_button.click(spectrogram.generate_spectrogram_and_signal_plot, inputs=[
102
  file_input, analysis_method,
103
  fs_slider, fmax_slider, column_dropdown, start_time, end_time,
104
- filter_setting, fp_hp, fs_hp, gpass, gstop, band_intensity_setting],
105
- outputs=[wavelet_image, band_intensity, signal_image])
 
106
 
107
  with gr.Tab("1f noise analyze"):
108
  with gr.Row():
 
84
  )
85
  fs_slider = gr.Slider(minimum=0, maximum=10000, value=1000, label="サンプリング周波数", step=10, info="単位はHz。")
86
  column_dropdown = gr.Dropdown(["Fp1", "Fp2", "T7", "T8", "O1", "O2"], value="Fp2", label="使用する信号データ", allow_custom_value=True, info="使用する信号データを選んでください。デフォルトはFp2です。")
87
+ integration_method = gr.Radio(
88
+ ["Trapezoid(台形積分)", "Simpson(シンプソン法)"],
89
+ label="Integration Method",
90
+ value="Simpson(シンプソン法)",
91
+ )
92
+ segment_length = gr.Slider(minimum=0, maximum=8192, value=4096, step=1, label="STFT: セグメント長")
93
+ overlap = gr.Slider(minimum=0, maximum=99, value=90, step=1, label="STFT: オーバーラップ率 [%]")
94
+ fontsize = gr.Slider(minimum=0, maximum=20, value=12, step=1, label="グラフのフォントサイズ")
95
 
96
  submit_button = gr.Button("計算開始")
97
 
 
102
  )
103
 
104
  with gr.Column():
105
+ config_file = gr.File(label="Ziped Analyze File")
106
  wavelet_image = gr.Image(type="filepath", label="Spectrogram")
107
  band_intensity = gr.Image(type="filepath", label="Band Intensity")
108
  signal_image = gr.Image(type="filepath", label="Signal")
 
110
  submit_button.click(spectrogram.generate_spectrogram_and_signal_plot, inputs=[
111
  file_input, analysis_method,
112
  fs_slider, fmax_slider, column_dropdown, start_time, end_time,
113
+ filter_setting, fp_hp, fs_hp, gpass, gstop, band_intensity_setting,
114
+ integration_method, segment_length, overlap, fontsize],
115
+ outputs=[wavelet_image, band_intensity, signal_image, config_file])
116
 
117
  with gr.Tab("1f noise analyze"):
118
  with gr.Row():
lab_tools/labutils.py CHANGED
@@ -22,3 +22,29 @@ def load_signal(file_path, column_name):
22
  except KeyError as e:
23
  print(f"Column '{column_name}' not found in the file. ({e})", file=sys.stderr)
24
  return []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  except KeyError as e:
23
  print(f"Column '{column_name}' not found in the file. ({e})", file=sys.stderr)
24
  return []
25
+
26
+
27
+ def band_intensity_setting_to_band(input: str):
28
+ if "GAMMA" in input:
29
+ return (30, 36)
30
+ elif "BETA" in input:
31
+ return (15, 30)
32
+ elif "ALPHA" in input:
33
+ return (8, 12)
34
+ elif "THETA" in input:
35
+ return (4, 8)
36
+ elif "DELTA" in input:
37
+ return (0, 4)
38
+ else:
39
+ print("Unknown band")
40
+ return (None, None)
41
+
42
+
43
+ def integration_method_to_method(input: str):
44
+ if "Trapezoid" in input:
45
+ return "trapz"
46
+ elif "Simpson" in input:
47
+ return "simps"
48
+ else:
49
+ print("Unknown method")
50
+ return None
lab_tools/spectrogram.py CHANGED
@@ -1,32 +1,16 @@
 
 
 
 
 
1
  import numpy as np
2
  import matplotlib.pyplot as plt
3
  import scipy.signal as signal
4
  from scipy.signal import fftconvolve
 
 
5
  from lab_tools import labutils
6
  from lab_tools import filter
7
- import math
8
- import os
9
-
10
-
11
- def band_intensity_setting_to_band(input: str):
12
- if "GAMMA" in input:
13
- print("GAMMA")
14
- return (30, 36)
15
- elif "BETA" in input:
16
- print("BETA")
17
- return (15, 30)
18
- elif "ALPHA" in input:
19
- print("ALPHA")
20
- return (8, 12)
21
- elif "THETA" in input:
22
- print("THETA")
23
- return (4, 8)
24
- elif "DELTA" in input:
25
- print("DELTA")
26
- return (0, 4)
27
- else:
28
- print("Unknown")
29
- return (0, 0)
30
 
31
 
32
  # モルレーウェーブレットの計算
@@ -60,14 +44,14 @@ def perform_cwt(sample_rate, signal_data, max_frequency, wavelet_width=48, wavel
60
 
61
 
62
  # CWTの結果をプロットする関数
63
- def plot_cwt_result(cwt_matrix, time_array, max_frequency):
64
  plt.subplots(figsize=(12, 6))
65
  plt.imshow(cwt_matrix, cmap='jet', aspect='auto',
66
  extent=[time_array[0], time_array[-1], max_frequency, 0],
67
  vmax=abs(cwt_matrix).max(), vmin=-abs(cwt_matrix).max())
68
- plt.xlabel("Time [sec]")
69
- plt.ylabel("Frequency [Hz]")
70
- plt.colorbar(label="Power")
71
  plt.clim(0, 5)
72
  plt.gca().invert_yaxis()
73
 
@@ -91,7 +75,7 @@ def perform_stft(signal_data, sample_rate: int, segment_length: int, overlap=0.5
91
 
92
 
93
  # 短時間フーリエ変換 (STFT) のスペクトログラムをプロットする関数
94
- def plot_stft_spectrogram(amplitude, frequencies, times, max_frequency=None):
95
  """
96
  Parameters:
97
  amplitude (np.ndarray): 信号強度データ
@@ -103,55 +87,194 @@ def plot_stft_spectrogram(amplitude, frequencies, times, max_frequency=None):
103
 
104
  fig, ax = plt.subplots(figsize=(12, 6))
105
  spectrogram = ax.pcolormesh(times, frequencies, amplitude, cmap='jet', shading="gourand", vmin=0, vmax=5)
106
- fig.colorbar(spectrogram, ax=ax, orientation="vertical").set_label("Power")
107
- ax.set_xlabel("Time [s]")
108
- ax.set_ylabel("Frequency [Hz]")
109
 
110
  # 最大周波数の設定
111
  if max_frequency:
112
  ax.set_ylim([0, max_frequency])
113
 
114
 
115
- def plot_frequency_band_intensity(
116
- time_array, frequency_array, analysis_matrix, freq_band, method="STFT",):
 
 
 
 
 
 
 
 
 
 
117
  """
118
- 特定の周波数帯の強度変化プロットする関数
119
 
120
  Parameters:
121
- time_array (np.ndarray): 時間配列
122
  frequency_array (np.ndarray): 周波数配列 (STFT の場合は frequency、CWT の場合は range(max_frequency))
123
  analysis_matrix (np.ndarray): CWT または STFT の解析結果
124
- freq_band (tuple): 表示する周波数帯 (例: (10, 20))
125
  method (str): 解析手法 ("STFT" または "CWT")
 
 
 
 
126
  """
127
  # 周波数インデックスの範囲を取得
128
  freq_start, freq_end = freq_band
129
  if method == "STFT":
130
  freq_indices = np.where((frequency_array >= freq_start) & (frequency_array <= freq_end))[0]
 
131
  elif method == "CWT":
132
  freq_indices = range(freq_start, freq_end + 1)
 
133
  else:
134
  raise ValueError("Invalid method. Use 'STFT' or 'CWT'.")
135
 
136
- # 指定した周波数帯域の強度平均化
137
- band_intensity = analysis_matrix[freq_indices, :].mean(axis=0)
138
 
139
- # プロット
140
- plt.figure(figsize=(10, 5))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  plt.plot(time_array, band_intensity)
142
- plt.xlabel("Time [sec]")
143
- plt.ylabel("Power")
144
- plt.title(f"Frequency Band Intensity ({freq_start}~{freq_end} Hz)")
145
- plt.legend()
146
  plt.grid()
147
 
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  # UI処理: スペクトログラム生成・信号プロット
150
  def generate_spectrogram_and_signal_plot(
151
  uploaded_file, analysis_method,
152
  sample_rate, max_frequency, signal_column_name, start_time, end_time,
153
  filter_type, highpass_cutoff, stopband_cutoff, passband_ripple, stopband_attenuation,
154
- band_intensity_setting):
 
155
  file_path = uploaded_file.name
156
  file_basename = os.path.basename(file_path)
157
 
@@ -159,7 +282,7 @@ def generate_spectrogram_and_signal_plot(
159
  if len(signal_data) == 0:
160
  return None, None
161
 
162
- output_dir = "/tmp/spectrogram/"
163
  os.makedirs(output_dir, exist_ok=True)
164
 
165
  # フィルタ処理
@@ -182,55 +305,60 @@ def generate_spectrogram_and_signal_plot(
182
 
183
  # 信号プロットの保存
184
  window_size = 50
185
- smoothed_signal = np.convolve(signal_data, np.ones(window_size) / window_size, mode='valid')
186
- trimmed_time_array = time_array[:len(smoothed_signal)]
187
-
188
- title = f"Signal(File: {file_basename}, Convolve Window Size: {window_size})"
189
-
190
  plt.figure(dpi=200)
191
- plt.subplots(figsize=(12, 6))
192
- plt.title(title)
193
- plt.plot(trimmed_time_array, smoothed_signal)
194
- plt.xlim(start_time, end_time)
195
- plt.xlabel("Time [sec]")
196
- plt.ylabel("Voltage [uV]")
197
  signal_plot_path = os.path.join(output_dir, "signal_plot.png")
198
  plt.savefig(signal_plot_path)
199
 
200
- freq_start, freq_end = band_intensity_setting_to_band(band_intensity_setting)
 
 
201
 
202
  # スペクトログラムプロットの保存
203
  if analysis_method == "Short-Time Fourier Transform":
204
- frequencies, times, amplitude = perform_stft(signal_data, sample_rate, 4096, 0.9)
205
 
206
  plt.figure(dpi=200)
207
- plot_stft_spectrogram(amplitude, frequencies, times, max_frequency)
208
  spectrogram_plot_path = os.path.join(output_dir, "stft_spectrogram_plot.png")
209
- title = f"Spectrogram (File: {file_basename}, Method: STFT, Fs: {sample_rate} Hz, Segment Length: {4096}, Overlap: {0.9*100:.0f}%)"
210
- plt.title(title)
211
  plt.savefig(spectrogram_plot_path)
212
 
213
  plt.figure(dpi=200)
214
- plot_frequency_band_intensity(times, frequencies, amplitude, (freq_start, freq_end), method="STFT")
 
215
  plot_frequency_band_intensity_path = os.path.join(output_dir, "band_intensity.png")
216
- title = f"Band Intensity (File: {file_basename}, {freq_start}~{freq_end} Hz Band Intensity)"
217
- plt.title(title)
218
  plt.savefig(plot_frequency_band_intensity_path)
219
 
 
 
 
220
  else:
221
  spectrogram_plot_path = os.path.join(output_dir, "wavelet_spectrogram_plot.png")
222
  cwt_matrix = perform_cwt(sample_rate, signal_data, max_frequency)
223
  plt.figure(dpi=200)
224
- plot_cwt_result(cwt_matrix, time_array, max_frequency)
225
- title = f"Spectrogram (File: {file_basename}, Method: Wavelet, Fs: {sample_rate} Hz, Wavelet Width: {48})"
226
- plt.title(title)
227
  plt.savefig(spectrogram_plot_path)
228
 
229
  plt.figure(dpi=200)
230
- plot_frequency_band_intensity(times, frequencies, amplitude, (freq_start, freq_end), method="CWT")
 
231
  plot_frequency_band_intensity_path = os.path.join(output_dir, "band_intensity.png")
232
- title = f"Band Intensity (File: {file_basename}, {freq_start}~{freq_end} Hz Band Intensity)"
233
- plt.title(title)
234
  plt.savefig(plot_frequency_band_intensity_path)
235
 
236
- return spectrogram_plot_path, plot_frequency_band_intensity_path, signal_plot_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import os
3
+ import yaml
4
+ import subprocess
5
+ import uuid
6
  import numpy as np
7
  import matplotlib.pyplot as plt
8
  import scipy.signal as signal
9
  from scipy.signal import fftconvolve
10
+ from scipy.integrate import simpson, trapezoid
11
+ import pandas as pd
12
  from lab_tools import labutils
13
  from lab_tools import filter
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
 
16
  # モルレーウェーブレットの計算
 
44
 
45
 
46
  # CWTの結果をプロットする関数
47
+ def plot_cwt_result(cwt_matrix, time_array, max_frequency, fontsize=12):
48
  plt.subplots(figsize=(12, 6))
49
  plt.imshow(cwt_matrix, cmap='jet', aspect='auto',
50
  extent=[time_array[0], time_array[-1], max_frequency, 0],
51
  vmax=abs(cwt_matrix).max(), vmin=-abs(cwt_matrix).max())
52
+ plt.xlabel("Time [sec]", fontsize=fontsize)
53
+ plt.ylabel("Frequency [Hz]", fontsize=fontsize)
54
+ plt.colorbar().set_label("Power", fontsize=fontsize)
55
  plt.clim(0, 5)
56
  plt.gca().invert_yaxis()
57
 
 
75
 
76
 
77
  # 短時間フーリエ変換 (STFT) のスペクトログラムをプロットする関数
78
+ def plot_stft_spectrogram(amplitude, frequencies, times, max_frequency=None, fontsize=12):
79
  """
80
  Parameters:
81
  amplitude (np.ndarray): 信号強度データ
 
87
 
88
  fig, ax = plt.subplots(figsize=(12, 6))
89
  spectrogram = ax.pcolormesh(times, frequencies, amplitude, cmap='jet', shading="gourand", vmin=0, vmax=5)
90
+ fig.colorbar(spectrogram, ax=ax, orientation="vertical").set_label("Power", fontsize=fontsize)
91
+ ax.set_xlabel("Time [s]", fontsize=fontsize)
92
+ ax.set_ylabel("Frequency [Hz]", fontsize=fontsize)
93
 
94
  # 最大周波数の設定
95
  if max_frequency:
96
  ax.set_ylim([0, max_frequency])
97
 
98
 
99
+ def plot_signal(signal_data, time_data, start_time, end_time, fontsize, window_size=50):
100
+ smoothed_signal = np.convolve(signal_data, np.ones(window_size) / window_size, mode='valid')
101
+ trimmed_time_array = time_data[:len(smoothed_signal)]
102
+ plt.subplots(figsize=(12, 6))
103
+ plt.plot(trimmed_time_array, smoothed_signal)
104
+ plt.xlim(start_time, end_time)
105
+ plt.xlabel("Time [sec]", fontsize=fontsize)
106
+ plt.ylabel("Voltage [uV]", fontsize=fontsize)
107
+
108
+
109
+ def calculate_frequency_band_intensity(
110
+ frequency_array, analysis_matrix, freq_band, method="STFT", integration_method="simps"):
111
  """
112
+ 特定の周波数帯の強度を計算する関数
113
 
114
  Parameters:
 
115
  frequency_array (np.ndarray): 周波数配列 (STFT の場合は frequency、CWT の場合は range(max_frequency))
116
  analysis_matrix (np.ndarray): CWT または STFT の解析結果
117
+ freq_band (tuple): 計算する周波数帯 (例: (10, 20))
118
  method (str): 解析手法 ("STFT" または "CWT")
119
+ integration_method (str): 数値積分の手法 ("trapz" または "simps")
120
+
121
+ Returns:
122
+ band_intensity (np.ndarray): 指定周波数帯域の強度の時間変化
123
  """
124
  # 周波数インデックスの範囲を取得
125
  freq_start, freq_end = freq_band
126
  if method == "STFT":
127
  freq_indices = np.where((frequency_array >= freq_start) & (frequency_array <= freq_end))[0]
128
+ freq_values = frequency_array[freq_indices]
129
  elif method == "CWT":
130
  freq_indices = range(freq_start, freq_end + 1)
131
+ freq_values = np.arange(freq_start, freq_end + 1) # 仮の周波数配列
132
  else:
133
  raise ValueError("Invalid method. Use 'STFT' or 'CWT'.")
134
 
135
+ # 指定した周波数帯域の解析データ抽��
136
+ selected_matrix = analysis_matrix[freq_indices, :]
137
 
138
+ # 積分の実行
139
+ if integration_method == "trapz":
140
+ band_intensity = trapezoid(selected_matrix, x=freq_values, axis=0)
141
+ elif integration_method == "simps":
142
+ band_intensity = simpson(selected_matrix, x=freq_values, axis=0)
143
+ else:
144
+ raise ValueError("Invalid integration method. Use 'trapz' or 'simps'.")
145
+
146
+ return band_intensity
147
+
148
+
149
+ def plot_frequency_band_intensity(
150
+ time_array, band_intensity, fontsize=12):
151
+ """
152
+ 特定の周波数帯の強度変化をプロットする関数
153
+
154
+ Parameters:
155
+ time_array (np.ndarray): 時間配列
156
+ band_intensity (np.ndarray): 指定周波数帯域の強度の時間変化
157
+ freq_band (tuple): 表示する周波数帯 (例: (10, 20))
158
+ fontsize (int): プロットのフォントサイズ
159
+ """
160
+ plt.figure(figsize=(12, 6))
161
  plt.plot(time_array, band_intensity)
162
+ plt.xlabel("Time [sec]", fontsize=fontsize)
163
+ plt.ylabel("Integrated Power", fontsize=fontsize)
 
 
164
  plt.grid()
165
 
166
 
167
+ def save_all_data_to_csv(
168
+ time_array, frequency_array, analysis_matrix, output_path, method="STFT", integration_method="simps"):
169
+ """
170
+ 時間・周波数帯の解析データをCSVファイルに保存する関数 (pandasを使用)
171
+
172
+ Parameters:
173
+ time_array (np.ndarray): 時間配列
174
+ frequency_array (np.ndarray): 周波数配列
175
+ analysis_matrix (np.ndarray): STFTまたはCWTの解析結果
176
+ output_path (str): 保存先のCSVファイルパス
177
+ method (str): 解析手法 ("STFT" または "CWT")
178
+ integration_method (str): 数値積分の手法 ("trapz" または "simps")
179
+ """
180
+ # 各帯域の強度を計算
181
+ gamma = calculate_frequency_band_intensity(frequency_array, analysis_matrix, (30, 36), method, integration_method)
182
+ beta = calculate_frequency_band_intensity(frequency_array, analysis_matrix, (15, 30), method, integration_method)
183
+ alpha = calculate_frequency_band_intensity(frequency_array, analysis_matrix, (8, 12), method, integration_method)
184
+ theta = calculate_frequency_band_intensity(frequency_array, analysis_matrix, (4, 8), method, integration_method)
185
+ delta = calculate_frequency_band_intensity(frequency_array, analysis_matrix, (0, 4), method, integration_method)
186
+
187
+ # pandas DataFrameにまとめる
188
+ data = {
189
+ "Time [sec]": time_array,
190
+ "Gamma [30-36 Hz]": gamma,
191
+ "Beta [15-30 Hz]": beta,
192
+ "Alpha [8-12 Hz]": alpha,
193
+ "Theta [4-8 Hz]": theta,
194
+ "Delta [0-4 Hz]": delta
195
+ }
196
+ df = pd.DataFrame(data)
197
+
198
+ # CSVファイルに書き込み
199
+ df.to_csv(output_path, index=False)
200
+
201
+
202
+ def export_arguments_to_yaml(
203
+ uploaded_file, analysis_method, sample_rate, max_frequency,
204
+ signal_column_name, start_time, end_time, filter_type,
205
+ highpass_cutoff, stopband_cutoff, passband_ripple, stopband_attenuation,
206
+ band_intensity_setting, integration_method, segment_length, overlap,
207
+ output_path="arguments.yaml"):
208
+ """
209
+ generate_spectrogram_and_signal_plotの引数をわかりやすい形式でYAMLに書き出す関数
210
+
211
+ Parameters:
212
+ 各引数: generate_spectrogram_and_signal_plotの引数
213
+ output_path (str): 書き出すYAMLファイルのパス
214
+ """
215
+ arguments = {
216
+ "input_file": uploaded_file, # アップロードされたファイル
217
+ "analysis": {
218
+ "method": analysis_method, # 使用する解析手法
219
+ "sample_rate_hz": sample_rate, # サンプリングレート
220
+ "max_frequency_hz": max_frequency, # 最大周波数
221
+ "time_range_sec": {
222
+ "start": start_time, # 開始時間
223
+ "end": end_time # 終了時間
224
+ }
225
+ },
226
+ "signal_processing": {
227
+ "signal_column": signal_column_name, # 信号データが格納された列名
228
+ "filter": {
229
+ "type": filter_type, # フィルタタイプ (High Pass, Low Pass など)
230
+ "highpass_cutoff_hz": highpass_cutoff, # ハイパスフィルタのカットオフ周波数
231
+ "stopband_cutoff_hz": stopband_cutoff, # ストップバンドのカットオフ周波数
232
+ "passband_ripple_db": passband_ripple, # パスバンドのリップル
233
+ "stopband_attenuation_db": stopband_attenuation # ストップバンドの減衰量
234
+ }
235
+ },
236
+ "frequency_analysis": {
237
+ "band_of_interest": band_intensity_setting, # 強度を解析する周波数帯 (例: Gamma, Beta など)
238
+ "integration_method": integration_method, # 数値積分の手法 (Simpson, Trapezoidal など)
239
+ },
240
+ "stft_settings": {
241
+ "segment_length_samples": segment_length, # セグメント長 (サンプル数)
242
+ "overlap_ratio": overlap # セグメントのオーバーラップ率
243
+ }
244
+ }
245
+
246
+ # YAMLファイルに書き出し
247
+ with open(output_path, "w") as yaml_file:
248
+ yaml.dump(arguments, yaml_file, default_flow_style=False, allow_unicode=True)
249
+
250
+
251
+ def zip_directory_with_command(directory_path, output_zip_path):
252
+ """
253
+ zipコマンドを使ってディレクトリを圧縮する関数。
254
+
255
+ Args:
256
+ directory_path (str): 圧縮するディレクトリのパス。
257
+ output_zip_path (str): 出力するzipファイルのパス。
258
+ """
259
+ try:
260
+ # zipコマンドを実行
261
+ subprocess.run(['zip', '-j', '-r', output_zip_path, directory_path], check=True)
262
+ print(f"{output_zip_path} に圧縮しました。")
263
+ except FileNotFoundError:
264
+ print("zipコマンドが見つかりません。インストールされているか確認してください。")
265
+ except subprocess.CalledProcessError as e:
266
+ print(f"zipコマンドの実行に失敗しました: {e}")
267
+
268
+ return output_zip_path
269
+
270
+
271
  # UI処理: スペクトログラム生成・信号プロット
272
  def generate_spectrogram_and_signal_plot(
273
  uploaded_file, analysis_method,
274
  sample_rate, max_frequency, signal_column_name, start_time, end_time,
275
  filter_type, highpass_cutoff, stopband_cutoff, passband_ripple, stopband_attenuation,
276
+ band_intensity_setting, integration_method, segment_length, overlap, fontsize):
277
+
278
  file_path = uploaded_file.name
279
  file_basename = os.path.basename(file_path)
280
 
 
282
  if len(signal_data) == 0:
283
  return None, None
284
 
285
+ output_dir = os.path.join("/tmp/spectrogram/", str(uuid.uuid1())[0:20].replace("-", ""))
286
  os.makedirs(output_dir, exist_ok=True)
287
 
288
  # フィルタ処理
 
305
 
306
  # 信号プロットの保存
307
  window_size = 50
 
 
 
 
 
308
  plt.figure(dpi=200)
309
+ plot_signal(signal_data, time_array, start_time, end_time, fontsize, window_size)
 
 
 
 
 
310
  signal_plot_path = os.path.join(output_dir, "signal_plot.png")
311
  plt.savefig(signal_plot_path)
312
 
313
+ freq_start, freq_end = labutils.band_intensity_setting_to_band(band_intensity_setting)
314
+ integration_method = labutils.integration_method_to_method(integration_method)
315
+ overlap = float(overlap) / 100.0
316
 
317
  # スペクトログラムプロットの保存
318
  if analysis_method == "Short-Time Fourier Transform":
319
+ frequencies, times, amplitude = perform_stft(signal_data, sample_rate, segment_length, overlap)
320
 
321
  plt.figure(dpi=200)
322
+ plot_stft_spectrogram(amplitude, frequencies, times, max_frequency, fontsize)
323
  spectrogram_plot_path = os.path.join(output_dir, "stft_spectrogram_plot.png")
 
 
324
  plt.savefig(spectrogram_plot_path)
325
 
326
  plt.figure(dpi=200)
327
+ band_intensity = calculate_frequency_band_intensity(frequencies, amplitude, (freq_start, freq_end), method="STFT", integration_method=integration_method)
328
+ plot_frequency_band_intensity(times, band_intensity, fontsize=fontsize)
329
  plot_frequency_band_intensity_path = os.path.join(output_dir, "band_intensity.png")
 
 
330
  plt.savefig(plot_frequency_band_intensity_path)
331
 
332
+ csv_path = os.path.join(output_dir, "band_intensity_data.csv")
333
+ save_all_data_to_csv(times, frequencies, amplitude, csv_path, method="STFT", integration_method=integration_method)
334
+
335
  else:
336
  spectrogram_plot_path = os.path.join(output_dir, "wavelet_spectrogram_plot.png")
337
  cwt_matrix = perform_cwt(sample_rate, signal_data, max_frequency)
338
  plt.figure(dpi=200)
339
+ plot_cwt_result(cwt_matrix, time_array, max_frequency, fontsize)
 
 
340
  plt.savefig(spectrogram_plot_path)
341
 
342
  plt.figure(dpi=200)
343
+ band_intensity = calculate_frequency_band_intensity(np.arange(max_frequency), cwt_matrix, (freq_start, freq_end), method="CWT", integration_method=integration_method)
344
+ plot_frequency_band_intensity(time_array, band_intensity, fontsize=fontsize)
345
  plot_frequency_band_intensity_path = os.path.join(output_dir, "band_intensity.png")
 
 
346
  plt.savefig(plot_frequency_band_intensity_path)
347
 
348
+ csv_path = os.path.join(output_dir, "band_intensity_data.csv")
349
+ save_all_data_to_csv(time_array, np.arange(max_frequency), cwt_matrix, csv_path, method="CWT", integration_method=integration_method)
350
+
351
+ config_yaml_path = os.path.join(output_dir, "lab_tool_spectrogram.yaml")
352
+
353
+ export_arguments_to_yaml(
354
+ file_basename, analysis_method,
355
+ sample_rate, max_frequency, signal_column_name, start_time, end_time,
356
+ filter_type, highpass_cutoff, stopband_cutoff, passband_ripple, stopband_attenuation,
357
+ band_intensity_setting, integration_method, segment_length, overlap,
358
+ config_yaml_path
359
+ )
360
+
361
+ os.remove('/tmp/all_analyze_file.zip')
362
+ ziped_file = zip_directory_with_command(output_dir, "/tmp/all_analyze_file.zip")
363
+
364
+ return spectrogram_plot_path, plot_frequency_band_intensity_path, signal_plot_path, ziped_file
unit_test.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 必要なライブラリをインポート
2
+ import numpy as np
3
+ import matplotlib.pyplot as plt
4
+ from lab_tools import spectrogram
5
+
6
+
7
+ def spectrogram_test():
8
+ # パラメータ設定
9
+ Fs = 1000 # サンプリング周波数 (Hz)
10
+ duration = 5 # 信号の長さ(秒)
11
+ f0, f1 = 0, 50 # チャープ信号の開始・終了周波数
12
+ mod_freq = 1.0 # 振幅変調の周波数(Hz)
13
+ fmax = 50 # CWTの最大周波数
14
+
15
+ # 時間ベクトル
16
+ t = np.arange(0, duration, 1 / Fs)
17
+
18
+ # チャープ信号(0から50 Hzに周波数が変化)
19
+ chirp_signal = np.sin(2 * np.pi * ((f1 - f0) / duration * t**2 / 2 + f0 * t))
20
+
21
+ # 振幅変調(1 Hzの正弦波で振幅を変化させる)
22
+ modulation = (np.sin(2 * np.pi * mod_freq * t) + 1) / 0.2 # 0〜1の範囲にスケーリング
23
+ modulated_signal = chirp_signal * modulation
24
+
25
+ plt.figure(dpi=200)
26
+ plt.subplot(2, 1, 1)
27
+ spectrogram.plot_stft_spectrogram(modulated_signal, sample_rate=Fs, segment_length=512+256, overlap=0.99, max_frequency=fmax)
28
+ spectrogram_filename = "cwt_result.png"
29
+
30
+ plt.savefig(spectrogram_filename)
31
+
32
+ plt.figure(figsize=(12, 6))
33
+ plt.plot(t, modulated_signal, label="Amplitude Modulated Signal", color="orange")
34
+ plt.title("Amplitude Modulated Signal")
35
+ plt.xlabel("Time (s)")
36
+ plt.ylabel("Amplitude")
37
+ plt.grid()
38
+ plt.legend()
39
+
40
+ spectrogram_filename = "signal.png"
41
+ plt.savefig(spectrogram_filename)
42
+
43
+
44
+ if __name__ == "__main__":
45
+ spectrogram_test()