Browse Source

Additions for META data and start of new loop dialogue

tags/1.6.1
Trevor Irons 4 years ago
parent
commit
a1d59fc259
5 changed files with 3720 additions and 2885 deletions
  1. 158
    0
      akvo/gui/addCircularLoop.ui
  2. 90
    17
      akvo/gui/akvoGUI.py
  3. 3467
    2866
      akvo/gui/main.ui
  4. 4
    0
      pyuic.json
  5. 1
    2
      setup.py

+ 158
- 0
akvo/gui/addCircularLoop.ui View File

@@ -0,0 +1,158 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<ui version="4.0">
3
+ <class>circularLoopAdd</class>
4
+ <widget class="QDialog" name="circularLoopAdd">
5
+  <property name="geometry">
6
+   <rect>
7
+    <x>0</x>
8
+    <y>0</y>
9
+    <width>400</width>
10
+    <height>300</height>
11
+   </rect>
12
+  </property>
13
+  <property name="windowTitle">
14
+   <string>Dialog</string>
15
+  </property>
16
+  <layout class="QGridLayout" name="gridLayout">
17
+   <item row="0" column="0">
18
+    <widget class="QLabel" name="label">
19
+     <property name="text">
20
+      <string>Centre Northing </string>
21
+     </property>
22
+    </widget>
23
+   </item>
24
+   <item row="0" column="1">
25
+    <widget class="QDoubleSpinBox" name="centreNorth">
26
+     <property name="minimum">
27
+      <double>-999999999.000000000000000</double>
28
+     </property>
29
+     <property name="maximum">
30
+      <double>9999999999.000000000000000</double>
31
+     </property>
32
+    </widget>
33
+   </item>
34
+   <item row="1" column="0">
35
+    <widget class="QLabel" name="label_2">
36
+     <property name="text">
37
+      <string>Centre Easting</string>
38
+     </property>
39
+    </widget>
40
+   </item>
41
+   <item row="1" column="1">
42
+    <widget class="QDoubleSpinBox" name="centreEast">
43
+     <property name="minimum">
44
+      <double>-99999999.000000000000000</double>
45
+     </property>
46
+     <property name="maximum">
47
+      <double>99999999.989999994635582</double>
48
+     </property>
49
+    </widget>
50
+   </item>
51
+   <item row="2" column="0">
52
+    <widget class="QLabel" name="label_3">
53
+     <property name="text">
54
+      <string>height </string>
55
+     </property>
56
+    </widget>
57
+   </item>
58
+   <item row="2" column="1">
59
+    <widget class="QDoubleSpinBox" name="doubleSpinBox">
60
+     <property name="toolTip">
61
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Akvo uses a positive down convention, a slight negative value to the loop height improves numerical stability using digital filtering hankel transforms. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
62
+     </property>
63
+     <property name="decimals">
64
+      <number>3</number>
65
+     </property>
66
+     <property name="minimum">
67
+      <double>-99.000000000000000</double>
68
+     </property>
69
+     <property name="value">
70
+      <double>-0.001000000000000</double>
71
+     </property>
72
+    </widget>
73
+   </item>
74
+   <item row="3" column="0">
75
+    <widget class="QLabel" name="label_4">
76
+     <property name="text">
77
+      <string>radius</string>
78
+     </property>
79
+    </widget>
80
+   </item>
81
+   <item row="3" column="1">
82
+    <widget class="QDoubleSpinBox" name="doubleSpinBox_2">
83
+     <property name="toolTip">
84
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Radius of the loop&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
85
+     </property>
86
+     <property name="minimum">
87
+      <double>0.100000000000000</double>
88
+     </property>
89
+     <property name="maximum">
90
+      <double>299.990000000000009</double>
91
+     </property>
92
+    </widget>
93
+   </item>
94
+   <item row="4" column="0">
95
+    <widget class="QLabel" name="label_5">
96
+     <property name="text">
97
+      <string>segments</string>
98
+     </property>
99
+    </widget>
100
+   </item>
101
+   <item row="4" column="1">
102
+    <widget class="QSpinBox" name="spinBox">
103
+     <property name="toolTip">
104
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Currently Akvo/Merlin calculates circular loops using segments of wire, forming a polygon. Analytic circular loops may be added in the future. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
105
+     </property>
106
+     <property name="minimum">
107
+      <number>5</number>
108
+     </property>
109
+    </widget>
110
+   </item>
111
+   <item row="5" column="1">
112
+    <widget class="QDialogButtonBox" name="buttonBox">
113
+     <property name="orientation">
114
+      <enum>Qt::Horizontal</enum>
115
+     </property>
116
+     <property name="standardButtons">
117
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
118
+     </property>
119
+    </widget>
120
+   </item>
121
+  </layout>
122
+ </widget>
123
+ <resources/>
124
+ <connections>
125
+  <connection>
126
+   <sender>buttonBox</sender>
127
+   <signal>accepted()</signal>
128
+   <receiver>circularLoopAdd</receiver>
129
+   <slot>accept()</slot>
130
+   <hints>
131
+    <hint type="sourcelabel">
132
+     <x>248</x>
133
+     <y>254</y>
134
+    </hint>
135
+    <hint type="destinationlabel">
136
+     <x>157</x>
137
+     <y>274</y>
138
+    </hint>
139
+   </hints>
140
+  </connection>
141
+  <connection>
142
+   <sender>buttonBox</sender>
143
+   <signal>rejected()</signal>
144
+   <receiver>circularLoopAdd</receiver>
145
+   <slot>reject()</slot>
146
+   <hints>
147
+    <hint type="sourcelabel">
148
+     <x>316</x>
149
+     <y>260</y>
150
+    </hint>
151
+    <hint type="destinationlabel">
152
+     <x>286</x>
153
+     <y>274</y>
154
+    </hint>
155
+   </hints>
156
+  </connection>
157
+ </connections>
158
+</ui>

