pyTREMOR.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. pyTREMOR - Python /Seismoacoustics/ Squeezer - 2023-2024 - by Kräken.LABS (https://krakenslab.com)
  5. ----------
  6. Seismoacoustics — the combined study of vibrations in the Earth and sound waves in the atmosphere
  7. to characterize non-earthquake geohazards, such as avalanches, landslides, and volcanic eruptions.
  8. https://code.03c8.net/krakenslab/pytremor
  9. ----------
  10. You should have received a copy of the GNU General Public License along
  11. with PyTREMOR; if not, write to the Free Software Foundation, Inc., 51
  12. Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  13. """
  14. VERSION = str(0.5)
  15. import datetime
  16. from datetime import timedelta
  17. import os, sys
  18. import shutil
  19. from os import environ
  20. environ['PYGAME_HIDE_SUPPORT_PROMPT'] = '1'
  21. import pygame
  22. import subprocess
  23. from obspy import UTCDateTime
  24. import warnings
  25. def custom_filter(message, category, filename, lineno, *args, **kwargs):
  26. return not ('Font family' in str(message) and 'cursive' in str(message))
  27. warnings.simplefilter('ignore', custom_filter)
  28. def banner():
  29. print(r''' __ _______ __ __
  30. _ _\ \ / /_ _| __ ___| \/ | ___ _ __
  31. | '_ \ V / | || '__/ _ \ |\/| |/ _ \| '__|
  32. | |_) | | | || | | __/ | | | (_) | |
  33. | .__/|_| |_||_| \___|_| |_|\___/|_|
  34. |_| pyTREMOR (v'''+VERSION+''') by Kräken.LABS | (2023/2024)
  35. ''')
  36. import os
  37. import shutil
  38. import datetime
  39. from obspy import UTCDateTime
  40. def sonify(network_conf, station_conf, channel_conf, starttime_conf, endtime_conf, freqmax_conf, freqmin_conf, speed_up_factor_conf, fps_conf, spec_win_dur_conf, db_lim_conf):
  41. db_lim_conf = db_lim_conf.replace("\n", "")
  42. db_lim_conf_1 = int(db_lim_conf.split(",")[0])
  43. db_lim_conf_2 = int(db_lim_conf.split(",")[1])
  44. from sonify.sonify.sonify import sonify
  45. try:
  46. print(f"\nSonifying data for: {station_conf}...")
  47. result = sonify(
  48. network=network_conf.replace("\n", ""),
  49. station=station_conf.replace("\n", ""),
  50. channel=channel_conf.replace("\n", ""),
  51. starttime=UTCDateTime(starttime_conf),
  52. endtime=UTCDateTime(endtime_conf),
  53. freqmax=int(freqmax_conf.replace("\n", "")),
  54. freqmin=int(freqmin_conf.replace("\n", "")),
  55. speed_up_factor=int(speed_up_factor_conf.replace("\n", "")),
  56. fps=int(fps_conf.replace("\n", "")),
  57. spec_win_dur=int(spec_win_dur_conf.replace("\n", "")),
  58. db_lim=(db_lim_conf_1, db_lim_conf_2),
  59. )
  60. print("Sonification completed successfully.")
  61. now = datetime.datetime.now()
  62. filename = now.strftime("%Y-%m-%d-%H-%M-") + station_conf.replace("\n", "") + ".mp4"
  63. dataset_folder = "dataset"
  64. if not os.path.exists(dataset_folder):
  65. os.makedirs(dataset_folder)
  66. new_filepath = os.path.join(dataset_folder, filename)
  67. mp4_files = [file for file in os.listdir(".") if file.endswith(".mp4")]
  68. if mp4_files:
  69. mp4_file = mp4_files[0]
  70. shutil.move(mp4_file, new_filepath)
  71. print(f"Video moved and renamed to: {new_filepath}")
  72. if "--autorun" in sys.argv:
  73. pass
  74. else:
  75. menu()
  76. return true
  77. else:
  78. print("No .mp4 file found in the directory.")
  79. except Exception as e:
  80. print(f"An error occurred during sonification: This station is not replying!")
  81. def menu():
  82. main_menu = {
  83. "(h)elp ":"show this message",
  84. "(v)ersion ":"current version",
  85. "(c)lear ":"clear screen",
  86. "(q)uit ":"quit program"
  87. }
  88. sonification_menu = {
  89. "(setup) ":"setup template",
  90. "(view) ":"view template",
  91. "(run) ":"run template",
  92. "(play) ":"play sonification"
  93. }
  94. clear()
  95. while 1:
  96. cmd = input("pyTREMOR@GSN% ")
  97. if cmd == "h" or cmd == "help":
  98. print()
  99. for n in main_menu:
  100. print(" "+ n + ": " + main_menu[n])
  101. print()
  102. for n in sonification_menu:
  103. print(" "+ n + ": " + sonification_menu[n])
  104. print()
  105. elif cmd == "v" or cmd == "version":
  106. banner()
  107. elif cmd == "c" or cmd == "clear":
  108. clear()
  109. elif cmd == "setup":
  110. setup()
  111. elif cmd == "view":
  112. view()
  113. elif cmd == "run":
  114. run_from_config_file()
  115. elif cmd == "play":
  116. play_sonification()
  117. elif cmd == "q" or cmd == "quit" or cmd == "exit":
  118. quit()
  119. def clear():
  120. os.system('clear')
  121. def quit():
  122. sys.exit()
  123. def read_config(file):
  124. if file == "config":
  125. f = open("config","r")
  126. else:
  127. f = open("autoconfig","r")
  128. lines = f.readlines()
  129. f.close()
  130. return lines
  131. import subprocess
  132. def play_sonification():
  133. dataset_folder = "dataset"
  134. if not os.path.exists(dataset_folder):
  135. print("No sonification files found.")
  136. return
  137. mp4_files = [file for file in os.listdir(dataset_folder) if file.endswith(".mp4")]
  138. wav_files = [file for file in os.listdir(dataset_folder) if file.endswith(".wav")]
  139. files = []
  140. for mp4_file in mp4_files:
  141. base_name = os.path.splitext(mp4_file)[0]
  142. if f"{base_name}.wav" in wav_files:
  143. files.append(mp4_file)
  144. else:
  145. files.append(mp4_file)
  146. if not files:
  147. print("No sonification files found.")
  148. return
  149. print("Available sonification files:")
  150. for i, filename in enumerate(files):
  151. print(f"{i+1}. {filename}")
  152. selection = input("Choose a file to play (enter number): ")
  153. try:
  154. selection = int(selection)
  155. if selection < 1 or selection > len(files):
  156. print("Invalid selection.")
  157. return
  158. selected_file = files[selection - 1]
  159. mp4_file = os.path.join(dataset_folder, selected_file)
  160. wav_file = os.path.splitext(selected_file)[0] + ".wav"
  161. wav_path = os.path.join(dataset_folder, wav_file)
  162. if not os.path.exists(wav_path):
  163. subprocess.run(["ffmpeg", "-i", mp4_file, wav_path])
  164. pygame.init()
  165. pygame.mixer.init()
  166. pygame.mixer.music.load(wav_path)
  167. pygame.mixer.music.play()
  168. while pygame.mixer.music.get_busy():
  169. pygame.time.Clock().tick(10)
  170. pygame.mixer.quit()
  171. except ValueError:
  172. print("Invalid input. Please enter a number.")
  173. def setup():
  174. network = input("\n set network (str) (ex: AV): ")
  175. station = input(" set station (str) (ex: ILSW): ")
  176. channel = input(" set channel (str) (ex: BHZ): ")
  177. starttime = input(" set starttime (ex: 2019, 6, 20, 23, 10): ")
  178. endtime = input(" set endtime (ex: 2019, 6, 21, 0, 30): ")
  179. freqmin = input(" set freqmin (int or float) (ex: 1): ")
  180. freqmax = input(" set freqmax (int or float) (ex: 23): ")
  181. speed_up_factor = input(" set speed_up_factor (int) (ex: 200): ")
  182. fps = input(" fps (int) (ex: 1): ")
  183. spec_win_dur = input(" set spec_win_dur (int or float) (ex: 8): ")
  184. db_lim = input(" set db_lim (tuple or str) (ex: -180,-130): ")
  185. with open("config", mode='w') as config:
  186. config.write("network="+network+"\n")
  187. config.write("station="+station+"\n")
  188. config.write("channel="+channel+"\n")
  189. config.write("starttime="+starttime+"\n")
  190. config.write("endtime="+endtime+"\n")
  191. config.write("freqmin="+freqmin+"\n")
  192. config.write("freqmax="+freqmax+"\n")
  193. config.write("speed_up_factor="+speed_up_factor+"\n")
  194. config.write("fps="+fps+"\n")
  195. config.write("spec_win_dur="+spec_win_dur+"\n")
  196. config.write("db_lim="+db_lim)
  197. config.close()
  198. def view():
  199. if os.path.isfile("config"):
  200. lines = read_config("config")
  201. else:
  202. with open("config", mode='w') as config:
  203. config.write("network=\n")
  204. config.write("station=\n")
  205. config.write("channel=\n")
  206. config.write("starttime=\n")
  207. config.write("endtime=\n")
  208. config.write("freqmin=\n")
  209. config.write("freqmax=\n")
  210. config.write("speed_up_factor=\n")
  211. config.write("fps=\n")
  212. config.write("spec_win_dur=\n")
  213. config.write("db_lim=")
  214. config.close()
  215. lines = read_config("config")
  216. print("\n", "sonify(")
  217. for line in lines:
  218. line = line.replace("\n","")
  219. print(" ",line)
  220. print(" )\n")
  221. def run(network_conf, station_conf, channel_conf, starttime_conf, endtime_conf, freqmax_conf, freqmin_conf, speed_up_factor_conf, fps_conf, spec_win_dur_conf, db_lim_conf):
  222. print("\n[+] Generating -sonify- setup from LOCAL config...")
  223. if os.path.isfile("config"):
  224. lines = read_config("config")
  225. else:
  226. print("\n[Error] not 'config' file generated... Exiting!\n")
  227. sys.exit(2)
  228. for line in lines:
  229. if "network" in line:
  230. network_conf = line.split("=")[1]
  231. if "station" in line:
  232. station_conf = line.split("=")[1]
  233. if "channel" in line:
  234. channel_conf = line.split("=")[1]
  235. if "starttime" in line:
  236. starttime_conf = line.split("=")[1]
  237. if "endtime" in line:
  238. endtime_conf = line.split("=")[1]
  239. if "freqmax" in line:
  240. freqmax_conf = line.split("=")[1]
  241. if "freqmin" in line:
  242. freqmin_conf = line.split("=")[1]
  243. if "speed_up_factor" in line:
  244. speed_up_factor_conf = line.split("=")[1]
  245. if "fps" in line:
  246. fps_conf = line.split("=")[1]
  247. if "spec_win_dur" in line:
  248. spec_win_dur_conf = line.split("=")[1]
  249. if "db_lim" in line:
  250. db_lim_conf = line.split("=")[1]
  251. success = sonify(network_conf, station_conf, channel_conf, starttime_conf, endtime_conf, freqmax_conf, freqmin_conf, speed_up_factor_conf, fps_conf, spec_win_dur_conf, db_lim_conf)
  252. def run_from_config_file():
  253. lines = read_config("config")
  254. network_conf = ""
  255. station_conf = ""
  256. channel_conf = ""
  257. starttime_conf = ""
  258. endtime_conf = ""
  259. freqmax_conf = ""
  260. freqmin_conf = ""
  261. speed_up_factor_conf = ""
  262. fps_conf = ""
  263. spec_win_dur_conf = ""
  264. db_lim_conf = ""
  265. for line in lines:
  266. if "network" in line:
  267. network_conf = line.split("=")[1]
  268. if "station" in line:
  269. station_conf = line.split("=")[1]
  270. if "channel" in line:
  271. channel_conf = line.split("=")[1]
  272. if "starttime" in line:
  273. starttime_conf = line.split("=")[1]
  274. if "endtime" in line:
  275. endtime_conf = line.split("=")[1]
  276. if "freqmax" in line:
  277. freqmax_conf = line.split("=")[1]
  278. if "freqmin" in line:
  279. freqmin_conf = line.split("=")[1]
  280. if "speed_up_factor" in line:
  281. speed_up_factor_conf = line.split("=")[1]
  282. if "fps" in line:
  283. fps_conf = line.split("=")[1]
  284. if "spec_win_dur" in line:
  285. spec_win_dur_conf = line.split("=")[1]
  286. if "db_lim" in line:
  287. db_lim_conf = line.split("=")[1]
  288. success = run(network_conf, station_conf, channel_conf, starttime_conf, endtime_conf, freqmax_conf, freqmin_conf, speed_up_factor_conf, fps_conf, spec_win_dur_conf, db_lim_conf)
  289. if success:
  290. menu()
  291. def init():
  292. if "--cmd" in sys.argv:
  293. try:
  294. network_conf = sys.argv[2]+"\n"
  295. station_conf = sys.argv[3]+"\n"
  296. channel_conf = sys.argv[4]+"\n"
  297. starttime_conf = sys.argv[5].replace(",",", ")+"\n"
  298. endtime_conf = sys.argv[6].replace(",",", ")+"\n"
  299. freqmax_conf = sys.argv[7]+"\n"
  300. freqmin_conf = sys.argv[8]+"\n"
  301. speed_up_factor_conf = sys.argv[9]+"\n"
  302. fps_conf = sys.argv[10]+"\n"
  303. spec_win_dur_conf = sys.argv[11]+"\n"
  304. db_lim_conf = sys.argv[12]+"\n"
  305. print("\n[+] Generating -sonify- setup from CMD config...")
  306. print("\n", "sonify(")
  307. print(" network="+network_conf.replace("\n",""))
  308. print(" station="+station_conf.replace("\n",""))
  309. print(" channel="+channel_conf.replace("\n",""))
  310. print(" starttime="+starttime_conf.replace("\n",""))
  311. print(" endtime="+endtime_conf.replace("\n",""))
  312. print(" freqmax="+freqmax_conf.replace("\n",""))
  313. print(" freqmin="+freqmin_conf.replace("\n",""))
  314. print(" speed_up_factor="+speed_up_factor_conf.replace("\n",""))
  315. print(" fps="+fps_conf.replace("\n",""))
  316. print(" spec_win_dur="+spec_win_dur_conf.replace("\n",""))
  317. print(" db_lim="+db_lim_conf)
  318. print(" )")
  319. success = sonify(network_conf, station_conf, channel_conf, starttime_conf, endtime_conf, freqmax_conf, freqmin_conf, speed_up_factor_conf, fps_conf, spec_win_dur_conf, db_lim_conf)
  320. if success:
  321. menu()
  322. except:
  323. print("\n[Error] Executing parameters are wrong... Please review your command line!")
  324. print("\n +SYNTAX:\n python3 pyTREMOR.py --cmd <network> <station> <channel> <starttime> <endtime> <freqmax> <freqmin> <speed_up_factor> <fps> <spec_win_dur> <db_lim>")
  325. print("\n +EXAMPLE:\n python3 pyTREMOR.py --cmd AV ILSW BHZ 2019,6,20,23,10 2019,6,21,0,30 23 1 200 1 8 -180,-130\n")
  326. elif "--autorun" in sys.argv:
  327. print("\n[+] Generating -sonify- setup from LOCAL auto-config...")
  328. if os.path.isfile("autoconfig"):
  329. lines = read_config("autoconfig")
  330. else:
  331. print("\n[Error] not 'autoconfig' file found... Exiting!\n")
  332. sys.exit(2)
  333. datetime_format = "%Y, %m, %d, %H, %M"
  334. endtime_conf = datetime.datetime.now()
  335. endtime_conf_format = endtime_conf.strftime(datetime_format)
  336. print("\n"+"-"*24)
  337. for line in lines:
  338. if "LASTHOURS" in line:
  339. lasthours = line.split("=")[1]
  340. print ("[Info] LAST HOURS: ["+ str(lasthours).replace("\n","")+"]")
  341. starttime_conf = endtime_conf - timedelta(hours=int(lasthours))
  342. starttime_conf_format = starttime_conf.strftime(datetime_format)
  343. print ("[Info] Starttime: "+str(starttime_conf_format))
  344. print ("[Info] Endtime: "+ str(endtime_conf_format))
  345. print("-"*24+"\n")
  346. stations_list=[]
  347. for line in lines:
  348. if "#" in line:
  349. location = line.split("{")[0]
  350. print (location)
  351. location_conf = line.split("{")[1]
  352. location_conf = location_conf.replace("{", "")
  353. location_conf = location_conf.replace("}", "")
  354. location_conf = location_conf.replace("\n", "")
  355. location_list = list(location_conf.split(","))
  356. location_list.append("starttime="+starttime_conf_format)
  357. location_list.append("endtime="+endtime_conf_format)
  358. print(" "+ str(location_list)+"\n")
  359. stations_list.append(location_list)
  360. print("-"*24+"\n")
  361. for station in stations_list:
  362. for value in station:
  363. if "network" in value:
  364. network_conf = value.split("=")[1]
  365. if "station" in value:
  366. station_conf = value.split("=")[1]
  367. if "channel" in value:
  368. channel_conf = value.split("=")[1]
  369. if "starttime" in value:
  370. starttime_conf = value.split("=")[1]
  371. if "endtime" in value:
  372. endtime_conf = value.split("=")[1]
  373. if "freqmax" in value:
  374. freqmax_conf = value.split("=")[1]
  375. if "freqmin" in value:
  376. freqmin_conf = value.split("=")[1]
  377. if "speed_up_factor" in value:
  378. speed_up_factor_conf = value.split("=")[1]
  379. if "fps" in value:
  380. fps_conf = value.split("=")[1]
  381. if "spec_win_dur" in value:
  382. spec_win_dur_conf = value.split("=")[1]
  383. if "db_lim" in value:
  384. db_lim_conf_1 = value.split("|")[0]
  385. db_lim_conf_1 = db_lim_conf_1.split("=")[1]
  386. db_lim_conf_2 = value.split("|")[1]
  387. db_lim_conf=(db_lim_conf_1+","+db_lim_conf_2)
  388. success = sonify(network_conf, station_conf, channel_conf, starttime_conf, endtime_conf, freqmax_conf, freqmin_conf, speed_up_factor_conf, fps_conf, spec_win_dur_conf, db_lim_conf)
  389. if "--help" in sys.argv:
  390. print("="*50)
  391. banner()
  392. print(" Seismoacoustics — the combined study of vibrations in the Earth and sound waves in the atmosphere\n to characterize non-earthquake geohazards, such as avalanches, landslides, and volcanic eruptions.\n")
  393. print("="*50)
  394. print(" +HELP:\n python3 pyTREMOR.py --help")
  395. print("-"*50)
  396. print("\n +SHELL:\n python3 pyTREMOR.py")
  397. print("\n +AUTORUN:\n python3 pyTREMOR.py --autorun")
  398. print("\n +CMD:\n python3 pyTREMOR.py --cmd <network> <station> <channel> <starttime> <endtime> <freqmax> <freqmin> <speed_up_factor> <fps> <spec_win_dur> <db_lim>\n")
  399. else:
  400. menu()
  401. init()