Browse Source

Rework of yaml log of processing steps. The log is now a flow of steps, any of which can be repeated. Additionally, plotting of the harmonic modelling has been changed to frequency domain.

tags/1.6.1
Trevor Irons 4 years ago
parent
commit
67c74fc49e
5 changed files with 579 additions and 429 deletions
  1. 133
    108
      akvo/gui/akvoGUI.py
  2. 324
    233
      akvo/gui/main.ui
  3. 39
    33
      akvo/tressel/harmonic.py
  4. 82
    54
      akvo/tressel/mrsurvey.py
  5. 1
    1
      setup.py

+ 133
- 108
akvo/gui/akvoGUI.py View File

@@ -17,7 +17,7 @@ each time you launch Akvo.
17 17
 """
18 18
 
19 19
 import matplotlib
20
-#matplotlib.use("QT4Agg")
20
+matplotlib.use("QT5Agg")
21 21
 from PyQt5 import QtCore, QtGui, QtWidgets
22 22
 
23 23
 import numpy as np
@@ -81,16 +81,16 @@ class AkvoYamlNode(yaml.YAMLObject):
81 81
     def __init__(self):
82 82
         self.Akvo_VERSION = version
83 83
         self.Import = OrderedDict() # {}
84
-        self.Processing = OrderedDict() 
84
+        self.Processing = [] # OrderedDict() 
85
+        self.Stacking = OrderedDict() 
85 86
     #def __init__(self, node):
86 87
     #    self.Akvo_VERSION = node["version"]
87 88
     #    self.Import = OrderedDict( node["Import"] ) # {}
88 89
     #    self.Processing = OrderedDict( node["Processing"] ) 
89 90
     def __repr__(self):
90 91
         return "%s(name=%r, Akvo_VERSION=%r, Import=%r, Processing=%r)" % (
91
-            #self.__class__.__name__, self.Akvo_VERSION, self.Import, self.Processing )
92
-            self.__class__.__name__, self.Akvo_VERSION, self.Import, OrderedDict(self.Processing) ) 
93
-            #self.__class__.__name__, self.Akvo_VERSION, self.Import, OrderedDict(self.Processing)) 
92
+            self.__class__.__name__, self.Akvo_VERSION, self.Import, self.Processing, self.Stacking )
93
+            #self.__class__.__name__, self.Akvo_VERSION, self.Import, OrderedDict(self.Processing) ) 
94 94
     
95 95
 try:    
96 96
     import thread 
@@ -141,14 +141,17 @@ class ApplicationWindow(QtWidgets.QMainWindow):
141 141
         self.ui.lcdNumberTauDelay.setEnabled(0)
142 142
         self.ui.lcdNumberNQ.setEnabled(0)
143 143
 
144
-        #MAK 20170126: add in a list to hold processing steps
145 144
         self.logText = []      
146 145
 
147
-        ####################
148
-        # Make connections #
149
-        ####################
146
+        #######################
147
+        ##################### #
148
+        ## Make connections # #
149
+        ##################### #
150
+        #######################
150 151
 
151
-        # Menu items 
152
+        ##############
153
+        # Menu items #
154
+        ##############
152 155
         self.ui.actionOpen_GMR.triggered.connect(self.openGMRRAWDataset)
153 156
         self.ui.actionSave_Preprocessed_Dataset.triggered.connect(self.SavePreprocess)
154 157
         self.ui.actionExport_Preprocessed_Dataset.triggered.connect(self.ExportPreprocess)
@@ -156,7 +159,9 @@ class ApplicationWindow(QtWidgets.QMainWindow):
156 159
         self.ui.actionOpen_Preprocessed_Dataset.triggered.connect(self.OpenPreprocess)
157 160
         self.ui.actionAboutAkvo.triggered.connect(self.about)
158 161
 
159
-        # Buttons
162
+        ###########
163
+        # Buttons #
164
+        ###########
160 165
 #         #QtCore.QObject.connect(self.ui.fullWorkflowPushButton, QtCore.SIGNAL("clicked()"), self.preprocess )
161 166
         self.ui.loadDataPushButton.pressed.connect(self.loadRAW) 
162 167
         self.ui.sumDataGO.pressed.connect( self.sumDataChans )
@@ -812,7 +817,9 @@ class ApplicationWindow(QtWidgets.QMainWindow):
812 817
 
813 818
         self.YamlNode.Import = OrderedDict((yaml.load( self.logText, Loader=yaml.Loader )).Import)
814 819
         self.YamlNode.Processing = OrderedDict((yaml.load( self.logText, Loader=yaml.Loader )).Processing)
815
-        self.Log() 
820
+        self.YamlNode.Stacking = OrderedDict((yaml.load( self.logText, Loader=yaml.Loader )).Stacking)
821
+        self.Log()
822
+ 
816 823
             #self.ui.logTextBrowser.append( yaml.dump(self.YamlNode)) #, default_flow_style=False)  )
817 824
         #except KeyError:
818 825
         #    pass
@@ -1128,9 +1135,9 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1128 1135
                 self.ui.mplwidget))
1129 1136
 
1130 1137
     def calcQ(self):
1131
-        if "Calc Q" not in self.YamlNode.Processing.keys():
1138
+        if "Calc Q" not in self.YamlNode.Stacking.keys():
1132 1139
             #print("In CalcQ", yaml.dump(self.YamlNode.Processing)  )
1133
-            self.YamlNode.Processing["Calc Q"] = True
1140
+            self.YamlNode.Stacking["Calc Q"] = True
1134 1141
             #print( yaml.dump(self.YamlNode.Processing)  )
1135 1142
             self.Log()
1136 1143
         else:
@@ -1145,28 +1152,41 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1145 1152
                 self.ui.mplwidget))
1146 1153
 
1147 1154
     def harmonicModel(self):
1148
-
1149
-        if "Harmonic modelling" not in self.YamlNode.Processing.keys():
1150
-            self.YamlNode.Processing["Harmonic modelling"] = {}
1151
-            self.YamlNode.Processing["Harmonic modelling"]["NF"] = str( self.ui.NHarmonicsFreqsSpin.value() ) 
1152
-            self.YamlNode.Processing["Harmonic modelling"]["Segments"] = str( self.ui.NSegments.value() ) 
1153
-            self.YamlNode.Processing["Harmonic modelling"]["f0K1"] = str( self.ui.f0K1Spin.value() )
1154
-            self.YamlNode.Processing["Harmonic modelling"]["f0KN"] = str( self.ui.f0KNSpin.value() )
1155
-            self.YamlNode.Processing["Harmonic modelling"]["f0Ks"] = str( self.ui.f0KsSpin.value() )
1156
-            self.YamlNode.Processing["Harmonic modelling"]["f0"] = str( self.ui.f0Spin.value() )
1157
-            if self.ui.NHarmonicsFreqsSpin.value() > 1:
1158
-                self.YamlNode.Processing["Harmonic modelling"]["f1K1"] = str( self.ui.f1K1Spin.value() )
1159
-                self.YamlNode.Processing["Harmonic modelling"]["f1KN"] = str( self.ui.f1KNSpin.value() )
1160
-                self.YamlNode.Processing["Harmonic modelling"]["f1Ks"] = str( self.ui.f1KsSpin.value() )
1161
-                self.YamlNode.Processing["Harmonic modelling"]["f1"] = str( self.ui.f1Spin.value() )
1162
-            self.Log()
1163
-        #else:
1164
-        #    err_msg = "Harmonic modelling noise cancellation has already been applied!"
1165
-        #    reply = QtWidgets.QMessageBox.critical(self, 'Error', 
1166
-        #        err_msg) 
1167
-        #    return 
1168
-
1155
+        
1169 1156
         self.lock("harmonic noise modelling")
1157
+        
1158
+        Harm = OrderedDict()
1159
+        Harm["STEP"] = "Harmonic modelling"
1160
+        Harm["NF"] = str( self.ui.NHarmonicsFreqsSpin.value() ) 
1161
+        Harm["Segments"] = str( self.ui.NSegments.value() ) 
1162
+        Harm["Proc. ref."] = self.ui.harmRef.isChecked() 
1163
+        
1164
+        
1165
+        if self.ui.searchAll.currentText() == "All":
1166
+            Harm["search"] = self.ui.searchAll.currentText()
1167
+            Search = False  
1168
+        else:
1169
+            #Harm["search"] = self.ui.searchAll.currentText() 
1170
+            Harm["search"] = str(self.ui.Nsearch.value()) 
1171
+            Search = self.ui.Nsearch.value() 
1172
+        if self.ui.boundsCheck.isChecked():
1173
+            Harm["Bounds"] = str(self.ui.bounds.value()) 
1174
+            Bounds = self.ui.bounds.value() 
1175
+        else:
1176
+            Harm["Bounds"] = self.ui.boundsCheck.isChecked() 
1177
+            Bounds = 0
1178
+
1179
+        Harm["f0K1"] = str( self.ui.f0K1Spin.value() )
1180
+        Harm["f0KN"] = str( self.ui.f0KNSpin.value() )
1181
+        Harm["f0Ks"] = str( self.ui.f0KsSpin.value() )
1182
+        Harm["f0"] = str( self.ui.f0Spin.value() )
1183
+        if self.ui.NHarmonicsFreqsSpin.value() > 1:
1184
+            Harm["f1K1"] = str( self.ui.f1K1Spin.value() )
1185
+            Harm["f1KN"] = str( self.ui.f1KNSpin.value() )
1186
+            Harm["f1Ks"] = str( self.ui.f1KsSpin.value() )
1187
+            Harm["f1"] = str( self.ui.f1Spin.value() )
1188
+        self.YamlNode.Processing.append(Harm)
1189
+        self.Log()
1170 1190
 
1171 1191
         thread.start_new_thread(self.RAWDataProc.harmonicModel, \
1172 1192
                 ( \
@@ -1180,6 +1200,9 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1180 1200
                  self.ui.f1K1Spin.value(), \
1181 1201
                  self.ui.f1KNSpin.value(), \
1182 1202
                  self.ui.f1KsSpin.value(), \
1203
+                 Search, \
1204
+                 Bounds, \
1205
+                 self.ui.harmRef.isChecked(), \
1183 1206
                  self.ui.plotHarmonic.isChecked(), \
1184 1207
                  self.ui.mplwidget \
1185 1208
                 ) \
@@ -1187,10 +1210,10 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1187 1210
 
1188 1211
     def FDSmartStack(self):
1189 1212
 
1190
-        if "TD stack" not in self.YamlNode.Processing.keys():
1191
-            self.YamlNode.Processing["TD stack"] = {}
1192
-            self.YamlNode.Processing["TD stack"]["outlier"] = str( self.ui.outlierTestCB.currentText() ) 
1193
-            self.YamlNode.Processing["TD stack"]["cutoff"] = str( self.ui.MADCutoff.value() )
1213
+        if "TD stack" not in self.YamlNode.Stacking.keys():
1214
+            self.YamlNode.Stacking["TD stack"] = {}
1215
+            self.YamlNode.Stacking["TD stack"]["outlier"] = str( self.ui.outlierTestCB.currentText() ) 
1216
+            self.YamlNode.Stacking["TD stack"]["cutoff"] = str( self.ui.MADCutoff.value() )
1194 1217
             self.Log()
1195 1218
         else:
1196 1219
             err_msg = "TD noise cancellation has already been applied!"
@@ -1205,21 +1228,20 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1205 1228
                 self.ui.mplwidget))
1206 1229
 
1207 1230
     def adaptFilter(self):
1208
-
1209
-        if "TD noise cancellation" not in self.YamlNode.Processing.keys():
1210
-            self.YamlNode.Processing["TD noise cancellation"] = {}
1211
-            self.YamlNode.Processing["TD noise cancellation"]["n_Taps"] = str(self.ui.MTapsSpinBox.value())
1212
-            self.YamlNode.Processing["TD noise cancellation"]["lambda"] = str(self.ui.adaptLambdaSpinBox.value())
1213
-            self.YamlNode.Processing["TD noise cancellation"]["truncate"] = str(self.ui.adaptTruncateSpinBox.value())
1214
-            self.YamlNode.Processing["TD noise cancellation"]["mu"] = str(self.ui.adaptMuSpinBox.value()) 
1215
-            self.YamlNode.Processing["TD noise cancellation"]["PCA"] = str(self.ui.PCAComboBox.currentText())
1216
-            self.Log()
1217
-        else:
1218
-            err_msg = "TD noise cancellation has already been applied!"
1219
-            reply =QtWidgets.QMessageBox.critical(self, 'Error', err_msg) 
1220
-            #return 
1221 1231
         
1222 1232
         self.lock("TD noise cancellation filter")
1233
+        
1234
+        # Log processing 
1235
+        Adapt = OrderedDict()
1236
+        Adapt["STEP"] = "TD noise cancellation"
1237
+        Adapt["n_Taps"] = str(self.ui.MTapsSpinBox.value())
1238
+        Adapt["lambda"] = str(self.ui.adaptLambdaSpinBox.value())
1239
+        Adapt["truncate"] = str(self.ui.adaptTruncateSpinBox.value())
1240
+        Adapt["mu"] = str(self.ui.adaptMuSpinBox.value()) 
1241
+        Adapt["PCA"] = str(self.ui.PCAComboBox.currentText())
1242
+        self.YamlNode.Processing.append(Adapt)
1243
+        self.Log( )
1244
+
1223 1245
         thread.start_new_thread(self.RAWDataProc.adaptiveFilter, \
1224 1246
                 (self.ui.MTapsSpinBox.value(), \
1225 1247
                 self.ui.adaptLambdaSpinBox.value(), \
@@ -1230,16 +1252,13 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1230 1252
 
1231 1253
     def sumDataChans(self): 
1232 1254
 
1233
-        if "Data sum" not in self.YamlNode.Processing.keys():
1234
-            self.YamlNode.Processing["Data sum"] = True
1235
-            self.Log()
1236
-        else:
1237
-            err_msg = "Data channels have already been summed!"
1238
-            reply =QtWidgets.QMessageBox.critical(self, 'Error', 
1239
-                err_msg) 
1240
-            return 
1241
-
1242 1255
         self.lock("Summing data channels")
1256
+        
1257
+        Sum = OrderedDict()
1258
+        Sum["STEP"] = "Channel sum"
1259
+        self.YamlNode.Processing.append(Sum)
1260
+        self.Log( )
1261
+
1243 1262
         self.dataChan = [self.dataChan[0]]
1244 1263
         self.ui.sumDataBox.setEnabled(False)    
1245 1264
         thread.start_new_thread( self.RAWDataProc.sumData, ( self.ui.mplwidget, 7 ) )
@@ -1253,35 +1272,36 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1253 1272
                 self.ui.mplwidget))
1254 1273
 
1255 1274
     def bandPassFilter(self):
1256
-        if "Bandpass filter" not in self.YamlNode.Processing.keys():
1257
-            self.YamlNode.Processing["Bandpass filter"] = {}
1258
-            self.YamlNode.Processing["Bandpass filter"]["central_nu"] = str(self.ui.CentralVSpinBox.value())
1259
-            self.YamlNode.Processing["Bandpass filter"]["passband"] = str(self.ui.passBandSpinBox.value())
1260
-            self.YamlNode.Processing["Bandpass filter"]["stopband"] = str(self.ui.stopBandSpinBox.value()) 
1261
-            self.YamlNode.Processing["Bandpass filter"]["gpass"] = str(self.ui.gpassSpinBox.value())
1262
-            self.YamlNode.Processing["Bandpass filter"]["gstop"] = str(self.ui.gstopSpinBox.value())
1263
-            self.YamlNode.Processing["Bandpass filter"]["type"] = str(self.ui.fTypeComboBox.currentText())
1264
-            self.Log()
1265
-        else:
1266
-            err_msg = "Bandpass filter has already been applied!"
1267
-            reply =QtWidgets.QMessageBox.critical(self, 'Error', 
1268
-                err_msg) 
1269
-            return 
1275
+        
1270 1276
         self.lock("bandpass filter")        
1277
+        
1278
+        # Log processing 
1279
+        Band = OrderedDict()
1280
+        Band["STEP"] = "Bandpass filter"
1281
+        Band["central_nu"] = str(self.ui.CentralVSpinBox.value())
1282
+        Band["passband"] = str(self.ui.passBandSpinBox.value())
1283
+        Band["stopband"] = str(self.ui.stopBandSpinBox.value()) 
1284
+        Band["gpass"] = str(self.ui.gpassSpinBox.value())
1285
+        Band["gstop"] = str(self.ui.gstopSpinBox.value())
1286
+        Band["type"] = str(self.ui.fTypeComboBox.currentText())
1287
+        self.YamlNode.Processing.append(Band)
1288
+        self.Log( )
1289
+
1271 1290
         nv = self.ui.lcdTotalDeadTime.value( ) + self.ui.lcdNumberFTauDead.value()
1272 1291
         self.ui.lcdTotalDeadTime.display( nv )
1273 1292
         thread.start_new_thread(self.RAWDataProc.bandpassFilter, \
1274 1293
                 (self.ui.mplwidget, 0, self.ui.plotBP.isChecked() ))
1275 1294
 
1276 1295
     def downsample(self):
1296
+
1277 1297
         self.lock("resampling")
1278
-        
1279
-        if "Resample" not in self.YamlNode.Processing.keys():
1280
-            self.YamlNode.Processing["Resample"] = {}
1281
-            self.YamlNode.Processing["Resample"]["downsample factor"] = [] 
1282
-            self.YamlNode.Processing["Resample"]["truncate length"] = []  
1283
-        self.YamlNode.Processing["Resample"]["downsample factor"].append( str(self.ui.downSampleSpinBox.value() ) )
1284
-        self.YamlNode.Processing["Resample"]["truncate length"].append(  str( self.ui.truncateSpinBox.value() ) )
1298
+
1299
+        # Log processing 
1300
+        Resample = OrderedDict() 
1301
+        Resample["STEP"] = "Resample"
1302
+        Resample["downsample factor"] = str(self.ui.downSampleSpinBox.value())
1303
+        Resample["truncate length"] = str(self.ui.truncateSpinBox.value()) 
1304
+        self.YamlNode.Processing.append(Resample)
1285 1305
         self.Log( )
1286 1306
         
1287 1307
         thread.start_new_thread(self.RAWDataProc.downsample, \
@@ -1295,12 +1315,11 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1295 1315
         method = ['trf','dogbox','lm'][int(self.ui.QDMethod.currentIndex())]
1296 1316
         loss = ['linear','soft_l1','cauchy','huber'][int(self.ui.QDLoss.currentIndex())]         
1297 1317
 
1298
-
1299 1318
         # allow overwrite of Quad Det.    
1300
-        self.YamlNode.Processing["Quadrature detection"] = {}
1301
-        self.YamlNode.Processing["Quadrature detection"]["trim"] = str( self.ui.trimSpin.value() )
1302
-        self.YamlNode.Processing["Quadrature detection"]["method"] = method 
1303
-        self.YamlNode.Processing["Quadrature detection"]["loss"] = loss
1319
+        self.YamlNode.Stacking["Quadrature detection"] = {}
1320
+        self.YamlNode.Stacking["Quadrature detection"]["trim"] = str( self.ui.trimSpin.value() )
1321
+        self.YamlNode.Stacking["Quadrature detection"]["method"] = method 
1322
+        self.YamlNode.Stacking["Quadrature detection"]["loss"] = loss
1304 1323
         self.Log()
1305 1324
 
1306 1325
         #if "Quadrature detection" not in self.YamlNode.Processing.keys():
@@ -1330,9 +1349,9 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1330 1349
 
1331 1350
     def gateIntegrate(self):
1332 1351
         
1333
-        if "Gate integrate" not in self.YamlNode.Processing.keys():
1334
-            self.YamlNode.Processing["Gate integrate"] = {}
1335
-        self.YamlNode.Processing["Gate integrate"]["gpd"] = str(self.ui.GPDspinBox.value( ) )
1352
+        if "Gate integrate" not in self.YamlNode.Stacking.keys():
1353
+            self.YamlNode.Stacking["Gate integrate"] = {}
1354
+        self.YamlNode.Stacking["Gate integrate"]["gpd"] = str(self.ui.GPDspinBox.value( ) )
1336 1355
         self.Log()
1337 1356
  
1338 1357
         self.lock("gate integration")
@@ -1361,7 +1380,11 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1361 1380
         self.ui.lcdNumberFilterOrder.display(bord)
1362 1381
         self.ui.lcdNumberFTauDead.display(1e3*fe)
1363 1382
         self.ui.bandPassGO.setEnabled(1)
1383
+
1384
+        ################################################################
1364 1385
         # Hack for MacOS to force refresh of group box and plot
1386
+        # this has an undesirable effect that it causes the groupbox to 'jump' up
1387
+        # TODO come up with a better solution  
1365 1388
         self.ui.mplwidget.hide()
1366 1389
         self.ui.mplwidget.show()
1367 1390
         self.ui.BandPassBox.hide()
@@ -1369,39 +1392,37 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1369 1392
  
1370 1393
     def windowFilter(self):
1371 1394
         
1372
-        if "Window filter" not in self.YamlNode.Processing.keys():
1373
-            self.YamlNode.Processing["Window filter"] = {}
1374
-            self.YamlNode.Processing["Window filter"]["type"] = str(self.ui.windowTypeComboBox.currentText()) 
1375
-            self.YamlNode.Processing["Window filter"]["width"] = str(self.ui.windowBandwidthSpinBox.value()) 
1376
-            self.YamlNode.Processing["Window filter"]["centre"] = str(self.ui.CentralVSpinBox.value() )
1377
-            self.Log()
1378
-        else:
1379
-            err_msg = "FD window has already been applied!"
1380
-            reply =QtWidgets.QMessageBox.critical(self, 'Error', 
1381
-                err_msg) 
1382
-            return 
1383 1395
         self.lock("window filter")
1384 1396
         
1397
+        # Log processing 
1398
+        Window = OrderedDict()
1399
+        Window["STEP"] = "Window filter"
1400
+        Window["type"] = str(self.ui.windowTypeComboBox.currentText()) 
1401
+        Window["width"] = str(self.ui.windowBandwidthSpinBox.value()) 
1402
+        Window["centre"] = str(self.ui.CentralVSpinBox.value() )
1403
+        Window["trim"] = str(self.ui.windowTrim.isChecked())
1404
+        self.YamlNode.Processing.append(Window)
1405
+        self.Log( )
1406
+        
1407
+        if self.ui.windowTrim.isChecked():
1408
+            nv = self.ui.lcdTotalDeadTime.value( ) + self.ui.lcdWinDead.value()
1409
+            self.ui.lcdTotalDeadTime.display( nv )
1410
+        
1385 1411
         thread.start_new_thread(self.RAWDataProc.windowFilter, \
1386 1412
                 (str(self.ui.windowTypeComboBox.currentText()), \
1387 1413
                 self.ui.windowBandwidthSpinBox.value(), \
1388 1414
                 self.ui.CentralVSpinBox.value(), \
1415
+                self.ui.windowTrim.isChecked(), \
1389 1416
                 self.ui.mplwidget))
1390 1417
 
1391 1418
     def designFDFilter(self):
1392
-#         thread.start_new_thread(self.RAWDataProc.computeWindow, ( \
1393
-#                 "Pulse 1",
1394
-#                 self.ui.windowBandwidthSpinBox.value(), \
1395
-#                 self.ui.CentralVSpinBox.value(), \
1396
-#                 str(self.ui.windowTypeComboBox.currentText()), \
1397
-#                 self.ui.mplwidget ))
1398 1419
 
1399 1420
         mPulse = "None"
1400 1421
         if u"Pulse 1" in self.RAWDataProc.DATADICT.keys():
1401 1422
             mPulse = u"Pulse 1"
1402 1423
         elif u"Pulse 2" in self.RAWDataProc.DATADICT.keys():
1403 1424
             mPulse = u"Pulse 2"
1404
-        a,b,c,d,dead = self.RAWDataProc.computeWindow( \
1425
+        a,b,c,d,dead,ndead = self.RAWDataProc.computeWindow( \
1405 1426
                 mPulse,
1406 1427
                 self.ui.windowBandwidthSpinBox.value(), \
1407 1428
                 self.ui.CentralVSpinBox.value(), \
@@ -1409,7 +1430,11 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1409 1430
                 self.ui.mplwidget )
1410 1431
 
1411 1432
         self.ui.lcdWinDead.display(dead)
1433
+
1434
+        ################################################################
1412 1435
         # Hack for MacOS to force refresh of group box and plot
1436
+        # this has an undesirable effect that it causes the groupbox to 'jump' up
1437
+        # TODO come up with a better solution  
1413 1438
         self.ui.mplwidget.hide()
1414 1439
         self.ui.mplwidget.show()
1415 1440
         self.ui.windowFilterGroupBox.hide()

+ 324
- 233
akvo/gui/main.ui View File

@@ -355,13 +355,6 @@
355 355
                <bool>true</bool>
356 356
               </property>
357 357
               <layout class="QGridLayout" name="gridLayout_5">
358
-               <item row="0" column="0">
359
-                <widget class="QLabel" name="label_3">
360
-                 <property name="text">
361
-                  <string>Truncate [ms]</string>
362
-                 </property>
363
-                </widget>
364
-               </item>
365 358
                <item row="0" column="1">
366 359
                 <widget class="QSpinBox" name="truncateSpinBox">
367 360
                  <property name="maximumSize">
@@ -381,10 +374,10 @@
381 374
                  </property>
382 375
                 </widget>
383 376
                </item>
384
-               <item row="1" column="0">
385
-                <widget class="QLabel" name="label_12">
377
+               <item row="0" column="0">
378
+                <widget class="QLabel" name="label_3">
386 379
                  <property name="text">
387
-                  <string>Downsample factor</string>
380
+                  <string>Truncate [ms]</string>
388 381
                  </property>
389 382
                 </widget>
390 383
                </item>
@@ -407,6 +400,13 @@
407 400
                  </property>
408 401
                 </widget>
409 402
                </item>
403
+               <item row="1" column="0">
404
+                <widget class="QLabel" name="label_12">
405
+                 <property name="text">
406
+                  <string>Downsample factor</string>
407
+                 </property>
408
+                </widget>
409
+               </item>
410 410
                <item row="1" column="2">
411 411
                 <widget class="QPushButton" name="downSampleGO">
412 412
                  <property name="styleSheet">
@@ -466,27 +466,20 @@
466 466
                <bool>true</bool>
467 467
               </property>
468 468
               <layout class="QGridLayout" name="gridLayout_6">
469
-               <item row="4" column="1">
470
-                <widget class="QLCDNumber" name="lcdWinDead">
471
-                 <property name="sizePolicy">
472
-                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
473
-                   <horstretch>0</horstretch>
474
-                   <verstretch>0</verstretch>
475
-                  </sizepolicy>
469
+               <item row="4" column="0">
470
+                <widget class="QLabel" name="label_55">
471
+                 <property name="text">
472
+                  <string>dead time [ms]</string>
476 473
                  </property>
474
+                </widget>
475
+               </item>
476
+               <item row="1" column="3">
477
+                <widget class="QPushButton" name="fdDesignPushButton">
477 478
                  <property name="styleSheet">
478
-                  <string notr="true">#lcdWinDead {
479
-color: green;
480
-background: black;
481
-}
482
-
483
-#lcdWinDead:disabled {
484
-color: grey;
485
-background: dark grey;
486
-}</string>
479
+                  <string notr="true"/>
487 480
                  </property>
488
-                 <property name="segmentStyle">
489
-                  <enum>QLCDNumber::Flat</enum>
481
+                 <property name="text">
482
+                  <string>design</string>
490 483
                  </property>
491 484
                 </widget>
492 485
                </item>
@@ -526,17 +519,34 @@ background: dark grey;
526 519
                  </property>
527 520
                 </widget>
528 521
                </item>
529
-               <item row="0" column="0">
530
-                <widget class="QLabel" name="label_45">
531
-                 <property name="text">
532
-                  <string>Type</string>
522
+               <item row="4" column="1">
523
+                <widget class="QLCDNumber" name="lcdWinDead">
524
+                 <property name="sizePolicy">
525
+                  <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
526
+                   <horstretch>0</horstretch>
527
+                   <verstretch>0</verstretch>
528
+                  </sizepolicy>
529
+                 </property>
530
+                 <property name="styleSheet">
531
+                  <string notr="true">#lcdWinDead {
532
+color: green;
533
+background: black;
534
+}
535
+
536
+#lcdWinDead:disabled {
537
+color: grey;
538
+background: dark grey;
539
+}</string>
540
+                 </property>
541
+                 <property name="segmentStyle">
542
+                  <enum>QLCDNumber::Flat</enum>
533 543
                  </property>
534 544
                 </widget>
535 545
                </item>
536
-               <item row="4" column="0">
537
-                <widget class="QLabel" name="label_55">
546
+               <item row="0" column="0">
547
+                <widget class="QLabel" name="label_45">
538 548
                  <property name="text">
539
-                  <string>dead time [ms]</string>
549
+                  <string>Type</string>
540 550
                  </property>
541 551
                 </widget>
542 552
                </item>
@@ -564,13 +574,16 @@ background: dark grey;
564 574
                  </item>
565 575
                 </widget>
566 576
                </item>
567
-               <item row="1" column="3">
568
-                <widget class="QPushButton" name="fdDesignPushButton">
569
-                 <property name="styleSheet">
570
-                  <string notr="true"/>
577
+               <item row="0" column="3">
578
+                <widget class="QCheckBox" name="windowTrim">
579
+                 <property name="toolTip">
580
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Sets whether or not the dead time will be trimmed from the beginning and end of the signal. When doing a cascade of filters, users may wish to hold off on edge effect removal. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
571 581
                  </property>
572 582
                  <property name="text">
573
-                  <string>design</string>
583
+                  <string>Trim dead time </string>
584
+                 </property>
585
+                 <property name="checked">
586
+                  <bool>true</bool>
574 587
                  </property>
575 588
                 </widget>
576 589
                </item>
@@ -1021,76 +1034,80 @@ background: dark grey;
1021 1034
                <bool>true</bool>
1022 1035
               </property>
1023 1036
               <layout class="QGridLayout" name="gridLayout_9">
1024
-               <item row="0" column="0">
1025
-                <widget class="QLabel" name="label_26">
1037
+               <item row="12" column="0">
1038
+                <widget class="QLabel" name="label_34">
1026 1039
                  <property name="text">
1027
-                  <string>N freqs</string>
1040
+                  <string>First harmonic 2</string>
1028 1041
                  </property>
1029 1042
                 </widget>
1030 1043
                </item>
1031
-               <item row="0" column="1">
1032
-                <widget class="QSpinBox" name="NHarmonicsFreqsSpin">
1033
-                 <property name="minimum">
1034
-                  <number>1</number>
1044
+               <item row="1" column="0">
1045
+                <widget class="QLabel" name="label_49">
1046
+                 <property name="text">
1047
+                  <string>N segments</string>
1035 1048
                  </property>
1036
-                 <property name="maximum">
1037
-                  <number>2</number>
1049
+                </widget>
1050
+               </item>
1051
+               <item row="17" column="2">
1052
+                <widget class="QPushButton" name="harmonicGO">
1053
+                 <property name="layoutDirection">
1054
+                  <enum>Qt::LeftToRight</enum>
1038 1055
                  </property>
1039
-                 <property name="value">
1040
-                  <number>1</number>
1056
+                 <property name="styleSheet">
1057
+                  <string notr="true">#harmonicGO {background: green;}
1058
+#harmonicGO:disabled{background: black;}</string>
1059
+                 </property>
1060
+                 <property name="text">
1061
+                  <string>GO</string>
1041 1062
                  </property>
1042 1063
                 </widget>
1043 1064
                </item>
1044
-               <item row="5" column="1">
1045
-                <widget class="QSpinBox" name="f0KNSpin">
1046
-                 <property name="minimum">
1047
-                  <number>2</number>
1048
-                 </property>
1049
-                 <property name="value">
1050
-                  <number>40</number>
1065
+               <item row="13" column="0">
1066
+                <widget class="QLabel" name="label_35">
1067
+                 <property name="text">
1068
+                  <string>Last harmonic 2</string>
1051 1069
                  </property>
1052 1070
                 </widget>
1053 1071
                </item>
1054
-               <item row="4" column="1">
1055
-                <widget class="QSpinBox" name="f0K1Spin">
1072
+               <item row="14" column="1">
1073
+                <widget class="QSpinBox" name="f1KsSpin">
1056 1074
                  <property name="minimum">
1057 1075
                   <number>1</number>
1058 1076
                  </property>
1059 1077
                  <property name="maximum">
1060
-                  <number>50</number>
1078
+                  <number>3</number>
1079
+                 </property>
1080
+                </widget>
1081
+               </item>
1082
+               <item row="11" column="1">
1083
+                <widget class="QDoubleSpinBox" name="f1Spin">
1084
+                 <property name="maximum">
1085
+                  <double>25000.000000000000000</double>
1061 1086
                  </property>
1062 1087
                  <property name="value">
1063
-                  <number>1</number>
1088
+                  <double>60.000000000000000</double>
1064 1089
                  </property>
1065 1090
                 </widget>
1066 1091
                </item>
1067
-               <item row="12" column="2">
1068
-                <widget class="QLCDNumber" name="lcdf0NK2">
1069
-                 <property name="styleSheet">
1070
-                  <string notr="true">#lcdf0NK2 { 
1071
-color: green;
1072
-background: black;
1073
-}
1074
-
1075
-#lcdf0NK2:disabled {
1076
-color: grey;
1077
-background: dark grey;
1078
-}</string>
1092
+               <item row="17" column="1">
1093
+                <widget class="QCheckBox" name="plotHarmonic">
1094
+                 <property name="text">
1095
+                  <string>Plot</string>
1079 1096
                  </property>
1080
-                 <property name="segmentStyle">
1081
-                  <enum>QLCDNumber::Flat</enum>
1097
+                 <property name="checked">
1098
+                  <bool>true</bool>
1082 1099
                  </property>
1083 1100
                 </widget>
1084 1101
                </item>
1085
-               <item row="6" column="2">
1086
-                <widget class="QLCDNumber" name="lcdf0NK">
1102
+               <item row="14" column="2">
1103
+                <widget class="QLCDNumber" name="lcdf0NK2">
1087 1104
                  <property name="styleSheet">
1088
-                  <string notr="true">#lcdf0NK { 
1105
+                  <string notr="true">#lcdf0NK2 { 
1089 1106
 color: green;
1090 1107
 background: black;
1091 1108
 }
1092 1109
 
1093
-#lcdf0NK:disabled {
1110
+#lcdf0NK2:disabled {
1094 1111
 color: grey;
1095 1112
 background: dark grey;
1096 1113
 }</string>
@@ -1098,61 +1115,40 @@ background: dark grey;
1098 1115
                  <property name="segmentStyle">
1099 1116
                   <enum>QLCDNumber::Flat</enum>
1100 1117
                  </property>
1101
-                 <property name="intValue" stdset="0">
1102
-                  <number>0</number>
1103
-                 </property>
1104
-                </widget>
1105
-               </item>
1106
-               <item row="10" column="0">
1107
-                <widget class="QLabel" name="label_34">
1108
-                 <property name="text">
1109
-                  <string>First harmonic 2</string>
1110
-                 </property>
1111 1118
                 </widget>
1112 1119
                </item>
1113 1120
                <item row="12" column="1">
1114
-                <widget class="QSpinBox" name="f1KsSpin">
1121
+                <widget class="QSpinBox" name="f1K1Spin">
1115 1122
                  <property name="minimum">
1116 1123
                   <number>1</number>
1117 1124
                  </property>
1118
-                 <property name="maximum">
1119
-                  <number>3</number>
1120
-                 </property>
1121 1125
                 </widget>
1122 1126
                </item>
1123
-               <item row="13" column="2">
1124
-                <widget class="Line" name="line_9">
1125
-                 <property name="orientation">
1126
-                  <enum>Qt::Horizontal</enum>
1127
+               <item row="14" column="0">
1128
+                <widget class="QLabel" name="label_41">
1129
+                 <property name="text">
1130
+                  <string>Sub-harmonics</string>
1127 1131
                  </property>
1128 1132
                 </widget>
1129 1133
                </item>
1130
-               <item row="11" column="0">
1131
-                <widget class="QLabel" name="label_35">
1132
-                 <property name="text">
1133
-                  <string>Last harmonic 2</string>
1134
+               <item row="10" column="2">
1135
+                <widget class="Line" name="line_6">
1136
+                 <property name="orientation">
1137
+                  <enum>Qt::Horizontal</enum>
1134 1138
                  </property>
1135 1139
                 </widget>
1136 1140
                </item>
1137
-               <item row="5" column="2">
1138
-                <widget class="QLCDNumber" name="lcdHNF">
1139
-                 <property name="styleSheet">
1140
-                  <string notr="true">#lcdHNF {
1141
-color: green;
1142
-background: black;
1143
-}
1144
-
1145
-#lcdHNF:disabled {
1146
-color: grey;
1147
-background: dark grey;
1148
-}</string>
1141
+               <item row="7" column="1">
1142
+                <widget class="QSpinBox" name="f0KNSpin">
1143
+                 <property name="minimum">
1144
+                  <number>2</number>
1149 1145
                  </property>
1150
-                 <property name="segmentStyle">
1151
-                  <enum>QLCDNumber::Flat</enum>
1146
+                 <property name="value">
1147
+                  <number>40</number>
1152 1148
                  </property>
1153 1149
                 </widget>
1154 1150
                </item>
1155
-               <item row="4" column="2">
1151
+               <item row="6" column="2">
1156 1152
                 <widget class="QLCDNumber" name="lcdH1F">
1157 1153
                  <property name="styleSheet">
1158 1154
                   <string notr="true">#lcdH1F {
@@ -1170,60 +1166,89 @@ background: dark grey;
1170 1166
                  </property>
1171 1167
                 </widget>
1172 1168
                </item>
1173
-               <item row="10" column="2">
1174
-                <widget class="QLCDNumber" name="lcdH1F2">
1175
-                 <property name="styleSheet">
1176
-                  <string notr="true">#lcdH1F2{ 
1177
-color: green;
1178
-background: black;
1179
-}
1180
-
1181
-#lcdH1F2:disabled {
1182
-color: grey;
1183
-background: dark grey;
1184
-}</string>
1185
-                 </property>
1186
-                 <property name="segmentStyle">
1187
-                  <enum>QLCDNumber::Flat</enum>
1169
+               <item row="7" column="0">
1170
+                <widget class="QLabel" name="label_31">
1171
+                 <property name="text">
1172
+                  <string>Last harmonic 1</string>
1188 1173
                  </property>
1189 1174
                 </widget>
1190 1175
                </item>
1191
-               <item row="12" column="0">
1192
-                <widget class="QLabel" name="label_41">
1193
-                 <property name="text">
1194
-                  <string>Sub-harmonics</string>
1176
+               <item row="10" column="1">
1177
+                <widget class="Line" name="line_5">
1178
+                 <property name="orientation">
1179
+                  <enum>Qt::Horizontal</enum>
1195 1180
                  </property>
1196 1181
                 </widget>
1197 1182
                </item>
1198
-               <item row="10" column="1">
1199
-                <widget class="QSpinBox" name="f1K1Spin">
1183
+               <item row="6" column="1">
1184
+                <widget class="QSpinBox" name="f0K1Spin">
1200 1185
                  <property name="minimum">
1201 1186
                   <number>1</number>
1202 1187
                  </property>
1203
-                </widget>
1204
-               </item>
1205
-               <item row="9" column="0">
1206
-                <widget class="QLabel" name="label_27">
1207
-                 <property name="text">
1208
-                  <string>Base freq. 2 </string>
1188
+                 <property name="maximum">
1189
+                  <number>50</number>
1190
+                 </property>
1191
+                 <property name="value">
1192
+                  <number>1</number>
1209 1193
                  </property>
1210 1194
                 </widget>
1211 1195
                </item>
1212
-               <item row="8" column="1">
1213
-                <widget class="Line" name="line_5">
1196
+               <item row="15" column="1">
1197
+                <widget class="Line" name="line_8">
1214 1198
                  <property name="orientation">
1215 1199
                   <enum>Qt::Horizontal</enum>
1216 1200
                  </property>
1217 1201
                 </widget>
1218 1202
                </item>
1219
-               <item row="8" column="2">
1220
-                <widget class="Line" name="line_6">
1203
+               <item row="2" column="0">
1204
+                <widget class="QLabel" name="label_50">
1205
+                 <property name="text">
1206
+                  <string>Base freq. search </string>
1207
+                 </property>
1208
+                </widget>
1209
+               </item>
1210
+               <item row="10" column="0">
1211
+                <widget class="Line" name="line_4">
1221 1212
                  <property name="orientation">
1222 1213
                   <enum>Qt::Horizontal</enum>
1223 1214
                  </property>
1224 1215
                 </widget>
1225 1216
                </item>
1226
-               <item row="3" column="1">
1217
+               <item row="4" column="2">
1218
+                <widget class="Line" name="line_2">
1219
+                 <property name="orientation">
1220
+                  <enum>Qt::Horizontal</enum>
1221
+                 </property>
1222
+                </widget>
1223
+               </item>
1224
+               <item row="8" column="0">
1225
+                <widget class="QLabel" name="label_33">
1226
+                 <property name="text">
1227
+                  <string>Sub-harmonics </string>
1228
+                 </property>
1229
+                </widget>
1230
+               </item>
1231
+               <item row="6" column="0">
1232
+                <widget class="QLabel" name="label_11">
1233
+                 <property name="text">
1234
+                  <string>First harmonic 1</string>
1235
+                 </property>
1236
+                </widget>
1237
+               </item>
1238
+               <item row="0" column="1">
1239
+                <widget class="QSpinBox" name="NHarmonicsFreqsSpin">
1240
+                 <property name="minimum">
1241
+                  <number>1</number>
1242
+                 </property>
1243
+                 <property name="maximum">
1244
+                  <number>2</number>
1245
+                 </property>
1246
+                 <property name="value">
1247
+                  <number>1</number>
1248
+                 </property>
1249
+                </widget>
1250
+               </item>
1251
+               <item row="5" column="1">
1227 1252
                 <widget class="QDoubleSpinBox" name="f0Spin">
1228 1253
                  <property name="maximum">
1229 1254
                   <double>25000.000000000000000</double>
@@ -1236,38 +1261,46 @@ background: dark grey;
1236 1261
                  </property>
1237 1262
                 </widget>
1238 1263
                </item>
1239
-               <item row="9" column="1">
1240
-                <widget class="QDoubleSpinBox" name="f1Spin">
1241
-                 <property name="maximum">
1242
-                  <double>25000.000000000000000</double>
1264
+               <item row="12" column="2">
1265
+                <widget class="QLCDNumber" name="lcdH1F2">
1266
+                 <property name="styleSheet">
1267
+                  <string notr="true">#lcdH1F2{ 
1268
+color: green;
1269
+background: black;
1270
+}
1271
+
1272
+#lcdH1F2:disabled {
1273
+color: grey;
1274
+background: dark grey;
1275
+}</string>
1243 1276
                  </property>
1244
-                 <property name="value">
1245
-                  <double>60.000000000000000</double>
1277
+                 <property name="segmentStyle">
1278
+                  <enum>QLCDNumber::Flat</enum>
1246 1279
                  </property>
1247 1280
                 </widget>
1248 1281
                </item>
1249
-               <item row="2" column="2">
1250
-                <widget class="Line" name="line_2">
1282
+               <item row="4" column="0">
1283
+                <widget class="Line" name="line_3">
1251 1284
                  <property name="orientation">
1252 1285
                   <enum>Qt::Horizontal</enum>
1253 1286
                  </property>
1254 1287
                 </widget>
1255 1288
                </item>
1256
-               <item row="15" column="2">
1257
-                <widget class="QPushButton" name="harmonicGO">
1258
-                 <property name="layoutDirection">
1259
-                  <enum>Qt::LeftToRight</enum>
1260
-                 </property>
1261
-                 <property name="styleSheet">
1262
-                  <string notr="true">#harmonicGO {background: green;}
1263
-#harmonicGO:disabled{background: black;}</string>
1289
+               <item row="15" column="0">
1290
+                <widget class="Line" name="line_7">
1291
+                 <property name="orientation">
1292
+                  <enum>Qt::Horizontal</enum>
1264 1293
                  </property>
1294
+                </widget>
1295
+               </item>
1296
+               <item row="11" column="0">
1297
+                <widget class="QLabel" name="label_27">
1265 1298
                  <property name="text">
1266
-                  <string>GO</string>
1299
+                  <string>Base freq. 2 </string>
1267 1300
                  </property>
1268 1301
                 </widget>
1269 1302
                </item>
1270
-               <item row="6" column="1">
1303
+               <item row="8" column="1">
1271 1304
                 <widget class="QSpinBox" name="f0KsSpin">
1272 1305
                  <property name="toolTip">
1273 1306
                   <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Would you like to calculate subharmonics? For instance, setting this to 1, will calculate only the exact harmonics, setting this to 2 will calculate 1/2 step subharmonics (i.e. if the baseline frequency is 60 Hz, this will result in calcualtion of 30 Hz subharmonics)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -1283,124 +1316,182 @@ background: dark grey;
1283 1316
                  </property>
1284 1317
                 </widget>
1285 1318
                </item>
1286
-               <item row="2" column="1">
1287
-                <widget class="Line" name="line">
1288
-                 <property name="orientation">
1289
-                  <enum>Qt::Horizontal</enum>
1290
-                 </property>
1291
-                </widget>
1292
-               </item>
1293
-               <item row="5" column="0">
1294
-                <widget class="QLabel" name="label_31">
1319
+               <item row="0" column="0">
1320
+                <widget class="QLabel" name="label_26">
1295 1321
                  <property name="text">
1296
-                  <string>Last harmonic 1</string>
1322
+                  <string>N freqs</string>
1297 1323
                  </property>
1298 1324
                 </widget>
1299 1325
                </item>
1300
-               <item row="3" column="0">
1301
-                <widget class="QLabel" name="label_25">
1302
-                 <property name="text">
1303
-                  <string>Base freq. 1</string>
1326
+               <item row="13" column="1">
1327
+                <widget class="QSpinBox" name="f1KNSpin">
1328
+                 <property name="minimum">
1329
+                  <number>2</number>
1330
+                 </property>
1331
+                 <property name="value">
1332
+                  <number>40</number>
1304 1333
                  </property>
1305 1334
                 </widget>
1306 1335
                </item>
1307
-               <item row="11" column="2">
1308
-                <widget class="QLCDNumber" name="lcdHNF2">
1336
+               <item row="8" column="2">
1337
+                <widget class="QLCDNumber" name="lcdf0NK">
1309 1338
                  <property name="styleSheet">
1310
-                  <string notr="true">#lcdHNF2 { 
1311
- color: green;
1312
- background: black;
1339
+                  <string notr="true">#lcdf0NK { 
1340
+color: green;
1341
+background: black;
1313 1342
 }
1314 1343
 
1315
-#lcdHNF2:disabled {
1316
-  color: grey;
1317
-  background: dark grey;
1344
+#lcdf0NK:disabled {
1345
+color: grey;
1346
+background: dark grey;
1318 1347
 }</string>
1319 1348
                  </property>
1320 1349
                  <property name="segmentStyle">
1321 1350
                   <enum>QLCDNumber::Flat</enum>
1322 1351
                  </property>
1323
-                </widget>
1324
-               </item>
1325
-               <item row="11" column="1">
1326
-                <widget class="QSpinBox" name="f1KNSpin">
1327
-                 <property name="minimum">
1328
-                  <number>2</number>
1329
-                 </property>
1330
-                 <property name="value">
1331
-                  <number>40</number>
1352
+                 <property name="intValue" stdset="0">
1353
+                  <number>0</number>
1332 1354
                  </property>
1333 1355
                 </widget>
1334 1356
                </item>
1335
-               <item row="15" column="1">
1336
-                <widget class="QCheckBox" name="plotHarmonic">
1337
-                 <property name="text">
1338
-                  <string>Plot</string>
1357
+               <item row="7" column="2">
1358
+                <widget class="QLCDNumber" name="lcdHNF">
1359
+                 <property name="styleSheet">
1360
+                  <string notr="true">#lcdHNF {
1361
+color: green;
1362
+background: black;
1363
+}
1364
+
1365
+#lcdHNF:disabled {
1366
+color: grey;
1367
+background: dark grey;
1368
+}</string>
1339 1369
                  </property>
1340
-                 <property name="checked">
1341
-                  <bool>true</bool>
1370
+                 <property name="segmentStyle">
1371
+                  <enum>QLCDNumber::Flat</enum>
1342 1372
                  </property>
1343 1373
                 </widget>
1344 1374
                </item>
1345
-               <item row="13" column="1">
1346
-                <widget class="Line" name="line_8">
1375
+               <item row="4" column="1">
1376
+                <widget class="Line" name="line">
1347 1377
                  <property name="orientation">
1348 1378
                   <enum>Qt::Horizontal</enum>
1349 1379
                  </property>
1350 1380
                 </widget>
1351 1381
                </item>
1352
-               <item row="13" column="0">
1353
-                <widget class="Line" name="line_7">
1354
-                 <property name="orientation">
1355
-                  <enum>Qt::Horizontal</enum>
1382
+               <item row="1" column="1">
1383
+                <widget class="QSpinBox" name="NSegments">
1384
+                 <property name="minimum">
1385
+                  <number>1</number>
1386
+                 </property>
1387
+                 <property name="maximum">
1388
+                  <number>100</number>
1389
+                 </property>
1390
+                 <property name="value">
1391
+                  <number>1</number>
1356 1392
                  </property>
1357 1393
                 </widget>
1358 1394
                </item>
1359
-               <item row="6" column="0">
1360
-                <widget class="QLabel" name="label_33">
1361
-                 <property name="text">
1362
-                  <string>Sub-harmonics </string>
1395
+               <item row="13" column="2">
1396
+                <widget class="QLCDNumber" name="lcdHNF2">
1397
+                 <property name="styleSheet">
1398
+                  <string notr="true">#lcdHNF2 { 
1399
+ color: green;
1400
+ background: black;
1401
+}
1402
+
1403
+#lcdHNF2:disabled {
1404
+  color: grey;
1405
+  background: dark grey;
1406
+}</string>
1407
+                 </property>
1408
+                 <property name="segmentStyle">
1409
+                  <enum>QLCDNumber::Flat</enum>
1363 1410
                  </property>
1364 1411
                 </widget>
1365 1412
                </item>
1366
-               <item row="4" column="0">
1367
-                <widget class="QLabel" name="label_11">
1413
+               <item row="5" column="0">
1414
+                <widget class="QLabel" name="label_25">
1368 1415
                  <property name="text">
1369
-                  <string>First harmonic 1</string>
1416
+                  <string>Base freq. 1</string>
1370 1417
                  </property>
1371 1418
                 </widget>
1372 1419
                </item>
1373
-               <item row="2" column="0">
1374
-                <widget class="Line" name="line_3">
1420
+               <item row="15" column="2">
1421
+                <widget class="Line" name="line_9">
1375 1422
                  <property name="orientation">
1376 1423
                   <enum>Qt::Horizontal</enum>
1377 1424
                  </property>
1378 1425
                 </widget>
1379 1426
                </item>
1380
-               <item row="8" column="0">
1381
-                <widget class="Line" name="line_4">
1382
-                 <property name="orientation">
1383
-                  <enum>Qt::Horizontal</enum>
1427
+               <item row="2" column="2">
1428
+                <widget class="QSpinBox" name="Nsearch">
1429
+                 <property name="prefix">
1430
+                  <string/>
1384 1431
                  </property>
1385 1432
                 </widget>
1386 1433
                </item>
1387
-               <item row="1" column="1">
1388
-                <widget class="QSpinBox" name="NSegments">
1434
+               <item row="2" column="1">
1435
+                <widget class="QComboBox" name="searchAll">
1436
+                 <property name="toolTip">
1437
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When searching for the fundamental frequency, should the entire ensemble of harmonics be included? Reducing this number can accelerate the algorithm significantly. If a selection other than &amp;quot;All&amp;quot; is chosen, once the fundamental frequency is found, the whole set of harmonics will be included in the modelling.  &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
1438
+                 </property>
1439
+                 <item>
1440
+                  <property name="text">
1441
+                   <string>All</string>
1442
+                  </property>
1443
+                 </item>
1444
+                 <item>
1445
+                  <property name="text">
1446
+                   <string>First</string>
1447
+                  </property>
1448
+                 </item>
1449
+                 <item>
1450
+                  <property name="text">
1451
+                   <string/>
1452
+                  </property>
1453
+                 </item>
1454
+                </widget>
1455
+               </item>
1456
+               <item row="3" column="2">
1457
+                <widget class="QDoubleSpinBox" name="bounds">
1458
+                 <property name="toolTip">
1459
+                  <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If bounds is selected, this is the variance in the fundamental frequency which will be searched from the &lt;span style=&quot; font-weight:600;&quot;&gt;prior &lt;/span&gt;result. As such, for each record, the fundamental frequency can shift by this much (in either direction) from the prior record. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
1460
+                 </property>
1461
+                 <property name="decimals">
1462
+                  <number>3</number>
1463
+                 </property>
1389 1464
                  <property name="minimum">
1390
-                  <number>1</number>
1465
+                  <double>0.005000000000000</double>
1391 1466
                  </property>
1392 1467
                  <property name="maximum">
1393
-                  <number>100</number>
1468
+                  <double>10.000000000000000</double>
1469
+                 </property>
1470
+                 <property name="singleStep">
1471
+                  <double>0.001000000000000</double>
1394 1472
                  </property>
1395 1473
                  <property name="value">
1396
-                  <number>1</number>
1474
+                  <double>0.125000000000000</double>
1397 1475
                  </property>
1398 1476
                 </widget>
1399 1477
                </item>
1400
-               <item row="1" column="0">
1401
-                <widget class="QLabel" name="label_49">
1478
+               <item row="3" column="1">
1479
+                <widget class="QCheckBox" name="boundsCheck">
1402 1480
                  <property name="text">
1403
-                  <string>N segments</string>
1481
+                  <string>Bounded search</string>
1482
+                 </property>
1483
+                 <property name="checked">
1484
+                  <bool>true</bool>
1485
+                 </property>
1486
+                </widget>
1487
+               </item>
1488
+               <item row="0" column="2">
1489
+                <widget class="QCheckBox" name="harmRef">
1490
+                 <property name="text">
1491
+                  <string>proc ref. channels</string>
1492
+                 </property>
1493
+                 <property name="checked">
1494
+                  <bool>true</bool>
1404 1495
                  </property>
1405 1496
                 </widget>
1406 1497
                </item>
@@ -2544,8 +2635,8 @@ background: dark grey;
2544 2635
               <rect>
2545 2636
                <x>0</x>
2546 2637
                <y>0</y>
2547
-               <width>96</width>
2548
-               <height>26</height>
2638
+               <width>100</width>
2639
+               <height>30</height>
2549 2640
               </rect>
2550 2641
              </property>
2551 2642
              <attribute name="label">

+ 39
- 33
akvo/tressel/harmonic.py View File

@@ -37,29 +37,21 @@ def harmonicNorm (f0, sN, fs, t, k1, kN, ks):
37 37
     ii =  sN < (3.* np.std(sN))
38 38
     return np.linalg.norm( harmonicEuler(sN, fs, t, f0, k1, kN, ks)[ii] ) 
39 39
 
40
-def minHarmonic(sN, fs, t, f0, k1, kN, ks):
40
+def minHarmonic(sN, fs, t, f0, k1, kN, ks, Bounds, Nsearch):
41 41
     
42
-    # CG, BFGS, Newton-CG, L-BFGS-B, TNC, SLSQP, dogleg, trust-ncg, trust-krylov, trust-exact and trust-constr
43
-    res = minimize(harmonicNorm, np.array((f0)), args=(sN, fs, t, k1, kN, ks), jac='2-point', method='BFGS') # hess=None, bounds=None )
42
+    kNs = kN
43
+    if Nsearch != False:
44
+        kNs = k1+Nsearch    
45
+    if Bounds == 0:
46
+        print("UNbounded search from ", k1, " to ", kNs) # for f0 with fN=10 in search", f0)
47
+        # CG, BFGS, Newton-CG, L-BFGS-B, TNC, SLSQP, dogleg, trust-ncg, trust-krylov, trust-exact and trust-constr
48
+        res = minimize(harmonicNorm, np.array((f0)), args=(sN, fs, t, k1, kNs, ks), jac='2-point', method='BFGS') # hess=None, bounds=None )
44 49
     
45
-    #############
46
-    # Reduced N #
47
-    #############
48
-    #print("min 10")
49
-    #res = minimize(harmonicNorm, np.array((f0)), args=(sN, fs, t, k1, 10, ks), jac='2-point', method='BFGS') # hess=None, bounds=None )
50
-    
51
-    ########## 
52
-    # Bounds #
53
-    ##########
54
-    #print("bounded search for f0 with 10", f0)
55
-    #bnds = ( (f0-0.125, f0+0.125), )
56
-    #print("len f0", len( [f0,] ))
57
-    #print("len bnds", len(bnds) )
58
-    #res = minimize(harmonicNorm, (f0,), args=(sN, fs, t, k1, kN, ks), jac='2-point', method='L-BFGS-B', bounds=bnds ) # hess=None, bounds=None )
59
-    #res = minimize(harmonicNorm, (f0,), args=(sN, fs, t, k1, 10, ks), jac='2-point', method='L-BFGS-B', bounds=bnds ) # hess=None, bounds=None )
60
-    
61
-    #print(res)
62
-    #print ( "guess", guessf0(  harmonicEuler(sN, fs, t, res.x[0], k1, kN, ks), fs  ) )
50
+    else:
51
+        bnds = ( (f0-Bounds, f0+Bounds), )
52
+        print("bounded ( +-", Bounds, ") search from ", k1, "to", kNs) # for f0 with fN=10 in search", f0)
53
+        res = minimize(harmonicNorm, (f0,), args=(sN, fs, t, k1, kNs, ks), jac='2-point', method='L-BFGS-B', bounds=bnds ) # hess=None, bounds=None )
54
+
63 55
     return harmonicEuler(sN, fs, t, res.x[0], k1, kN, ks), res.x[0]#[0]
64 56
 
65 57
 def harmonicEuler2 ( sN, fs, t, f0, f0k1, f0kN, f0ks, f1, f1k1, f1kN, f1ks ): 
@@ -70,7 +62,7 @@ def harmonicEuler2 ( sN, fs, t, f0, f0k1, f0kN, f0ks, f1, f1k1, f1kN, f1ks ):
70 62
         fs = sampling frequency
71 63
         t = time samples 
72 64
         f0 = first base frequency of the sinusoidal noise 
73
-        f0k1 = First harmonic to calulate for f0 
65
+        f0k1 = First harmonic to calula11te for f0 
74 66
         f0kN = Last base harmonic to calulate for f0
75 67
         f0ks = subharmonics to calculate 
76 68
         f1 = second base frequency of the sinusoidal noise 
@@ -108,26 +100,40 @@ def harmonic2Norm (f0, sN, fs, t, f0k1, f0kN, f0ks, f1k1, f1kN, f1ks):
108 100
     ii =  sN < (3.* np.std(sN))
109 101
     return np.linalg.norm( harmonicEuler2(sN, fs, t, f0[0], f0k1, f0kN, f0ks, f0[1], f1k1, f1kN, f1ks)[ii] ) 
110 102
 
111
-def minHarmonic2(sN, fs, t, f0, f0k1, f0kN, f0ks, f1, f1k1, f1kN, f1ks):
112
-    
113
-    # CG, BFGS, Newton-CG, L-BFGS-B, TNC, SLSQP, dogleg, trust-ncg, trust-krylov, trust-exact and trust-constr
114
-    #res = minimize(harmonic2Norm, np.array((f0, f1)), args=(sN, fs, t, f0k1, f0kN, f0ks, f1k1,f1kN, f1ks), jac='2-point', method='BFGS') # hess=None, bounds=None )
115
-    
116
-    print("search 10")
117
-    res = minimize(harmonic2Norm, np.array((f0, f1)), args=(sN, fs, t, f0k1, 10, f0ks, f1k1, 10, f1ks), jac='2-point', method='BFGS') # hess=None, bounds=None )
118
-    
119
-    #print(res)
120
-    #print ( "guess", guessf0(harmonicEuler2(sN, fs, t, res.x[0], f0k1, f0kN, f0ks, res.x[1], f1k1, f1kN, f1ks), fs)  )
103
+def minHarmonic2(sN, fs, t, f0, f0k1, f0kN, f0ks, f1, f1k1, f1kN, f1ks, Bounds, Nsearch):
104
+
105
+    kNs0 = f0kN
106
+    kNs1 = f1kN
107
+    if Nsearch != False:
108
+        kNs0 = f0k1+Nsearch    
109
+        kNs1 = f1k1+Nsearch    
110
+
111
+    if Bounds == 0:
112
+
113
+        # CG, BFGS, Newton-CG, L-BFGS-B, TNC, SLSQP, dogleg, trust-ncg, trust-krylov, trust-exact and trust-constr
114
+        print("2 UNbounded ( +-", Bounds,") search length ", kNs0, kNs1 ,"for f0", f0, f1)
115
+        res = minimize(harmonic2Norm, np.array((f0, f1)), args=(sN, fs, t, f0k1, f0k1+kNs0, f0ks, f1k1, f1k1+kNs1, f1ks), jac='2-point', method='BFGS') # hess=None, bounds=None )
116
+    else:
117
+        # Bounded
118
+        bnds = ( (f0-Bounds, f0+Bounds),(f1-Bounds, f1+Bounds) )
119
+        print("2 bounded ( +-", Bounds,") search length ", kNs0, kNs1 ,"for f0", f0, f1)
120
+        # L-BFGS-B hess=None, bounds=None )
121
+        res = minimize(harmonic2Norm, ((f0,f1)), args=(sN, fs, t, f0k1, f0k1+kNs0, f0ks, f1k1, f1k1+kNs1, f1ks), jac='2-point', method='L-BFGS-B', bounds=bnds ) 
122
+
121 123
     return harmonicEuler2(sN, fs, t, res.x[0], f0k1, f0kN, f0ks, res.x[1], f1k1, f1kN, f1ks), res.x[0], res.x[1]#[0]
122 124
 
123 125
 def guessf0( sN, fs ):
124 126
     S = np.fft.fft(sN)
125 127
     w = np.fft.fftfreq( len(sN), 1/fs )
126 128
     imax = np.argmax( np.abs(S) )
129
+
130
+    #np.save( "sN.npy", S )
131
+    #np.save( "w.npy", w )
132
+    #exit()
127 133
     #plt.plot( w, np.abs(S) )
128 134
     #plt.show()
129 135
     #print(w)
130
-    #print ( w[imax], w[imax+1] )
136
+    #print ( w[imax], w[imax+1] )esta bien in english
131 137
     return abs(w[imax])
132 138
 
133 139
 if __name__ == "__main__":

+ 82
- 54
akvo/tressel/mrsurvey.py View File

@@ -536,12 +536,11 @@ class GMRDataProcessor(SNMRDataProcessor):
536 536
         #canvas.fig.tight_layout() 
537 537
         canvas.draw()
538 538
         self.doneTrigger.emit() 
539
-
540
-    #def harmonicModel(self, nF, nK, f0, f1, plot, canvas):
541 539
     
542 540
     def harmonicModel(self, nF, \
543 541
         f0, f0K1, f0KN, f0Ks, f0ns, \
544 542
         f1, f1K1, f1KN, f1Ks,  \
543
+        Nsearch, Bounds, procRefs, \
545 544
         plot, canvas):
546 545
         """ nF = number of base frequencies, must be 1 or 2 
