Browse Source

Work towards kernel calc inside Akvo

tags/1.6.1
Trevor Irons 3 years ago
parent
commit
5b25a43c51
11 changed files with 3774 additions and 10 deletions
  1. 110
    0
      akvo/gui/Loop.ui
  2. 30
    1
      akvo/gui/akvoGUI.py
  3. 55
    0
      akvo/gui/callScript.py
  4. 3370
    0
      akvo/gui/main-bu.ui
  5. 16
    3
      akvo/gui/main.ui
  6. 57
    0
      akvo/gui/redirect.ui
  7. 2
    4
      akvo/terminal/plotyaml.py
  8. 127
    0
      akvo/tressel/calcAkvoKernel.py
  9. 1
    1
      akvo/tressel/mrsurvey.py
  10. 4
    0
      pyuic.json
  11. 2
    1
      setup.py

+ 110
- 0
akvo/gui/Loop.ui View File

@@ -0,0 +1,110 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<ui version="4.0">
3
+ <class>LoopAdd</class>
4
+ <widget class="QDialog" name="LoopAdd">
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="QFormLayout" name="formLayout">
17
+   <item row="0" column="0">
18
+    <widget class="QLabel" name="label_2">
19
+     <property name="text">
20
+      <string>Label</string>
21
+     </property>
22
+    </widget>
23
+   </item>
24
+   <item row="1" column="0">
25
+    <widget class="QLabel" name="label">
26
+     <property name="text">
27
+      <string>Type</string>
28
+     </property>
29
+    </widget>
30
+   </item>
31
+   <item row="1" column="1">
32
+    <widget class="QComboBox" name="comboBox">
33
+     <item>
34
+      <property name="text">
35
+       <string>Circular</string>
36
+      </property>
37
+     </item>
38
+     <item>
39
+      <property name="text">
40
+       <string>figure-8</string>
41
+      </property>
42
+     </item>
43
+     <item>
44
+      <property name="text">
45
+       <string>square-8</string>
46
+      </property>
47
+     </item>
48
+     <item>
49
+      <property name="text">
50
+       <string>New Item</string>
51
+      </property>
52
+     </item>
53
+     <item>
54
+      <property name="text">
55
+       <string>polygon</string>
56
+      </property>
57
+     </item>
58
+    </widget>
59
+   </item>
60
+   <item row="2" column="0" colspan="2">
61
+    <widget class="QDialogButtonBox" name="buttonBox">
62
+     <property name="orientation">
63
+      <enum>Qt::Horizontal</enum>
64
+     </property>
65
+     <property name="standardButtons">
66
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
67
+     </property>
68
+    </widget>
69
+   </item>
70
+   <item row="0" column="1">
71
+    <widget class="QLineEdit" name="lineEdit"/>
72
+   </item>
73
+  </layout>
74
+ </widget>
75
+ <resources/>
76
+ <connections>
77
+  <connection>
78
+   <sender>buttonBox</sender>
79
+   <signal>accepted()</signal>
80
+   <receiver>LoopAdd</receiver>
81
+   <slot>accept()</slot>
82
+   <hints>
83
+    <hint type="sourcelabel">
84
+     <x>248</x>
85
+     <y>254</y>
86
+    </hint>
87
+    <hint type="destinationlabel">
88
+     <x>157</x>
89
+     <y>274</y>
90
+    </hint>
91
+   </hints>
92
+  </connection>
93
+  <connection>
94
+   <sender>buttonBox</sender>
95
+   <signal>rejected()</signal>
96
+   <receiver>LoopAdd</receiver>
97
+   <slot>reject()</slot>
98
+   <hints>
99
+    <hint type="sourcelabel">
100
+     <x>316</x>
101
+     <y>260</y>
102
+    </hint>
103
+    <hint type="destinationlabel">
104
+     <x>286</x>
105
+     <y>274</y>
106
+    </hint>
107
+   </hints>
108
+  </connection>
109
+ </connections>
110
+</ui>