+ 90
- 17
akvo/gui/akvoGUI.py View File

@@ -16,6 +16,8 @@ Clicking ignore will prevent this warning from showing
16 16
 each time you launch Akvo.                  
17 17
 """
18 18
 
19
+from akvo.gui.addCircularLoop_ui import Ui_circularLoopAdd
20
+
19 21
 import matplotlib
20 22
 matplotlib.use("QT5Agg")
21 23
 from PyQt5 import QtCore, QtGui, QtWidgets
@@ -34,6 +36,8 @@ from akvo.tressel import mrsurvey
34 36
 import pkg_resources  # part of setuptools
35 37
 version = pkg_resources.require("Akvo")[0].version
36 38
 
39
+from collections import OrderedDict
40
+
37 41
 from ruamel import yaml
38 42
 #import ruamel.yaml 
39 43
 #yaml = ruamel.yaml.YAML()
@@ -59,16 +63,6 @@ class VectorXr(yaml.YAMLObject):
59 63
         # Converts to numpy array on import 
60 64
         return "np.array(%r)" % (self.data)
61 65
 
62
-from collections import OrderedDict
63
-#def represent_ordereddict(dumper, data):
64
-#    print("representing IN DA HOUSE!!!!!!!!!!!!!!!!!!!!!")
65
-#    value = []
66
-#    for item_key, item_value in data.items():
67
-#        node_key = dumper.represent_data(item_key)
68
-#        node_value = dumper.represent_data(item_value)
69
-#        value.append((node_key, node_value))
70
-#    return yaml.nodes.MappingNode(u'tag:yaml.org,2002:map', value)
71
-#yaml.add_representer(OrderedDict, represent_ordereddict)
72 66
 
73 67
 def setup_yaml():
74 68
     """ https://stackoverflow.com/a/8661021 """
@@ -82,14 +76,15 @@ class AkvoYamlNode(yaml.YAMLObject):
82 76
         self.Akvo_VERSION = version
83 77
         self.Import = OrderedDict() # {}
84 78
         self.Processing = [] # OrderedDict() 
85
-        self.Stacking = OrderedDict() 
79
+        self.Stacking = OrderedDict()
80
+        self.META = OrderedDict() 
86 81
     #def __init__(self, node):
87 82
     #    self.Akvo_VERSION = node["version"]
88 83
     #    self.Import = OrderedDict( node["Import"] ) # {}
89 84
     #    self.Processing = OrderedDict( node["Processing"] ) 
