Surface NMR processing and inversion GUI
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

akvoGUI.py 81KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869
  1. #/usr/bin/env python
  2. import sys
  3. import matplotlib
  4. matplotlib.use("QT5Agg")
  5. from PyQt5 import QtCore, QtGui, QtWidgets #, uic
  6. import numpy as np
  7. import time
  8. import os
  9. from copy import deepcopy
  10. from matplotlib.backends.backend_qt4 import NavigationToolbar2QT #as NavigationToolbar
  11. import datetime, time
  12. import pkg_resources # part of setuptools
  13. from collections import OrderedDict
  14. from ruamel import yaml
  15. from akvo.gui.main_ui import Ui_MainWindow
  16. from akvo.gui.addCircularLoop_ui import Ui_circularLoopAdd
  17. from akvo.gui.addFigure8Loop_ui import Ui_figure8LoopAdd
  18. from akvo.gui.addPolygonalLoop_ui import Ui_polygonalLoopAdd
  19. from akvo.gui.redirect_ui import Ui_callScript
  20. from akvo.gui.callScript import callScript
  21. from akvo.tressel import mrsurvey
  22. from pyLemma import LemmaCore
  23. from pyLemma import FDEM1D
  24. from pyLemma import Merlin
  25. VERSION = pkg_resources.require("Akvo")[0].version
  26. # Writes out numpy arrays into Eigen vectors as serialized by Lemma
  27. class MatrixXr(yaml.YAMLObject):
  28. yaml_tag = u'MatrixXr'
  29. def __init__(self, rows, cols, data):
  30. self.rows = rows
  31. self.cols = cols
  32. self.data = np.zeros((rows,cols))
  33. def __repr__(self):
  34. return "%s(rows=%r, cols=%r, data=%r)" % (self.__class__.__name__, self.rows, self.cols, self.data)
  35. class VectorXr(yaml.YAMLObject):
  36. yaml_tag = r'VectorXr'
  37. def __init__(self, array):
  38. self.size = np.shape(array)[0]
  39. self.data = array.tolist()
  40. def __repr__(self):
  41. # Converts to numpy array on import
  42. return "np.array(%r)" % (self.data)
  43. def setup_yaml():
  44. """ https://stackoverflow.com/a/8661021 """
  45. represent_dict_order = lambda self, data: self.represent_mapping('tag:yaml.org,2002:map', data.items())
  46. yaml.add_representer(OrderedDict, represent_dict_order)
  47. setup_yaml()
  48. class AkvoYamlNode(yaml.YAMLObject):
  49. yaml_tag = u'AkvoData'
  50. def __init__(self):
  51. self.Akvo_VERSION = VERSION
  52. self.Import = OrderedDict() # {}
  53. self.Processing = [] # OrderedDict()
  54. self.Stacking = OrderedDict()
  55. self.META = OrderedDict()
  56. def __repr__(self):
  57. return "%s(name=%r, Akvo_VERSION=%r, Import=%r, Processing=%r, self.Stacking=%r, self.META=%r)" % (
  58. self.__class__.__name__, self.Akvo_VERSION, self.Import, self.Processing, self.Stacking, self.META )
  59. try:
  60. import thread
  61. except ImportError:
  62. import _thread as thread #Py3K compatibility
  63. class MyPopup(QtWidgets.QWidget):
  64. def __init__(self, name):
  65. super().__init__()
  66. self.name = name
  67. self.initUI()
  68. def initUI(self):
  69. lblName = QtWidgets.QLabel(self.name, self)
  70. class ApplicationWindow(QtWidgets.QMainWindow):
  71. def __init__(self):
  72. super().__init__()
  73. #QtWidgets.QMainWindow.__init__(self)
  74. self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
  75. # alternative to calling pyuic
  76. #self.ui = uic.loadUi('main.ui', self)
  77. self.ui = Ui_MainWindow()
  78. self.ui.setupUi(self)
  79. self.RAWDataProc = None
  80. self.YamlNode = AkvoYamlNode()
  81. # initialise some stuff
  82. self.ui.lcdNumberTauPulse2.setEnabled(0)
  83. self.ui.lcdNumberTauPulse1.setEnabled(0)
  84. self.ui.lcdNumberNuTx.setEnabled(0)
  85. self.ui.lcdNumberTuneuF.setEnabled(0)
  86. self.ui.lcdNumberSampFreq.setEnabled(0)
  87. self.ui.lcdNumberTauDelay.setEnabled(0)
  88. self.ui.lcdNumberNQ.setEnabled(0)
  89. self.logText = []
  90. #######################
  91. ##################### #
  92. ## Make connections # #
  93. ##################### #
  94. #######################
  95. ##############
  96. # Menu items #
  97. ##############
  98. self.ui.actionOpen_GMR.triggered.connect(self.openGMRRAWDataset)
  99. self.ui.actionSave_Preprocessed_Dataset.triggered.connect(self.SavePreprocess)
  100. self.ui.actionExport_Preprocessed_Dataset.triggered.connect(self.ExportPreprocess)
  101. self.ui.actionExport_Preprocessed_Dataset.setEnabled(False)
  102. self.ui.actionOpen_Preprocessed_Dataset.triggered.connect(self.OpenPreprocess)
  103. self.ui.actionAboutAkvo.triggered.connect(self.about)
  104. ###########
  105. # Buttons #
  106. ###########
  107. self.ui.loadDataPushButton.pressed.connect(self.loadRAW)
  108. self.ui.sumDataGO.pressed.connect( self.sumDataChans )
  109. self.ui.bandPassGO.pressed.connect( self.bandPassFilter )
  110. self.ui.filterDesignPushButton.pressed.connect( self.designFilter )
  111. self.ui.fdDesignPushButton.pressed.connect( self.designFDFilter )
  112. self.ui.downSampleGO.pressed.connect( self.downsample )
  113. self.ui.windowFilterGO.pressed.connect( self.windowFilter )
  114. self.ui.adaptGO.pressed.connect( self.adaptFilter )
  115. self.ui.adaptFDGO.pressed.connect( self.adaptFilterFD )
  116. self.ui.qdGO.pressed.connect( self.quadDet )
  117. self.ui.gateIntegrateGO.pressed.connect( self.gateIntegrate )
  118. self.ui.calcQGO.pressed.connect( self.calcQ )
  119. self.ui.FDSmartStackGO.pressed.connect( self.FDSmartStack )
  120. self.ui.harmonicGO.pressed.connect( self.harmonicModel )
  121. self.ui.K0Data.pressed.connect( self.K0DataSelect )
  122. self.ui.invDataButton.pressed.connect( self.invDataSelect )
  123. self.ui.invKernelButton.pressed.connect( self.invKernelSelect )
  124. self.ui.f0K1Spin.valueChanged.connect( self.LCDHarmonics )
  125. self.ui.f0KNSpin.valueChanged.connect( self.LCDHarmonics )
  126. self.ui.f0KsSpin.valueChanged.connect( self.LCDHarmonics )
  127. self.ui.f0Spin.valueChanged.connect( self.LCDHarmonics )
  128. self.ui.NHarmonicsFreqsSpin.valueChanged.connect( self.LCDHarmonics2 )
  129. self.ui.f1K1Spin.valueChanged.connect( self.LCDHarmonics2 )
  130. self.ui.f1KNSpin.valueChanged.connect( self.LCDHarmonics2 )
  131. self.ui.f1KsSpin.valueChanged.connect( self.LCDHarmonics2 )
  132. self.ui.f1Spin.valueChanged.connect( self.LCDHarmonics2 )
  133. self.ui.plotQD.setEnabled(False)
  134. self.ui.plotQD.pressed.connect( self.plotQD )
  135. self.ui.plotGI.setEnabled(False)
  136. self.ui.plotGI.pressed.connect( self.plotGI )
  137. # Kernel
  138. self.ui.calcK0.pressed.connect( self.calcK0 )
  139. # Inversion
  140. self.ui.invertButton.pressed.connect( self.QTInv )
  141. # META
  142. self.ui.locEdit.editingFinished.connect( self.logSite )
  143. self.ui.UTMzone.currentIndexChanged.connect( self.logSite )
  144. self.ui.latBand.currentIndexChanged.connect( self.logSite )
  145. self.ui.ellipsoid.currentIndexChanged.connect( self.logSite )
  146. self.ui.incSpinBox.valueChanged.connect( self.logSite )
  147. self.ui.decSpinBox.valueChanged.connect( self.logSite )
  148. self.ui.intensitySpinBox.valueChanged.connect( self.logSite )
  149. self.ui.tempSpinBox.valueChanged.connect( self.logSite )
  150. self.ui.timeEdit.timeChanged.connect( self.logSite )
  151. self.ui.dateEdit.dateChanged.connect( self.logSite )
  152. # this may call the yaml stuff too often...
  153. self.ui.txtComments.textChanged.connect( self.logSite )
  154. self.ui.plotLoops.pressed.connect( self.plotLoops2 )
  155. self.ui.removeLoopButton.pressed.connect( self.removeLoop )
  156. # Loops
  157. self.ui.addLoopButton.pressed.connect( self.loopAdd )
  158. self.loops = {}
  159. # hide header info box
  160. #self.ui.headerFileBox.setVisible(False)
  161. self.ui.headerFileBox.clicked.connect( self.headerBoxShrink )
  162. self.ui.headerBox2.setVisible(False)
  163. # Clean up the tab widget
  164. self.ui.actionPreprocessing.triggered.connect(self.addPreProc)
  165. self.ui.actionModelling.triggered.connect(self.addModelling)
  166. self.ui.actionInversion.triggered.connect(self.addInversion)
  167. # tabs
  168. #self.ui.ProcTabs.tabCloseRequested.connect( self.closeTabs )
  169. #self.ui.ProcTabs.tabBar().setTabButton(7, QtWidgets.QTabBar.RightSide,None)
  170. self.ui.ProcTabs.removeTab(4)
  171. self.ui.ProcTabs.removeTab(4)
  172. self.ui.ProcTabs.removeTab(4)
  173. self.ui.ProcTabs.removeTab(4)
  174. #self.ui.LoadTab.close( )
  175. # Add progressbar to statusbar
  176. self.ui.barProgress = QtWidgets.QProgressBar()
  177. self.ui.statusbar.addPermanentWidget(self.ui.barProgress, 0);
  178. self.ui.barProgress.setMaximumSize(100, 16777215);
  179. self.ui.barProgress.hide();
  180. self.ui.mplwidget_navigator.setCanvas(self.ui.mplwidget)
  181. #self.ui.mplwidget_navigator_2.setCanvas(self.ui.mplwidget)
  182. self.ui.txRxTable.setColumnCount(4)
  183. self.ui.txRxTable.setRowCount(0)
  184. self.ui.txRxTable.setHorizontalHeaderLabels( ["Label", "Geom.","Turns","Tx/Rx"] )
  185. ##########################################################################
  186. # layer Table
  187. self.ui.layerTableWidget.setRowCount(80)
  188. self.ui.layerTableWidget.setColumnCount(3)
  189. self.ui.layerTableWidget.setHorizontalHeaderLabels( [r"top [m]", r"bottom [m]", "ρ [Ωm]" ] )
  190. # do we want this
  191. self.ui.layerTableWidget.setDragDropOverwriteMode(False)
  192. self.ui.layerTableWidget.setDragEnabled(True)
  193. self.ui.layerTableWidget.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
  194. pCell0 = QtWidgets.QTableWidgetItem()
  195. pCell0.setFlags(QtCore.Qt.NoItemFlags) # not selectable
  196. pCell0.setBackground( QtGui.QColor("lightgrey").lighter(110) )
  197. pCell0.setForeground( QtGui.QColor("black") )
  198. pCell0.setText(str("0"))
  199. self.ui.layerTableWidget.setItem(0, 0, pCell0)
  200. pCell1 = QtWidgets.QTableWidgetItem()
  201. #pCell1.setFlags(QtCore.Qt.NoItemFlags) # not selectable
  202. pCell1.setBackground( QtGui.QColor("lightblue") ) #.lighter(110) )
  203. pCell1.setForeground( QtGui.QColor("black") )
  204. self.ui.layerTableWidget.setItem(0, 1, pCell1)
  205. pCell2 = QtWidgets.QTableWidgetItem()
  206. #pCell1.setFlags(QtCore.Qt.NoItemFlags) # not selectable
  207. pCell2.setBackground( QtGui.QColor("white") ) #.lighter(110) )
  208. pCell2.setForeground( QtGui.QColor("black") )
  209. self.ui.layerTableWidget.setItem(0, 2, pCell2)
  210. for ir in range(1, self.ui.layerTableWidget.rowCount() ):
  211. for ic in range(0, self.ui.layerTableWidget.columnCount() ):
  212. pCell = QtWidgets.QTableWidgetItem()
  213. #pCell.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
  214. pCell.setFlags(QtCore.Qt.NoItemFlags) # not selectable
  215. pCell.setBackground( QtGui.QColor("lightgrey").lighter(110) )
  216. pCell.setForeground( QtGui.QColor("black"))
  217. self.ui.layerTableWidget.setItem(ir, ic, pCell)
  218. self.ui.layerTableWidget.cellChanged.connect(self.sigmaCellChanged)
  219. def LCDHarmonics(self):
  220. self.ui.lcdH1F.setEnabled(True)
  221. self.ui.lcdH1F.display( self.ui.f0Spin.value() * self.ui.f0K1Spin.value() )
  222. self.ui.lcdHNF.setEnabled(True)
  223. self.ui.lcdHNF.display( self.ui.f0Spin.value() * self.ui.f0KNSpin.value() )
  224. self.ui.lcdf0NK.setEnabled(True)
  225. self.ui.lcdf0NK.display( (self.ui.f0KNSpin.value()+1-self.ui.f0K1Spin.value()) * self.ui.f0KsSpin.value() )
  226. def LCDHarmonics2(self):
  227. if self.ui.NHarmonicsFreqsSpin.value() == 2:
  228. self.ui.lcdH1F2.setEnabled(True)
  229. self.ui.lcdH1F2.display( self.ui.f1Spin.value() * self.ui.f1K1Spin.value() )
  230. self.ui.lcdHNF2.setEnabled(True)
  231. self.ui.lcdHNF2.display( self.ui.f1Spin.value() * self.ui.f1KNSpin.value() )
  232. self.ui.lcdf0NK2.setEnabled(True)
  233. self.ui.lcdf0NK2.display( (self.ui.f1KNSpin.value()+1-self.ui.f1K1Spin.value()) * self.ui.f1KsSpin.value() )
  234. else:
  235. self.ui.lcdH1F2.setEnabled(False)
  236. self.ui.lcdHNF2.setEnabled(False)
  237. self.ui.lcdf0NK2.setEnabled(False)
  238. def closeTabs(self):
  239. #self.ui.ProcTabs.removeTab(idx)
  240. self.ui.ProcTabs.clear( )
  241. def addPreProc(self):
  242. if self.ui.actionPreprocessing.isChecked():
  243. self.ui.actionModelling.setChecked(False)
  244. self.ui.actionInversion.setChecked(False)
  245. self.ui.ProcTabs.clear( )
  246. self.ui.ProcTabs.insertTab( 0, self.ui.LoadTab, "Load" )
  247. self.ui.ProcTabs.insertTab( 1, self.ui.NCTab, "Noise removal" )
  248. self.ui.ProcTabs.insertTab( 2, self.ui.QCTab, "QC" )
  249. self.ui.ProcTabs.insertTab( 3, self.ui.METATab, "META" )
  250. self.ui.ProcTabs.insertTab( 4, self.ui.LogTab, "Log" )
  251. else:
  252. self.ui.ProcTabs.removeTab(0)
  253. self.ui.ProcTabs.removeTab(0)
  254. self.ui.ProcTabs.removeTab(0)
  255. self.ui.ProcTabs.removeTab(0)
  256. def addModelling(self):
  257. if self.ui.actionModelling.isChecked():
  258. self.ui.actionPreprocessing.setChecked(False)
  259. self.ui.actionInversion.setChecked(False)
  260. self.ui.ProcTabs.clear( )
  261. self.ui.ProcTabs.insertTab( 0, self.ui.KernTab, "Kernel" )
  262. self.ui.ProcTabs.insertTab( 1, self.ui.ModelTab, "Modelling" )
  263. #self.ui.ProcTabs.insertTab( 2, self.ui.LogTab, "Log" )
  264. else:
  265. self.ui.ProcTabs.removeTab(0)
  266. self.ui.ProcTabs.removeTab(0)
  267. def addInversion(self, idx):
  268. if self.ui.actionInversion.isChecked():
  269. self.ui.actionPreprocessing.setChecked(False)
  270. self.ui.actionModelling.setChecked(False)
  271. self.ui.ProcTabs.clear( )
  272. self.ui.ProcTabs.insertTab( 0, self.ui.InvertTab, "QT Inversion" )
  273. self.ui.ProcTabs.insertTab( 1, self.ui.AppraiseTab, "Appraisal" )
  274. #self.ui.ProcTabs.insertTab( 2, self.ui.LogTab, "Log" )
  275. else:
  276. self.ui.ProcTabs.removeTab(0)
  277. self.ui.ProcTabs.removeTab(0)
  278. def invDataSelect(self):
  279. try:
  280. with open('.akvo.last.path') as f:
  281. fpath = f.readline()
  282. pass
  283. except IOError as e:
  284. fpath = '.'
  285. self.akvoDataFile = QtWidgets.QFileDialog.getOpenFileName(self, 'Select Datafile File', fpath, r"Akvo datafiles (*.yaml)")[0]
  286. self.ui.dataText.clear()
  287. self.ui.dataText.append( self.akvoDataFile )
  288. def K0DataSelect(self):
  289. try:
  290. with open('.akvo.last.path') as f:
  291. fpath = f.readline()
  292. pass
  293. except IOError as e:
  294. fpath = '.'
  295. self.K0akvoDataFile = QtWidgets.QFileDialog.getOpenFileName(self, 'Select Datafile File', fpath, r"Akvo datafiles (*.yaml)")[0]
  296. self.ui.K0DataText.clear()
  297. self.ui.K0DataText.append( self.K0akvoDataFile )
  298. # populate combo box with loops
  299. with open(self.K0akvoDataFile) as f:
  300. parse = yaml.load( f, Loader=yaml.Loader )
  301. self.ui.txListWidget.clear()
  302. self.ui.rxListWidget.clear()
  303. for loop in parse.META["Loops"]:
  304. print(loop)
  305. self.ui.txListWidget.addItem( parse.META["Loops"][loop] )
  306. self.ui.rxListWidget.addItem( parse.META["Loops"][loop] )
  307. self.ui.txListWidget.setCurrentRow(0)
  308. self.ui.rxListWidget.setCurrentRow(0)
  309. def invKernelSelect(self):
  310. try:
  311. with open('.akvo.last.path') as f:
  312. fpath = f.readline()
  313. pass
  314. except IOError as e:
  315. fpath = '.'
  316. self.K0file = QtWidgets.QFileDialog.getOpenFileName(self, 'Select Kernel File', fpath, r"Akvo kernels (*.yml)")[0]
  317. self.ui.kernelText.clear()
  318. self.ui.kernelText.append(self.K0file)
  319. def QTInv(self):
  320. print("Big RED INVERT BUTTON")
  321. try:
  322. with open('.akvo.last.path') as f:
  323. fpath = f.readline()
  324. pass
  325. except IOError as e:
  326. fpath = '.'
  327. #K0file = self.ui.kernelText.text()
  328. #akvoDataFile = self.ui.dataText.text()
  329. T2lo = self.ui.T2low.value()
  330. T2hi = self.ui.T2hi.value()
  331. NT2 = self.ui.NT2.value()
  332. dataChan = self.ui.invChan.currentText()
  333. t2Obj = self.ui.T2Objective.currentText()
  334. depthObj = self.ui.depthObjective.currentText()
  335. alpha_0 = self.ui.initialAlpha.value()
  336. invDict = dict()
  337. invDict["data"] = dict()
  338. invDict["data"] = dict()
  339. invDict["data"][self.akvoDataFile] = dict()
  340. invDict["data"][self.akvoDataFile]["channels"] = [dataChan,]
  341. invDict["K0"] = [self.K0file,]
  342. invDict["T2Bins"] = dict()
  343. invDict["T2Bins"]["low"] = T2lo
  344. invDict["T2Bins"]["high"] = T2hi
  345. invDict["T2Bins"]["number"] = NT2
  346. node = yaml.YAML()
  347. kpo = open( "invert.yml", 'w' )
  348. node.dump(invDict, kpo)
  349. callBox = callScript( ) #QtWidgets.QDialog()
  350. callBox.ui = Ui_callScript()
  351. callBox.ui.setupUi( callBox )
  352. callBox.setupQTInv( "invert.yml" )
  353. callBox.exec_()
  354. callBox.show()
  355. def calcK0(self):
  356. try:
  357. with open('.akvo.last.path') as f:
  358. fpath = f.readline()
  359. pass
  360. except IOError as e:
  361. fpath = '.'
  362. #self.K0akvoDataFile = QtWidgets.QFileDialog.getOpenFileName(self, 'Select Datafile File', fpath, r"Akvo datafiles (*.yaml)")[0]
  363. #akvoData = QtWidgets.QFileDialog.getOpenFileName(self, 'Open Datafile File', fpath, r"Akvo datafiles (*.yaml)")[0]
  364. txCoil = self.ui.txListWidget.currentItem().text()
  365. saveStr = QtWidgets.QFileDialog.getSaveFileName(self, "Save kernel as", fpath, r"Merlin KernelV0 (*.yml)")[0]
  366. intDict = dict()
  367. intDict["origin_n"] = self.ui.originN.value()
  368. intDict["origin_e"] = self.ui.originE.value()
  369. intDict["origin_d"] = self.ui.originD.value()
  370. intDict["size_n"] = self.ui.sizeN.value()
  371. intDict["size_e"] = self.ui.sizeE.value()
  372. intDict["size_d"] = self.ui.sizeD.value()
  373. intDict["nLay"] = self.ui.NLayers.value()
  374. intDict["thick1"] = self.ui.thick1.value()
  375. intDict["thickN"] = self.ui.thickN.value()
  376. intDict["Lspacing"] = self.ui.layerSpacing.currentText()
  377. intDict["minLevel"] = self.ui.minLevel.value()
  378. intDict["maxLevel"] = self.ui.maxLevel.value()
  379. intDict["branchTol"] = self.ui.branchTol.value()
  380. # conductivity model...
  381. #tops = self.ui.layerTableWidget.col(0)
  382. #print("Tops", tops)
  383. tops = []
  384. itop = 0
  385. while self.ui.layerTableWidget.item(itop, 0).text():
  386. tops.append( float(self.ui.layerTableWidget.item(itop,0).text()) )
  387. itop += 1
  388. bots = []
  389. ibot = 0
  390. while self.ui.layerTableWidget.item(ibot, 1).text():
  391. bots.append( float(self.ui.layerTableWidget.item(ibot, 1).text()) )
  392. ibot += 1
  393. sigs = []
  394. isig = 0
  395. while self.ui.layerTableWidget.item(isig, 2).text():
  396. sigs.append( 1./float(self.ui.layerTableWidget.item(isig, 2).text()) )
  397. isig += 1
  398. intDict["tops"] = tops
  399. intDict["bots"] = bots
  400. intDict["sigs"] = sigs
  401. node = yaml.YAML()
  402. kpo = open( "kparams.yml", 'w' )
  403. node.dump(intDict, kpo)
  404. callBox = callScript( ) #QtWidgets.QDialog()
  405. callBox.ui = Ui_callScript()
  406. callBox.ui.setupUi( callBox )
  407. callBox.setupCB( self.K0akvoDataFile, txCoil, "kparams.yml", saveStr )
  408. callBox.exec_()
  409. callBox.show()
  410. def loopAdd(self):
  411. #print(self.ui.loopLabel.text())
  412. #print(self.ui.loopGeom.currentText())
  413. #print(self.ui.loopType.currentText())
  414. #print( "label len", len(self.ui.loopLabel.text()) )
  415. if len(self.ui.loopLabel.text().strip()) == 0:
  416. Error = QtWidgets.QMessageBox()
  417. Error.setWindowTitle("Error!")
  418. Error.setText("Loop label cannot be blank or repeated")
  419. Error.setDetailedText("Each loop label must be unique and comprise at least one character. Leading and trailing whitespace will be trimmed.")
  420. Error.exec_()
  421. else:
  422. ### Circular loop
  423. if self.ui.loopGeom.currentText() == "Circular":
  424. dialog = QtWidgets.QDialog()
  425. dialog.ui = Ui_circularLoopAdd()
  426. dialog.ui.setupUi(dialog)
  427. dialog.exec_()
  428. dialog.show()
  429. if dialog.result():
  430. cn = dialog.ui.centreNorth.value()
  431. ce = dialog.ui.centreEast.value()
  432. ht = dialog.ui.loopHeight.value()
  433. rad = dialog.ui.loopRadius.value()
  434. turns = dialog.ui.loopTurns.value()
  435. ns = dialog.ui.segments.value()
  436. cwise = dialog.ui.cwiseBox.currentIndex()
  437. #print("cwise", cwise)
  438. #dip = dialog.ui.dip.value()
  439. #azimuth = dialog.ui.az.value()
  440. self.loops[self.ui.loopLabel.text()] = FDEM1D.PolygonalWireAntenna()
  441. self.loops[self.ui.loopLabel.text()].SetNumberOfPoints( dialog.ui.segments.value() + 1 )
  442. self.loops[self.ui.loopLabel.text()].SetNumberOfTurns( dialog.ui.loopTurns.value() )
  443. points = np.linspace(0, 2*np.pi, dialog.ui.segments.value()+1)
  444. for iseg, ipt in enumerate(points):
  445. if cwise == 0:
  446. self.loops[self.ui.loopLabel.text()].SetPoint(iseg, ( cn+rad*np.sin(ipt), ce+rad*np.cos(ipt), ht) )
  447. else:
  448. self.loops[self.ui.loopLabel.text()].SetPoint(iseg, ( -cn+rad*np.sin(ipt), ce+rad*np.cos(ipt), ht) )
  449. self.loops[self.ui.loopLabel.text()].SetNumberOfFrequencies(1)
  450. self.loops[self.ui.loopLabel.text()].SetCurrent(1.)
  451. if self.ui.loopGeom.currentText() == "figure-8":
  452. dialog = QtWidgets.QDialog()
  453. dialog.ui = Ui_figure8LoopAdd()
  454. dialog.ui.setupUi(dialog)
  455. dialog.exec_()
  456. dialog.show()
  457. if dialog.result():
  458. cn1 = dialog.ui.centreNorth1.value()
  459. ce1 = dialog.ui.centreEast1.value()
  460. cn2 = dialog.ui.centreNorth2.value()
  461. ce2 = dialog.ui.centreEast2.value()
  462. ht = dialog.ui.loopHeight.value()
  463. rad = dialog.ui.loopRadius.value()
  464. turns = dialog.ui.loopTurns.value()
  465. ns = dialog.ui.segments.value()
  466. #cwise = dialog.ui.cwiseBox.currentIndex()
  467. print(cn1, ce1, cn2, ce2, ht, rad, turns, ns)
  468. if self.ui.loopGeom.currentText() == "polygon":
  469. dialog = QtWidgets.QDialog()
  470. dialog.ui = Ui_polygonalLoopAdd()
  471. dialog.ui.setupUi(dialog)
  472. ##########################################################################
  473. # Loop Table
  474. dialog.ui.loopTableWidget.setRowCount(80)
  475. dialog.ui.loopTableWidget.setColumnCount(3)
  476. #dialog.ui.loopTableWidget.horizontalHeader().setSectionResizeMode(0, QtGui.Qt.QHeaderView.Stretch)
  477. dialog.ui.loopTableWidget.setHorizontalHeaderLabels( \
  478. ["Northing [m]","Easting [m]","Height [m]"])
  479. for ir in range(0, dialog.ui.loopTableWidget.rowCount() ):
  480. for ic in range(0, 3): #dialog.ui.loopTableWidget.columnCount() ):
  481. pCell = QtWidgets.QTableWidgetItem()
  482. #pCell.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
  483. #pCell.setFlags(QtCore.Qt.NoItemFlags) # not selectable
  484. #pCell.setBackground( QtGui.QColor("lightgrey").lighter(110) )
  485. dialog.ui.loopTableWidget.setItem(ir, ic, pCell)
  486. #dialog.ui.loopTableWidget.cellChanged.connect(self.loopCellChanged)
  487. #dialog.ui.loopTableWidget.itemClicked.connect(self.loopCellClicked)
  488. #self.ui.loopTableWidget.cellPressed.connect(self.loopCellChanged)
  489. #self.ui.loopTableWidget.cellPressed.connect(self.loopCellClicked)
  490. dialog.ui.loopTableWidget.setDragDropOverwriteMode(False)
  491. dialog.ui.loopTableWidget.setDragEnabled(False)
  492. #self.ui.loopTableWidget.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
  493. dialog.ui.loopTableWidget.resizeColumnsToContents()
  494. dialog.exec_()
  495. dialog.show()
  496. if dialog.result():
  497. self.loops[self.ui.loopLabel.text()] = FDEM1D.PolygonalWireAntenna()
  498. self.loops[self.ui.loopLabel.text()].SetNumberOfTurns( dialog.ui.loopTurns.value() )
  499. npts = 0
  500. for ir in range(0, dialog.ui.loopTableWidget.rowCount() ):
  501. if len(dialog.ui.loopTableWidget.item(ir, 0).text()) == 0:
  502. break
  503. npts += 1
  504. self.loops[self.ui.loopLabel.text()].SetNumberOfPoints( npts )
  505. for ir in range( 0, npts ):
  506. self.loops[self.ui.loopLabel.text()].SetPoint(ir, eval(dialog.ui.loopTableWidget.item(ir, 0).text()), \
  507. eval(dialog.ui.loopTableWidget.item(ir, 1).text()), \
  508. eval(dialog.ui.loopTableWidget.item(ir, 2).text()) \
  509. )
  510. self.loops[self.ui.loopLabel.text()].SetNumberOfFrequencies(1)
  511. self.loops[self.ui.loopLabel.text()].SetCurrent(1.)
  512. # general across all types
  513. if dialog.result():
  514. yml = open( self.ui.loopLabel.text() + ".yml", 'w' )
  515. print( self.loops[self.ui.loopLabel.text()], file=yml)
  516. # update the table
  517. self.ui.txRxTable.setRowCount( len(self.loops.keys()) )
  518. pCell = QtWidgets.QTableWidgetItem()
  519. pCell.setText( self.ui.loopLabel.text() )
  520. pCell.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
  521. self.ui.txRxTable.setItem( len(self.loops.keys())-1, 0, pCell)
  522. gCell = QtWidgets.QTableWidgetItem()
  523. gCell.setText( self.ui.loopGeom.currentText() )
  524. gCell.setFlags( QtCore.Qt.ItemIsEnabled )
  525. self.ui.txRxTable.setItem( len(self.loops.keys())-1, 1, gCell)
  526. tCell = QtWidgets.QTableWidgetItem()
  527. tCell.setText( str(dialog.ui.loopTurns.value()) )
  528. tCell.setFlags( QtCore.Qt.ItemIsEnabled )
  529. self.ui.txRxTable.setItem( len(self.loops.keys())-1, 2, tCell)
  530. txCell = QtWidgets.QTableWidgetItem()
  531. txCell.setText( str(self.ui.loopType.currentText()) )
  532. txCell.setFlags( QtCore.Qt.ItemIsEnabled )
  533. self.ui.txRxTable.setItem( len(self.loops.keys())-1, 3, txCell)
  534. def headerBoxShrink(self):
  535. #self.ui.headerFileBox.setVisible(False)
  536. if self.ui.headerFileBox.isChecked( ):
  537. #self.ui.headerFileBox.setMinimumSize(460,250)
  538. self.ui.headerBox2.setVisible(True)
  539. else:
  540. #self.ui.headerFileBox.setMinimumSize(460,50)
  541. self.ui.headerBox2.setVisible(False)
  542. def sigmaCellChanged(self):
  543. self.ui.layerTableWidget.cellChanged.disconnect(self.sigmaCellChanged)
  544. # TODO consider building the model whenever this is called. Would be nice to be able to
  545. # do that. Would require instead dist of T2 I guess.
  546. jj = self.ui.layerTableWidget.currentColumn()
  547. ii = self.ui.layerTableWidget.currentRow()
  548. val = "class 'NoneType'>"
  549. try:
  550. val = eval (str( self.ui.layerTableWidget.item(ii, jj).text() ))
  551. except:
  552. #if jj != 0:
  553. # Error = QtWidgets.QMessageBox()
  554. # Error.setWindowTitle("Error!")
  555. # Error.setText("Non-numeric value encountered")
  556. self.ui.layerTableWidget.cellChanged.connect(self.sigmaCellChanged)
  557. return
  558. if jj == 1:
  559. #item.setFlags(QtCore.Qt.ItemIsEnabled)
  560. pCell = self.ui.layerTableWidget.item(ii, jj)
  561. pCell.setBackground( QtGui.QColor("white"))
  562. pCell = self.ui.layerTableWidget.item(ii+1, jj-1)
  563. if str(type(pCell)) == "<class 'NoneType'>":
  564. pCell = QtWidgets.QTableWidgetItem()
  565. pCell.setFlags(QtCore.Qt.ItemIsEnabled)
  566. self.ui.layerTableWidget.setItem(ii+1, jj-1, pCell)
  567. if ii == 0:
  568. pCell.setText(str(val))
  569. #pCell3 = self.ui.layerTableWidget.item(ii+1, jj)
  570. #print ("setting", ii, jj, type(pCell3))
  571. #print ( "setting", ii, jj, type(pCell3))
  572. #pCell3.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled )
  573. #pCell3.setFlags( QtCore.Qt.ItemIsEditable )
  574. elif ii > 0:
  575. val2 = eval (str( self.ui.layerTableWidget.item(ii-1, jj).text() ))
  576. #print ("val2", val2, val, type(val))
  577. #if str(type(pCell)) == "<class 'NoneType'>":
  578. if type(val) == str or val > val2:
  579. pCell.setText(str(val))
  580. else:
  581. Error = QtWidgets.QMessageBox()
  582. Error.setWindowTitle("Error!")
  583. Error.setText("Non-increasing layer detected")
  584. Error.setDetailedText("Each layer interface must be below the one above it.")
  585. Error.exec_()
  586. #err_msg = "Quadrature detection has already been done!"
  587. #reply =QtWidgets.QMessageBox.critical(self, 'Error',
  588. # err_msg)
  589. pCell2 = self.ui.layerTableWidget.item(ii, jj)
  590. pCell2.setText(str(""))
  591. self.ui.layerTableWidget.cellChanged.connect(self.sigmaCellChanged)
  592. return
  593. # enable next layer
  594. pCell4 = self.ui.layerTableWidget.item(ii+1, jj)
  595. pCell4.setBackground( QtGui.QColor("lightblue") ) #.lighter(110))
  596. pCell4.setForeground( QtGui.QColor("black"))
  597. pCell4.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled )
  598. pCell5 = self.ui.layerTableWidget.item(ii+1, jj+1)
  599. pCell5.setBackground( QtGui.QColor("white"))
  600. pCell5.setForeground( QtGui.QColor("black"))
  601. pCell5.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled )
  602. if ii == 0 and jj == 0:
  603. pCell = self.ui.layerTableWidget.item(0, 1)
  604. pCell.setBackground(QtGui.QColor("lightblue")) #.lighter(110) )
  605. pCell.setForeground( QtGui.QColor("black"))
  606. pCell.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled )
  607. self.ui.layerTableWidget.cellChanged.connect(self.sigmaCellChanged)
  608. def plotLoops2(self):
  609. self.ui.mplwidget.reAxH(1)
  610. for loop in self.loops:
  611. POINTS = self.loops[loop].GetPoints().T
  612. self.ui.mplwidget.ax1.plot( POINTS[:,1], POINTS[:,0], label=loop )
  613. self.ui.mplwidget.ax1.spines['right'].set_visible(False)
  614. self.ui.mplwidget.ax1.spines['top'].set_visible(False)
  615. self.ui.mplwidget.ax1.set_xlabel("easting (m)")
  616. self.ui.mplwidget.ax1.set_ylabel("northing (m)")
  617. self.ui.mplwidget.ax1.legend()
  618. self.ui.mplwidget.ax1.set_aspect('equal') #, adjustable='box')
  619. self.ui.mplwidget.draw()
  620. def removeLoop(self):
  621. del self.loops[ self.ui.txRxTable.item( self.ui.txRxTable.currentRow(), 0).text() ]
  622. self.ui.txRxTable.removeRow(self.ui.txRxTable.currentRow())
  623. def about(self):
  624. # TODO proper popup with info
  625. #self.w = MyPopup("""About Akvo \n
  626. # Akvo is an open source project developed primarily by Trevor Irons.
  627. #""")
  628. #self.w.setGeometry(100, 100, 400, 200)
  629. #self.w.show()
  630. #print("ABOUT")
  631. # Just a splash screen for now
  632. logo = pkg_resources.resource_filename(__name__, 'akvo-about.png')
  633. pixmap = QtGui.QPixmap(logo)
  634. self.splash = QtWidgets.QSplashScreen(pixmap, QtCore.Qt.WindowStaysOnTopHint)
  635. self.splash.show()
  636. def connectGMRDataProcessor(self):
  637. self.RAWDataProc = mrsurvey.GMRDataProcessor()
  638. self.RAWDataProc.progressTrigger.connect(self.updateProgressBar)
  639. self.RAWDataProc.enableDSPTrigger.connect(self.enableDSP)
  640. self.RAWDataProc.doneTrigger.connect(self.doneStatus)
  641. self.RAWDataProc.updateProcTrigger.connect(self.updateProc)
  642. def openGMRRAWDataset(self):
  643. """ Opens a GMR header file
  644. """
  645. try:
  646. with open('.gmr.last.path') as f:
  647. fpath = f.readline()
  648. pass
  649. except IOError as e:
  650. fpath = '.'
  651. self.headerstr = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', fpath)[0] # arg2 = File Type 'All Files (*)'
  652. self.ui.headerFileTextBrowser.clear()
  653. self.ui.headerFileTextBrowser.append(self.headerstr)
  654. if len(self.headerstr) == 0:
  655. return
  656. # clear the processing log
  657. self.ui.logTextBrowser.clear()
  658. self.logText = [] #MAK 20170126
  659. path,filen=os.path.split(str(self.headerstr))
  660. f = open('.gmr.last.path', 'w')
  661. f.write( str(self.headerstr) ) # prompt last file
  662. self.connectGMRDataProcessor()
  663. self.RAWDataProc.readHeaderFile(str(self.headerstr))
  664. # If we got this far, enable all the widgets
  665. self.ui.lcdNumberTauPulse1.setEnabled(True)
  666. self.ui.lcdNumberNuTx.setEnabled(True)
  667. self.ui.lcdNumberTuneuF.setEnabled(True)
  668. self.ui.lcdNumberSampFreq.setEnabled(True)
  669. self.ui.lcdNumberNQ.setEnabled(True)
  670. self.ui.headerFileBox.setEnabled(True)
  671. self.ui.headerFileBox.setChecked( True )
  672. self.ui.headerBox2.setVisible(True)
  673. self.ui.inputRAWParametersBox.setEnabled(True)
  674. self.ui.loadDataPushButton.setEnabled(True)
  675. # make plots as you import the dataset
  676. self.ui.plotImportCheckBox.setEnabled(True)
  677. self.ui.plotImportCheckBox.setChecked(True)
  678. # Update info from the header into the GUI
  679. self.ui.pulseTypeTextBrowser.clear()
  680. self.ui.pulseTypeTextBrowser.append(self.RAWDataProc.pulseType)
  681. self.ui.lcdNumberNuTx.display(self.RAWDataProc.transFreq)
  682. self.ui.lcdNumberTauPulse1.display(1e3*self.RAWDataProc.pulseLength[0])
  683. self.ui.lcdNumberTuneuF.display(self.RAWDataProc.TuneCapacitance)
  684. self.ui.lcdNumberSampFreq.display(self.RAWDataProc.samp)
  685. self.ui.lcdNumberNQ.display(self.RAWDataProc.nPulseMoments)
  686. self.ui.DeadTimeSpinBox.setValue(1e3*self.RAWDataProc.deadTime)
  687. self.ui.CentralVSpinBox.setValue( self.RAWDataProc.transFreq )
  688. if self.RAWDataProc.pulseType != "FID":
  689. self.ui.lcdNumberTauPulse2.setEnabled(1)
  690. self.ui.lcdNumberTauPulse2.display(1e3*self.RAWDataProc.pulseLength[1])
  691. self.ui.lcdNumberTauDelay.setEnabled(1)
  692. self.ui.lcdNumberTauDelay.display(1e3*self.RAWDataProc.interpulseDelay)
  693. self.ui.FIDProcComboBox.clear()
  694. if self.RAWDataProc.pulseType == "4PhaseT1" or self.RAWDataProc.pulseType == "T1":
  695. self.ui.FIDProcComboBox.insertItem(0, "Pulse 1")
  696. self.ui.FIDProcComboBox.insertItem(1, "Pulse 2")
  697. self.ui.FIDProcComboBox.insertItem(2, "Both")
  698. self.ui.FIDProcComboBox.setCurrentIndex (1)
  699. elif self.RAWDataProc.pulseType == "FID":
  700. self.ui.FIDProcComboBox.insertItem(0, "Pulse 1")
  701. self.ui.FIDProcComboBox.setCurrentIndex (0)
  702. def ExportPreprocess(self):
  703. """ This method exports to YAML
  704. """
  705. try:
  706. with open('.akvo.last.yaml.path') as f:
  707. fpath = f.readline()
  708. pass
  709. except IOError as e:
  710. fpath = '.'
  711. fdir = os.path.dirname(fpath)
  712. # Pickle the preprocessed data dictionary
  713. SaveStr = QtWidgets.QFileDialog.getSaveFileName(self, "Save as", fdir, r"Processed data (*.yaml)")[0]
  714. spath,filen=os.path.split(str(SaveStr))
  715. f = open('.akvo.last.yaml.path', 'w')
  716. f.write( str(spath) ) # prompt last file
  717. INFO = {}
  718. INFO["headerstr"] = str(self.headerstr)
  719. INFO["pulseType"] = self.RAWDataProc.pulseType
  720. INFO["transFreq"] = self.RAWDataProc.transFreq.tolist()
  721. INFO["pulseLength"] = self.RAWDataProc.pulseLength.tolist()
  722. INFO["TuneCapacitance"] = self.RAWDataProc.TuneCapacitance.tolist()
  723. #INFO["samp"] = self.RAWDataProc.samp
  724. INFO["nPulseMoments"] = self.RAWDataProc.nPulseMoments
  725. #INFO["deadTime"] = self.RAWDataProc.deadTime
  726. INFO["processed"] = "Akvo v" + VERSION + ", on " + time.strftime("%d/%m/%Y")
  727. # Pulse current info
  728. ip = 0
  729. INFO["Pulses"] = {}
  730. for pulse in self.RAWDataProc.DATADICT["PULSES"]:
  731. qq = []
  732. qv = []
  733. for ipm in range(self.RAWDataProc.DATADICT["nPulseMoments"]):
  734. #for istack in self.RAWDataProc.DATADICT["stacks"]:
  735. # print ("stack q", self.RAWDataProc.DATADICT[pulse]["Q"][ipm,istack-1])
  736. qq.append(np.mean( self.RAWDataProc.DATADICT[pulse]["Q"][ipm,:]) )
  737. qv.append(np.std( self.RAWDataProc.DATADICT[pulse]["Q"][ipm,:]/self.RAWDataProc.pulseLength[ip] ))
  738. qq = np.array(qq)
  739. qv = np.array(qv)
  740. iQ = np.argsort(np.array(qq))
  741. qq = np.array(qq)[iQ]
  742. qv = np.array(qv)[iQ]
  743. INFO["Pulses"][pulse] = {}
  744. INFO["Pulses"][pulse]["units"] = "A"
  745. INFO["Pulses"][pulse]["current"] = VectorXr(qq/self.RAWDataProc.pulseLength[ip])
  746. INFO["Pulses"][pulse]["variance"] = VectorXr(qv)
  747. ip += 1
  748. # Data
  749. if self.RAWDataProc.gated == True:
  750. INFO["Gated"] = {}
  751. INFO["Gated"]["abscissa units"] = "ms"
  752. INFO["Gated"]["data units"] = "nT"
  753. for pulse in self.RAWDataProc.DATADICT["PULSES"]:
  754. INFO["Gated"][pulse] = {}
  755. INFO["Gated"][pulse]["abscissa"] = VectorXr( self.RAWDataProc.GATEDABSCISSA )
  756. INFO["Gated"][pulse]["windows"] = VectorXr( self.RAWDataProc.GATEDWINDOW )
  757. for ichan in self.RAWDataProc.DATADICT[pulse]["chan"]:
  758. INFO["Gated"][pulse]["Chan. " + str(ichan)] = {}
  759. #INFO["Gated"][pulse]["Chan. " + str(ichan)]["STD"] = VectorXr( np.std(self.RAWDataProc.GATED[ichan]["NR"], axis=0) )
  760. INFO["Gated"][pulse]["Chan. " + str(ichan)]["STD"] = VectorXr( np.average(self.RAWDataProc.GATED[ichan]["BN"], axis=0) )
  761. for ipm in range(self.RAWDataProc.DATADICT["nPulseMoments"]):
  762. INFO["Gated"][pulse]["Chan. " + str(ichan)]["Q-"+str(ipm) + " CA"] = VectorXr(self.RAWDataProc.GATED[ichan]["CA"][ipm])
  763. INFO["Gated"][pulse]["Chan. " + str(ichan)]["Q-"+str(ipm) + " RE"] = VectorXr(self.RAWDataProc.GATED[ichan]["RE"][ipm])
  764. INFO["Gated"][pulse]["Chan. " + str(ichan)]["Q-"+str(ipm) + " IM"] = VectorXr(self.RAWDataProc.GATED[ichan]["IM"][ipm])
  765. #INFO["Gated"][pulse]["Chan. " + str(ichan)]["Q-"+str(ipm) + " IP"] = VectorXr(self.RAWDataProc.GATED[ichan]["IP"][ipm])
  766. #INFO["Gated"][pulse]["Chan. " + str(ichan)]["Q-"+str(ipm) + " NR"] = VectorXr(self.RAWDataProc.GATED[ichan]["NR"][ipm])
  767. #INFO["Gated"][pulse]["Chan. " + str(ichan)]["Q-"+str(ipm) + " STD" ] = VectorXr(self.RAWDataProc.GATED[ichan]["SIGMA"][ipm])
  768. # we have gated data
  769. # Window edges
  770. # Window centres
  771. with open(SaveStr, 'w') as outfile:
  772. #for line in self.logText:
  773. # outfile.write(line+"\n")
  774. yaml.dump(self.YamlNode, outfile)
  775. yaml.dump(INFO, outfile) #, default_flow_style=False)
  776. def SavePreprocess(self):
  777. #if "Saved" not in self.YamlNode.Processing.keys():
  778. # self.YamlNode.Processing["Saved"] = []
  779. #self.YamlNode.Processing["Saved"].append(datetime.datetime.now().isoformat())
  780. #self.Log()
  781. import pickle, os
  782. try:
  783. with open('.akvo.last.path') as f:
  784. fpath = f.readline()
  785. pass
  786. except IOError as e:
  787. fpath = '.'
  788. fdir = os.path.dirname(fpath)
  789. # Pickle the preprocessed data dictionary
  790. SaveStr = QtWidgets.QFileDialog.getSaveFileName(self, "Save as", fdir, r"Pickle (*.dmp)")
  791. spath,filen=os.path.split(str(SaveStr[0]))
  792. f = open('.akvo.last.path', 'w')
  793. f.write( str(spath) ) # prompt last file
  794. save = open(SaveStr[0], 'wb')
  795. # Add some extra info
  796. INFO = {}
  797. INFO["pulseType"] = self.RAWDataProc.pulseType
  798. INFO["prePulseDelay"] = self.RAWDataProc.prePulseDelay
  799. INFO["interpulseDelay"] = self.RAWDataProc.interpulseDelay
  800. INFO["transFreq"] = self.RAWDataProc.transFreq
  801. INFO["pulseLength"] = self.RAWDataProc.pulseLength
  802. INFO["TuneCapacitance"] = self.RAWDataProc.TuneCapacitance
  803. INFO["samp"] = self.RAWDataProc.samp
  804. INFO["nPulseMoments"] = self.RAWDataProc.nPulseMoments
  805. INFO["deadTime"] = self.RAWDataProc.deadTime
  806. INFO["transFreq"] = self.RAWDataProc.transFreq
  807. INFO["headerstr"] = str(self.headerstr)
  808. INFO["nDAQVersion"] = self.RAWDataProc.nDAQVersion
  809. INFO["log"] = yaml.dump( self.YamlNode )
  810. TXRX = []
  811. for ir in range(0, self.ui.txRxTable.rowCount() ):
  812. txrx = []
  813. for ic in range(0, self.ui.txRxTable.columnCount() ):
  814. txrx.append( self.ui.txRxTable.item(ir, ic).text() )
  815. TXRX.append(txrx)
  816. INFO["TXRX"] = TXRX
  817. #
  818. print("META SAVE")
  819. print("INFO log", INFO["log"])
  820. self.RAWDataProc.DATADICT["INFO"] = INFO
  821. pickle.dump(self.RAWDataProc.DATADICT, save)
  822. save.close()
  823. # Export XML file suitable for USGS ScienceBase Data Release
  824. def ExportXML(self):
  825. """ This is a filler function for use by USGS collaborators
  826. """
  827. return 42
  828. def OpenPreprocess(self):
  829. import pickle
  830. try:
  831. with open('.akvo.last.path') as f:
  832. fpath = f.readline()
  833. pass
  834. except IOError as e:
  835. fpath = '.'
  836. #filename = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', '.')
  837. fpath = QtWidgets.QFileDialog.getOpenFileName(self, 'Open preprocessed file', fpath, r"Pickle Files (*.dmp)")[0]
  838. f = open('.akvo.last.path', 'w')
  839. f.write( str(fpath) ) # prompt last file
  840. self.ui.logTextBrowser.clear()
  841. self.logText = []
  842. if len(fpath) == 0:
  843. return
  844. pfile = open(fpath,'rb')
  845. unpickle = pickle.Unpickler(pfile)
  846. self.connectGMRDataProcessor()
  847. self.RAWDataProc.DATADICT = unpickle.load()
  848. # This line causes Akvo to crash, if the header file is no longer there. We don't need to load the
  849. # file. TODO, need to disable "Load Data" in Load command though, as that is no longer possible.
  850. #self.RAWDataProc.readHeaderFile(self.RAWDataProc.DATADICT["INFO"]["headerstr"])
  851. self.headerstr = self.RAWDataProc.DATADICT["INFO"]["headerstr"]
  852. self.RAWDataProc.pulseType = self.RAWDataProc.DATADICT["INFO"]["pulseType"]
  853. self.RAWDataProc.transFreq = self.RAWDataProc.DATADICT["INFO"]["transFreq"]
  854. self.RAWDataProc.pulseLength = self.RAWDataProc.DATADICT["INFO"]["pulseLength"]
  855. self.RAWDataProc.TuneCapacitance = self.RAWDataProc.DATADICT["INFO"]["TuneCapacitance"]
  856. self.RAWDataProc.samp = self.RAWDataProc.DATADICT["INFO"]["samp"]
  857. self.RAWDataProc.nPulseMoments = self.RAWDataProc.DATADICT["INFO"]["nPulseMoments"]
  858. self.RAWDataProc.deadTime = self.RAWDataProc.DATADICT["INFO"]["deadTime"]
  859. self.RAWDataProc.transFreq = self.RAWDataProc.DATADICT["INFO"]["transFreq"]
  860. self.RAWDataProc.nDAQVersion = self.RAWDataProc.DATADICT["INFO"]["nDAQVersion"]
  861. #self.RAWDataProc.prePulseDelay = self.RAWDataProc.DATADICT["INFO"]["prePulseDelay"]
  862. self.RAWDataProc.dt = 1./self.RAWDataProc.samp
  863. self.dataChan = self.RAWDataProc.DATADICT[ self.RAWDataProc.DATADICT["PULSES"][0] ]["chan"]
  864. # Keep backwards compatibility with prior saved pickles???
  865. #self.ui.logTextBrowser.clear()
  866. #self.ui.logTextBrowser.append( yaml.dump(self.YamlNode)) #, default_flow_style=False) )
  867. #for a in self.logText:
  868. # self.ui.logTextBrowser.append(str(a))
  869. #self.ui.logTextBrowser
  870. #self.ui.logTextBrowser.clear()
  871. #print ( self.RAWDataProc.DATADICT["INFO"]["log"] )
  872. if "TXRX" in self.RAWDataProc.DATADICT["INFO"].keys():
  873. TXRX = self.RAWDataProc.DATADICT["INFO"]["TXRX"]
  874. self.ui.txRxTable.setRowCount( len(TXRX))
  875. for irow, row in enumerate(TXRX):
  876. for icol, val in enumerate(row):
  877. pCell = QtWidgets.QTableWidgetItem()
  878. pCell.setText( val )
  879. pCell.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled )
  880. self.ui.txRxTable.setItem(irow, icol, pCell)
  881. self.logText = self.RAWDataProc.DATADICT["INFO"]["log"] # YAML
  882. parse = yaml.load( self.logText, Loader=yaml.Loader )
  883. self.YamlNode = AkvoYamlNode( ) #self.logText )
  884. self.YamlNode.Akvo_VERSION = (yaml.load( self.logText, Loader=yaml.Loader )).Akvo_VERSION
  885. AKVO_VERSION = np.array(self.YamlNode.Akvo_VERSION.split("."), dtype=int)
  886. if AKVO_VERSION[0] >= 1 and AKVO_VERSION[1] >= 2 and AKVO_VERSION[2] >= 3:
  887. self.RAWDataProc.interpulseDelay = self.RAWDataProc.DATADICT["INFO"]["interpulseDelay"]
  888. self.YamlNode.Import = OrderedDict(parse.Import)
  889. self.YamlNode.Processing = list(parse.Processing)
  890. self.YamlNode.Stacking = OrderedDict(parse.Stacking)
  891. self.YamlNode.META = OrderedDict(parse.META)
  892. self.logGUI()
  893. self.Log()
  894. #self.ui.logTextBrowser.append( yaml.dump(self.YamlNode)) #, default_flow_style=False) )
  895. #except KeyError:
  896. # pass
  897. # Remove "Saved" and "Loaded" from processing flow
  898. #if "Loaded" not in self.YamlNode.Processing.keys():
  899. # self.YamlNode.Processing["Loaded"] = []
  900. #self.YamlNode.Processing["Loaded"].append(datetime.datetime.now().isoformat())
  901. #self.Log()
  902. # If we got this far, enable all the widgets
  903. self.ui.lcdNumberTauPulse1.setEnabled(True)
  904. self.ui.lcdNumberNuTx.setEnabled(True)
  905. self.ui.lcdNumberTuneuF.setEnabled(True)
  906. self.ui.lcdNumberSampFreq.setEnabled(True)
  907. self.ui.lcdNumberNQ.setEnabled(True)
  908. self.ui.headerFileBox.setEnabled(True)
  909. self.ui.headerFileBox.setChecked( True )
  910. self.headerBoxShrink()
  911. #self.ui.headerBox2.setVisible(True)
  912. self.ui.inputRAWParametersBox.setEnabled(False)
  913. self.ui.loadDataPushButton.setEnabled(True)
  914. # make plots as you import the datasetmost
  915. self.ui.plotImportCheckBox.setEnabled(True)
  916. self.ui.plotImportCheckBox.setChecked(True)
  917. # enable the LCDs
  918. self.ui.lcdNumberFID1Length.setEnabled(1)
  919. self.ui.lcdNumberFID2Length.setEnabled(1)
  920. self.ui.lcdNumberResampFreq.setEnabled(1)
  921. self.ui.lcdTotalDeadTime.setEnabled(1)
  922. # enable META tab
  923. self.ui.METATab.setEnabled(1)
  924. self.ui.siteBox.setEnabled(1)
  925. #self.ui.lcdTotalDeadTime.display( 1e3*self.RAWDataProc.DATADICT["INFO"]["deadTime"] )
  926. self.ui.headerFileTextBrowser.clear( )
  927. self.ui.headerFileTextBrowser.append( self.RAWDataProc.DATADICT["INFO"]["headerstr"] )
  928. if u"Pulse 1" in self.RAWDataProc.DATADICT.keys():
  929. self.ui.lcdNumberFID1Length.display(self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][-1]- self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][0])
  930. self.ui.lcdTotalDeadTime.display( round(1e3*(self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][0]-self.RAWDataProc.DATADICT["Pulse 1"]["PULSE_TIMES"][-1]), 3) )
  931. print("CALC DEAD", (1e3*(self.RAWDataProc.prePulseDelay))) # - (self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][0]-self.RAWDataProc.DATADICT["Pulse 1"]["PULSE_TIMES"][-1])), 3) )
  932. if u"Pulse 2" in self.RAWDataProc.DATADICT.keys():
  933. self.ui.lcdNumberFID1Length.display(self.RAWDataProc.DATADICT["Pulse 2"]["TIMES"][-1]- self.RAWDataProc.DATADICT["Pulse 2"]["TIMES"][0])
  934. self.ui.lcdTotalDeadTime.display( 1e3 * (self.RAWDataProc.DATADICT["Pulse 2"]["TIMES"][0]-self.RAWDataProc.DATADICT["Pulse 2"]["PULSE_TIMES"][-1]) )
  935. # Update info from the header into the GUI
  936. self.ui.pulseTypeTextBrowser.clear()
  937. self.ui.pulseTypeTextBrowser.append(self.RAWDataProc.pulseType)
  938. self.ui.lcdNumberNuTx.display(self.RAWDataProc.transFreq)
  939. self.ui.lcdNumberTauPulse1.display(1e3*self.RAWDataProc.pulseLength[0])
  940. self.ui.lcdNumberTuneuF.display(self.RAWDataProc.TuneCapacitance)
  941. self.ui.lcdNumberResampFreq.display(self.RAWDataProc.samp)
  942. self.ui.lcdNumberSampFreq.display(50000) # TODO, if non GMR is supported, query
  943. self.ui.lcdNumberNQ.display(self.RAWDataProc.nPulseMoments)
  944. self.ui.DeadTimeSpinBox.setValue(1e3*self.RAWDataProc.deadTime)
  945. self.ui.CentralVSpinBox.setValue( self.RAWDataProc.transFreq )
  946. if self.RAWDataProc.pulseType != "FID":
  947. self.ui.lcdNumberTauPulse2.setEnabled(1)
  948. self.ui.lcdNumberTauPulse2.display(1e3*self.RAWDataProc.pulseLength[1])
  949. self.ui.lcdNumberTauDelay.setEnabled(1)
  950. self.ui.lcdNumberTauDelay.display(1e3*self.RAWDataProc.interpulseDelay)
  951. self.ui.FIDProcComboBox.clear()
  952. if self.RAWDataProc.pulseType == "4PhaseT1" or self.RAWDataProc.pulseType == "T1":
  953. self.ui.FIDProcComboBox.insertItem(0, "Pulse 1") #, const QVariant & userData = QVariant() )
  954. self.ui.FIDProcComboBox.insertItem(1, "Pulse 2") #, const QVariant & userData = QVariant() )
  955. self.ui.FIDProcComboBox.insertItem(2, "Both") #, const QVariant & userData = QVariant() )
  956. if len( self.RAWDataProc.DATADICT["PULSES"]) == 2:
  957. self.ui.FIDProcComboBox.setCurrentIndex (2)
  958. elif self.RAWDataProc.DATADICT["PULSES"][0] == "Pulse 1":
  959. self.ui.FIDProcComboBox.setCurrentIndex (0)
  960. else:
  961. self.ui.FIDProcComboBox.setCurrentIndex (1)
  962. elif self.RAWDataProc.pulseType == "FID":
  963. self.ui.FIDProcComboBox.insertItem(0, "Pulse 1") #, const QVariant & userData = QVariant() )
  964. self.ui.FIDProcComboBox.setCurrentIndex (0)
  965. # QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("updateProgress(int)"), self.updateProgressBar)
  966. # QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("enableDSP()"), self.enableDSP)
  967. # QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("doneStatus()"), self.doneStatus)
  968. self.RAWDataProc.progressTrigger.connect(self.updateProgressBar)
  969. self.RAWDataProc.enableDSPTrigger.connect(self.enableDSP)
  970. self.RAWDataProc.doneTrigger.connect(self.doneStatus)
  971. self.enableAll()
  972. def loadRAW(self):
  973. #################################################
  974. # Check to make sure we are ready to process
  975. # Header
  976. if self.RAWDataProc == None:
  977. err_msg = "You need to load a header first."
  978. reply = QtGui.QMessageBox.critical(self, 'Error',
  979. err_msg) #, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
  980. return
  981. # Stacks
  982. try:
  983. self.procStacks = np.array(eval(str("np.r_["+self.ui.stacksLineEdit.text())+"]"))
  984. except:
  985. err_msg = "You need to set your stacks correctly.\n" + \
  986. "This should be a Python Numpy interpretable list\n" + \
  987. "of stack indices. For example 1:24 or 1:4,8:24"
  988. QtGui.QMessageBox.critical(self, 'Error', err_msg)
  989. return
  990. # Data Channels
  991. #Chan = np.arange(0,9,1)
  992. try:
  993. self.dataChan = np.array(eval(str("np.r_["+self.ui.dataChanLineEdit.text())+"]"))
  994. except:
  995. #QMessageBox messageBox;
  996. #messageBox.critical(0,"Error","An error has occured !");
  997. #messageBox.setFixedSize(500,200);
  998. #quit_msg = "Are you sure you want to exit the program?"
  999. #reply = QtGui.QMessageBox.question(self, 'Message',
  1000. # quit_msg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
  1001. err_msg = "You need to set your data channels correctly.\n" + \
  1002. "This should be a Python Numpy interpretable list\n" + \
  1003. "of indices. For example 1 or 1:3 or 1:3 5\n\n" + \
  1004. "valid GMR data channels fall between 1 and 8. Note that\n" +\
  1005. "1:3 is not inclusive of 3 and is the same as 1,2 "
  1006. reply = QtGui.QMessageBox.critical(self, 'Error',
  1007. err_msg) #, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
  1008. return
  1009. #############################
  1010. # Reference Channels
  1011. # TODO make sure no overlap between data and ref channels
  1012. self.refChan = np.array( () )
  1013. if str(self.ui.refChanLineEdit.text()): # != "none":
  1014. try:
  1015. self.refChan = np.array(eval(str("np.r_["+self.ui.refChanLineEdit.text())+"]"))
  1016. except:
  1017. err_msg = "You need to set your reference channels correctly.\n" + \
  1018. "This should be a Python Numpy interpretable list\n" + \
  1019. "of indices. For example 1 or 1:3 or 1:3 5\n\n" + \
  1020. "valid GMR data channels fall between 1 and 8. Note that\n" +\
  1021. "1:3 is not inclusive of 3 and is the same as 1,2 "
  1022. QtGui.QMessageBox.critical(self, 'Error', err_msg)
  1023. return
  1024. #####################################################
  1025. # Load data
  1026. self.lock("loading RAW GMR dataset")
  1027. if self.RAWDataProc.pulseType == "FID":
  1028. self.procThread = thread.start_new_thread(self.RAWDataProc.loadFIDData, \
  1029. (str(self.headerstr), self.procStacks, self.dataChan, self.refChan, \
  1030. str(self.ui.FIDProcComboBox.currentText()), self.ui.mplwidget, \
  1031. 1e-3 * self.ui.DeadTimeSpinBox.value( ), self.ui.plotImportCheckBox.isChecked() )) #, self))
  1032. elif self.RAWDataProc.pulseType == "4PhaseT1":
  1033. self.procThread = thread.start_new_thread(self.RAWDataProc.load4PhaseT1Data, \
  1034. (str(self.headerstr), self.procStacks, self.dataChan, self.refChan, \
  1035. str(self.ui.FIDProcComboBox.currentText()), self.ui.mplwidget, \
  1036. 1e-3 * self.ui.DeadTimeSpinBox.value( ), self.ui.plotImportCheckBox.isChecked() )) #, self))
  1037. elif self.RAWDataProc.pulseType == "T1":
  1038. self.procThread = thread.start_new_thread(self.RAWDataProc.loadT1Data, \
  1039. (str(self.headerstr), self.procStacks, self.dataChan, self.refChan, \
  1040. str(self.ui.FIDProcComboBox.currentText()), self.ui.mplwidget, \
  1041. 1e-3 * self.ui.DeadTimeSpinBox.value( ), self.ui.plotImportCheckBox.isChecked() )) #, self))
  1042. #self.procThread = thread.start_new_thread(self.RAWDataProc.load4PhaseT1Data, \
  1043. # (str(self.headerstr), self.procStacks, self.dataChan, self.refChan, \
  1044. # str(self.ui.FIDProcComboBox.currentText()), self.ui.mplwidget, \
  1045. # 1e-3 * self.ui.DeadTimeSpinBox.value( ), self.ui.plotImportCheckBox.isChecked() )) #, self))
  1046. self.YamlNode.Import["GMR Header"] = self.headerstr
  1047. self.YamlNode.Import["opened"] = datetime.datetime.now().isoformat()
  1048. self.YamlNode.Import["pulse Type"] = str(self.RAWDataProc.pulseType)
  1049. self.YamlNode.Import["stacks"] = self.procStacks.tolist()
  1050. self.YamlNode.Import["data channels"] = self.dataChan.tolist()
  1051. self.YamlNode.Import["reference channels"] = self.refChan.tolist()
  1052. self.YamlNode.Import["pulse records"] = str(self.ui.FIDProcComboBox.currentText())
  1053. self.YamlNode.Import["instrument dead time"] = (1e-3 * self.ui.DeadTimeSpinBox.value( ))
  1054. self.Log ( )
  1055. # enable META tab
  1056. self.ui.METATab.setEnabled(1)
  1057. self.ui.siteBox.setEnabled(1)
  1058. # should be already done
  1059. # QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("updateProgress(int)"), self.updateProgressBar)
  1060. # QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("enableDSP()"), self.enableDSP)
  1061. # QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("doneStatus()"), self.doneStatus)
  1062. #self.ui.ProcessedBox.setEnabled(True)
  1063. self.ui.lcdNumberFID1Length.setEnabled(1)
  1064. self.ui.lcdNumberFID2Length.setEnabled(1)
  1065. self.ui.lcdNumberResampFreq.setEnabled(1)
  1066. self.ui.lcdTotalDeadTime.setEnabled(1)
  1067. self.ui.lcdTotalDeadTime.display( self.ui.DeadTimeSpinBox.value( ) )
  1068. #self.ui.lcdTotalDeadTime.display( round(1e3*(self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][0]-self.RAWDataProc.DATADICT["Pulse 1"]["PULSE_TIMES"][-1]), 3) )
  1069. #self.ui.lcdNumberFID1Length.display(0)
  1070. #self.ui.lcdNumberFID2Length.display(0)
  1071. #self.ui.lcdNumberResampFreq.display( self.RAWDataProc.samp )
  1072. self.mpl_toolbar = NavigationToolbar2QT(self.ui.mplwidget, self.ui.mplwidget)
  1073. self.ui.mplwidget.draw()
  1074. def Log(self):
  1075. #for line in yaml.dump(self.YamlNode, default_flow_style=False):
  1076. #for line in nlogText:
  1077. # self.ui.logTextBrowser.append( line )
  1078. # self.logText.append( line )
  1079. self.ui.logTextBrowser.clear()
  1080. self.ui.logTextBrowser.append( yaml.dump(self.YamlNode ))
  1081. def disable(self):
  1082. self.ui.inputRAWParametersBox.setEnabled(False)
  1083. self.ui.BandPassBox.setEnabled(False)
  1084. self.ui.downSampleGroupBox.setEnabled(False)
  1085. self.ui.windowFilterGroupBox.setEnabled(False)
  1086. self.ui.harmonicBox.setEnabled(False)
  1087. # self.ui.despikeGroupBox.setEnabled(False)
  1088. self.ui.adaptBox.setEnabled(False)
  1089. self.ui.adaptFDBox.setEnabled(False)
  1090. self.ui.qCalcGroupBox.setEnabled(False)
  1091. self.ui.FDSmartStackGroupBox.setEnabled(False)
  1092. self.ui.sumDataBox.setEnabled(False)
  1093. self.ui.qdGroupBox.setEnabled(False)
  1094. self.ui.gateBox.setEnabled(False)
  1095. def enableAll(self):
  1096. self.enableDSP()
  1097. self.enableQC()
  1098. def enableDSP(self):
  1099. # Bandpass filter
  1100. self.ui.BandPassBox.setEnabled(True)
  1101. self.ui.BandPassBox.setChecked(True)
  1102. self.ui.bandPassGO.setEnabled(False) # need to design first
  1103. self.ui.plotBP.setEnabled(True)
  1104. self.ui.plotBP.setChecked(True)
  1105. # downsample
  1106. self.ui.downSampleGroupBox.setEnabled(True)
  1107. self.ui.downSampleGroupBox.setChecked(True)
  1108. # window
  1109. self.ui.windowFilterGroupBox.setEnabled(True)
  1110. self.ui.windowFilterGroupBox.setChecked(True)
  1111. # Despike
  1112. # self.ui.despikeGroupBox.setEnabled(True)
  1113. # self.ui.despikeGroupBox.setChecked(False)
  1114. # Adaptive filtering
  1115. self.ui.adaptBox.setEnabled(True)
  1116. self.ui.adaptBox.setChecked(True)
  1117. # FD Adaptive filtering
  1118. self.ui.adaptFDBox.setEnabled(True)
  1119. self.ui.adaptFDBox.setChecked(False)
  1120. # Harmonic
  1121. self.ui.harmonicBox.setEnabled(True)
  1122. self.ui.harmonicBox.setChecked(True)
  1123. self.LCDHarmonics()
  1124. self.LCDHarmonics2()
  1125. # sum group box
  1126. try:
  1127. if len(self.dataChan) > 1:
  1128. self.ui.sumDataBox.setEnabled(True)
  1129. self.ui.sumDataBox.setChecked(False)
  1130. except:
  1131. pass
  1132. # Quadrature Detect
  1133. self.ui.qdGroupBox.setEnabled(True)
  1134. self.ui.qdGroupBox.setChecked(True)
  1135. self.enableQC()
  1136. def enableQC(self):
  1137. # Q calc
  1138. self.ui.qCalcGroupBox.setEnabled(True)
  1139. self.ui.qCalcGroupBox.setChecked(True)
  1140. # FD SmartStack
  1141. self.ui.FDSmartStackGroupBox.setEnabled(True)
  1142. self.ui.FDSmartStackGroupBox.setChecked(True)
  1143. # Quadrature detect
  1144. try:
  1145. for pulse in self.RAWDataProc.DATADICT["PULSES"]:
  1146. np.shape(self.RAWDataProc.DATADICT[pulse]["Q"])
  1147. self.RAWDataProc.DATADICT["stack"]
  1148. self.ui.qdGroupBox.setEnabled(True)
  1149. self.ui.qdGroupBox.setChecked(True)
  1150. except:
  1151. self.ui.qdGroupBox.setEnabled(False)
  1152. self.ui.qdGroupBox.setChecked(False)
  1153. # Gating
  1154. try:
  1155. self.RAWDataProc.DATADICT["CA"]
  1156. self.ui.gateBox.setEnabled(True)
  1157. self.ui.gateBox.setChecked(True)
  1158. except:
  1159. self.ui.gateBox.setEnabled(False)
  1160. self.ui.gateBox.setChecked(False)
  1161. def despikeFilter(self):
  1162. self.lock("despike filter")
  1163. thread.start_new_thread(self.RAWDataProc.despike, \
  1164. (self.ui.windowSpinBox.value(), \
  1165. self.ui.thresholdSpinBox.value(), \
  1166. str(self.ui.replComboBox.currentText()), \
  1167. self.ui.rollOnSpinBox.value(), \
  1168. self.ui.despikeInterpWinSpinBox.value(),
  1169. self.ui.mplwidget))
  1170. def calcQ(self):
  1171. if "Calc Q" not in self.YamlNode.Stacking.keys():
  1172. #print("In CalcQ", yaml.dump(self.YamlNode.Processing) )
  1173. self.YamlNode.Stacking["Calc Q"] = True
  1174. #print( yaml.dump(self.YamlNode.Processing) )
  1175. self.Log()
  1176. else:
  1177. err_msg = "Q values have already been calculated"
  1178. reply =QtWidgets.QMessageBox.critical(self, 'Error',
  1179. err_msg)
  1180. return
  1181. self.lock("pulse moment calculation")
  1182. thread.start_new_thread(self.RAWDataProc.effectivePulseMoment, \
  1183. (self.ui.CentralVSpinBox.value(), \
  1184. self.ui.mplwidget))
  1185. def harmonicModel(self):
  1186. self.lock("harmonic noise modelling")
  1187. Harm = OrderedDict()
  1188. Harm["STEP " + str(len(self.YamlNode.Processing))] = "Harmonic modelling"
  1189. Harm["NF"] = str( self.ui.NHarmonicsFreqsSpin.value() )
  1190. Harm["Segments"] = str( self.ui.NSegments.value() )
  1191. Harm["Proc. ref."] = self.ui.harmRef.isChecked()
  1192. if self.ui.searchAll.currentText() == "All":
  1193. Harm["search"] = self.ui.searchAll.currentText()
  1194. Search = False
  1195. else:
  1196. #Harm["search"] = self.ui.searchAll.currentText()
  1197. Harm["search"] = str(self.ui.Nsearch.value())
  1198. Search = self.ui.Nsearch.value()
  1199. if self.ui.boundsCheck.isChecked():
  1200. Harm["Bounds"] = str(self.ui.bounds.value())
  1201. Bounds = self.ui.bounds.value()
  1202. else:
  1203. Harm["Bounds"] = self.ui.boundsCheck.isChecked()
  1204. Bounds = 0
  1205. Harm["f0K1"] = str( self.ui.f0K1Spin.value() )
  1206. Harm["f0KN"] = str( self.ui.f0KNSpin.value() )
  1207. Harm["f0Ks"] = str( self.ui.f0KsSpin.value() )
  1208. Harm["f0"] = str( self.ui.f0Spin.value() )
  1209. if self.ui.NHarmonicsFreqsSpin.value() > 1:
  1210. Harm["f1K1"] = str( self.ui.f1K1Spin.value() )
  1211. Harm["f1KN"] = str( self.ui.f1KNSpin.value() )
  1212. Harm["f1Ks"] = str( self.ui.f1KsSpin.value() )
  1213. Harm["f1"] = str( self.ui.f1Spin.value() )
  1214. self.YamlNode.Processing.append(Harm)
  1215. self.Log()
  1216. thread.start_new_thread(self.RAWDataProc.harmonicModel, \
  1217. ( \
  1218. self.ui.NHarmonicsFreqsSpin.value(), \
  1219. self.ui.f0Spin.value(), \
  1220. self.ui.f0K1Spin.value(), \
  1221. self.ui.f0KNSpin.value(), \
  1222. self.ui.f0KsSpin.value(), \
  1223. self.ui.NSegments.value(), \
  1224. self.ui.f1Spin.value(), \
  1225. self.ui.f1K1Spin.value(), \
  1226. self.ui.f1KNSpin.value(), \
  1227. self.ui.f1KsSpin.value(), \
  1228. Search, \
  1229. Bounds, \
  1230. self.ui.harmRef.isChecked(), \
  1231. self.ui.plotHarmonic.isChecked(), \
  1232. self.ui.mplwidget \
  1233. ) \
  1234. )
  1235. def FDSmartStack(self):
  1236. if "TD stack" not in self.YamlNode.Stacking.keys():
  1237. self.YamlNode.Stacking["TD stack"] = {}
  1238. self.YamlNode.Stacking["TD stack"]["outlier"] = str( self.ui.outlierTestCB.currentText() )
  1239. self.YamlNode.Stacking["TD stack"]["cutoff"] = str( self.ui.MADCutoff.value() )
  1240. self.Log()
  1241. else:
  1242. err_msg = "TD noise cancellation has already been applied!"
  1243. reply =QtWidgets.QMessageBox.critical(self, 'Error',
  1244. err_msg)
  1245. return
  1246. self.lock("time-domain smart stack")
  1247. thread.start_new_thread(self.RAWDataProc.TDSmartStack, \
  1248. (str(self.ui.outlierTestCB.currentText()), \
  1249. self.ui.MADCutoff.value(),
  1250. self.ui.mplwidget))
  1251. def adaptFilter(self):
  1252. self.lock("TD noise cancellation filter")
  1253. # Log processing
  1254. Adapt = OrderedDict()
  1255. Adapt["STEP " + str(len(self.YamlNode.Processing)) ] = "TD noise cancellation"
  1256. #print(Adapt) # this locks STEP in as first...
  1257. Adapt["n_Taps"] = self.ui.MTapsSpinBox.value()
  1258. Adapt["lambda"] = self.ui.adaptLambdaSpinBox.value()
  1259. Adapt["truncate"] = self.ui.adaptTruncateSpinBox.value()
  1260. Adapt["mu"] = self.ui.adaptMuSpinBox.value()
  1261. Adapt["PCA"] = self.ui.PCAComboBox.currentText()
  1262. #Adapt # this locsk in the dict ordering...
  1263. #print(Adapt) # this locks in the dict...
  1264. self.YamlNode.Processing.append(Adapt)
  1265. self.Log( )
  1266. thread.start_new_thread(self.RAWDataProc.adaptiveFilter, \
  1267. (self.ui.MTapsSpinBox.value(), \
  1268. self.ui.adaptLambdaSpinBox.value(), \
  1269. self.ui.adaptTruncateSpinBox.value(), \
  1270. self.ui.adaptMuSpinBox.value(), \
  1271. str(self.ui.PCAComboBox.currentText()), \
  1272. self.ui.mplwidget))
  1273. def sumDataChans(self):
  1274. self.lock("Summing data channels")
  1275. Sum = OrderedDict()
  1276. Sum["STEP " + str(len(self.YamlNode.Processing))] = "Channel sum"
  1277. self.YamlNode.Processing.append(Sum)
  1278. self.Log( )
  1279. self.dataChan = [self.dataChan[0]]
  1280. self.ui.sumDataBox.setEnabled(False)
  1281. thread.start_new_thread( self.RAWDataProc.sumData, ( self.ui.mplwidget, 7 ) )
  1282. def adaptFilterFD(self):
  1283. self.lock("FD noise cancellation filter")
  1284. thread.start_new_thread(self.RAWDataProc.adaptiveFilterFD, \
  1285. (str(self.ui.windowTypeComboBox.currentText()), \
  1286. self.ui.windowBandwidthSpinBox.value(), \
  1287. self.ui.CentralVSpinBox.value(), \
  1288. self.ui.mplwidget))
  1289. def logGUI(self):
  1290. # You have a race condiditon where the GUI is modifying the Yaml node while you are updating it
  1291. # hence, we need to cache these. More elegant solutions exist
  1292. if "B_0" in self.YamlNode.META:
  1293. B0 = self.YamlNode.META["B_0"]["intensity"]
  1294. Bdec = self.YamlNode.META["B_0"]["dec"]
  1295. Binc = self.YamlNode.META["B_0"]["inc"]
  1296. if "DateTime" in self.YamlNode.META:
  1297. [Date,Time] = self.YamlNode.META["DateTime"].split("T")
  1298. year,month,day = Date.split("-")
  1299. if "Temp" in self.YamlNode.META:
  1300. temp = float(self.YamlNode.META["Temp"])
  1301. if "Coordinates" in self.YamlNode.META:
  1302. UTM = self.YamlNode.META["Coordinates"]["UTM"]
  1303. LatBand = self.YamlNode.META["Coordinates"]["LatBand"]
  1304. Ellipsoid = self.YamlNode.META["Coordinates"]["ellipsoid"]
  1305. # and set
  1306. if "Location" in self.YamlNode.META:
  1307. self.ui.locEdit.setText( self.YamlNode.META["Location"] )
  1308. if "Field Notes" in self.YamlNode.META:
  1309. self.ui.txtComments.setText( self.YamlNode.META["Field Notes"] )
  1310. if "B_0" in self.YamlNode.META:
  1311. self.ui.incSpinBox.setValue( Binc )
  1312. self.ui.decSpinBox.setValue( Bdec )
  1313. self.ui.intensitySpinBox.setValue( B0 )
  1314. if "DateTime" in self.YamlNode.META:
  1315. self.ui.dateEdit.setDate( datetime.date(int(year), int(month), int(day)) )
  1316. self.ui.timeEdit.setTime( datetime.time.fromisoformat( Time ) )
  1317. if "Temp" in self.YamlNode.META:
  1318. self.ui.tempSpinBox.setValue(temp)
  1319. if "Coordinates" in self.YamlNode.META:
  1320. self.ui.UTMzone.setCurrentText(UTM)
  1321. self.ui.latBand.setCurrentText(LatBand)
  1322. self.ui.ellipsoid.setCurrentText(Ellipsoid)
  1323. def logSite(self):
  1324. self.YamlNode.META["Location"] = self.ui.locEdit.text()
  1325. self.YamlNode.META["Coordinates"] = OrderedDict()
  1326. self.YamlNode.META["Coordinates"]["UTM"] = self.ui.UTMzone.currentText()
  1327. self.YamlNode.META["Coordinates"]["LatBand"] = self.ui.latBand.currentText()
  1328. self.YamlNode.META["Coordinates"]["ellipsoid"] = self.ui.ellipsoid.currentText()
  1329. self.YamlNode.META["DateTime"] = self.ui.dateEdit.date().toString("yyyy-MM-dd") + "T" + str( self.ui.timeEdit.time().toString("hh:mm") )
  1330. self.YamlNode.META["Temp"] = self.ui.tempSpinBox.value()
  1331. self.YamlNode.META["B_0"] = OrderedDict()
  1332. self.YamlNode.META["B_0"]["inc"] = self.ui.incSpinBox.value()
  1333. self.YamlNode.META["B_0"]["dec"] = self.ui.decSpinBox.value()
  1334. self.YamlNode.META["B_0"]["intensity"] = self.ui.intensitySpinBox.value()
  1335. self.YamlNode.META["Field Notes"] = self.ui.txtComments.toPlainText()
  1336. self.YamlNode.META["Loops"] = OrderedDict()
  1337. for loop in self.loops:
  1338. print(self.loops[loop])
  1339. self.YamlNode.META["Loops"][loop] = loop + ".yml"
  1340. self.Log()
  1341. def bandPassFilter(self):
  1342. self.lock("bandpass filter")
  1343. # Log processing
  1344. Band = OrderedDict()
  1345. Band["STEP " + str(len(self.YamlNode.Processing))] = "Bandpass filter"
  1346. Band["central_nu"] = str(self.ui.CentralVSpinBox.value())
  1347. Band["passband"] = str(self.ui.passBandSpinBox.value())
  1348. Band["stopband"] = str(self.ui.stopBandSpinBox.value())
  1349. Band["gpass"] = str(self.ui.gpassSpinBox.value())
  1350. Band["gstop"] = str(self.ui.gstopSpinBox.value())
  1351. Band["type"] = str(self.ui.fTypeComboBox.currentText())
  1352. self.YamlNode.Processing.append(Band)
  1353. self.Log( )
  1354. nv = self.ui.lcdTotalDeadTime.value( ) + self.ui.lcdNumberFTauDead.value()
  1355. self.ui.lcdTotalDeadTime.display( nv )
  1356. thread.start_new_thread(self.RAWDataProc.bandpassFilter, \
  1357. (self.ui.mplwidget, 0, self.ui.plotBP.isChecked() ))
  1358. def downsample(self):
  1359. self.lock("resampling")
  1360. # Log processing
  1361. Resample = OrderedDict()
  1362. Resample["STEP "+ str(len(self.YamlNode.Processing))] = "Resample"
  1363. Resample["downsample factor"] = str(self.ui.downSampleSpinBox.value())
  1364. Resample["truncate length"] = str(self.ui.truncateSpinBox.value())
  1365. self.YamlNode.Processing.append(Resample)
  1366. self.Log( )
  1367. thread.start_new_thread(self.RAWDataProc.downsample, \
  1368. (self.ui.truncateSpinBox.value(), \
  1369. self.ui.downSampleSpinBox.value(), \
  1370. self.ui.dsPlot.isChecked(), \
  1371. self.ui.mplwidget))
  1372. def quadDet(self):
  1373. method = ['trf','dogbox','lm'][int(self.ui.QDMethod.currentIndex())]
  1374. loss = ['linear','soft_l1','cauchy','huber'][int(self.ui.QDLoss.currentIndex())]
  1375. # allow overwrite of Quad Det.
  1376. self.YamlNode.Stacking["Quadrature detection"] = {}
  1377. self.YamlNode.Stacking["Quadrature detection"]["trim"] = str( self.ui.trimSpin.value() )
  1378. self.YamlNode.Stacking["Quadrature detection"]["method"] = method
  1379. self.YamlNode.Stacking["Quadrature detection"]["loss"] = loss
  1380. self.Log()
  1381. #if "Quadrature detection" not in self.YamlNode.Processing.keys():
  1382. # self.YamlNode.Processing["Quadrature detection"] = {}
  1383. # self.YamlNode.Processing["Quadrature detection"]["trim"] = str( self.ui.trimSpin.value() )
  1384. # self.Log()
  1385. #else:
  1386. # self.YamlNode.Processing["Quadrature detection"] = {}
  1387. # self.YamlNode.Processing["Quadrature detection"]["trim"] = str( self.ui.trimSpin.value() )
  1388. # self.Log()
  1389. #err_msg = "Quadrature detection has already been done!"
  1390. #reply =QtWidgets.QMessageBox.critical(self, 'Error',
  1391. # err_msg)
  1392. #return
  1393. self.lock("quadrature detection")
  1394. thread.start_new_thread(self.RAWDataProc.quadDet, \
  1395. (self.ui.trimSpin.value(), method, loss, self.ui.mplwidget))
  1396. self.ui.plotQD.setEnabled(True)
  1397. def plotQD(self):
  1398. self.lock("plot QD")
  1399. thread.start_new_thread(self.RAWDataProc.plotQuadDet, \
  1400. (self.ui.trimSpin.value(), int(self.ui.QDType.currentIndex()), self.ui.mplwidget))
  1401. def gateIntegrate(self):
  1402. if "Gate integrate" not in self.YamlNode.Stacking.keys():
  1403. self.YamlNode.Stacking["Gate integrate"] = {}
  1404. self.YamlNode.Stacking["Gate integrate"]["gpd"] = str(self.ui.GPDspinBox.value( ) )
  1405. self.Log()
  1406. self.lock("gate integration")
  1407. thread.start_new_thread(self.RAWDataProc.gateIntegrate, \
  1408. (self.ui.GPDspinBox.value(), self.ui.trimSpin.value(), self.ui.mplwidget))
  1409. self.ui.actionExport_Preprocessed_Dataset.setEnabled(True)
  1410. self.ui.plotGI.setEnabled(True)
  1411. def plotGI(self):
  1412. self.lock("plot gate integrate")
  1413. thread.start_new_thread(self.RAWDataProc.plotGateIntegrate, \
  1414. (self.ui.GPDspinBox.value(), self.ui.trimSpin.value(), \
  1415. self.ui.QDType_2.currentIndex(), self.ui.mplwidget))
  1416. def designFilter(self):
  1417. [bord, fe] = self.RAWDataProc.designFilter( \
  1418. self.ui.CentralVSpinBox.value(), \
  1419. self.ui.passBandSpinBox.value(), \
  1420. self.ui.stopBandSpinBox.value(), \
  1421. self.ui.gpassSpinBox.value(), \
  1422. self.ui.gstopSpinBox.value(), \
  1423. str(self.ui.fTypeComboBox.currentText()),
  1424. self.ui.mplwidget
  1425. )
  1426. self.ui.lcdNumberFilterOrder.display(bord)
  1427. self.ui.lcdNumberFTauDead.display(1e3*fe)
  1428. self.ui.bandPassGO.setEnabled(1)
  1429. ################################################################
  1430. # Hack for MacOS to force refresh of group box and plot
  1431. # this has an undesirable effect that it causes the groupbox to 'jump' up
  1432. # TODO come up with a better solution
  1433. self.ui.mplwidget.hide()
  1434. self.ui.mplwidget.show()
  1435. self.ui.BandPassBox.hide()
  1436. self.ui.BandPassBox.show()
  1437. def windowFilter(self):
  1438. self.lock("window filter")
  1439. # Log processing
  1440. Window = OrderedDict()
  1441. Window["STEP " + str(len(self.YamlNode.Processing))] = "Window filter"
  1442. Window["type"] = str(self.ui.windowTypeComboBox.currentText())
  1443. Window["width"] = str(self.ui.windowBandwidthSpinBox.value())
  1444. Window["centre"] = str(self.ui.CentralVSpinBox.value() )
  1445. Window["trim"] = str(self.ui.windowTrim.isChecked())
  1446. self.YamlNode.Processing.append(Window)
  1447. self.Log( )
  1448. if self.ui.windowTrim.isChecked():
  1449. nv = self.ui.lcdTotalDeadTime.value( ) + self.ui.lcdWinDead.value()
  1450. self.ui.lcdTotalDeadTime.display( nv )
  1451. thread.start_new_thread(self.RAWDataProc.windowFilter, \
  1452. (str(self.ui.windowTypeComboBox.currentText()), \
  1453. self.ui.windowBandwidthSpinBox.value(), \
  1454. self.ui.CentralVSpinBox.value(), \
  1455. self.ui.windowTrim.isChecked(), \
  1456. self.ui.mplwidget))
  1457. def designFDFilter(self):
  1458. mPulse = "None"
  1459. if u"Pulse 1" in self.RAWDataProc.DATADICT.keys():
  1460. mPulse = u"Pulse 1"
  1461. elif u"Pulse 2" in self.RAWDataProc.DATADICT.keys():
  1462. mPulse = u"Pulse 2"
  1463. a,b,c,d,dead,ndead = self.RAWDataProc.computeWindow( \
  1464. mPulse,
  1465. self.ui.windowBandwidthSpinBox.value(), \
  1466. self.ui.CentralVSpinBox.value(), \
  1467. str(self.ui.windowTypeComboBox.currentText()), \
  1468. self.ui.mplwidget )
  1469. self.ui.lcdWinDead.display(dead)
  1470. ################################################################
  1471. # Hack for MacOS to force refresh of group box and plot
  1472. # this has an undesirable effect that it causes the groupbox to 'jump' up
  1473. # TODO come up with a better solution
  1474. self.ui.mplwidget.hide()
  1475. self.ui.mplwidget.show()
  1476. self.ui.windowFilterGroupBox.hide()
  1477. self.ui.windowFilterGroupBox.show()
  1478. def updateProgressBar(self, percent):
  1479. self.ui.barProgress.setValue(percent)
  1480. def updateProc(self):
  1481. if str(self.ui.FIDProcComboBox.currentText()) == "Pulse 1":
  1482. self.ui.lcdNumberFID1Length.display(self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][-1]- self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][0])
  1483. elif str(self.ui.FIDProcComboBox.currentText()) == "Pulse 2":
  1484. self.ui.lcdNumberFID2Length.display(self.RAWDataProc.DATADICT["Pulse 2"]["TIMES"][-1]- self.RAWDataProc.DATADICT["Pulse 2"]["TIMES"][0])
  1485. else:
  1486. self.ui.lcdNumberFID1Length.display(self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][-1]- self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][0])
  1487. self.ui.lcdNumberFID2Length.display(self.RAWDataProc.DATADICT["Pulse 2"]["TIMES"][-1]- self.RAWDataProc.DATADICT["Pulse 2"]["TIMES"][0])
  1488. self.ui.lcdNumberResampFreq.display( self.RAWDataProc.samp )
  1489. def doneStatus(self): # unlocks GUI
  1490. self.ui.statusbar.clearMessage ( )
  1491. self.ui.barProgress.hide()
  1492. self.updateProc()
  1493. self.enableAll()
  1494. def lock(self, string):
  1495. self.ui.statusbar.showMessage ( string )
  1496. self.ui.barProgress.show()
  1497. self.ui.barProgress.setValue(0)
  1498. self.disable()
  1499. def unlock(self):
  1500. self.ui.statusbar.clearMessage ( )
  1501. self.ui.barProgress.hide()
  1502. self.enableAll()
  1503. def done(self):
  1504. self.ui.statusbar.showMessage ( "" )
  1505. ################################################################
  1506. ################################################################
  1507. # Boiler plate main function
  1508. import pkg_resources
  1509. from pkg_resources import resource_string
  1510. import matplotlib.image as mpimg
  1511. import matplotlib.pyplot as plt
  1512. from akvo.gui.logo import plotLogo
  1513. def main():
  1514. # splash screen logo
  1515. logo = pkg_resources.resource_filename(__name__, 'akvo.png')
  1516. logo2 = pkg_resources.resource_filename(__name__, 'akvo2.png')
  1517. qApp = QtWidgets.QApplication(sys.argv)
  1518. ssplash = True
  1519. if ssplash:
  1520. pixmap = QtGui.QPixmap(logo)
  1521. splash = QtWidgets.QSplashScreen(pixmap, QtCore.Qt.WindowStaysOnTopHint)
  1522. splash.show()
  1523. aw = ApplicationWindow()
  1524. #img=mpimg.imread(logo)
  1525. for ax in [ aw.ui.mplwidget ]:
  1526. ax.fig.clear()
  1527. subplot = ax.fig.add_subplot(211)
  1528. # old logo plot
  1529. ax.fig.patch.set_facecolor( None )
  1530. ax.fig.patch.set_alpha( .0 )
  1531. #subplot.imshow(img)
  1532. #ax.fig.patch.set_visible(False)
  1533. subplot.axis('off')
  1534. plotLogo(subplot)
  1535. subplot.xaxis.set_major_locator(plt.NullLocator())
  1536. subplot.yaxis.set_major_locator(plt.NullLocator())
  1537. subplot2 = ax.fig.add_subplot(212)
  1538. subplot2.text(0.5, 1.,'surface NMR workbench',
  1539. horizontalalignment='center',
  1540. verticalalignment='center',
  1541. size=22,
  1542. transform = subplot2.transAxes)
  1543. subplot2.xaxis.set_major_locator(plt.NullLocator())
  1544. subplot2.yaxis.set_major_locator(plt.NullLocator())
  1545. subplot2.axis('off')
  1546. ax.draw()
  1547. if ssplash:
  1548. splash.showMessage("Loading modules")
  1549. splash.finish(aw)
  1550. #time.sleep(1)
  1551. aw.setWindowTitle("Akvo v"+str(VERSION))
  1552. aw.show()
  1553. qApp.setWindowIcon(QtGui.QIcon(logo2))
  1554. sys.exit(qApp.exec_())
  1555. if __name__ == "__main__":
  1556. main()