+ 30
- 1
akvo/gui/akvoGUI.py View File

@@ -18,6 +18,9 @@ from akvo.gui.main_ui import Ui_MainWindow
18 18
 from akvo.gui.addCircularLoop_ui import Ui_circularLoopAdd
19 19
 from akvo.gui.addFigure8Loop_ui import Ui_figure8LoopAdd
20 20
 from akvo.gui.addPolygonalLoop_ui import Ui_polygonalLoopAdd
21
+from akvo.gui.redirect_ui import Ui_callScript
22
+from akvo.gui.callScript import callScript
23
+
21 24
 from akvo.tressel import mrsurvey 
22 25
 
23 26
 from pyLemma import LemmaCore  
@@ -158,6 +161,10 @@ class ApplicationWindow(QtWidgets.QMainWindow):
158 161
         self.ui.plotGI.setEnabled(False) 
159 162
         self.ui.plotGI.pressed.connect( self.plotGI )
160 163
 
164
+        # Kernel         
165
+        self.ui.calcK0.pressed.connect( self.calcK0 )       
166
+
167
+
161 168
         # META 
162 169
         self.ui.locEdit.editingFinished.connect( self.logSite )
163 170
         self.ui.UTMzone.currentIndexChanged.connect( self.logSite )
@@ -299,6 +306,28 @@ class ApplicationWindow(QtWidgets.QMainWindow):
299 306
             self.ui.ProcTabs.removeTab(0)    
300 307
             self.ui.ProcTabs.removeTab(0)    
301 308
     
309
+    def calcK0(self):
310
+        
311
+        try:
312
+            with open('.akvo.last.path') as f: 
313
+                fpath = f.readline()  
314
+                pass
315
+        except IOError as e:
316
+            fpath = '.'
317
+
318
+        akvoData = QtWidgets.QFileDialog.getOpenFileName(self, 'Open Datafile File', fpath, r"Akvo datafiles (*.yaml)")[0] # arg2 = File Type 'All Files (*)'
319
+        txCoil = QtWidgets.QFileDialog.getOpenFileName(self, 'Open Tx File', fpath, r"Akvo datafiles (*.yaml, *.yml)")[0] # arg2 = File Type 'All Files (*)'
320
+        saveStr = QtWidgets.QFileDialog.getSaveFileName(self, "Save kernel as", fpath, r"Merlin KernelV0 (*.yml)")[0] #[0]
321
+
322
+        callBox = callScript(  ) #QtWidgets.QDialog() 
323
+        
324
+        callBox.ui = Ui_callScript()
325
+        callBox.ui.setupUi( callBox )
326
+        callBox.setupCB( akvoData, txCoil, saveStr  )
327
+        
328
+        callBox.exec_()
329
+        callBox.show()
330
+    
302 331
     def loopAdd(self):
303 332
 
304 333
         #print(self.ui.loopLabel.text())
@@ -329,7 +358,7 @@ class ApplicationWindow(QtWidgets.QMainWindow):
329 358
                     turns = dialog.ui.loopTurns.value()
330 359
                     ns = dialog.ui.segments.value()
331 360
                     cwise = dialog.ui.cwiseBox.currentIndex()
332
-                    print("cwise", cwise)
361
+                    #print("cwise", cwise)
333 362
                     #dip = dialog.ui.dip.value()
334 363
                     #azimuth = dialog.ui.az.value()
335 364
                     

+ 55
- 0
akvo/gui/callScript.py View File