90 85
     def __repr__(self):
91
-        return "%s(name=%r, Akvo_VERSION=%r, Import=%r, Processing=%r)" % (
92
-            self.__class__.__name__, self.Akvo_VERSION, self.Import, self.Processing, self.Stacking )
86
+        return "%s(name=%r, Akvo_VERSION=%r, Import=%r, Processing=%r, self.Stacking=%r, self.META=%r)" % (
87
+            self.__class__.__name__, self.Akvo_VERSION, self.Import, self.Processing, self.Stacking, self.META )
93 88
             #self.__class__.__name__, self.Akvo_VERSION, self.Import, OrderedDict(self.Processing) ) 
94 89
     
95 90
 try:    
@@ -196,6 +191,23 @@ class ApplicationWindow(QtWidgets.QMainWindow):
196 191
         
197 192
         self.ui.plotGI.setEnabled(False) 
198 193
         self.ui.plotGI.pressed.connect( self.plotGI )
194
+
195
+        # META 
196
+        self.ui.locEdit.editingFinished.connect( self.logSite )
197
+        self.ui.UTMzone.currentIndexChanged.connect( self.logSite )
198
+        self.ui.latBand.currentIndexChanged.connect( self.logSite )
199
+        self.ui.ellipsoid.currentIndexChanged.connect( self.logSite )
200
+        self.ui.incSpinBox.valueChanged.connect( self.logSite )
201
+        self.ui.decSpinBox.valueChanged.connect( self.logSite )
202
+        self.ui.intensitySpinBox.valueChanged.connect( self.logSite )
203
+        self.ui.tempSpinBox.valueChanged.connect( self.logSite )
204
+        self.ui.timeEdit.timeChanged.connect( self.logSite )
205
+        self.ui.dateEdit.dateChanged.connect( self.logSite )
206
+        # this may call the yaml stuff too often... 
207
+        self.ui.txtComments.textChanged.connect( self.logSite )
208
+ 
209
+        # invert
210
+        self.ui.addLoopButton.pressed.connect( self.loopAdd )
199 211
  
200 212
         # hide header info box 
201 213
         #self.ui.headerFileBox.setVisible(False) 
@@ -340,6 +352,29 @@ class ApplicationWindow(QtWidgets.QMainWindow):
340 352
         else:
341 353
             self.ui.ProcTabs.removeTab(0)    
342 354
             self.ui.ProcTabs.removeTab(0)    
355
+    
356
+    def loopAdd(self):
357
+
358
+        print(self.ui.loopLabel.text())
359
+        print(self.ui.loopGeom.currentText())
360
+        print(self.ui.loopType.currentText())
361
+           
362
+        print( "label len", len(self.ui.loopLabel.text()) ) 
363
+        if len(self.ui.loopLabel.text().strip()) == 0: 
364
+            Error = QtWidgets.QMessageBox()
365
+            Error.setWindowTitle("Error!")
366
+            Error.setText("Loop label cannot be blank or repeated")
367
+            Error.setDetailedText("Each loop label must be unique and comprise at least one character. Leading and trailing whitespace will be trimmed.")
368
+            Error.exec_()
369
+        else:
370
+            if self.ui.loopGeom.currentText() == "Circular":
371
+                dialog = QtWidgets.QDialog()
372
+                dialog.ui = Ui_circularLoopAdd()
373
+                dialog.ui.setupUi(dialog)
374
+                dialog.exec_()
375
+                dialog.show()
376
+                if dialog.result():
377
+                    print("centre north", dialog.ui.centreNorth.value())
343 378
 
344 379
     def headerBoxShrink(self):
345 380
         #self.ui.headerFileBox.setVisible(False)
@@ -396,7 +431,10 @@ class ApplicationWindow(QtWidgets.QMainWindow):
396 431
                     Error.setText("Non-increasing layer detected")
397 432
                     Error.setDetailedText("Each layer interface must be below the one above it.")
398 433
                     Error.exec_()
399
-            
434
+                    #err_msg = "Quadrature detection has already been done!"
435
+                    #reply =QtWidgets.QMessageBox.critical(self, 'Error', 
436
+                    #    err_msg) 
437
+
400 438
                     pCell2 = self.ui.layerTableWidget.item(ii, jj)
