alwaysgood commited on
Commit
e390221
·
verified ·
1 Parent(s): da9f88d

Update noise_scenarios.py

Browse files
Files changed (1) hide show
  1. noise_scenarios.py +94 -75
noise_scenarios.py CHANGED
@@ -270,8 +270,17 @@ def create_noise_comparison_plot(df_original, df_noisy, scenario_name):
270
  horizontal_spacing=0.08
271
  )
272
 
273
- # 시간축 (인덱스 사용)
274
- time_axis = list(range(len(df_original)))
 
 
 
 
 
 
 
 
 
275
 
276
  # 색상 설정 (더 선명하게)
277
  original_color = '#2E86AB' # 진한 파랑
@@ -283,72 +292,84 @@ def create_noise_comparison_plot(df_original, df_noisy, scenario_name):
283
  var_units = ['cm', 'hPa', 'm/s', '°C', '°']
284
 
285
  for var, (row, col), unit in zip(variables, positions, var_units):
286
- if var in df_original.columns:
287
- # 원본 데이터 (실선, 두껍게)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
  fig.add_trace(
289
  go.Scatter(
290
- x=time_axis, y=df_original[var],
291
- name=f'🔵 원본',
292
- line=dict(color=original_color, width=3),
293
- showlegend=(row==1 and col==1),
294
- hovertemplate=f'원본 {var}: %{{y:.1f}}{unit}<br>시점: %{{x}}<extra></extra>'
295
  ),
296
- row=row, col=col
297
  )
298
-
299
- # 노이즈 데이터 (점선, 두껍게)
300
  fig.add_trace(
301
  go.Scatter(
302
- x=time_axis, y=df_noisy[var],
303
- name=f'🔴 노이즈',
304
- line=dict(color=noise_color, width=2.5, dash='dash'),
305
- showlegend=(row==1 and col==1),
306
- hovertemplate=f'노이즈 {var}: %{{y:.1f}}{unit}<br>시점: %{{x}}<extra></extra>'
307
  ),
308
- row=row, col=col
309
  )
310
-
311
- # Y축 범위 자동 조정 (변화를 더 명확히 보기 위해)
312
- original_range = df_original[var].max() - df_original[var].min()
313
- noisy_range = df_noisy[var].max() - df_noisy[var].min()
314
-
315
- # 더 큰 범위를 기준으로 패딩 적용
316
- total_range = max(original_range, noisy_range)
317
- y_center = (df_original[var].mean() + df_noisy[var].mean()) / 2
318
-
319
- y_min = y_center - total_range * 0.6
320
- y_max = y_center + total_range * 0.6
321
-
322
- fig.update_yaxes(range=[y_min, y_max], row=row, col=col)
323
-
324
- # 전체 비교 (tide_level 중심) - 더 크고 선명하게
325
- if 'tide_level' in df_original.columns:
326
- fig.add_trace(
327
- go.Scatter(
328
- x=time_axis, y=df_original['tide_level'],
329
- name='🔵 원본 조위',
330
- line=dict(color=original_color, width=4),
331
- showlegend=True,
332
- hovertemplate='원본 조위: %{y:.1f}cm<br>시점: %{x}<extra></extra>'
333
- ),
334
- row=3, col=2
335
- )
336
- fig.add_trace(
337
- go.Scatter(
338
- x=time_axis, y=df_noisy['tide_level'],
339
- name='🔴 노이즈 조위',
340
- line=dict(color=noise_color, width=3, dash='dash'),
341
- showlegend=True,
342
- hovertemplate='노이즈 조위: %{y:.1f}cm<br>시점: %{x}<extra></extra>'
343
- ),
344
- row=3, col=2
345
- )
346
 
347
  # 노이즈 시나리오 구간 하이라이트 추가
348
  def add_scenario_highlight(scenario_name):
349
  if scenario_name == 'typhoon':
350
- # 태풍 구간 계산 (generate_typhoon_scenario와 동일한 로직)
351
- n_points = len(df_original)
352
 