@@ -0,0 +1,55 @@
1
+from PyQt5 import uic
2
+from PyQt5 import QtGui, QtCore
3
+from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication, QTextEdit, QApplication, QDialog
4
+
5
+def p(x):
6
+    print (x)
7
+
8
+class callScript(QDialog):
9
+
10
+    #def __init__(self):
11
+    #    super().__init__()
12
+    
13
+    def setupCB(self, akvoData, TxCoil, SaveStr):
14
+
15
+        #QtGui.QWidget.__init__(self)
16
+        #uic.loadUi('redirect.ui', self)
17
+
18
+        print ('Connecting process')
19
+        self.process = QtCore.QProcess(self)
20
+        self.process.readyReadStandardOutput.connect(self.stdoutReady)
21
+        self.process.readyReadStandardError.connect(self.stderrReady)
22
+        self.process.started.connect(lambda: p('Started!'))
23
+        self.process.finished.connect(lambda: p('Finished!'))
24
+
25
+        print ('Starting process')
26
+        self.process.start('python', ['calcAkvoKernel.py', akvoData, TxCoil, SaveStr])
27
+
28
+    def append(self, text):
29
+        cursor = self.ui.textEdit.textCursor()
30
+        cursor.movePosition(cursor.End)
31
+        cursor.insertText(text)
32
+        self.ui.textEdit.ensureCursorVisible()
33
+        #MyTextEdit.verticalScrollBar()->setValue(MyTextEdit.verticalScrollBar()->maximum());
34
+
35
+
36
+    def stdoutReady(self):
37
+        text = str(self.process.readAllStandardOutput(), encoding='utf-8')
38
+        #print (text) 
39
+        self.append(text)
40
+
41
+    def stderrReady(self):
42
+        text = str(self.process.readAllStandardError())
43
+        #print (text) #.strip())
44
+        self.append(text)
45
+
46
+
47
+#def main():
48
+#    import sys
49
+#    app = QApplication(sys.argv)
50
+#    win = MainWindow()
51
+#    win.show()
52
+#    sys.exit(app.exec_())
53
+    
54
+#if __name__ == '__main__':
55
+   # main()

+ 3370
- 0
akvo/gui/main-bu.ui
File diff suppressed because it is too large
View File


+ 16
- 3
akvo/gui/main.ui View File

@@ -3825,13 +3825,26 @@ background: dark grey;
3825 3825
               <x>30</x>
3826 3826
               <y>320</y>
3827 3827
               <width>351</width>
3828
-              <height>501</height>
3828
+              <height>431</height>
3829 3829
              </rect>
3830 3830
             </property>
3831 3831
             <property name="toolTip">
3832 3832
              <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This table is used to enter coil geometries the format is as follows: each row specifies a single point on a coil. The first column is the coil index (using the GMR channel is useful), the next three colums specify the point in Northing, Easting, and Elevation. These can either be local coordinates or global ones. The final column specifies the loop radius if it is a circle or figure 8, for non circular or figure 8 loops leave this column blank. For figure-8 loops the coils do not need to be touching (see Irons and Kass, 2017). If a given index has 1 row it will be a circular loop, two rows will be a figure 8, and more than that will be a polygonal representation of the points, linearlly interpolated between them. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
3833 3833
             </property>
3834 3834
            </widget>
3835
+           <widget class="QPushButton" name="calcK0">
3836
+            <property name="geometry">
3837
+             <rect>
3838
+              <x>400</x>
3839
+              <y>330</y>
3840
+              <width>105</width>
3841
+              <height>39</height>
3842
+             </rect>
3843
+            </property>
3844
+            <property name="text">
3845
+             <string>Calc Kernel</string>
3846
+            </property>
3847
+           </widget>
3835 3848
           </widget>
3836 3849
           <widget class="QWidget" name="ModelTab">
3837 3850
            <attribute name="title">
@@ -3854,8 +3867,8 @@ background: dark grey;
3854 3867
               <rect>
3855 3868
                <x>0</x>
3856 3869
                <y>0</y>
3857
-               <width>100</width>
3858
-               <height>30</height>
3870
+               <width>96</width>
3871
+               <height>26</height>
3859 3872
               </rect>
3860 3873
              </property>
