Browse Source

Pulled SVN into GIT.

HEAD
Trevor Irons 6 years ago
commit
859e00702c

+ 21
- 0
INSTALL.txt View File

1
+Akvo is a surface NMR (sNMR) processing utility. Currently preprocessing is supported, but we are adding inversion capabilities. 
2
+
3
+Installation is done in the typical python fashion
4
+
5
+python setup.py build 
6
+python setup.py build_ui   # OPTIONAL, see below
7
+python setup.py install    # requires sudo on most installations 
8
+
9
+# If you are going to be editing the source code, you may prefer to run 
10
+# the develop option which will not require rerunning the install option 
11
+# for each edit. This is entirely optional 
12
+python setup.py develop    # requires sudo on most installations 
13
+
14
+## Building the user interface 
15
+Akvo ships with a
16
+
17
+## On some platforms you may receive an error regarding PyQt5, it should be possible to manually 
18
+## install this via 
19
+pip install PyQt5 
20
+## Or 
21
+pip3 install PyQt5 

+ 17
- 0
LICENSE.txt View File

1
+Akvo, a surface NMR workbench
2
+Copyright (C) 2014-2017 Trevor P. Irons  
3
+Copyright (C) 2017 M. Andrew Kass  
4
+
5
+This program is free software: you can redistribute it and/or modify
6
+it under the terms of the GNU General Public License as published by
7
+the Free Software Foundation, either version 3 of the License, or
8
+(at your option) any later version.
9
+
10
+This program is distributed in the hope that it will be useful,
11
+but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+GNU General Public License for more details.
14
+
15
+You should have received a copy of the GNU General Public License
16
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
+

+ 1
- 0
akvo/__init__.py View File

1
+#import akvo.tressel.decay

+ 1
- 0
akvo/gui/__init__.py View File

1
+#import mainui.py 

BIN
akvo/gui/akvo-crop.png View File


BIN
akvo/gui/akvo.png View File


BIN
akvo/gui/akvo2.png View File


+ 1097
- 0
akvo/gui/akvoGUI.py
File diff suppressed because it is too large
View File


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


+ 9
- 0
akvo/gui/main2ui.py View File

1
+# -*- coding: utf-8 -*-
2
+
3
+# Form implementation generated from reading ui file 'main.ui'
4
+#
5
+# Created: Fri Jan 11 23:28:48 2013
6
+#      by: PyQt4 UI code generator 4.9.6
7
+#
8
+# WARNING! All changes made in this file will be lost!
9
+

+ 1585
- 0
akvo/gui/mainbu.ui
File diff suppressed because it is too large
View File


+ 1187
- 0
akvo/gui/mainui.py
File diff suppressed because it is too large
View File


+ 586
- 0
akvo/gui/mainui2.py View File

1
+# -*- coding: utf-8 -*-
2
+
3
+# Form implementation generated from reading ui file 'main.ui'
4
+#
5
+# Created: Fri Jan 11 23:34:58 2013
6
+#      by: PyQt4 UI code generator 4.9.6
7
+#
8
+# WARNING! All changes made in this file will be lost!
9
+
10
+from PyQt4 import QtCore, QtGui
11
+
12
+try:
13
+    _fromUtf8 = QtCore.QString.fromUtf8
14
+except AttributeError:
15
+    def _fromUtf8(s):
16
+        return s
17
+
18
+try:
19
+    _encoding = QtGui.QApplication.UnicodeUTF8
20
+    def _translate(context, text, disambig):
21
+        return QtGui.QApplication.translate(context, text, disambig, _encoding)
22
+except AttributeError:
23
+    def _translate(context, text, disambig):
24
+        return QtGui.QApplication.translate(context, text, disambig)
25
+
26
+class Ui_MainWindow(object):
27
+    def setupUi(self, MainWindow):
28
+        MainWindow.setObjectName(_fromUtf8("MainWindow"))
29
+        MainWindow.resize(1000, 980)
30
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Expanding)
31
+        sizePolicy.setHorizontalStretch(0)
32
+        sizePolicy.setVerticalStretch(0)
33
+        sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
34
+        MainWindow.setSizePolicy(sizePolicy)
35
+        MainWindow.setMinimumSize(QtCore.QSize(60, 60))
36
+        MainWindow.setMaximumSize(QtCore.QSize(1000, 16777215))
37
+        MainWindow.setWindowOpacity(1.0)
38
+        MainWindow.setAutoFillBackground(True)
39
+        self.centralwidget = QtGui.QWidget(MainWindow)
40
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
41
+        sizePolicy.setHorizontalStretch(0)
42
+        sizePolicy.setVerticalStretch(0)
43
+        sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth())
44
+        self.centralwidget.setSizePolicy(sizePolicy)
45
+        self.centralwidget.setMinimumSize(QtCore.QSize(0, 0))
46
+        self.centralwidget.setMaximumSize(QtCore.QSize(1000, 16777215))
47
+        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
48
+        self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
49
+        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
50
+        self.scrollArea = QtGui.QScrollArea(self.centralwidget)
51
+        self.scrollArea.setWidgetResizable(True)
52
+        self.scrollArea.setObjectName(_fromUtf8("scrollArea"))
53
+        self.scrollAreaWidgetContents = QtGui.QWidget()
54
+        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 986, 927))
55
+        self.scrollAreaWidgetContents.setObjectName(_fromUtf8("scrollAreaWidgetContents"))
56
+        self.horizontalLayout_2 = QtGui.QHBoxLayout(self.scrollAreaWidgetContents)
57
+        self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
58
+        self.tabWidget = QtGui.QTabWidget(self.scrollAreaWidgetContents)
59
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
60
+        sizePolicy.setHorizontalStretch(0)
61
+        sizePolicy.setVerticalStretch(0)
62
+        sizePolicy.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth())
63
+        self.tabWidget.setSizePolicy(sizePolicy)
64
+        self.tabWidget.setMinimumSize(QtCore.QSize(940, 0))
65
+        self.tabWidget.setObjectName(_fromUtf8("tabWidget"))
66
+        self.tab = QtGui.QWidget()
67
+        self.tab.setObjectName(_fromUtf8("tab"))
68
+        self.gridLayout = QtGui.QGridLayout(self.tab)
69
+        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
70
+        self.groupBox_4 = QtGui.QGroupBox(self.tab)
71
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
72
+        sizePolicy.setHorizontalStretch(0)
73
+        sizePolicy.setVerticalStretch(0)
74
+        sizePolicy.setHeightForWidth(self.groupBox_4.sizePolicy().hasHeightForWidth())
75
+        self.groupBox_4.setSizePolicy(sizePolicy)
76
+        self.groupBox_4.setMinimumSize(QtCore.QSize(480, 150))
77
+        self.groupBox_4.setFlat(False)
78
+        self.groupBox_4.setCheckable(True)
79
+        self.groupBox_4.setObjectName(_fromUtf8("groupBox_4"))
80
+        self.gridLayout.addWidget(self.groupBox_4, 4, 1, 1, 1)
81
+        self.groupBox = QtGui.QGroupBox(self.tab)
82
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
83
+        sizePolicy.setHorizontalStretch(0)
84
+        sizePolicy.setVerticalStretch(0)
85
+        sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth())
86
+        self.groupBox.setSizePolicy(sizePolicy)
87
+        self.groupBox.setMinimumSize(QtCore.QSize(460, 230))
88
+        self.groupBox.setAutoFillBackground(False)
89
+        self.groupBox.setFlat(False)
90
+        self.groupBox.setObjectName(_fromUtf8("groupBox"))
91
+        self.headerFileTextBrowser = QtGui.QTextBrowser(self.groupBox)
92
+        self.headerFileTextBrowser.setGeometry(QtCore.QRect(10, 30, 441, 31))
93
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
94
+        sizePolicy.setHorizontalStretch(0)
95
+        sizePolicy.setVerticalStretch(0)
96
+        sizePolicy.setHeightForWidth(self.headerFileTextBrowser.sizePolicy().hasHeightForWidth())
97
+        self.headerFileTextBrowser.setSizePolicy(sizePolicy)
98
+        font = QtGui.QFont()
99
+        font.setPointSize(8)
100
+        font.setItalic(True)
101
+        self.headerFileTextBrowser.setFont(font)
102
+        self.headerFileTextBrowser.setObjectName(_fromUtf8("headerFileTextBrowser"))
103
+        self.label_4 = QtGui.QLabel(self.groupBox)
104
+        self.label_4.setGeometry(QtCore.QRect(10, 70, 81, 21))
105
+        self.label_4.setObjectName(_fromUtf8("label_4"))
106
+        self.pulseTypeTextBrowser = QtGui.QTextBrowser(self.groupBox)
107
+        self.pulseTypeTextBrowser.setGeometry(QtCore.QRect(90, 70, 361, 21))
108
+        font = QtGui.QFont()
109
+        font.setItalic(True)
110
+        self.pulseTypeTextBrowser.setFont(font)
111
+        self.pulseTypeTextBrowser.setAcceptDrops(True)
112
+        self.pulseTypeTextBrowser.setObjectName(_fromUtf8("pulseTypeTextBrowser"))
113
+        self.lcdNumberNuTx = QtGui.QLCDNumber(self.groupBox)
114
+        self.lcdNumberNuTx.setGeometry(QtCore.QRect(160, 100, 64, 23))
115
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
116
+        sizePolicy.setHorizontalStretch(0)
117
+        sizePolicy.setVerticalStretch(0)
118
+        sizePolicy.setHeightForWidth(self.lcdNumberNuTx.sizePolicy().hasHeightForWidth())
119
+        self.lcdNumberNuTx.setSizePolicy(sizePolicy)
120
+        font = QtGui.QFont()
121
+        font.setPointSize(8)
122
+        self.lcdNumberNuTx.setFont(font)
123
+        self.lcdNumberNuTx.setWhatsThis(_fromUtf8(""))
124
+        self.lcdNumberNuTx.setAutoFillBackground(False)
125
+        self.lcdNumberNuTx.setStyleSheet(_fromUtf8("#lcdNumberNuTx {\n"
126
+"color: green;\n"
127
+"background: black;\n"
128
+"}\n"
129
+"\n"
130
+"#lcdNumberNuTx:disabled {\n"
131
+"color: grey;\n"
132
+"background: black;\n"
133
+"}"))
134
+        self.lcdNumberNuTx.setFrameShadow(QtGui.QFrame.Raised)
135
+        self.lcdNumberNuTx.setLineWidth(1)
136
+        self.lcdNumberNuTx.setMidLineWidth(0)
137
+        self.lcdNumberNuTx.setSegmentStyle(QtGui.QLCDNumber.Flat)
138
+        self.lcdNumberNuTx.setProperty("value", 0.0)
139
+        self.lcdNumberNuTx.setObjectName(_fromUtf8("lcdNumberNuTx"))
140
+        self.lcdNumberTuneuF = QtGui.QLCDNumber(self.groupBox)
141
+        self.lcdNumberTuneuF.setGeometry(QtCore.QRect(370, 100, 64, 23))
142
+        self.lcdNumberTuneuF.setStyleSheet(_fromUtf8("#lcdNumberTuneuF {\n"
143
+"color: green;\n"
144
+"background: black;\n"
145
+"}\n"
146
+"\n"
147
+"#lcdNumberTuneuF:disabled {\n"
148
+"color: grey;\n"
149
+"background: black;\n"
150
+"}"))
151
+        self.lcdNumberTuneuF.setLineWidth(1)
152
+        self.lcdNumberTuneuF.setMidLineWidth(0)
153
+        self.lcdNumberTuneuF.setSegmentStyle(QtGui.QLCDNumber.Flat)
154
+        self.lcdNumberTuneuF.setObjectName(_fromUtf8("lcdNumberTuneuF"))
155
+        self.lcdNumberTauPulse1 = QtGui.QLCDNumber(self.groupBox)
156
+        self.lcdNumberTauPulse1.setGeometry(QtCore.QRect(160, 130, 64, 23))
157
+        self.lcdNumberTauPulse1.setStyleSheet(_fromUtf8("#lcdNumberTauPulse1 {\n"
158
+"color: green;\n"
159
+"background: black;\n"
160
+"}\n"
161
+"\n"
162
+"#lcdNumberTauPulse1:disabled {\n"
163
+"color: grey;\n"
164
+"background: black;\n"
165
+"}"))
166
+        self.lcdNumberTauPulse1.setFrameShadow(QtGui.QFrame.Raised)
167
+        self.lcdNumberTauPulse1.setLineWidth(1)
168
+        self.lcdNumberTauPulse1.setMidLineWidth(0)
169
+        self.lcdNumberTauPulse1.setSegmentStyle(QtGui.QLCDNumber.Flat)
170
+        self.lcdNumberTauPulse1.setObjectName(_fromUtf8("lcdNumberTauPulse1"))
171
+        self.label_6 = QtGui.QLabel(self.groupBox)
172
+        self.label_6.setGeometry(QtCore.QRect(10, 100, 91, 21))
173
+        self.label_6.setObjectName(_fromUtf8("label_6"))
174
+        self.label_7 = QtGui.QLabel(self.groupBox)
175
+        self.label_7.setGeometry(QtCore.QRect(10, 130, 141, 21))
176
+        self.label_7.setObjectName(_fromUtf8("label_7"))
177
+        self.label_13 = QtGui.QLabel(self.groupBox)
178
+        self.label_13.setGeometry(QtCore.QRect(260, 160, 91, 21))
179
+        self.label_13.setObjectName(_fromUtf8("label_13"))
180
+        self.lcdNumberTauPulse2 = QtGui.QLCDNumber(self.groupBox)
181
+        self.lcdNumberTauPulse2.setGeometry(QtCore.QRect(160, 160, 64, 23))
182
+        self.lcdNumberTauPulse2.setStyleSheet(_fromUtf8("#lcdNumberTauPulse2 {\n"
183
+"color: green;\n"
184
+"background: black;\n"
185
+"}\n"
186
+"\n"
187
+"#lcdNumberTauPulse2:disabled{\n"
188
+"color: grey;\n"
189
+"background: black;\n"
190
+"}"))
191
+        self.lcdNumberTauPulse2.setLineWidth(1)
192
+        self.lcdNumberTauPulse2.setMidLineWidth(0)
193
+        self.lcdNumberTauPulse2.setSegmentStyle(QtGui.QLCDNumber.Flat)
194
+        self.lcdNumberTauPulse2.setObjectName(_fromUtf8("lcdNumberTauPulse2"))
195
+        self.label_14 = QtGui.QLabel(self.groupBox)
196
+        self.label_14.setGeometry(QtCore.QRect(260, 100, 111, 21))
197
+        self.label_14.setObjectName(_fromUtf8("label_14"))
198
+        self.label_15 = QtGui.QLabel(self.groupBox)
199
+        self.label_15.setGeometry(QtCore.QRect(260, 130, 111, 21))
200
+        self.label_15.setObjectName(_fromUtf8("label_15"))
201
+        self.lcdNumberSampFreq = QtGui.QLCDNumber(self.groupBox)
202
+        self.lcdNumberSampFreq.setEnabled(True)
203
+        self.lcdNumberSampFreq.setGeometry(QtCore.QRect(370, 130, 64, 23))
204
+        self.lcdNumberSampFreq.setStyleSheet(_fromUtf8("#lcdNumberSampFreq {\n"
205
+"color: green;\n"
206
+"background: black;\n"
207
+"}\n"
208
+"\n"
209
+"#lcdNumberSampFreq:disabled{\n"
210
+"color: grey;\n"
211
+"background: black;\n"
212
+"}"))
213
+        self.lcdNumberSampFreq.setLineWidth(1)
214
+        self.lcdNumberSampFreq.setMidLineWidth(0)
215
+        self.lcdNumberSampFreq.setDigitCount(5)
216
+        self.lcdNumberSampFreq.setSegmentStyle(QtGui.QLCDNumber.Flat)
217
+        self.lcdNumberSampFreq.setObjectName(_fromUtf8("lcdNumberSampFreq"))
218
+        self.lcdNumberTauDelay = QtGui.QLCDNumber(self.groupBox)
219
+        self.lcdNumberTauDelay.setEnabled(True)
220
+        self.lcdNumberTauDelay.setGeometry(QtCore.QRect(370, 160, 64, 23))
221
+        self.lcdNumberTauDelay.setStyleSheet(_fromUtf8("#lcdNumberTauDelay {\n"
222
+"color: green;\n"
223
+"background: black;\n"
224
+"}\n"
225
+"\n"
226
+"#lcdNumberTauDelay:disabled {\n"
227
+"color: grey;\n"
228
+"background: black;\n"
229
+"}"))
230
+        self.lcdNumberTauDelay.setLineWidth(1)
231
+        self.lcdNumberTauDelay.setMidLineWidth(0)
232
+        self.lcdNumberTauDelay.setSegmentStyle(QtGui.QLCDNumber.Flat)
233
+        self.lcdNumberTauDelay.setObjectName(_fromUtf8("lcdNumberTauDelay"))
234
+        self.label_16 = QtGui.QLabel(self.groupBox)
235
+        self.label_16.setGeometry(QtCore.QRect(10, 160, 131, 21))
236
+        self.label_16.setObjectName(_fromUtf8("label_16"))
237
+        self.lcdNumberNQ = QtGui.QLCDNumber(self.groupBox)
238
+        self.lcdNumberNQ.setGeometry(QtCore.QRect(160, 190, 64, 23))
239
+        self.lcdNumberNQ.setStyleSheet(_fromUtf8("#lcdNumberNQ {\n"
240
+"color: green;\n"
241
+"background: black;\n"
242
+"}\n"
243
+"\n"
244
+"#lcdNumberNQ:disabled{\n"
245
+"color: grey;\n"
246
+"background: black;\n"
247
+"}"))
248
+        self.lcdNumberNQ.setSegmentStyle(QtGui.QLCDNumber.Flat)
249
+        self.lcdNumberNQ.setObjectName(_fromUtf8("lcdNumberNQ"))
250
+        self.label_9 = QtGui.QLabel(self.groupBox)
251
+        self.label_9.setGeometry(QtCore.QRect(10, 190, 141, 21))
252
+        self.label_9.setObjectName(_fromUtf8("label_9"))
253
+        self.gridLayout.addWidget(self.groupBox, 4, 0, 1, 1)
254
+        self.groupBox_10 = QtGui.QGroupBox(self.tab)
255
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
256
+        sizePolicy.setHorizontalStretch(0)
257
+        sizePolicy.setVerticalStretch(0)
258
+        sizePolicy.setHeightForWidth(self.groupBox_10.sizePolicy().hasHeightForWidth())
259
+        self.groupBox_10.setSizePolicy(sizePolicy)
260
+        self.groupBox_10.setMinimumSize(QtCore.QSize(460, 160))
261
+        self.groupBox_10.setObjectName(_fromUtf8("groupBox_10"))
262
+        self.stacksLineEdit = QtGui.QLineEdit(self.groupBox_10)
263
+        self.stacksLineEdit.setGeometry(QtCore.QRect(110, 30, 91, 21))
264
+        self.stacksLineEdit.setToolTip(_fromUtf8("<html><head/><body><p>Set the stacks that you would like processed.</p><p>This must be a valid set of numpy array indices. Remember that Python uses non end-inclusive indexing. </p><p>So things like [1:24] will include stacks 1-23</p><p>Furthermore [1:8,12:24] will include stacks 1-7 and 12:23. Any list of valid indices will be accepted, but they must be comma seperated. </p></body></html>"))
265
+        self.stacksLineEdit.setObjectName(_fromUtf8("stacksLineEdit"))
266
+        self.label = QtGui.QLabel(self.groupBox_10)
267
+        self.label.setGeometry(QtCore.QRect(10, 30, 51, 20))
268
+        self.label.setToolTip(_fromUtf8(""))
269
+        self.label.setStatusTip(_fromUtf8(""))
270
+        self.label.setObjectName(_fromUtf8("label"))
271
+        self.label_23 = QtGui.QLabel(self.groupBox_10)
272
+        self.label_23.setGeometry(QtCore.QRect(10, 65, 101, 16))
273
+        self.label_23.setObjectName(_fromUtf8("label_23"))
274
+        self.dataChanLineEdit = QtGui.QLineEdit(self.groupBox_10)
275
+        self.dataChanLineEdit.setGeometry(QtCore.QRect(110, 60, 91, 21))
276
+        self.dataChanLineEdit.setObjectName(_fromUtf8("dataChanLineEdit"))
277
+        self.label_24 = QtGui.QLabel(self.groupBox_10)
278
+        self.label_24.setGeometry(QtCore.QRect(220, 36, 101, 16))
279
+        self.label_24.setObjectName(_fromUtf8("label_24"))
280
+        self.DeadTimeSpinBox = QtGui.QDoubleSpinBox(self.groupBox_10)
281
+        self.DeadTimeSpinBox.setGeometry(QtCore.QRect(360, 30, 91, 25))
282
+        self.DeadTimeSpinBox.setMinimum(5.0)
283
+        self.DeadTimeSpinBox.setSingleStep(0.5)
284
+        self.DeadTimeSpinBox.setProperty("value", 5.0)
285
+        self.DeadTimeSpinBox.setObjectName(_fromUtf8("DeadTimeSpinBox"))
286
+        self.label_28 = QtGui.QLabel(self.groupBox_10)
287
+        self.label_28.setGeometry(QtCore.QRect(220, 64, 131, 16))
288
+        self.label_28.setObjectName(_fromUtf8("label_28"))
289
+        self.refChanLineEdit = QtGui.QLineEdit(self.groupBox_10)
290
+        self.refChanLineEdit.setGeometry(QtCore.QRect(360, 60, 91, 21))
291
+        self.refChanLineEdit.setObjectName(_fromUtf8("refChanLineEdit"))
292
+        self.label_30 = QtGui.QLabel(self.groupBox_10)
293
+        self.label_30.setGeometry(QtCore.QRect(12, 96, 91, 16))
294
+        self.label_30.setObjectName(_fromUtf8("label_30"))
295
+        self.CentralVSpinBox = QtGui.QDoubleSpinBox(self.groupBox_10)
296
+        self.CentralVSpinBox.setGeometry(QtCore.QRect(110, 90, 91, 25))
297
+        self.CentralVSpinBox.setMinimum(100.0)
298
+        self.CentralVSpinBox.setMaximum(5000.99)
299
+        self.CentralVSpinBox.setSingleStep(1.0)
300
+        self.CentralVSpinBox.setObjectName(_fromUtf8("CentralVSpinBox"))
301
+        self.label_29 = QtGui.QLabel(self.groupBox_10)
302
+        self.label_29.setGeometry(QtCore.QRect(220, 95, 111, 16))
303
+        self.label_29.setObjectName(_fromUtf8("label_29"))
304
+        self.FIDProcComboBox = QtGui.QComboBox(self.groupBox_10)
305
+        self.FIDProcComboBox.setGeometry(QtCore.QRect(360, 90, 91, 25))
306
+        self.FIDProcComboBox.setObjectName(_fromUtf8("FIDProcComboBox"))
307
+        self.fullWorkflowPushButton = QtGui.QPushButton(self.groupBox_10)
308
+        self.fullWorkflowPushButton.setGeometry(QtCore.QRect(280, 130, 131, 31))
309
+        self.fullWorkflowPushButton.setAutoFillBackground(False)
310
+        self.fullWorkflowPushButton.setStyleSheet(_fromUtf8("#fullWorkflowPushButton {\n"
311
+"background: green;\n"
312
+"}"))
313
+        self.fullWorkflowPushButton.setAutoDefault(False)
314
+        self.fullWorkflowPushButton.setDefault(False)
315
+        self.fullWorkflowPushButton.setFlat(False)
316
+        self.fullWorkflowPushButton.setObjectName(_fromUtf8("fullWorkflowPushButton"))
317
+        self.loadDataPushButton = QtGui.QPushButton(self.groupBox_10)
318
+        self.loadDataPushButton.setGeometry(QtCore.QRect(90, 130, 91, 31))
319
+        self.loadDataPushButton.setObjectName(_fromUtf8("loadDataPushButton"))
320
+        self.gridLayout.addWidget(self.groupBox_10, 5, 0, 1, 1)
321
+        self.groupBox_9 = QtGui.QGroupBox(self.tab)
322
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
323
+        sizePolicy.setHorizontalStretch(0)
324
+        sizePolicy.setVerticalStretch(0)
325
+        sizePolicy.setHeightForWidth(self.groupBox_9.sizePolicy().hasHeightForWidth())
326
+        self.groupBox_9.setSizePolicy(sizePolicy)
327
+        self.groupBox_9.setMinimumSize(QtCore.QSize(480, 100))
328
+        self.groupBox_9.setCheckable(True)
329
+        self.groupBox_9.setObjectName(_fromUtf8("groupBox_9"))
330
+        self.checkBox = QtGui.QCheckBox(self.groupBox_9)
331
+        self.checkBox.setGeometry(QtCore.QRect(30, 30, 171, 20))
332
+        self.checkBox.setObjectName(_fromUtf8("checkBox"))
333
+        self.comboBox_2 = QtGui.QComboBox(self.groupBox_9)
334
+        self.comboBox_2.setGeometry(QtCore.QRect(130, 50, 78, 25))
335
+        self.comboBox_2.setObjectName(_fromUtf8("comboBox_2"))
336
+        self.label_5 = QtGui.QLabel(self.groupBox_9)
337
+        self.label_5.setGeometry(QtCore.QRect(40, 60, 71, 16))
338
+        self.label_5.setObjectName(_fromUtf8("label_5"))
339
+        self.doubleSpinBox = QtGui.QDoubleSpinBox(self.groupBox_9)
340
+        self.doubleSpinBox.setGeometry(QtCore.QRect(390, 20, 62, 25))
341
+        self.doubleSpinBox.setObjectName(_fromUtf8("doubleSpinBox"))
342
+        self.label_8 = QtGui.QLabel(self.groupBox_9)
343
+        self.label_8.setGeometry(QtCore.QRect(220, 20, 161, 20))
344
+        self.label_8.setObjectName(_fromUtf8("label_8"))
345
+        self.gridLayout.addWidget(self.groupBox_9, 5, 1, 1, 1)
346
+        self.groupBox_7 = QtGui.QGroupBox(self.tab)
347
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
348
+        sizePolicy.setHorizontalStretch(0)
349
+        sizePolicy.setVerticalStretch(0)
350
+        sizePolicy.setHeightForWidth(self.groupBox_7.sizePolicy().hasHeightForWidth())
351
+        self.groupBox_7.setSizePolicy(sizePolicy)
352
+        self.groupBox_7.setMinimumSize(QtCore.QSize(480, 100))
353
+        self.groupBox_7.setCheckable(True)
354
+        self.groupBox_7.setObjectName(_fromUtf8("groupBox_7"))
355
+        self.comboBox = QtGui.QComboBox(self.groupBox_7)
356
+        self.comboBox.setGeometry(QtCore.QRect(40, 30, 141, 22))
357
+        self.comboBox.setMouseTracking(True)
358
+        self.comboBox.setToolTip(_fromUtf8(""))
359
+        self.comboBox.setStatusTip(_fromUtf8(""))
360
+        self.comboBox.setWhatsThis(_fromUtf8(""))
361
+        self.comboBox.setObjectName(_fromUtf8("comboBox"))
362
+        self.comboBox.addItem(_fromUtf8(""))
363
+        self.comboBox.addItem(_fromUtf8(""))
364
+        self.gridLayout.addWidget(self.groupBox_7, 2, 1, 1, 1)
365
+        self.label_2 = QtGui.QLabel(self.tab)
366
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
367
+        sizePolicy.setHorizontalStretch(0)
368
+        sizePolicy.setVerticalStretch(0)
369
+        sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth())
370
+        self.label_2.setSizePolicy(sizePolicy)
371
+        font = QtGui.QFont()
372
+        font.setPointSize(20)
373
+        font.setBold(True)
374
+        font.setWeight(75)
375
+        self.label_2.setFont(font)
376
+        self.label_2.setLayoutDirection(QtCore.Qt.LeftToRight)
377
+        self.label_2.setObjectName(_fromUtf8("label_2"))
378
+        self.gridLayout.addWidget(self.label_2, 0, 1, 1, 1)
379
+        self.groupBox_8 = QtGui.QGroupBox(self.tab)
380
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
381
+        sizePolicy.setHorizontalStretch(0)
382
+        sizePolicy.setVerticalStretch(0)
383
+        sizePolicy.setHeightForWidth(self.groupBox_8.sizePolicy().hasHeightForWidth())
384
+        self.groupBox_8.setSizePolicy(sizePolicy)
385
+        self.groupBox_8.setMinimumSize(QtCore.QSize(480, 150))
386
+        self.groupBox_8.setCheckable(True)
387
+        self.groupBox_8.setObjectName(_fromUtf8("groupBox_8"))
388
+        self.label_3 = QtGui.QLabel(self.groupBox_8)
389
+        self.label_3.setGeometry(QtCore.QRect(30, 60, 111, 16))
390
+        self.label_3.setObjectName(_fromUtf8("label_3"))
391
+        self.spinBox = QtGui.QSpinBox(self.groupBox_8)
392
+        self.spinBox.setGeometry(QtCore.QRect(140, 60, 101, 25))
393
+        self.spinBox.setMaximum(1000)
394
+        self.spinBox.setProperty("value", 300)
395
+        self.spinBox.setObjectName(_fromUtf8("spinBox"))
396
+        self.gridLayout.addWidget(self.groupBox_8, 3, 1, 1, 1)
397
+        self.groupBox_5 = QtGui.QGroupBox(self.tab)
398
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
399
+        sizePolicy.setHorizontalStretch(0)
400
+        sizePolicy.setVerticalStretch(0)
401
+        sizePolicy.setHeightForWidth(self.groupBox_5.sizePolicy().hasHeightForWidth())
402
+        self.groupBox_5.setSizePolicy(sizePolicy)
403
+        self.groupBox_5.setMinimumSize(QtCore.QSize(480, 150))
404
+        self.groupBox_5.setCheckable(True)
405
+        self.groupBox_5.setObjectName(_fromUtf8("groupBox_5"))
406
+        self.gridLayout.addWidget(self.groupBox_5, 1, 1, 1, 1)
407
+        self.mplwidget = MyDynamicMplCanvas(self.tab)
408
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
409
+        sizePolicy.setHorizontalStretch(0)
410
+        sizePolicy.setVerticalStretch(0)
411
+        sizePolicy.setHeightForWidth(self.mplwidget.sizePolicy().hasHeightForWidth())
412
+        self.mplwidget.setSizePolicy(sizePolicy)
413
+        self.mplwidget.setMinimumSize(QtCore.QSize(460, 460))
414
+        self.mplwidget.setObjectName(_fromUtf8("mplwidget"))
415
+        self.gridLayout.addWidget(self.mplwidget, 0, 0, 4, 1)
416
+        self.tabWidget.addTab(self.tab, _fromUtf8(""))
417
+        self.tab_3 = QtGui.QWidget()
418
+        self.tab_3.setObjectName(_fromUtf8("tab_3"))
419
+        self.treeWidget = QtGui.QTreeWidget(self.tab_3)
420
+        self.treeWidget.setGeometry(QtCore.QRect(70, 50, 256, 192))
421
+        self.treeWidget.setObjectName(_fromUtf8("treeWidget"))
422
+        self.treeWidget.headerItem().setText(0, _fromUtf8("1"))
423
+        self.toolBox = QtGui.QToolBox(self.tab_3)
424
+        self.toolBox.setGeometry(QtCore.QRect(320, 460, 79, 137))
425
+        self.toolBox.setObjectName(_fromUtf8("toolBox"))
426
+        self.page = QtGui.QWidget()
427
+        self.page.setGeometry(QtCore.QRect(0, 0, 94, 24))
428
+        self.page.setObjectName(_fromUtf8("page"))
429
+        self.toolBox.addItem(self.page, _fromUtf8(""))
430
+        self.page_2 = QtGui.QWidget()
431
+        self.page_2.setGeometry(QtCore.QRect(0, 0, 94, 24))
432
+        self.page_2.setObjectName(_fromUtf8("page_2"))
433
+        self.toolBox.addItem(self.page_2, _fromUtf8(""))
434
+        self.dateEdit = QtGui.QDateEdit(self.tab_3)
435
+        self.dateEdit.setGeometry(QtCore.QRect(400, 280, 110, 25))
436
+        self.dateEdit.setObjectName(_fromUtf8("dateEdit"))
437
+        self.tabWidget.addTab(self.tab_3, _fromUtf8(""))
438
+        self.tab_2 = QtGui.QWidget()
439
+        self.tab_2.setObjectName(_fromUtf8("tab_2"))
440
+        self.dateEdit_2 = QtGui.QDateEdit(self.tab_2)
441
+        self.dateEdit_2.setGeometry(QtCore.QRect(50, 100, 110, 25))
442
+        self.dateEdit_2.setObjectName(_fromUtf8("dateEdit_2"))
443
+        self.tabWidget.addTab(self.tab_2, _fromUtf8(""))
444
+        self.tab_6 = QtGui.QWidget()
445
+        self.tab_6.setObjectName(_fromUtf8("tab_6"))
446
+        self.tabWidget.addTab(self.tab_6, _fromUtf8(""))
447
+        self.tab_4 = QtGui.QWidget()
448
+        self.tab_4.setObjectName(_fromUtf8("tab_4"))
449
+        self.invertButton = QtGui.QPushButton(self.tab_4)
450
+        self.invertButton.setGeometry(QtCore.QRect(290, 140, 311, 141))
451
+        self.invertButton.setStyleSheet(_fromUtf8("#invertButton {\n"
452
+"font-size:29pt;\n"
453
+"font-weight: bold;\n"
454
+"color: white;\n"
455
+"background: red;\n"
456
+"}"))
457
+        self.invertButton.setObjectName(_fromUtf8("invertButton"))
458
+        self.tabWidget.addTab(self.tab_4, _fromUtf8(""))
459
+        self.tab_5 = QtGui.QWidget()
460
+        self.tab_5.setObjectName(_fromUtf8("tab_5"))
461
+        self.tabWidget.addTab(self.tab_5, _fromUtf8(""))
462
+        self.horizontalLayout_2.addWidget(self.tabWidget)
463
+        self.scrollArea.setWidget(self.scrollAreaWidgetContents)
464
+        self.horizontalLayout.addWidget(self.scrollArea)
465
+        MainWindow.setCentralWidget(self.centralwidget)
466
+        self.menubar = QtGui.QMenuBar(MainWindow)
467
+        self.menubar.setGeometry(QtCore.QRect(0, 0, 1000, 20))
468
+        self.menubar.setObjectName(_fromUtf8("menubar"))
469
+        self.menuFile = QtGui.QMenu(self.menubar)
470
+        self.menuFile.setObjectName(_fromUtf8("menuFile"))
471
+        self.menuAbout = QtGui.QMenu(self.menubar)
472
+        self.menuAbout.setObjectName(_fromUtf8("menuAbout"))
473
+        MainWindow.setMenuBar(self.menubar)
474
+        self.statusbar = QtGui.QStatusBar(MainWindow)
475
+        self.statusbar.setObjectName(_fromUtf8("statusbar"))
476
+        MainWindow.setStatusBar(self.statusbar)
477
+        self.actionClose = QtGui.QAction(MainWindow)
478
+        self.actionClose.setObjectName(_fromUtf8("actionClose"))
479
+        self.actionAboutBrewCentral = QtGui.QAction(MainWindow)
480
+        self.actionAboutBrewCentral.setObjectName(_fromUtf8("actionAboutBrewCentral"))
481
+        self.actionNothing = QtGui.QAction(MainWindow)
482
+        self.actionNothing.setObjectName(_fromUtf8("actionNothing"))
483
+        self.actionTemperature = QtGui.QAction(MainWindow)
484
+        self.actionTemperature.setObjectName(_fromUtf8("actionTemperature"))
485
+        self.actionOpen_GMR = QtGui.QAction(MainWindow)
486
+        self.actionOpen_GMR.setCheckable(False)
487
+        self.actionOpen_GMR.setObjectName(_fromUtf8("actionOpen_GMR"))
488
+        self.actionProcess = QtGui.QAction(MainWindow)
489
+        self.actionProcess.setCheckable(True)
490
+        self.actionProcess.setObjectName(_fromUtf8("actionProcess"))
491
+        self.actionOpen_Preprocessed_dataset = QtGui.QAction(MainWindow)
492
+        self.actionOpen_Preprocessed_dataset.setEnabled(False)
493
+        self.actionOpen_Preprocessed_dataset.setObjectName(_fromUtf8("actionOpen_Preprocessed_dataset"))
494
+        self.actionOpen_VC_Preprocessed_dataset = QtGui.QAction(MainWindow)
495
+        self.actionOpen_VC_Preprocessed_dataset.setEnabled(False)
496
+        self.actionOpen_VC_Preprocessed_dataset.setObjectName(_fromUtf8("actionOpen_VC_Preprocessed_dataset"))
497
+        self.actionSave_Preprocesssed_Dataset = QtGui.QAction(MainWindow)
498
+        self.actionSave_Preprocesssed_Dataset.setEnabled(False)
499
+        self.actionSave_Preprocesssed_Dataset.setObjectName(_fromUtf8("actionSave_Preprocesssed_Dataset"))
500
+        self.menuFile.addAction(self.actionOpen_GMR)
501
+        self.menuFile.addSeparator()
502
+        self.menuFile.addAction(self.actionOpen_Preprocessed_dataset)
503
+        self.menuFile.addAction(self.actionOpen_VC_Preprocessed_dataset)
504
+        self.menuFile.addSeparator()
505
+        self.menuFile.addAction(self.actionSave_Preprocesssed_Dataset)
506
+        self.menuFile.addSeparator()
507
+        self.menuFile.addAction(self.actionClose)
508
+        self.menuAbout.addAction(self.actionAboutBrewCentral)
509
+        self.menubar.addAction(self.menuFile.menuAction())
510
+        self.menubar.addAction(self.menuAbout.menuAction())
511
+
512
+        self.retranslateUi(MainWindow)
513
+        self.tabWidget.setCurrentIndex(0)
514
+        self.toolBox.setCurrentIndex(0)
515
+        QtCore.QObject.connect(self.actionClose, QtCore.SIGNAL(_fromUtf8("activated()")), MainWindow.close)
516
+        QtCore.QObject.connect(self.actionAboutBrewCentral, QtCore.SIGNAL(_fromUtf8("activated()")), MainWindow.show)
517
+        QtCore.QMetaObject.connectSlotsByName(MainWindow)
518
+
519
+    def retranslateUi(self, MainWindow):
520
+        MainWindow.setWindowTitle(_translate("MainWindow", "Avko - sNMR Workbench", None))
521
+        self.groupBox_4.setTitle(_translate("MainWindow", "Adaptive Noise Suppresion", None))
522
+        self.groupBox.setTitle(_translate("MainWindow", "Header file info", None))
523
+        self.headerFileTextBrowser.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
524
+"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
525
+"p, li { white-space: pre-wrap; }\n"
526
+"</style></head><body style=\" font-family:\'Sans Serif\'; font-size:8pt; font-weight:400; font-style:italic;\">\n"
527
+"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'DejaVu Serif\'; font-size:9pt;\">Load supported RAW Dataset header from file menu</span></p></body></html>", None))
528
+        self.label_4.setText(_translate("MainWindow", "Pulse Type", None))
529
+        self.pulseTypeTextBrowser.setHtml(_translate("MainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
530
+"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
531
+"p, li { white-space: pre-wrap; }\n"
532
+"</style></head><body style=\" font-family:\'Sans Serif\'; font-size:9pt; font-weight:400; font-style:italic;\">\n"
533
+"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:\'DejaVu Serif\'; font-size:10pt;\"><br /></p></body></html>", None))
534
+        self.label_6.setText(_translate("MainWindow", "ν Tx  [Hz]", None))
535
+        self.label_7.setText(_translate("MainWindow", "τ Pulse 1 [ms]", None))
536
+        self.label_13.setText(_translate("MainWindow", "τ Delay [ms]", None))
537
+        self.label_14.setText(_translate("MainWindow", "Tx tuning [μF]", None))
538
+        self.label_15.setText(_translate("MainWindow", "ν Sampling [Hz]", None))
539
+        self.label_16.setText(_translate("MainWindow", "τ Pulse 2 [ms]", None))
540
+        self.label_9.setText(_translate("MainWindow", "Num. pulse moments", None))
541
+        self.groupBox_10.setTitle(_translate("MainWindow", "Input parameters", None))
542
+        self.label.setText(_translate("MainWindow", "Stacks", None))
543
+        self.label_23.setText(_translate("MainWindow", "Data Channels", None))
544
+        self.label_24.setText(_translate("MainWindow", "Dead time [ms]", None))
545
+        self.label_28.setText(_translate("MainWindow", "Reference Channels", None))
546
+        self.label_30.setText(_translate("MainWindow", "Central ν Hz", None))
547
+        self.CentralVSpinBox.setToolTip(_translate("MainWindow", "<html><head/><body><p>In case of off-resonant transmitter pulse, you can set the central frequency that will be used for all processing. This has the biggest impact on the band-pass filter, and the frequencies used in inversion. </p></body></html>", None))
548
+        self.label_29.setText(_translate("MainWindow", "Process FID #", None))
549
+        self.FIDProcComboBox.setToolTip(_translate("MainWindow", "<html><head/><body><p>For T1 or CPMG pulses, which pulse(s) would you like to process. Note that for very short delay T1 pulses, the first pulse may be disabled. </p></body></html>", None))
550
+        self.fullWorkflowPushButton.setText(_translate("MainWindow", "Full Workflow", None))
551
+        self.loadDataPushButton.setText(_translate("MainWindow", "Load Data", None))
552
+        self.groupBox_9.setTitle(_translate("MainWindow", "SmartStack^TM", None))
553
+        self.checkBox.setText(_translate("MainWindow", "Correct phase jitter", None))
554
+        self.label_5.setText(_translate("MainWindow", "Outlier test", None))
555
+        self.label_8.setText(_translate("MainWindow", "Instrument phase delay", None))
556
+        self.groupBox_7.setTitle(_translate("MainWindow", "Band-Pass Filter", None))
557
+        self.comboBox.setAccessibleDescription(_translate("MainWindow", "Hello", None))
558
+        self.comboBox.setItemText(0, _translate("MainWindow", "Butterworth", None))
559
+        self.comboBox.setItemText(1, _translate("MainWindow", "Chebychev Type II", None))
560
+        self.label_2.setText(_translate("MainWindow", "         Preprocessing Workflow", None))
561
+        self.groupBox_8.setTitle(_translate("MainWindow", "Downsample and truncate", None))
562
+        self.label_3.setText(_translate("MainWindow", "Truncate [ms]", None))
563
+        self.groupBox_5.setTitle(_translate("MainWindow", "Despike Filter", None))
564
+        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Preprocess RAW", None))
565
+        self.toolBox.setItemText(self.toolBox.indexOf(self.page), _translate("MainWindow", "Page 1", None))
566
+        self.toolBox.setItemText(self.toolBox.indexOf(self.page_2), _translate("MainWindow", "Page 2", None))
567
+        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "Data QC", None))
568
+        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Model Parameters", None))
569
+        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_6), _translate("MainWindow", "Forward modelling", None))
570
+        self.invertButton.setText(_translate("MainWindow", "Invert", None))
571
+        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), _translate("MainWindow", "Inversion", None))
572
+        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_5), _translate("MainWindow", "Analysis", None))
573
+        self.menuFile.setTitle(_translate("MainWindow", "&File", None))
574
+        self.menuAbout.setTitle(_translate("MainWindow", "About", None))
575
+        self.actionClose.setText(_translate("MainWindow", "&Close", None))
576
+        self.actionAboutBrewCentral.setText(_translate("MainWindow", "Brew Central", None))
577
+        self.actionNothing.setText(_translate("MainWindow", "Nothing", None))
578
+        self.actionTemperature.setText(_translate("MainWindow", "Temperature", None))
579
+        self.actionOpen_GMR.setText(_translate("MainWindow", "Open GMR RAW header", None))
580
+        self.actionOpen_GMR.setIconText(_translate("MainWindow", "Open GMR RAW dataset(s)", None))
581
+        self.actionProcess.setText(_translate("MainWindow", "Process", None))
582
+        self.actionOpen_Preprocessed_dataset.setText(_translate("MainWindow", "Open Avko Preprocessed dataset", None))
583
+        self.actionOpen_VC_Preprocessed_dataset.setText(_translate("MainWindow", "Open VC Preprocessed dataset", None))
584
+        self.actionSave_Preprocesssed_Dataset.setText(_translate("MainWindow", "Save Preprocesssed Dataset", None))
585
+
586
+from mydynamicmplcanvas import MyDynamicMplCanvas