353
  if n_points >= 72:
354
  typhoon_center = int(n_points * 0.7) # 70% 지점
@@ -363,30 +384,28 @@ def create_noise_comparison_plot(df_original, df_noisy, scenario_name):
363
  print(f" 📍 시각화 태풍 구간: {start_idx}-{end_idx}")
364
 
365
  # 모든 서브플롯에 배경 영역 추가
366
- for row in range(1, 4):
367
- for col in range(1, 3):
368
- fig.add_vrect(
369
- x0=start_idx, x1=end_idx,
370
- fillcolor="rgba(255,0,0,0.15)",
371
- layer="below", line_width=0,
372
- annotation_text="🌀 태풍 구간",
373
- annotation_position="top left",
374
- row=row, col=col
375
- )
 
 
 
376
 
377
  add_scenario_highlight(scenario_name)
378
 
379
  # 차이가 큰 구간 하이라이트 (tide_level 기준)
380
- if 'tide_level' in df_original.columns and 'tide_level' in df_noisy.columns:
381
  try:
382
- # 안전한 비교를 위해 인덱스 정렬
383
- df_orig_reset = df_original.reset_index(drop=True)
384
- df_noisy_reset = df_noisy.reset_index(drop=True)
385
-
386
- # 길이 맞추기
387
- min_len = min(len(df_orig_reset), len(df_noisy_reset))
388
- orig_tide = df_orig_reset['tide_level'][:min_len]
389
- noisy_tide = df_noisy_reset['tide_level'][:min_len]
390
 
391
  # NaN이 아닌 값들만 비교
392
  valid_mask = orig_tide.notna() & noisy_tide.notna()
 
270
  horizontal_spacing=0.08
271
  )
272
 
273
+ # 안전한 DataFrame 정렬 - 같은 길이와 인덱스로 맞추기
274
+ df_orig_slice = df_original.tail(len(df_noisy)).reset_index(drop=True)
275
+ df_noisy_reset = df_noisy.reset_index(drop=True)
276
+
277
+ # 최소 길이로 맞추기
278
+ min_len = min(len(df_orig_slice), len(df_noisy_reset))
279
+ df_orig_slice = df_orig_slice[:min_len]
280
+ df_noisy_reset = df_noisy_reset[:min_len]
281
+
282
+ # 시간축 (공통 길이 사용)
283
+ time_axis = list(range(len(df_orig_slice)))
284
 
285
  # 색상 설정 (더 선명하게)
286
  original_color = '#2E86AB' # 진한 파랑
 
292
  var_units = ['cm', 'hPa', 'm/s', '°C', '°']
293
 
294
  for var, (row, col), unit in zip(variables, positions, var_units):