3861 3874
              <attribute name="label">

+ 57
- 0
akvo/gui/redirect.ui View File

@@ -0,0 +1,57 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<ui version="4.0">
3
+ <class>callScript</class>
4
+ <widget class="QDialog" name="callScript">
5
+  <property name="geometry">
6
+   <rect>
7
+    <x>0</x>
8
+    <y>0</y>
9
+    <width>691</width>
10
+    <height>852</height>
11
+   </rect>
12
+  </property>
13
+  <property name="windowTitle">
14
+   <string>Dialog</string>
15
+  </property>
16
+  <layout class="QVBoxLayout" name="verticalLayout">
17
+   <item>
18
+    <widget class="QStatusBar" name="statusbar"/>
19
+   </item>
20
+   <item>
21
+    <widget class="QTextEdit" name="textEdit">
22
+     <property name="sizePolicy">
23
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
24
+       <horstretch>0</horstretch>
25
+       <verstretch>0</verstretch>
26
+      </sizepolicy>
27
+     </property>
28
+     <property name="font">
29
+      <font>
30
+       <family>Monospace</family>
31
+      </font>
32
+     </property>
33
+     <property name="cursor" stdset="0">
34
+      <cursorShape>IBeamCursor</cursorShape>
35
+     </property>
36
+     <property name="mouseTracking">
37
+      <bool>false</bool>
38
+     </property>
39
+     <property name="readOnly">
40
+      <bool>true</bool>
41
+     </property>
42
+     <property name="overwriteMode">
43
+      <bool>true</bool>
44
+     </property>
45
+     <property name="acceptRichText">
46
+      <bool>false</bool>
47
+     </property>
48
+     <property name="placeholderText">
49
+      <string>This windows outputs STDOUT from a seperate process.</string>
50
+     </property>
51
+    </widget>
52
+   </item>
53
+  </layout>
54
+ </widget>
55
+ <resources/>
56
+ <connections/>
57
+</ui>

+ 2
- 4
akvo/terminal/plotyaml.py View File

@@ -52,7 +52,6 @@ def loadAkvoData(fnamein):
52 52
     return AKVO 
53 53
 
54 54
 def plotQt( akvo ):
55
- 
56 55
     plt.style.use('ggplot')
57 56
     #plt.style.use('seaborn-white')
58 57
     for pulse in akvo.Gated:
@@ -100,10 +99,9 @@ def plotQt( akvo ):
100 99
 
101 100
     #plt.matshow(RE)
102 101
     #plt.matshow(IM)
103
-
104
-
105
-
102
+    plt.savefig("data.pdf")
106 103
     plt.show()
104
+
107 105
 if __name__ == "__main__":
108 106
     akvo = loadAkvoData( sys.argv[1] ) #, "Chan. 1")
109 107
     plotQt(akvo)

+ 127
- 0
akvo/tressel/calcAkvoKernel.py View File