547 546
             f0 = first base frequency  
@@ -553,15 +552,20 @@ class GMRDataProcessor(SNMRDataProcessor):
553 552
             f1K1 = first harmonic to model for second base frequency 
554 553
             f1KN = last harmonic to model for the second base frequency 
555 554
             f1Ks = subharmonic spacing for the second base frequency, set to 1 for no subharmonics.
555
+            Nsearch = the number of harmonics to use when determining base frequency 
556
+            bounds = 1/2 the width of the space where baseline frequency will be searched  
557
+            procRefs = should the reference loops be processed as well  
556 558
             plot = should Akvo plot the results 
557 559
             canvas = mpl plotting axis      
558 560
         """
559 561
         if plot:
560
-            canvas.reAx2()
562
+            canvas.reAx2(shy=False)
561 563
             canvas.ax1.set_ylabel(r"signal [nV]", fontsize=8)
562
-            canvas.ax2.set_xlabel(r"time [s]", fontsize=8)
564
+            #canvas.ax2.set_xlabel(r"time [s]", fontsize=8)
563 565
             canvas.ax2.set_ylabel(r"signal [nV]", fontsize=8)
564
-
566
+            canvas.ax2.set_xlabel(r"frequency [Hz]", fontsize=8)
567
+            canvas.ax1.set_yscale('log')
568
+            canvas.ax2.set_yscale('log')
565 569
         # Data
566 570
         iFID = 0
567 571
 
@@ -582,62 +586,75 @@ class GMRDataProcessor(SNMRDataProcessor):
582 586
                 for ipm in range(self.DATADICT["nPulseMoments"]):
583 587
                     if plot:
584 588
                         canvas.softClear()
585
-                        mmax = 0
586
-                        for ichan in self.DATADICT[pulse]["rchan"]:
587
-                            canvas.ax1.plot( self.DATADICT[pulse]["TIMES"], 1e9*self.DATADICT[pulse][ichan][ipm][istack], alpha=.5) 
588
-                            mmax = max( mmax, np.max(1e9*self.DATADICT[pulse][ichan][ipm][istack])) 
589
+                        mmaxr = 0
590
+                        mmaxd = 0
591
+                        if procRefs: 
592
+                            for ichan in self.DATADICT[pulse]["rchan"]:
593
+                                #canvas.ax1.plot( self.DATADICT[pulse]["TIMES"], 1e9*self.DATADICT[pulse][ichan][ipm][istack], alpha=.5) 
594
+                                #mmaxr = max( mmaxr, np.max(1e9*self.DATADICT[pulse][ichan][ipm][istack])) 
595
+                                ww = np.fft.fftfreq(len(self.DATADICT[pulse][ichan][ipm][istack]), d=self.dt)
596
+                                X = np.fft.rfft(self.DATADICT[pulse][ichan][ipm][istack])
597
+                                canvas.ax1.plot(np.abs(ww[0:len(X)]), np.abs(X), alpha=.5)
598
+                            canvas.ax1.set_prop_cycle(None)
599
+                            #canvas.ax1.set_ylim(-mmaxr, mmaxr) 
589 600
                         for ichan in self.DATADICT[pulse]["chan"]:
590
-                            canvas.ax2.plot( self.DATADICT[pulse]["TIMES"], 1e9*self.DATADICT[pulse][ichan][ipm][istack], alpha=.5) 
591
-                            mmax = max( mmax, np.max(1e9*self.DATADICT[pulse][ichan][ipm][istack])) 
592
-                        canvas.ax1.set_prop_cycle(None)
601
+                            #canvas.ax2.plot( self.DATADICT[pulse]["TIMES"], 1e9*self.DATADICT[pulse][ichan][ipm][istack], alpha=.5) 
602
+                            #mmaxd = max( mmaxd, np.max(1e9*self.DATADICT[pulse][ichan][ipm][istack])) 
603
+                            ww = np.fft.fftfreq(len(self.DATADICT[pulse][ichan][ipm][istack]), d=self.dt)
604
+                            X = np.fft.rfft(self.DATADICT[pulse][ichan][ipm][istack])
605
+                            canvas.ax2.plot(np.abs(ww[0:len(X)]), np.abs(X), alpha=.5)
593 606
                         canvas.ax2.set_prop_cycle(None)
594
-                        canvas.ax1.set_ylim(-mmax, mmax) 
595
-                    for ichan in self.DATADICT[pulse]["rchan"]:
596
-                        if nF == 1:
597
-                            for iseg in range(f0ns):
598
-                                if iseg < f0ns-1:
599
-                                    self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg:(iseg+1)*Nseg], f0p[ichan] = \
600
-                                        harmonic.minHarmonic( self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg:(iseg+1)*Nseg], \
607
+                        #canvas.ax2.set_ylim(-mmaxd, mmaxd)
608
+                    if procRefs: 
609
+                        for ichan in self.DATADICT[pulse]["rchan"]:
610
+                            if nF == 1:
611
+                                for iseg in range(f0ns):
612
+                                    if iseg < f0ns-1:
613
+                                        self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg:(iseg+1)*Nseg], f0p[ichan] = \
614
+                                            harmonic.minHarmonic( self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg:(iseg+1)*Nseg], \
601 615
                                             self.samp,  self.DATADICT[pulse]["TIMES"][iseg*Nseg:(iseg+1)*Nseg], \
602
-                                            f0p[ichan], f0K1, f0KN, f0Ks ) 
603
-                                else:
604
-                                    self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg::], f0p[ichan] = \
605
-                                        harmonic.minHarmonic( self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg::], \
616
+                                            f0p[ichan], f0K1, f0KN, f0Ks, Bounds, Nsearch ) 
617
+                                    else:
618
+                                        self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg::], f0p[ichan] = \
619
+                                            harmonic.minHarmonic( self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg::], \
606 620
                                             self.samp,  self.DATADICT[pulse]["TIMES"][iseg*Nseg::], \
607
-                                            f0p[ichan], f0K1, f0KN, f0Ks ) 
608
-                        elif nF == 2:
609
-                            for iseg in range(f0ns):
610
-                                if iseg < f0ns-1:
611
-                                    self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg:(iseg+1)*Nseg], f0p[ichan], f1p[ichan] = \
612
-                                        harmonic.minHarmonic2( self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg:(iseg+1)*Nseg],\
613
-                                     self.samp,  self.DATADICT[pulse]["TIMES"][iseg*Nseg:(iseg+1)*Nseg], \
614
-                                     f0p[ichan], f0K1, f0KN, f0Ks,  \
615
-                                     f1p[ichan], f1K1, f1KN, f1Ks ) 
616
-                                else:
617
-                                    self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg::], f0p[ichan], f1p[ichan] = \
618
-                                        harmonic.minHarmonic2( self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg::],\
619
-                                     self.samp,  self.DATADICT[pulse]["TIMES"][iseg*Nseg::], \
620
-                                     f0p[ichan], f0K1, f0KN, f0Ks,  \
621
-                                     f1p[ichan], f1K1, f1KN, f1Ks ) 
622
-                        # plot
623
-                        if plot:
624
-                            canvas.ax1.plot( self.DATADICT[pulse]["TIMES"], 1e9*self.DATADICT[pulse][ichan][ipm][istack], \
621
+                                            f0p[ichan], f0K1, f0KN, f0Ks, Bounds, Nsearch ) 
622
+                            elif nF == 2:
623
+                                for iseg in range(f0ns):
624
+                                    if iseg < f0ns-1:
625
+                                        self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg:(iseg+1)*Nseg], f0p[ichan], f1p[ichan] = \
626
+                                            harmonic.minHarmonic2( self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg:(iseg+1)*Nseg],\
627
+                                        self.samp,  self.DATADICT[pulse]["TIMES"][iseg*Nseg:(iseg+1)*Nseg], \
628
+                                        f0p[ichan], f0K1, f0KN, f0Ks,  \
629
+                                        f1p[ichan], f1K1, f1KN, f1Ks, Bounds, Nsearch ) 
630
+                                    else:
631
+                                        self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg::], f0p[ichan], f1p[ichan] = \
632
+                                            harmonic.minHarmonic2( self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg::],\
633
+                                        self.samp,  self.DATADICT[pulse]["TIMES"][iseg*Nseg::], \
634
+                                        f0p[ichan], f0K1, f0KN, f0Ks,  \
635
+                                        f1p[ichan], f1K1, f1KN, f1Ks, Bounds, Nsearch ) 
636
+                            # plot
637
+                            if plot:
638
+                                #canvas.ax1.plot( self.DATADICT[pulse]["TIMES"], 1e9*self.DATADICT[pulse][ichan][ipm][istack], \
639
+                                #    label = pulse + " ipm=" + str(ipm) + " istack=" + str(istack) + " rchan="  + str(ichan))
640
+                                ww = np.fft.fftfreq(len(self.DATADICT[pulse][ichan][ipm][istack]), d=self.dt)
641
+                                X = np.fft.rfft(self.DATADICT[pulse][ichan][ipm][istack])
642
+                                canvas.ax1.plot(np.abs(ww[0:len(X)]), np.abs(X),\
625 643
                                 label = pulse + " ipm=" + str(ipm) + " istack=" + str(istack) + " rchan="  + str(ichan))
626 644
 
627 645
                     for ichan in self.DATADICT[pulse]["chan"]:
628
-                        
629 646
                         if nF == 1:
630 647
                             for iseg in range(f0ns):
631 648
                                 if iseg < f0ns-1:
632 649
                                     self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg:(iseg+1)*Nseg], f0p[ichan] = \
633 650
                                         harmonic.minHarmonic( self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg:(iseg+1)*Nseg], 
634 651
                                             self.samp,  self.DATADICT[pulse]["TIMES"][iseg*Nseg:(iseg+1)*Nseg], \
635
-                                            f0p[ichan], f0K1, f0KN, f0Ks ) 
652
+                                            f0p[ichan], f0K1, f0KN, f0Ks, Bounds, Nsearch ) 
636 653
                                 else:
637 654
                                     self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg::], f0p[ichan] = \
638 655
                                         harmonic.minHarmonic( self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg::], 
639 656
                                             self.samp,  self.DATADICT[pulse]["TIMES"][iseg*Nseg::], \
640
-                                            f0p[ichan], f0K1, f0KN, f0Ks )
657
+                                            f0p[ichan], f0K1, f0KN, f0Ks, Bounds, Nsearch )
641 658
 
642 659
                         elif nF == 2:
643 660
                             for iseg in range(f0ns):
@@ -646,21 +663,26 @@ class GMRDataProcessor(SNMRDataProcessor):
646 663
                                         harmonic.minHarmonic2( self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg:(iseg+1)*Nseg],\
647 664
                                      self.samp,  self.DATADICT[pulse]["TIMES"][iseg*Nseg:(iseg+1)*Nseg], \
648 665
                                      f0p[ichan], f0K1, f0KN, f0Ks,  \
649
-                                     f1p[ichan], f1K1, f1KN, f1Ks ) 
666
+                                     f1p[ichan], f1K1, f1KN, f1Ks, Bounds, Nsearch ) 
650 667
                                 else:
651 668
                                     self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg::], f0p[ichan], f1p[ichan] = \
652 669
                                         harmonic.minHarmonic2( self.DATADICT[pulse][ichan][ipm][istack][iseg*Nseg::],\
653 670
                                      self.samp,  self.DATADICT[pulse]["TIMES"][iseg*Nseg::], \
654 671
                                      f0p[ichan], f0K1, f0KN, f0Ks,  \
655
-                                     f1p[ichan], f1K1, f1KN, f1Ks ) 
672
+                                     f1p[ichan], f1K1, f1KN, f1Ks, Bounds, Nsearch ) 
656 673
                
657 674
                         # plot
658 675
                         if plot:
659
-                            canvas.ax2.plot( self.DATADICT[pulse]["TIMES"], 1e9*self.DATADICT[pulse][ichan][ipm][istack], \
676
+                            #canvas.ax2.plot( self.DATADICT[pulse]["TIMES"], 1e9*self.DATADICT[pulse][ichan][ipm][istack], \
677
+                            #    label = pulse + " ipm=" + str(ipm) + " istack=" + str(istack) + " chan="  + str(ichan))
678
+                            ww = np.fft.fftfreq(len(self.DATADICT[pulse][ichan][ipm][istack]), d=self.dt)
679
+                            X = np.fft.rfft(self.DATADICT[pulse][ichan][ipm][istack])
680
+                            canvas.ax2.plot(np.abs(ww[0:len(X)]), np.abs(X), \
660 681
                                 label = pulse + " ipm=" + str(ipm) + " istack=" + str(istack) + " chan="  + str(ichan))
661 682
 
662 683
                     if plot:
663
-                        canvas.ax1.legend(prop={'size':6}, loc='upper right')
684
+                        if procRefs: 
685
+                            canvas.ax1.legend(prop={'size':6}, loc='upper right')
664 686
                         canvas.ax2.legend(prop={'size':6}, loc='upper right')
665 687
                         canvas.draw() 
666 688
                 
@@ -1063,7 +1085,8 @@ class GMRDataProcessor(SNMRDataProcessor):
1063 1085
                 if phase == 1: # Amp phase
1064 1086
                     im1 = ax1.pcolormesh( time_sp, QQ, self.DATADICT["CA"][pulse][chan], cmap=dcmap, rasterized=True,
1065 1087
                          vmin=-self.DATADICT["CAmax"][pulse] , vmax=self.DATADICT["CAmax"][pulse]  )
1066
-                    im2 = ax2.pcolormesh( time_sp, QQ, self.DATADICT["IP"][pulse][chan], cmap=cmocean.cm.balance, rasterized=True,\
1088
+                    #im2 = ax2.pcolormesh( time_sp, QQ, self.DATADICT["IP"][pulse][chan], cmap=cmocean.cm.balance, rasterized=True,\
1089
+                    im2 = ax2.pcolormesh( time_sp, QQ, self.DATADICT["IP"][pulse][chan], cmap=cmocean.cm.delta, rasterized=True,\
1067 1090
                          vmin=-np.pi, vmax=np.pi)
1068 1091
                 if phase == 2: # CA NR
1069 1092
                     im1 = ax1.pcolormesh( time_sp, QQ, self.DATADICT["CA"][pulse][chan], cmap=dcmap, rasterized=True,\
@@ -2065,7 +2088,7 @@ class GMRDataProcessor(SNMRDataProcessor):
2065 2088
     def computeWindow(self, pulse, band, centre, ftype, canvas=None):
2066 2089
         
2067 2090
         # Compute window
2068
-        nd = len(self.DATADICT[pulse][self.DATADICT[pulse]["chan"][0]][0][self.DATADICT["stacks"][0]])
2091
+        nd = len(self.DATADICT[pulse][self.DATADICT[pulse]["chan"][0]][0][self.DATADICT["stacks"][0]]) # num. data 
2069 2092
         fft1 = np.fft.rfft(self.DATADICT[pulse][self.DATADICT[pulse]["chan"][0]][0][self.DATADICT["stacks"][0]])
2070 2093
         freqs   = np.fft.fftfreq(nd, self.dt)
2071 2094
         df      = freqs[1] - freqs[0]
@@ -2119,26 +2142,31 @@ class GMRDataProcessor(SNMRDataProcessor):
2119 2142
             canvas.ax2.set_title("IFFT")
2120 2143
             canvas.draw()
2121 2144
 
2122
-        return [WINDOW, nd, istart, iend, dead]
2145
+        return [WINDOW, nd, istart, iend, dead, ift]
2123 2146
 
2124
-    def windowFilter(self, ftype, band, centre, canvas):
2147
+    def windowFilter(self, ftype, band, centre, trunc, canvas):
2125 2148
 
2126 2149
         ###############################
2127 2150
         # Window Filter (Ormsby filter http://www.xsgeo.com/course/filt.htm) 
2128 2151
         # apply window
2129 2152
         iFID = 0
2130 2153
         for pulse in self.DATADICT["PULSES"]:
2131
-            [WINDOW, nd, istart, iend,dead] = self.computeWindow(pulse, band, centre, ftype)
2154
+            [WINDOW, nd, istart, iend, dead, idead] = self.computeWindow(pulse, band, centre, ftype)
2132 2155
             for istack in self.DATADICT["stacks"]:
2133 2156
                 for ipm in range(self.DATADICT["nPulseMoments"]):
2134 2157
                     for ichan in np.append(self.DATADICT[pulse]["chan"], self.DATADICT[pulse]["rchan"]):
2135 2158
                         fft = np.fft.rfft( self.DATADICT[pulse][ichan][ipm][istack]  )
2136 2159
                         fft *= WINDOW
2137
-                        self.DATADICT[pulse][ichan][ipm][istack] = np.fft.irfft(fft , nd)
2160
+                        if trunc:
2161
+                            self.DATADICT[pulse][ichan][ipm][istack] = np.fft.irfft(fft, nd)[idead:-idead]
2162
+                        else:
2163
+                            self.DATADICT[pulse][ichan][ipm][istack] = np.fft.irfft(fft, nd)
2138 2164
                 
2139 2165
                     percent = (int)(1e2*((float)(iFID*self.DATADICT["nPulseMoments"]+(ipm))/(len(self.DATADICT["PULSES"])*self.nPulseMoments)))
2140 2166
                     self.progressTrigger.emit(percent)  
2141 2167
                 iFID += 1
2168
+            if trunc:
2169
+                self.DATADICT[pulse]["TIMES"] = self.DATADICT[pulse]["TIMES"][idead:-idead]
2142 2170
 
2143 2171
         self.plotFT(canvas, istart, iend)
2144 2172
         self.doneTrigger.emit() 

+ 1
- 1
setup.py View File

@@ -21,7 +21,7 @@ with open("README.md", "r") as fh:
21 21
     long_description = fh.read()
22 22
 
23 23
 setup(name='Akvo',
24
-      version='1.2.6',
24
+      version='1.2.7',
25 25
       description='Surface nuclear magnetic resonance workbench',
26 26
       long_description=long_description,
27 27
       long_description_content_type='text/markdown',

Loading…
Cancel
Save