401 439
                     pCell2.setText(str(""))
402 440
                     self.ui.layerTableWidget.cellChanged.connect(self.sigmaCellChanged) 
@@ -512,6 +550,14 @@ class ApplicationWindow(QtWidgets.QMainWindow):
512 550
                             nor[idx] = list()
513 551
                             eas[idx] = list()
514 552
                             dep[idx] = list()
553
+                    if jj == 4:
554
+                        # circular loop 
555
+                        m2pi = np.linspace(0,2*np.pi,10)
556
+                        rad = 30.
557
+                        nor[idx] = np.concatenate((np.array(nor[idx]),  rad * np.sin(m2pi))) 
558
+                        eas[idx] = np.concatenate((np.array(eas[idx]),  rad * np.cos(m2pi))) 
559
+                        dep[idx] = np.concatenate((np.array(dep[idx]),  np.ones(len(m2pi)))) 
560
+                        print("nor", nor[idx]) 
515 561
                     if jj == 1: 
516 562
                         nor[idx].append( eval(self.ui.loopTableWidget.item(ii, 1).text()) )
517 563
                     elif jj == 2:
@@ -595,7 +641,7 @@ class ApplicationWindow(QtWidgets.QMainWindow):
595 641
         # make plots as you import the dataset
596 642
         self.ui.plotImportCheckBox.setEnabled(True)
597 643
         self.ui.plotImportCheckBox.setChecked(True)
598
- 
644
+         
599 645
         # Update info from the header into the GUI
600 646
         self.ui.pulseTypeTextBrowser.clear()
601 647
         self.ui.pulseTypeTextBrowser.append(self.RAWDataProc.pulseType)
@@ -743,7 +789,7 @@ class ApplicationWindow(QtWidgets.QMainWindow):
743 789
         INFO["transFreq"] = self.RAWDataProc.transFreq
744 790
         INFO["headerstr"] = str(self.headerstr)
745 791
         INFO["nDAQVersion"] = self.RAWDataProc.nDAQVersion
746
-        INFO["log"] = yaml.dump( self.YamlNode )  #self.logText  #MAK 20170127
792
+        INFO["log"] = yaml.dump( self.YamlNode )  
747 793
 
748 794
         self.RAWDataProc.DATADICT["INFO"] = INFO 
749 795
 
@@ -820,9 +866,10 @@ class ApplicationWindow(QtWidgets.QMainWindow):
820 866
         if  AKVO_VERSION[0] >= 1 and AKVO_VERSION[1] >= 2 and AKVO_VERSION[2] >= 3:
821 867
             self.RAWDataProc.interpulseDelay = self.RAWDataProc.DATADICT["INFO"]["interpulseDelay"]
822 868
 
823
-        self.YamlNode.Import = OrderedDict((yaml.load( self.logText, Loader=yaml.Loader )).Import)
869
+        self.YamlNode.Import =   OrderedDict((yaml.load( self.logText, Loader=yaml.Loader )).Import)
824 870
         self.YamlNode.Processing = list((yaml.load( self.logText, Loader=yaml.Loader )).Processing)
825 871
         self.YamlNode.Stacking = OrderedDict((yaml.load( self.logText, Loader=yaml.Loader )).Stacking)
872
+        self.YamlNode.META =     OrderedDict((yaml.load( self.logText, Loader=yaml.Loader )).META)
826 873
         self.Log()
827 874
  
828 875
             #self.ui.logTextBrowser.append( yaml.dump(self.YamlNode)) #, default_flow_style=False)  )
@@ -857,6 +904,10 @@ class ApplicationWindow(QtWidgets.QMainWindow):
857 904
         self.ui.lcdNumberFID2Length.setEnabled(1)
858 905
         self.ui.lcdNumberResampFreq.setEnabled(1)
859 906
         self.ui.lcdTotalDeadTime.setEnabled(1)
907
+
908
+        # enable META tab 
909
+        self.ui.METATab.setEnabled(1)
910
+        self.ui.siteBox.setEnabled(1)
860 911
         
861 912
         #self.ui.lcdTotalDeadTime.display( 1e3*self.RAWDataProc.DATADICT["INFO"]["deadTime"] )