@@ -0,0 +1,127 @@
1
+
2
+import os, sys
3
+import numpy as np
4
+from ruamel import yaml
5
+
6
+import pyLemma.LemmaCore as lc 
7
+import pyLemma.Merlin as mrln 
8
+import pyLemma.FDEM1D as em1d 
9
+
10
+import numpy as np
11
+
12
+import matplotlib.pyplot as plt 
13
+import seaborn as sns
14
+sns.set(style="ticks")
15
+import cmocean 
16
+from SEGPlot import *
17
+from matplotlib.ticker import FormatStrFormatter
18
+import matplotlib.ticker as plticker
19
+
20
+
21
+# Converts Lemma/Merlin/Akvo serialized Eigen arrays into numpy ones for use by Python 
22
+class VectorXr(yaml.YAMLObject):
23
+    """
24
+    Converts Lemma/Merlin/Akvo serialized Eigen arrays into numpy ones for use by Python 
25
+    """
26
+    yaml_tag = u'VectorXr'
27
+    def __init__(self, array):
28
+        self.size = np.shape(array)[0]
29
+        self.data = array.tolist()
30
+    def __repr__(self):
31
+        # Converts to numpy array on import 
32
+        return "np.array(%r)" % (self.data)
33
+
34
+class AkvoData(yaml.YAMLObject):
35
+    """
36
+    Reads an Akvo serialized dataset into a standard python dictionary 
37
+    """
38
+    yaml_tag = u'AkvoData'
39
+    def __init__(self, array):
40
+        pass
41
+        #self.size = np.shape(array)[0]
42
+        #self.Imp = array.tolist()
43
+    def __repr__(self):
44
+        # Converts to a dictionary with Eigen vectors represented as Numpy arrays 
45
+        return self
46
+
47
+def loadAkvoData(fnamein):
48
+    """ Loads data from an Akvo YAML file. The 0.02 is hard coded as the pulse length. This needs to be 
49
+        corrected in future kernel calculations. The current was reported but not the pulse length. 
50
+    """
51
+    fname = (os.path.splitext(fnamein)[0])
52
+    with open(fnamein, 'r') as stream:
53
+        try:
54
+            AKVO = (yaml.load(stream, Loader=yaml.Loader))
55
+        except yaml.YAMLError as exc:
56
+            print(exc)
57
+    return AKVO 
58
+
59
+if __name__ == "__main__":
60
+
61
+    if len(sys.argv) < 3:
62
+        print ("usage  python calcAkvoKernel.py   AkvoDataset.yaml  Coil1.yaml  " )
63
+        exit()
64
+    
65
+    gamma = 2.67518e8
66
+    fL = 2289.
67
+    B0 = (fL*2.*np.pi) /gamma * 1e9
68
+
69
+    AKVO = loadAkvoData(sys.argv[1])
70
+    Coil1 = em1d.PolygonalWireAntenna.DeSerialize( sys.argv[2] )
71
+    Coil1.SetNumberOfFrequencies(1)
72
+    Coil1.SetFrequency(0, fL) 
73
+    Coil1.SetCurrent(1.)
74
+
75
+
76
+    lmod = em1d.LayeredEarthEM() 
77
+    lmod.SetNumberOfLayers(4)
78
+    lmod.SetLayerThickness([15.49, 28.18])
79
+    lmod.SetLayerConductivity([0.0, 1./16.91, 1./24.06, 1./33.23])
80
+    lmod.SetMagneticFieldIncDecMag( 68.9, 0, B0, lc.NANOTESLA )
81
+
82
+
83
+    Kern = mrln.KernelV0()
84
+    Kern.PushCoil( "Coil 1", Coil1 )
85
+    Kern.SetLayeredEarthEM( lmod );
86
+    Kern.SetIntegrationSize( (200,200,200) )
87
+    Kern.SetIntegrationOrigin( (0,0,0) )
88
+    Kern.SetTolerance( 1e-9 )
89
+    Kern.SetMinLevel( 3 )
90
+    Kern.SetHankelTransformType( lc.FHTKEY201 )
91
+    Kern.AlignWithAkvoDataset( sys.argv[1] )
92
+
93
+    thick = np.geomspace(.5, 10,num=40)
94
+    iface = np.cumsum(thick)
95
+    Kern.SetDepthLayerInterfaces(iface)
96
+    #Kern.SetDepthLayerInterfaces(np.geomspace(1, 110, num=40))
97
+    #Kern.SetDepthLayerInterfaces(np.linspace(1, 110, num=50))
98
+    #Kern.SetDepthLayerInterfaces(np.geomspace(1, 110, num=40))
99
+ 
100
+    # autAkvoDataNode = YAML::LoadFile(argv[4]);
101
+    # Kern->AlignWithAkvoDataset( AkvoDataNode );
102
+
103
+    #Kern.SetPulseDuration(0.040)
104
+    #Kern.SetPulseCurrent(  [1.6108818092452406, 1.7549935078885168, 1.7666319459646016, 1.9270787752430283,
105
+    #    1.9455431806179229, 2.111931346726564, 2.1466747256211747, 2.3218217392379588,
106
+    #    2.358359967649008, 2.5495654202189058, 2.5957289164577992, 2.8168532605800802,
107
+    #    2.85505242699187, 3.1599429539069774, 3.2263673040205068, 3.6334182368296544,
108
+    #    3.827985200119751, 4.265671313014058, 4.582237014873297, 5.116839616183394,
109
+    #    5.515173073160611, 6.143620383280934, 6.647972282096122, 7.392577402979211,
110
+    #    8.020737177449933, 8.904435233295793, 9.701975105606063, 10.74508217792577,
111
+    #    11.743887525923592, 12.995985956061467, 14.23723766879807, 15.733870137824457,
112
+    #    17.290155933625808, 19.07016662950366, 21.013341340455703, 23.134181634845618,
113
+    #    25.570925414182238, 28.100862178905476, 31.13848909847073, 34.16791099558486,
114
+    #    37.95775984680512, 41.589619321873165, 46.327607251605286, 50.667786337299205,
115
+    #    56.60102493062895, 61.81174065797068, 69.23049946198458, 75.47409803238031,
116
+    #    84.71658869065816, 92.1855007134236, 103.77129947551164, 112.84577430578537,
117
+    #    127.55127257092909, 138.70199812969176, 157.7443764728878, 171.39653462998626]
118
+    #)
119
+
120
+    Kern.CalculateK0( ["Coil 1"], ["Coil 1"], False )
121
+
122
+    yml = open('akvoK3-' + str(Kern.GetTolerance()) + '.yaml', 'w')
123
+    print(Kern, file=yml)
124
+
125
+    K0 = Kern.GetKernel()
126
+    plt.matshow(np.abs(K0))
127
+    plt.show()

