pyTREMOR.py 18 KB

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