+ 299
- 0
akvo/gui/mydynamicmplcanvas.py View File

1
+from __future__ import unicode_literals
2
+import sys
3
+import os
4
+import random
5
+import matplotlib
6
+# Make sure that we are using QT5
7
+matplotlib.use('Qt5Agg')
8
+from PyQt5 import QtCore, QtWidgets
9
+
10
+from numpy import arange, sin, pi
11
+from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
12
+from matplotlib.figure import Figure
13
+import numpy as np
14
+
15
+class MyMplCanvas(FigureCanvas):
16
+    
17
+    """Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
18
+    def __init__(self, parent=None, width=3, height=4, dpi=100):
19
+        
20
+        self.fig = Figure(figsize=(width, height), dpi=dpi)
21
+        FigureCanvas.__init__(self, self.fig)
22
+
23
+        self.setParent(parent)
24
+        FigureCanvas.updateGeometry(self)
25
+
26
+    def compute_initial_figure(self):
27
+        pass
28
+
29
+    def clicked(self):
30
+        print ("Clicked")
31
+
32
+class MyDynamicMplCanvas(MyMplCanvas):
33
+
34
+    """A canvas that updates itself every second with a new plot."""
35
+    def __init__(self, *args, **kwargs):
36
+        
37
+        MyMplCanvas.__init__(self, *args, **kwargs)
38
+        self.ax1 = self.fig.add_axes([.125,.1,.725,.8])
39
+        self.ax2 = self.ax1.twinx() # fig.add_axes([.125,.1,.725,.8])
40
+        self.compute_initial_figure()
41
+
42
+    def reAxH(self, num, shx=True, shy=True):
43
+        try:
44
+            self.fig.clear()
45
+        except:
46
+            pass
47
+        for n in range(num):
48
+            if n == 0:
49
+                self.ax1 = self.fig.add_subplot( 1, num, 1 )
50
+                self.ax1.tick_params(axis='both', which='major', labelsize=8)
51
+                self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
52
+                self.ax1.yaxis.get_offset_text().set_size(8) 
53
+            if n == 1:
54
+                self.ax2 = self.fig.add_subplot( 1, num, 2 )
55
+                self.ax2.tick_params(axis='both', which='major', labelsize=8)
56
+                self.ax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
57
+                self.ax2.yaxis.get_offset_text().set_size(8) 
58
+            if n == 2:
59
+                self.ax3 = self.fig.add_subplot( 1, num, 3 )
60
+                self.ax3.tick_params(axis='both', which='major', labelsize=8)
61
+                self.ax3.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
62
+                self.ax3.yaxis.get_offset_text().set_size(8) 
63
+            if n == 3:
64
+                self.ax4 = self.fig.add_subplot( 1, num, 4 )
65
+                self.ax4.tick_params(axis='both', which='major', labelsize=8)
66
+                self.ax4.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
67
+                self.ax4.yaxis.get_offset_text().set_size(8) 
68
+    
69
+    def reAxH2(self, num, shx=True, shy=True):
70
+        try:
71
+            for ax in fig.axes:
72
+                self.fig.delaxes(ax)
73
+        except:
74
+            pass
75
+
76
+        try:
77
+            self.fig.clear()
78
+        except:
79
+            pass
80
+        
81
+        for n in range(num):
82
+            if n == 0:
83
+                self.ax1 = self.fig.add_subplot( 2, num, 1 )
84
+                self.ax1.tick_params(axis='both', which='major', labelsize=8)
85
+                self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
86
+                self.ax1.yaxis.get_offset_text().set_size(8) 
87
+                self.ax21 = self.fig.add_subplot( 2, num, num+1 )
88
+                self.ax21.tick_params(axis='both', which='major', labelsize=8)
89
+                self.ax21.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
90
+                self.ax21.yaxis.get_offset_text().set_size(8) 
91
+            if n == 1:
92
+                self.ax2 = self.fig.add_subplot( 2, num, 2, sharex=self.ax1, sharey=self.ax1 )
93
+                self.ax2.tick_params(axis='both', which='major', labelsize=8)
94
+                self.ax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
95
+                self.ax2.yaxis.get_offset_text().set_size(8) 
96
+                self.ax22 = self.fig.add_subplot( 2, num, num+2, sharex=self.ax21, sharey=self.ax21 )
97
+                self.ax22.tick_params(axis='both', which='major', labelsize=8)
98
+                self.ax22.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
99
+                self.ax22.yaxis.get_offset_text().set_size(8) 
100
+            if n == 2:
101
+                self.ax3 = self.fig.add_subplot( 2, num, 3, sharex=self.ax1, sharey=self.ax1 )
102
+                self.ax3.tick_params(axis='both', which='major', labelsize=8)
103
+                self.ax3.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
104
+                self.ax3.yaxis.get_offset_text().set_size(8) 
105
+                self.ax23 = self.fig.add_subplot( 2, num, num+3, sharex=self.ax21, sharey=self.ax21 )
106
+                self.ax23.tick_params(axis='both', which='major', labelsize=8)
107
+                self.ax23.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
108
+                self.ax23.yaxis.get_offset_text().set_size(8) 
109
+            if n == 3:
110
+                self.ax4 = self.fig.add_subplot( 2, num, 4, sharex=self.ax1, sharey=self.ax1 )
111
+                self.ax4.tick_params(axis='both', which='major', labelsize=8)
112
+                self.ax4.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
113
+                self.ax4.yaxis.get_offset_text().set_size(8) 
114
+                self.ax24 = self.fig.add_subplot( 2, num, num+4, sharex=self.ax21, sharey=self.ax21 )
115
+                self.ax24.tick_params(axis='both', which='major', labelsize=8)
116
+                self.ax24.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
117
+                self.ax24.yaxis.get_offset_text().set_size(8) 
118
+            if n == 4:
119
+                self.ax5 = self.fig.add_subplot( 2, num, 5, sharex=self.ax1, sharey=self.ax1 )
120
+                self.ax5.tick_params(axis='both', which='major', labelsize=8)
121
+                self.ax5.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
122
+                self.ax5.yaxis.get_offset_text().set_size(8) 
123
+                self.ax25 = self.fig.add_subplot( 2, num, num+5, sharex=self.ax21, sharey=self.ax21 )
124
+                self.ax25.tick_params(axis='both', which='major', labelsize=8)
125
+                self.ax25.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
126
+                self.ax25.yaxis.get_offset_text().set_size(8) 
127
+            if n == 5:
128
+                self.ax6 = self.fig.add_subplot( 2, num, 6, sharex=self.ax1, sharey=self.ax1 )
129
+                self.ax6.tick_params(axis='both', which='major', labelsize=8)
130
+                self.ax6.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
131
+                self.ax6.yaxis.get_offset_text().set_size(8) 
132
+                self.ax26 = self.fig.add_subplot( 2, num, num+6, sharex=self.ax21, sharey=self.ax21 )
133
+                self.ax26.tick_params(axis='both', which='major', labelsize=8)
134
+                self.ax26.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
135
+                self.ax26.yaxis.get_offset_text().set_size(8) 
136
+            if n == 6:
137
+                self.ax7 = self.fig.add_subplot( 2, num, 7, sharex=self.ax1, sharey=self.ax1 )
138
+                self.ax7.tick_params(axis='both', which='major', labelsize=8)
139
+                self.ax7.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
140
+                self.ax7.yaxis.get_offset_text().set_size(8) 
141
+                self.ax27 = self.fig.add_subplot( 2, num, num+7, sharex=self.ax21, sharey=self.ax21 )
142
+                self.ax27.tick_params(axis='both', which='major', labelsize=8)
143
+                self.ax27.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
144
+                self.ax27.yaxis.get_offset_text().set_size(8) 
145
+            if n == 7:
146
+                self.ax8 = self.fig.add_subplot( 2, num, 8, sharex=self.ax1, sharey=self.ax1 )
147
+                self.ax8.tick_params(axis='both', which='major', labelsize=8)
148
+                self.ax8.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
149
+                self.ax8.yaxis.get_offset_text().set_size(8) 
150
+                self.ax28 = self.fig.add_subplot( 2, num, num+8, sharex=self.ax21, sharey=self.ax21 )
151
+                self.ax28.tick_params(axis='both', which='major', labelsize=8)
152
+                self.ax28.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
153
+                self.ax28.yaxis.get_offset_text().set_size(8) 
154
+
155
+    def reAx2(self, shx=True, shy=True):
156
+
157
+        try:
158
+            self.fig.clear()
159
+        except:
160
+            pass
161
+
162
+        try:
163
+            self.ax1.clear() 
164
+            self.delaxes(self.ax1) #.clear()
165
+        except:
166
+            pass
167
+        
168
+        try:    
169
+            self.delaxes(self.ax3) #.clear()
170
+        except:
171
+            pass
172
+        
173
+        try:
174
+            self.ax2.clear() 
175
+            self.delaxes(self.ax2) #.clear()
176
+        except:
177
+            pass
178
+
179
+        self.ax1 = self.fig.add_subplot(211)
180
+        if shx and shy:
181
+            self.ax2 = self.fig.add_subplot(212, sharex=self.ax1, sharey=self.ax1)
182
+        elif shx == True:
183
+            self.ax2 = self.fig.add_subplot(212, sharex=self.ax1) 
184
+        elif shy == True:
185
+            self.ax2 = self.fig.add_subplot(212, sharey=self.ax1) 
186
+        else:
187
+            self.ax2 = self.fig.add_subplot(212)
188
+
189
+        self.ax1.tick_params(axis='both', which='major', labelsize=8)
190
+        self.ax2.tick_params(axis='both', which='major', labelsize=8)
191
+
192
+        self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
193
+        self.ax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
194
+
195
+        self.ax1.yaxis.get_offset_text().set_size(8) 
196
+        self.ax2.yaxis.get_offset_text().set_size(8) 
197
+
198
+    def reAx3(self, shx=True, shy=True):
199
+
200
+        try:
201
+            self.fig.clear()
202
+        except:
203
+            pass
204
+
205
+        try:
206
+            self.ax1.clear() 
207
+            self.delaxes(self.ax1) #.clear()
208
+        except:
209
+            pass
210
+            
211
+        try:
212
+            self.ax2.clear() 
213
+            self.delaxes(self.ax2) #.clear()
214
+        except:
215
+            pass
216
+        
217
+        try:    
218
+            self.ax3.clear() 
219
+            self.delaxes(self.ax3) #.clear()
220
+        except:
221
+            pass
222
+
223
+        self.ax1 = self.fig.add_subplot(211)
224
+        if shx and shy:
225
+            self.ax2 = self.fig.add_subplot(212, sharex=self.ax1, sharey=self.ax1)
226
+        elif shx:
227
+            self.ax2 = self.fig.add_subplot(212, sharex=self.ax1) 
228
+        elif shy:
229
+            self.ax2 = self.fig.add_subplot(212, sharey=self.ax1) 
230
+        else:
231
+            self.ax2 = self.fig.add_subplot(212) 
232
+
233
+        self.ax3 = self.ax1.twinx()
234
+
235
+        self.ax1.tick_params(axis='both', which='major', labelsize=8)
236
+        self.ax2.tick_params(axis='both', which='major', labelsize=8)
237
+        self.ax3.tick_params(axis='both', which='major', labelsize=8)
238
+
239
+        self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
240
+        self.ax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
241
+        self.ax3.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
242
+
243
+        self.ax1.yaxis.get_offset_text().set_size(8) 
244
+        self.ax2.yaxis.get_offset_text().set_size(8)    
245
+        self.ax3.yaxis.get_offset_text().set_size(8)    
246
+ 
247
+    def reAx4(self):
248
+
249
+        try:
250
+            self.fig.clear()
251
+        except:
252
+            pass
253
+
254
+        # two main axes
255
+        self.ax1 = self.fig.add_axes([0.15, 0.55,   0.625, 0.3672])
256
+        self.ax2 = self.fig.add_axes([0.15, 0.135,  0.625, 0.3672])
257
+        
258
+        # for colourbars
259
+        self.cax1 = self.fig.add_axes([0.8, 0.55,   0.025, 0.3672])
260
+        self.cax2 = self.fig.add_axes([0.8, 0.135,  0.025, 0.3672])
261
+        
262
+        self.ax1.tick_params(axis='both', which='major', labelsize=8)
263
+        self.ax2.tick_params(axis='both', which='major', labelsize=8)
264
+
265
+        self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
266
+        self.ax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
267
+
268
+        self.ax1.yaxis.get_offset_text().set_size(8) 
269
+        self.ax2.yaxis.get_offset_text().set_size(8) 
270
+
271
+        self.cax1.tick_params(axis='both', which='major', labelsize=8)
272
+        self.cax2.tick_params(axis='both', which='major', labelsize=8)
273
+
274
+        self.cax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
275
+        self.cax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
276
+
277
+        self.cax1.yaxis.get_offset_text().set_size(8) #.get_text()
278
+        self.cax2.yaxis.get_offset_text().set_size(8) #.get_text()
279
+
280
+        self.cax1.tick_params(labelsize=8) 
281
+        self.cax2.tick_params(labelsize=8)
282
+
283
+
284
+    def compute_initial_figure(self):
285
+        
286
+        t = np.arange(0,.3,1e-4)
287
+        x = np.cos(t*2000.*np.pi*2)*np.exp(-t/.07)
288
+        x2 = np.exp(-t/.07)
289
+        dp = self.ax1.plot(t, x, 'r',label='test function')
290
+        dp2 = self.ax2.plot(t, x2, 'r',label='test function2')
291
+        self.ax1.set_xlabel("Time [s]", fontsize=8)
292
+        self.ax1.set_ylabel("Signal [nV]", fontsize=8)
293
+
294
+        self.ax1.tick_params(axis='both', which='major', labelsize=8)
295
+        self.ax1.tick_params(axis='both', which='minor', labelsize=6)
296
+
297
+        self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y') 
298
+        self.ax1.legend(prop={'size':6})
299
+

+ 35
- 0
akvo/gui/mydynamicmplcanvasnavigator.py View File

1
+from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
2
+from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
3
+from matplotlib.figure import Figure
4
+import numpy as np
5
+
6
+import sys
7
+from PyQt5 import QtCore, QtGui
8
+
9
+#from mydynamicmplcanvas import MyMplCanvas
10
+
11
+class MyMplCanvasN(FigureCanvas):
12
+    
13
+    """Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
14
+    def __init__(self, parent=None, width=3, height=.2, dpi=100):
15
+        
16
+        self.fig = Figure(figsize=(width, height), dpi=dpi)
17
+        FigureCanvas.__init__(self, self.fig)
18
+
19
+        self.setParent(parent)
20
+        FigureCanvas.updateGeometry(self)
21
+
22
+    def compute_initial_figure(self):
23
+        pass
24
+
25
+    def clicked(self):
26
+        print ("Clicked")
27
+
28
+class MyDynamicMplCanvasNavigator(MyMplCanvasN):
29
+    
30
+    def __init__(self, *args, **kwargs):
31
+        
32
+        MyMplCanvasN.__init__(self, *args, **kwargs)
33
+
34
+    def setCanvas(self, canvas):
35
+        NavigationToolbar(canvas, self)