862 913
 
@@ -1006,6 +1057,10 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1006 1057
         self.YamlNode.Import["instrument dead time"] = (1e-3 * self.ui.DeadTimeSpinBox.value( ))    
1007 1058
 
1008 1059
         self.Log (  )     
1060
+        
1061
+        # enable META tab 
1062
+        self.ui.METATab.setEnabled(1)
1063
+        self.ui.siteBox.setEnabled(1)
1009 1064
 
1010 1065
         # should be already done
1011 1066
 #        QtCore.QObject.connect(self.RAWDataProc, QtCore.SIGNAL("updateProgress(int)"), self.updateProgressBar)
@@ -1244,11 +1299,13 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1244 1299
         # Log processing 
1245 1300
         Adapt = OrderedDict()
1246 1301
         Adapt["STEP"] = "TD noise cancellation"
1302
+        #print(Adapt)
1247 1303
         Adapt["n_Taps"] = str(self.ui.MTapsSpinBox.value())
1248 1304
         Adapt["lambda"] = str(self.ui.adaptLambdaSpinBox.value())
1249 1305
         Adapt["truncate"] = str(self.ui.adaptTruncateSpinBox.value())
1250 1306
         Adapt["mu"] = str(self.ui.adaptMuSpinBox.value()) 
1251 1307
         Adapt["PCA"] = str(self.ui.PCAComboBox.currentText())
1308
+        #print(Adapt)
1252 1309
         self.YamlNode.Processing.append(Adapt)
1253 1310
         self.Log( )
1254 1311
 
@@ -1281,6 +1338,22 @@ class ApplicationWindow(QtWidgets.QMainWindow):
1281 1338
                 self.ui.CentralVSpinBox.value(), \
1282 1339
                 self.ui.mplwidget))
1283 1340
 
1341
+    def logSite(self):
1342
+        self.YamlNode.META["Location"] = self.ui.locEdit.text()
1343
+        self.YamlNode.META["Coordinates"] = OrderedDict() 
1344
+        self.YamlNode.META["Coordinates"]["UTM"] = self.ui.UTMzone.currentText()
1345
+        self.YamlNode.META["Coordinates"]["LatBand"] = self.ui.latBand.currentText() 
1346
+        self.YamlNode.META["Coordinates"]["ellipsoid"] =  self.ui.ellipsoid.currentText()
1347
+        self.YamlNode.META["DateTime"] = self.ui.dateEdit.date().toString("yyyy-MM-dd") + "T" + str( self.ui.timeEdit.time().toString("hh:mm") )
1348
+        self.YamlNode.META["Temp"] = self.ui.tempSpinBox.value()
1349
+        self.YamlNode.META["B_0"] = OrderedDict()
1350
+        self.YamlNode.META["B_0"]["inc"] = self.ui.incSpinBox.value()
1351
+        self.YamlNode.META["B_0"]["dec"] = self.ui.decSpinBox.value()
1352
+        self.YamlNode.META["B_0"]["intensity"] = self.ui.intensitySpinBox.value()
1353
+        self.YamlNode.META["Field Notes"] = self.ui.txtComments.toPlainText()
1354
+
1355
+        self.Log()
1356
+
1284 1357
     def bandPassFilter(self):
1285 1358
         
1286 1359
         self.lock("bandpass filter")        

+ 3467
- 2866
akvo/gui/main.ui
File diff suppressed because it is too large
View File


+ 4
- 0
pyuic.json View File

@@ -3,6 +3,10 @@
3 3
         [
4 4
             "akvo/gui/main.ui",
5 5
             "akvo/gui"
6
+        ],
7
+        [
8
+            "akvo/gui/addCircularLoop.ui",
9
+            "akvo/gui"
6 10
         ]
7 11
     ],
8 12
     "pyrcc": "pyrcc5",

+ 1
- 2
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.8',
24
+      version='1.2.9',
25 25
       description='Surface nuclear magnetic resonance workbench',
26 26
       long_description=long_description,
27 27
       long_description_content_type='text/markdown',
@@ -77,4 +77,3 @@ setup(name='Akvo',
77 77
       ],
78 78
     )
79 79
 
80
-

Loading…
Cancel
Save