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 52KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. #/usr/bin/env python
  2. import sys
  3. #import readline
  4. try:
  5. from akvo.gui.main_ui import Ui_MainWindow
  6. uicerr = False
  7. except: # Fallback
  8. from akvo.gui.mainui import Ui_MainWindow
  9. uicerr = """
  10. USING THE DEFAULT GUI FILES, AKVO MAY NOT WORK CORRECTLY!
  11. See INSTALL.txt for details regarding GUI configuration
  12. if you are encountering problems.
  13. Clicking ignore will prevent this warning from showing
  14. each time you launch Akvo.
  15. """
  16. import matplotlib
  17. #matplotlib.use("QT4Agg")
  18. from PyQt5 import QtCore, QtGui, QtWidgets
  19. import numpy as np
  20. import time
  21. import os
  22. from copy import deepcopy
  23. from matplotlib.backends.backend_qt4 import NavigationToolbar2QT #as NavigationToolbar
  24. import datetime, time
  25. from akvo.tressel import mrsurvey
  26. import pkg_resources # part of setuptools
  27. version = pkg_resources.require("Akvo")[0].version
  28. import yaml
  29. # Writes out numpy arrays into Eigen vectors as serialized by Lemma
  30. class MatrixXr(yaml.YAMLObject):
  31. yaml_tag = u'MatrixXr'
  32. def __init__(self, rows, cols, data):
  33. self.rows = rows
  34. self.cols = cols
  35. self.data = np.zeros((rows,cols))
  36. def __repr__(self):
  37. return "%s(rows=%r, cols=%r, data=%r)" % (self.__class__.__name__, self.rows, self.cols, self.data)
  38. class VectorXr(yaml.YAMLObject):
  39. yaml_tag = r'VectorXr'
  40. def __init__(self, array):
  41. self.size = np.shape(array)[0]
  42. self.data = array.tolist()
  43. def __repr__(self):
  44. # Converts to numpy array on import
  45. return "np.array(%r)" % (self.data)
  46. from collections import OrderedDict
  47. def represent_ordereddict(dumper, data):
  48. value = []
  49. for item_key, item_value in data.items():
  50. node_key = dumper.represent_data(item_key)
  51. node_value = dumper.represent_data(item_value)
  52. value.append((node_key, node_value))
  53. return yaml.nodes.MappingNode(u'tag:yaml.org,2002:map', value)
  54. yaml.add_representer(OrderedDict, represent_ordereddict)
  55. class AkvoYamlNode(yaml.YAMLObject):
  56. yaml_tag = u'!AkvoData'
  57. def __init__(self):
  58. self.Akvo_VERSION = version
  59. self.Import = {}
  60. self.Processing = OrderedDict()
  61. #self.ProcessingFlow = []
  62. #self.Data = {}
  63. # For going the other way, data import based on Yaml serialization,
  64. def __repr__(self):
  65. return "%s(name=%r, Akvo_VESION=%r, Import=%r, Processing=%r)" % (
  66. self.__class__.__name__, self.Akvo_VERSION, self.Import, OrderedDict(dict(self.Processing)) )
  67. try:
  68. import thread
  69. except ImportError:
  70. import _thread as thread #Py3K compatibility
  71. class MyPopup(QtWidgets.QWidget):
  72. def __init__(self, name):
  73. super().__init__()
  74. self.name = name
  75. self.initUI()
  76. def initUI(self):
  77. lblName = QtWidgets.QLabel(self.name, self)
  78. class ApplicationWindow(QtWidgets.QMainWindow):
  79. def __init__(self):
  80. QtWidgets.QMainWindow.__init__(self)
  81. self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
  82. akvohome = os.path.expanduser("~") + "/.akvo"
  83. if not os.path.exists(akvohome):
  84. os.makedirs(akvohome)
  85. self.ui = Ui_MainWindow()
  86. self.ui.setupUi(self)
  87. if uicerr != False and not os.path.exists(akvohome+"/pyuic-warned"):
  88. reply = QtGui.QMessageBox.warning(self, 'Warning', uicerr, QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ignore)
  89. if reply == 1024: # "0x400" in hex
  90. pass
  91. elif reply == 1048576: # "0x100000" in hex
  92. warn = open( akvohome+"/pyuic-warned" ,"w" )
  93. warn.write("Gui files were not compiled locally using pyuic! Further warnings have been supressed")
  94. warn.close()
  95. self.RAWDataProc = None
  96. self.YamlNode = AkvoYamlNode()
  97. # initialise some stuff
  98. self.ui.lcdNumberTauPulse2.setEnabled(0)
  99. self.ui.lcdNumberTauPulse1.setEnabled(0)
  100. self.ui.lcdNumberNuTx.setEnabled(0)
  101. self.ui.lcdNumberTuneuF.setEnabled(0)
  102. self.ui.lcdNumberSampFreq.setEnabled(0)
  103. self.ui.lcdNumberTauDelay.setEnabled(0)
  104. self.ui.lcdNumberNQ.setEnabled(0)
  105. #MAK 20170126: add in a list to hold processing steps
  106. self.logText = []
  107. ####################
  108. # Make connections #
  109. ####################
  110. # Menu items
  111. self.ui.actionOpen_GMR.triggered.connect(self.openGMRRAWDataset)
  112. self.ui.actionSave_Preprocessed_Dataset.triggered.connect(self.SavePreprocess)
  113. self.ui.actionExport_Preprocessed_Dataset.triggered.connect(self.ExportPreprocess)
  114. self.ui.actionExport_Preprocessed_Dataset.setEnabled(False)
  115. self.ui.actionOpen_Preprocessed_Dataset.triggered.connect(self.OpenPreprocess)
  116. self.ui.actionAboutAkvo.triggered.connect(self.about)
  117. # Buttons
  118. # #QtCore.QObject.connect(self.ui.fullWorkflowPushButton, QtCore.SIGNAL("clicked()"), self.preprocess )
  119. self.ui.loadDataPushButton.pressed.connect(self.loadRAW)
  120. self.ui.sumDataGO.pressed.connect( self.sumDataChans )
  121. self.ui.bandPassGO.pressed.connect( self.bandPassFilter )
  122. self.ui.filterDesignPushButton.pressed.connect( self.designFilter )
  123. self.ui.fdDesignPushButton.pressed.connect( self.designFDFilter )
  124. self.ui.downSampleGO.pressed.connect( self.downsample )
  125. self.ui.windowFilterGO.pressed.connect( self.windowFilter )
  126. # self.ui.despikeGO.pressed.connect( self.despikeFilter ) # use smart stack instead
  127. self.ui.adaptGO.pressed.connect( self.adaptFilter )
  128. self.ui.adaptFDGO.pressed.connect( self.adaptFilterFD )
  129. self.ui.qdGO.pressed.connect( self.quadDet )
  130. self.ui.gateIntegrateGO.pressed.connect( self.gateIntegrate )
  131. self.ui.calcQGO.pressed.connect( self.calcQ )
  132. self.ui.FDSmartStackGO.pressed.connect( self.FDSmartStack )
  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. # Add progressbar to statusbar
  138. self.ui.barProgress = QtWidgets.QProgressBar()
  139. self.ui.statusbar.addPermanentWidget(self.ui.barProgress, 0);
  140. self.ui.barProgress.setMaximumSize(100, 16777215);
  141. self.ui.barProgress.hide();
  142. self.ui.mplwidget_navigator.setCanvas(self.ui.mplwidget)
  143. self.ui.mplwidget_navigator_2.setCanvas(self.ui.mplwidget_2)
  144. ##########################################################################
  145. # modelling Table
  146. self.ui.loopTableWidget.setRowCount(80)
  147. self.ui.loopTableWidget.setColumnCount(6)
  148. self.ui.loopTableWidget.setHorizontalHeaderLabels( ["ch. tag", "Northing [m]","Easting [m]","Height [m]", "Radius","Tx"] )
  149. for ir in range(1, self.ui.loopTableWidget.rowCount() ):
  150. for ic in range( self.ui.loopTableWidget.columnCount() ):
  151. pCell = QtWidgets.QTableWidgetItem()
  152. #pCell.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
  153. pCell.setFlags(QtCore.Qt.NoItemFlags) # not selectable
  154. pCell.setBackground( QtGui.QColor("lightgrey").lighter(110) )
  155. self.ui.loopTableWidget.setItem(ir, ic, pCell)
  156. self.ui.loopTableWidget.cellChanged.connect(self.loopCellChanged)
  157. self.ui.loopTableWidget.setDragDropOverwriteMode(False)
  158. self.ui.loopTableWidget.setDragEnabled(True)
  159. self.ui.loopTableWidget.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
  160. ##########################################################################
  161. # layer Table
  162. self.ui.layerTableWidget.setRowCount(80)
  163. self.ui.layerTableWidget.setColumnCount(3)
  164. self.ui.layerTableWidget.setHorizontalHeaderLabels( [r"top [m]", r"bottom [m]", "σ [ Ωm]" ] )
  165. self.ui.layerTableWidget.setDragDropOverwriteMode(False)
  166. self.ui.layerTableWidget.setDragEnabled(True)
  167. self.ui.layerTableWidget.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
  168. pCell = QtWidgets.QTableWidgetItem()
  169. pCell.setFlags(QtCore.Qt.NoItemFlags) # not selectable
  170. pCell.setBackground( QtGui.QColor("lightgrey").lighter(110) )
  171. self.ui.layerTableWidget.setItem(0, 1, pCell)
  172. for ir in range(1, 80):
  173. for ic in range(0, 3):
  174. pCell = QtWidgets.QTableWidgetItem()
  175. #pCell.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
  176. pCell.setFlags(QtCore.Qt.NoItemFlags) # not selectable
  177. pCell.setBackground( QtGui.QColor("lightgrey").lighter(110) )
  178. self.ui.layerTableWidget.setItem(ir, ic, pCell)
  179. self.ui.layerTableWidget.cellChanged.connect(self.sigmaCellChanged)
  180. def sigmaCellChanged(self):
  181. self.ui.layerTableWidget.cellChanged.disconnect(self.sigmaCellChanged)
  182. # TODO consider building the model whenever this is called. Would be nice to be able to
  183. # do that. Would require instead dist of T2 I guess.
  184. jj = self.ui.layerTableWidget.currentColumn()
  185. ii = self.ui.layerTableWidget.currentRow()
  186. val = "class 'NoneType'>"
  187. try:
  188. val = eval (str( self.ui.layerTableWidget.item(ii, jj).text() ))
  189. except:
  190. #if jj != 0:
  191. # Error = QtWidgets.QMessageBox()
  192. # Error.setWindowTitle("Error!")
  193. # Error.setText("Non-numeric value encountered")
  194. self.ui.layerTableWidget.cellChanged.connect(self.sigmaCellChanged)
  195. return
  196. if jj == 1:
  197. #item.setFlags(QtCore.Qt.ItemIsEnabled)
  198. pCell = self.ui.layerTableWidget.item(ii, jj)
  199. pCell.setBackground( QtGui.QColor("white"))
  200. pCell = self.ui.layerTableWidget.item(ii+1, jj-1)
  201. if str(type(pCell)) == "<class 'NoneType'>":
  202. pCell = QtWidgets.QTableWidgetItem()
  203. pCell.setFlags(QtCore.Qt.ItemIsEnabled)
  204. self.ui.layerTableWidget.setItem(ii+1, jj-1, pCell)
  205. if ii == 0:
  206. pCell.setText(str(val))
  207. #pCell3 = self.ui.layerTableWidget.item(ii+1, jj)
  208. #print ("setting", ii, jj, type(pCell3))
  209. #print ( "setting", ii, jj, type(pCell3))
  210. #pCell3.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled )
  211. #pCell3.setFlags( QtCore.Qt.ItemIsEditable )
  212. elif ii > 0:
  213. val2 = eval (str( self.ui.layerTableWidget.item(ii-1, jj).text() ))
  214. #print ("val2", val2, val, type(val))
  215. #if str(type(pCell)) == "<class 'NoneType'>":
  216. if type(val) == str or val > val2:
  217. pCell.setText(str(val))
  218. else:
  219. Error = QtWidgets.QMessageBox()
  220. Error.setWindowTitle("Error!")
  221. Error.setText("Non-increasing layer detected")
  222. Error.setDetailedText("Each layer interface must be below the one above it.")
  223. Error.exec_()
  224. pCell2 = self.ui.layerTableWidget.item(ii, jj)
  225. pCell2.setText(str(""))
  226. self.ui.layerTableWidget.cellChanged.connect(self.sigmaCellChanged)
  227. return
  228. # enable next layer
  229. pCell4 = self.ui.layerTableWidget.item(ii+1, jj)
  230. pCell4.setBackground( QtGui.QColor("lightblue") ) #.lighter(110))
  231. pCell4.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled )
  232. pCell5 = self.ui.layerTableWidget.item(ii+1, jj+1)
  233. pCell5.setBackground( QtGui.QColor("white"))
  234. pCell5.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled )
  235. print("ii", ii, "jj", jj)
  236. if ii == 0 and jj == 0:
  237. pCell = self.ui.layerTableWidget.item(0, 1)
  238. pCell.setBackground( QtGui.QColor("lightblue")) #.lighter(110) )
  239. pCell.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled )
  240. self.ui.layerTableWidget.cellChanged.connect(self.sigmaCellChanged)
  241. def loopCellChanged(self):
  242. # TODO consider building the model whenever this is called. Would be nice to be able to
  243. # do that. Would require instead dist of T2 I guess.
  244. jj = self.ui.loopTableWidget.currentColumn()
  245. ii = self.ui.loopTableWidget.currentRow()
  246. #if self.ui.loopTableWidget.item(ii, jj) == None:
  247. # return
  248. if jj == 5:
  249. pass
  250. #pCell = QtWidgets.QTableWidgetItem()
  251. #pCell.setFlags(QtCore.Qt.ItemIsEnabled)
  252. #pCell.setBackground( QtGui.QColor("lightblue") ) #.lighter(110))
  253. #self.ui.loopTableWidget.setItem(ii, jj, pCell)
  254. #pCell4 = self.ui.layerTableWidget.item(ii, jj)
  255. #print(pCell4)
  256. #pCell4.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled )
  257. #pCell4.setBackground( QtGui.QColor("lightblue") ) #.lighter(110))
  258. # try:
  259. # eval (str( self.ui.loopTableWidget.item(ii, jj).text() ))
  260. # except:
  261. # if jj != 0:
  262. # Error = QtWidgets.QMessageBox()
  263. # Error.setWindowTitle("Error!")
  264. # Error.setText("Non-numeric value encountered")
  265. # Error.setDetailedText("Modelling parameters must be able to be cast into numeric values.")
  266. # Error.exec_()
  267. self.plotLoops()
  268. def plotLoops(self):
  269. #self.ui.mplwidget_3.fig.clear()
  270. self.ui.mplwidget_3.ax1.clear()
  271. self.ui.mplwidget_3.ax2.clear()
  272. nor = dict()
  273. eas = dict()
  274. dep = dict()
  275. for ii in range( self.ui.loopTableWidget.rowCount() ):
  276. for jj in range( self.ui.loopTableWidget.columnCount() ):
  277. tp = type(self.ui.loopTableWidget.item(ii, jj))
  278. if str(tp) == "<class 'NoneType'>":
  279. pass
  280. elif not len(self.ui.loopTableWidget.item(ii, jj).text()):
  281. pass
  282. else:
  283. if jj == 0:
  284. idx = self.ui.loopTableWidget.item(ii, 0).text()
  285. if idx not in nor.keys():
  286. nor[idx] = list()
  287. eas[idx] = list()
  288. dep[idx] = list()
  289. if jj == 1:
  290. nor[idx].append( eval(self.ui.loopTableWidget.item(ii, 1).text()) )
  291. elif jj == 2:
  292. eas[idx].append( eval(self.ui.loopTableWidget.item(ii, 2).text()) )
  293. elif jj == 3:
  294. dep[idx].append( eval(self.ui.loopTableWidget.item(ii, 3).text()) )
  295. for ii in nor.keys():
  296. try:
  297. self.ui.mplwidget_3.ax1.plot( np.array(nor[ii]), np.array(eas[ii]) )
  298. except:
  299. pass
  300. #self.ui.mplwidget_3.figure.axes().set
  301. plt.gca().set_aspect('equal') #, adjustable='box')
  302. self.ui.mplwidget_3.draw()
  303. def about(self):
  304. # TODO proper popup with info
  305. #self.w = MyPopup("""About Akvo \n
  306. # Akvo is an open source project developed primarily by Trevor Irons.
  307. #""")
  308. #self.w.setGeometry(100, 100, 400, 200)
  309. #self.w.show()
  310. # Just a splash screen for now
  311. logo = pkg_resources.resource_filename(__name__, 'akvo_about.png')
  312. pixmap = QtGui.QPixmap(logo)
  313. self.splash = QtWidgets.QSplashScreen(pixmap, QtCore.Qt.WindowStaysOnTopHint)
  314. self.splash.show()
  315. def connectGMRDataProcessor(self):
  316. self.RAWDataProc = mrsurvey.GMRDataProcessor()
  317. self.RAWDataProc.progressTrigger.connect(self.updateProgressBar)
  318. self.RAWDataProc.enableDSPTrigger.connect(self.enableDSP)
  319. self.RAWDataProc.doneTrigger.connect(self.doneStatus)
  320. self.RAWDataProc.updateProcTrigger.connect(self.updateProc)
  321. def openGMRRAWDataset(self):
  322. try:
  323. with open('.gmr.last.path') as f:
  324. fpath = f.readline()
  325. pass
  326. except IOError as e:
  327. fpath = '.'
  328. self.headerstr = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', fpath)[0] # arg2 = File Type 'All Files (*)'
  329. self.ui.headerFileTextBrowser.clear()
  330. self.ui.headerFileTextBrowser.append(self.headerstr)
  331. if len(self.headerstr) == 0:
  332. return
  333. # clear the processing log
  334. self.ui.logTextBrowser.clear()
  335. self.logText = [] #MAK 20170126
  336. path,filen=os.path.split(str(self.headerstr))
  337. f = open('.gmr.last.path', 'w')
  338. f.write( str(self.headerstr) ) # prompt last file
  339. self.connectGMRDataProcessor()
  340. self.RAWDataProc.readHeaderFile(str(self.headerstr))
  341. # If we got this far, enable all the widgets
  342. self.ui.lcdNumberTauPulse1.setEnabled(True)
  343. self.ui.lcdNumberNuTx.setEnabled(True)
  344. self.ui.lcdNumberTuneuF.setEnabled(True)
  345. self.ui.lcdNumberSampFreq.setEnabled(True)
  346. self.ui.lcdNumberNQ.setEnabled(True)
  347. self.ui.headerFileBox.setEnabled(True)
  348. self.ui.inputRAWParametersBox.setEnabled(True)
  349. self.ui.loadDataPushButton.setEnabled(True)
  350. # make plots as you import the dataset
  351. self.ui.plotImportCheckBox.setEnabled(True)
  352. self.ui.plotImportCheckBox.setChecked(True)
  353. # Update info from the header into the GUI
  354. self.ui.pulseTypeTextBrowser.clear()
  355. self.ui.pulseTypeTextBrowser.append(self.RAWDataProc.pulseType)
  356. self.ui.lcdNumberNuTx.display(self.RAWDataProc.transFreq)
  357. self.ui.lcdNumberTauPulse1.display(1e3*self.RAWDataProc.pulseLength[0])
  358. self.ui.lcdNumberTuneuF.display(self.RAWDataProc.TuneCapacitance)
  359. self.ui.lcdNumberSampFreq.display(self.RAWDataProc.samp)
  360. self.ui.lcdNumberNQ.display(self.RAWDataProc.nPulseMoments)
  361. self.ui.DeadTimeSpinBox.setValue(1e3*self.RAWDataProc.deadTime)
  362. self.ui.CentralVSpinBox.setValue( self.RAWDataProc.transFreq )
  363. if self.RAWDataProc.pulseType != "FID":
  364. self.ui.lcdNumberTauPulse2.setEnabled(1)
  365. self.ui.lcdNumberTauPulse2.display(1e3*self.RAWDataProc.pulseLength[1])
  366. self.ui.lcdNumberTauDelay.setEnabled(1)
  367. self.ui.lcdNumberTauDelay.display(1e3*self.RAWDataProc.interpulseDelay)
  368. self.ui.FIDProcComboBox.clear()
  369. if self.RAWDataProc.pulseType == "4PhaseT1":
  370. self.ui.FIDProcComboBox.insertItem(0, "Pulse 1")
  371. self.ui.FIDProcComboBox.insertItem(1, "Pulse 2")
  372. self.ui.FIDProcComboBox.insertItem(2, "Both")
  373. self.ui.FIDProcComboBox.setCurrentIndex (1)
  374. elif self.RAWDataProc.pulseType == "FID":
  375. self.ui.FIDProcComboBox.insertItem(0, "Pulse 1")
  376. self.ui.FIDProcComboBox.setCurrentIndex (0)
  377. def ExportPreprocess(self):
  378. """ This method export to YAML
  379. """
  380. try:
  381. with open('.akvo.last.yaml.path') as f:
  382. fpath = f.readline()
  383. pass
  384. except IOError as e:
  385. fpath = '.'
  386. fdir = os.path.dirname(fpath)
  387. # Pickle the preprocessed data dictionary
  388. SaveStr = QtWidgets.QFileDialog.getSaveFileName(self, "Save as", fdir, r"Processed data (*.yaml)")[0]
  389. spath,filen=os.path.split(str(SaveStr))
  390. f = open('.akvo.last.yaml.path', 'w')
  391. f.write( str(spath) ) # prompt last file
  392. INFO = {}
  393. INFO["headerstr"] = str(self.headerstr)
  394. INFO["pulseType"] = self.RAWDataProc.pulseType
  395. INFO["transFreq"] = self.RAWDataProc.transFreq.tolist()
  396. INFO["pulseLength"] = self.RAWDataProc.pulseLength.tolist()
  397. INFO["TuneCapacitance"] = self.RAWDataProc.TuneCapacitance.tolist()
  398. #INFO["samp"] = self.RAWDataProc.samp
  399. INFO["nPulseMoments"] = self.RAWDataProc.nPulseMoments
  400. #INFO["deadTime"] = self.RAWDataProc.deadTime
  401. INFO["processed"] = "Akvo v. 1.0, on " + time.strftime("%d/%m/%Y")
  402. # Pulse current info
  403. ip = 0
  404. INFO["Pulses"] = {}
  405. for pulse in self.RAWDataProc.DATADICT["PULSES"]:
  406. qq = []
  407. qv = []
  408. for ipm in range(self.RAWDataProc.DATADICT["nPulseMoments"]):
  409. #for istack in self.RAWDataProc.DATADICT["stacks"]:
  410. # print ("stack q", self.RAWDataProc.DATADICT[pulse]["Q"][ipm,istack-1])
  411. qq.append(np.mean( self.RAWDataProc.DATADICT[pulse]["Q"][ipm,:]) )
  412. qv.append(np.std( self.RAWDataProc.DATADICT[pulse]["Q"][ipm,:]/self.RAWDataProc.pulseLength[ip] ))
  413. INFO["Pulses"][pulse] = {}
  414. INFO["Pulses"][pulse]["units"] = "A"
  415. INFO["Pulses"][pulse]["current"] = VectorXr(np.array(qq)/self.RAWDataProc.pulseLength[ip])
  416. INFO["Pulses"][pulse]["variance"] = VectorXr(np.array(qv))
  417. ip += 1
  418. # Data
  419. if self.RAWDataProc.gated == True:
  420. INFO["Gated"] = {}
  421. INFO["Gated"]["abscissa units"] = "ms"
  422. INFO["Gated"]["data units"] = "nT"
  423. for pulse in self.RAWDataProc.DATADICT["PULSES"]:
  424. INFO["Gated"][pulse] = {}
  425. INFO["Gated"][pulse]["abscissa"] = VectorXr( self.RAWDataProc.GATEDABSCISSA )
  426. INFO["Gated"][pulse]["windows"] = VectorXr( self.RAWDataProc.GATEDWINDOW )
  427. for ichan in self.RAWDataProc.DATADICT[pulse]["chan"]:
  428. INFO["Gated"][pulse]["Chan. " + str(ichan)] = {}
  429. INFO["Gated"][pulse]["Chan. " + str(ichan)]["STD"] = VectorXr( np.std(self.RAWDataProc.GATED[ichan]["NR"], axis=0) )
  430. for ipm in range(self.RAWDataProc.DATADICT["nPulseMoments"]):
  431. INFO["Gated"][pulse]["Chan. " + str(ichan)]["Q-"+str(ipm) + " CA"] = VectorXr(self.RAWDataProc.GATED[ichan]["CA"][ipm])
  432. INFO["Gated"][pulse]["Chan. " + str(ichan)]["Q-"+str(ipm) + " RE"] = VectorXr(self.RAWDataProc.GATED[ichan]["RE"][ipm])
  433. INFO["Gated"][pulse]["Chan. " + str(ichan)]["Q-"+str(ipm) + " IM"] = VectorXr(self.RAWDataProc.GATED[ichan]["IM"][ipm])
  434. #INFO["Gated"][pulse]["Chan. " + str(ichan)]["Q-"+str(ipm) + " IP"] = VectorXr(self.RAWDataProc.GATED[ichan]["IP"][ipm])
  435. #INFO["Gated"][pulse]["Chan. " + str(ichan)]["Q-"+str(ipm) + " NR"] = VectorXr(self.RAWDataProc.GATED[ichan]["NR"][ipm])
  436. #INFO["Gated"][pulse]["Chan. " + str(ichan)]["Q-"+str(ipm) + " STD" ] = VectorXr(self.RAWDataProc.GATED[ichan]["SIGMA"][ipm])
  437. # we have gated data
  438. # Window edges
  439. # Window centres
  440. with open(SaveStr, 'w') as outfile:
  441. for line in self.logText:
  442. outfile.write(line+"\n")
  443. yaml.dump(INFO, outfile, default_flow_style=False)
  444. def SavePreprocess(self):
  445. #if "Saved" not in self.YamlNode.Processing.keys():
  446. # self.YamlNode.Processing["Saved"] = []
  447. #self.YamlNode.Processing["Saved"].append(datetime.datetime.now().isoformat())
  448. #self.Log()
  449. import pickle, os
  450. try:
  451. with open('.akvo.last.path') as f:
  452. fpath = f.readline()
  453. pass
  454. except IOError as e:
  455. fpath = '.'
  456. fdir = os.path.dirname(fpath)
  457. # Pickle the preprocessed data dictionary
  458. SaveStr = QtWidgets.QFileDialog.getSaveFileName(self, "Save as", fdir, r"Pickle (*.dmp)")
  459. print(SaveStr)
  460. spath,filen=os.path.split(str(SaveStr[0]))
  461. f = open('.akvo.last.path', 'w')
  462. f.write( str(spath) ) # prompt last file
  463. save = open(SaveStr[0], 'wb')
  464. # Add some extra info
  465. INFO = {}
  466. INFO["pulseType"] = self.RAWDataProc.pulseType
  467. INFO["transFreq"] = self.RAWDataProc.transFreq
  468. INFO["pulseLength"] = self.RAWDataProc.pulseLength
  469. INFO["TuneCapacitance"] = self.RAWDataProc.TuneCapacitance
  470. INFO["samp"] = self.RAWDataProc.samp
  471. INFO["nPulseMoments"] = self.RAWDataProc.nPulseMoments
  472. INFO["deadTime"] = self.RAWDataProc.deadTime
  473. INFO["transFreq"] = self.RAWDataProc.transFreq
  474. INFO["headerstr"] = str(self.headerstr)
  475. INFO["log"] = yaml.dump( self.YamlNode ) #self.logText #MAK 20170127
  476. print ("YAML NODE", yaml.dump( self.YamlNode ) )
  477. self.RAWDataProc.DATADICT["INFO"] = INFO
  478. pickle.dump(self.RAWDataProc.DATADICT, save)
  479. save.close()
  480. # Export XML file suitable for USGS ScienceBase Data Release
  481. def ExportXML(self):
  482. return 42
  483. def OpenPreprocess(self):
  484. import pickle
  485. try:
  486. with open('.akvo.last.path') as f:
  487. fpath = f.readline()
  488. pass
  489. except IOError as e:
  490. fpath = '.'
  491. #filename = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', '.')
  492. fpath = QtWidgets.QFileDialog.getOpenFileName(self, 'Open preprocessed file', fpath, r"Pickle Files (*.dmp)")[0]
  493. f = open('.akvo.last.path', 'w')
  494. f.write( str(fpath) ) # prompt last file
  495. self.ui.logTextBrowser.clear()
  496. self.logText = []
  497. if len(fpath) == 0:
  498. return
  499. pfile = open(fpath,'rb')
  500. unpickle = pickle.Unpickler(pfile)
  501. self.connectGMRDataProcessor()
  502. self.RAWDataProc.DATADICT = unpickle.load()
  503. self.RAWDataProc.readHeaderFile(self.RAWDataProc.DATADICT["INFO"]["headerstr"])
  504. self.headerstr = self.RAWDataProc.DATADICT["INFO"]["headerstr"]
  505. self.RAWDataProc.pulseType = self.RAWDataProc.DATADICT["INFO"]["pulseType"]
  506. self.RAWDataProc.transFreq = self.RAWDataProc.DATADICT["INFO"]["transFreq"]
  507. self.RAWDataProc.pulseLength = self.RAWDataProc.DATADICT["INFO"]["pulseLength"]
  508. self.RAWDataProc.TuneCapacitance = self.RAWDataProc.DATADICT["INFO"]["TuneCapacitance"]
  509. self.RAWDataProc.samp = self.RAWDataProc.DATADICT["INFO"]["samp"]
  510. self.RAWDataProc.nPulseMoments = self.RAWDataProc.DATADICT["INFO"]["nPulseMoments"]
  511. self.RAWDataProc.deadTime = self.RAWDataProc.DATADICT["INFO"]["deadTime"]
  512. self.RAWDataProc.transFreq = self.RAWDataProc.DATADICT["INFO"]["transFreq"]
  513. self.RAWDataProc.dt = 1./self.RAWDataProc.samp
  514. self.dataChan = self.RAWDataProc.DATADICT[ self.RAWDataProc.DATADICT["PULSES"][0] ]["chan"]
  515. # Keep backwards compatibility with prior saved pickles???
  516. #self.ui.logTextBrowser.clear()
  517. #self.ui.logTextBrowser.append( yaml.dump(self.YamlNode)) #, default_flow_style=False) )
  518. #for a in self.logText:
  519. # self.ui.logTextBrowser.append(str(a))
  520. #self.ui.logTextBrowser
  521. #self.ui.logTextBrowser.clear()
  522. #print ( self.RAWDataProc.DATADICT["INFO"]["log"] )
  523. self.logText = self.RAWDataProc.DATADICT["INFO"]["log"] # YAML
  524. self.YamlNode = yaml.load( self.logText )
  525. #self.ui.logTextBrowser.append( yaml.dump(self.YamlNode)) #, default_flow_style=False) )
  526. #except KeyError:
  527. # pass
  528. # Remove "Saved" and "Loaded" from processing flow
  529. #if "Loaded" not in self.YamlNode.Processing.keys():
  530. # self.YamlNode.Processing["Loaded"] = []
  531. #self.YamlNode.Processing["Loaded"].append(datetime.datetime.now().isoformat())
  532. #self.Log()
  533. # If we got this far, enable all the widgets
  534. self.ui.lcdNumberTauPulse1.setEnabled(True)
  535. self.ui.lcdNumberNuTx.setEnabled(True)
  536. self.ui.lcdNumberTuneuF.setEnabled(True)
  537. self.ui.lcdNumberSampFreq.setEnabled(True)
  538. self.ui.lcdNumberNQ.setEnabled(True)
  539. self.ui.headerFileBox.setEnabled(True)
  540. self.ui.inputRAWParametersBox.setEnabled(True)
  541. self.ui.loadDataPushButton.setEnabled(True)
  542. # make plots as you import the dataset
  543. self.ui.plotImportCheckBox.setEnabled(True)
  544. self.ui.plotImportCheckBox.setChecked(True)
  545. # Update info from the header into the GUI
  546. self.ui.pulseTypeTextBrowser.clear()
  547. self.ui.pulseTypeTextBrowser.append(self.RAWDataProc.pulseType)
  548. self.ui.lcdNumberNuTx.display(self.RAWDataProc.transFreq)
  549. self.ui.lcdNumberTauPulse1.display(1e3*self.RAWDataProc.pulseLength[0])
  550. self.ui.lcdNumberTuneuF.display(self.RAWDataProc.TuneCapacitance)
  551. self.ui.lcdNumberSampFreq.display(self.RAWDataProc.samp)
  552. self.ui.lcdNumberNQ.display(self.RAWDataProc.nPulseMoments)
  553. self.ui.DeadTimeSpinBox.setValue(1e3*self.RAWDataProc.deadTime)
  554. self.ui.CentralVSpinBox.setValue( self.RAWDataProc.transFreq )
  555. if self.RAWDataProc.pulseType != "FID":
  556. self.ui.lcdNumberTauPulse2.setEnabled(1)
  557. self.ui.lcdNumberTauPulse2.display(1e3*self.RAWDataProc.pulseLength[1])
  558. self.ui.lcdNumberTauDelay.setEnabled(1)
  559. self.ui.lcdNumberTauDelay.display(1e3*self.RAWDataProc.interpulseDelay)
  560. self.ui.FIDProcComboBox.clear()
  561. if self.RAWDataProc.pulseType == "4PhaseT1":
  562. self.ui.FIDProcComboBox.insertItem(0, "Pulse 1") #, const QVariant & userData = QVariant() )
  563. self.ui.FIDProcComboBox.insertItem(1, "Pulse 2") #, const QVariant & userData = QVariant() )
  564. self.ui.FIDProcComboBox.insertItem(2, "Both") #, const QVariant & userData = QVariant() )
  565. if len( self.RAWDataProc.DATADICT["PULSES"]) == 2:
  566. self.ui.FIDProcComboBox.setCurrentIndex (2)
  567. elif self.RAWDataProc.DATADICT["PULSES"][0] == "Pulse 1":
  568. self.ui.FIDProcComboBox.setCurrentIndex (0)
  569. else:
  570. self.ui.FIDProcComboBox.setCurrentIndex (1)
  571. elif self.RAWDataProc.pulseType == "FID":
  572. self.ui.FIDProcComboBox.insertItem(0, "Pulse 1") #, const QVariant & userData = QVariant() )
  573. self.ui.FIDProcComboBox.setCurrentIndex (0)
  574. # QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("updateProgress(int)"), self.updateProgressBar)
  575. # QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("enableDSP()"), self.enableDSP)
  576. # QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("doneStatus()"), self.doneStatus)
  577. self.RAWDataProc.progressTrigger.connect(self.updateProgressBar)
  578. self.RAWDataProc.enableDSPTrigger.connect(self.enableDSP)
  579. self.RAWDataProc.doneTrigger.connect(self.doneStatus)
  580. self.enableAll()
  581. def loadRAW(self):
  582. #################################################
  583. # Check to make sure we are ready to process
  584. # Header
  585. if self.RAWDataProc == None:
  586. err_msg = "You need to load a header first."
  587. reply = QtGui.QMessageBox.critical(self, 'Error',
  588. err_msg) #, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
  589. return
  590. # Stacks
  591. try:
  592. self.procStacks = np.array(eval(str("np.r_["+self.ui.stacksLineEdit.text())+"]"))
  593. except:
  594. err_msg = "You need to set your stacks correctly.\n" + \
  595. "This should be a Python Numpy interpretable list\n" + \
  596. "of stack indices. For example 1:24 or 1:4,8:24"
  597. QtGui.QMessageBox.critical(self, 'Error', err_msg)
  598. return
  599. # Data Channels
  600. #Chan = np.arange(0,9,1)
  601. try:
  602. self.dataChan = np.array(eval(str("np.r_["+self.ui.dataChanLineEdit.text())+"]"))
  603. except:
  604. #QMessageBox messageBox;
  605. #messageBox.critical(0,"Error","An error has occured !");
  606. #messageBox.setFixedSize(500,200);
  607. #quit_msg = "Are you sure you want to exit the program?"
  608. #reply = QtGui.QMessageBox.question(self, 'Message',
  609. # quit_msg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
  610. err_msg = "You need to set your data channels correctly.\n" + \
  611. "This should be a Python Numpy interpretable list\n" + \
  612. "of indices. For example 1 or 1:3 or 1:3 5\n\n" + \
  613. "valid GMR data channels fall between 1 and 8. Note that\n" +\
  614. "1:3 is not inclusive of 3 and is the same as 1,2 "
  615. reply = QtGui.QMessageBox.critical(self, 'Error',
  616. err_msg) #, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
  617. return
  618. #############################
  619. # Reference Channels
  620. # TODO make sure no overlap between data and ref channels
  621. self.refChan = np.array( () )
  622. if str(self.ui.refChanLineEdit.text()): # != "none":
  623. try:
  624. self.refChan = np.array(eval(str("np.r_["+self.ui.refChanLineEdit.text())+"]"))
  625. except:
  626. err_msg = "You need to set your reference channels correctly.\n" + \
  627. "This should be a Python Numpy interpretable list\n" + \
  628. "of indices. For example 1 or 1:3 or 1:3 5\n\n" + \
  629. "valid GMR data channels fall between 1 and 8. Note that\n" +\
  630. "1:3 is not inclusive of 3 and is the same as 1,2 "
  631. QtGui.QMessageBox.critical(self, 'Error', err_msg)
  632. return
  633. #####################################################
  634. # Load data
  635. self.lock("loading RAW GMR dataset")
  636. if self.RAWDataProc.pulseType == "FID":
  637. self.procThread = thread.start_new_thread(self.RAWDataProc.loadFIDData, \
  638. (str(self.headerstr), self.procStacks, self.dataChan, self.refChan, \
  639. str(self.ui.FIDProcComboBox.currentText()), self.ui.mplwidget, \
  640. 1e-3 * self.ui.DeadTimeSpinBox.value( ), self.ui.plotImportCheckBox.isChecked() )) #, self))
  641. elif self.RAWDataProc.pulseType == "4PhaseT1":
  642. self.procThread = thread.start_new_thread(self.RAWDataProc.load4PhaseT1Data, \
  643. (str(self.headerstr), self.procStacks, self.dataChan, self.refChan, \
  644. str(self.ui.FIDProcComboBox.currentText()), self.ui.mplwidget, \
  645. 1e-3 * self.ui.DeadTimeSpinBox.value( ), self.ui.plotImportCheckBox.isChecked() )) #, self))
  646. self.YamlNode.Import["GMR Header"] = self.headerstr
  647. self.YamlNode.Import["opened"] = datetime.datetime.now().isoformat()
  648. self.YamlNode.Import["pulse Type"] = str(self.RAWDataProc.pulseType)
  649. self.YamlNode.Import["stacks"] = self.procStacks.tolist()
  650. self.YamlNode.Import["data channels"] = self.dataChan.tolist()
  651. self.YamlNode.Import["reference channels"] = self.refChan.tolist()
  652. self.YamlNode.Import["pulse records"] = str(self.ui.FIDProcComboBox.currentText())
  653. self.YamlNode.Import["instrument dead time"] = (1e-3 * self.ui.DeadTimeSpinBox.value( ))
  654. self.Log ( )
  655. # should be already done
  656. # QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("updateProgress(int)"), self.updateProgressBar)
  657. # QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("enableDSP()"), self.enableDSP)
  658. # QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("doneStatus()"), self.doneStatus)
  659. self.ui.ProcessedBox.setEnabled(True)
  660. self.ui.lcdNumberFID1Length.setEnabled(1)
  661. self.ui.lcdNumberFID2Length.setEnabled(1)
  662. self.ui.lcdNumberResampFreq.setEnabled(1)
  663. self.ui.lcdTotalDeadTime.setEnabled(1)
  664. self.ui.lcdTotalDeadTime.display( self.ui.DeadTimeSpinBox.value( ) )
  665. #self.ui.lcdNumberFID1Length.display(0)
  666. #self.ui.lcdNumberFID2Length.display(0)
  667. #self.ui.lcdNumberResampFreq.display( self.RAWDataProc.samp )
  668. self.mpl_toolbar = NavigationToolbar2QT(self.ui.mplwidget, self.ui.mplwidget)
  669. self.ui.mplwidget.draw()
  670. def Log(self):
  671. #for line in yaml.dump(self.YamlNode, default_flow_style=False):
  672. #for line in nlogText:
  673. # self.ui.logTextBrowser.append( line )
  674. # self.logText.append( line )
  675. self.ui.logTextBrowser.clear()
  676. self.ui.logTextBrowser.append( yaml.dump(self.YamlNode)) #, default_flow_style=False) )
  677. def disable(self):
  678. self.ui.BandPassBox.setEnabled(False)
  679. self.ui.downSampleGroupBox.setEnabled(False)
  680. self.ui.windowFilterGroupBox.setEnabled(False)
  681. # self.ui.despikeGroupBox.setEnabled(False)
  682. self.ui.adaptBox.setEnabled(False)
  683. self.ui.adaptFDBox.setEnabled(False)
  684. self.ui.qCalcGroupBox.setEnabled(False)
  685. self.ui.FDSmartStackGroupBox.setEnabled(False)
  686. self.ui.sumDataBox.setEnabled(False)
  687. self.ui.qdGroupBox.setEnabled(False)
  688. self.ui.gateBox.setEnabled(False)
  689. def enableAll(self):
  690. self.enableDSP()
  691. self.enableQC()
  692. def enableDSP(self):
  693. # Bandpass filter
  694. self.ui.BandPassBox.setEnabled(True)
  695. self.ui.BandPassBox.setChecked(True)
  696. self.ui.bandPassGO.setEnabled(False) # need to design first
  697. self.ui.plotBP.setEnabled(True)
  698. self.ui.plotBP.setChecked(True)
  699. # downsample
  700. self.ui.downSampleGroupBox.setEnabled(True)
  701. self.ui.downSampleGroupBox.setChecked(True)
  702. # window
  703. self.ui.windowFilterGroupBox.setEnabled(True)
  704. self.ui.windowFilterGroupBox.setChecked(True)
  705. # Despike
  706. # self.ui.despikeGroupBox.setEnabled(True)
  707. # self.ui.despikeGroupBox.setChecked(False)
  708. # Adaptive filtering
  709. self.ui.adaptBox.setEnabled(True)
  710. self.ui.adaptBox.setChecked(True)
  711. # FD Adaptive filtering
  712. self.ui.adaptFDBox.setEnabled(True)
  713. self.ui.adaptFDBox.setChecked(True)
  714. # sum group box
  715. try:
  716. if len(self.dataChan) > 1:
  717. self.ui.sumDataBox.setEnabled(True)
  718. self.ui.sumDataBox.setChecked(True)
  719. except:
  720. pass
  721. # Quadrature Detect
  722. self.ui.qdGroupBox.setEnabled(True)
  723. self.ui.qdGroupBox.setChecked(True)
  724. self.enableQC()
  725. def enableQC(self):
  726. # Q calc
  727. self.ui.qCalcGroupBox.setEnabled(True)
  728. self.ui.qCalcGroupBox.setChecked(True)
  729. # FD SmartStack
  730. self.ui.FDSmartStackGroupBox.setEnabled(True)
  731. self.ui.FDSmartStackGroupBox.setChecked(True)
  732. # Quadrature detect
  733. try:
  734. for pulse in self.RAWDataProc.DATADICT["PULSES"]:
  735. np.shape(self.RAWDataProc.DATADICT[pulse]["Q"])
  736. self.RAWDataProc.DATADICT["stack"]
  737. self.ui.qdGroupBox.setEnabled(True)
  738. self.ui.qdGroupBox.setChecked(True)
  739. except:
  740. self.ui.qdGroupBox.setEnabled(False)
  741. self.ui.qdGroupBox.setChecked(False)
  742. # Gating
  743. try:
  744. self.RAWDataProc.DATADICT["CA"]
  745. self.ui.gateBox.setEnabled(True)
  746. self.ui.gateBox.setChecked(True)
  747. except:
  748. self.ui.gateBox.setEnabled(False)
  749. self.ui.gateBox.setChecked(False)
  750. def despikeFilter(self):
  751. self.lock("despike filter")
  752. thread.start_new_thread(self.RAWDataProc.despike, \
  753. (self.ui.windowSpinBox.value(), \
  754. self.ui.thresholdSpinBox.value(), \
  755. str(self.ui.replComboBox.currentText()), \
  756. self.ui.rollOnSpinBox.value(), \
  757. self.ui.despikeInterpWinSpinBox.value(),
  758. self.ui.mplwidget))
  759. def calcQ(self):
  760. if "Calc Q" not in self.YamlNode.Processing.keys():
  761. self.YamlNode.Processing["Calc Q"] = True
  762. self.Log()
  763. else:
  764. err_msg = "Q values have already been calculated"
  765. reply =QtWidgets.QMessageBox.critical(self, 'Error',
  766. err_msg)
  767. return
  768. self.lock("pulse moment calculation")
  769. thread.start_new_thread(self.RAWDataProc.effectivePulseMoment, \
  770. (self.ui.CentralVSpinBox.value(), \
  771. self.ui.mplwidget_2))
  772. def FDSmartStack(self):
  773. if "TD stack" not in self.YamlNode.Processing.keys():
  774. self.YamlNode.Processing["TD stack"] = {}
  775. self.YamlNode.Processing["TD stack"]["outlier"] = str( self.ui.outlierTestCB.currentText() )
  776. self.YamlNode.Processing["TD stack"]["cutoff"] = str( self.ui.MADCutoff.value() )
  777. self.Log()
  778. else:
  779. err_msg = "TD noise cancellation has already been applied!"
  780. reply =QtWidgets.QMessageBox.critical(self, 'Error',
  781. err_msg)
  782. return
  783. self.lock("time-domain smart stack")
  784. thread.start_new_thread(self.RAWDataProc.TDSmartStack, \
  785. (str(self.ui.outlierTestCB.currentText()), \
  786. self.ui.MADCutoff.value(),
  787. self.ui.mplwidget_2))
  788. def adaptFilter(self):
  789. if "TD noise cancellation" not in self.YamlNode.Processing.keys():
  790. self.YamlNode.Processing["TD noise cancellation"] = {}
  791. self.YamlNode.Processing["TD noise cancellation"]["n_Taps"] = str(self.ui.MTapsSpinBox.value())
  792. self.YamlNode.Processing["TD noise cancellation"]["lambda"] = str(self.ui.adaptLambdaSpinBox.value())
  793. self.YamlNode.Processing["TD noise cancellation"]["truncate"] = str(self.ui.adaptTruncateSpinBox.value())
  794. self.YamlNode.Processing["TD noise cancellation"]["mu"] = str(self.ui.adaptMuSpinBox.value())
  795. self.YamlNode.Processing["TD noise cancellation"]["PCA"] = str(self.ui.PCAComboBox.currentText())
  796. self.Log()
  797. else:
  798. err_msg = "TD noise cancellation has already been applied!"
  799. reply =QtWidgets.QMessageBox.critical(self, 'Error',
  800. err_msg)
  801. return
  802. self.lock("TD noise cancellation filter")
  803. thread.start_new_thread(self.RAWDataProc.adaptiveFilter, \
  804. (self.ui.MTapsSpinBox.value(), \
  805. self.ui.adaptLambdaSpinBox.value(), \
  806. self.ui.adaptTruncateSpinBox.value(), \
  807. self.ui.adaptMuSpinBox.value(), \
  808. str(self.ui.PCAComboBox.currentText()), \
  809. self.ui.mplwidget))
  810. def sumDataChans(self):
  811. if "Data sum" not in self.YamlNode.Processing.keys():
  812. self.YamlNode.Processing["Data sum"] = True
  813. self.Log()
  814. else:
  815. err_msg = "Data channels have already been summed!"
  816. reply =QtWidgets.QMessageBox.critical(self, 'Error',
  817. err_msg)
  818. return
  819. self.lock("Summing data channels")
  820. self.dataChan = [self.dataChan[0]]
  821. self.ui.sumDataBox.setEnabled(False)
  822. thread.start_new_thread( self.RAWDataProc.sumData, ( self.ui.mplwidget, 7 ) )
  823. def adaptFilterFD(self):
  824. self.lock("FD noise cancellation filter")
  825. thread.start_new_thread(self.RAWDataProc.adaptiveFilterFD, \
  826. (str(self.ui.windowTypeComboBox.currentText()), \
  827. self.ui.windowBandwidthSpinBox.value(), \
  828. self.ui.CentralVSpinBox.value(), \
  829. self.ui.mplwidget))
  830. def bandPassFilter(self):
  831. if "Bandpass filter" not in self.YamlNode.Processing.keys():
  832. self.YamlNode.Processing["Bandpass filter"] = {}
  833. self.YamlNode.Processing["Bandpass filter"]["central_nu"] = str(self.ui.CentralVSpinBox.value())
  834. self.YamlNode.Processing["Bandpass filter"]["passband"] = str(self.ui.passBandSpinBox.value())
  835. self.YamlNode.Processing["Bandpass filter"]["stopband"] = str(self.ui.stopBandSpinBox.value())
  836. self.YamlNode.Processing["Bandpass filter"]["gpass"] = str(self.ui.gpassSpinBox.value())
  837. self.YamlNode.Processing["Bandpass filter"]["gstop"] = str(self.ui.gstopSpinBox.value())
  838. self.YamlNode.Processing["Bandpass filter"]["type"] = str(self.ui.fTypeComboBox.currentText())
  839. self.Log()
  840. else:
  841. err_msg = "Bandpass filter has already been applied!"
  842. reply =QtWidgets.QMessageBox.critical(self, 'Error',
  843. err_msg)
  844. return
  845. self.lock("bandpass filter")
  846. nv = self.ui.lcdTotalDeadTime.value( ) + self.ui.lcdNumberFTauDead.value()
  847. self.ui.lcdTotalDeadTime.display( nv )
  848. thread.start_new_thread(self.RAWDataProc.bandpassFilter, \
  849. (self.ui.mplwidget, 0, self.ui.plotBP.isChecked() ))
  850. def downsample(self):
  851. self.lock("resampling")
  852. if "Resample" not in self.YamlNode.Processing.keys():
  853. self.YamlNode.Processing["Resample"] = {}
  854. self.YamlNode.Processing["Resample"]["downsample factor"] = []
  855. self.YamlNode.Processing["Resample"]["truncate length"] = []
  856. self.YamlNode.Processing["Resample"]["downsample factor"].append( str(self.ui.downSampleSpinBox.value() ) )
  857. self.YamlNode.Processing["Resample"]["truncate length"].append( str( self.ui.truncateSpinBox.value() ) )
  858. self.Log( )
  859. thread.start_new_thread(self.RAWDataProc.downsample, \
  860. (self.ui.truncateSpinBox.value(), \
  861. self.ui.downSampleSpinBox.value(),
  862. self.ui.mplwidget))
  863. def quadDet(self):
  864. if "Quadrature detection" not in self.YamlNode.Processing.keys():
  865. self.YamlNode.Processing["Quadrature detection"] = {}
  866. self.YamlNode.Processing["Quadrature detection"]["trim"] = str( self.ui.trimSpin.value() )
  867. self.Log()
  868. else:
  869. err_msg = "Quadrature detection has already been done!"
  870. reply =QtWidgets.QMessageBox.critical(self, 'Error',
  871. err_msg)
  872. return
  873. self.lock("quadrature detection")
  874. thread.start_new_thread(self.RAWDataProc.quadDet, \
  875. (self.ui.trimSpin.value(), int(self.ui.QDType.currentIndex()), self.ui.mplwidget_2))
  876. self.ui.plotQD.setEnabled(True)
  877. def plotQD(self):
  878. self.lock("plot QD")
  879. thread.start_new_thread(self.RAWDataProc.plotQuadDet, \
  880. (self.ui.trimSpin.value(), int(self.ui.QDType.currentIndex()), self.ui.mplwidget_2))
  881. def gateIntegrate(self):
  882. if "Gate integrate" not in self.YamlNode.Processing.keys():
  883. self.YamlNode.Processing["Gate integrate"] = {}
  884. self.YamlNode.Processing["Gate integrate"]["gpd"] = str(self.ui.GPDspinBox.value( ) )
  885. self.Log()
  886. self.lock("gate integration")
  887. thread.start_new_thread(self.RAWDataProc.gateIntegrate, \
  888. (self.ui.GPDspinBox.value(), self.ui.trimSpin.value(), self.ui.mplwidget_2))
  889. self.ui.actionExport_Preprocessed_Dataset.setEnabled(True)
  890. self.ui.plotGI.setEnabled(True)
  891. def plotGI(self):
  892. self.lock("plot gate integrate")
  893. thread.start_new_thread(self.RAWDataProc.plotGateIntegrate, \
  894. (self.ui.GPDspinBox.value(), self.ui.trimSpin.value(), \
  895. self.ui.QDType_2.currentIndex(), self.ui.mplwidget_2))
  896. def designFilter(self):
  897. [bord, fe] = self.RAWDataProc.designFilter( \
  898. self.ui.CentralVSpinBox.value(), \
  899. self.ui.passBandSpinBox.value(), \
  900. self.ui.stopBandSpinBox.value(), \
  901. self.ui.gpassSpinBox.value(), \
  902. self.ui.gstopSpinBox.value(), \
  903. str(self.ui.fTypeComboBox.currentText()),
  904. self.ui.mplwidget)
  905. self.ui.lcdNumberFilterOrder.display(bord)
  906. self.ui.lcdNumberFTauDead.display(1e3*fe)
  907. #self.ui.lcdNumberFilterOrder.display(bord)
  908. self.ui.bandPassGO.setEnabled(1)
  909. # self.ui.lcdNumberTauPulse2.display(1e3*self.RAWDataProc.pulseLength[1])
  910. def windowFilter(self):
  911. if "Window filter" not in self.YamlNode.Processing.keys():
  912. self.YamlNode.Processing["Window filter"] = {}
  913. self.YamlNode.Processing["Window filter"]["type"] = str(self.ui.windowTypeComboBox.currentText())
  914. self.YamlNode.Processing["Window filter"]["width"] = str(self.ui.windowBandwidthSpinBox.value())
  915. self.YamlNode.Processing["Window filter"]["centre"] = str(self.ui.CentralVSpinBox.value() )
  916. self.Log()
  917. else:
  918. err_msg = "FD window has already been applied!"
  919. reply =QtWidgets.QMessageBox.critical(self, 'Error',
  920. err_msg)
  921. return
  922. self.lock("window filter")
  923. thread.start_new_thread(self.RAWDataProc.windowFilter, \
  924. (str(self.ui.windowTypeComboBox.currentText()), \
  925. self.ui.windowBandwidthSpinBox.value(), \
  926. self.ui.CentralVSpinBox.value(), \
  927. self.ui.mplwidget))
  928. def designFDFilter(self):
  929. # thread.start_new_thread(self.RAWDataProc.computeWindow, ( \
  930. # "Pulse 1",
  931. # self.ui.windowBandwidthSpinBox.value(), \
  932. # self.ui.CentralVSpinBox.value(), \
  933. # str(self.ui.windowTypeComboBox.currentText()), \
  934. # self.ui.mplwidget ))
  935. a,b,c,d,dead = self.RAWDataProc.computeWindow( \
  936. "Pulse 1",
  937. self.ui.windowBandwidthSpinBox.value(), \
  938. self.ui.CentralVSpinBox.value(), \
  939. str(self.ui.windowTypeComboBox.currentText()), \
  940. self.ui.mplwidget )
  941. self.ui.lcdWinDead.display(dead)
  942. def updateProgressBar(self, percent):
  943. self.ui.barProgress.setValue(percent)
  944. def updateProc(self):
  945. if str(self.ui.FIDProcComboBox.currentText()) == "Pulse 1":
  946. self.ui.lcdNumberFID1Length.display(self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][-1]- self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][0])
  947. elif str(self.ui.FIDProcComboBox.currentText()) == "Pulse 2":
  948. self.ui.lcdNumberFID2Length.display(self.RAWDataProc.DATADICT["Pulse 2"]["TIMES"][-1]- self.RAWDataProc.DATADICT["Pulse 2"]["TIMES"][0])
  949. else:
  950. self.ui.lcdNumberFID1Length.display(self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][-1]- self.RAWDataProc.DATADICT["Pulse 1"]["TIMES"][0])
  951. self.ui.lcdNumberFID2Length.display(self.RAWDataProc.DATADICT["Pulse 2"]["TIMES"][-1]- self.RAWDataProc.DATADICT["Pulse 2"]["TIMES"][0])
  952. self.ui.lcdNumberResampFreq.display( self.RAWDataProc.samp )
  953. def doneStatus(self): # unlocks GUI
  954. self.ui.statusbar.clearMessage ( )
  955. self.ui.barProgress.hide()
  956. self.updateProc()
  957. self.enableAll()
  958. def lock(self, string):
  959. self.ui.statusbar.showMessage ( string )
  960. self.ui.barProgress.show()
  961. self.ui.barProgress.setValue(0)
  962. self.disable()
  963. def unlock(self):
  964. self.ui.statusbar.clearMessage ( )
  965. self.ui.barProgress.hide()
  966. self.enableAll()
  967. def done(self):
  968. self.ui.statusbar.showMessage ( "" )
  969. ################################################################
  970. ################################################################
  971. # Boiler plate main function
  972. import pkg_resources
  973. from pkg_resources import resource_string
  974. import matplotlib.image as mpimg
  975. import matplotlib.pyplot as plt
  976. def main():
  977. # splash screen logo
  978. logo = pkg_resources.resource_filename(__name__, 'akvo.png')
  979. logo2 = pkg_resources.resource_filename(__name__, 'akvo2.png')
  980. qApp = QtWidgets.QApplication(sys.argv)
  981. ssplash = False
  982. if ssplash:
  983. pixmap = QtGui.QPixmap(logo)
  984. splash = QtWidgets.QSplashScreen(pixmap, QtCore.Qt.WindowStaysOnTopHint)
  985. splash.show()
  986. aw = ApplicationWindow()
  987. img=mpimg.imread(logo)
  988. for ax in [ aw.ui.mplwidget ]:
  989. ax.fig.clear()
  990. subplot = ax.fig.add_subplot(111)
  991. ax.fig.patch.set_facecolor( None )
  992. ax.fig.patch.set_alpha( .0 )
  993. subplot.imshow(img)
  994. subplot.xaxis.set_major_locator(plt.NullLocator())
  995. subplot.yaxis.set_major_locator(plt.NullLocator())
  996. ax.draw()
  997. if ssplash:
  998. splash.showMessage("Loading modules")
  999. splash.finish(aw)
  1000. #time.sleep(1)
  1001. aw.setWindowTitle("Akvo v"+str(version))
  1002. aw.show()
  1003. qApp.setWindowIcon(QtGui.QIcon(logo2))
  1004. sys.exit(qApp.exec_())
  1005. if __name__ == "__main__":
  1006. main()