+ 13
- 0
akvo/gui/quad.r View File

1
+
2
+# Define 
3
+Xc <- function(E0, df, tt, phi, T2) {
4
+	E0 * -sin(2*pi*df*tt + phi) * exp(-tt/T2)
5
+}
6
+
7
+Yc <- function(E0, df, tt, phi, T2) {
8
+	E0 * cos(2*pi*df*tt + phi) * exp(-tt/T2)
9
+}
10
+
11
+#QI <- function(E0, df, tt, phi, T2, X, Y) {
12
+#	(X-Xc(E0, df, tt, phi, T2))  + (Y-Yc(E0, df, tt, phi, T2))
13
+#}

+ 3
- 0
akvo/gui/replace.sh View File

1
+#!/bin/bash
2
+python2-pyuic4 main.ui > mainui.py
3
+sed 's/QtGui.KLed/KLed/g' mainui.py > mainui2.py

+ 1490
- 0
akvo/gui/scroll.ui
File diff suppressed because it is too large
View File


+ 219
- 0
akvo/gui/temp.py View File

1
+"""
2
+This demo demonstrates how to embed a matplotlib (mpl) plot 
3
+into a PyQt4 GUI application, including:
4
+
5
+* Using the navigation toolbar
6
+* Adding data to the plot
7
+* Dynamically modifying the plot's properties
8
+* Processing mpl events
9
+* Saving the plot to a file from a menu
10
+
11
+The main goal is to serve as a basis for developing rich PyQt GUI
12
+applications featuring mpl plots (using the mpl OO API).
13
+
14
+Eli Bendersky (eliben@gmail.com)
15
+License: this code is in the public domain
16
+Last modified: 19.01.2009
17
+"""
18
+import sys, os, random
19
+from PyQt4.QtCore import *
20
+from PyQt4.QtGui import *
21
+
22
+import matplotlib
23
+from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
24
+from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
25
+from matplotlib.figure import Figure
26
+
27
+
28
+class AppForm(QMainWindow):
29
+    def __init__(self, parent=None):
30
+        QMainWindow.__init__(self, parent)
31
+        self.setWindowTitle('Demo: PyQt with matplotlib')
32
+
33
+        self.create_menu()
34
+        self.create_main_frame()
35
+        self.create_status_bar()
36
+
37
+        self.textbox.setText('1 2 3 4')
38
+        self.on_draw()
39
+
40
+    def save_plot(self):
41
+        file_choices = "PNG (*.png)|*.png"
42
+        
43
+        path = unicode(QFileDialog.getSaveFileName(self, 
44
+                        'Save file', '', 
45
+                        file_choices))
46
+        if path:
47
+            self.canvas.print_figure(path, dpi=self.dpi)
48
+            self.statusBar().showMessage('Saved to %s' % path, 2000)
49
+    
50
+    def on_about(self):
51
+        msg = """ A demo of using PyQt with matplotlib:
52
+        
53
+         * Use the matplotlib navigation bar
54
+         * Add values to the text box and press Enter (or click "Draw")
55
+         * Show or hide the grid
56
+         * Drag the slider to modify the width of the bars
57
+         * Save the plot to a file using the File menu
58
+         * Click on a bar to receive an informative message
59
+        """
60
+        QMessageBox.about(self, "About the demo", msg.strip())
61
+    
62
+    def on_pick(self, event):
63
+        # The event received here is of the type
64
+        # matplotlib.backend_bases.PickEvent
65
+        #
66
+        # It carries lots of information, of which we're using
67
+        # only a small amount here.
68
+        # 
69
+        box_points = event.artist.get_bbox().get_points()
70
+        msg = "You've clicked on a bar with coords:\n %s" % box_points
71
+        
72
+        QMessageBox.information(self, "Click!", msg)
73
+    
74
+    def on_draw(self):
75
+        """ Redraws the figure
76
+        """
77
+        str = unicode(self.textbox.text())
78
+        self.data = map(int, str.split())
79
+        
80
+        x = range(len(self.data))
81
+
82
+        # clear the axes and redraw the plot anew
83
+        #
84
+        self.axes.clear()        
85
+        self.axes.grid(self.grid_cb.isChecked())
86
+        
87
+        self.axes.bar(
88
+            left=x, 
89
+            height=self.data, 
90
+            width=self.slider.value() / 100.0, 
91
+            align='center', 
92
+            alpha=0.44,
93
+            picker=5)
94
+        
95
+        self.canvas.draw()
96
+    
97
+    def create_main_frame(self):
98
+        self.main_frame = QWidget()
99
+        
100
+        # Create the mpl Figure and FigCanvas objects. 
101
+        # 5x4 inches, 100 dots-per-inch
102
+        #
103
+        self.dpi = 100
104
+        self.fig = Figure((5.0, 4.0), dpi=self.dpi)
105
+        self.canvas = FigureCanvas(self.fig)
106
+        self.canvas.setParent(self.main_frame)
107
+        
108
+        # Since we have only one plot, we can use add_axes 
109
+        # instead of add_subplot, but then the subplot
110
+        # configuration tool in the navigation toolbar wouldn't
111
+        # work.
112
+        #
113
+        self.axes = self.fig.add_subplot(111)
114
+        
115
+        # Bind the 'pick' event for clicking on one of the bars
116
+        #
117
+        self.canvas.mpl_connect('pick_event', self.on_pick)
118
+        
119
+        # Create the navigation toolbar, tied to the canvas
120
+        #
121
+        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)
122
+        
123
+        # Other GUI controls
124
+        # 
125
+        self.textbox = QLineEdit()
126
+        self.textbox.setMinimumWidth(200)
127
+        self.connect(self.textbox, SIGNAL('editingFinished ()'), self.on_draw)
128
+        
129
+        self.draw_button = QPushButton("&Draw")
130
+        self.connect(self.draw_button, SIGNAL('clicked()'), self.on_draw)
131
+        
132
+        self.grid_cb = QCheckBox("Show &Grid")
133
+        self.grid_cb.setChecked(False)
134
+        self.connect(self.grid_cb, SIGNAL('stateChanged(int)'), self.on_draw)
135
+        
136
+        slider_label = QLabel('Bar width (%):')
137
+        self.slider = QSlider(Qt.Horizontal)
138
+        self.slider.setRange(1, 100)
139
+        self.slider.setValue(20)
140
+        self.slider.setTracking(True)
141
+        self.slider.setTickPosition(QSlider.TicksBothSides)
142
+        self.connect(self.slider, SIGNAL('valueChanged(int)'), self.on_draw)
143
+        
144
+        #
145
+        # Layout with box sizers
146
+        # 
147
+        hbox = QHBoxLayout()
148
+        
149
+        for w in [  self.textbox, self.draw_button, self.grid_cb,
150
+                    slider_label, self.slider]:
151
+            hbox.addWidget(w)
152
+            hbox.setAlignment(w, Qt.AlignVCenter)
153
+        
154
+        vbox = QVBoxLayout()
155
+        vbox.addWidget(self.canvas)
156
+        vbox.addWidget(self.mpl_toolbar)
157
+        vbox.addLayout(hbox)
158
+        
159
+        self.main_frame.setLayout(vbox)
160
+        self.setCentralWidget(self.main_frame)
161
+    
162
+    def create_status_bar(self):
163
+        self.status_text = QLabel("This is a demo")
164
+        self.statusBar().addWidget(self.status_text, 1)
165
+        
166
+    def create_menu(self):        
167
+        self.file_menu = self.menuBar().addMenu("&File")
168
+        
169
+        load_file_action = self.create_action("&Save plot",
170
+            shortcut="Ctrl+S", slot=self.save_plot, 
171
+            tip="Save the plot")
172
+        quit_action = self.create_action("&Quit", slot=self.close, 
173
+            shortcut="Ctrl+Q", tip="Close the application")
174
+        
175
+        self.add_actions(self.file_menu, 
176
+            (load_file_action, None, quit_action))
177
+        
178
+        self.help_menu = self.menuBar().addMenu("&Help")
179
+        about_action = self.create_action("&About", 
180
+            shortcut='F1', slot=self.on_about, 
181
+            tip='About the demo')
182
+        
183
+        self.add_actions(self.help_menu, (about_action,))
184
+
185
+    def add_actions(self, target, actions):
186
+        for action in actions:
187
+            if action is None:
188
+                target.addSeparator()
189
+            else:
190
+                target.addAction(action)
191
+
192
+    def create_action(  self, text, slot=None, shortcut=None, 
193
+                        icon=None, tip=None, checkable=False, 
194
+                        signal="triggered()"):
195
+        action = QAction(text, self)
196
+        if icon is not None:
197
+            action.setIcon(QIcon(":/%s.png" % icon))
198
+        if shortcut is not None:
199
+            action.setShortcut(shortcut)
200
+        if tip is not None:
201
+            action.setToolTip(tip)
202
+            action.setStatusTip(tip)
203
+        if slot is not None:
204
+            self.connect(action, SIGNAL(signal), slot)
205
+        if checkable:
206
+            action.setCheckable(True)
207
+        return action
208
+
209
+
210
+def main():
211
+    app = QApplication(sys.argv)
212
+    form = AppForm()
213
+    form.show()
214
+    app.exec_()
215
+
216
+
217
+if __name__ == "__main__":
218
+    main()
219
+

BIN
akvo/gui/turtle.png View File


+ 35
- 0
akvo/terminal/SEGPlot.py View File

1
+#################################################################################
2
+# GJI final pub specs                                                           #
3
+import matplotlib                                                               #
4
+from matplotlib import rc                                                       #
5
+#matplotlib.rcParams['text.latex.preamble']=[r"\usepackage{amsmath,amssymb}"]    #
6
+matplotlib.rcParams['text.latex.preamble']=[r"\usepackage{timet,amsmath,amssymb}"]  #
7
+rc('font',**{'family':'serif','serif':['timet']})                                   #
8
+rc('font',**{'size':8})                                                             #
9
+rc('text', usetex=True)                                                             #
10
+# converts pc that GJI is defined in to inches                                      # 
11
+# In GEOPHYSICS \textwidth = 42pc                                               #
12
+#        \columnwidth = 20pc                                                    #
13
+#        one column widthe figures are 20 picas                                 #
14
+#        one and one third column figures are 26 picas                          #
15
+def pc2in(pc):                                                                  #
16
+    return pc*12/72.27                                                          #
17
+#################################################################################
18
+import numpy as np
19
+light_grey = np.array([float(248)/float(255)]*3)
20
+
21
+def fixLeg(legend):
22
+    rect = legend.get_frame()
23
+    #rect.set_color('None')
24
+    rect.set_facecolor(light_grey)
25
+    rect.set_linewidth(0.0)
26
+    rect.set_alpha(0.5)
27
+
28
+def deSpine(ax1):
29
+    spines_to_remove = ['top', 'right']
30
+    for spine in spines_to_remove:
31
+        ax1.spines[spine].set_visible(False)
32
+    #ax1.xaxis.set_ticks_position('none')
33
+    #ax1.yaxis.set_ticks_position('none')
34
+    ax1.get_xaxis().tick_bottom()
35
+    ax1.get_yaxis().tick_left()

+ 51
- 0
akvo/terminal/USGSPlots.py View File

1
+import sys
2
+import numpy as np
3
+import matplotlib.pyplot as plt
4
+import plotyaml
5
+
6
+__author__ = "M. Andy Kass"
7
+__version__ = "$Revision 0.1"
8
+__date__ = "$Date: 2017-05-25"
9
+
10
+
11
+class USGSPlots:
12
+
13
+    def getData(self,fname,chan):
14
+            
15
+        self.channels = []
16
+        for part in chan.split(','):
17
+            if ':' in part:
18
+                a,b = part.split(':')
19
+                a,b = int(a), int(b)
20
+                self.channels.extend(range(a,b))
21
+            else:
22
+                a = int(part)
23
+                self.channels.append(a)
24
+        #print self.channels
25
+
26
+        self.data = []
27
+        for c in self.channels:
28
+            nm = "Chan. " + str(c)
29
+            self.data.append(plotyaml.loadAkvoData(fname,nm))
30
+
31
+
32
+        return 0
33
+
34
+    def plotSingleDecay(self,pm,chan=1):
35
+       
36
+
37
+        return 42
38
+
39
+
40
+    def plotAllDecays(self,chan=1):
41
+
42
+        return 42
43
+
44
+    def plotAverageFID(self,chan=1):
45
+
46
+        return 42
47
+
48
+    def plotSpectrum(self,chan=1):
49
+
50
+        return 42
51
+ 

+ 192
- 0
akvo/terminal/epsPlots.py View File

