Skip to content

Commit c5bb7c8

Browse files
committed
Rename: plot_helicorder_v2.py → plot_helicorder.py and Edit README.md
1 parent eacefb3 commit c5bb7c8

5 files changed

Lines changed: 130 additions & 207 deletions

File tree

README.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,25 +76,28 @@ python draw_helicorder_v2.py
7676

7777
## 🧩 Scripts
7878

79-
### draw_helicorder_v2.py
80-
- 지정 경로 내 저장된 지진파형(MSEED Format)으로부터 Helicorder 자동 생성
81-
- 실행 날짜 기준 **이전 날짜(어제)** 의 데이터를 불러옴
82-
- `crontab`을 통해 매일 오전 9시에 자동 실행되도록 설정 가능
79+
### plot_helicorder.py
80+
- 지정 경로 내 저장된 지진파형(MSEED Format)으로부터 일일 Helicorder 이미지 자동 생성
81+
- 실행일 기준 **이전 날짜** 의 데이터를 불러와 처리
82+
- `--date` 옵션을 통해 특정 날짜(YYYYMMDD 형식)를 지정 가능
83+
- 관측소별 진폭 스케일(`station_scale`) 및 진폭 임계값(`threshold_raw`)을 설정 가능
84+
- 출력 이미지는 `helicorder_<STATION>_<YYYYMMDD>0000_<CHANNEL>.png` 형식으로 저장됨
8385
---
8486

85-
### test.py (WIP)
86-
- 특정 날짜를 지정해 Helicorder를 생성
87+
### plot_ppsd.py
88+
- WIP
89+
8790

8891
---
8992

9093
### helicorder_one_station.html
91-
- 특정 관측소명, 날짜 범위, 성분(Z/N/E)을 선택하여 `plots` 경로 내 Helicorder 이미지 검색
94+
- 특정 관측소명, 날짜 범위, 성분(Z/N/E)을 기준으로 경로 내 Helicorder 이미지 검색
9295
- 검색 결과로 표시된 그래프는 클릭 시 새 창에서 원본 이미지로 열리며, 저장 가능
9396

9497
---
9598

9699
### helicorder_all_stations.html
97-
- 특정 날짜를 기준으로 모든 관측소의 Helicorder 이미지 일괄 검색
100+
- 특정 날짜를 기준으로 모든 관측소의 Helicorder 이미지 검색
98101
- 검색 결과로 표시된 그래프는 클릭 시 새 창에서 원본 이미지로 열리며, 저장 가능
99102

100103
---

plot_helicorder.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#!/usr/bin/env python
2+
3+
from datetime import datetime, timedelta, UTC
4+
from obspy import read
5+
import argparse
6+
import glob
7+
import math
8+
import matplotlib
9+
import matplotlib.pyplot as plt
10+
import numpy as np
11+
import os
12+
import sys
13+
14+
# Argument parsing
15+
parser = argparse.ArgumentParser(
16+
description="Plot helicorder for given date."
17+
)
18+
parser.add_argument(
19+
"--date",
20+
type=str,
21+
help="Target date in YYYYMMDD format (default: yesterday in UTC)",
22+
)
23+
args = parser.parse_args()
24+
25+
# Target date setup
26+
if args.date:
27+
try:
28+
target_dt = datetime.strptime(args.date, "%Y%m%d").replace(tzinfo=UTC)
29+
except ValueError:
30+
sys.exit("Invalid date format. Use YYYYMMDD (e.g., 20250101).")
31+
else:
32+
target_dt = datetime.now(UTC) - timedelta(days=1)
33+
34+
year = target_dt.strftime("%Y")
35+
datestr = target_dt.strftime("%Y%m%d")
36+
julday = target_dt.strftime("%j")
37+
print(f"Processing date: {datestr} (Julian day {julday})")
38+
39+
# Station-specific scale configuration
40+
station_scale = {
41+
# --- Network ---
42+
# Format: StationName : ScaleValue
43+
# Example: JN01: 2000, JN02: 30000
44+
# ScaleValue must be an integer
45+
}
46+
threshold_raw = 1.5
47+
48+
# Load files
49+
pattern = f"/path_to_mseed_data/station.network.location.channel.{year}.{julday}"
50+
files = sorted(glob.glob(pattern))
51+
print(f"Found {len(files)} files for {year}.{julday}")
52+
53+
if not files:
54+
sys.exit(f"No file matching pattern: {pattern}")
55+
56+
try:
57+
st = read(files[0])
58+
for f in files[1:]:
59+
st += read(f)
60+
st.merge(fill_value="interpolate")
61+
st.detrend("demean")
62+
st.taper(0.0005, "cosine")
63+
st.filter("bandpass", freqmin=1, freqmax=20)
64+
except Exception as e:
65+
sys.exit(f"Error reading waveform files: {e}")
66+
67+
# Output directory
68+
outdir = "/path_to_output_directory"
69+
os.makedirs(outdir, exist_ok=True)
70+
71+
# Main plotting loop
72+
for tr in st:
73+
try:
74+
station = tr.stats.station
75+
channel = tr.stats.channel[-1]
76+
data = tr.data
77+
delta = tr.stats.delta
78+
npts = tr.stats.npts
79+
times = np.arange(0, npts * delta, delta)
80+
starttime = tr.stats.starttime.datetime
81+
82+
interval = 60 * 15
83+
segments = [int(i * interval / delta) for i in range(math.ceil(times[-1] / interval)
84+
+ 1)]
85+
86+
fig, ax = plt.subplots(figsize=(10, 8))
87+
scale = station_scale.get(station, 5000)
88+
89+
for i in range(len(segments) - 1):
90+
seg_data = data[segments[i]:segments[i + 1]]
91+
seg_time = np.linspace(0, interval, len(seg_data))
92+
color = "red" if np.any(np.abs(seg_data / scale) > threshold_raw) else "black"
93+
ax.plot(seg_time, seg_data / scale + i, color=color, linewidth=0.5)
94+
95+
# Axis configuration
96+
ax.set_ylim(len(segments) - 1, -0.5)
97+
ax.set_xlim(0, interval)
98+
ax.set_xticks(np.linspace(0, interval, 16))
99+
ax.set_xticklabels([str(int(x / 60)) for x in np.linspace(0, 15 * 60, 16)])
100+
ax.set_yticks(np.arange(0, len(segments) - 1, 4))
101+
yt_labels = [(starttime + timedelta(minutes=15 * i)).strftime("%H")
102+
for i in range(0, len(segments) - 1, 4)]
103+
ax.set_yticklabels(yt_labels)
104+
ax.set_xlabel("Time (minutes)")
105+
ax.set_title(f"{tr.id} {str(starttime)[:10]}")
106+
ax.set_facecolor("white")
107+
plt.tight_layout()
108+
109+
outfile = f"{outdir}/helicorder_{station}_{datestr}0000_{channel}.png"
110+
os.makedirs(os.path.dirname(outfile), exist_ok=True)
111+
print(f"Saving {outfile}")
112+
plt.savefig(outfile, dpi=150)
113+
plt.close(fig)
114+
115+
except Exception as e:
116+
print(f"Error plotting {tr.id}: {e}")
117+
continue
118+
119+
print("All helicorders saved successfully!")

plot_helicorder_v2.py

Lines changed: 0 additions & 73 deletions
This file was deleted.

scripts/plot_helicorder_v1.py

Lines changed: 0 additions & 50 deletions
This file was deleted.

scripts/test.py

Lines changed: 0 additions & 76 deletions
This file was deleted.

0 commit comments

Comments
 (0)