From fc73f18a0d7dcf8c4fca488d97a6bb1c5df72ff9 Mon Sep 17 00:00:00 2001 From: destinyk <destiny.kuehn@student.nmt.edu> Date: Mon, 21 Aug 2023 16:54:28 -0600 Subject: [PATCH] create main window and trace headers tab --- fixhdr/pyside.py | 580 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 580 insertions(+) create mode 100644 fixhdr/pyside.py diff --git a/fixhdr/pyside.py b/fixhdr/pyside.py new file mode 100644 index 0000000..5416215 --- /dev/null +++ b/fixhdr/pyside.py @@ -0,0 +1,580 @@ +import os +import sys +import time +from itertools import repeat + +from getopt import getopt +from glob import glob +from operator import mod +from PySide2 import QtWidgets, QtGui, QtCore + +#from fixhdr.LibTrace import * +from LibTrace import * + +VERSION = "2022.1.0.0" + +SPACE = " " +DATALOC = "" + +# vars used for batchmode +BatchFile = "" +Endianess = "" +RunHeaderBatch = 0 +RunTimeBatch = 0 +RunEndianBatch = 0 +BATCHMODE = 0 + + +def Usage(err=''): + print(err) + print("Usage\nfixhdr \nfixhdr -#\nfixhdr -h\nfixhdr [-d DataDirs] " + "[-m batch_file] [-t batch_file] [-e endianess]") + print("\n Invoked with no arguements, fixhdr will launch the GUI\n") + print(" -d DataDirs - colon separated list of data directories " + "[default: cwd]") + print(" -e endianess - convert trace headers to endianess [" + "big or little]") + print(" -h - this usage page") + print(" -m batch_file - correct mseed headers in batch mode using " + "batch_file") + print(" -t batch_file - correct trace timing in batch mode using " + "batch_file") + print(" -# - print version number") + print(" NOTE: -m, -t & -e are mutually exclusive. If you wish to do") + print(" both timing and headers, run time corrections first.") + + +# get commandline args +try: + opts, pargs = getopt(sys.argv[1:], 'hd:t:m:e:#') +except Exception: + err = "\nERROR: Invalid command line usage\n" + Usage(err) + sys.exit(1) +else: + for flag, arg in opts: + if flag == "-h": + Usage() + sys.exit(0) + if flag == "-d": + DATALOC = arg + if flag == "-e": + Endianess = arg + if Endianess != "big" and Endianess != "little": + err = "\nError: Endianess must be either 'big' or 'little'" + Usage(err) + RunEndianBatch = 1 + BATCHMODE = 1 + if flag == "-m": + BatchFile = arg + RunHeaderBatch = 1 + BATCHMODE = 1 + if flag == "-t": + BatchFile = arg + RunTimeBatch = 1 + BATCHMODE = 1 + if flag == "-#": + print(VERSION) + sys.exit(0) + if RunTimeBatch + RunHeaderBatch + RunEndianBatch > 1: + err = ("\nERROR: Cannot correct timing, headers and/or endianess " + "simultaniously\n") + Usage(err) + sys.exit(1) +print("\n", os.path.basename(sys.argv[0]), VERSION) + + +# main +class MainWindow(QtWidgets.QWidget): + def __init__(self, BatchFile=''): + super().__init__() + self.resize(600,400) + self.setWindowTitle("fixhdr " + VERSION) + + # set timezone to UTC + os.environ['TZ'] = 'GMT' + time.tzname = ('GMT', 'GMT') + time.timezone = 0 + + # set global vars + self.initVars() + + # build main window and tabs + self.buildWindow() + self.buildTraceHeaders() + self.buildGlobalModify() + self.buildTimeShift() + self.buildEndianess() + self.buildLog() + self.buildHelp() + self.buildMSEEDformat() + + def initVars(self): + """ + Initialize variables, lists, and dictionaries + associated with traces and trace headers + """ + + self.e_width = 24 + self.OldSID = "" + self.DataDirs = "" + self.StatSel = "" + self.StatSelList = [] + self.TraceDict = {} + self.UpdateHdrDict = {} + self.StatChanList = [] + self.StationName = "" + self.Station = "" + self.NetCode = "" + self.SampleRate = 0 + self.Channel = "" + self.LocCode = "" + self.StatChanListVars = [ + ["Stat:Chan:Loc:Net:Sps", self.StationName], + ["Station_Name", self.Station], + ["Channel", self.Channel], + ["Location_Code", self.LocCode], + ["Network_Code", self.NetCode], + ["Sample_Rate", self.SampleRate] + ] + + # New Values on Trace Headers notebook + self.NStation = "" + self.NChannel = "" + self.NLocCode = "" + self.NNetCode = "" + self.NewVars = [ + ["Station_Name", self.NStation], + ["Channel", self.NChannel], + ["Location_Code", self.NLocCode], + ["Network_Code", self.NNetCode] + ] + + # Modified button on Trace Headers notebook + # denote whether applied updates or not + self.SetStat = 0 + self.SetChan = 0 + self.SetLoc = 0 + self.SetNet = 0 + self.SetHdrVars = [ + ["Station_Name", self.SetStat], + ["Channel", self.SetChan], + ["Location_Code", self.SetLoc], + ["Network_Code", self.SetNet] + ] + self.SetHdrDict = {} + + # vars used in global nb + self.GlobalStation = "" + self.GlobalChannel = "" + self.GlobalLocCode = "" + self.GlobalSps = "" + self.GlobalNetCode = "" + + # global update variables + self.GUStation = "" + self.GUChannel = "" + self.GULocCode = "" + self.GUSps = "" + self.GUNetCode = "" + + # lists for dropdown menus on Global Modify notebook + self.StationList = [] + self.ChannelList = [] + self.LocList = [] + self.NetList = [] + self.SpsList = [] + + self.GlobalListVars = [ + ["Station_Name", self.GlobalStation, self.StationList, + self.GUStation], + ["Channel", self.GlobalChannel, self.ChannelList, self.GUChannel], + ["Location_Code", self.GlobalLocCode, self.LocList, + self.GULocCode], + ["Network_Code", self.GlobalNetCode, self.NetList, + self.GUNetCode], + ["Sample_Rate", self.GlobalSps, self.SpsList, self.GUSps] + ] + + # vars used in TimeShift nb + self.TimeShiftName = "" + self.OldShiftName = "" + self.TSStartTime = "" + self.TSEndTime = "" + self.TSShift = 0 + self.TypeTimeCor = 0 + self.TimeTagQuest = "" + self.WildLoc = 0 + self.PopUpHelp = 0 + self.UpdateTimeDict = {} + self.TraceTimeDict = {} + self.SetTimeDict = {} + self.TimeCorrectedFiles = {} + + self.ShiftVars = [ + ["Start_Time", self.TSStartTime], + ["End_Time", self.TSEndTime], + ["Time_Shift_sec", self.TSShift], + ["Time_Tag_Quest", self.TimeTagQuest], + ["Corr_Type", self.TypeTimeCor] + ] + + self.SetTime = 0 + self.SetTQuest = 0 + self.SetTimeVars = [ + ["Time_Shift_sec", self.SetTime], + ["Time_Tag_Quest", self.SetTQuest] + ] + + # vars used in Endianess nb + self.Savefile = "" + self.DataDirList = [] + self.BigEndianList = [] + self.LittleEndianList = [] + self.NumLittleFiles = 0 + self.NumBigFiles = 0 + self.ToEndian = "" + + # log vars and lists + self.LogList = [ + ["All", 0], + ["Header", 1], + ["Timing", 2], + ["Endian", 3] + ] + + self.LogVar = 0 + self.LogAll = [] + self.LogHeader = [] + self.LogTime = [] + self.LogEndian = [] + self.LogSummary = [] + + # activity and warning vars + self.ActiveText = "" + self.AlteredText = "" + + # set of vars watched for active threading event + self.RunBuilddb = 0 + self.RunModHdrs = 0 + self.RunApplyTimeCor = 0 + self.RunChangeEndian = 0 + self.FoundFiles = 0 + self.RWErrors = 0 + self.CancelWarn = 0 + self.IgnoreWarn = 0 + self.UseNewOnlyTime = 0 + + # if DATALOC not set on commandline set here + if DATALOC: + self.DataDirs = DATALOC + else: + self.DataDirs = os.getcwd() + + # if a batch file exists on the command line, + # we just run necessary processes for modifying headers + self.BatchFile = "" + self.BatchFile = BatchFile + + # INSERT BATCHMODE HERE + """ + if BATCHMODE: + # address endian change first since unique i.e. no batchfile + print("Running in Batch Mode") + if RunEndianBatch: + print("Changing Endianess to: ", Endianess) + self.ToEndian.set(Endianess) + self.RunChangeEndian.set(1) + print("Finding Files beneath directory: ", + self.DataDirs.get()) + self.BuildTrcList() + self.ChangeEndian() + else: + if RunTimeBatch: + print("Correcting Timing") + if RunHeaderBatch: + print("Correcting Headers") + + print("Using Template: ", self.BatchFile.get()) + self.LoadTemplate() + if RunTimeBatch: + if not self.UpdateTimeDict: + print("No Timing Corrections in Template.\nDone") + sys.exit(1) + print("Finding Files beneath directory: ", + self.DataDirs.get()) + self.BuildTrcList() + self.RunApplyTimeCor.set(1) + self.ApplyTimeCor() + if RunHeaderBatch: + if not self.UpdateHdrDict: + print("No Header Corrections in Template.\nDone") + sys.exit(1) + print("Finding Files beneath directory: ", + self.DataDirs.get()) + self.BuildTrcList() + self.RunModHdrs.set(1) + self.ModHdrs() + print("Done") + sys.exit(0) + """ + + def buildWindow(self): + """ + Build widgets for root window + """ + + # tab widget + self.tabWidget = QtWidgets.QTabWidget() + self.tabWidget.addTab(QtWidgets.QWidget(), "Trace Headers") + self.tabWidget.addTab(QtWidgets.QWidget(), "Global Modify") + self.tabWidget.addTab(QtWidgets.QWidget(), "Time Shift") + self.tabWidget.addTab(QtWidgets.QWidget(), "Endianess") + self.tabWidget.addTab(QtWidgets.QWidget(), "Log") + self.tabWidget.addTab(QtWidgets.QWidget(), "Help") + self.tabWidget.addTab(QtWidgets.QWidget(), "MSEED format") + + # save + self.save_b = QtWidgets.QPushButton("Save Template") + self.save_b.clicked.connect(self.clickedSaveTemplate) + self.save_b.setToolTip("Export saved header & \ntiming corrections to file") + self.save_b.setStyleSheet("QPushButton::hover{background-color:green;}") + + # load + self.load_b = QtWidgets.QPushButton("Load Template") + self.load_b.clicked.connect(self.clickedLoadTemplate) + self.load_b.setToolTip("Import saved header &\ntiming corrections file") + self.load_b.setStyleSheet("QPushButton::hover{background-color:green;}") + + # exit + exit_b = QtWidgets.QPushButton("Exit") + exit_b.clicked.connect(lambda: quit()) + exit_b.setToolTip("Exit program") + exit_b.setStyleSheet("QPushButton::hover{background-color:red;}") + + # groupbox for buttons/widgets under tab widget + box = QtWidgets.QGroupBox() + + self.PopUpHelp_cb = QtWidgets.QCheckBox("PopUp Help") + self.PopUpHelp_cb.setChecked(True) + self.PopUpHelp_cb.clicked.connect(self.clickedPopUpHelp) + self.PopUpHelp_cb.setToolTip("Toggles 'PopUp Help' on and off") + + + # groupbox layout + boxLayout = QtWidgets.QHBoxLayout() + boxLayout.addWidget(self.PopUpHelp_cb) + boxLayout.addStretch() + boxLayout.addWidget(self.load_b) + boxLayout.addWidget(self.save_b) + boxLayout.addWidget(exit_b) + boxLayout.setMargin(0) + box.setLayout(boxLayout) + + # info bar + self.InfoString_l = QtWidgets.QLineEdit() + self.InfoString_l.setReadOnly(True) + self.InfoString_l.setStyleSheet("background-color:yellow") + + # main window layout + mainLayout = QtWidgets.QVBoxLayout() + mainLayout.addWidget(self.tabWidget) + mainLayout.addWidget(box) + mainLayout.addWidget(self.InfoString_l) + mainLayout.setMargin(0) + self.setLayout(mainLayout) + + + def buildTraceHeaders(self): + """ + Build widgets for Trace Headers tab for selecting traces, building trace database, and correcting + headers one key at a time + """ + + # data directory find and clear buttons, and entry field + # button to build trace db + box1 = QtWidgets.QGroupBox() + + DataDirs_l = QtWidgets.QLabel("Data Directories:") + DataDirs_l.setToolTip("Search path(s) for finding mseed files.\n" + "Colon separate multiple entries") + + self.DataDir_le = QtWidgets.QLineEdit() + self.DataDir_le.setText(self.DataDirs) + + self.BuildTrcList_b = QtWidgets.QPushButton("Build Trace db") + self.BuildTrcList_b.setStyleSheet(""" + QPushButton{background-color:lightblue;} + QPushButton::hover{background-color:green;} + """) + self.BuildTrcList_b.setToolTip("Build a Trace db using\n" + "'Data Directories'\n" + "as top level directories") + + self.FindDataDir_b = QtWidgets.QPushButton("Find") + self.FindDataDir_b.setStyleSheet("QPushButton::hover{background-color:green;}") + self.FindDataDir_b.setToolTip("Dialog window to\n" + "select Data Directories") + + self.ClearDataDir_b = QtWidgets.QPushButton("Clear") + self.ClearDataDir_b.setStyleSheet("QPushButton::hover{background-color:orange;}") + self.ClearDataDir_b.setToolTip("Clears 'Data Directories' entry") + + layout1 = QtWidgets.QHBoxLayout(box1) + layout1.addWidget(DataDirs_l) + layout1.addWidget(self.DataDir_le) + layout1.addWidget(self.BuildTrcList_b) + layout1.addWidget(self.FindDataDir_b) + layout1.addWidget(self.ClearDataDir_b) + layout1.setMargin(0) + + # station selection frame and entry box + box2 = QtWidgets.QGroupBox() + + StatSel_l = QtWidgets.QLabel("Find only stations (colon separated list):") + + self.StatSel_le = QtWidgets.QLineEdit() + self.StatSel_le.setToolTip("Filter trace search\n" + "for these stations") + + self.ClearStatSel_b = QtWidgets.QPushButton("Clear") + self.ClearStatSel_b.setStyleSheet("QPushButton::hover{background-color:orange;}") + self.ClearStatSel_b.setToolTip("Clear station filter") + + layout2 = QtWidgets.QHBoxLayout(box2) + layout2.addWidget(StatSel_l) + layout2.addWidget(self.StatSel_le) + layout2.addWidget(self.ClearStatSel_b) + layout2.setMargin(0) + + # global substitutions + box3 = QtWidgets.QGroupBox() + + layout3 = QtWidgets.QHBoxLayout(box3) + layout31 = QtWidgets.QFormLayout() + layout32 = QtWidgets.QFormLayout() + layout3.addLayout(layout31) + layout3.addLayout(layout32) + + for widget in self.StatChanListVars: + if widget[0] == "Stat:Chan:Loc:Net:Sps": + layout31.addRow(QtWidgets.QLabel(widget[0]), QtWidgets.QComboBox()) + else: + layout31.addRow(QtWidgets.QLabel(widget[0]), QtWidgets.QLineEdit()) + + layout32.addRow(QtWidgets.QLabel("New Values"), QtWidgets.QLabel("Applied")) + + for _ in repeat(None, 4): + layout32.addRow(QtWidgets.QLineEdit(), QtWidgets.QCheckBox()) + + + # 4th groupbox + box4 = QtWidgets.QGroupBox() + box4.setStyleSheet("QGroupBox{border:0px;}") + + self.ListTraces_b = QtWidgets.QPushButton("List Traces") + self.ListTraces_b.setStyleSheet("QPushButton::hover{background-color:green;}") + self.ListTraces_b.setToolTip("Lists traces for selected\n" + "Stat:Chan:Loc:Net:Sps") + + self.ModHdr_b = QtWidgets.QPushButton("Modify Headers") + self.ModHdr_b.setStyleSheet(""" + QPushButton{background-color:lightblue;} + QPushButton::hover{background-color:green;} + """) + self.ModHdr_b.setToolTip("Modifies headers using current entries\n" + "and all entries in 'Update Dictionary") + + self.ClearCurrent_b = QtWidgets.QPushButton("Clear Current") + self.ClearCurrent_b.setStyleSheet("QPushButton::hover{background-color:orange;}") + self.ClearCurrent_b.setToolTip("Clears entries in 'Update Dictionary'\n" + "for selected Stat:Chan:Loc:Net:Sps") + + self.ClearUpdateDict_b = QtWidgets.QPushButton("Clear Update Dictionary") + self.ClearUpdateDict_b.setStyleSheet("QPushButton::hover{background-color:orange;}") + self.ClearUpdateDict_b.setToolTip("Clears all entries\n" + "in 'Update Dictionary'") + + layout4 = QtWidgets.QHBoxLayout(box4) + layout4.addWidget(self.ListTraces_b) + layout4.addStretch() + layout4.addWidget(self.ModHdr_b) + layout4.addWidget(self.ClearCurrent_b) + layout4.addWidget(self.ClearUpdateDict_b) + layout4.setMargin(0) + + tabLayout = QtWidgets.QVBoxLayout(self.tabWidget.widget(0)) + tabLayout.addWidget(box1) + tabLayout.addWidget(box2) + tabLayout.addWidget(box3) + tabLayout.addStretch() + tabLayout.addWidget(box4) + tabLayout.setMargin(0) + + + def buildGlobalModify(self): + """ + Build widgets for Global Modify tab for making global changes to headers + """ + + + def buildTimeShift(self): + """ + Build widgets for Time Shift tab for applying time corrections to headers + """ + + + def buildEndianess(self): + """ + Build widgets for Endianness tab for swapping endianess of headers + """ + + + def buildLog(self): + """ + Build widgets for Log tab for keeping track of changes + """ + + + def buildHelp(self): + """ + Build widgets for Help tab + """ + + + def buildMSEEDformat(self): + """ + Build widgets for MSEED format tab + """ + + + def clickedPopUpHelp(self): + """ + """ + + + def clickedLoadTemplate(self): + """ + """ + + + def clickedSaveTemplate(self): + """ + """ + + def clickedBuildTrace(self): + """ + """ + + def clickedFind(self): + """ + """ + + + +if __name__ == "__main__": + app = QtWidgets.QApplication() + window = MainWindow() + window.show() + sys.exit(app.exec_()) + -- GitLab