1
+from SEGPlot import *
2
+
3
+import sys
4
+sys.path.append( '../tressel' )
5
+
6
+import matplotlib.pyplot as plt
7
+import matplotlib.ticker
8
+import scipy.io as sio
9
+import scipy.signal as signal
10
+import numpy as np
11
+
12
+import mrsurvey
13
+import pickle
14
+import decay
15
+import cmaps
16
+plt.register_cmap(name='viridis', cmap=cmaps.viridis)
17
+plt.register_cmap(name='inferno', cmap=cmaps.inferno)
18
+plt.register_cmap(name='inferno_r', cmap=cmaps.inferno_r)
19
+
20
+plt.register_cmap(name='magma', cmap=cmaps.magma)
21
+plt.register_cmap(name='magma_r', cmap=cmaps.magma_r)
22
+
23
+
24
+class canvas():
25
+    
26
+    def __init__(self):
27
+        self.fig = plt.figure( figsize=(pc2in(20),pc2in(20) ) )
28
+        self.ax1 = self.fig.add_subplot((211))
29
+        self.ax2 = self.fig.add_subplot((212), sharex=self.ax1)
30
+   
31
+    def draw(self):
32
+        plt.draw() 
33
+
34
+    def reAx2(self):
35
+        try:
36
+            self.fig.clear()
37
+        except:
38
+            pass
39
+
40
+        try:
41
+            self.ax1.clear() 
42
+            self.delaxes(self.ax1) #.clear()
43
+        except:
44
+            pass
45
+            
46
+        try:
47
+            self.ax2.clear() 
48
+            self.delaxes(self.ax2) #.clear()
49
+        except:
50
+            pass
51
+
52
+        self.ax1 = self.fig.add_subplot(211)
53
+        self.ax2 = self.fig.add_subplot(212)
54
+
55
+        self.ax1.tick_params(axis='both', which='major', labelsize=8)
56
+        self.ax2.tick_params(axis='both', which='major', labelsize=8)
57
+
58
+        self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
59
+        self.ax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
60
+
61
+        self.ax1.yaxis.get_offset_text().set_size(8) 
62
+        self.ax2.yaxis.get_offset_text().set_size(8) 
63
+
64
+    def reAx4(self):
65
+        try:
66
+            self.fig.clear()
67
+        except:
68
+            pass
69
+
70
+        # two main axes
71
+        self.ax1 = self.fig.add_axes([0.15, 0.55,   0.625, 0.3672])
72
+        self.ax2 = self.fig.add_axes([0.15, 0.135 , 0.625, 0.3672])
73
+        
74
+        # for colourbars
75
+        self.cax1 = self.fig.add_axes([0.8, 0.55 ,  0.025, 0.3672])
76
+        self.cax2 = self.fig.add_axes([0.8, 0.135,  0.025, 0.3672])
77
+        
78
+        self.ax1.tick_params(axis='both', which='major', labelsize=8)
79
+        self.ax2.tick_params(axis='both', which='major', labelsize=8)
80
+
81
+        self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
82
+        self.ax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
83
+
84
+        self.ax1.yaxis.get_offset_text().set_size(8) 
85
+        self.ax2.yaxis.get_offset_text().set_size(8) 
86
+
87
+        self.cax1.tick_params(axis='both', which='major', labelsize=8)
88
+        self.cax2.tick_params(axis='both', which='major', labelsize=8)
89
+
90
+        self.cax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
91
+        self.cax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
92
+
93
+        self.cax1.yaxis.get_offset_text().set_size(8) #.get_text()
94
+        self.cax2.yaxis.get_offset_text().set_size(8) #.get_text()
95
+
96
+        self.cax1.tick_params(labelsize=8) 
97
+        self.cax2.tick_params(labelsize=8)
98
+        
99
+        #self.ax1.yaxis.minorticks_off()
100
+        #self.ax2.yaxis.minorticks_off()
101
+        
102
+        plt.tick_params(
103
+            axis='y',          # changes apply to the x-axis
104
+            which='minor',      # both major and minor ticks are affected
105
+            bottom='off',      # ticks along the bottom edge are off
106
+            top='off',         # ticks along the top edge are off
107
+            labelbottom='off') 
108
+
109
+if __name__ == "__main__":
110
+   
111
+    first = True
112
+    for ffile in sys.argv[1::]: 
113
+        Canvas = canvas()
114
+        pfile = file(ffile)
115
+        unpickle = pickle.Unpickler(pfile)
116
+        MRS = mrsurvey.GMRDataProcessor()
117
+        MRS.DATADICT = unpickle.load()
118
+        MRS.pulseType = MRS.DATADICT["INFO"]["pulseType"]
119
+        MRS.transFreq = MRS.DATADICT["INFO"]["transFreq"]
120
+        MRS.pulseLength = MRS.DATADICT["INFO"]["pulseLength"]
121
+        MRS.TuneCapacitance = MRS.DATADICT["INFO"]["TuneCapacitance"]
122
+        MRS.samp = MRS.DATADICT["INFO"]["samp"]
123
+        MRS.nPulseMoments = MRS.DATADICT["INFO"]["nPulseMoments"]
124
+        MRS.deadTime = MRS.DATADICT["INFO"]["deadTime"]
125
+
126
+        MRS.quadDet(1, True, Canvas)
127
+        MRS.gateIntegrate(14, 1, Canvas )
128
+
129
+        #Canvas.fig.suptitle(r"\textbf{Experiment 0, channel 4}",  fontsize=8) #, fontweight='bold')
130
+        Canvas.ax1.set_title(r"Experiment 0, channel 4",  fontsize=8) 
131
+        #Canvas.ax1.set_title("Channel 4")
132
+
133
+
134
+
135
+        plt.savefig("test.eps", dpi=2200)
136
+
137
+        if first:
138
+            mat = MRS.DATADICT["CA"]
139
+            pmat = MRS.DATADICT["CP"]
140
+            first = False
141
+        else:
142
+            mat += MRS.DATADICT["CA"]
143
+            pmat += MRS.DATADICT["CP"]
144
+
145
+    quadSum = True
146
+    if quadSum:
147
+    
148
+        Canvas.ax1.clear() 
149
+        Canvas.ax2.clear() 
150
+        Canvas.cax1.clear() 
151
+        Canvas.cax2.clear() 
152
+        pulse = "Pulse 1"
153
+        clip = 1
154
+        QQ = np.average(MRS.DATADICT[pulse]["Q"], axis=1 )
155
+        im1 = Canvas.ax1.pcolormesh( 1e3*MRS.DATADICT[pulse]["TIMES"][clip-1:-clip], QQ, mat,  cmap='coolwarm_r', rasterized=True, vmin=-np.max(np.abs(mat)), vmax=np.max(np.abs(mat)))
156
+        im2 = Canvas.ax2.pcolormesh( 1e3*MRS.DATADICT[pulse]["TIMES"][clip-1:-clip], QQ, pmat, cmap='coolwarm_r', rasterized=True, vmin=-np.max(np.abs(pmat)), vmax=np.max(np.abs(pmat)))
157
+
158
+        cb2 = Canvas.fig.colorbar(im2, cax=Canvas.cax2)
159
+        cb2.set_label("Noise residual (nV)", fontsize=8)
160
+
161
+
162
+        #canvas.ax2.yaxis.set_ticks( QQ[0,9::7] )       
163
+        
164
+        Canvas.ax1.set_yscale('log')
165
+        Canvas.ax2.set_yscale('log')
166
+        
167
+        qlabs = np.append(np.concatenate( (QQ[0:1],QQ[9::10] )), QQ[-1] ) 
168
+        Canvas.ax1.yaxis.set_ticks( qlabs ) # np.append(np.concatenate( (QQ[0:1],QQ[9::10] )), QQ[-1] ) )
169
+        Canvas.ax2.yaxis.set_ticks( qlabs ) #np.append(np.concatenate( (QQ[0:1],QQ[9::10] )), QQ[-1] ) )
170
+        #formatter = matplotlib.ticker.LogFormatter(10, labelOnlyBase=False)
171
+        formatter = matplotlib.ticker.FuncFormatter(lambda x, pos: str((round(x,1)))) 
172
+        Canvas.ax1.yaxis.set_major_formatter(formatter)#matplotlib.ticker.FormatStrFormatter('%d.1'))
173
+        Canvas.ax2.yaxis.set_major_formatter(formatter)#matplotlib.ticker.FormatStrFormatter('%d.1')) 
174
+
175
+        plt.setp(Canvas.ax1.get_xticklabels(), visible=False)
176
+ 
177
+        t = 1e3*MRS.DATADICT[pulse]["TIMES"][clip-1:-clip],
178
+        Canvas.ax1.set_ylim( np.min(QQ), np.max(QQ) )
179
+        Canvas.ax2.set_ylim( np.min(QQ), np.max(QQ) )
180
+        Canvas.ax1.set_xlim( np.min(t), np.max(t) )
181
+        Canvas.ax2.set_xlim( np.min(t), np.max(t) )
182
+
183
+        cb1 = Canvas.fig.colorbar(im1, cax=Canvas.cax1)
184
+        cb1.set_label("Phased amplitude (nV)", fontsize=8)
185
+
186
+        Canvas.ax2.set_xlabel(r"Time (ms)", fontsize=8)
187
+        Canvas.ax1.set_ylabel(r"$q$ ( $\mathrm{A}\cdot\mathrm{s}$)", fontsize=8)
188
+        Canvas.ax2.set_ylabel(r"$q$ ( $\mathrm{A}\cdot\mathrm{s}$)", fontsize=8)
189
+
190
+        plt.savefig("quadSum.eps")
191
+
192
+    plt.show()

+ 64
- 0
akvo/terminal/plotyaml.py View File

1
+import yaml
2
+import os, sys
3
+import numpy as np
4
+
5
+def slicedict(d, s):
6
+    return {k:v for k,v in d.items() if k.startswith(s)}
7
+
8
+# Converts Lemma/Merlin/Akvo serialized Eigen arrays into numpy ones for use by Python 
9
+class VectorXr(yaml.YAMLObject):
10
+    """
11
+    Converts Lemma/Merlin/Akvo serialized Eigen arrays into numpy ones for use by Python 
12
+    """
13
+    yaml_tag = u'VectorXr'
14
+    def __init__(self, array):
15
+        self.size = np.shape(array)[0]
16
+        self.data = array.tolist()
17
+    def __repr__(self):
18
+        # Converts to numpy array on import 
19
+        return "np.array(%r)" % (self.data)
20
+
21
+class AkvoData(yaml.YAMLObject):
22
+    """
23
+    Reads an Akvo serialized dataset into a standard python dictionary 
24
+    """
25
+    yaml_tag = u'AkvoData'
26
+    def __init__(self, array):
27
+        pass
28
+        #self.size = np.shape(array)[0]
29
+        #self.Imp = array.tolist()
30
+    def __repr__(self):
31
+        # Converts to a dictionary with Eigen vectors represented as Numpy arrays 
32
+        return self
33
+
34
+def loadAkvoData(fnamein, chan):
35
+    """ Loads data from an Akvo YAML file. The 0.02 is hard coded as the pulse length. This needs to be 
36
+        corrected in future kernel calculations. The current was reported but not the pulse length. 
37
+    """
38
+    fname = (os.path.splitext(fnamein)[0])
39
+    with open(fnamein, 'r') as stream:
40
+        try:
41
+            AKVO = (yaml.load(stream))
42
+        except yaml.YAMLError as exc:
43
+            print(exc)
44
+    return AKVO 
45
+
46
+def plotQt( akvo ):
47
+    import matplotlib.pyplot as plt
48
+    plt.style.use('ggplot')
49
+    for pulse in akvo.Gated:
50
+        if pulse[0:5] == "Pulse":
51
+            #print(akvo.GATED[pulse].keys())
52
+            nq = akvo.Pulses[pulse]["current"].size
53
+            for chan in slicedict(akvo.Gated[pulse], "Chan."):
54
+                # accumulate pulse moments
55
+                X = np.zeros( (nq, len( akvo.Gated[pulse]["abscissa"].data )) )
56
+                for q in range(nq):
57
+                    plt.plot(  akvo.Gated[pulse]["abscissa"].data,  akvo.Gated[pulse][chan]["Q-" + str(q)+" CA"].data ) 
58
+                    X[q] = akvo.Gated[pulse][chan]["Q-" + str(q)+" CA"].data
59
+    plt.matshow(X)
60
+
61
+    plt.show()
62
+if __name__ == "__main__":
63
+    akvo = loadAkvoData( sys.argv[1] , "Chan. 1")
64
+    plotQt(akvo)

+ 24
- 0
akvo/terminal/tempPlots.py View File

1
+from USGSPlots import USGSPlots
2
+import plotyaml
3
+import sys
4
+
5
+
6
+if len(sys.argv) != 4 and len(sys.argv) != 2:
7
+    print('Usage:')
8
+    print('whatever.py filename channel option')
9
+    print('Use whatever.py -h for detailed help')
10
+    sys.exit()
11
+
12
+if len(sys.argv) == 2:
13
+    print('help!')
14
+    sys.exit()
15
+
16
+
17
+fname = str(sys.argv[1])
18
+chan = sys.argv[2]
19
+
20
+myplot = USGSPlots()
21
+
22
+myplot.getData(fname,chan)
23
+
24
+

+ 3
- 0
akvo/tressel/__init__.py View File

1
+#import decay
2
+#import rotate
3
+#import mrsurvey 

+ 545
- 0
akvo/tressel/adapt.py View File

1
+import numpy as np
2
+from numpy.linalg import lstsq
3
+from numpy.linalg import norm
4
+from numpy import fft 
5
+
6
+import pylab
7
+
8
+from scipy.signal import correlate
9
+
10
+def autocorr(x):
11
+    #result = np.correlate(x, x, mode='full')
12
+    result = correlate(x, x, mode='full')
13
+    return result[result.size/2:]
14
+
15
+class AdaptiveFilter:
16
+
17
+    def __init__(self, mu):
18
+        self.mu = mu
19
+
20
+    def adapt_filt_Ref(self, x, R, M, mu, PCA, lambda2=0.95, H0=0):
21
+        """ Taken from .m file
22
+        This function is written to allow the user to filter a input signal   
23
+        with an adaptive filter that utilizes 2 reference signals instead of  
24
+        the standard method which allows for only 1 reference signal.         
25
+        Author: Rob Clemens              Date: 3/16/06                       
26
+        Modified and ported to Python, now takes arbitray number of reference points  
27
+        """
28
+        #from akvo.tressel import pca 
29
+        import akvo.tressel.pca as pca 
30
+
31
+        if np.shape(x) != np.shape(R[0]): # or np.shape(x) != np.shape(rx1):
32
+            print ("Error, non aligned")
33
+            exit(1)
34
+        
35
+        if PCA == "Yes":
36
+            # PCA decomposition on ref channels so signals are less related
37
+            R, K, means = pca.pca( R )
38
+        
39
+        if all(H0) == 0:
40
+            H = np.zeros( (len(R)*M))
41
+            #print ("resetting filter")
42
+        else:
43
+            H = H0
44
+        Rn = np.ones(len(R)*M) / mu 
45
+        
46
+        r_ = np.zeros( (len(R), M) ) 
47
+        e = np.zeros(len(x)) # error, desired output
48
+        ilambda = lambda2**-1
49
+
50
+        for z in range(0, len(x)):
51
+            # Only look forwards, to avoid distorting the lates times 
52
+            # (run backwards, if opposite and you don't care about distorting very late time.)
53
+            for ir in range(len(R)):
54
+                if z < M:
55
+                    r_[ir,0:z] = R[ir][0:z]
56
+                    r_[ir,z:M] = 0 
57
+                else:
58
+                    # TODO, use np.delete and np.append to speed this up
59
+                    r_[ir,:] = R[ir][z-M:z]
60
+            # reshape            
61
+            r_n = np.reshape(r_, -1) #concatenate((r_v, r_h ))
62
+
63
+            #K      = np.dot( np.diag(Rn,0), r_n) / (lambda2 + np.dot(r_n*Rn, r_n))  # Create/update K
64
+            K      = (Rn* r_n) / (lambda2 + np.dot(r_n*Rn, r_n))  # Create/update K
65
+            e[z]   = x[z] - np.dot(r_n.T, H)             # e is the filtered signal, input - r(n) * Filter Coefs
66
+            H     += K*e[z];                             # Update Filter Coefficients
67
+            Rn     = ilambda*Rn - ilambda*np.dot(np.dot(K, r_n.T), Rn)     # Update R(n)
68
+        return e, H
69
+
70
+    def transferFunctionFFT(self, D, R, reg=1e-2):
71
+        from akvo.tressel import pca
72
+        """
73
+            Computes the transfer function (H) between a Data channel and 
74
+            a number of Reference channels. The Matrices D and R are 
75
+            expected to be in the frequency domain on input.
76
+            | R1'R1 R1'R2 R1'R3|   |h1|   |R1'D|
77
+            | R2'R1 R2'R2 R2'R3| * |h2| = |R2'D|
78
+            | R3'R1 R3'R2 R3'R3|   |h3|   |R3'D|
79
+
80
+            Returns the corrected array 
81
+        """
82
+
83
+        # PCA decomposition on ref channels so signals are less related
84
+        #transMatrix, K, means = pca.pca( np.array([rx0, rx1]))   
85
+        #RR = np.zeros(( np.shape(R[0])[0]*np.shape(R[0])[1], len(R)))
86
+#         RR = np.zeros(( len(R), np.shape(R[0])[0]*np.shape(R[0])[1] ))
87
+#         for ir in range(len(R)):
88
+#             RR[ir,:] = np.reshape(R[ir], -1)
89
+#         transMatrix, K, means = pca.pca(RR)    
90
+#         #R rx0 = transMatrix[0,:]
91
+#         # rx1 = transMatrix[1,:]
92
+#         for ir in range(len(R)):
93
+#             R[ir] = transMatrix[ir,0]
94
+
95
+        import scipy.linalg 
96
+        import akvo.tressel.pca as pca 
97
+        # Compute as many transfer functions as len(R)
98
+        # A*H = B
99
+        nref = len(R)
100
+        H = np.zeros( (np.shape(D)[1], len(R)), dtype=complex )
101
+        for iw in range(np.shape(D)[1]):
102
+            A = np.zeros( (nref, nref), dtype=complex )
103
+            B = np.zeros( (nref) , dtype=complex)
104
+            for ii in range(nref):
105
+                for jj in range(nref):
106
+                    # build A
107
+                    A[ii,jj] = np.dot(R[ii][:,iw], R[jj][:,iw])                 
108
+
109
+                # build B
110
+                B[ii] = np.dot( R[ii][:,iw], D[:,iw] )
111
+
112
+            # compute H(iw)
113
+            #linalg.solve(a,b) if a is square
114
+            #print "A", A
115
+            #print "B", B
116
+            # TODO, regularise this solve step? So as to not fit the spurious noise
117
+            #print np.shape(B), np.shape(A) 
118
+            #H[iw, :] = scipy.linalg.solve(A,B)
119
+            H[iw, :] = scipy.linalg.lstsq(A,B,cond=reg)[0]
120
+            #print "lstqt", np.shape(scipy.linalg.lstsq(A,B))
121
+            #print "solve", scipy.linalg.solve(A,B)
122
+            #H[iw,:]  = scipy.linalg.lstsq(A,B) # otherwise 
123
+                #H = np.zeros( (np.shape(D)[1], )   )
124
+        #print H #A, B
125
+        Error = np.zeros(np.shape(D), dtype=complex)
126
+        for ir in range(nref):
127
+            for q in range( np.shape(D)[0] ):
128
+                #print "dimcheck", np.shape(H[:,ir]), np.shape(R[ir][q,:] )
129
+                Error[q,:] += H[:,ir]*R[ir][q,:]
130
+        return D - Error
131
+
132
+    def adapt_filt_tworefFreq(self, x, rx0, rx1, M, lambda2=0.95):
133
+        """ Frequency domain version of above
134
+        """
135
+        from akvo.tressel import pca 
136
+
137
+        pylab.figure()
138
+        pylab.plot(rx0)
139
+        pylab.plot(rx1)
140
+
141
+        # PCA decomposition on ref channels so signals are less related
142
+        transMatrix, K, means = pca.pca( np.array([rx0, rx1]))    
143
+        rx0 = transMatrix[:,0]
144
+        rx1 = transMatrix[:,1]
145
+        
146
+        pylab.plot(rx0)
147
+        pylab.plot(rx1)
148
+        pylab.show()
149
+        exit()
150
+
151
+        if np.shape(x) != np.shape(rx0) or np.shape(x) != np.shape(rx1):
152
+            print ("Error, non aligned")
153
+            exit(1)
154
+
155
+        wx = fft.rfft(x)
156
+        wr0 = fft.rfft(rx0)
157
+        wr1 = fft.rfft(rx1)
158
+ 
159
+        H = np.zeros( (2*M), dtype=complex ) 
160
+        ident_mat = np.eye((2*M))
161
+        Rn = ident_mat / 0.1
162
+        r_v = np.zeros( (M), dtype=complex ) 
163
+        r_h = np.zeros( (M), dtype=complex ) 
164
+        e = np.zeros(len(x), dtype=complex )
165
+        ilambda = lambda2**-1
166
+
167
+        for z in range(0, len(wx)):
168
+            # TODO Padd with Zeros or truncate if M >,< arrays 
169
+            r_v = wr0[::-1][:M] 
170
+            r_h = wr1[::-1][:M] 
171
+            r_n = np.concatenate((r_v, r_h ))
172
+            K      = np.dot(Rn, r_n) / (lambda2 + np.dot(np.dot(r_n.T, Rn), r_n))  # Create/update K
173
+            e[z]   = wx[z] - np.dot(r_n,H)        # e is the filtered signal, input - r(n) * Filter Coefs
174
+            H     += K * e[z];                    # Update Filter Coefficients
175
+            Rn     = ilambda*Rn - ilambda*K*r_n.T*Rn  # Update R(n)
176
+        
177
+        return fft.irfft(e)
178
+
179
+    def iter_filt_refFreq(self, x, rx0, Ahat=.05, Bhat=.5, k=0.05):
180
+
181
+        X = np.fft.rfft(x)
182
+        X0 = np.copy(X)
183
+        RX0 = np.fft.rfft(rx0)
184
+
185
+        # step 0
186
+        Abs2HW = []
187
+        alphai =  k * (np.abs(Ahat)**2 / np.abs(Bhat)**2) 
188
+        betai  =  k * (1. / (np.abs(Bhat)**2) ) 
189
+        Hw     =  ((1.+alphai) * np.abs(X)**2 ) / (np.abs(X)**2 + betai*(np.abs(RX0)**2))
190
+        H      =  np.abs(Hw)**2
191
+        pylab.ion()
192
+        pylab.figure()
193
+        for i in range(10):
194
+            #print "alphai", alphai
195
+            #print "betai", betai
196
+            #print "Hw", Hw
197
+            alphai = k * (np.abs(Ahat)**2 / np.abs(Bhat)**2) * np.product(H, axis=0)
198
+            betai  = k * (1. / np.abs(Bhat)**2) * np.product(H, axis=0)
199
+            # update signal
200
+            Hw   =  ((1.+alphai) * np.abs(X)**2) / (np.abs(X)**2 + betai*np.abs(RX0)**2)
201
+            Hw = np.nan_to_num(Hw)
202
+            X *= Hw
203
+            H = np.vstack( (H, np.abs(Hw)**2) )
204
+            #print "Hw", Hw
205
+            pylab.cla()
206
+            pylab.plot(Hw)
207
+            #pylab.plot(np.abs(X))
208
+            #pylab.plot(np.abs(RX0))
209
+            pylab.draw()
210
+            raw_input("wait")
211
+
212
+        pylab.cla()
213
+        pylab.ioff()
214
+        #return np.fft.irfft(X0-X)
215
+        return np.fft.irfft(X)
216
+
217
+    def iter_filt_refFreq(self, x, rx0, rx1, Ahat=.1, Bhat=1., k=0.001):
218
+
219
+        X = np.fft.rfft(x)
220
+        X0 = np.copy(X)
221
+        RX0 = np.fft.rfft(rx0)
222
+        RX1 = np.fft.rfft(rx1)
223
+
224
+        # step 0
225
+        alphai =  k * (np.abs(Ahat)**2 / np.abs(Bhat)**2) 
226
+        betai  =  k * (1. / (np.abs(Bhat)**2) ) 
227
+        #Hw     =  ((1.+alphai) * np.abs(X)**2 ) / (np.abs(X)**2 + betai*(np.abs(RX0)**2))
228
+        H      =  np.ones(len(X)) # abs(Hw)**2
229
+        #pylab.ion()
230
+        #pylab.figure(334)
231
+        for i in range(1000):
232
+            #print "alphai", alphai
233
+            #print "betai", betai
234
+            #print "Hw", Hw
235
+            alphai = k * (np.abs(Ahat)**2 / np.abs(Bhat)**2) * np.product(H, axis=0)
236
+            betai  = k * (1. / np.abs(Bhat)**2) * np.product(H, axis=0)
237
+            # update signal
238
+            Hw   =  ((1.+alphai) * np.abs(X)**2) / (np.abs(X)**2 + betai*np.abs(RX0)**2)
239
+            Hw = np.nan_to_num(Hw)
240
+            X *= Hw #.conjugate
241
+            #H = np.vstack((H, np.abs(Hw)**2) )
242
+            H = np.vstack((H, np.abs(Hw)) )
243
+            #print "Hw", Hw
244
+            #pylab.cla()
245
+            #pylab.plot(Hw)
246
+            #pylab.plot(np.abs(X))
247
+            #pylab.plot(np.abs(RX0))
248
+            #pylab.draw()
249
+            #raw_input("wait")
250
+
251
+        #pylab.cla()
252
+        #pylab.ioff()
253
+        return np.fft.irfft(X0-X)
254
+        #return np.fft.irfft(X)
255
+
256
+    def Tdomain_DFT(self, desired, input, S):
257
+        """ Lifted from Adaptive filtering toolbox. Modefied to accept more than one input 
258
+            vector
259
+        """
260
+        
261
+        # Initialisation Procedure
262
+        nCoefficients =   S["filterOrderNo"]/2+1
263
+        nIterations   =   len(desired)
264
+
265
+        # Pre Allocations
266
+        errorVector  = np.zeros(nIterations, dtype='complex')
267
+        outputVector = np.zeros(nIterations, dtype='complex')
268
+        
269
+        # Initial State
270
+        coefficientVectorDFT =   np.fft.rfft(S["initialCoefficients"])/np.sqrt(float(nCoefficients))
271
+        desiredDFT           =   np.fft.rfft(desired)
272
+        powerVector          =   S["initialPower"]*np.ones(nCoefficients)
273
+
274
+        # Improve source code regularity, pad with zeros
275
+        # TODO, confirm zeros(nCoeffics) not nCoeffics-1
276
+        prefixedInput  =   np.concatenate([np.zeros(nCoefficients-1), np.array(input)])
277
+
278
+        # Body
279
+        pylab.ion()
280
+        pylab.figure(11)
281
+        for it in range(nIterations): # = 1:nIterations,
282
+            
283
+            regressorDFT = np.fft.rfft(prefixedInput[it:it+nCoefficients][::-1]) /\
284
+                           np.sqrt(float(nCoefficients))
285
+
286
+            # Summing two column vectors
287
+            powerVector = S["alpha"] * (regressorDFT*np.conjugate(regressorDFT)) + \
288
+                                  (1.-S["alpha"])*(powerVector)
289
+
290
+            pylab.cla()
291
+            #pylab.plot(prefixedInput[::-1], 'b')
292
+            #pylab.plot(prefixedInput[it:it+nCoefficients][::-1], 'g', linewidth=3)
293
+            #pylab.plot(regressorDFT.real)
294
+            #pylab.plot(regressorDFT.imag)
295
+            pylab.plot(powerVector.real)
296
+            pylab.plot(powerVector.imag)
297
+            #pylab.plot(outputVector)
298
+            #pylab.plot(errorVector.real)
299
+            #pylab.plot(errorVector.imag)
300
+            pylab.draw()
301
+            #raw_input("wait")
302
+
303
+            outputVector[it] = np.dot(coefficientVectorDFT.T, regressorDFT)
304
+
305
+            #errorVector[it] = desired[it] - outputVector[it]
306
+            errorVector[it] = desiredDFT[it] - outputVector[it]
307
+
308
+            #print errorVector[it], desired[it], outputVector[it]
309
+
310
+            # Vectorized
311
+            coefficientVectorDFT += (S["step"]*np.conjugate(errorVector[it])*regressorDFT) /\
312
+                                    (S['gamma']+powerVector)
313
+
314
+        return np.real(np.fft.irfft(errorVector))
315
+        #coefficientVector = ifft(coefficientVectorDFT)*sqrt(nCoefficients);
316
+
317
+    def Tdomain_DCT(self, desired, input, S):
318
+        """ Lifted from Adaptive filtering toolbox. Modefied to accept more than one input 
319
+            vector. Uses cosine transform
320
+        """
321
+        from scipy.fftpack import dct
322
+ 
323
+        # Initialisation Procedure
324
+        nCoefficients =   S["filterOrderNo"]+1
325
+        nIterations   =   len(desired)
326
+
327
+        # Pre Allocations
328
+        errorVector  = np.zeros(nIterations)
329
+        outputVector = np.zeros(nIterations)
330
+        
331
+        # Initial State
332
+        coefficientVectorDCT =   dct(S["initialCoefficients"]) #/np.sqrt(float(nCoefficients))
333
+        desiredDCT           =   dct(desired)
334
+        powerVector          =   S["initialPower"]*np.ones(nCoefficients)
335
+
336
+        # Improve source code regularity, pad with zeros
337
+        prefixedInput  =   np.concatenate([np.zeros(nCoefficients-1), np.array(input)])
338
+        
339
+        # Body
340
+        #pylab.figure(11)
341
+        #pylab.ion()
342
+        for it in range(0, nIterations): # = 1:nIterations,
343
+            
344
+            regressorDCT = dct(prefixedInput[it:it+nCoefficients][::-1], type=2) 
345
+            #regressorDCT = dct(prefixedInput[it+nCoefficients:it+nCoefficients*2+1])#[::-1]) 
346
+
347
+            # Summing two column vectors
348
+            powerVector = S["alpha"]*(regressorDCT) + (1.-S["alpha"])*(powerVector)
349
+            #pylab.cla()
350
+            #pylab.plot(powerVector)
351
+            #pylab.draw()
352
+
353
+            outputVector[it] = np.dot(coefficientVectorDCT.T, regressorDCT)
354
+            #errorVector[it] = desired[it] - outputVector[it]
355
+            errorVector[it] = desiredDCT[it] - outputVector[it]
356
+
357
+            # Vectorized
358
+            coefficientVectorDCT += (S["step"]*errorVector[it]*regressorDCT) #/\
359
+                                    #(S['gamma']+powerVector)
360
+
361
+        #pylab.plot(errorVector)
362
+        #pylab.show()
363
+        return dct(errorVector, type=3)
364
+        #coefficientVector = ifft(coefficientVectorDCT)*sqrt(nCoefficients);
365
+
366
+
367
+
368
+    def Tdomain_CORR(self, desired, input, S):
369
+
370
+        from scipy.linalg import toeplitz
371
+        from scipy.signal import correlate
372
+
373
+        # Autocorrelation
374
+        ac = np.correlate(input, input, mode='full')
375
+        ac = ac[ac.size/2:]
376
+        R = toeplitz(ac)
377
+        
378
+        # cross correllation
379
+        r = np.correlate(desired, input, mode='full')
380
+        r = r[r.size/2:]
381
+        
382
+        #r = np.correlate(desired, input, mode='valid')
383
+        print ("R", np.shape(R))
384
+        print ("r", np.shape(r))
385
+        print ("solving")
386
+        #H = np.linalg.solve(R,r)
387
+        H = np.linalg.lstsq(R,r,rcond=.01)[0]
388
+        #return desired - np.dot(H,input)
389
+        print ("done solving")
390
+        pylab.figure()
391
+        pylab.plot(H)
392
+        pylab.title("H")
393
+        #return desired - np.convolve(H, input, mode='valid')
394
+        #return desired - np.convolve(H, input, mode='same')
395
+        #return np.convolve(H, input, mode='same')
396
+        return desired - np.dot(toeplitz(H), input)
397
+        #return np.dot(R, H)
398
+
399
+#         T = toeplitz(input)
400
+#         print "shapes", np.shape(T), np.shape(desired)
401
+#         h = np.linalg.lstsq(T, desired)[0]
402
+#         print "shapes", np.shape(h), np.shape(input)
403
+#         #return np.convolve(h, input, mode='same')
404
+#         return desired - np.dot(T,h)
405
+ 
406
+    def Fdomain_CORR(self, desired, input, dt, freq):
407
+        
408
+        from scipy.linalg import toeplitz
409
+        
410
+        # Fourier domain
411
+        Input = np.fft.rfft(input)
412
+        Desired = np.fft.rfft(desired)
413
+
414
+        T = toeplitz(Input)
415
+        #H = np.linalg.solve(T, Desired)
416
+        H = np.linalg.lstsq(T, Desired)[0]
417
+#         ac = np.correlate(Input, Input, mode='full')
418
+#         ac = ac[ac.size/2:]
419
+#         R = toeplitz(ac)
420
+#         
421
+#         r = np.correlate(Desired, Input, mode='full')
422
+#         r = r[r.size/2:]
423
+#         
424
+#         #r = np.correlate(desired, input, mode='valid')
425
+#         print "R", np.shape(R)
426
+#         print "r", np.shape(r)
427
+#         print "solving"
428
+#         H = np.linalg.solve(R,r)
429
+#         #H = np.linalg.lstsq(R,r)
430
+#         #return desired - np.dot(H,input)
431
+#         print "done solving"
432
+        pylab.figure()
433
+        pylab.plot(H.real)
434
+        pylab.plot(H.imag)
435
+        pylab.plot(Input.real)
436
+        pylab.plot(Input.imag)
437
+        pylab.plot(Desired.real)
438
+        pylab.plot(Desired.imag)
439
+        pylab.legend(["hr","hi","ir","ii","dr","di"])
440
+        pylab.title("H")
441
+        #return desired - np.fft.irfft(Input*H)
442
+        return np.fft.irfft(H*Input)
443
+
444
+    def Tdomain_RLS(self, desired, input, S):
445
+        """
446
+            A DFT is first performed on the data. Than a RLS algorithm is carried out 
447
+            for noise cancellation. Related to the RLS_Alt Algoritm 5.3 in  Diniz book.
448
+            The desired and input signals are assummed to be real time series data.
449
+        """
450
+
451
+        # Transform data into frequency domain
452
+        Input = np.fft.rfft(input)
453
+        Desired = np.fft.rfft(desired)
454
+
455
+        # Initialisation Procedure
456
+        nCoefficients = S["filterOrderNo"]+1
457
+        nIterations   = len(Desired)
458
+
459
+        # Pre Allocations
460
+        errorVector  = np.zeros(nIterations, dtype="complex")
461
+        outputVector = np.zeros(nIterations, dtype="complex")
462
+        errorVectorPost  = np.zeros(nIterations, dtype="complex")
463
+        outputVectorPost = np.zeros(nIterations, dtype="complex")
464
+        coefficientVector = np.zeros( (nCoefficients, nIterations+1), dtype="complex" )        
465
+
466
+        # Initial State
467
+        coefficientVector[:,1] = S["initialCoefficients"]  
468
+        S_d                    = S["delta"]*np.eye(nCoefficients)
469
+
470
+        # Improve source code regularity, pad with zeros
471
+        prefixedInput = np.concatenate([np.zeros(nCoefficients-1, dtype="complex"), 
472
+                                np.array(Input)])
473
+        invLambda = 1./S["lambda"]
474
+        
475
+        # Body
476
+        pylab.ion()
477
+        pylab.figure(11)
478
+
479
+        for it in range(nIterations):
480
+            
481
+            regressor = prefixedInput[it:it+nCoefficients][::-1]
482
+
483
+            # a priori estimated output
484
+            outputVector[it] = np.dot(coefficientVector[:,it].T, regressor)
485
+       
486
+            # a priori error
487
+            errorVector[it] = Desired[it] - outputVector[it]
488
+
489
+            psi             = np.dot(S_d, regressor)
490
+            if np.isnan(psi).any():
491
+                print ("psi", psi)
492
+                exit(1)
493
+            
494
+            pylab.cla()
495
+            #pylab.plot(psi)
496
+            pylab.plot(regressor.real)
497
+            pylab.plot(regressor.imag)
498
+            pylab.plot(coefficientVector[:,it].real)
499
+            pylab.plot(coefficientVector[:,it].imag)
500
+            pylab.legend(["rr","ri", "cr", "ci"])
501
+            pylab.draw()
502
+            raw_input("paws")
503
+
504
+            S_d             = invLambda * (S_d - np.dot(psi, psi.T)  /\
505
+                                S["lambda"] + np.dot(psi.T, regressor))
506
+
507
+            coefficientVector[:,it+1] = coefficientVector[:,it] + \
508
+                                        np.conjugate(errorVector[it])*np.dot(S_d, regressor)
509
+            # A posteriori estimated output
510
+            outputVectorPost[it]  =  np.dot(coefficientVector[:,it+1].T, regressor)
511
+
512
+            # A posteriori error
513
+            errorVectorPost[it] = Desired[it] - outputVectorPost[it]
514
+ 
515
+        errorVectorPost = np.nan_to_num(errorVectorPost)
516
+
517
+        pylab.figure(11)
518
+        print (np.shape(errorVectorPost))
519
+        pylab.plot(errorVectorPost.real)
520
+        pylab.plot(errorVectorPost.imag)
521
+        pylab.show()
522
+        print(errorVectorPost)
523
+        #return np.fft.irfft(Desired)
524
+        return np.fft.irfft(errorVectorPost)
525
+
526
+if __name__ == "__main__":
527
+
528
+    def noise(nu, t, phi):
529
+        return np.sin(nu*2.*np.pi*t + phi)
530
+
531
+    import matplotlib.pyplot as plt
532
+    print("Test driver for adaptive filtering")
533
+    Filt = AdaptiveFilter(.1)
534
+    t = np.arange(0, .5, 1e-4)
535
+    omega = 2000 * 2.*np.pi
536
+    T2 = .100
537
+    n1 = noise(60, t, .2   )
538
+    n2 = noise(61, t, .514 )
539
+    x = np.sin(omega*t)* np.exp(-t/T2) + 2.3*noise(60, t, .34) + 1.783*noise(31, t, 2.1)
540
+    e = Filt.adapt_filt_tworef(x, n1, n2, 200, .98)
541
+    plt.plot(t,  x)
542
+    plt.plot(t, n1)
543
+    plt.plot(t, n2)
544
+    plt.plot(t,  e)
545
+    plt.show()