295
+ if var in df_orig_slice.columns and var in df_noisy_reset.columns:
296
+ try:
297
+ # 원본 데이터 (실선, 두껍게)
298
+ fig.add_trace(
299
+ go.Scatter(
300
+ x=time_axis, y=df_orig_slice[var],
301
+ name=f'🔵 원본',
302
+ line=dict(color=original_color, width=3),
303
+ showlegend=(row==1 and col==1),
304
+ hovertemplate=f'원본 {var}: %{{y:.1f}}{unit}<br>시점: %{{x}}<extra></extra>'
305
+ ),
306
+ row=row, col=col
307
+ )
308
+
309
+ # 노이즈 데이터 (점선, 두껍게)
310
+ fig.add_trace(
311
+ go.Scatter(
312
+ x=time_axis, y=df_noisy_reset[var],
313
+ name=f'🔴 노이즈',
314
+ line=dict(color=noise_color, width=2.5, dash='dash'),
315
+ showlegend=(row==1 and col==1),
316
+ hovertemplate=f'노이즈 {var}: %{{y:.1f}}{unit}<br>시점: %{{x}}<extra></extra>'
317
+ ),
318
+ row=row, col=col
319
+ )
320
+
321
+ # Y축 범위 자동 조정 (변화를 더 명확히 보기 위해) - 안전하게
322
+ orig_vals = df_orig_slice[var].dropna()
323
+ noisy_vals = df_noisy_reset[var].dropna()
324
+
325
+ if len(orig_vals) > 0 and len(noisy_vals) > 0:
326
+ original_range = orig_vals.max() - orig_vals.min()
327
+ noisy_range = noisy_vals.max() - noisy_vals.min()
328
+
329
+ # 더 큰 범위를 기준으로 패딩 적용
330
+ total_range = max(original_range, noisy_range)
331
+ y_center = (orig_vals.mean() + noisy_vals.mean()) / 2
332
+
333
+ if total_range > 0:
334
+ y_min = y_center - total_range * 0.6
335
+ y_max = y_center + total_range * 0.6
336
+ fig.update_yaxes(range=[y_min, y_max], row=row, col=col)
337
+
338
+ except Exception as e:
339
+ print(f"변수 {var} 플롯 생성 오류: {e}")
340
+ continue
341
+
342
+ # 전체 비교 (tide_level 중심) - 더 크고 선명하게
343
+ if 'tide_level' in df_orig_slice.columns and 'tide_level' in df_noisy_reset.columns:
344
+ try:
345
  fig.add_trace(
346
  go.Scatter(
347
+ x=time_axis, y=df_orig_slice['tide_level'],
348
+ name='🔵 원본 조위',
349
+ line=dict(color=original_color, width=4),
350
+ showlegend=True,
351
+ hovertemplate='원본 조위: %{y:.1f}cm<br>시점: %{x}<extra></extra>'
352
  ),
353
+ row=3, col=2
354
  )
 
 
355
  fig.add_trace(
356
  go.Scatter(
357
+ x=time_axis, y=df_noisy_reset['tide_level'],
358
+ name='🔴 노이즈 조위',
359
+ line=dict(color=noise_color, width=3, dash='dash'),
360
+ showlegend=True,
361
+ hovertemplate='노이즈 조위: %{y:.1f}cm<br>시점: %{x}<extra></extra>'
362
  ),
363
+ row=3, col=2
364
  )
365
+ except Exception as e:
366
+ print(f"전체 조위 비교 플롯 생성 오류: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367
 
368
  # 노이즈 시나리오 구간 하이라이트 추가
369
  def add_scenario_highlight(scenario_name):
370
  if scenario_name == 'typhoon':
371
+ # 태풍 구간 계산 (정렬된 DataFrame 기준)
372
+ n_points = len(df_orig_slice)
373
 
374
  if n_points >= 72:
375
  typhoon_center = int(n_points * 0.7) # 70% 지점
 
384
  print(f" 📍 시각화 태풍 구간: {start_idx}-{end_idx}")
385
 
386
  # 모든 서브플롯에 배경 영역 추가
387
+ try:
388
+ for row in range(1, 4):
389
+ for col in range(1, 3):
390
+ fig.add_vrect(
391
+ x0=start_idx, x1=end_idx,
392
+ fillcolor="rgba(255,0,0,0.15)",
393
+ layer="below", line_width=0,
394
+ annotation_text="🌀 태풍 구간",
395
+ annotation_position="top left",
396
+ row=row, col=col
397
+ )
398
+ except Exception as e:
399
+ print(f"태풍 구간 하이라이트 오류: {e}")
400
 
401
  add_scenario_highlight(scenario_name)
402
 
403
  # 차이가 큰 구간 하이라이트 (tide_level 기준)
404
+ if 'tide_level' in df_orig_slice.columns and 'tide_level' in df_noisy_reset.columns:
405
  try:
406
+ # DataFrame은 이미 정렬됨
407
+ orig_tide = df_orig_slice['tide_level']
408
+ noisy_tide = df_noisy_reset['tide_level']
 
 
 
 
 
409
 
410
  # NaN이 아닌 값들만 비교
411
  valid_mask = orig_tide.notna() & noisy_tide.notna()