+ 1
- 1
akvo/tressel/mrsurvey.py View File

@@ -1778,7 +1778,7 @@ class GMRDataProcessor(SNMRDataProcessor):
1778 1778
                                                      M, mu, PCA, flambda, H[pulse][ichan])
1779 1779
                             iloop = 0
1780 1780
                             #while False: 
1781
-                            while (np.linalg.norm( H[pulse][ichan] - hm1) > .05):
1781
+                            while (np.linalg.norm( H[pulse][ichan] - hm1) > .05): # threshold for recall 
1782 1782
                                 hm1 = np.copy(H[pulse][ichan]) 
1783 1783
                                 [e, H[pulse][ichan]] = Filt.adapt_filt_Ref( self.DATADICT[pulse][ichan][ipm][istack][::-1],\
1784 1784
                                                         RX,\

+ 4
- 0
pyuic.json View File

@@ -15,6 +15,10 @@
15 15
         [
16 16
             "akvo/gui/addPolygonalLoop.ui",
17 17
             "akvo/gui"
18
+        ],
19
+        [
20
+            "akvo/gui/redirect.ui",
21
+            "akvo/gui"
18 22
         ]
19 23
     ],
20 24
     "pyrcc": "pyrcc5",

+ 2
- 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.3.3',
24
+      version='1.3.4',
25 25
       python_requires='>3.7.0', # due to pyLemma
26 26
       description='Surface nuclear magnetic resonance workbench',
27 27
       long_description=long_description,
@@ -59,6 +59,7 @@ setup(name='Akvo',
59 59
       entry_points = {
60 60
               'console_scripts': [
61 61
                   'akvo = akvo.gui.akvoGUI:main',                  
62
+                  'akvoK0 = akvo.tressel.calcAkvoKernel:main',                  
62 63
               ],              
63 64
           },
64 65
       #cmdclass = cmdclass,

Loading…
Cancel
Save