+ 546
- 0
akvo/tressel/cadapt.pyx View File

1
+import numpy as np
2
+from numpy.linalg import lstsq
3
+from numpy.linalg import norm
4
+from numpy import fft 
5
+
6
+import pylab
7
+
8
+from scipy.signal import correlate
9
+
10
+def autocorr(x):
11
+    #result = np.correlate(x, x, mode='full')
12
+    result = correlate(x, x, mode='full')
13
+    return result[result.size/2:]
14
+
15
+class AdaptiveFilter:
16
+
17
+    def __init__(self, mu):
18
+        self.mu = mu
19
+
20
+    def adapt_filt_Ref(self, x, R, M, mu, PCA, lambda2=0.95, H0=0):
21
+        """ Taken from .m file
22
+        This function is written to allow the user to filter a input signal   
23
+        with an adaptive filter that utilizes 2 reference signals instead of  
24
+        the standard method which allows for only 1 reference signal.         
25
+        Author: Rob Clemens              Date: 3/16/06                       
26
+        Modified and ported to Python, now takes arbitray number of reference points  
27
+        """
28
+        #from akvo.tressel import pca 
29
+        import akvo.tressel.cpca as pca 
30
+
31
+        if np.shape(x) != np.shape(R[0]): # or np.shape(x) != np.shape(rx1):
32
+            print ("Error, non aligned")
33
+            exit(1)
34
+        
35
+        if PCA == "Yes":
36
+            # PCA decomposition on ref channels so signals are less related
37
+            R, K, means = pca.pca( R )
38
+        
39
+        if all(H0) == 0:
40
+            H = np.zeros( (len(R)*M))
41
+            #print ("resetting filter")
42
+        else:
43
+            H = H0
44
+        Rn = np.ones(len(R)*M) / mu 
45
+        
46
+        r_ = np.zeros( (len(R), M) ) 
47
+        e = np.zeros(len(x)) # error, desired output
48
+        ilambda = lambda2**-1
49
+        cdef int z
50
+        cdef int ir
51
+        for z in range(0, len(x)):
52
+            # Only look forwards, to avoid distorting the lates times 
53
+            # (run backwards, if opposite and you don't care about distorting very late time.)
54
+            for ir in range(len(R)):
55
+                if z < M:
56
+                    r_[ir,0:z] = R[ir][0:z]
57
+                    r_[ir,z:M] = 0 
58
+                else:
59
+                    # TODO, use np.delete and np.append to speed this up
60
+                    r_[ir,:] = R[ir][z-M:z]
61
+            # reshape            
62
+            r_n = np.reshape(r_, -1) #concatenate((r_v, r_h ))
63
+
64
+            #K      = np.dot( np.diag(Rn,0), r_n) / (lambda2 + np.dot(r_n*Rn, r_n))  # Create/update K
65
+            K      = (Rn* r_n) / (lambda2 + np.dot(r_n*Rn, r_n))  # Create/update K
66
+            e[z]   = x[z] - np.dot(r_n.T, H)             # e is the filtered signal, input - r(n) * Filter Coefs
67
+            H     += K*e[z];                             # Update Filter Coefficients
68
+            Rn     = ilambda*Rn - ilambda*np.dot(np.dot(K, r_n.T), Rn)     # Update R(n)
69
+        return e, H
70
+
71
+    def transferFunctionFFT(self, D, R, reg=1e-2):
72
+        from akvo.tressel import pca
73
+        """
74
+            Computes the transfer function (H) between a Data channel and 
75
+            a number of Reference channels. The Matrices D and R are 
76
+            expected to be in the frequency domain on input.
77
+            | R1'R1 R1'R2 R1'R3|   |h1|   |R1'D|
78
+            | R2'R1 R2'R2 R2'R3| * |h2| = |R2'D|
79
+            | R3'R1 R3'R2 R3'R3|   |h3|   |R3'D|
80
+
81
+            Returns the corrected array 
82
+        """
83
+
84
+        # PCA decomposition on ref channels so signals are less related
85
+        #transMatrix, K, means = pca.pca( np.array([rx0, rx1]))   
86
+        #RR = np.zeros(( np.shape(R[0])[0]*np.shape(R[0])[1], len(R)))
87
+#         RR = np.zeros(( len(R), np.shape(R[0])[0]*np.shape(R[0])[1] ))
88
+#         for ir in range(len(R)):
89
+#             RR[ir,:] = np.reshape(R[ir], -1)
90
+#         transMatrix, K, means = pca.pca(RR)    
91
+#         #R rx0 = transMatrix[0,:]
92
+#         # rx1 = transMatrix[1,:]
93
+#         for ir in range(len(R)):
94
+#             R[ir] = transMatrix[ir,0]
95
+
96
+        import scipy.linalg 
97
+        import akvo.tressel.pca as pca 
98
+        # Compute as many transfer functions as len(R)
99
+        # A*H = B
100
+        nref = len(R)
101
+        H = np.zeros( (np.shape(D)[1], len(R)), dtype=complex )
102
+        for iw in range(np.shape(D)[1]):
103
+            A = np.zeros( (nref, nref), dtype=complex )
104
+            B = np.zeros( (nref) , dtype=complex)
105
+            for ii in range(nref):
106
+                for jj in range(nref):
107
+                    # build A
108
+                    A[ii,jj] = np.dot(R[ii][:,iw], R[jj][:,iw])                 
109
+
110
+                # build B
111
+                B[ii] = np.dot( R[ii][:,iw], D[:,iw] )
112
+
113
+            # compute H(iw)
114
+            #linalg.solve(a,b) if a is square
115
+            #print "A", A
116
+            #print "B", B
117
+            # TODO, regularise this solve step? So as to not fit the spurious noise
118
+            #print np.shape(B), np.shape(A) 
119
+            #H[iw, :] = scipy.linalg.solve(A,B)
120
+            H[iw, :] = scipy.linalg.lstsq(A,B,cond=reg)[0]
121
+            #print "lstqt", np.shape(scipy.linalg.lstsq(A,B))
122
+            #print "solve", scipy.linalg.solve(A,B)
123
+            #H[iw,:]  = scipy.linalg.lstsq(A,B) # otherwise 
124
+                #H = np.zeros( (np.shape(D)[1], )   )
125
+        #print H #A, B
126
+        Error = np.zeros(np.shape(D), dtype=complex)
127
+        for ir in range(nref):
128
+            for q in range( np.shape(D)[0] ):
129
+                #print "dimcheck", np.shape(H[:,ir]), np.shape(R[ir][q,:] )
130
+                Error[q,:] += H[:,ir]*R[ir][q,:]
131
+        return D - Error
132
+
133
+    def adapt_filt_tworefFreq(self, x, rx0, rx1, M, lambda2=0.95):
134
+        """ Frequency domain version of above
135
+        """
136
+        from akvo.tressel import pca 
137
+
138
+        pylab.figure()
139
+        pylab.plot(rx0)
140
+        pylab.plot(rx1)
141
+
142
+        # PCA decomposition on ref channels so signals are less related
143
+        transMatrix, K, means = pca.pca( np.array([rx0, rx1]))    
144
+        rx0 = transMatrix[:,0]
145
+        rx1 = transMatrix[:,1]
146
+        
147
+        pylab.plot(rx0)
148
+        pylab.plot(rx1)
149
+        pylab.show()
150
+        exit()
151
+
152
+        if np.shape(x) != np.shape(rx0) or np.shape(x) != np.shape(rx1):
153
+            print ("Error, non aligned")
154
+            exit(1)
155
+
156
+        wx = fft.rfft(x)
157
+        wr0 = fft.rfft(rx0)
158
+        wr1 = fft.rfft(rx1)
159
+ 
160
+        H = np.zeros( (2*M), dtype=complex ) 
161
+        ident_mat = np.eye((2*M))
162
+        Rn = ident_mat / 0.1
163
+        r_v = np.zeros( (M), dtype=complex ) 
164
+        r_h = np.zeros( (M), dtype=complex ) 
165
+        e = np.zeros(len(x), dtype=complex )
166
+        ilambda = lambda2**-1
167
+
168
+        for z in range(0, len(wx)):
169
+            # TODO Padd with Zeros or truncate if M >,< arrays 
170
+            r_v = wr0[::-1][:M] 
171
+            r_h = wr1[::-1][:M] 
172
+            r_n = np.concatenate((r_v, r_h ))
173
+            K      = np.dot(Rn, r_n) / (lambda2 + np.dot(np.dot(r_n.T, Rn), r_n))  # Create/update K
174
+            e[z]   = wx[z] - np.dot(r_n,H)        # e is the filtered signal, input - r(n) * Filter Coefs
175
+            H     += K * e[z];                    # Update Filter Coefficients
176
+            Rn     = ilambda*Rn - ilambda*K*r_n.T*Rn  # Update R(n)
177
+        
178
+        return fft.irfft(e)
179
+
180
+    def iter_filt_refFreq(self, x, rx0, Ahat=.05, Bhat=.5, k=0.05):
181
+
182
+        X = np.fft.rfft(x)
183
+        X0 = np.copy(X)
184
+        RX0 = np.fft.rfft(rx0)
185
+
186
+        # step 0
187
+        Abs2HW = []
188
+        alphai =  k * (np.abs(Ahat)**2 / np.abs(Bhat)**2) 
189
+        betai  =  k * (1. / (np.abs(Bhat)**2) ) 
190
+        Hw     =  ((1.+alphai) * np.abs(X)**2 ) / (np.abs(X)**2 + betai*(np.abs(RX0)**2))
191
+        H      =  np.abs(Hw)**2
192
+        pylab.ion()
193
+        pylab.figure()
194
+        for i in range(10):
195
+            #print "alphai", alphai
196
+            #print "betai", betai
197
+            #print "Hw", Hw
198
+            alphai = k * (np.abs(Ahat)**2 / np.abs(Bhat)**2) * np.product(H, axis=0)
199
+            betai  = k * (1. / np.abs(Bhat)**2) * np.product(H, axis=0)
200
+            # update signal
201
+            Hw   =  ((1.+alphai) * np.abs(X)**2) / (np.abs(X)**2 + betai*np.abs(RX0)**2)
202
+            Hw = np.nan_to_num(Hw)
203
+            X *= Hw
204
+            H = np.vstack( (H, np.abs(Hw)**2) )
205
+            #print "Hw", Hw
206
+            pylab.cla()
207
+            pylab.plot(Hw)
208
+            #pylab.plot(np.abs(X))
209
+            #pylab.plot(np.abs(RX0))
210
+            pylab.draw()
211
+            raw_input("wait")
212
+
213
+        pylab.cla()
214
+        pylab.ioff()
215
+        #return np.fft.irfft(X0-X)
216
+        return np.fft.irfft(X)
217
+
218
+    def iter_filt_refFreq(self, x, rx0, rx1, Ahat=.1, Bhat=1., k=0.001):
219
+
220
+        X = np.fft.rfft(x)
221
+        X0 = np.copy(X)
222
+        RX0 = np.fft.rfft(rx0)
223
+        RX1 = np.fft.rfft(rx1)
224
+
225
+        # step 0
226
+        alphai =  k * (np.abs(Ahat)**2 / np.abs(Bhat)**2) 
227
+        betai  =  k * (1. / (np.abs(Bhat)**2) ) 
228
+        #Hw     =  ((1.+alphai) * np.abs(X)**2 ) / (np.abs(X)**2 + betai*(np.abs(RX0)**2))
229
+        H      =  np.ones(len(X)) # abs(Hw)**2
230
+        #pylab.ion()
231
+        #pylab.figure(334)
232
+        for i in range(1000):
233
+            #print "alphai", alphai
234
+            #print "betai", betai
235
+            #print "Hw", Hw
236
+            alphai = k * (np.abs(Ahat)**2 / np.abs(Bhat)**2) * np.product(H, axis=0)
237
+            betai  = k * (1. / np.abs(Bhat)**2) * np.product(H, axis=0)
238
+            # update signal
239
+            Hw   =  ((1.+alphai) * np.abs(X)**2) / (np.abs(X)**2 + betai*np.abs(RX0)**2)
240
+            Hw = np.nan_to_num(Hw)
241
+            X *= Hw #.conjugate
242
+            #H = np.vstack((H, np.abs(Hw)**2) )
243
+            H = np.vstack((H, np.abs(Hw)) )
244
+            #print "Hw", Hw
245
+            #pylab.cla()
246
+            #pylab.plot(Hw)
247
+            #pylab.plot(np.abs(X))
248
+            #pylab.plot(np.abs(RX0))
249
+            #pylab.draw()
250
+            #raw_input("wait")
251
+
252
+        #pylab.cla()
253
+        #pylab.ioff()
254
+        return np.fft.irfft(X0-X)
255
+        #return np.fft.irfft(X)
256
+
257
+    def Tdomain_DFT(self, desired, input, S):
258
+        """ Lifted from Adaptive filtering toolbox. Modefied to accept more than one input 
259
+            vector
260
+        """
261
+        
262
+        # Initialisation Procedure
263
+        nCoefficients =   S["filterOrderNo"]/2+1
264
+        nIterations   =   len(desired)
265
+
266
+        # Pre Allocations
267
+        errorVector  = np.zeros(nIterations, dtype='complex')
268
+        outputVector = np.zeros(nIterations, dtype='complex')
269
+        
270
+        # Initial State
271
+        coefficientVectorDFT =   np.fft.rfft(S["initialCoefficients"])/np.sqrt(float(nCoefficients))
272
+        desiredDFT           =   np.fft.rfft(desired)
273
+        powerVector          =   S["initialPower"]*np.ones(nCoefficients)
274
+
275
+        # Improve source code regularity, pad with zeros
276
+        # TODO, confirm zeros(nCoeffics) not nCoeffics-1
277
+        prefixedInput  =   np.concatenate([np.zeros(nCoefficients-1), np.array(input)])
278
+
279
+        # Body
280
+        pylab.ion()
281
+        pylab.figure(11)
282
+        for it in range(nIterations): # = 1:nIterations,
283
+            
284
+            regressorDFT = np.fft.rfft(prefixedInput[it:it+nCoefficients][::-1]) /\
285
+                           np.sqrt(float(nCoefficients))
286
+
287
+            # Summing two column vectors
288
+            powerVector = S["alpha"] * (regressorDFT*np.conjugate(regressorDFT)) + \
289
+                                  (1.-S["alpha"])*(powerVector)
290
+
291
+            pylab.cla()
292
+            #pylab.plot(prefixedInput[::-1], 'b')
293
+            #pylab.plot(prefixedInput[it:it+nCoefficients][::-1], 'g', linewidth=3)
294
+            #pylab.plot(regressorDFT.real)
295
+            #pylab.plot(regressorDFT.imag)
296
+            pylab.plot(powerVector.real)
297
+            pylab.plot(powerVector.imag)
298
+            #pylab.plot(outputVector)
299
+            #pylab.plot(errorVector.real)
300
+            #pylab.plot(errorVector.imag)
301
+            pylab.draw()
302
+            #raw_input("wait")
303
+
304
+            outputVector[it] = np.dot(coefficientVectorDFT.T, regressorDFT)
305
+
306
+            #errorVector[it] = desired[it] - outputVector[it]
307
+            errorVector[it] = desiredDFT[it] - outputVector[it]
308
+
309
+            #print errorVector[it], desired[it], outputVector[it]
310
+
311
+            # Vectorized
312
+            coefficientVectorDFT += (S["step"]*np.conjugate(errorVector[it])*regressorDFT) /\
313
+                                    (S['gamma']+powerVector)
314
+
315
+        return np.real(np.fft.irfft(errorVector))
316
+        #coefficientVector = ifft(coefficientVectorDFT)*sqrt(nCoefficients);
317
+
318
+    def Tdomain_DCT(self, desired, input, S):
319
+        """ Lifted from Adaptive filtering toolbox. Modefied to accept more than one input 
320
+            vector. Uses cosine transform
321
+        """
322
+        from scipy.fftpack import dct
323
+ 
324
+        # Initialisation Procedure
325
+        nCoefficients =   S["filterOrderNo"]+1
326
+        nIterations   =   len(desired)
327
+
328
+        # Pre Allocations
329
+        errorVector  = np.zeros(nIterations)
330
+        outputVector = np.zeros(nIterations)
331
+        
332
+        # Initial State
333
+        coefficientVectorDCT =   dct(S["initialCoefficients"]) #/np.sqrt(float(nCoefficients))
334
+        desiredDCT           =   dct(desired)
335
+        powerVector          =   S["initialPower"]*np.ones(nCoefficients)
336
+
337
+        # Improve source code regularity, pad with zeros
338
+        prefixedInput  =   np.concatenate([np.zeros(nCoefficients-1), np.array(input)])
339
+        
340
+        # Body
341
+        #pylab.figure(11)
342
+        #pylab.ion()
343
+        for it in range(0, nIterations): # = 1:nIterations,
344
+            
345
+            regressorDCT = dct(prefixedInput[it:it+nCoefficients][::-1], type=2) 
346
+            #regressorDCT = dct(prefixedInput[it+nCoefficients:it+nCoefficients*2+1])#[::-1]) 
347
+
348
+            # Summing two column vectors
349
+            powerVector = S["alpha"]*(regressorDCT) + (1.-S["alpha"])*(powerVector)
350
+            #pylab.cla()
351
+            #pylab.plot(powerVector)
352
+            #pylab.draw()
353
+
354
+            outputVector[it] = np.dot(coefficientVectorDCT.T, regressorDCT)
355
+            #errorVector[it] = desired[it] - outputVector[it]
356
+            errorVector[it] = desiredDCT[it] - outputVector[it]
357
+
358
+            # Vectorized
359
+            coefficientVectorDCT += (S["step"]*errorVector[it]*regressorDCT) #/\
360
+                                    #(S['gamma']+powerVector)
361
+
362
+        #pylab.plot(errorVector)
363
+        #pylab.show()
364
+        return dct(errorVector, type=3)
365
+        #coefficientVector = ifft(coefficientVectorDCT)*sqrt(nCoefficients);
366
+
367
+
368
+
369
+    def Tdomain_CORR(self, desired, input, S):
370
+
371
+        from scipy.linalg import toeplitz
372
+        from scipy.signal import correlate
373
+
374
+        # Autocorrelation
375
+        ac = np.correlate(input, input, mode='full')
376
+        ac = ac[ac.size/2:]
377
+        R = toeplitz(ac)
378
+        
379
+        # cross correllation
380
+        r = np.correlate(desired, input, mode='full')
381
+        r = r[r.size/2:]
382
+        
383
+        #r = np.correlate(desired, input, mode='valid')
384
+        print ("R", np.shape(R))
385
+        print ("r", np.shape(r))
386
+        print ("solving")
387
+        #H = np.linalg.solve(R,r)
388
+        H = np.linalg.lstsq(R,r,rcond=.01)[0]
389
+        #return desired - np.dot(H,input)
390
+        print ("done solving")
391
+        pylab.figure()
392
+        pylab.plot(H)
393
+        pylab.title("H")
394
+        #return desired - np.convolve(H, input, mode='valid')
395
+        #return desired - np.convolve(H, input, mode='same')
396
+        #return np.convolve(H, input, mode='same')
397
+        return desired - np.dot(toeplitz(H), input)
398
+        #return np.dot(R, H)
399
+
400
+#         T = toeplitz(input)
401
+#         print "shapes", np.shape(T), np.shape(desired)
402
+#         h = np.linalg.lstsq(T, desired)[0]
403
+#         print "shapes", np.shape(h), np.shape(input)
404
+#         #return np.convolve(h, input, mode='same')
405
+#         return desired - np.dot(T,h)
406
+ 
407
+    def Fdomain_CORR(self, desired, input, dt, freq):
408
+        
409
+        from scipy.linalg import toeplitz
410
+        
411
+        # Fourier domain
412
+        Input = np.fft.rfft(input)
413
+        Desired = np.fft.rfft(desired)
414
+
415
+        T = toeplitz(Input)
416
+        #H = np.linalg.solve(T, Desired)
417
+        H = np.linalg.lstsq(T, Desired)[0]
418
+#         ac = np.correlate(Input, Input, mode='full')
419
+#         ac = ac[ac.size/2:]
420
+#         R = toeplitz(ac)
421
+#         
422
+#         r = np.correlate(Desired, Input, mode='full')
423
+#         r = r[r.size/2:]
424
+#         
425
+#         #r = np.correlate(desired, input, mode='valid')
426
+#         print "R", np.shape(R)
427
+#         print "r", np.shape(r)
428
+#         print "solving"
429
+#         H = np.linalg.solve(R,r)
430
+#         #H = np.linalg.lstsq(R,r)
431
+#         #return desired - np.dot(H,input)
432
+#         print "done solving"
433
+        pylab.figure()
434
+        pylab.plot(H.real)
435
+        pylab.plot(H.imag)
436
+        pylab.plot(Input.real)
437
+        pylab.plot(Input.imag)
438
+        pylab.plot(Desired.real)
439
+        pylab.plot(Desired.imag)
440
+        pylab.legend(["hr","hi","ir","ii","dr","di"])
441
+        pylab.title("H")
442
+        #return desired - np.fft.irfft(Input*H)
443
+        return np.fft.irfft(H*Input)
444
+
445
+    def Tdomain_RLS(self, desired, input, S):
446
+        """
447
+            A DFT is first performed on the data. Than a RLS algorithm is carried out 
448
+            for noise cancellation. Related to the RLS_Alt Algoritm 5.3 in  Diniz book.
449
+            The desired and input signals are assummed to be real time series data.
450
+        """
451
+
452
+        # Transform data into frequency domain
453
+        Input = np.fft.rfft(input)
454
+        Desired = np.fft.rfft(desired)
455
+
456
+        # Initialisation Procedure
457
+        nCoefficients = S["filterOrderNo"]+1
458
+        nIterations   = len(Desired)
459
+
460
+        # Pre Allocations
461
+        errorVector  = np.zeros(nIterations, dtype="complex")
462
+        outputVector = np.zeros(nIterations, dtype="complex")
463
+        errorVectorPost  = np.zeros(nIterations, dtype="complex")
464
+        outputVectorPost = np.zeros(nIterations, dtype="complex")
465
+        coefficientVector = np.zeros( (nCoefficients, nIterations+1), dtype="complex" )        
466
+
467
+        # Initial State
468
+        coefficientVector[:,1] = S["initialCoefficients"]  
469
+        S_d                    = S["delta"]*np.eye(nCoefficients)
470
+
471
+        # Improve source code regularity, pad with zeros
472
+        prefixedInput = np.concatenate([np.zeros(nCoefficients-1, dtype="complex"), 
473
+                                np.array(Input)])
474
+        invLambda = 1./S["lambda"]
475
+        
476
+        # Body
477
+        pylab.ion()
478
+        pylab.figure(11)
479
+
480
+        for it in range(nIterations):
481
+            
482
+            regressor = prefixedInput[it:it+nCoefficients][::-1]
483
+
484
+            # a priori estimated output
485
+            outputVector[it] = np.dot(coefficientVector[:,it].T, regressor)
486
+       
487
+            # a priori error
488
+            errorVector[it] = Desired[it] - outputVector[it]
489
+
490
+            psi             = np.dot(S_d, regressor)
491
+            if np.isnan(psi).any():
492
+                print ("psi", psi)
493
+                exit(1)
494
+            
495
+            pylab.cla()
496
+            #pylab.plot(psi)
497
+            pylab.plot(regressor.real)
498
+            pylab.plot(regressor.imag)
499
+            pylab.plot(coefficientVector[:,it].real)
500
+            pylab.plot(coefficientVector[:,it].imag)
501
+            pylab.legend(["rr","ri", "cr", "ci"])
502
+            pylab.draw()
503
+            raw_input("paws")
504
+
505
+            S_d             = invLambda * (S_d - np.dot(psi, psi.T)  /\
506
+                                S["lambda"] + np.dot(psi.T, regressor))
507
+
508
+            coefficientVector[:,it+1] = coefficientVector[:,it] + \
509
+                                        np.conjugate(errorVector[it])*np.dot(S_d, regressor)
510
+            # A posteriori estimated output
511
+            outputVectorPost[it]  =  np.dot(coefficientVector[:,it+1].T, regressor)
512
+
513
+            # A posteriori error
514
+            errorVectorPost[it] = Desired[it] - outputVectorPost[it]
515
+ 
516
+        errorVectorPost = np.nan_to_num(errorVectorPost)
517
+
518
+        pylab.figure(11)
519
+        print (np.shape(errorVectorPost))
520
+        pylab.plot(errorVectorPost.real)
521
+        pylab.plot(errorVectorPost.imag)
522
+        pylab.show()
523
+        print(errorVectorPost)
524
+        #return np.fft.irfft(Desired)
525
+        return np.fft.irfft(errorVectorPost)
526
+
527
+if __name__ == "__main__":
528
+
529
+    def noise(nu, t, phi):
530
+        return np.sin(nu*2.*np.pi*t + phi)
531
+
532
+    import matplotlib.pyplot as plt
533
+    print("Test driver for adaptive filtering")
534
+    Filt = AdaptiveFilter(.1)
535
+    t = np.arange(0, .5, 1e-4)
536
+    omega = 2000 * 2.*np.pi
537
+    T2 = .100
538
+    n1 = noise(60, t, .2   )
539
+    n2 = noise(61, t, .514 )
540
+    x = np.sin(omega*t)* np.exp(-t/T2) + 2.3*noise(60, t, .34) + 1.783*noise(31, t, 2.1)
541
+    e = Filt.adapt_filt_tworef(x, n1, n2, 200, .98)
542
+    plt.plot(t,  x)
543
+    plt.plot(t, n1)
544
+    plt.plot(t, n2)
545
+    plt.plot(t,  e)
546
+    plt.show()

