pyTREMOR.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  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. menu()
  73. return True
  74. else:
  75. print("No .mp4 file found in the directory.")
  76. return False
  77. except Exception as e:
  78. print(f"An error occurred during sonification: {str(e)}")
  79. return False
  80. def menu():
  81. main_menu = {
  82. "(h)elp ":"show this message",
  83. "(v)ersion ":"current version",
  84. "(c)lear ":"clear screen",
  85. "(q)uit ":"quit program"
  86. }
  87. sonification_menu = {
  88. "(setup) ":"setup template",
  89. "(view) ":"view template",
  90. "(run) ":"run template",
  91. "(play) ":"play sonification"
  92. }
  93. clear()
  94. while 1:
  95. cmd = input("pyTREMOR@GSN% ")
  96. if cmd == "h" or cmd == "help":
  97. print()
  98. for n in main_menu:
  99. print(" "+ n + ": " + main_menu[n])
  100. print()
  101. for n in sonification_menu:
  102. print(" "+ n + ": " + sonification_menu[n])
  103. print()
  104. elif cmd == "v" or cmd == "version":
  105. banner()
  106. elif cmd == "c" or cmd == "clear":
  107. clear()
  108. elif cmd == "setup":
  109. setup()
  110. elif cmd == "view":
  111. view()
  112. elif cmd == "run":
  113. run_from_config_file()
  114. elif cmd == "play":
  115. play_sonification()
  116. elif cmd == "q" or cmd == "quit" or cmd == "exit":
  117. quit()
  118. def clear():
  119. os.system('clear')
  120. def quit():
  121. sys.exit()
  122. def read_config(file):
  123. if file == "config":
  124. f = open("config","r")
  125. else:
  126. f = open("autoconfig","r")
  127. lines = f.readlines()
  128. f.close()
  129. return lines
  130. import subprocess
  131. def play_sonification():
  132. dataset_folder = "dataset"
  133. if not os.path.exists(dataset_folder):
  134. print("No sonification files found.")
  135. return
  136. mp4_files = [file for file in os.listdir(dataset_folder) if file.endswith(".mp4")]
  137. wav_files = [file for file in os.listdir(dataset_folder) if file.endswith(".wav")]
  138. files = []
  139. for mp4_file in mp4_files:
  140. base_name = os.path.splitext(mp4_file)[0]
  141. if f"{base_name}.wav" in wav_files:
  142. files.append(mp4_file)
  143. else:
  144. files.append(mp4_file)
  145. if not files:
  146. print("No sonification files found.")
  147. return
  148. print("Available sonification files:")
  149. for i, filename in enumerate(files):
  150. print(f"{i+1}. {filename}")
  151. selection = input("Choose a file to play (enter number): ")
  152. try:
  153. selection = int(selection)
  154. if selection < 1 or selection > len(files):
  155. print("Invalid selection.")
  156. return
  157. selected_file = files[selection - 1]
  158. mp4_file = os.path.join(dataset_folder, selected_file)
  159. wav_file = os.path.splitext(selected_file)[0] + ".wav"
  160. wav_path = os.path.join(dataset_folder, wav_file)
  161. if not os.path.exists(wav_path):
  162. subprocess.run(["ffmpeg", "-i", mp4_file, wav_path])
  163. pygame.init()
  164. pygame.mixer.init()
  165. pygame.mixer.music.load(wav_path)
  166. pygame.mixer.music.play()
  167. while pygame.mixer.music.get_busy():
  168. pygame.time.Clock().tick(10)
  169. pygame.mixer.quit()
  170. except ValueError:
  171. print("Invalid input. Please enter a number.")
  172. def setup():
  173. network = input("\n set network (str) (ex: AV): ")
  174. station = input(" set station (str) (ex: ILSW): ")
  175. channel = input(" set channel (str) (ex: BHZ): ")
  176. starttime = input(" set starttime (ex: 2019, 6, 20, 23, 10): ")
  177. endtime = input(" set endtime (ex: 2019, 6, 21, 0, 30): ")
  178. freqmin = input(" set freqmin (int or float) (ex: 1): ")
  179. freqmax = input(" set freqmax (int or float) (ex: 23): ")
  180. speed_up_factor = input(" set speed_up_factor (int) (ex: 200): ")
  181. fps = input(" fps (int) (ex: 1): ")
  182. spec_win_dur = input(" set spec_win_dur (int or float) (ex: 8): ")
  183. db_lim = input(" set db_lim (tuple or str) (ex: -180,-130): ")
  184. with open("config", mode='w') as config:
  185. config.write("network="+network+"\n")
  186. config.write("station="+station+"\n")
  187. config.write("channel="+channel+"\n")
  188. config.write("starttime="+starttime+"\n")
  189. config.write("endtime="+endtime+"\n")
  190. config.write("freqmin="+freqmin+"\n")
  191. config.write("freqmax="+freqmax+"\n")
  192. config.write("speed_up_factor="+speed_up_factor+"\n")
  193. config.write("fps="+fps+"\n")
  194. config.write("spec_win_dur="+spec_win_dur+"\n")
  195. config.write("db_lim="+db_lim)
  196. config.close()
  197. def view():
  198. if os.path.isfile("config"):
  199. lines = read_config("config")
  200. else:
  201. with open("config", mode='w') as config:
  202. config.write("network=\n")
  203. config.write("station=\n")
  204. config.write("channel=\n")
  205. config.write("starttime=\n")
  206. config.write("endtime=\n")
  207. config.write("freqmin=\n")
  208. config.write("freqmax=\n")
  209. config.write("speed_up_factor=\n")
  210. config.write("fps=\n")
  211. config.write("spec_win_dur=\n")
  212. config.write("db_lim=")
  213. config.close()
  214. lines = read_config("config")
  215. print("\n", "sonify(")
  216. for line in lines:
  217. line = line.replace("\n","")
  218. print(" ",line)
  219. print(" )\n")
  220. 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):
  221. print("\n[+] Generating -sonify- setup from LOCAL config...")
  222. if os.path.isfile("config"):
  223. lines = read_config("config")
  224. else:
  225. print("\n[Error] not 'config' file generated... Exiting!\n")
  226. sys.exit(2)
  227. for line in lines:
  228. if "network" in line:
  229. network_conf = line.split("=")[1]
  230. if "station" in line:
  231. station_conf = line.split("=")[1]
  232. if "channel" in line:
  233. channel_conf = line.split("=")[1]
  234. if "starttime" in line:
  235. starttime_conf = line.split("=")[1]
  236. if "endtime" in line:
  237. endtime_conf = line.split("=")[1]
  238. if "freqmax" in line:
  239. freqmax_conf = line.split("=")[1]
  240. if "freqmin" in line:
  241. freqmin_conf = line.split("=")[1]
  242. if "speed_up_factor" in line:
  243. speed_up_factor_conf = line.split("=")[1]
  244. if "fps" in line:
  245. fps_conf = line.split("=")[1]
  246. if "spec_win_dur" in line:
  247. spec_win_dur_conf = line.split("=")[1]
  248. if "db_lim" in line:
  249. db_lim_conf = line.split("=")[1]
  250. 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)
  251. if not success:
  252. return False
  253. return True
  254. def run_from_config_file():
  255. lines = read_config("config")
  256. network_conf = ""
  257. station_conf = ""
  258. channel_conf = ""
  259. starttime_conf = ""
  260. endtime_conf = ""
  261. freqmax_conf = ""
  262. freqmin_conf = ""
  263. speed_up_factor_conf = ""
  264. fps_conf = ""
  265. spec_win_dur_conf = ""
  266. db_lim_conf = ""
  267. for line in lines:
  268. if "network" in line:
  269. network_conf = line.split("=")[1]
  270. if "station" in line:
  271. station_conf = line.split("=")[1]
  272. if "channel" in line:
  273. channel_conf = line.split("=")[1]
  274. if "starttime" in line:
  275. starttime_conf = line.split("=")[1]
  276. if "endtime" in line:
  277. endtime_conf = line.split("=")[1]
  278. if "freqmax" in line:
  279. freqmax_conf = line.split("=")[1]
  280. if "freqmin" in line:
  281. freqmin_conf = line.split("=")[1]
  282. if "speed_up_factor" in line:
  283. speed_up_factor_conf = line.split("=")[1]
  284. if "fps" in line:
  285. fps_conf = line.split("=")[1]
  286. if "spec_win_dur" in line:
  287. spec_win_dur_conf = line.split("=")[1]
  288. if "db_lim" in line:
  289. db_lim_conf = line.split("=")[1]
  290. 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)
  291. if success:
  292. menu()
  293. def init():
  294. if "--cmd" in sys.argv:
  295. try:
  296. network_conf = sys.argv[2]+"\n"
  297. station_conf = sys.argv[3]+"\n"
  298. channel_conf = sys.argv[4]+"\n"
  299. starttime_conf = sys.argv[5].replace(",",", ")+"\n"
  300. endtime_conf = sys.argv[6].replace(",",", ")+"\n"
  301. freqmax_conf = sys.argv[7]+"\n"
  302. freqmin_conf = sys.argv[8]+"\n"
  303. speed_up_factor_conf = sys.argv[9]+"\n"
  304. fps_conf = sys.argv[10]+"\n"
  305. spec_win_dur_conf = sys.argv[11]+"\n"
  306. db_lim_conf = sys.argv[12]+"\n"
  307. print("\n[+] Generating -sonify- setup from CMD config...")
  308. print("\n", "sonify(")
  309. print(" network="+network_conf.replace("\n",""))
  310. print(" station="+station_conf.replace("\n",""))
  311. print(" channel="+channel_conf.replace("\n",""))
  312. print(" starttime="+starttime_conf.replace("\n",""))
  313. print(" endtime="+endtime_conf.replace("\n",""))
  314. print(" freqmax="+freqmax_conf.replace("\n",""))
  315. print(" freqmin="+freqmin_conf.replace("\n",""))
  316. print(" speed_up_factor="+speed_up_factor_conf.replace("\n",""))
  317. print(" fps="+fps_conf.replace("\n",""))
  318. print(" spec_win_dur="+spec_win_dur_conf.replace("\n",""))
  319. print(" db_lim="+db_lim_conf)
  320. print(" )")
  321. 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)
  322. if success:
  323. menu()
  324. except:
  325. print("\n[Error] Executing parameters are wrong... Please review your command line!")
  326. print("\n +SYNTAX:\n python3 pyTREMOR.py --cmd <network> <station> <channel> <starttime> <endtime> <freqmax> <freqmin> <speed_up_factor> <fps> <spec_win_dur> <db_lim>")
  327. 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")
  328. elif "--autorun" in sys.argv:
  329. print("\n[+] Generating -sonify- setup from LOCAL auto-config...")
  330. if os.path.isfile("autoconfig"):
  331. lines = read_config("autoconfig")
  332. else:
  333. print("\n[Error] not 'autoconfig' file found... Exiting!\n")
  334. sys.exit(2)
  335. datetime_format = "%Y, %m, %d, %H, %M"
  336. endtime_conf = datetime.datetime.now()
  337. endtime_conf_format = endtime_conf.strftime(datetime_format)
  338. print("\n"+"-"*24)
  339. for line in lines:
  340. if "LASTHOURS" in line:
  341. lasthours = line.split("=")[1]
  342. print ("[Info] LAST HOURS: ["+ str(lasthours).replace("\n","")+"]")
  343. starttime_conf = endtime_conf - timedelta(hours=int(lasthours))
  344. starttime_conf_format = starttime_conf.strftime(datetime_format)
  345. print ("[Info] Starttime: "+str(starttime_conf_format))
  346. print ("[Info] Endtime: "+ str(endtime_conf_format))
  347. print("-"*24+"\n")
  348. stations_list=[]
  349. for line in lines:
  350. if "#" in line:
  351. location = line.split("{")[0]
  352. print (location)
  353. location_conf = line.split("{")[1]
  354. location_conf = location_conf.replace("{", "")
  355. location_conf = location_conf.replace("}", "")
  356. location_conf = location_conf.replace("\n", "")
  357. location_list = list(location_conf.split(","))
  358. location_list.append("starttime="+starttime_conf_format)
  359. location_list.append("endtime="+endtime_conf_format)
  360. print(" "+ str(location_list)+"\n")
  361. stations_list.append(location_list)
  362. print("-"*24+"\n")
  363. for station in stations_list:
  364. for value in station:
  365. if "network" in value:
  366. network_conf = value.split("=")[1]
  367. if "station" in value:
  368. station_conf = value.split("=")[1]
  369. if "channel" in value:
  370. channel_conf = value.split("=")[1]
  371. if "starttime" in value:
  372. starttime_conf = value.split("=")[1]
  373. if "endtime" in value:
  374. endtime_conf = value.split("=")[1]
  375. if "freqmax" in value:
  376. freqmax_conf = value.split("=")[1]
  377. if "freqmin" in value:
  378. freqmin_conf = value.split("=")[1]
  379. if "speed_up_factor" in value:
  380. speed_up_factor_conf = value.split("=")[1]
  381. if "fps" in value:
  382. fps_conf = value.split("=")[1]
  383. if "spec_win_dur" in value:
  384. spec_win_dur_conf = value.split("=")[1]
  385. if "db_lim" in value:
  386. db_lim_conf_1 = value.split("|")[0]
  387. db_lim_conf_1 = db_lim_conf_1.split("=")[1]
  388. db_lim_conf_2 = value.split("|")[1]
  389. db_lim_conf=(db_lim_conf_1+","+db_lim_conf_2)
  390. 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)
  391. if not success:
  392. return False
  393. if "--help" in sys.argv:
  394. print("="*50)
  395. banner()
  396. 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")
  397. print("="*50)
  398. print(" +HELP:\n python3 pyTREMOR.py --help")
  399. print("-"*50)
  400. print("\n +SHELL:\n python3 pyTREMOR.py")
  401. print("\n +AUTORUN:\n python3 pyTREMOR.py --autorun")
  402. 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")
  403. else:
  404. menu()
  405. init()