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

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