+ 1070
- 0
akvo/tressel/cmaps.py
File diff suppressed because it is too large
View File


+ 68
- 0
akvo/tressel/cpca.pyx View File

1
+##########################################################
2
+#
3
+#
4
+#
5
+#
6
+#
7
+#from scipy import mean
8
+import numpy
9
+
10
+def pca(A, remove=[]):
11
+    ''' The input matrix A should be a 2D numpy array in column-major 
12
+        order. Each column is a dataset and PCA will be applied across
13
+        columns
14
+    '''
15
+    #nrow = len(A[:,0])
16
+    #ncol = len(A[0,:])
17
+    nrow,ncol = numpy.shape(A)
18
+
19
+    # Cast into matrix type for easier math
20
+    A = numpy.matrix(A)
21
+
22
+    # Allocate Covariance Matrix
23
+    covMatrix = numpy.matrix(numpy.zeros((nrow, nrow)))
24
+    
25
+    # Compute Means of each row. Each column must be normalised
26
+    meanArray = []
27
+    for i in range(nrow):
28
+        meanArray.append(numpy.mean(A[i].tolist()[0]) ) 
29
+        A[i] -= meanArray[i]
30
+    meanArray = numpy.array(meanArray) 
31
+    
32
+    # Generate Covariance Matrix
33
+    covMatrix = numpy.cov(A)
34
+
35
+    # Compute Eigen Values, Eigen Vectors     
36
+    eigs = numpy.linalg.eig(covMatrix)
37
+    K = eigs[1].T
38
+    
39
+    #print K
40
+    #print "Eigen Values"
41
+    #print eigs[0]
42
+    
43
+    # Zero requested components
44
+    for i in remove:
45
+        K[i] = numpy.zeros(len(K))        
46
+
47
+    # Make Transform Matrices
48
+    transMatrix = K*A
49
+    
50
+    # Return Necssary Stuff
51
+    return numpy.array(transMatrix), K, meanArray
52
+    #return K, A, meanArray 
53
+
54
+#def invpca(K, A, means):
55
+def invpca(transMatrix, K, means):
56
+    '''Converts a PCA rotated dataset back to normal. Input parameters
57
+    are the components to discard in re-creation.
58
+    '''
59
+    K = numpy.matrix(K)
60
+    # Transform and Untransform the data
61
+    #transMatrix = K*A
62
+    untransMatrix = K.T*transMatrix
63
+    
64
+    # Correct for normalisation
65
+    for i in range(len(transMatrix)):
66
+        untransMatrix[i] += means[i]
67
+
68
+    return untransMatrix    

+ 550
- 0
akvo/tressel/decay.py View File

1
+import numpy, pylab,array #,rpy2
2
+
3
+from rpy2.robjects.packages import importr
4
+
5
+import rpy2.robjects as robjects
6
+import rpy2.robjects.numpy2ri
7
+
8
+#import notch
9
+from numpy.fft import fft, fftfreq
10
+
11
+# We know/can calculate frequency peak, use this to guess where picks will be.
12
+# maybe have a sliding window that reports peak values.
13
+def peakPicker(data, omega, dt):
14
+
15
+    # compute window based on omega and dt
16
+    # make sure you are not aliased, grab every other peak
17
+    window = (2*numpy.pi) / (omega*dt)
18
+
19
+    data = numpy.array(data) 
20
+    peaks = []
21
+    troughs = []
22
+    times = []
23
+    times2 = []
24
+    indices = []
25
+    ws = 0
26
+    we = window
27
+    ii = 0
28
+    for i in range((int)(len(data)/window)):
29
+        
30
+        # initially was just returning this I think avg is better
31
+        #times.append( (ws + numpy.abs(data[ws:we]).argmax()) * dt )
32
+    
33
+        peaks.append(numpy.max(data[ws:we]))
34
+        times.append( (ws + data[ws:we].argmax()) * dt )
35
+        indices.append( ii + data[ws:we].argmax() )        
36
+
37
+        troughs.append(numpy.min(data[ws:we]))
38
+        times2.append( (ws + (data[ws:we]).argmin()) * dt )
39
+        indices.append( ii + data[ws:we].argmin() )        
40
+
41
+        ws += window
42
+        we += window
43
+        ii += (int)(we-ws)
44
+    
45
+    #return numpy.array(peaks), numpy.array(times)
46
+    
47
+    # Averaging peaks does a good job of removing bias in noise
48
+    return (numpy.array(peaks)-numpy.array(troughs))/2., \
49
+        (numpy.array(times)+numpy.array(times2))/2., \
50
+        indices           
51
+
52
+
53
+#################################################
54
+# Regress for T2 using rpy2 interface
55
+def regressCurve(peaks,times,sigma2=None  ,intercept=True):
56
+
57
+    # TODO, if regression fails, it might be because there is no exponential
58
+    # term, maybe do a second regression then on a linear model. 
59
+    b1  = 0                  # Bias
60
+    b2  = 0                  # Linear 
61
+    rT2 = 0.3                # T2 regressed
62
+    r   = robjects.r         
63
+
64
+    # Variable shared between R and Python
65
+    robjects.globalenv['b1'] = b1
66
+    robjects.globalenv['b2'] = b2
67
+    robjects.globalenv['rT2'] = rT2
68
+    #robjects.globalenv['sigma2'] = sigma2
69
+    value = robjects.FloatVector(peaks)
70
+    times = robjects.FloatVector(numpy.array(times))
71
+    
72
+#    my_weights = robjects.RVector(value/sigma2)
73
+#    robjects.globalenv['my_weigts'] = my_weights
74
+
75
+    if sigma2 != None:
76
+        # print ("weighting")
77
+        #tw = numpy.array(peaks)/sigma2 
78
+        my_weights = robjects.FloatVector( sigma2 )
79
+    #else:
80
+    #    my_weights = robjects.FloatVector(numpy.ones(len(peaks))) 
81
+
82
+        robjects.globalenv['my_weights'] = my_weights
83
+        #print (my_weights)
84
+        #print (len(peaks))
85
+    
86
+    if (intercept):
87
+        my_list = robjects.r('list(b1=50, b2=1e2, rT2=0.03)')
88
+        my_lower = robjects.r('list(b1=0, b2=0, rT2=.005)')
89
+        my_upper = robjects.r('list(b1=20000, b2=2000, rT2=.700)')
90
+    else:
91
+        my_list = robjects.r('list(b2=1e2, rT2=0.3)')
92
+        my_lower = robjects.r('list(b2=0, rT2=.005)')
93
+        my_upper = robjects.r('list(b2=2000, rT2=.700)')
94
+
95
+    my_cont = robjects.r('nls.control(maxiter=1000, warnOnly=TRUE, printEval=FALSE)')
96
+
97
+    
98
+    if (intercept):
99
+        #fmla = robjects.RFormula('value ~ b1 + exp(-times/rT2)')
100
+        fmla = robjects.Formula('value ~ b1 + b2*exp(-times/rT2)')
101
+        #fmla = robjects.RFormula('value ~ b1 + b2*times + exp(-times/rT2)')
102
+    else:
103
+        fmla = robjects.Formula('value ~ b2*exp(-times/rT2)')
104
+
105
+    env = fmla.getenvironment()
106
+    env['value'] = value
107
+    env['times'] = times
108
+    
109
+    # ugly, but I get errors with everything else I've tried
110
+    #my_weights = robjects.r('rep(1,length(value))')
111
+    #for ii in range(len(my_weights)):
112
+    #    my_weights[ii] *= peaks[ii]/sigma2
113
+
114
+
115
+    Error = False
116
+    #fit = robjects.r.nls(fmla,start=my_list,control=my_cont,weights=my_weights)
117
+    if (sigma2 != None):
118
+        #print("SIGMA 2")
119
+        #fit = robjects.r.tryCatch(robjects.r.suppressWarnings(robjects.r.nls(fmla,start=my_list,control=my_cont,algorithm="port", \
120
+        #                     weights=my_weights)), 'silent=TRUE')
121
+        try:
122
+            fit = robjects.r.tryCatch(    robjects.r.nls(fmla, start=my_list, control=my_cont, weights=my_weights, algorithm="port" , \
123
+                lower=my_lower,upper=my_upper))
124
+        except:
125
+            print("regression issue pass")
126
+            Error = True
127
+                            # weights=my_weights))
128
+    else:
129
+        try:
130
+            fit = robjects.r.tryCatch(robjects.r.nls(fmla,start=my_list,control=my_cont,algorithm="port",lower=my_lower,upper=my_upper))
131
+        except:
132
+            print("regression issue pass")
133
+            Error = True
134
+    # If failure fall back on zero regression values   
135
+    if not Error:
136
+        #Error = fit[3][0]
137
+        report =  r.summary(fit)
138
+    b1 = 0
139
+    b2 = 0 
140
+    rT2 = 1
141
+    if (intercept):
142
+        if not Error:
143
+            b1  =  r['$'](report,'par')[0]
144
+            b2  =  r['$'](report,'par')[1]
145
+            rT2 =  r['$'](report,'par')[2]
146
+            #print  report
147
+            #print  r['$'](report,'convergence')
148
+            #print  r['convergence'] #(report,'convergence')
149
+            #print  r['$'](report,'par')[13]
150
+            #print  r['$'](report,'par')[14]
151
+        else:
152
+            print("ERROR DETECTED, regressed values set to default")
153
+            b1 = 1e1
154
+            b2 = 1e-2
155
+            rT2 = 1e-2
156
+            #print r['$'](report,'par')[0]
157
+            #print r['$'](report,'par')[1]
158
+            #print r['$'](report,'par')[2]
159
+        return [b1,b2,rT2] 
160
+    else:
161
+        if not Error:
162
+            rT2 =  r['$'](report,'par')[1]
163
+            b2  =  r['$'](report,'par')[0]
164
+        else:
165
+            print("ERROR DETECTED, regressed values set to default")
166
+        return [b2, rT2] 
167
+
168
+def quadratureDetect(X, Y, tt):
169
+    
170
+    r   = robjects.r         
171
+
172
+    robjects.r(''' 
173
+         Xc <- function(E0, df, tt, phi, T2) {
174
+	            E0 * -sin(2*pi*df*tt + phi) * exp(-tt/T2)
175
+                }
176
+
177
+         Yc <- function(E0, df, tt, phi, T2) {
178
+	            E0 * cos(2*pi*df*tt + phi) * exp(-tt/T2)
179
+                } 
180
+         ''')  
181
+
182
+    # Make 0 vector 
183
+    Zero = robjects.FloatVector(numpy.zeros(len(X)))
184
+    
185
+    # Fitted Parameters
186
+    E0 = 0.
187
+    df = 0.
188
+    phi = 0.
189
+    T2 = 0.
190
+    robjects.globalenv['E0'] = E0
191
+    robjects.globalenv['df'] = df
192
+    robjects.globalenv['phi'] = phi
193
+    robjects.globalenv['T2'] = T2
194
+    XY = robjects.FloatVector(numpy.concatenate((X,Y)))
195
+    
196
+    # Arrays
197
+    tt = robjects.FloatVector(numpy.array(tt))
198
+    X = robjects.FloatVector(numpy.array(X))
199
+    Y = robjects.FloatVector(numpy.array(Y))
200
+    Zero = robjects.FloatVector(numpy.array(Zero))
201
+
202
+    #fmla = robjects.Formula('Zero ~ QI( E0, df, tt, phi, T2, X, Y )')
203
+    #fmla = robjects.Formula('X ~ Xc( E0, df, tt, phi, T2 )')
204
+    #fmla = robjects.Formula('Y ~ Yc( E0, df, tt, phi, T2 )')
205
+    fmla = robjects.Formula('XY ~ c(Xc( E0, df, tt, phi, T2 ), Yc( E0, df, tt, phi, T2 ))')
206
+
207
+    env = fmla.getenvironment()
208
+    env['Zero'] = Zero
209
+    env['X'] = X
210
+    env['Y'] = Y
211
+    env['XY'] = XY 
212
+    env['tt'] = tt
213
+    
214
+    # Bounds and control    
215
+    start = robjects.r('list(E0=100,   df= 0   , phi=   0.00,  T2=.100)')
216
+    lower = robjects.r('list(E0=1,     df=-13.0, phi=  -3.14,  T2=.005)')
217
+    upper = robjects.r('list(E0=1000,  df= 13.0, phi=   3.14,  T2=.800)')
218
+
219
+    cont = robjects.r('nls.control(maxiter=10000, warnOnly=TRUE, printEval=FALSE)')
220
+    
221
+    fit = robjects.r.tryCatch(robjects.r.nls(fmla, start=start, control=cont, lower=lower, upper=upper, algorithm='port')) #, \
222
+    report =  r.summary(fit)
223
+    #print (report)
224
+    
225
+    E0  =  r['$'](report,'par')[0]
226
+    df  =  r['$'](report,'par')[1]
227
+    phi =  r['$'](report,'par')[2]
228
+    T2  =  r['$'](report,'par')[3]
229
+    #print ( E0,df,phi,T2 )
230
+    return E0,df,phi,T2
231
+    
232
+
233
+#################################################
234
+# Regress for T2 using rpy2 interface
235
+def regressSpec(w, wL, X): #,sigma2=1,intercept=True):
236
+
237
+    # compute s
238
+    s = -1j*w
239
+
240
+    # TODO, if regression fails, it might be because there is no exponential
241
+    # term, maybe do a second regression then on a linear model. 
242
+    a   = 0                  # Linear 
243
+    rT2 = 0.1                # T2 regressed
244
+    r   = robjects.r         
245
+
246
+    # Variable shared between R and Python
247
+    robjects.globalenv['a'] = a
248
+    #robjects.globalenv['w'] = w
249
+    robjects.globalenv['rT2'] = rT2
250
+    robjects.globalenv['wL'] = wL
251
+    robjects.globalenv['nb'] = 0
252
+
253
+    #s = robjects.ComplexVector(numpy.array(s))
254
+    w = robjects.FloatVector(numpy.array(w))
255
+    XX = robjects.FloatVector(X)
256
+    #Xr = robjects.FloatVector(numpy.real(X))
257
+    #Xi = robjects.FloatVector(numpy.imag(X))
258
+    #Xa = robjects.FloatVector(numpy.abs(X))
259
+    #Xri = robjects.FloatVector(numpy.concatenate((Xr,Xi)))
260
+    
261
+    #my_lower = robjects.r('list(a=.001, rT2=.001, nb=.0001)')
262
+    my_lower = robjects.r('list(a=.001, rT2=.001)')
263
+    #my_upper = robjects.r('list(a=1.5, rT2=.300, nb =100.)')
264
+    my_upper = robjects.r('list(a=1.5, rT2=.300)')
265
+     
266
+    #my_list = robjects.r('list(a=.2, rT2=0.03, nb=.1)')
267
+    my_list = robjects.r('list(a=.2, rT2=0.03)')
268
+    my_cont = robjects.r('nls.control(maxiter=5000, warnOnly=TRUE, printEval=FALSE)')
269
+    
270
+    #fmla = robjects.Formula('Xri ~ c(a*Re((wL) / (wL^2+(s+1/rT2)^2 )), a*Im((wL)/(wL^2 + (s+1/rT2)^2 )))') # envelope
271
+    ##fmla = robjects.Formula('Xri ~ c(a*Re((wL) / (wL^2+(s+1/rT2)^2 )), a*Im((wL)/(wL^2 + (s+1/rT2)^2 )))') # envelope
272
+    #fmla = robjects.Formula('XX ~ a*(wL) / (wL^2 + (s+1/rT2)^2 )') # complex
273
+    #fmla = robjects.Formula('Xa ~ abs(a*(wL) / (wL^2 + (s+1/rT2)^2 )) + nb') # complex
274
+    #fmla = robjects.Formula('XX ~ Re(a*( s + 1./rT2 )  / (wL^2 + (s+1/rT2)^2 ))') # complex
275
+    fmla = robjects.Formula('XX ~ a*(.5/rT2)  / ((1./rT2)^2 + (w-wL)^2 )')
276
+    #fmla = robjects.Formula('Xa ~ (s + 1./T2) / ( wL**2 + (1/T2 + 1j*w)**2 ) ')
277
+ 
278
+    env = fmla.getenvironment()
279
+    #env['s'] = s
280
+    env['w'] = w
281
+    #env['Xr'] = Xr
282
+    #env['Xa'] = Xa
283
+    #env['Xi'] = Xi
284
+    #env['Xri'] = Xri
285
+    env['XX'] = XX
286
+     
287
+    #fit = robjects.r.tryCatch(robjects.r.nls(fmla,start=my_list, control=my_cont)) #, lower=my_lower, algorithm='port')) #, \
288
+    fit = robjects.r.tryCatch(robjects.r.nls(fmla, start=my_list, control=my_cont, lower=my_lower, upper=my_upper, algorithm='port')) #, \
289
+    report =  r.summary(fit)
290
+    #print report 
291
+    #print(r.warnings())
292
+ 
293
+    a  =  r['$'](report,'par')[0]
294
+    rT2 =  r['$'](report,'par')[1]
295
+    nb =  r['$'](report,'par')[2]
296
+    
297
+    return a, rT2, nb
298
+
299
+#################################################
300
+# Regress for T2 using rpy2 interface
301
+def regressModulus(w, wL, X): #,sigma2=1,intercept=True):
302
+
303
+    # compute s
304
+    s = -1j*w
305
+
306
+    # TODO, if regression fails, it might be because there is no exponential
307
+    # term, maybe do a second regression then on a linear model. 
308
+    a   = 0                  # Linear 
309
+    rT2 = 0.1                # T2 regressed
310
+    r   = robjects.r         
311
+
312
+    # Variable shared between R and Python
313
+    robjects.globalenv['a'] = a
314
+    robjects.globalenv['rT2'] = rT2
315
+    robjects.globalenv['wL'] = wL
316
+    robjects.globalenv['nb'] = 0
317
+
318
+    s = robjects.ComplexVector(numpy.array(s))
319
+    XX = robjects.ComplexVector(X)
320
+    Xr = robjects.FloatVector(numpy.real(X))
321
+    Xi = robjects.FloatVector(numpy.imag(X))
322
+    Xa = robjects.FloatVector(numpy.abs(X))
323
+    Xri = robjects.FloatVector(numpy.concatenate((Xr,Xi)))
324
+    
325
+    #my_lower = robjects.r('list(a=.001, rT2=.001, nb=.0001)')
326
+    my_lower = robjects.r('list(a=.001, rT2=.001)')
327
+    #my_upper = robjects.r('list(a=1.5, rT2=.300, nb =100.)')
328
+    my_upper = robjects.r('list(a=1.5, rT2=.300)')
329
+     
330
+    #my_list = robjects.r('list(a=.2, rT2=0.03, nb=.1)')
331
+    my_list = robjects.r('list(a=.2, rT2=0.03)')
332
+    my_cont = robjects.r('nls.control(maxiter=5000, warnOnly=TRUE, printEval=FALSE)')
333
+    
334
+    #fmla = robjects.Formula('Xri ~ c(a*Re((wL) / (wL^2+(s+1/rT2)^2 )), a*Im((wL)/(wL^2 + (s+1/rT2)^2 )))') # envelope
335
+    ##fmla = robjects.Formula('Xri ~ c(a*Re((wL) / (wL^2+(s+1/rT2)^2 )), a*Im((wL)/(wL^2 + (s+1/rT2)^2 )))') # envelope
336
+    #fmla = robjects.Formula('XX ~ a*(wL) / (wL^2 + (s+1/rT2)^2 )') # complex
337
+    #fmla = robjects.Formula('Xa ~ abs(a*(wL) / (wL^2 + (s+1/rT2)^2 )) + nb') # complex
338
+    fmla = robjects.Formula('Xa ~ abs(a*(wL) / (wL^2 + (s+1/rT2)^2 ))') # complex
339
+ 
340
+    env = fmla.getenvironment()
341
+    env['s'] = s
342
+    env['Xr'] = Xr
343
+    env['Xa'] = Xa
344
+    env['Xi'] = Xi
345
+    env['Xri'] = Xri
346
+    env['XX'] = XX
347
+     
348
+    #fit = robjects.r.tryCatch(robjects.r.nls(fmla,start=my_list, control=my_cont)) #, lower=my_lower, algorithm='port')) #, \
349
+    fit = robjects.r.tryCatch(robjects.r.nls(fmla, start=my_list, control=my_cont, lower=my_lower, upper=my_upper, algorithm='port')) #, \
350
+    report =  r.summary(fit)
351
+    #print report 
352
+    #print  r.warnings()
353
+ 
354
+    a  =  r['$'](report,'par')[0]
355
+    rT2 =  r['$'](report,'par')[1]
356
+    nb =  r['$'](report,'par')[2]
357
+    
358
+    return a, rT2
359
+
360
+#################################################
361
+# Regress for T2 using rpy2 interface
362
+def regressSpecComplex(w, wL, X, known=True, win=None): #,sigma2=1,intercept=True):
363
+
364
+    # compute s
365
+    s = -1j*w
366
+
367
+    # TODO, if regression fails, it might be because there is no exponential
368
+    # term, maybe do a second regression then on a linear model. 
369
+    a   = 1                  # Linear 
370
+    rT2 = 0.1                # T2 regressed
371
+    r   = robjects.r         
372
+    phi2 = 0                 # phase
373
+    wL2 = wL
374
+
375
+    # Variable shared between R and Python
376
+    robjects.globalenv['a'] = a
377
+    robjects.globalenv['rT2'] = rT2
378
+    robjects.globalenv['wL'] = wL
379
+    robjects.globalenv['wL2'] = 0
380
+    robjects.globalenv['nb'] = 0
381
+    robjects.globalenv['phi2'] = phi2
382
+
383
+    s = robjects.ComplexVector(numpy.array(s))
384
+    XX = robjects.ComplexVector(X)
385
+    Xr = robjects.FloatVector(numpy.real(X))
386
+    Xi = robjects.FloatVector(numpy.imag(X))
387
+    Xa = robjects.FloatVector(numpy.abs(X))
388
+    Xri = robjects.FloatVector(numpy.concatenate((X.real,X.imag)))
389
+
390
+    robjects.r(''' 
391
+        source('kernel.r')
392
+    ''')   
393
+    #Kw = robjects.globalenv['Kwri']
394
+     
395
+    #print (numpy.shape(X))
396
+    
397
+    #######################################################################
398
+
399
+    if known:
400
+        # known Frequency
401
+        my_lower = robjects.r('list(a=.001, rT2=.001, phi2=-3.14)')
402
+        my_upper = robjects.r('list(a=3.5, rT2=.300, phi2=3.14)')
403
+        my_list = robjects.r('list(a=.2, rT2=0.03, phi2=0)')
404
+    else:
405
+        # Unknown Frequency
406
+        my_lower = robjects.r('list(a=.001, rT2=.001, phi2=-3.14, wL2=wL-5)')
407
+        my_upper = robjects.r('list(a=3.5, rT2=.300, phi2=3.14, wL2=wL+5)')
408
+        my_list = robjects.r('list(a=.2, rT2=0.03, phi2=0, wL2=wL)')
409
+    
410
+    my_cont = robjects.r('nls.control(maxiter=5000, warnOnly=TRUE, printEval=FALSE)')
411
+    
412
+    #fmla = robjects.Formula('Xri ~ c(a*Re((wL) / (wL^2+(s+1/rT2)^2 )), a*Im((wL)/(wL^2 + (s+1/rT2)^2 )))') # envelope
413
+    #fmla = robjects.Formula('Xi   ~   Im(a*(sin(phi2)*s + ((1/rT2)*sin(phi2)) + wL*cos(phi2)) / (wL^2+(s+1/rT2)^2 ))') # envelope
414
+    #fmla = robjects.Formula('Xri ~ c(Re(a*(sin(phi2)*s + ((1/rT2)*sin(phi2)) + wL*cos(phi2)) / (wL^2+(s+1/rT2)^2 )), Im(a*(sin(phi2)*s + ((1/rT2)*sin(phi2)) + wL*cos(phi2)) / (wL^2+(s+1/rT2)^2 )))') # envelope
415
+    
416
+    #fmlar = robjects.Formula('Xr ~ (Kwr(a, phi2, s, rT2, wL)) ') # envelope
417
+    #fmlai = robjects.Formula('Xi ~ (Kwi(a, phi2, s, rT2, wL)) ') # envelope
418
+    
419
+
420
+    
421
+    if known:
422
+        ###########################################3
423
+        # KNOWN freq 
424
+        fmla = robjects.Formula('Xri ~ c(Kwr(a, phi2, s, rT2, wL), Kwi(a, phi2, s, rT2, wL) ) ') # envelope
425
+    else:
426
+        ####################################################################################################3
427
+        # unknown frequency
428
+        fmla = robjects.Formula('Xri ~ c(Kwr(a, phi2, s, rT2, wL2), Kwi(a, phi2, s, rT2, wL2) ) ') # envelope
429
+
430
+    #fmla = robjects.Formula('Xri ~ (Kwri(a, phi2, s, rT2, wL)) ') # envelope
431
+    
432
+    #fmla = robjects.Formula('Xa ~ (abs(a*(sin(phi2)*s + ((1/rT2)*sin(phi2)) + wL*cos(phi2)) / (wL^2+(s+1/rT2)^2 )))') # envelope
433
+    #fmla = robjects.Formula('XX ~ a*(wL) / (wL^2 + (s+1/rT2)^2 )') # complex
434
+    #fmla = robjects.Formula('Xa ~ abs(a*(wL) / (wL^2 + (s+1/rT2)^2 )) + nb') # complex
435
+    
436
+    #fmla = robjects.Formula('Xri ~ c(a*Re((wL) / (wL^2+(s+1/rT2)^2 )), a*Im((wL)/(wL^2 + (s+1/rT2)^2 )))') # envelope
437
+    
438
+    #        self.Gw[iw, iT2] = ((np.sin(phi2) *  (alpha + 1j*self.w[iw]) + self.wL*np.cos(phi2)) / \
439
+    #                               (self.wL**2 + (alpha+1.j*self.w[iw])**2 ))
440
+    #        self.Gw[iw, iT2] = ds * self.sc*((np.sin(phi2)*( alpha + 1j*self.w[iw]) + self.wL*np.cos(phi2)) / \
441
+    #                               (self.wL**2 + (alpha+1.j*self.w[iw])**2 ))
442
+    
443
+    # Works Amplitude Only!
444
+    #fmla = robjects.Formula('Xa ~ abs(a*(wL) / (wL^2 + (s+1/rT2)^2 ))') # complex
445
+ 
446
+    env = fmla.getenvironment()
447
+    env['s'] = s
448
+    env['Xr'] = Xr
449
+    env['Xa'] = Xa
450
+    env['Xi'] = Xi
451
+    env['Xri'] = Xri
452
+    env['XX'] = XX
453
+     
454
+    #fit = robjects.r.tryCatch(robjects.r.nls(fmla,start=my_list, control=my_cont)) #, lower=my_lower, algorithm='port')) #, \
455
+    #fit = robjects.r.tryCatch(robjects.r.nls(fmlar, start=my_list, control=my_cont, lower=my_lower, upper=my_upper, algorithm='port')) #, \
456
+    fit = robjects.r.tryCatch(robjects.r.nls(fmla, start=my_list, control=my_cont, lower=my_lower, upper=my_upper, algorithm='port')) #, \
457
+    
458
+    #env = fmlai.getenvironment()
459
+    #fiti = robjects.r.tryCatch(robjects.r.nls(fmlai, start=my_list, control=my_cont, lower=my_lower, upper=my_upper, algorithm='port')) #, \
460
+    
461
+    #reportr =  r.summary(fitr)
462
+    #reporti =  r.summary(fiti)
463
+    report =  r.summary(fit)
464
+    #print( report )
465
+    #exit()
466
+    #print( reportr )
467
+    #print( reporti  )
468
+    #exit()
469
+    #print ( r.warnings())
470
+ 
471
+    #a   =  (r['$'](reportr,'par')[0] + r['$'](reporti,'par')[0]) / 2.
472
+    #rT2 =  (r['$'](reportr,'par')[1] + r['$'](reporti,'par')[1]) / 2.
473
+    #nb  =  (r['$'](reportr,'par')[2] + r['$'](reporti,'par')[2]) / 2.
474
+    a   =  r['$'](report,'par')[0] 
475
+    rT2 =  r['$'](report,'par')[1] 
476
+    nb  =  r['$'](report,'par')[2] #phi2 
477
+
478
+    #print ("Python wL2", r['$'](report,'par')[3] )   
479
+    #print ("Python zeta", r['$'](report,'par')[2] )   
480
+ 
481
+    return a, rT2, nb
482
+
483
+
484
+
485
+###################################################################
486
+###################################################################
487
+###################################################################
488
+if __name__ == "__main__":
489
+
490
+    dt    = .0001
491
+    T2    = .1
492
+    omega = 2000.*2*numpy.pi
493
+    phi   = .0
494
+    T     = 8.*T2
495
+    
496
+    t = numpy.arange(0, T, dt)
497
+
498
+    # Synthetic data, simple single decaying sinusoid 
499
+    # with a single decay parameter and gaussian noise added 
500
+    data = numpy.exp(-t/T2) * numpy.sin(omega * t + phi) + numpy.random.normal(0,.05,len(t)) \
501
+                         + numpy.random.randint(-1,2,len(t))*numpy.random.exponential(.2,len(t)) 
502
+    cdata = numpy.exp(-t/T2) * numpy.sin(omega * t + phi) #+ numpy.random.normal(0,.25,len(t))
503
+    #data = numpy.random.normal(0,.25,len(t))
504
+
505
+    sigma2 = numpy.std(data[::-len(data)/4])
506
+    #sigma2 = numpy.var(data[::-len(data)/4])
507
+    print("sigma2", sigma2)    
508
+    
509
+    [peaks,times,indices] = peakPicker(data, omega, dt)
510
+    
511
+    [b1,b2,rT2] = regressCurve(peaks,times)
512
+    print("rT2 nonweighted", rT2)
513
+    
514
+    [b1,b2,rT2] = regressCurve(peaks,times,sigma2)
515
+    print("rT2 weighted", rT2)
516
+
517
+    envelope   =  numpy.exp(-t/T2)
518
+    renvelope  =  numpy.exp(-t/rT2)
519
+
520
+    outf = file('regress.txt','w')
521
+    for i in range(len(times)):
522
+        outf.write(str(times[i]) + "   " +  str(peaks[i]) + "\n")  
523
+    outf.close()
524
+
525
+    pylab.plot(t,data, 'b')
526
+    pylab.plot(t,cdata, 'g', linewidth=1)
527
+    pylab.plot(t,envelope, color='violet', linewidth=4)
528
+    pylab.plot(t,renvelope, 'r', linewidth=4)
529
+    pylab.plot(times, numpy.array(peaks), 'bo', markersize=8, alpha=.25)
530
+    pylab.legend(['noisy data','clean data','real envelope','regressed env','picks'])
531
+    pylab.savefig("regression.pdf")
532
+
533
+
534
+    # FFT check
535
+    fourier = fft(data)
536
+    pylab.figure()
537
+    freq = fftfreq(len(data), d=dt)
538
+    pylab.plot(freq, (fourier.real))
539
+    
540
+    pylab.show()
541
+
542
+    # TODO do a bunch in batch mode to see if T2 estimate is better with or without 
543
+    # weighting and which model is best.
544
+
545
+    # TODO try with real data
546
+
547
+    # TODO test filters (median, FFT, notch)
548
+
549
+    # It looks like weighting is good for relatively low sigma, but for noisy data
550
+    # it hurts us. Check

+ 91
- 0
akvo/tressel/filtfilt.py View File

1
+from numpy import vstack, hstack, eye, ones, zeros, linalg, \
2
+newaxis, r_, flipud, convolve, matrix, array
3
+from scipy.signal import lfilter
4
+
5
+def lfilter_zi(b,a):
6
+    #compute the zi state from the filter parameters. see [Gust96].
7
+
8
+    #Based on:
9
+    # [Gust96] Fredrik Gustafsson, Determining the initial states in forward-backward 
10
+    # filtering, IEEE Transactions on Signal Processing, pp. 988--992, April 1996, 
11
+    # Volume 44, Issue 4
12
+
13
+    n=max(len(a),len(b))
14
+
15
+    zin = (  eye(n-1) - hstack( (-a[1:n,newaxis],
16
+                                 vstack((eye(n-2), zeros(n-2))))))
17
+
18
+    zid=  b[1:n] - a[1:n]*b[0]
19
+
20
+    zi_matrix=linalg.inv(zin)*(matrix(zid).transpose())
21
+    zi_return=[]
22
+
23
+    #convert the result into a regular array (not a matrix)
24
+    for i in range(len(zi_matrix)):
25
+      zi_return.append(float(zi_matrix[i][0]))
26
+
27
+    return array(zi_return)
28
+
29
+
30
+
31
+
32
+def filtfilt(b,a,x):
33
+    #For now only accepting 1d arrays
34
+    ntaps=max(len(a),len(b))
35
+    edge=ntaps*3
36
+
37
+    if x.ndim != 1:
38
+        raise ValueError, "Filiflit is only accepting 1 dimension arrays."
39
+
40
+    #x must be bigger than edge
41
+    if x.size < edge:
42
+        raise ValueError, "Input vector needs to be bigger than 3 * max(len(a),len(b)."
43
+
44
+    if len(a) < ntaps:
45
+        a=r_[a,zeros(len(b)-len(a))]
46
+
47
+    if len(b) < ntaps:
48
+        b=r_[b,zeros(len(a)-len(b))]
49
+
50
+    zi=lfilter_zi(b,a)
51
+
52
+    #Grow the signal to have edges for stabilizing 
53
+    #the filter with inverted replicas of the signal
54
+    s=r_[2*x[0]-x[edge:1:-1],x,2*x[-1]-x[-1:-edge:-1]]
55
+    #in the case of one go we only need one of the extrems 
56
+    # both are needed for filtfilt
57
+
58
+    (y,zf)=lfilter(b,a,s,-1,zi*s[0])
59
+
60
+    (y,zf)=lfilter(b,a,flipud(y),-1,zi*y[-1])
61
+
62
+    return flipud(y[edge-1:-edge+1])
63
+
64
+
65
+if __name__=='__main__':
66
+
67
+    from scipy.signal import butter
68
+    from scipy import sin, arange, pi, randn
69
+
70
+    from pylab import plot, legend, show, hold
71
+
72
+    t=arange(-1,1,.01)
73
+    x=sin(2*pi*t*.5+2)
74
+    #xn=x + sin(2*pi*t*10)*.1
75
+    xn=x+randn(len(t))*0.05
76
+
77
+    [b,a]=butter(3,0.05)
78
+
79
+    z=lfilter(b,a,xn)
80
+    y=filtfilt(b,a,xn)
81
+
82
+    plot(x,'c')
83
+    hold(True)
84
+    plot(xn,'k')
85
+    plot(z,'r')
86
+    plot(y,'g')
87
+
88
+    legend(('original','noisy signal','lfilter - butter 3 order','filtfilt - butter 3 order'))
89
+    hold(False)
90
+    show()
91
+

+ 2116
- 0
akvo/tressel/mrsurvey.py
File diff suppressed because it is too large
View File


+ 68
- 0
akvo/tressel/pca.py View File

1
+##########################################################
2
+#
3
+#
4
+#
5
+#
6
+#
7
+#from scipy import mean
8
+import numpy
9
+
10
+def pca(A, remove=[]):
11
+    ''' The input matrix A should be a 2D numpy array in column-major 
12
+        order. Each column is a dataset and PCA will be applied across
13
+        columns
14
+    '''
15
+    #nrow = len(A[:,0])
16
+    #ncol = len(A[0,:])
17
+    nrow,ncol = numpy.shape(A)
18
+
19
+    # Cast into matrix type for easier math
20
+    A = numpy.matrix(A)
21
+
22
+    # Allocate Covariance Matrix
23
+    covMatrix = numpy.matrix(numpy.zeros((nrow, nrow)))
24
+    
25
+    # Compute Means of each row. Each column must be normalised
26
+    meanArray = []
27
+    for i in range(nrow):
28
+        meanArray.append(numpy.mean(A[i].tolist()[0]) ) 
29
+        A[i] -= meanArray[i]
30
+    meanArray = numpy.array(meanArray) 
31
+    
32
+    # Generate Covariance Matrix
33
+    covMatrix = numpy.cov(A)
34
+
35
+    # Compute Eigen Values, Eigen Vectors     
36
+    eigs = numpy.linalg.eig(covMatrix)
37
+    K = eigs[1].T
38
+    
39
+    #print K
40
+    #print "Eigen Values"
41
+    #print eigs[0]
42
+    
43
+    # Zero requested components
44
+    for i in remove:
45
+        K[i] = numpy.zeros(len(K))        
46
+
47
+    # Make Transform Matrices
48
+    transMatrix = K*A
49
+    
50
+    # Return Necssary Stuff
51
+    return numpy.array(transMatrix), K, meanArray
52
+    #return K, A, meanArray 
53
+
54
+#def invpca(K, A, means):
55
+def invpca(transMatrix, K, means):
56
+    '''Converts a PCA rotated dataset back to normal. Input parameters
57
+    are the components to discard in re-creation.
58
+    '''
59
+    K = numpy.matrix(K)
60
+    # Transform and Untransform the data
61
+    #transMatrix = K*A
62
+    untransMatrix = K.T*transMatrix
63
+    
64
+    # Correct for normalisation
65
+    for i in range(len(transMatrix)):
66
+        untransMatrix[i] += means[i]
67
+
68
+    return untransMatrix    

+ 263
- 0
akvo/tressel/rotate.py View File

1
+# #################################################################################
2
+# # GJI final pub specs                                                           #
3
+# import matplotlib                                                               #
4
+# from matplotlib import rc                                                       #
5
+# matplotlib.rcParams['text.latex.preamble']=[r"\usepackage{timet,amsmath}"]      #
6
+# rc('font',**{'family':'serif','serif':['timet']})                               #
7
+# rc('font',**{'size':8})                                                         #
8
+# rc('text', usetex=True)                                                         #
9
+# # converts pc that GJI is defined in to inches                                  # 
10
+# # In GJI \textwidth = 42pc                                                      #
11
+# #        \columnwidth = 20pc                                                    #
12
+# def pc2in(pc):                                                                  #
13
+#     return pc*12/72.27                                                          #
14
+# #################################################################################
15
+
16
+#from GJIPlot import *
17
+
18
+import numpy as np
19
+import matplotlib.pyplot as plt
20
+#from invertColours import *
21
+from akvo.tressel.decay import *
22
+from scipy import signal
23
+
24
+def quadrature(T, vL, wL, dt, xn, DT, t):
25
+        # decimate
26
+    # blind decimation
27
+    # 1 instead of T 
28
+    irsamp = (T) * int(  (1./vL) / dt) # real 
29
+    iisamp =       int(  ((1./vL)/ dt) * ( .5*np.pi / (2.*np.pi) ) ) # imaginary
30
+   
31
+
32
+    dsamp =  int( DT / dt) # real 
33
+
34
+    iisamp += dsamp
35
+
36
+    ############################################################
37
+    # simple quadrature-detection via sampling
38
+    xr = xn[dsamp::irsamp]
39
+    xi = xn[iisamp::irsamp]
40
+    phase = np.angle( xr + 1j*xi )
41
+    abse = np.abs( xr + 1j*xi )
42
+
43
+    # times
44
+    #ta = np.arange(0, TT, dt)
45
+    #te = np.arange(DT, TT, TT/len(abse))
46
+
47
+    #############################################################
48
+    # hilbert transform
49
+    ht = signal.hilbert(xn) #, 100))
50
+    he = np.abs(ht)         #, 100))
51
+    hp = ((np.angle(ht[dsamp::irsamp]))) 
52
+
53
+    #############################################################
54
+    # Resample ht
55
+    #htd = signal.decimate(he, 100, ftype='fir') 
56
+    #td = signal.decimate(t, 100, ftype='fir')
57
+    #[htd, td] = signal.resample(he, 21, t) 
58
+    #toss first, and use every third 
59
+    #htd = htd[1::3]
60
+    #td = td[1::3]
61
+
62
+    #############################################################
63
+    # Pre-envelope
64
+    #gplus = xn + 1j*ht  
65
+
66
+    #############################################################
67
+    # Complex envelope
68
+    #gc = gplus / np.exp(1j*wL*t)    
69
+
70
+    #############################################################
71
+    ## Design a low-pass filter
72
+    FS = 1./dt                                           # sampling rate
73
+    FC = 10.05/(0.5*FS)                                 # cutoff frequency at 0.05 Hz
74
+    N = 11                                               # number of filter taps
75
+    a = [1]                                              # filter denominator
76
+    b = signal.firwin(N, cutoff=FC, window='hamming')    # filter numerator
77
+
78
+    #############################################################
79
+    ## In-phase 
80
+    #2*np.cos(wL*t)  
81
+    dw = -2.*np.pi*2
82
+    Q = signal.filtfilt(b, a, xn*2*np.cos((wL+dw)*t))  # X
83
+    I = signal.filtfilt(b, a, xn*2*np.sin((wL+dw)*t))  # Y
84
+
85
+    ###############################################
86
+    # Plots
87
+    #plt.plot(ht.real)
88
+    #plt.plot(ht.imag)
89
+    #plt.plot(np.abs(ht))
90
+    #plt.plot(gc.real)
91
+    #plt.plot(gc.imag)
92
+
93
+    #plt.plot(xn)
94
+    #plt.plot(xn)
95
+    #plt.plot(ta, xn)
96
+    #plt.plot(te, abse, '-.', linewidth=2, markersize=10)
97
+    #plt.plot(ta, he, '.', markersize=10 )
98
+    #plt.plot(td, htd, color='green', linewidth=2)
99
+    # Phase Plots
100
+    #ax2 = plt.twinx()
101
+    #ax2.plot(te, hp, '.', markersize=10, color='green' )
102
+    #ax2.plot(te, phase, '-.', linewidth=2, markersize=10, color='green')
103
+
104
+
105
+    return Q[N:-N], I[N:-N], t[N:-N]
106
+
107
+#     #####################################################################
108
+#     # regress raw signal
109
+#     
110
+#     #[peaks, times, ind] = peakPicker(xn, wL, dt)
111
+#     #[a0,b0,rt20] =  regressCurve(peaks,  times) #,sigma2=1,intercept=True):
112
+#     
113
+#     dsamp = int( DT / dt) # real 
114
+#     # regress analytic signal
115
+#     [a0,b0,rt20] =  regressCurve(he[dsamp::],  t[dsamp::], intercept=True) #,sigma2=1,intercept=True):
116
+#     #[b0,rt20] =  regressCurve(he[dsamp::],  t[dsamp::], intercept=False) #,sigma2=1,intercept=True):
117
+#     #[a0,b0,rt20] =  regressCurve(he,  t) #,sigma2=1,intercept=True):
118
+#    
119
+#     # regress downsampled 
120
+#     [a,b,rt2] =  regressCurve(abse,  t[dsamp::irsamp], intercept=True) #,sigma2=1,intercept=True):
121
+#     #[b,rt2] =  regressCurve(htd,  td, intercept=False) #,sigma2=1,intercept=True):
122
+#     
123
+#     return irsamp, iisamp, htd, b0, rt20, ta, b, rt2, phase, td, he, dsamp
124
+#     #return irsamp, iisamp, abse, a0, b0, rt20, times, a, b, rt2, phase
125
+
126
+def RotateAmplitude(X, Y, zeta, df, t):
127
+    V = X + 1j*Y
128
+    return np.abs(V) * np.exp( 1j * ( np.angle(V) - zeta - 2.*np.pi*df*t ) )
129
+    #return np.abs(V) * np.exp( 1j * ( np.angle(V) - zeta - df*t ) )
130
+
131
+#def Gate(x, t):
132
+#    pass
133
+
134
+def gateIntegrate(T2D, T2T, gpd, sigma, stackEfficiency=2.):
135
+    """ Gate integrate the signal to gpd, gates per decade
136
+    """
137
+    
138
+    # use artificial time gates so that early times are fully captured
139
+    T2T0 = T2T[0]
140
+    T2TD = T2T[0] - (T2T[1]-T2T[0])
141
+    T2T -= T2TD
142
+    
143
+    # calculate total number of decades
144
+    nd = np.log10(T2T[-1]/T2T[0]) #np.log10(self.T2T[-1]) -  np.log10(self.T2T[-1])
145
+    tdd = np.logspace( np.log10(T2T[0]), np.log10(T2T[-1]), (int)(gpd*nd)+1, base=10, endpoint=True) 
146
+    tdl = tdd[0:-1]     # these are left edges
147
+    tdr = tdd[1::]      # these are left edges
148
+    td = (tdl+tdr) / 2. # window centres
149
+
150
+    Vars = np.ones( len(td) ) * sigma**2 #* .15**2
151
+    htd = np.zeros( len(td), dtype=complex )
152
+    isum = np.zeros( len(td) )
153
+    ii = 0
154
+
155
+    SIGSTACK = {}
156
+    SIGSTACK[ii]= []
157
+    for itd in range(len(T2T)):
158
+        if ( T2T[itd] > tdr[ii] ):
159
+            if (ii < len(td)-1):
160
+                ii += 1
161
+                SIGSTACK[ii] = []
162
+            else:
163
+                #print "overshoot??", ii
164
+                break
165
+        isum[ii] += 1
166
+        htd[ii] += T2D[ itd ]
167
+        SIGSTACK[ii].append(T2D[itd])
168
+        Vars[ii] += sigma**2
169
+
170
+    sigma = np.sqrt( Vars  * (1/isum)**stackEfficiency ) 
171
+    for ii in range(len(td)):
172
+        if len(SIGSTACK[ii]) > 30:
173
+            sigma[ii] = np.var(SIGSTACK[ii]) / ((len(SIGSTACK[ii])-1)**(1/stackEfficiency))
174
+            #sigma[ii] = np.std(SIGSTACK[ii]) * ( 1./(len(SIGSTACK[ii]))**stackEfficiency)
175
+
176
+    # RESET times where isum == 1
177
+    ii = 0
178
+    while (isum[ii] == 1):
179
+        td[ii] = T2T[ii]
180
+        ii += 1
181
+
182
+    htd /= isum
183
+    T2T += T2TD  
184
+    return td+T2TD, htd, tdd+T2TD, sigma, isum  # centre abscissa, data, window edges, error  
185
+
186
+if __name__ == "__main__":
187
+
188
+    dt = 1e-4
189
+    TT = 1.5
190
+    t = np.arange(0, TT, dt)
191
+    vL = 2057.
192
+    wL =  2.*np.pi*vL
193
+    wL2 = 2.*np.pi*(vL-2.5) #-2) #-2.2) # 3 Hz off 
194
+    zeta = -np.pi/6. #4.234
195
+    t2 = .150
196
+
197
+    xs = np.exp(-t/t2) * np.cos(wL2*t + zeta) 
198
+    xe = np.exp(-t/t2)    
199
+    xn = xs + np.random.normal(0,.1,len(xs))# + (np.sign(xs) 
200
+            #    np.random.random_integers(-1,1,len(xs))*0.6*np.random.lognormal(0, .35, len(xs)) + \
201
+            #    np.random.random_integers(-1,1,len(xs))*.004*np.random.weibull(.25, len(xs)), 60)))
202
+
203
+    # quadrature detection downsampling
204
+    T = 50    # sampling period, grab every T'th oscilation
205
+    DT = .002 #85  # dead time ms
206
+    #[irsamp, iisamp, abse, b0, rt20, times, b, rt2, phase, tdec, he, dsamp] = quadDetect(T, vL, wL, dt, xn, DT)
207
+    
208
+    [Q, I, tt] = quadrature(T, vL, wL, dt, xn, DT, t)
209
+    [E0,df,phi,T2] = quadratureDetect(Q, I, tt)
210
+    print("df", df)
211
+    D = RotateAmplitude(I, Q, phi, df, tt)
212
+
213
+    fig = plt.figure(figsize=[pc2in(20), pc2in(14)]) #
214
+    ax1 = fig.add_axes([.125,.2,.8,.7])
215
+    #ax1.plot(tt*1e3, np.exp(-tt/t2), linewidth=2, color='black', label="actual")   
216
+    ax1.plot(tt*1e3, D.imag, label="CA", color='red')    
217
+    ax1.plot(t*1e3, xn, color='blue', alpha=.25)
218
+    ax1.plot(tt*1e3, I, label="inphase", color='blue')
219
+    ax1.plot(tt*1e3, Q, label="quadrature", color='green')
220
+    
221
+    #ax1.plot(tt*1e3, np.angle( Q + 1j*I), label="angle", color='purple')
222
+
223
+
224
+    GT, GD = gateIntegrate( D.imag, tt, 10  )
225
+    GT, GDR = gateIntegrate( D.real, tt, 10  )
226
+    GT, GQ = gateIntegrate( Q, tt, 10  )
227
+    GT, GI = gateIntegrate( I, tt, 10  )
228
+    #ax1.plot(tt*1e3, np.arctan( Q/I), label="angle", color='purple')
229
+    #ax1.plot(GT*1e3, np.real(GD), 'o', label="GATE", color='purple')
230
+    #ax1.plot(GT*1e3, np.real(GDR), 'o', label="GATE Real", color='red')
231
+    #ax1.plot(GT*1e3, np.arctan( np.real(GQ)/np.real(GI)), 'o',label="GATE ANGLE", color='magenta')
232
+    
233
+
234
+    ax1.set_xlabel(r"time [ms]") 
235
+    ax1.set_ylim( [-1.25,1.65] )
236
+    
237
+    #light_grey = np.array([float(248)/float(255)]*3)
238
+    legend = plt.legend( frameon=True, scatterpoints=1, numpoints=1, labelspacing=0.2  )
239
+    #rect = legend.get_frame()
240
+    fixLeg(legend)
241
+    #rect.set_color('None')
242
+    #rect.set_facecolor(light_grey)
243
+    #rect.set_linewidth(0.0)
244
+    #rect.set_alpha(0.5)
245
+
246
+    # Remove top and right axes lines ("spines")
247
+    spines_to_remove = ['top', 'right']
248
+    for spine in spines_to_remove:
249
+        ax1.spines[spine].set_visible(False)
250
+    #ax1.xaxis.set_ticks_position('none')
251
+    #ax1.yaxis.set_ticks_position('none')
252
+    ax1.get_xaxis().tick_bottom()
253
+    ax1.get_yaxis().tick_left()
254
+
255
+    plt.savefig('rotatetime.pdf',dpi=600)
256
+    plt.savefig('rotatetime.eps',dpi=600)
257
+
258
+    # phase part
259
+    plt.figure()
260
+    plt.plot( tt*1e3, D.real, label="CA", color='red' )
261
+
262
+    plt.show()
263
+    exit()

+ 102
- 0
akvo/tressel/smooth.py View File

1
+import numpy
2
+
3
+def smooth(x,window_len=11,window='hanning'):
4
+    """smooth the data using a window with requested size.
5
+    
6
+    This method is based on the convolution of a scaled window with the signal.
7
+    The signal is prepared by introducing reflected copies of the signal 
8
+    (with the window size) in both ends so that transient parts are minimized
9
+    in the begining and end part of the output signal.
10
+    
11
+    input:
12
+        x: the input signal 
13
+        window_len: the dimension of the smoothing window; should be an odd integer
14
+        window: the type of window from 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'
15
+            flat window will produce a moving average smoothing.
16
+
17
+    output:
18
+        the smoothed signal
19
+        
20
+    example:
21
+
22
+    t=linspace(-2,2,0.1)
23
+    x=sin(t)+randn(len(t))*0.1
24
+    y=smooth(x)
25
+    
26
+    see also: 
27
+    
28
+    numpy.hanning, numpy.hamming, numpy.bartlett, numpy.blackman, numpy.convolve
29
+    scipy.signal.lfilter
30
+ 
31
+    TODO: the window parameter could be the window itself if an array instead of a string   
32
+    """
33
+
34
+    if x.ndim != 1:
35
+        raise ValueError("smooth only accepts 1 dimension arrays.")
36
+
37
+    if x.size < window_len:
38
+        raise ValueError("Input vector needs to be bigger than window size.")
39
+
40
+
41
+    if window_len<3:
42
+        return x
43
+
44
+
45
+    if not window in ['flat', 'hanning', 'hamming', 'bartlett', 'blackman']:
46
+        raise ValueError("Window is on of 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'")
47
+
48
+
49
+    s=numpy.r_[2*x[0]-x[window_len:1:-1],x,2*x[-1]-x[-1:-window_len:-1]]
50
+    #print(len(s))
51
+    if window == 'flat': #moving average
52
+        w=ones(window_len,'d')
53
+    else:
54
+        w=eval('numpy.'+window+'(window_len)')
55
+
56
+    y=numpy.convolve(w/w.sum(),s,mode='same')
57
+    return y[window_len-1:-window_len+1]
58
+
59
+
60
+
61
+
62
+from numpy import *
63
+from pylab import *
64
+
65
+def smooth_demo():
66
+
67
+    t=linspace(-4,4,100)
68
+    x=sin(t)
69
+    xn=x+randn(len(t))*0.1
70
+    y=smooth(x)
71
+
72
+    ws=31
73
+
74
+    subplot(211)
75
+    plot(ones(ws))
76
+
77
+    windows=['flat', 'hanning', 'hamming', 'bartlett', 'blackman']
78
+
79
+    hold(True)
80
+    for w in windows[1:]:
81
+        eval('plot('+w+'(ws) )')
82
+
83
+    axis([0,30,0,1.1])
84
+
85
+    legend(windows)
86
+    title("The smoothing windows")
87
+    subplot(212)
88
+    plot(x)
89
+    plot(xn)
90
+    for w in windows:
91
+        plot(smooth(xn,10,w))
92
+    l=['original signal', 'signal with noise']
93
+    l.extend(windows)
94
+
95
+    legend(l)
96
+    title("Smoothing a noisy signal")
97
+    show()
98
+
99
+
100
+if __name__=='__main__':
101
+    smooth_demo()
102
+

+ 80
- 0
akvo/xml/usgsXML.py View File

1
+# XML metadata writer suitable for USGS Sciencebase Data Release
2
+# M. Andy Kass
3
+# 2017-02-17
4
+
5
+
6
+class Akvo(sNMRdata):
7
+
8
+    def __init__(self):
9
+        return
10
+
11
+    def readProcessed(self,fname):
12
+        # Load in the saved pickle saved from Akvo
13
+
14
+        return 42
15
+
16
+    def readInverted(self,fname):
17
+        return 42
18
+
19
+    def readGenericInfo(self,gfname='basicinfo,yaml',sfname='sNMRinfo.yaml'):
20
+        super().readGenericInfo(gfname)
21
+        super().readsNMRinfo(sfname)
22
+
23
+    def importProcessed(self,fname):
24
+        # Load in the exported YAML data from Akvo
25
+
26
+        return 42
27
+
28
+class VCsurfProcessed(sNMRdata):
29
+
30
+    def __init__(self):
31
+        return
32
+
33
+class VCDartdata(bNMRdata):
34
+
35
+    def __init__(self):
36
+        print('VCDartdata')
37
+        return
38
+
39
+
40
+class VCJavelindata(bNMRdata):
41
+
42
+    def __init__(self):
43
+        return
44
+
45
+
46
+
47
+
48
+# ----------Should never call these directly-------------------
49
+
50
+class data():
51
+    
52
+    def __init__(self):
53
+        return
54
+
55
+    def readGenericInfo(self,fname):
56
+        # Read in the generic information common to all surveys.
57
+
58
+        return 42
59
+
60
+class NMRdata(data):
61
+
62
+    def __init__(self):
63
+        return
64
+
65
+class bNMRdata(NMRdata):
66
+
67
+    def __init__(self):
68
+        return
69
+
70
+class sNMRdata(NMRdata):
71
+
72
+    def __init__(self):
73
+        return
74
+
75
+    def readsNMRinfo(self,fname):
76
+        # Read in generic info common to all sNMR surveys
77
+
78
+        return 42
79
+
80
+

+ 4
- 0
akvo/xml/utClasses.py View File

1
+from usgsXML import AkvoProcessed
2
+
3
+mydata = AkvoProcessed()
4
+mydata.loadProcessed('test.txt')

+ 4
- 0
akvo/xml/utLoadAkvoProc.py View File

1
+from usgsXML import AkvoProcessed
2
+
3
+mydata = AkvoProcessed()
4
+mydata.loadProcessed('test.p')

+ 166
- 0
akvologo.svg View File

1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
3
+
4
+<svg
5
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
6
+   xmlns:cc="http://creativecommons.org/ns#"
7
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8
+   xmlns:svg="http://www.w3.org/2000/svg"
9
+   xmlns="http://www.w3.org/2000/svg"
10
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
11
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
12
+   width="210mm"
13
+   height="297mm"
14
+   viewBox="0 0 744.09448819 1052.3622047"
15
+   id="svg2"
16
+   version="1.1"
17
+   inkscape:version="0.91 r13725"
18
+   sodipodi:docname="akvologo.svg"
19
+   inkscape:export-filename="/home/tirons/src/akvo/akvo/gui/akvo.png"
20
+   inkscape:export-xdpi="90"
21
+   inkscape:export-ydpi="90">
22
+  <defs
23
+     id="defs4" />
24
+  <sodipodi:namedview
25
+     id="base"
26
+     pagecolor="#ffffff"
27
+     bordercolor="#666666"
28
+     borderopacity="1.0"
29
+     inkscape:pageopacity="0.0"
30
+     inkscape:pageshadow="2"
31
+     inkscape:zoom="2.32"
32
+     inkscape:cx="276.59198"
33
+     inkscape:cy="822.71621"
34
+     inkscape:document-units="px"
35
+     inkscape:current-layer="layer1"
36
+     showgrid="false"
37
+     inkscape:window-width="1626"
38
+     inkscape:window-height="834"
39
+     inkscape:window-x="251"
40
+     inkscape:window-y="156"
41
+     inkscape:window-maximized="0" />
42
+  <metadata
43
+     id="metadata7">
44
+    <rdf:RDF>
45
+      <cc:Work
46
+         rdf:about="">
47
+        <dc:format>image/svg+xml</dc:format>
48
+        <dc:type
49
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
50
+        <dc:title></dc:title>
51
+      </cc:Work>
52
+    </rdf:RDF>
53
+  </metadata>
54
+  <g
55
+     inkscape:label="Layer 1"
56
+     inkscape:groupmode="layer"
57
+     id="layer1"
58
+     style="opacity:1">
59
+    <path
60
+       style="fill:none;fill-rule:evenodd;stroke:#780000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4.1;stroke-dasharray:none"
61
+       d="m 108.51064,231.89412 c 0,0 27.65957,-218.085107 84.04255,0"
62
+       id="path4144"
63
+       inkscape:connector-curvature="0" />
64
+    <path
65
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
66
+       d="m 186.69616,140.69112 c 0,0 -27.65957,218.08512 -84.04255,0"
67
+       id="path4144-3"
68
+       inkscape:connector-curvature="0" />
69
+    <path
70
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
71
+       d="m 206.77958,229.8786 c 0,0 27.65957,-218.085111 84.04255,0"
72
+       id="path4144-6"
73
+       inkscape:connector-curvature="0" />
74
+    <a
75
+       id="a4195"
76
+       style="">
77
+      <path
78
+         inkscape:connector-curvature="0"
79
+         id="path4144-3-7"
80
+         d="m 284.9651,138.67559 c 0,0 -27.65957,218.08513 -84.04255,0"
81
+         style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
82
+      <path
83
+         style="fill:none;fill-rule:evenodd;stroke:#600000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
84
+         d="m 247.88645,235.67934 c 0,0 -20.54347,9.09636 -46.9639,-97.00375"
85
+         id="path4235"
86
+         inkscape:connector-curvature="0"
87
+         sodipodi:nodetypes="cc" />
88
+    </a>
89
+    <path
90
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
91
+       d="m 300.86469,231.02753 c 0,0 27.65957,-218.085107 84.04255,0"
92
+       id="path4144-5"
93
+       inkscape:connector-curvature="0" />
94
+    <path
95
+       style="fill:none;fill-rule:evenodd;stroke:#6b0000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
96
+       d="m 379.05021,139.82453 c 0,0 -27.65957,218.08512 -84.04255,0"
97
+       id="path4144-3-3"
98
+       inkscape:connector-curvature="0" />
99
+    <path
100
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
101
+       d="m 392.69447,234.04881 c 0,0 27.65957,-218.08511 84.04255,0"
102
+       id="path4144-56"
103
+       inkscape:connector-curvature="0" />
104
+    <path
105
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
106
+       d="m 470.87999,136.84581 c 0,0 -27.65957,218.08512 -84.04255,0"
107
+       id="path4144-3-2"
108
+       inkscape:connector-curvature="0" />
109
+    <path
110
+       inkscape:connector-curvature="0"
111
+       id="path4237"
112
+       d="m 206.77958,229.8786 c 0,0 12.30376,-94.86414 37.6006,-97.75281"
113
+       style="fill:none;fill-rule:evenodd;stroke:#670000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
114
+       sodipodi:nodetypes="cc" />
115
+    <path
116
+       inkscape:connector-curvature="0"
117
+       id="path4260"
118
+       d="m 401.518,186.33639 c 0,0 22.7576,-107.300794 59.85954,-2.61438"
119
+       style="fill:none;fill-rule:evenodd;stroke:#5f0000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
120
+       sodipodi:nodetypes="cc" />
121
+    <path
122
+       inkscape:connector-curvature="0"
123
+       id="path4262"
124
+       d="m 460.74927,183.90463 c 0,0 -20.79682,111.22238 -59.53275,1.96079"
125
+       style="fill:none;fill-rule:evenodd;stroke:#660000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
126
+       sodipodi:nodetypes="cc" />
127
+    <text
128
+       xml:space="preserve"
129
+       style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
130
+       x="118.28571"
131
+       y="266.07648"
132
+       id="text4264"
133
+       sodipodi:linespacing="125%"><tspan
134
+         sodipodi:role="line"
135
+         id="tspan4266"
136
+         x="118.28571"
137
+         y="266.07648"></tspan></text>
138
+    <text
139
+       xml:space="preserve"
140
+       style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
141
+       x="100"
142
+       y="294.17255"
143
+       id="text4268"
144
+       sodipodi:linespacing="125%"><tspan
145
+         sodipodi:role="line"
146
+         id="tspan4270"
147
+         x="100"
148
+         y="294.17255" /></text>
149
+    <text
150
+       xml:space="preserve"
151
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:125%;font-family:'Asana Math';-inkscape-font-specification:'Asana Math, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
152
+       x="137.8793"
153
+       y="274.6553"
154
+       id="text4272"
155
+       sodipodi:linespacing="125%"><tspan
156
+         sodipodi:role="line"
157
+         id="tspan4274"
158
+         x="137.8793"
159
+         y="274.6553">Surface NMR Workbench</tspan></text>
160
+    <path
161
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
162
+       d="m 138.63793,248.05186 c 306.89655,2.58621 306.89655,2.58621 306.89655,2.58621"
163
+       id="path4276"
164
+       inkscape:connector-curvature="0" />
165
+  </g>
166
+</svg>

+ 4
- 0
bir.sh View File

1
+#!/bin/bash
2
+python3 setup.py build
3
+sudo python3 setup.py install
4
+akvo

+ 12
- 0
pyuic.json View File

1
+{
2
+    "files": [
3
+        [
4
+            "akvo/gui/main.ui",
5
+            "akvo/gui"
6
+        ]
7
+    ],
8
+    "pyrcc": "pyrcc5",
9
+    "pyrcc_options": "",
10
+    "pyuic": "pyuic5",
11
+    "pyuic_options": "--from-imports"
12
+}

+ 80
- 0
setup.py View File

1
+#!/usr/bin/env python
2
+import sys
3
+
4
+# optionally use qt4
5
+# if sys.argv[1] == "build_ui":
6
+#     try:
7
+#         from pyqt_distutils.build_ui import build_ui
8
+#         cmdclass = {'build_ui': build_ui}
9
+#     except ImportError:
10
+#         build_ui = None  # user won't have pyqt_distutils when deploying
11
+#         cmdclass = {}
12
+# else:
13
+#     build_ui = None  # user won't have pyqt_distutils when deploying
14
+#     cmdclass = {}
15
+
16
+# Require PyQt5 and compiltion of GUI files via pyuic 
17
+from setuptools import setup, Extension
18
+from setuptools.command.build_py import build_py
19
+from pyqt_distutils.build_ui import build_ui
20
+
21
+class custom_build_py(build_py):
22
+    def run(self):
23
+        self.run_command('build_ui')
24
+        build_py.run(self)
25
+
26
+try:
27
+    from Cython.Build import cythonize as cythonise
28
+except ImportError:
29
+    def cythonise(*args, **kwargs):
30
+        #from Cython.Build import cythonize
31
+        #return cythonize(*args, **kwargs)
32
+        return 
33
+
34
+#from distutils.core import setup
35
+
36
+setup(name='Akvo',
37
+      version='1.0.4',
38
+      description='Surface nuclear magnetic resonance workbench',
39
+      author='Trevor P. Irons',
40
+      author_email='Trevor.Irons@lemmasoftware.org',
41
+      url='https://svn.lemmasofware.org/akvo',
42
+      #setup_requires=['PyQt5'],
43
+      setup_requires=[
44
+        # Setuptools 18.0 properly handles Cython extensions.
45
+        'PyQt5','setuptools>=18.0',
46
+      ],
47
+#      ext_modules = cythonise("akvo/tressel/*.pyx"), 
48
+#      build_requires=['cython'],
49
+      install_requires=[
50
+#          'cython',
51
+          'rpy2',
52
+          'matplotlib',
53
+          'scipy',
54
+          'numpy',
55
+          'PyQt5',
56
+          'pyyaml',
57
+          'pyqt-distutils',
58
+          'cmocean'
59
+      ],
60
+      packages=['akvo', 'akvo.tressel', 'akvo.gui'],
61
+      license=['GPL 4.0'],
62
+      entry_points = {
63
+              'console_scripts': [
64
+                  'akvo = akvo.gui.akvoGUI:main',                  
65
+              ],              
66
+          },
67
+      # for forced build of pyuic
68
+      cmdclass={
69
+          'build_ui': build_ui,
70
+          'build_py': custom_build_py,
71
+      },
72
+      #cmdclass=cmdclass,
73
+      # Mechanism to include auxiliary files
74
+      include_package_data=True,
75
+      package_data={
76
+        'akvo.gui': ['*.png']  #All .r files 
77
+      },
78
+    )
79
+
80
+

Loading…
Cancel
Save