diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3f4c241
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+build/
+dist/
+schainpy.egg-info/
diff --git a/.project b/.project
new file mode 100644
index 0000000..9c51264
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+
+
+ schain_ebocanegra
+
+
+
+
+
+ org.python.pydev.PyDevBuilder
+
+
+
+
+
+ org.python.pydev.pythonNature
+
+
diff --git a/.pydevproject b/.pydevproject
new file mode 100644
index 0000000..037bd25
--- /dev/null
+++ b/.pydevproject
@@ -0,0 +1,8 @@
+
+
+
+/${PROJECT_DIR_NAME}
+
+python 2.7
+Default
+
diff --git a/.svn/all-wcprops b/.svn/all-wcprops
new file mode 100644
index 0000000..972abe7
--- /dev/null
+++ b/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra
+END
+setup.py
+K 25
+svn:wc:ra_dav:version-url
+V 70
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/setup.py
+END
+README
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/README
+END
diff --git a/.svn/entries b/.svn/entries
new file mode 100644
index 0000000..c03a9f0
--- /dev/null
+++ b/.svn/entries
@@ -0,0 +1,111 @@
+10
+
+dir
+1608
+http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra
+http://jro-dev.igp.gob.pe/svn/jro_soft/schain
+
+
+
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ea082a80-fb9f-4feb-b8d7-17586309b78c
+
+README
+file
+
+
+
+
+2017-04-17T17:05:32.000000Z
+3d318c6aa62816ad1d23198cfda6a2f9
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+781
+
+build
+dir
+
+dist
+dir
+
+schainc
+dir
+
+schainpy
+dir
+
+schainpy.egg-info
+dir
+
+setup.py
+file
+
+
+
+
+2017-04-17T17:05:35.000000Z
+6274494a6dcad776739e84cb0a33570f
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1415
+
diff --git a/.svn/text-base/README.svn-base b/.svn/text-base/README.svn-base
new file mode 100644
index 0000000..7b2047d
--- /dev/null
+++ b/.svn/text-base/README.svn-base
@@ -0,0 +1,36 @@
+Prerequisites:
+
+Core:
+ -numpy 1.8.0
+ -scipy
+ -math
+ -matplotlib
+ -h5py
+ -ftplib
+ -paramiko (optional for SendTFilesToServer)
+ -stuffr (optional for jroIO_hf)
+ -pyfits (Fits data)
+
+GUI:
+ -PyQt4
+ -wxPython
+
+Signal Chain Installation:
+
+ 1. Install numpy, matplotlib, TKAgg
+ 2. Install digital_rf_hdf5 module (developed by Haystack Observatory)
+ if you want to use USRP data
+ 3. untar schainpy-x.x.x.tar.gz
+ 4. cd schainpy-x.x.x
+ 5. execute:
+ [hostname]$ sudo pyhon setup.py install
+ 6. testing gui:
+ [hostname]$ schainGUI (enter)
+
+If you want to use serialization and zerorpc you will need to install the next packages:
+
+ 1. zerorpc
+ [hostname]$ sudo port install zerorpc
+
+ 2. cPickle, msgpack and msgpack_numpy
+ [hostname]$ sudo port install cPickle msgpack mspack_numpy
\ No newline at end of file
diff --git a/.svn/text-base/setup.py.svn-base b/.svn/text-base/setup.py.svn-base
new file mode 100644
index 0000000..46a06dd
--- /dev/null
+++ b/.svn/text-base/setup.py.svn-base
@@ -0,0 +1,40 @@
+'''
+Created on Jul 16, 2014
+
+@author: @author: Miguel Urco
+'''
+
+from schainpy import __version__
+from setuptools import setup, Extension
+
+setup(name="schainpy",
+ version=__version__,
+ description="Python tools to read, write and process Jicamarca data",
+ author="Miguel Urco",
+ author_email="miguel.urco@jro.igp.gob.pe",
+ url="http://jro.igp.gob.pe",
+ packages = {'schainpy',
+ 'schainpy.model',
+ 'schainpy.model.data',
+ 'schainpy.model.graphics',
+ 'schainpy.model.io',
+ 'schainpy.model.proc',
+ 'schainpy.model.serializer',
+ 'schainpy.model.utils',
+ 'schainpy.gui',
+ 'schainpy.gui.figures',
+ 'schainpy.gui.viewcontroller',
+ 'schainpy.gui.viewer',
+ 'schainpy.gui.viewer.windows'},
+ py_modules=[''],
+ package_data={'': ['schain.conf.template'],
+ 'schainpy.gui.figures': ['*.png','*.jpg'],
+ },
+ include_package_data=False,
+ scripts =['schainpy/gui/schainGUI',
+ 'schainpy/scripts/schain'],
+ install_requires=["numpy >= 1.6.0",
+ "scipy >= 0.9.0",
+ "matplotlib >= 1.0.0",
+ ],
+ )
\ No newline at end of file
diff --git a/README b/README
new file mode 100644
index 0000000..7b2047d
--- /dev/null
+++ b/README
@@ -0,0 +1,36 @@
+Prerequisites:
+
+Core:
+ -numpy 1.8.0
+ -scipy
+ -math
+ -matplotlib
+ -h5py
+ -ftplib
+ -paramiko (optional for SendTFilesToServer)
+ -stuffr (optional for jroIO_hf)
+ -pyfits (Fits data)
+
+GUI:
+ -PyQt4
+ -wxPython
+
+Signal Chain Installation:
+
+ 1. Install numpy, matplotlib, TKAgg
+ 2. Install digital_rf_hdf5 module (developed by Haystack Observatory)
+ if you want to use USRP data
+ 3. untar schainpy-x.x.x.tar.gz
+ 4. cd schainpy-x.x.x
+ 5. execute:
+ [hostname]$ sudo pyhon setup.py install
+ 6. testing gui:
+ [hostname]$ schainGUI (enter)
+
+If you want to use serialization and zerorpc you will need to install the next packages:
+
+ 1. zerorpc
+ [hostname]$ sudo port install zerorpc
+
+ 2. cPickle, msgpack and msgpack_numpy
+ [hostname]$ sudo port install cPickle msgpack mspack_numpy
\ No newline at end of file
diff --git a/schainc/.svn/all-wcprops b/schainc/.svn/all-wcprops
new file mode 100644
index 0000000..e5558a7
--- /dev/null
+++ b/schainc/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainc
+END
diff --git a/schainc/.svn/entries b/schainc/.svn/entries
new file mode 100644
index 0000000..99de90d
--- /dev/null
+++ b/schainc/.svn/entries
@@ -0,0 +1,37 @@
+10
+
+dir
+1608
+http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainc
+http://jro-dev.igp.gob.pe/svn/jro_soft/schain
+
+
+
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ea082a80-fb9f-4feb-b8d7-17586309b78c
+
+include
+dir
+
+schaincuda
+dir
+
+schainmpi
+dir
+
diff --git a/schainc/include/.svn/all-wcprops b/schainc/include/.svn/all-wcprops
new file mode 100644
index 0000000..6a0c96c
--- /dev/null
+++ b/schainc/include/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainc/include
+END
diff --git a/schainc/include/.svn/entries b/schainc/include/.svn/entries
new file mode 100644
index 0000000..86ee647
--- /dev/null
+++ b/schainc/include/.svn/entries
@@ -0,0 +1,28 @@
+10
+
+dir
+1608
+http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainc/include
+http://jro-dev.igp.gob.pe/svn/jro_soft/schain
+
+
+
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ea082a80-fb9f-4feb-b8d7-17586309b78c
+
diff --git a/schainc/schaincuda/.svn/all-wcprops b/schainc/schaincuda/.svn/all-wcprops
new file mode 100644
index 0000000..dead4d2
--- /dev/null
+++ b/schainc/schaincuda/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainc/schaincuda
+END
diff --git a/schainc/schaincuda/.svn/entries b/schainc/schaincuda/.svn/entries
new file mode 100644
index 0000000..c9e5c79
--- /dev/null
+++ b/schainc/schaincuda/.svn/entries
@@ -0,0 +1,28 @@
+10
+
+dir
+1608
+http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainc/schaincuda
+http://jro-dev.igp.gob.pe/svn/jro_soft/schain
+
+
+
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ea082a80-fb9f-4feb-b8d7-17586309b78c
+
diff --git a/schainc/schainmpi/.svn/all-wcprops b/schainc/schainmpi/.svn/all-wcprops
new file mode 100644
index 0000000..6622275
--- /dev/null
+++ b/schainc/schainmpi/.svn/all-wcprops
@@ -0,0 +1,5 @@
+K 25
+svn:wc:ra_dav:version-url
+V 79
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainc/schainmpi
+END
diff --git a/schainc/schainmpi/.svn/entries b/schainc/schainmpi/.svn/entries
new file mode 100644
index 0000000..c8cffea
--- /dev/null
+++ b/schainc/schainmpi/.svn/entries
@@ -0,0 +1,28 @@
+10
+
+dir
+1608
+http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainc/schainmpi
+http://jro-dev.igp.gob.pe/svn/jro_soft/schain
+
+
+
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ea082a80-fb9f-4feb-b8d7-17586309b78c
+
diff --git a/schainpy/.gitignore b/schainpy/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/schainpy/.gitignore
diff --git a/schainpy/.svn/all-wcprops b/schainpy/.svn/all-wcprops
new file mode 100644
index 0000000..413800e
--- /dev/null
+++ b/schainpy/.svn/all-wcprops
@@ -0,0 +1,155 @@
+K 25
+svn:wc:ra_dav:version-url
+V 70
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy
+END
+mst_blocks.xml
+K 25
+svn:wc:ra_dav:version-url
+V 85
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/mst_blocks.xml
+END
+controller_api.py
+K 25
+svn:wc:ra_dav:version-url
+V 88
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/controller_api.py
+END
+bltr_reader.xml
+K 25
+svn:wc:ra_dav:version-url
+V 86
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/bltr_reader.xml
+END
+controller_api.pyc
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/controller_api.pyc
+END
+schain.conf.template
+K 25
+svn:wc:ra_dav:version-url
+V 91
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/schain.conf.template
+END
+SA2014050.xml
+K 25
+svn:wc:ra_dav:version-url
+V 84
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/SA2014050.xml
+END
+__init__.py
+K 25
+svn:wc:ra_dav:version-url
+V 82
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/__init__.py
+END
+ProcBLTR.xml
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/ProcBLTR.xml
+END
+controller.pyc
+K 25
+svn:wc:ra_dav:version-url
+V 85
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/controller.pyc
+END
+admin.py
+K 25
+svn:wc:ra_dav:version-url
+V 79
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/admin.py
+END
+JASMET01.xml
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/JASMET01.xml
+END
+JASMET02.xml
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/JASMET02.xml
+END
+JASMET04.xml
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/JASMET04.xml
+END
+JASMET05.xml
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/JASMET05.xml
+END
+speedTools.bash
+K 25
+svn:wc:ra_dav:version-url
+V 86
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/speedTools.bash
+END
+amisr_reader.xml
+K 25
+svn:wc:ra_dav:version-url
+V 87
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/amisr_reader.xml
+END
+DBStest.xml
+K 25
+svn:wc:ra_dav:version-url
+V 82
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/DBStest.xml
+END
+150km_jicamarca.xml
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/150km_jicamarca.xml
+END
+schain.xml
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/schain.xml
+END
+VERSION
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/VERSION
+END
+controller.py
+K 25
+svn:wc:ra_dav:version-url
+V 84
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/controller.py
+END
+admin.pyc
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/admin.pyc
+END
+__init__.pyc
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/__init__.pyc
+END
+sousy_processing.xml
+K 25
+svn:wc:ra_dav:version-url
+V 91
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/sousy_processing.xml
+END
+meteor20130812.xml
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/meteor20130812.xml
+END
diff --git a/schainpy/.svn/entries b/schainpy/.svn/entries
new file mode 100644
index 0000000..3125a99
--- /dev/null
+++ b/schainpy/.svn/entries
@@ -0,0 +1,890 @@
+10
+
+dir
+1608
+http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainpy
+http://jro-dev.igp.gob.pe/svn/jro_soft/schain
+
+
+
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+ea082a80-fb9f-4feb-b8d7-17586309b78c
+
+150km_jicamarca.xml
+file
+
+
+
+
+2017-04-17T17:05:33.000000Z
+633cc63c9fe917dc19d1c6d2f3bbb0ec
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6122
+
+DBStest.xml
+file
+
+
+
+
+2017-04-17T17:05:34.000000Z
+d4cb1cb3843ed196a5e1058e3fd9e039
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3209
+
+JASMET01.xml
+file
+
+
+
+
+2017-04-17T17:05:34.000000Z
+dcbd9aaad09e87074d9c9b703b708343
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3810
+
+JASMET02.xml
+file
+
+
+
+
+2017-04-17T17:05:32.000000Z
+fa9468d8a9826be7a1b8852efd00265a
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2821
+
+JASMET04.xml
+file
+
+
+
+
+2017-04-17T17:05:33.000000Z
+2859132c5ce3da4469f7c679a74219f8
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2206
+
+JASMET05.xml
+file
+
+
+
+
+2017-04-17T17:05:33.000000Z
+188fbde965b5247e0eadad7b4c2144c9
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3232
+
+ProcBLTR.xml
+file
+
+
+
+
+2017-04-17T17:05:33.000000Z
+88c5fec9242c6f8fb0d0fde499251664
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1230
+
+SA2014050.xml
+file
+
+
+
+
+2017-04-17T17:05:33.000000Z
+96e4902fee1679c76b0ce5670265f3e0
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2542
+
+VERSION
+file
+
+
+
+
+2017-04-17T17:05:33.000000Z
+943ea679477eadeb41e73a15c3d55da1
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3168
+
+__init__.py
+file
+
+
+
+
+2017-04-17T17:05:33.000000Z
+ef3eb494b3b7cac28d84ca163803109e
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+144
+
+__init__.pyc
+file
+
+
+
+
+2017-04-17T17:05:33.000000Z
+f1687e9e91d073dc76c9b70744693a53
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+314
+
+admin.py
+file
+
+
+
+
+2017-04-17T17:05:34.000000Z
+8130389a60244b201f5802f6e3affe7d
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12756
+
+admin.pyc
+file
+
+
+
+
+2017-04-17T17:05:34.000000Z
+8b318e79db6972833dc1c91ea74d392b
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12424
+
+amisr_reader.xml
+file
+
+
+
+
+2017-04-17T17:05:33.000000Z
+c5472b4d7a5a941bb3b4c1fb5cee814d
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4832
+
+bltr_reader.xml
+file
+
+
+
+
+2017-04-17T17:05:32.000000Z
+b73684acdc87b83c42f035005e9e61b2
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+953
+
+controller.py
+file
+
+
+
+
+2017-04-17T17:05:34.000000Z
+118bea7c38eeb0a3699cff099c55b6b3
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+40737
+
+controller.pyc
+file
+
+
+
+
+2017-04-17T17:05:34.000000Z
+93a834abc5671c8319d1b50761d2db4f
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+34851
+
+controller_api.py
+file
+
+
+
+
+2017-04-17T17:05:34.000000Z
+13c7d41a54e30c6684a31a9922a629df
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4363
+
+controller_api.pyc
+file
+
+
+
+
+2017-04-17T17:05:34.000000Z
+4b9047ce8c3f6e3e490e174de1a8b0c2
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4105
+
+gui
+dir
+
+meteor20130812.xml
+file
+
+
+
+
+2017-04-17T17:05:34.000000Z
+e73018cbbebca1c4f625f0e899d889df
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1529
+
+model
+dir
+
+mst_blocks.xml
+file
+
+
+
+
+2017-04-17T17:05:33.000000Z
+71cbe0250db18692c1df9f7f6806b1a6
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4249
+
+schain.conf.template
+file
+
+
+
+
+2017-04-17T17:05:34.000000Z
+0fef670499653363e26c48930c834dac
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+192
+
+schain.xml
+file
+
+
+
+
+2017-04-17T17:05:34.000000Z
+566cfaa9fa71229d6360abfc3618f52b
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3825
+
+scripts
+dir
+
+sousy_processing.xml
+file
+
+
+
+
+2017-04-17T17:05:34.000000Z
+aba1b28f36d5a7b6632a1554aed92975
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2650
+
+speedTools.bash
+file
+
+
+
+
+2017-04-17T17:05:33.000000Z
+f2457a2f9b102f87208f0caf76759a91
+2017-04-12T22:42:28.822577Z
+1606
+ebocanegra
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+358
+
+zerorpc
+dir
+
diff --git a/schainpy/.svn/prop-base/__init__.pyc.svn-base b/schainpy/.svn/prop-base/__init__.pyc.svn-base
new file mode 100644
index 0000000..5e9587e
--- /dev/null
+++ b/schainpy/.svn/prop-base/__init__.pyc.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
diff --git a/schainpy/.svn/prop-base/admin.pyc.svn-base b/schainpy/.svn/prop-base/admin.pyc.svn-base
new file mode 100644
index 0000000..5e9587e
--- /dev/null
+++ b/schainpy/.svn/prop-base/admin.pyc.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
diff --git a/schainpy/.svn/prop-base/controller.pyc.svn-base b/schainpy/.svn/prop-base/controller.pyc.svn-base
new file mode 100644
index 0000000..5e9587e
--- /dev/null
+++ b/schainpy/.svn/prop-base/controller.pyc.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
diff --git a/schainpy/.svn/prop-base/controller_api.pyc.svn-base b/schainpy/.svn/prop-base/controller_api.pyc.svn-base
new file mode 100644
index 0000000..5e9587e
--- /dev/null
+++ b/schainpy/.svn/prop-base/controller_api.pyc.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
diff --git a/schainpy/.svn/text-base/150km_jicamarca.xml.svn-base b/schainpy/.svn/text-base/150km_jicamarca.xml.svn-base
new file mode 100644
index 0000000..95c5465
--- /dev/null
+++ b/schainpy/.svn/text-base/150km_jicamarca.xml.svn-base
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/DBStest.xml.svn-base b/schainpy/.svn/text-base/DBStest.xml.svn-base
new file mode 100644
index 0000000..9573a59
--- /dev/null
+++ b/schainpy/.svn/text-base/DBStest.xml.svn-base
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/JASMET01.xml.svn-base b/schainpy/.svn/text-base/JASMET01.xml.svn-base
new file mode 100644
index 0000000..18f18b6
--- /dev/null
+++ b/schainpy/.svn/text-base/JASMET01.xml.svn-base
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/JASMET02.xml.svn-base b/schainpy/.svn/text-base/JASMET02.xml.svn-base
new file mode 100644
index 0000000..4ad0cde
--- /dev/null
+++ b/schainpy/.svn/text-base/JASMET02.xml.svn-base
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/JASMET04.xml.svn-base b/schainpy/.svn/text-base/JASMET04.xml.svn-base
new file mode 100644
index 0000000..9e2f34f
--- /dev/null
+++ b/schainpy/.svn/text-base/JASMET04.xml.svn-base
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/JASMET05.xml.svn-base b/schainpy/.svn/text-base/JASMET05.xml.svn-base
new file mode 100644
index 0000000..0a2bc25
--- /dev/null
+++ b/schainpy/.svn/text-base/JASMET05.xml.svn-base
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/ProcBLTR.xml.svn-base b/schainpy/.svn/text-base/ProcBLTR.xml.svn-base
new file mode 100644
index 0000000..63dcb27
--- /dev/null
+++ b/schainpy/.svn/text-base/ProcBLTR.xml.svn-base
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/SA2014050.xml.svn-base b/schainpy/.svn/text-base/SA2014050.xml.svn-base
new file mode 100644
index 0000000..ade1ed6
--- /dev/null
+++ b/schainpy/.svn/text-base/SA2014050.xml.svn-base
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/VERSION.svn-base b/schainpy/.svn/text-base/VERSION.svn-base
new file mode 100644
index 0000000..a19b1a9
--- /dev/null
+++ b/schainpy/.svn/text-base/VERSION.svn-base
@@ -0,0 +1,85 @@
+VERSIONS:
+
+2.1.2:
+-jroutils_ftp.py: Bug fixed, Any error sending file stopped the Server Thread
+ Server thread opens and closes remote server each time file list is sent
+-jroplot_spectra.py: Noise path was not being created when noise data is saved.
+-jroIO_base.py: startTime can be greater than endTime. Example: SpreadF [18:00 - 07:00]
+
+2.1.3:
+-jroplot_heispectra.py: SpectraHeisScope was not showing the right channels
+-jroproc_voltage.py: Bug fixed selecting profiles (self.nProfiles took a wrong value),
+ Bug fixed selecting heights by block (selecting profiles instead heights)
+-jroproc_voltage.py: New feature added: decoding data by block using FFT.
+-jroIO_heispectra.py: Bug fixed in FitsReader. Using local Fits instance instead schainpy.mode.data.jrodata.Fits.
+-jroIO_heispectra.py: Channel index list does not exist.
+
+2.1.3.1:
+-GUI: every icon were resized
+-jroproc_voltage.py: Print a message when "Read from code" option is selected and the code is not defined inside data file
+
+2.1.3.2:
+-GUI: user interaction enhanced
+-controller_api.py: Safe access to ControllerThead
+
+2.1.3.3:
+-Colored Button Icons were added to GUI
+
+2.1.4:
+-Sending error notifications to signal chain administrator
+-Login to email server added
+
+2.1.4.1:
+-Send notifications when an error different to ValueError is detected
+
+2.1.4.2:
+-A new Plotter Class was added
+-Project.start() does not accept filename as a parameter anymore
+
+2.1.5:
+-serializer module added to Signal Chain
+-jroplotter.py added to Signal Chain
+
+2.2.0:
+-GUI: use of external plotter
+-Compatible with matplotlib 1.5.0
+
+2.2.1:
+-Bugs fixed in GUI
+-Views were improved in GUI
+-Support to MST-ISR experiments
+-Bug fixed getting noise using hyldebrant. (minimum number of points > 20%)
+-handleError added to jroplotter.py
+
+2.2.2:
+-VoltageProc: ProfileSelector, Reshape, Decoder with nTxs!=1 and getblock=True was tested
+-Rawdata and testRawdata.py added to Signal Chain project
+
+2.2.3:
+-Bug fixed in GUI: Error getting(reading) Code value
+-Bug fixed in GUI: Flip option always needs channelList field
+-Bug fixed in jrodata: when one branch modified a value in "dataOut" (example: dataOut.code) this value
+was modified for every branch (because this was a reference). It was modified in data.copy()
+-Bug fixed in jroproc_voltage.profileSelector(): rangeList replaces to profileRangeList.
+
+
+2.2.3.1:
+-Filtering block by time has been added.
+-Bug fixed plotting RTI, CoherenceMap and others using xmin and xmax parameters. The first day worked
+properly but the next days did not.
+
+2.2.4:
+-jroproc_spectra_lags.py added to schainpy
+-Bug fixed in schainGUI: ProcUnit was created with the same id in some cases.
+-Bug fixed in jroHeaderIO: Header size validation.
+
+2.2.4.1:
+-jroIO_usrp.py is update to read Sandra's data
+-decimation in Spectra and RTI plots is always enabled.
+-time-window option added to GUI
+
+2.2.5:
+-splitProfiles and combineProfiles modules were added to VoltageProc and Signal Chain GUI.
+-nProfiles of USRP data (hdf5) is the number of profiles thera are in one second.
+-jroPlotter works directly with data objects instead of dictionaries
+-script "schain" was added to Signal Chain installer
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/__init__.py.svn-base b/schainpy/.svn/text-base/__init__.py.svn-base
new file mode 100644
index 0000000..0e5d2a9
--- /dev/null
+++ b/schainpy/.svn/text-base/__init__.py.svn-base
@@ -0,0 +1,7 @@
+'''
+Created on Feb 7, 2012
+
+@author $Author: murco $
+@version $Id: __init__.py 1436 2016-04-27 09:33:27Z murco $
+'''
+__version__ = "2.2.5"
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/__init__.pyc.svn-base b/schainpy/.svn/text-base/__init__.pyc.svn-base
new file mode 100644
index 0000000000000000000000000000000000000000..be14cb881310bc7219c2e6a610423d2c0b5f53db
GIT binary patch
literal 314
zc$`g-O-sZu5QfuTTqPp-6LRRG2itVhy2Y|cMG(Ar@gVdPY7%Hz+ms|#_IG<0oGk0d
zz&sgdGVjbRKQC}ve!U2Ev1N*>OX9o3Ta#h7!jKp@@5(w2-{VJF6VCOhJ?Gi9C+o7t}RUU
literal 0
Hc$@" + subtitle.replace("\n", "\n") + "
" + message.replace("\n", "
\n")
+ message = "\n" + message + ''
+
+ # This is the textual part:
+ part = MIMEText(message, "html")
+ else:
+ message = subject + "\n" + subtitle + "\n" + message
+ part = MIMEText(message)
+
+ msg.attach(part)
+
+ if os.path.isfile(filename):
+ # This is the binary part(The Attachment):
+ part = MIMEApplication(open(filename,"rb").read())
+ part.add_header('Content-Disposition',
+ 'attachment',
+ filename=os.path.basename(filename))
+ msg.attach(part)
+
+ # Create an instance in SMTP server
+ try:
+ smtp = smtplib.SMTP(self.__emailServer)
+ except:
+ print "***** Could not connect to server %s *****" %self.__emailServer
+ return 0
+
+ # Start the server:
+# smtp.ehlo()
+ if self.__emailPass:
+ smtp.login(self.__emailFromAddress, self.__emailPass)
+
+ # Send the email
+ try:
+ smtp.sendmail(msg['From'], msg['To'], msg.as_string())
+ except:
+ print "***** Could not send the email to %s *****" %msg['To']
+ smtp.quit()
+ return 0
+
+ smtp.quit()
+
+ return 1
+
+ def sendAlert(self, message, subject = "", subtitle="", filename=""):
+ """sendAlert sends an email with the given message and optional title.
+
+ Inputs: message (string), and optional title (string)
+
+ Returns: void
+
+ Affects: none
+
+ Exceptions: None.
+ """
+
+ if not self.__emailToAddress:
+ return 0
+
+ print "***** Sending alert to %s *****" %self.__emailToAddress
+ # set up message
+
+ sent=self.sendEmail(email_from=self.__emailFromAddress,
+ email_to=self.__emailToAddress,
+ subject=subject,
+ message=message,
+ subtitle=subtitle,
+ filename=filename)
+
+ if not sent:
+ return 0
+
+ print "***** Your system administrator has been notified *****"
+
+ return 1
+
+ def notify(self, email, message, subject = "", subtitle="", filename=""):
+ """notify sends an email with the given message and title to email.
+
+ Inputs: email (string), message (string), and subject (string)
+
+ Returns: void
+
+ Affects: none
+
+ Exceptions: None.
+ """
+
+ print "Notifying to %s ..." %email
+
+ self.sendEmail(email_from=self.__emailFromAddress,
+ email_to=email,
+ subject=subject,
+ message=message,
+ subtitle=subtitle,
+ filename=filename)
+
+ print "***** Your system administrator has been notified *****"
+
+class SchainError(Exception):
+ """SchainError is an exception class that is thrown for all known errors using Schain Py lib.
+
+ Usage example:
+
+ import sys, traceback
+ import schainpy.admin
+
+ try:
+
+ test = open('ImportantFile.txt', 'r')
+
+ except:
+
+ raise schainpy.admin.SchainError('ImportantFile.txt not opened!',
+ traceback.format_exception(sys.exc_info()[0],
+ sys.exc_info()[1],
+ sys.exc_info()[2]))
+ """
+
+
+ def __init__(self, strInterpretation, exceptionList=None):
+ """ __init__ gathers the interpretation string along with all information from sys.exc_info().
+
+ Inputs:
+ strIntepretation - A string representing the programmer's interpretation of
+ why the exception occurred
+
+ exceptionList - a list of strings completely describing the exception.
+ Generated by traceback.format_exception(sys.exc_info()[0],
+ sys.exc_info()[1],
+ sys.exc_info()[2])
+
+ Returns: Void.
+
+ Affects: Initializes class member variables _strInterp, _strExcList.
+
+ Exceptions: None.
+ """
+
+ if not exceptionList:
+ exceptionList = traceback.format_exception(sys.exc_info()[0],
+ sys.exc_info()[1],
+ sys.exc_info()[2])
+
+ self._strInterp = strInterpretation
+ self._strExcList = exceptionList
+
+
+ def getExceptionStr(self):
+ """ getExceptionStr returns a formatted string ready for printing completely describing the exception.
+
+ Inputs: None
+
+ Returns: A formatted string ready for printing completely describing the exception.
+
+ Affects: None
+
+ Exceptions: None.
+ """
+ excStr = ''
+ excStr = excStr + self._strInterp + '\n\n'
+
+ if self._strExcList != None:
+ for item in self._strExcList:
+ excStr = excStr + str(item) + '\n'
+
+ return excStr
+
+ def __str__(self):
+
+ return(self.getExceptionStr())
+
+
+ def getExceptionHtml(self):
+ """ getExceptionHtml returns an Html formatted string completely describing the exception.
+
+ Inputs: None
+
+ Returns: A formatted string ready for printing completely describing the exception.
+
+ Affects: None
+
+ Exceptions: None.
+ """
+
+ excStr = '
The following Schain Python exception has occurred:\n
'
+ excStr = excStr + self._strInterp + '\n
\n'
+
+ if self._strExcList != None:
+ for item in self._strExcList:
+ excStr = excStr + str(item) + '\n
'
+
+ return excStr
+
+if __name__ == '__main__':
+
+ test = SchainNotify()
+
+ test.sendAlert('This is a message from the python module SchainNotify', 'Test from SchainNotify')
+
+ print 'Hopefully message sent - check.'
diff --git a/schainpy/.svn/text-base/admin.pyc.svn-base b/schainpy/.svn/text-base/admin.pyc.svn-base
new file mode 100644
index 0000000000000000000000000000000000000000..bc5cd6a11941e739214a360759280f7ed8ddfc3a
GIT binary patch
literal 12424
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
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/bltr_reader.xml.svn-base b/schainpy/.svn/text-base/bltr_reader.xml.svn-base
new file mode 100644
index 0000000..b7226fb
--- /dev/null
+++ b/schainpy/.svn/text-base/bltr_reader.xml.svn-base
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/controller.py.svn-base b/schainpy/.svn/text-base/controller.py.svn-base
new file mode 100644
index 0000000..36d8ad8
--- /dev/null
+++ b/schainpy/.svn/text-base/controller.py.svn-base
@@ -0,0 +1,1294 @@
+'''
+Created on September , 2012
+@author:
+'''
+
+import sys
+import ast
+import datetime
+import traceback
+import schainpy
+import schainpy.admin
+
+from xml.etree.ElementTree import ElementTree, Element, SubElement, tostring
+from xml.dom import minidom
+
+from schainpy.model import *
+from time import sleep
+
+def prettify(elem):
+ """Return a pretty-printed XML string for the Element.
+ """
+ rough_string = tostring(elem, 'utf-8')
+ reparsed = minidom.parseString(rough_string)
+ return reparsed.toprettyxml(indent=" ")
+
+class ParameterConf():
+
+ id = None
+ name = None
+ value = None
+ format = None
+
+ __formated_value = None
+
+ ELEMENTNAME = 'Parameter'
+
+ def __init__(self):
+
+ self.format = 'str'
+
+ def getElementName(self):
+
+ return self.ELEMENTNAME
+
+ def getValue(self):
+
+ value = self.value
+ format = self.format
+
+ if self.__formated_value != None:
+
+ return self.__formated_value
+
+ if format == 'str':
+ self.__formated_value = str(value)
+ return self.__formated_value
+
+ if value == '':
+ raise ValueError, "%s: This parameter value is empty" %self.name
+
+ if format == 'list':
+ strList = value.split(',')
+
+ self.__formated_value = strList
+
+ return self.__formated_value
+
+ if format == 'intlist':
+ """
+ Example:
+ value = (0,1,2)
+ """
+
+ new_value = ast.literal_eval(value)
+
+ if type(new_value) not in (tuple, list):
+ new_value = [int(new_value)]
+
+ self.__formated_value = new_value
+
+ return self.__formated_value
+
+ if format == 'floatlist':
+ """
+ Example:
+ value = (0.5, 1.4, 2.7)
+ """
+
+ new_value = ast.literal_eval(value)
+
+ if type(new_value) not in (tuple, list):
+ new_value = [float(new_value)]
+
+ self.__formated_value = new_value
+
+ return self.__formated_value
+
+ if format == 'date':
+ strList = value.split('/')
+ intList = [int(x) for x in strList]
+ date = datetime.date(intList[0], intList[1], intList[2])
+
+ self.__formated_value = date
+
+ return self.__formated_value
+
+ if format == 'time':
+ strList = value.split(':')
+ intList = [int(x) for x in strList]
+ time = datetime.time(intList[0], intList[1], intList[2])
+
+ self.__formated_value = time
+
+ return self.__formated_value
+
+ if format == 'pairslist':
+ """
+ Example:
+ value = (0,1),(1,2)
+ """
+
+ new_value = ast.literal_eval(value)
+
+ if type(new_value) not in (tuple, list):
+ raise ValueError, "%s has to be a tuple or list of pairs" %value
+
+ if type(new_value[0]) not in (tuple, list):
+ if len(new_value) != 2:
+ raise ValueError, "%s has to be a tuple or list of pairs" %value
+ new_value = [new_value]
+
+ for thisPair in new_value:
+ if len(thisPair) != 2:
+ raise ValueError, "%s has to be a tuple or list of pairs" %value
+
+ self.__formated_value = new_value
+
+ return self.__formated_value
+
+ if format == 'multilist':
+ """
+ Example:
+ value = (0,1,2),(3,4,5)
+ """
+ multiList = ast.literal_eval(value)
+
+ if type(multiList[0]) == int:
+ multiList = ast.literal_eval("(" + value + ")")
+
+ self.__formated_value = multiList
+
+ return self.__formated_value
+
+ if format == 'bool':
+ value = int(value)
+
+ if format == 'int':
+ value = float(value)
+
+ format_func = eval(format)
+
+ self.__formated_value = format_func(value)
+
+ return self.__formated_value
+
+ def updateId(self, new_id):
+
+ self.id = str(new_id)
+
+ def setup(self, id, name, value, format='str'):
+
+ self.id = str(id)
+ self.name = name
+ self.value = str(value)
+ self.format = str.lower(format)
+
+ self.getValue()
+
+ return 1
+
+ def update(self, name, value, format='str'):
+
+ self.name = name
+ self.value = str(value)
+ self.format = format
+
+ def makeXml(self, opElement):
+
+ parmElement = SubElement(opElement, self.ELEMENTNAME)
+ parmElement.set('id', str(self.id))
+ parmElement.set('name', self.name)
+ parmElement.set('value', self.value)
+ parmElement.set('format', self.format)
+
+ def readXml(self, parmElement):
+
+ self.id = parmElement.get('id')
+ self.name = parmElement.get('name')
+ self.value = parmElement.get('value')
+ self.format = str.lower(parmElement.get('format'))
+
+ #Compatible with old signal chain version
+ if self.format == 'int' and self.name == 'idfigure':
+ self.name = 'id'
+
+ def printattr(self):
+
+ print "Parameter[%s]: name = %s, value = %s, format = %s" %(self.id, self.name, self.value, self.format)
+
+class OperationConf():
+
+ id = None
+ name = None
+ priority = None
+ type = None
+
+ parmConfObjList = []
+
+ ELEMENTNAME = 'Operation'
+
+ def __init__(self):
+
+ self.id = '0'
+ self.name = None
+ self.priority = None
+ self.type = 'self'
+
+
+ def __getNewId(self):
+
+ return int(self.id)*10 + len(self.parmConfObjList) + 1
+
+ def updateId(self, new_id):
+
+ self.id = str(new_id)
+
+ n = 1
+ for parmObj in self.parmConfObjList:
+
+ idParm = str(int(new_id)*10 + n)
+ parmObj.updateId(idParm)
+
+ n += 1
+
+ def getElementName(self):
+
+ return self.ELEMENTNAME
+
+ def getParameterObjList(self):
+
+ return self.parmConfObjList
+
+ def getParameterObj(self, parameterName):
+
+ for parmConfObj in self.parmConfObjList:
+
+ if parmConfObj.name != parameterName:
+ continue
+
+ return parmConfObj
+
+ return None
+
+ def getParameterObjfromValue(self, parameterValue):
+
+ for parmConfObj in self.parmConfObjList:
+
+ if parmConfObj.getValue() != parameterValue:
+ continue
+
+ return parmConfObj.getValue()
+
+ return None
+
+ def getParameterValue(self, parameterName):
+
+ parameterObj = self.getParameterObj(parameterName)
+
+# if not parameterObj:
+# return None
+
+ value = parameterObj.getValue()
+
+ return value
+
+ def setup(self, id, name, priority, type):
+
+ self.id = str(id)
+ self.name = name
+ self.type = type
+ self.priority = priority
+
+ self.parmConfObjList = []
+
+ def removeParameters(self):
+
+ for obj in self.parmConfObjList:
+ del obj
+
+ self.parmConfObjList = []
+
+ def addParameter(self, name, value, format='str'):
+
+ id = self.__getNewId()
+
+ parmConfObj = ParameterConf()
+ if not parmConfObj.setup(id, name, value, format):
+ return None
+
+ self.parmConfObjList.append(parmConfObj)
+
+ return parmConfObj
+
+ def changeParameter(self, name, value, format='str'):
+
+ parmConfObj = self.getParameterObj(name)
+ parmConfObj.update(name, value, format)
+
+ return parmConfObj
+
+ def makeXml(self, procUnitElement):
+
+ opElement = SubElement(procUnitElement, self.ELEMENTNAME)
+ opElement.set('id', str(self.id))
+ opElement.set('name', self.name)
+ opElement.set('type', self.type)
+ opElement.set('priority', str(self.priority))
+
+ for parmConfObj in self.parmConfObjList:
+ parmConfObj.makeXml(opElement)
+
+ def readXml(self, opElement):
+
+ self.id = opElement.get('id')
+ self.name = opElement.get('name')
+ self.type = opElement.get('type')
+ self.priority = opElement.get('priority')
+
+ #Compatible with old signal chain version
+ #Use of 'run' method instead 'init'
+ if self.type == 'self' and self.name == 'init':
+ self.name = 'run'
+
+ self.parmConfObjList = []
+
+ parmElementList = opElement.getiterator(ParameterConf().getElementName())
+
+ for parmElement in parmElementList:
+ parmConfObj = ParameterConf()
+ parmConfObj.readXml(parmElement)
+
+ #Compatible with old signal chain version
+ #If an 'plot' OPERATION is found, changes name operation by the value of its type PARAMETER
+ if self.type != 'self' and self.name == 'Plot':
+ if parmConfObj.format == 'str' and parmConfObj.name == 'type':
+ self.name = parmConfObj.value
+ continue
+
+ self.parmConfObjList.append(parmConfObj)
+
+ def printattr(self):
+
+ print "%s[%s]: name = %s, type = %s, priority = %s" %(self.ELEMENTNAME,
+ self.id,
+ self.name,
+ self.type,
+ self.priority)
+
+ for parmConfObj in self.parmConfObjList:
+ parmConfObj.printattr()
+
+ def createObject(self, plotter_queue=None):
+
+ if self.type == 'self':
+ raise ValueError, "This operation type cannot be created"
+
+ if self.type == 'plotter':
+ #Plotter(plotter_name)
+ if not plotter_queue:
+ raise ValueError, "plotter_queue is not defined. Use:\nmyProject = Project()\nmyProject.setPlotterQueue(plotter_queue)"
+
+ opObj = Plotter(self.name, plotter_queue)
+
+ if self.type == 'external' or self.type == 'other':
+ className = eval(self.name)
+ opObj = className()
+
+ return opObj
+
+class ProcUnitConf():
+
+ id = None
+ name = None
+ datatype = None
+ inputId = None
+ parentId = None
+
+ opConfObjList = []
+
+ procUnitObj = None
+ opObjList = []
+
+ ELEMENTNAME = 'ProcUnit'
+
+ def __init__(self):
+
+ self.id = None
+ self.datatype = None
+ self.name = None
+ self.inputId = None
+
+ self.opConfObjList = []
+
+ self.procUnitObj = None
+ self.opObjDict = {}
+
+ def __getPriority(self):
+
+ return len(self.opConfObjList)+1
+
+ def __getNewId(self):
+
+ return int(self.id)*10 + len(self.opConfObjList) + 1
+
+ def getElementName(self):
+
+ return self.ELEMENTNAME
+
+ def getId(self):
+
+ return self.id
+
+ def updateId(self, new_id, parentId=parentId):
+
+
+ new_id = int(parentId)*10 + (int(self.id) % 10)
+ new_inputId = int(parentId)*10 + (int(self.inputId) % 10)
+
+ #If this proc unit has not inputs
+ if self.inputId == '0':
+ new_inputId = 0
+
+ n = 1
+ for opConfObj in self.opConfObjList:
+
+ idOp = str(int(new_id)*10 + n)
+ opConfObj.updateId(idOp)
+
+ n += 1
+
+ self.parentId = str(parentId)
+ self.id = str(new_id)
+ self.inputId = str(new_inputId)
+
+
+ def getInputId(self):
+
+ return self.inputId
+
+ def getOperationObjList(self):
+
+ return self.opConfObjList
+
+ def getOperationObj(self, name=None):
+
+ for opConfObj in self.opConfObjList:
+
+ if opConfObj.name != name:
+ continue
+
+ return opConfObj
+
+ return None
+
+ def getOpObjfromParamValue(self, value=None):
+
+ for opConfObj in self.opConfObjList:
+ if opConfObj.getParameterObjfromValue(parameterValue=value) != value:
+ continue
+ return opConfObj
+ return None
+
+ def getProcUnitObj(self):
+
+ return self.procUnitObj
+
+ def setup(self, id, name, datatype, inputId, parentId=None):
+
+ #Compatible with old signal chain version
+ if datatype==None and name==None:
+ raise ValueError, "datatype or name should be defined"
+
+ if name==None:
+ if 'Proc' in datatype:
+ name = datatype
+ else:
+ name = '%sProc' %(datatype)
+
+ if datatype==None:
+ datatype = name.replace('Proc','')
+
+ self.id = str(id)
+ self.name = name
+ self.datatype = datatype
+ self.inputId = inputId
+ self.parentId = parentId
+
+ self.opConfObjList = []
+
+ self.addOperation(name='run', optype='self')
+
+ def removeOperations(self):
+
+ for obj in self.opConfObjList:
+ del obj
+
+ self.opConfObjList = []
+ self.addOperation(name='run')
+
+ def addParameter(self, **kwargs):
+ '''
+ Add parameters to "run" operation
+ '''
+ opObj = self.opConfObjList[0]
+
+ opObj.addParameter(**kwargs)
+
+ return opObj
+
+ def addOperation(self, name, optype='self'):
+
+ id = self.__getNewId()
+ priority = self.__getPriority()
+
+ opConfObj = OperationConf()
+ opConfObj.setup(id, name=name, priority=priority, type=optype)
+
+ self.opConfObjList.append(opConfObj)
+
+ return opConfObj
+
+ def makeXml(self, projectElement):
+
+ procUnitElement = SubElement(projectElement, self.ELEMENTNAME)
+ procUnitElement.set('id', str(self.id))
+ procUnitElement.set('name', self.name)
+ procUnitElement.set('datatype', self.datatype)
+ procUnitElement.set('inputId', str(self.inputId))
+
+ for opConfObj in self.opConfObjList:
+ opConfObj.makeXml(procUnitElement)
+
+ def readXml(self, upElement):
+
+ self.id = upElement.get('id')
+ self.name = upElement.get('name')
+ self.datatype = upElement.get('datatype')
+ self.inputId = upElement.get('inputId')
+
+ if self.ELEMENTNAME == "ReadUnit":
+ self.datatype = self.datatype.replace("Reader", "")
+
+ if self.ELEMENTNAME == "ProcUnit":
+ self.datatype = self.datatype.replace("Proc", "")
+
+ if self.inputId == 'None':
+ self.inputId = '0'
+
+ self.opConfObjList = []
+
+ opElementList = upElement.getiterator(OperationConf().getElementName())
+
+ for opElement in opElementList:
+ opConfObj = OperationConf()
+ opConfObj.readXml(opElement)
+ self.opConfObjList.append(opConfObj)
+
+ def printattr(self):
+
+ print "%s[%s]: name = %s, datatype = %s, inputId = %s" %(self.ELEMENTNAME,
+ self.id,
+ self.name,
+ self.datatype,
+ self.inputId)
+
+ for opConfObj in self.opConfObjList:
+ opConfObj.printattr()
+
+ def createObjects(self, plotter_queue=None):
+
+ className = eval(self.name)
+ procUnitObj = className()
+
+ for opConfObj in self.opConfObjList:
+
+ if opConfObj.type == 'self':
+ continue
+
+ opObj = opConfObj.createObject(plotter_queue)
+
+ self.opObjDict[opConfObj.id] = opObj
+ procUnitObj.addOperation(opObj, opConfObj.id)
+
+ self.procUnitObj = procUnitObj
+
+ return procUnitObj
+
+ def run(self):
+
+ is_ok = False
+
+ for opConfObj in self.opConfObjList:
+
+ kwargs = {}
+ for parmConfObj in opConfObj.getParameterObjList():
+ if opConfObj.name == 'run' and parmConfObj.name == 'datatype':
+ continue
+
+ kwargs[parmConfObj.name] = parmConfObj.getValue()
+
+ ini = time.time()
+
+ #print "\tRunning the '%s' operation with %s" %(opConfObj.name, opConfObj.id)
+ sts = self.procUnitObj.call(opType = opConfObj.type,
+ opName = opConfObj.name,
+ opId = opConfObj.id,
+ **kwargs)
+
+# total_time = time.time() - ini
+#
+# if total_time > 0.002:
+# print "%s::%s took %f seconds" %(self.name, opConfObj.name, total_time)
+
+ is_ok = is_ok or sts
+
+ return is_ok
+
+ def close(self):
+
+ for opConfObj in self.opConfObjList:
+ if opConfObj.type == 'self':
+ continue
+
+ opObj = self.procUnitObj.getOperationObj(opConfObj.id)
+ opObj.close()
+
+ self.procUnitObj.close()
+
+ return
+
+class ReadUnitConf(ProcUnitConf):
+
+ path = None
+ startDate = None
+ endDate = None
+ startTime = None
+ endTime = None
+
+ ELEMENTNAME = 'ReadUnit'
+
+ def __init__(self):
+
+ self.id = None
+ self.datatype = None
+ self.name = None
+ self.inputId = None
+
+ self.parentId = None
+
+ self.opConfObjList = []
+ self.opObjList = []
+
+ def getElementName(self):
+
+ return self.ELEMENTNAME
+
+ def setup(self, id, name, datatype, path, startDate="", endDate="", startTime="", endTime="", parentId=None, **kwargs):
+
+ #Compatible with old signal chain version
+ if datatype==None and name==None:
+ raise ValueError, "datatype or name should be defined"
+
+ if name==None:
+ if 'Reader' in datatype:
+ name = datatype
+ else:
+ name = '%sReader' %(datatype)
+
+ if datatype==None:
+ datatype = name.replace('Reader','')
+
+ self.id = id
+ self.name = name
+ self.datatype = datatype
+
+ self.path = os.path.abspath(path)
+ self.startDate = startDate
+ self.endDate = endDate
+ self.startTime = startTime
+ self.endTime = endTime
+
+ self.inputId = '0'
+ self.parentId = parentId
+
+ self.addRunOperation(**kwargs)
+
+ def update(self, datatype, path, startDate, endDate, startTime, endTime, parentId=None, name=None, **kwargs):
+
+ #Compatible with old signal chain version
+ if datatype==None and name==None:
+ raise ValueError, "datatype or name should be defined"
+
+ if name==None:
+ if 'Reader' in datatype:
+ name = datatype
+ else:
+ name = '%sReader' %(datatype)
+
+ if datatype==None:
+ datatype = name.replace('Reader','')
+
+ self.datatype = datatype
+ self.name = name
+ self.path = path
+ self.startDate = startDate
+ self.endDate = endDate
+ self.startTime = startTime
+ self.endTime = endTime
+
+ self.inputId = '0'
+ self.parentId = parentId
+
+ self.updateRunOperation(**kwargs)
+
+ def removeOperations(self):
+
+ for obj in self.opConfObjList:
+ del obj
+
+ self.opConfObjList = []
+
+ def addRunOperation(self, **kwargs):
+
+ opObj = self.addOperation(name = 'run', optype = 'self')
+
+ opObj.addParameter(name='datatype' , value=self.datatype, format='str')
+ opObj.addParameter(name='path' , value=self.path, format='str')
+ opObj.addParameter(name='startDate' , value=self.startDate, format='date')
+ opObj.addParameter(name='endDate' , value=self.endDate, format='date')
+ opObj.addParameter(name='startTime' , value=self.startTime, format='time')
+ opObj.addParameter(name='endTime' , value=self.endTime, format='time')
+
+ for key, value in kwargs.items():
+ opObj.addParameter(name=key, value=value, format=type(value).__name__)
+
+ return opObj
+
+ def updateRunOperation(self, **kwargs):
+
+ opObj = self.getOperationObj(name = 'run')
+ opObj.removeParameters()
+
+ opObj.addParameter(name='datatype' , value=self.datatype, format='str')
+ opObj.addParameter(name='path' , value=self.path, format='str')
+ opObj.addParameter(name='startDate' , value=self.startDate, format='date')
+ opObj.addParameter(name='endDate' , value=self.endDate, format='date')
+ opObj.addParameter(name='startTime' , value=self.startTime, format='time')
+ opObj.addParameter(name='endTime' , value=self.endTime, format='time')
+
+ for key, value in kwargs.items():
+ opObj.addParameter(name=key, value=value, format=type(value).__name__)
+
+ return opObj
+
+# def makeXml(self, projectElement):
+#
+# procUnitElement = SubElement(projectElement, self.ELEMENTNAME)
+# procUnitElement.set('id', str(self.id))
+# procUnitElement.set('name', self.name)
+# procUnitElement.set('datatype', self.datatype)
+# procUnitElement.set('inputId', str(self.inputId))
+#
+# for opConfObj in self.opConfObjList:
+# opConfObj.makeXml(procUnitElement)
+
+ def readXml(self, upElement):
+
+ self.id = upElement.get('id')
+ self.name = upElement.get('name')
+ self.datatype = upElement.get('datatype')
+ self.inputId = upElement.get('inputId')
+
+ if self.ELEMENTNAME == "ReadUnit":
+ self.datatype = self.datatype.replace("Reader", "")
+
+ if self.inputId == 'None':
+ self.inputId = '0'
+
+ self.opConfObjList = []
+
+ opElementList = upElement.getiterator(OperationConf().getElementName())
+
+ for opElement in opElementList:
+ opConfObj = OperationConf()
+ opConfObj.readXml(opElement)
+ self.opConfObjList.append(opConfObj)
+
+ if opConfObj.name == 'run':
+ self.path = opConfObj.getParameterValue('path')
+ self.startDate = opConfObj.getParameterValue('startDate')
+ self.endDate = opConfObj.getParameterValue('endDate')
+ self.startTime = opConfObj.getParameterValue('startTime')
+ self.endTime = opConfObj.getParameterValue('endTime')
+
+class Project():
+
+ id = None
+ name = None
+ description = None
+ filename = None
+
+ procUnitConfObjDict = None
+
+ ELEMENTNAME = 'Project'
+
+ plotterQueue = None
+
+ def __init__(self, plotter_queue=None):
+
+ self.id = None
+ self.name = None
+ self.description = None
+
+ self.plotterQueue = plotter_queue
+
+ self.procUnitConfObjDict = {}
+
+ def __getNewId(self):
+
+ idList = self.procUnitConfObjDict.keys()
+
+ id = int(self.id)*10
+
+ while True:
+ id += 1
+
+ if str(id) in idList:
+ continue
+
+ break
+
+ return str(id)
+
+ def getElementName(self):
+
+ return self.ELEMENTNAME
+
+ def getId(self):
+
+ return self.id
+
+ def updateId(self, new_id):
+
+ self.id = str(new_id)
+
+ keyList = self.procUnitConfObjDict.keys()
+ keyList.sort()
+
+ n = 1
+ newProcUnitConfObjDict = {}
+
+ for procKey in keyList:
+
+ procUnitConfObj = self.procUnitConfObjDict[procKey]
+ idProcUnit = str(int(self.id)*10 + n)
+ procUnitConfObj.updateId(idProcUnit, parentId = self.id)
+
+ newProcUnitConfObjDict[idProcUnit] = procUnitConfObj
+ n += 1
+
+ self.procUnitConfObjDict = newProcUnitConfObjDict
+
+ def setup(self, id, name, description):
+
+ self.id = str(id)
+ self.name = name
+ self.description = description
+
+ def update(self, name, description):
+
+ self.name = name
+ self.description = description
+
+ def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
+
+ if id is None:
+ idReadUnit = self.__getNewId()
+ else:
+ idReadUnit = str(id)
+
+ readUnitConfObj = ReadUnitConf()
+ readUnitConfObj.setup(idReadUnit, name, datatype, parentId=self.id, **kwargs)
+
+ self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
+
+ return readUnitConfObj
+
+ def addProcUnit(self, inputId='0', datatype=None, name=None):
+
+ idProcUnit = self.__getNewId()
+
+ procUnitConfObj = ProcUnitConf()
+ procUnitConfObj.setup(idProcUnit, name, datatype, inputId, parentId=self.id)
+
+ self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
+
+ return procUnitConfObj
+
+ def removeProcUnit(self, id):
+
+ if id in self.procUnitConfObjDict.keys():
+ self.procUnitConfObjDict.pop(id)
+
+ def getReadUnitId(self):
+
+ readUnitConfObj = self.getReadUnitObj()
+
+ return readUnitConfObj.id
+
+ def getReadUnitObj(self):
+
+ for obj in self.procUnitConfObjDict.values():
+ if obj.getElementName() == "ReadUnit":
+ return obj
+
+ return None
+
+ def getProcUnitObj(self, id=None, name=None):
+
+ if id != None:
+ return self.procUnitConfObjDict[id]
+
+ if name != None:
+ return self.getProcUnitObjByName(name)
+
+ return None
+
+ def getProcUnitObjByName(self, name):
+
+ for obj in self.procUnitConfObjDict.values():
+ if obj.name == name:
+ return obj
+
+ return None
+
+ def procUnitItems(self):
+
+ return self.procUnitConfObjDict.items()
+
+ def makeXml(self):
+
+ projectElement = Element('Project')
+ projectElement.set('id', str(self.id))
+ projectElement.set('name', self.name)
+ projectElement.set('description', self.description)
+
+ for procUnitConfObj in self.procUnitConfObjDict.values():
+ procUnitConfObj.makeXml(projectElement)
+
+ self.projectElement = projectElement
+
+ def writeXml(self, filename=None):
+
+ if filename == None:
+ if self.filename:
+ filename = self.filename
+ else:
+ filename = "schain.xml"
+
+ if not filename:
+ print "filename has not been defined. Use setFilename(filename) for do it."
+ return 0
+
+ abs_file = os.path.abspath(filename)
+
+ if not os.access(os.path.dirname(abs_file), os.W_OK):
+ print "No write permission on %s" %os.path.dirname(abs_file)
+ return 0
+
+ if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
+ print "File %s already exists and it could not be overwriten" %abs_file
+ return 0
+
+ self.makeXml()
+
+ ElementTree(self.projectElement).write(abs_file, method='xml')
+
+ self.filename = abs_file
+
+ return 1
+
+ def readXml(self, filename = None):
+
+ if not filename:
+ print "filename is not defined"
+ return 0
+
+ abs_file = os.path.abspath(filename)
+
+ if not os.path.isfile(abs_file):
+ print "%s file does not exist" %abs_file
+ return 0
+
+ self.projectElement = None
+ self.procUnitConfObjDict = {}
+
+ try:
+ self.projectElement = ElementTree().parse(abs_file)
+ except:
+ print "Error reading %s, verify file format" %filename
+ return 0
+
+ self.project = self.projectElement.tag
+
+ self.id = self.projectElement.get('id')
+ self.name = self.projectElement.get('name')
+ self.description = self.projectElement.get('description')
+
+ readUnitElementList = self.projectElement.getiterator(ReadUnitConf().getElementName())
+
+ for readUnitElement in readUnitElementList:
+ readUnitConfObj = ReadUnitConf()
+ readUnitConfObj.readXml(readUnitElement)
+
+ if readUnitConfObj.parentId == None:
+ readUnitConfObj.parentId = self.id
+
+ self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
+
+ procUnitElementList = self.projectElement.getiterator(ProcUnitConf().getElementName())
+
+ for procUnitElement in procUnitElementList:
+ procUnitConfObj = ProcUnitConf()
+ procUnitConfObj.readXml(procUnitElement)
+
+ if procUnitConfObj.parentId == None:
+ procUnitConfObj.parentId = self.id
+
+ self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
+
+ self.filename = abs_file
+
+ return 1
+
+ def printattr(self):
+
+ print "Project[%s]: name = %s, description = %s" %(self.id,
+ self.name,
+ self.description)
+
+ for procUnitConfObj in self.procUnitConfObjDict.values():
+ procUnitConfObj.printattr()
+
+ def createObjects(self):
+
+ for procUnitConfObj in self.procUnitConfObjDict.values():
+ procUnitConfObj.createObjects(self.plotterQueue)
+
+ def __connect(self, objIN, thisObj):
+
+ thisObj.setInput(objIN.getOutputObj())
+
+ def connectObjects(self):
+
+ for thisPUConfObj in self.procUnitConfObjDict.values():
+
+ inputId = thisPUConfObj.getInputId()
+
+ if int(inputId) == 0:
+ continue
+
+ #Get input object
+ puConfINObj = self.procUnitConfObjDict[inputId]
+ puObjIN = puConfINObj.getProcUnitObj()
+
+ #Get current object
+ thisPUObj = thisPUConfObj.getProcUnitObj()
+
+ self.__connect(puObjIN, thisPUObj)
+
+ def __handleError(self, procUnitConfObj, send_email=True):
+
+ import socket
+
+ err = traceback.format_exception(sys.exc_info()[0],
+ sys.exc_info()[1],
+ sys.exc_info()[2])
+
+ print "***** Error occurred in %s *****" %(procUnitConfObj.name)
+ print "***** %s" %err[-1]
+
+ message = "".join(err)
+
+ sys.stderr.write(message)
+
+ if not send_email:
+ return
+
+ subject = "SChain v%s: Error running %s\n" %(schainpy.__version__, procUnitConfObj.name)
+
+ subtitle = "%s: %s\n" %(procUnitConfObj.getElementName() ,procUnitConfObj.name)
+ subtitle += "Hostname: %s\n" %socket.gethostbyname(socket.gethostname())
+ subtitle += "Working directory: %s\n" %os.path.abspath("./")
+ subtitle += "Configuration file: %s\n" %self.filename
+ subtitle += "Time: %s\n" %str(datetime.datetime.now())
+
+ readUnitConfObj = self.getReadUnitObj()
+ if readUnitConfObj:
+ subtitle += "\nInput parameters:\n"
+ subtitle += "[Data path = %s]\n" %readUnitConfObj.path
+ subtitle += "[Data type = %s]\n" %readUnitConfObj.datatype
+ subtitle += "[Start date = %s]\n" %readUnitConfObj.startDate
+ subtitle += "[End date = %s]\n" %readUnitConfObj.endDate
+ subtitle += "[Start time = %s]\n" %readUnitConfObj.startTime
+ subtitle += "[End time = %s]\n" %readUnitConfObj.endTime
+
+ adminObj = schainpy.admin.SchainNotify()
+ adminObj.sendAlert(message=message,
+ subject=subject,
+ subtitle=subtitle,
+ filename=self.filename)
+
+ def isPaused(self):
+ return 0
+
+ def isStopped(self):
+ return 0
+
+ def runController(self):
+ """
+ returns 0 when this process has been stopped, 1 otherwise
+ """
+
+ if self.isPaused():
+ print "Process suspended"
+
+ while True:
+ sleep(0.1)
+
+ if not self.isPaused():
+ break
+
+ if self.isStopped():
+ break
+
+ print "Process reinitialized"
+
+ if self.isStopped():
+ print "Process stopped"
+ return 0
+
+ return 1
+
+ def setFilename(self, filename):
+
+ self.filename = filename
+
+ def setPlotterQueue(self, plotter_queue):
+
+ raise NotImplementedError, "Use schainpy.controller_api.ControllerThread instead Project class"
+
+ def getPlotterQueue(self):
+
+ raise NotImplementedError, "Use schainpy.controller_api.ControllerThread instead Project class"
+
+ def useExternalPlotter(self):
+
+ raise NotImplementedError, "Use schainpy.controller_api.ControllerThread instead Project class"
+
+ def run(self):
+
+ print
+ print "*"*60
+ print " Starting SIGNAL CHAIN PROCESSING v%s " %schainpy.__version__
+ print "*"*60
+ print
+
+ keyList = self.procUnitConfObjDict.keys()
+ keyList.sort()
+
+ while(True):
+
+ is_ok = False
+
+ for procKey in keyList:
+# print "Running the '%s' process with %s" %(procUnitConfObj.name, procUnitConfObj.id)
+
+ procUnitConfObj = self.procUnitConfObjDict[procKey]
+
+ try:
+ sts = procUnitConfObj.run()
+ is_ok = is_ok or sts
+ except KeyboardInterrupt:
+ is_ok = False
+ break
+ except ValueError, e:
+ sleep(0.5)
+ self.__handleError(procUnitConfObj, send_email=True)
+ is_ok = False
+ break
+ except:
+ sleep(0.5)
+ self.__handleError(procUnitConfObj)
+ is_ok = False
+ break
+
+ #If every process unit finished so end process
+ if not(is_ok):
+# print "Every process unit have finished"
+ break
+
+ if not self.runController():
+ break
+
+ #Closing every process
+ for procKey in keyList:
+ procUnitConfObj = self.procUnitConfObjDict[procKey]
+ procUnitConfObj.close()
+
+ print "Process finished"
+
+ def start(self):
+
+ self.writeXml()
+
+ self.createObjects()
+ self.connectObjects()
+ self.run()
+
+if __name__ == '__main__':
+
+ desc = "Segundo Test"
+ filename = "schain.xml"
+
+ controllerObj = Project()
+
+ controllerObj.setup(id = '191', name='test01', description=desc)
+
+ readUnitConfObj = controllerObj.addReadUnit(datatype='Voltage',
+ path='data/rawdata/',
+ startDate='2011/01/01',
+ endDate='2012/12/31',
+ startTime='00:00:00',
+ endTime='23:59:59',
+ online=1,
+ walk=1)
+
+ procUnitConfObj0 = controllerObj.addProcUnit(datatype='Voltage', inputId=readUnitConfObj.getId())
+
+ opObj10 = procUnitConfObj0.addOperation(name='selectChannels')
+ opObj10.addParameter(name='channelList', value='3,4,5', format='intlist')
+
+ opObj10 = procUnitConfObj0.addOperation(name='selectHeights')
+ opObj10.addParameter(name='minHei', value='90', format='float')
+ opObj10.addParameter(name='maxHei', value='180', format='float')
+
+ opObj12 = procUnitConfObj0.addOperation(name='CohInt', optype='external')
+ opObj12.addParameter(name='n', value='10', format='int')
+
+ procUnitConfObj1 = controllerObj.addProcUnit(datatype='Spectra', inputId=procUnitConfObj0.getId())
+ procUnitConfObj1.addParameter(name='nFFTPoints', value='32', format='int')
+# procUnitConfObj1.addParameter(name='pairList', value='(0,1),(0,2),(1,2)', format='')
+
+
+ opObj11 = procUnitConfObj1.addOperation(name='SpectraPlot', optype='external')
+ opObj11.addParameter(name='idfigure', value='1', format='int')
+ opObj11.addParameter(name='wintitle', value='SpectraPlot0', format='str')
+ opObj11.addParameter(name='zmin', value='40', format='int')
+ opObj11.addParameter(name='zmax', value='90', format='int')
+ opObj11.addParameter(name='showprofile', value='1', format='int')
+
+ print "Escribiendo el archivo XML"
+
+ controllerObj.writeXml(filename)
+
+ print "Leyendo el archivo XML"
+ controllerObj.readXml(filename)
+ #controllerObj.printattr()
+
+ controllerObj.createObjects()
+ controllerObj.connectObjects()
+ controllerObj.run()
+
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/controller.pyc.svn-base b/schainpy/.svn/text-base/controller.pyc.svn-base
new file mode 100644
index 0000000000000000000000000000000000000000..7508c2517ba355f26fa53498d2c0eb5122afb288
GIT binary patch
literal 34851
zc%0pR4R9UTb>7{5{|^rY2!H^=-$z;$L7C!@ekzNitRIphX-N?MK$$WW`soq7ARhSe
z-ox%f1RPLFOgm{4E9p$*vEr&toZ5-4CY`2@nkG#<@nq7b(@Z9lX*=VlX)=?von+eS
zPug@kolbhbbMC#n?*|gCKE!SbV7Ytm-QD|h&bjA&=iIxgKN&6_y?*JH1*QM(q`#->
zFKnfh@|2pVqoX`mH5@hXm~&UnyXHKl=2PZ8t>)9_Jfr3_<~(c8Q>u|uD|t1aS1ScI
zUr;MWHD6RKLu!6VIVh1MG8%sxhKgM%DZ%<>b_7sd77&msg8a
z#R4wxD)q_vG36CGX~-sxE3d>!!!~I`c{`Lpp%&@6BQ|xH@}qry~xa(7d1%0b>f&=a_7s+FRSH4
z{JsY$#hE{>{KIPbL!9zqC;^LAuj!}l(u<~aNeWIJo}`-
zpuESF_YtnoeagSj-19i!bB6DE!uEo+?vbuN)O+2dnX?52j>in2a
znK3E2IEE(k*#q|M!+h3M;F7tS=fQYK=}hwd!
zr)z7`QY$!9F4q5y{>{#$>5gcK4i_5!irS}1
zT%hnuy;=8KE0Tc219F-{r5e89UchBa|D8kX3FIra$ui=utL`|sbJs2
zqCRWU;)5TFvUFB&dXyEqbXqR+(<`W6#r8?N7KHvBKaj7Zmb`F%r7?q&5lZ^>hNwg*
zL2K>iQdQp1{S^580OCvf$A|EvbU3-xTJcZ%L4D!Y$=j{qR@kmB_$R}KrCPliv|7>0
zu(cN0l=jBSg;p~PT8)MuoM>AR@1VtG8o(szjE?hs2^I%fHpWBHxO*g#emFbp^;VlZ$r1Zj(t62vUY*Uvf-
zyExDB`3{Iz6d2JGmP9W}SCPDxxf%3WR7lpBX~fZWWg0oVt|QZjoM?Q^7YC(Y~bLz
zhx+p#9-8Nee%;ZHD(FVtRA|@v>tpIphO5V|{gkU#UvutcRWzcON7ZH)Trs`LY{&nV
z)b!nyx|36zx!zX|^Q$IY{i+@B`>KCtUbS=USLM}azV}rl{Hi~6@2RVHcTq%K6d8t!CRZrvk)FT>PuB5@I!^1Z5u#CjMRL#Zt?gPp2ytt8glke>s)gmK
zRlecVL>#TP8-AJQTofp`7Ry|k?^{`GM0H!G89pB47u;yI8Z67HhBFgJU*HB+U`s>?
zAapzCvuagDz3)}I96x8a)%2yKpsaiX=@){a6>w$~H?tnnZqy@wU5)Be;(ns1)*4lx
z9wjZ_XiHgcPGt%*`aV-H?mC_axZ9|6Dtl32KMLTn4U)L55YXdzdSm%sL2pTOax!hb
zUS+OuH*j;Bd^4A=7cAb=wb^
zAS-83IAbZbvoIGKZ09f=lJ4Gq2PY-&nGvTzG%@BD-32gDI@vv_#-`E#B1el%EhbaC
zV-n+?whb8VY(?6(aXXurwPXLTGJ3g-)-m0tbnCcfOLpKz>w*C!77uG#k*H2Q*p%hy
z44E7<$t0s=C6ajVBkcf5+&Sp>*}kI-YOOF+Oc*IfY*(Bq>QAOQUynx^%u|
zWpyu;!iwqqyN!yR)t8=mW>ecKxvjcf=94^&qs98owZP}H-1Q`FyKmu<_^9oFE59n|
z22Q=GM&Q>x>gHdK*>lXn&)(Dl$C^6UdO!`O<;zObvGfa$DYckZlNT?=W?Oh#C9J(y
zkA&CHlrcM(pDZ5%Z@mbccR%gWI$s#>||9sY6gQ%KX#Mj>4qDrF1#!VrTAFSSWSit4Rqe=ykT)!41
zETCEkploGsX50uh+u~k0Vn%hs5yJBNB&Ef3H7ybV3_Z(=-6Xn6OrNPyD)`ZHKp5D2l0!(kv4)&
z+6O)-lT)Sy5Y9_CmZ7h17sm=0lJuPQZ(sKQZOpPfH=y6`y!$EDt1mL-&tB$NC8Hiz8~asIh{%YYA00WohM@5g7^XYghH(C`YG9h(2HWzH-j@GwWi_!;(&4jircdi1Q-a>;)*p#me^;3fn29?;(zob_Gkv;Y
zN3t8(P_2Ao;KRPVxABWXYlUBzcM`oYM!hg3z0hIB9JHj`;o9KF3ijDyuU<2)O;{~2
zqqU`EYpE8jUktXbJGq~7rvV92SXL!e`U{p;L7Zt!NI1y=QC^nOl))u+AgxHF
zNAtu~UCwCO*`fcE1Irv#?a(CS*_t&{(SVPd?%_GF)^7VvPbj00X
zqa~o%3>2%%bMHkftZ9+-V&6g33PgahMSsz9E%R@+ld+#w39Cp`6+`{!wuiD%n-@S?
zWldT9lRn^(9CLTO!!)N2(-mDO=Qc}gm(_cMJHqda89+Sid-ZUfzdp*2WXAy0tEcs-
z2mth91;5?LQdKZR$xKw1~Dw)UoxvGHBZsbR}p3a9=cyW)*`F0vBrXB_SZ
ziA3ixUdP_UmYIvC>lbRxW-EdtZ$Uzb!~i9xfZ|Y#S9zzBn6E-t!mhP2W3FemV5d
z6jwH`1g&L%0jQlmn>iMzo(M^;l&5?g51HwB8A)aJk%+;hr8=4k7~n^2Dr1(sD&ZyrNJu=(slGAYAnq7aDwS`|DU2=E12OM0@
z&P=1e;IGQZl+kordVlpaLB;e
z1mS1Djb|NKJ-}kVkS>%MUL4||LLpZwm2z~pzc9p|cSTRO{ZYnY$D)i=j51C!$~eU+
z;}nN1O#x-RDJbIhP)Z90O#t
zf^dxO!kEx?Y#d$D6XBPgUJz^>;M(nMROJdi;;Vhy@$Ci}zy1O0^u#s}KISSK`pe$W
zCMt%(LtU&b_Am9IyLQAoDPVF6p|pJpxN(7$(f1`>Zyo}X5}RxyknXP0@RXq887LVR
z;K36~>1H%M%eX)Wp=GS)r*Z#d^nlf6bq$({8+%YYVg?<)OvNTkY|=5IR$c_PDoe7t
zPLd4`$%)LaT9a0N*^}}XR22X}B_ZZ6pxw%Zt$}ur8+uncy16HMn#*%s)vUnQ+9#>0p>%P=@k84nzlnH4`
zYdvq1W67#{qYD-oL=c#>ta%s(5MiHe&4){^wT1^fQk#YXu245I
zxOgPQX=T##kEb-&+iJ5S$s;vnC@;470>9m$0qVx^0wWDsyffVz_|`H|0zcmB#=-jz
z{=K6EEL3VY8GI#1Scd8UUB;KdYN*9rtgw1Sy}v&}rg~W$M{MoHKIgboMOkG={+zw!
zPWY~YGehiau$>;FRXWlDz6Pytr*w09rP2YFKuV^QLitU_(69)m@L@Xe+8z9R#`EIH
zXAV9-9IQ1D$9RS<$*M!58(!-WWlVIpZr6gFVP$3DB!GA2U4y8nhiT~ft*pu+EpNvA
zs_g{r3RK1|mVHr*EFI
zMA*a^gn_%XYMz;x5${??i@=VJh6^X)*SDJR*LNWyjNxw%f>8AKSO$nu~D1q&mieK}<
zge<6V;RiBruHx_+Wu{12Nqv15F|9B;eb!RVA`Z;SvCE>Dy-Ziqxk%5dvk-)$Vy2A{rTeaF
zEi^CTFJgnR{s-z~SYP^%dyLU=0N0h*ZO>vR5G_BRgBmzAO$PVu;OBSdh$Pw{zUU_4
z{(?5sMyR)^jFtzgD3~7q1?h1jy!CfVS8Ig64CYlkwj9#6-wYSuwNPs`WVjh<
zvoH=nq#jmVw`5d*00%hx^!l;7UK1P+mXpxX*D$*KcyzNgwpp6$4$$~cxuw)D2fS6t
zjk>+-+hIYkU$DCT86#*MGmI8^U=9y`vB6d@_ouEuHUb;Eg<5f%QXg#QE2F9Y5Y-qZNMW|n|5$xn
zV5?25|C{9$T2;tkwt+I8PppEp;8g)L6;6s~-TaVQ)y|7ba59Xg<2c#DJwAf9+;19*
z$}`(N;#!r@D-CcQ36t76tK*}V0x@8sdUr}XUX9ucdBSVgq9q2oYBxeYhr|n`S`eMb
zDr4mMO^?rQ&Q&bT);TzjX`2D$n&(y4nlS`6WT>cH;J%H+U&rCcarg-wzHHg#2L?`e
z5W!z{b+lwJHYQxMD@Mo=mxM+alVtfX6w^pdmiaBnGT%v-jv-428y;w~bcihTn(AV*
z%y*Kd(@B>3Zvjx%G+8hdm?TccW?^9)C~&wB1;&DK%TbT12*e@_Svv@+XbI^a$miJh
z(9qNLh+lPe?DZBj)JZ`DiP~nj);7YZteO0t1q~TC<(fl(D;V0}?Ib``*%%2ls@$Zz
zM^Jn1-__WC%89cJCOg$PyJ)i0oITW)T{793zS+YjTl@w)y0S-1b}o^<{**>o*xos<
zzKf>S#gMxR3|z3tm|EkI>d{W(-P=jQ`wbb3++;oR
zwfCiYu}>m@B@`_jnr^oV~KTcW$&gO2@ir=4Sc=xJXU
zJ>6AKa&d}d!BQc#O%ufHW$n01cFts{`)21&HluggAg3d{XtJ|?vxnj(?Z_^5We=O|
zd?H)ZRG}|TxrU|~(V&~`o;J%uQl+X=+CoO?^O0Vr`x6kvKN*y+!C(aClEjs(jVd
zWw2!QH|P<63No5xG8%J=y@b?*^1l3SLwVB%<$V)`^DSVvKOxxdTlbFL>acWyir?k3
z!z=+Eqf|;t$)t>!lwp%HYEpKXl$|DJ#H5U=)pzkLK%_{uewH$#ffZS!S;ks-CYVaj`#19z|suMK;Uam&`qYaa08UK`7#=qM{(N1%*F%w#Qm}6-jj;@_B
z(Y3owbgcx^9zd9_gx30H?7WKdhp_)D5)Wg`QJj1TTd3mXK5W8@lOx!Q6({#&Lspy|
z#kQK)zI+e#W79~*`c|tZJCQUFa`XIfA*i>Z
zv&*8b6*KB5QC@gp3*Of+}NihrKC__%V8mvj+Nmukh
z-D5=ZiGlYOf@PmWUyX8Kjkx2~UqxPAocYcPo&7}WJ1TUR0pR&Wo$w#5W4o{w+}FKE
z*#PgdUnF_%+0|Y@dgqSq|~*g7f819jv>;p6-0?WCGwV)fiv^0
zK$Ok&$}z9d7n=UB)(lO@U@A-cyrH%wFb
zerM7xIy<)5By7vo=UZ(O))iXu(<&KD(Va2SRziCSQz~9>TW}VP<
z*)FbOS77SkYyC7mVgt2KbFHb)ILYZhHYOL9h0*d@__k?UmKRzF$XeeRn^*0VtqM}G*l?j+hXonw`>)U
zd5n_5&eGIwgE7DmLBi=W@O?Hgc>}%G?|36+eF(AxB0`8j5Yj@qaF5X9m>z0oayXjo+bY-4(+WvGIqj;ogMjiaQL}F6Qt=XBZ)pAYZs=Q
zdUdVimaD9S0bOCnq!*DWh$O=Gski9KmSzXuHFz(`M`!&jrD!ay?Q%c$3xECTPD0?=jUVhJ1Y8b&uHjexN^&mdfL9`j
zoiVLjL*qZHq&M*a&D_BueS%=B2YAmp<5mnG#{gWsM4desu{{!p)A7JiXY2H=mIkK#VR9>z%J$g!cfxV}Cj{}-i
z1AbDICx{h4T55Sbt5dxN6|fFe4#qY0s{B=DP{O~a%q~R>3w{`~+2qxOrU`z#R(hBPtr@
z3hXp)f|Oc+Sw5`5;jfadHR>_z7NCo9!|%r&?bpw!>NqpFiMm9w3D&Mx|C2=Y$t!nt
zzB0?N%*rcsI$OTbfLG?^mHEUg-!`wzn^)$|EA#f1H=JvlX(y9RJC)?p&TTz}^I(V)
zTcHebq%S3exj;a?&3+jyhi~riF1|#eiyLx-?Bd%c!iB?lYyD1ss{ESaI+5dFH$21a
z!e7#1E{$q84NL)3uiKZw(**l1*yxM>795qpfr4$rZxU>5*{||X6n~i^w(=5T?;X~k
zSz+<6xuI*fD8^cDY|m_j#{4lj_&js4;oLFiSpcgknx9g1m2pSNR-hkuulPW)&e)ym
zx=KVySPtiqyneCtiz$wuKV-aeX_@wI6uk~v{cuMVJzB2q^4?JT7^;@|`Rsd6`dy*(
zgYR6t;9xp|R3mJD(&@ESI@T2%m3A_=RIE1Tyth8fF{fYK?q=aFc(XRWCi_56;7Dk0
zN-KpTkDM;diRY0}uMlVF0+#NsMRWx;B*w^j-<=!FmuHz*@%@T{qa|S8YL(KOL|G4}
zJJsHfH4e8iSnaOCs&<%_n6k`drA^E;2z$5tFHzRCUe}d2-eSj`C)PY{ifY_xnaXlR
z>uivr=TK!vZDC09-kULgrJEJwDy-@AcR*g&*pn<5;;mKIkaT$#2rY}owU@Z-3-*?Q
zcRo~MT}QnN;&j?NEhfphA9J#)VW*TTi2)3LvMV5d+mVP9r5e2AK|cHznXaWNemcHL
zB`?zQ#UhT{5P<`gKw^W)e#S+Pr@nLyHR_nrjM=a`{602BJPr$3F6!qjl5TQ`SBP!u
zIFMupe~rm2^6;1VIIKBj@-dw`1c+ssKk6hQ05(U|j-7GB4xp7ZZ_p$z6SOT&
zh~hFkO*eVBC44t(H{Um{n{`*EMNI5rQpa}%yFMqxOS&Gwzp`iyt%ZfPAn-{!hX!Bf
zEH<;H(2h6)@+KpQDj#Wa&Qg?xzq|HOfQmxhg>7tMrl&d
ziAr0+hGd~yCr+}|1MlEV46-8{G#4oXaz%KpTw#_kve-*3K|WLDje}l2UyEvGgzxes
zc0HMD7m86T`1sX1gz#bwnN0@Myn2C5m1JU~EWS0=Q#O$(U&tUkq;^x{g2Of0hAc1V
zQ9U9XgcTkvyJo{AY%SdK+
zHAB8Gx9Va?g^}k6LFFIYNkYpF7EskH>4h-as#Vs=3^2Gv!*ye$X*RIdDSeDB(a#tW
zIHfcQ+icxt#7)5Ft%CAu-b!8E;B#D~*%m&WD8bZz(|d;GS(J!u#oWudKQgQSO0C|g
z{H}Q;8u+hJ>UVJX*GgliVz%Ku0~fQhAJh`ru?_jA)w#4@J^}!B+!^NYFAZb08EJxP
zlDyN-erJ!f)7ekyS*J*6=4XQUnL+4CFNlSqOngPiwqd(qEA$vXX|)#m-in>NzXK{(
z;EK&ft#;e@+I?zf6(-chLhiv8F^1P4!DJR(1jHhNZ;mY!KBBH@b%On0!GyZ9I-%(I
z8clK+FLmVknCoaZ%g{uX)!R6-i^pzp5b#G(!}6)}?Ipiij`*{1WQLF&V8DgJmQWgU
zynMRM8!FzehrWFROQ|dRmT)b^hReQp^GiR5f4}%txGRwz_*i6DuQlqQ_PuZvi*%pk;1l!!S>PTtMa5e8GQcZhM^
zj*pEdVi#C=#v1xJ2Hu7t7C9CS`+P#3?ORhpaX;fGK8qS6%!@%a{fZOuE2_12{Y2bB
zSC?SP((D^X_}}c@$=hSf_ewF{k*K`9(iV%>_gMUFXP6LM*j?L%{^c&U-uZLxhsuB3
zM!GehRY
z>Q+$&ZvlvuXI`5_%2-Zmc&I|<`wz_UKcu!nK4Q{
zgPf)8vxlC0rFf2op0IQf#kmoL6oPFkn
z^0`aTT%Ijosl0UV!ra{D*^AJ;%QqGO`~9aX|3PUh&xrp;nis+)-{V;M${*r@FYv?;
z^UBZKnc%PBfbe8CcAxh*ZnSEFcbTM15UjN$S+2y})L`m~jp2m;Q~9qb!|QY7*p0u1
z!xwP)+e+(jl`ks&Ii0}*>0JG{L9)*=$vObg>CfS4rGlGvhf~9Diqb|&IU|*fRIZ{k
z&Sxn)Ls}t~b$K=-19=!RO+8uq;~x=D*}k(xO>gT21DUhvJh-Zw0raD+8bFbT8fP?N5O-Eq|Q-@^f$C{%tC2YeGy
z>;PWp4XsdM|}tXnD;MtN2Eu0pnu8QU>7RLIa-exxW{E0+$G9xW6oEnOHZJy1x|
z&$L-bUU)=*v5qVmvc7oVq&ffQTGMNlulixs<+qc-SJ*nIA3rTt9`hrWJat+|jaRUO
z_dd~TL}YQYktUyNCwuo~P`l0lvq8pBf9TZd(F63H}lRKElGH>$JG-
zs4OgaF=FF#r{vSN=!;Lo#>LYfIi;^_>!MOFwQiG908oP!;tPP=Z`6GZzuzd=f`z5}
z>#g!DFTTKF$qW8QpRAeVrXAI)*IFPO{`b*R=5Sc!m4BnO=$D}|YKWNL;A5h!6Mhu<
z{t4|Mxk~5a5M|NCT4l<-1*N^#N+sR%#FdukH)LTITNUi6<%x$Esjy>*-98*%aM^SZ
zybR)C<-J=h=K(~0%8HbCtz3cBVKAgC{Ph$s2jn{PrW7>9uXQFo)bF;_i2|n+5~)i_
z4_vA+^_-QjQ+|}=gc~efuwYjIxQCrl64;||AvgZ_$A5nO&s28uD|CFP#F4iJcb_}r
lWD`FH_kcU*?86@&chlbiXJ2|ZuH?tfxWjJ78BSpu_&?w|k*fq-cRh7~!uAPz+Ab&10(gU})XL^Cvr5(!n}LPCv5kboeoEHpCc!zOrj7FysnSZIUS
zWT69Iiv@f{n}rSVIxO_SI_+;D2v=mVNW*&s?TlEViVPSFn4@w~tE!Ss<_6pfFi;ws
zq#NF3eWDI=)vkjtKsAWU4*e6bL(5GfdD^Fk94V6?qoSB~8#}X9_FMGOCJn4GKfF*i
zoN4vpIe3KahrY6H%gAp{rP_Do6m?ApK1*hjg~Q05un>?yk9g_?crRJb)rRR4VGTnD
z=c-FE(1c1R_9dH|Y{f%L)*6hWsT|0}cPE3FQ8Gzm$CZQB9XWoOM3EY#(JU!e;_HE1
z*xz=Xmhyi16u^Vg}o1!avhD&6OMeV<#wLfPApb~dkZ-n>ABET$Kbc#jhV;{77
zIowrZW`)_dCj;BwqGJU^e;x88(0Ca#x`CnCRmSYkyV;J(J9o*Db*xSvSB`r*^AlOJ
zU$Be5Q))PZWkY$(D3-r&E(zxXy@w2aoxZ&Lh(S
z>#8MMMyt%oMy|0|;T*R_nbxz`Kzo_(1pbS4rl-ut)+`LMF7CtYskp$}Uc}m21Z%wu
z>#Y_o2Kf|=bUKpWw|7vIcbGZK-y!cXFuJaO1MPL%-S&UJgd40MB6GT%3bh&Y3i%wm
z>qJ1Z2bT{a1i0Gg+iLn}J8)yd+=OwRJelsBz~u?uM~e;WTqZS0PN=2A6>L;+7r$qC
z*cm%B;XCqSDQ>g2pid^SxNB&atA~E76a{;nMDBC!PO$GgM^E1OUB$Wkg%iwV%Bs1L
z>L83~>cC_7_Cx(kTt1Fv;wV1~@t1re;ZWDH?q)(~Ds`FUbon9eQ6#Am=C|kB0~xBH
z9pB7$k7L|fy`70ac2g%>1?eG8@3Wzs;!V*J_l%m@!q%on?MW;fC6Ps)C+1?Ttey06j;Z-lfYbmrIuQ{}O+EEr^x_4kMDftT>Ul=a8TGa-W
zi5=Zf=lfd@KQsmgT9(tx;^vdjYQKY=qV=c
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/mst_blocks.xml.svn-base b/schainpy/.svn/text-base/mst_blocks.xml.svn-base
new file mode 100644
index 0000000..6426f5c
--- /dev/null
+++ b/schainpy/.svn/text-base/mst_blocks.xml.svn-base
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/schain.conf.template.svn-base b/schainpy/.svn/text-base/schain.conf.template.svn-base
new file mode 100644
index 0000000..77dce17
--- /dev/null
+++ b/schainpy/.svn/text-base/schain.conf.template.svn-base
@@ -0,0 +1,8 @@
+#Copy this file to /etc/schain.conf
+
+[schain]
+
+CONTACT = miguel.urco@jro.igp.gob.pe
+MAILSERVER = jro-zimbra.igp.gob.pe
+MALSERVER_ACCOUNT = notifier-schain@jro.igp.gob.pe
+MAILSERVER_PASSWORD =
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/schain.xml.svn-base b/schainpy/.svn/text-base/schain.xml.svn-base
new file mode 100644
index 0000000..a671bc5
--- /dev/null
+++ b/schainpy/.svn/text-base/schain.xml.svn-base
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/sousy_processing.xml.svn-base b/schainpy/.svn/text-base/sousy_processing.xml.svn-base
new file mode 100644
index 0000000..d40b9a1
--- /dev/null
+++ b/schainpy/.svn/text-base/sousy_processing.xml.svn-base
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/.svn/text-base/speedTools.bash.svn-base b/schainpy/.svn/text-base/speedTools.bash.svn-base
new file mode 100644
index 0000000..70024c9
--- /dev/null
+++ b/schainpy/.svn/text-base/speedTools.bash.svn-base
@@ -0,0 +1,11 @@
+#Use this script in order to find the slowest module or function in your python code.
+#Reference: http://lukauskas.co.uk/articles/2014/02/12/how-to-make-python-faster-without-trying-that-much/
+
+#!/bin/sh
+
+script = "testRawData.py"
+output = "profile.pdf"
+
+python -m cProfile -o profile.pstats $script
+
+gprof2dot -f pstats profile.pstats | dot -Tpdf -o $output
\ No newline at end of file
diff --git a/schainpy/150km_jicamarca.xml b/schainpy/150km_jicamarca.xml
new file mode 100644
index 0000000..95c5465
--- /dev/null
+++ b/schainpy/150km_jicamarca.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/DBStest.xml b/schainpy/DBStest.xml
new file mode 100644
index 0000000..9573a59
--- /dev/null
+++ b/schainpy/DBStest.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/JASMET01.xml b/schainpy/JASMET01.xml
new file mode 100644
index 0000000..18f18b6
--- /dev/null
+++ b/schainpy/JASMET01.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/JASMET02.xml b/schainpy/JASMET02.xml
new file mode 100644
index 0000000..4ad0cde
--- /dev/null
+++ b/schainpy/JASMET02.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/JASMET04.xml b/schainpy/JASMET04.xml
new file mode 100644
index 0000000..9e2f34f
--- /dev/null
+++ b/schainpy/JASMET04.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/JASMET05.xml b/schainpy/JASMET05.xml
new file mode 100644
index 0000000..0a2bc25
--- /dev/null
+++ b/schainpy/JASMET05.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/ProcBLTR.xml b/schainpy/ProcBLTR.xml
new file mode 100644
index 0000000..63dcb27
--- /dev/null
+++ b/schainpy/ProcBLTR.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/SA2014050.xml b/schainpy/SA2014050.xml
new file mode 100644
index 0000000..ade1ed6
--- /dev/null
+++ b/schainpy/SA2014050.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/VERSION b/schainpy/VERSION
new file mode 100644
index 0000000..a19b1a9
--- /dev/null
+++ b/schainpy/VERSION
@@ -0,0 +1,85 @@
+VERSIONS:
+
+2.1.2:
+-jroutils_ftp.py: Bug fixed, Any error sending file stopped the Server Thread
+ Server thread opens and closes remote server each time file list is sent
+-jroplot_spectra.py: Noise path was not being created when noise data is saved.
+-jroIO_base.py: startTime can be greater than endTime. Example: SpreadF [18:00 - 07:00]
+
+2.1.3:
+-jroplot_heispectra.py: SpectraHeisScope was not showing the right channels
+-jroproc_voltage.py: Bug fixed selecting profiles (self.nProfiles took a wrong value),
+ Bug fixed selecting heights by block (selecting profiles instead heights)
+-jroproc_voltage.py: New feature added: decoding data by block using FFT.
+-jroIO_heispectra.py: Bug fixed in FitsReader. Using local Fits instance instead schainpy.mode.data.jrodata.Fits.
+-jroIO_heispectra.py: Channel index list does not exist.
+
+2.1.3.1:
+-GUI: every icon were resized
+-jroproc_voltage.py: Print a message when "Read from code" option is selected and the code is not defined inside data file
+
+2.1.3.2:
+-GUI: user interaction enhanced
+-controller_api.py: Safe access to ControllerThead
+
+2.1.3.3:
+-Colored Button Icons were added to GUI
+
+2.1.4:
+-Sending error notifications to signal chain administrator
+-Login to email server added
+
+2.1.4.1:
+-Send notifications when an error different to ValueError is detected
+
+2.1.4.2:
+-A new Plotter Class was added
+-Project.start() does not accept filename as a parameter anymore
+
+2.1.5:
+-serializer module added to Signal Chain
+-jroplotter.py added to Signal Chain
+
+2.2.0:
+-GUI: use of external plotter
+-Compatible with matplotlib 1.5.0
+
+2.2.1:
+-Bugs fixed in GUI
+-Views were improved in GUI
+-Support to MST-ISR experiments
+-Bug fixed getting noise using hyldebrant. (minimum number of points > 20%)
+-handleError added to jroplotter.py
+
+2.2.2:
+-VoltageProc: ProfileSelector, Reshape, Decoder with nTxs!=1 and getblock=True was tested
+-Rawdata and testRawdata.py added to Signal Chain project
+
+2.2.3:
+-Bug fixed in GUI: Error getting(reading) Code value
+-Bug fixed in GUI: Flip option always needs channelList field
+-Bug fixed in jrodata: when one branch modified a value in "dataOut" (example: dataOut.code) this value
+was modified for every branch (because this was a reference). It was modified in data.copy()
+-Bug fixed in jroproc_voltage.profileSelector(): rangeList replaces to profileRangeList.
+
+
+2.2.3.1:
+-Filtering block by time has been added.
+-Bug fixed plotting RTI, CoherenceMap and others using xmin and xmax parameters. The first day worked
+properly but the next days did not.
+
+2.2.4:
+-jroproc_spectra_lags.py added to schainpy
+-Bug fixed in schainGUI: ProcUnit was created with the same id in some cases.
+-Bug fixed in jroHeaderIO: Header size validation.
+
+2.2.4.1:
+-jroIO_usrp.py is update to read Sandra's data
+-decimation in Spectra and RTI plots is always enabled.
+-time-window option added to GUI
+
+2.2.5:
+-splitProfiles and combineProfiles modules were added to VoltageProc and Signal Chain GUI.
+-nProfiles of USRP data (hdf5) is the number of profiles thera are in one second.
+-jroPlotter works directly with data objects instead of dictionaries
+-script "schain" was added to Signal Chain installer
\ No newline at end of file
diff --git a/schainpy/__init__.py b/schainpy/__init__.py
new file mode 100644
index 0000000..0e5d2a9
--- /dev/null
+++ b/schainpy/__init__.py
@@ -0,0 +1,7 @@
+'''
+Created on Feb 7, 2012
+
+@author $Author: murco $
+@version $Id: __init__.py 1436 2016-04-27 09:33:27Z murco $
+'''
+__version__ = "2.2.5"
\ No newline at end of file
diff --git a/schainpy/__init__.pyc b/schainpy/__init__.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..67ef1fb3577917f9a99b9f4f60ab8e3574857ecc
GIT binary patch
literal 314
zc$`g-QA@)x5XaLE=covNggo@253cRfxndbo5rn;*0d<$dX{oY*Ug{*@yL0IN!aF
zq8{8YM{@sv?xtUt{^$4cMUXK(%mUM1AtWIs(j%ou_zy;LrzF)aeN;P|
zT~n4UneP|8ca=6YxIdjaZF(a#4gBI=8Czp}u$4IlsN32BMBRZdSLu3CuNTQ`!7`fM
z=4qO" + subtitle.replace("\n", "\n") + "
" + message.replace("\n", "
\n")
+ message = "\n" + message + ''
+
+ # This is the textual part:
+ part = MIMEText(message, "html")
+ else:
+ message = subject + "\n" + subtitle + "\n" + message
+ part = MIMEText(message)
+
+ msg.attach(part)
+
+ if os.path.isfile(filename):
+ # This is the binary part(The Attachment):
+ part = MIMEApplication(open(filename,"rb").read())
+ part.add_header('Content-Disposition',
+ 'attachment',
+ filename=os.path.basename(filename))
+ msg.attach(part)
+
+ # Create an instance in SMTP server
+ try:
+ smtp = smtplib.SMTP(self.__emailServer)
+ except:
+ print "***** Could not connect to server %s *****" %self.__emailServer
+ return 0
+
+ # Start the server:
+# smtp.ehlo()
+ if self.__emailPass:
+ smtp.login(self.__emailFromAddress, self.__emailPass)
+
+ # Send the email
+ try:
+ smtp.sendmail(msg['From'], msg['To'], msg.as_string())
+ except:
+ print "***** Could not send the email to %s *****" %msg['To']
+ smtp.quit()
+ return 0
+
+ smtp.quit()
+
+ return 1
+
+ def sendAlert(self, message, subject = "", subtitle="", filename=""):
+ """sendAlert sends an email with the given message and optional title.
+
+ Inputs: message (string), and optional title (string)
+
+ Returns: void
+
+ Affects: none
+
+ Exceptions: None.
+ """
+
+ if not self.__emailToAddress:
+ return 0
+
+ print "***** Sending alert to %s *****" %self.__emailToAddress
+ # set up message
+
+ sent=self.sendEmail(email_from=self.__emailFromAddress,
+ email_to=self.__emailToAddress,
+ subject=subject,
+ message=message,
+ subtitle=subtitle,
+ filename=filename)
+
+ if not sent:
+ return 0
+
+ print "***** Your system administrator has been notified *****"
+
+ return 1
+
+ def notify(self, email, message, subject = "", subtitle="", filename=""):
+ """notify sends an email with the given message and title to email.
+
+ Inputs: email (string), message (string), and subject (string)
+
+ Returns: void
+
+ Affects: none
+
+ Exceptions: None.
+ """
+
+ print "Notifying to %s ..." %email
+
+ self.sendEmail(email_from=self.__emailFromAddress,
+ email_to=email,
+ subject=subject,
+ message=message,
+ subtitle=subtitle,
+ filename=filename)
+
+ print "***** Your system administrator has been notified *****"
+
+class SchainError(Exception):
+ """SchainError is an exception class that is thrown for all known errors using Schain Py lib.
+
+ Usage example:
+
+ import sys, traceback
+ import schainpy.admin
+
+ try:
+
+ test = open('ImportantFile.txt', 'r')
+
+ except:
+
+ raise schainpy.admin.SchainError('ImportantFile.txt not opened!',
+ traceback.format_exception(sys.exc_info()[0],
+ sys.exc_info()[1],
+ sys.exc_info()[2]))
+ """
+
+
+ def __init__(self, strInterpretation, exceptionList=None):
+ """ __init__ gathers the interpretation string along with all information from sys.exc_info().
+
+ Inputs:
+ strIntepretation - A string representing the programmer's interpretation of
+ why the exception occurred
+
+ exceptionList - a list of strings completely describing the exception.
+ Generated by traceback.format_exception(sys.exc_info()[0],
+ sys.exc_info()[1],
+ sys.exc_info()[2])
+
+ Returns: Void.
+
+ Affects: Initializes class member variables _strInterp, _strExcList.
+
+ Exceptions: None.
+ """
+
+ if not exceptionList:
+ exceptionList = traceback.format_exception(sys.exc_info()[0],
+ sys.exc_info()[1],
+ sys.exc_info()[2])
+
+ self._strInterp = strInterpretation
+ self._strExcList = exceptionList
+
+
+ def getExceptionStr(self):
+ """ getExceptionStr returns a formatted string ready for printing completely describing the exception.
+
+ Inputs: None
+
+ Returns: A formatted string ready for printing completely describing the exception.
+
+ Affects: None
+
+ Exceptions: None.
+ """
+ excStr = ''
+ excStr = excStr + self._strInterp + '\n\n'
+
+ if self._strExcList != None:
+ for item in self._strExcList:
+ excStr = excStr + str(item) + '\n'
+
+ return excStr
+
+ def __str__(self):
+
+ return(self.getExceptionStr())
+
+
+ def getExceptionHtml(self):
+ """ getExceptionHtml returns an Html formatted string completely describing the exception.
+
+ Inputs: None
+
+ Returns: A formatted string ready for printing completely describing the exception.
+
+ Affects: None
+
+ Exceptions: None.
+ """
+
+ excStr = '
The following Schain Python exception has occurred:\n
'
+ excStr = excStr + self._strInterp + '\n
\n'
+
+ if self._strExcList != None:
+ for item in self._strExcList:
+ excStr = excStr + str(item) + '\n
'
+
+ return excStr
+
+if __name__ == '__main__':
+
+ test = SchainNotify()
+
+ test.sendAlert('This is a message from the python module SchainNotify', 'Test from SchainNotify')
+
+ print 'Hopefully message sent - check.'
diff --git a/schainpy/admin.pyc b/schainpy/admin.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..254125f882b6da9840ef8be66373c5090878f900
GIT binary patch
literal 12424
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
literal 0
Hc$@
\ No newline at end of file
diff --git a/schainpy/bltr_reader.xml b/schainpy/bltr_reader.xml
new file mode 100644
index 0000000..b7226fb
--- /dev/null
+++ b/schainpy/bltr_reader.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/schainpy/controller.py b/schainpy/controller.py
new file mode 100644
index 0000000..36d8ad8
--- /dev/null
+++ b/schainpy/controller.py
@@ -0,0 +1,1294 @@
+'''
+Created on September , 2012
+@author:
+'''
+
+import sys
+import ast
+import datetime
+import traceback
+import schainpy
+import schainpy.admin
+
+from xml.etree.ElementTree import ElementTree, Element, SubElement, tostring
+from xml.dom import minidom
+
+from schainpy.model import *
+from time import sleep
+
+def prettify(elem):
+ """Return a pretty-printed XML string for the Element.
+ """
+ rough_string = tostring(elem, 'utf-8')
+ reparsed = minidom.parseString(rough_string)
+ return reparsed.toprettyxml(indent=" ")
+
+class ParameterConf():
+
+ id = None
+ name = None
+ value = None
+ format = None
+
+ __formated_value = None
+
+ ELEMENTNAME = 'Parameter'
+
+ def __init__(self):
+
+ self.format = 'str'
+
+ def getElementName(self):
+
+ return self.ELEMENTNAME
+
+ def getValue(self):
+
+ value = self.value
+ format = self.format
+
+ if self.__formated_value != None:
+
+ return self.__formated_value
+
+ if format == 'str':
+ self.__formated_value = str(value)
+ return self.__formated_value
+
+ if value == '':
+ raise ValueError, "%s: This parameter value is empty" %self.name
+
+ if format == 'list':
+ strList = value.split(',')
+
+ self.__formated_value = strList
+
+ return self.__formated_value
+
+ if format == 'intlist':
+ """
+ Example:
+ value = (0,1,2)
+ """
+
+ new_value = ast.literal_eval(value)
+
+ if type(new_value) not in (tuple, list):
+ new_value = [int(new_value)]
+
+ self.__formated_value = new_value
+
+ return self.__formated_value
+
+ if format == 'floatlist':
+ """
+ Example:
+ value = (0.5, 1.4, 2.7)
+ """
+
+ new_value = ast.literal_eval(value)
+
+ if type(new_value) not in (tuple, list):
+ new_value = [float(new_value)]
+
+ self.__formated_value = new_value
+
+ return self.__formated_value
+
+ if format == 'date':
+ strList = value.split('/')
+ intList = [int(x) for x in strList]
+ date = datetime.date(intList[0], intList[1], intList[2])
+
+ self.__formated_value = date
+
+ return self.__formated_value
+
+ if format == 'time':
+ strList = value.split(':')
+ intList = [int(x) for x in strList]
+ time = datetime.time(intList[0], intList[1], intList[2])
+
+ self.__formated_value = time
+
+ return self.__formated_value
+
+ if format == 'pairslist':
+ """
+ Example:
+ value = (0,1),(1,2)
+ """
+
+ new_value = ast.literal_eval(value)
+
+ if type(new_value) not in (tuple, list):
+ raise ValueError, "%s has to be a tuple or list of pairs" %value
+
+ if type(new_value[0]) not in (tuple, list):
+ if len(new_value) != 2:
+ raise ValueError, "%s has to be a tuple or list of pairs" %value
+ new_value = [new_value]
+
+ for thisPair in new_value:
+ if len(thisPair) != 2:
+ raise ValueError, "%s has to be a tuple or list of pairs" %value
+
+ self.__formated_value = new_value
+
+ return self.__formated_value
+
+ if format == 'multilist':
+ """
+ Example:
+ value = (0,1,2),(3,4,5)
+ """
+ multiList = ast.literal_eval(value)
+
+ if type(multiList[0]) == int:
+ multiList = ast.literal_eval("(" + value + ")")
+
+ self.__formated_value = multiList
+
+ return self.__formated_value
+
+ if format == 'bool':
+ value = int(value)
+
+ if format == 'int':
+ value = float(value)
+
+ format_func = eval(format)
+
+ self.__formated_value = format_func(value)
+
+ return self.__formated_value
+
+ def updateId(self, new_id):
+
+ self.id = str(new_id)
+
+ def setup(self, id, name, value, format='str'):
+
+ self.id = str(id)
+ self.name = name
+ self.value = str(value)
+ self.format = str.lower(format)
+
+ self.getValue()
+
+ return 1
+
+ def update(self, name, value, format='str'):
+
+ self.name = name
+ self.value = str(value)
+ self.format = format
+
+ def makeXml(self, opElement):
+
+ parmElement = SubElement(opElement, self.ELEMENTNAME)
+ parmElement.set('id', str(self.id))
+ parmElement.set('name', self.name)
+ parmElement.set('value', self.value)
+ parmElement.set('format', self.format)
+
+ def readXml(self, parmElement):
+
+ self.id = parmElement.get('id')
+ self.name = parmElement.get('name')
+ self.value = parmElement.get('value')
+ self.format = str.lower(parmElement.get('format'))
+
+ #Compatible with old signal chain version
+ if self.format == 'int' and self.name == 'idfigure':
+ self.name = 'id'
+
+ def printattr(self):
+
+ print "Parameter[%s]: name = %s, value = %s, format = %s" %(self.id, self.name, self.value, self.format)
+
+class OperationConf():
+
+ id = None
+ name = None
+ priority = None
+ type = None
+
+ parmConfObjList = []
+
+ ELEMENTNAME = 'Operation'
+
+ def __init__(self):
+
+ self.id = '0'
+ self.name = None
+ self.priority = None
+ self.type = 'self'
+
+
+ def __getNewId(self):
+
+ return int(self.id)*10 + len(self.parmConfObjList) + 1
+
+ def updateId(self, new_id):
+
+ self.id = str(new_id)
+
+ n = 1
+ for parmObj in self.parmConfObjList:
+
+ idParm = str(int(new_id)*10 + n)
+ parmObj.updateId(idParm)
+
+ n += 1
+
+ def getElementName(self):
+
+ return self.ELEMENTNAME
+
+ def getParameterObjList(self):
+
+ return self.parmConfObjList
+
+ def getParameterObj(self, parameterName):
+
+ for parmConfObj in self.parmConfObjList:
+
+ if parmConfObj.name != parameterName:
+ continue
+
+ return parmConfObj
+
+ return None
+
+ def getParameterObjfromValue(self, parameterValue):
+
+ for parmConfObj in self.parmConfObjList:
+
+ if parmConfObj.getValue() != parameterValue:
+ continue
+
+ return parmConfObj.getValue()
+
+ return None
+
+ def getParameterValue(self, parameterName):
+
+ parameterObj = self.getParameterObj(parameterName)
+
+# if not parameterObj:
+# return None
+
+ value = parameterObj.getValue()
+
+ return value
+
+ def setup(self, id, name, priority, type):
+
+ self.id = str(id)
+ self.name = name
+ self.type = type
+ self.priority = priority
+
+ self.parmConfObjList = []
+
+ def removeParameters(self):
+
+ for obj in self.parmConfObjList:
+ del obj
+
+ self.parmConfObjList = []
+
+ def addParameter(self, name, value, format='str'):
+
+ id = self.__getNewId()
+
+ parmConfObj = ParameterConf()
+ if not parmConfObj.setup(id, name, value, format):
+ return None
+
+ self.parmConfObjList.append(parmConfObj)
+
+ return parmConfObj
+
+ def changeParameter(self, name, value, format='str'):
+
+ parmConfObj = self.getParameterObj(name)
+ parmConfObj.update(name, value, format)
+
+ return parmConfObj
+
+ def makeXml(self, procUnitElement):
+
+ opElement = SubElement(procUnitElement, self.ELEMENTNAME)
+ opElement.set('id', str(self.id))
+ opElement.set('name', self.name)
+ opElement.set('type', self.type)
+ opElement.set('priority', str(self.priority))
+
+ for parmConfObj in self.parmConfObjList:
+ parmConfObj.makeXml(opElement)
+
+ def readXml(self, opElement):
+
+ self.id = opElement.get('id')
+ self.name = opElement.get('name')
+ self.type = opElement.get('type')
+ self.priority = opElement.get('priority')
+
+ #Compatible with old signal chain version
+ #Use of 'run' method instead 'init'
+ if self.type == 'self' and self.name == 'init':
+ self.name = 'run'
+
+ self.parmConfObjList = []
+
+ parmElementList = opElement.getiterator(ParameterConf().getElementName())
+
+ for parmElement in parmElementList:
+ parmConfObj = ParameterConf()
+ parmConfObj.readXml(parmElement)
+
+ #Compatible with old signal chain version
+ #If an 'plot' OPERATION is found, changes name operation by the value of its type PARAMETER
+ if self.type != 'self' and self.name == 'Plot':
+ if parmConfObj.format == 'str' and parmConfObj.name == 'type':
+ self.name = parmConfObj.value
+ continue
+
+ self.parmConfObjList.append(parmConfObj)
+
+ def printattr(self):
+
+ print "%s[%s]: name = %s, type = %s, priority = %s" %(self.ELEMENTNAME,
+ self.id,
+ self.name,
+ self.type,
+ self.priority)
+
+ for parmConfObj in self.parmConfObjList:
+ parmConfObj.printattr()
+
+ def createObject(self, plotter_queue=None):
+
+ if self.type == 'self':
+ raise ValueError, "This operation type cannot be created"
+
+ if self.type == 'plotter':
+ #Plotter(plotter_name)
+ if not plotter_queue:
+ raise ValueError, "plotter_queue is not defined. Use:\nmyProject = Project()\nmyProject.setPlotterQueue(plotter_queue)"
+
+ opObj = Plotter(self.name, plotter_queue)
+
+ if self.type == 'external' or self.type == 'other':
+ className = eval(self.name)
+ opObj = className()
+
+ return opObj
+
+class ProcUnitConf():
+
+ id = None
+ name = None
+ datatype = None
+ inputId = None
+ parentId = None
+
+ opConfObjList = []
+
+ procUnitObj = None
+ opObjList = []
+
+ ELEMENTNAME = 'ProcUnit'
+
+ def __init__(self):
+
+ self.id = None
+ self.datatype = None
+ self.name = None
+ self.inputId = None
+
+ self.opConfObjList = []
+
+ self.procUnitObj = None
+ self.opObjDict = {}
+
+ def __getPriority(self):
+
+ return len(self.opConfObjList)+1
+
+ def __getNewId(self):
+
+ return int(self.id)*10 + len(self.opConfObjList) + 1
+
+ def getElementName(self):
+
+ return self.ELEMENTNAME
+
+ def getId(self):
+
+ return self.id
+
+ def updateId(self, new_id, parentId=parentId):
+
+
+ new_id = int(parentId)*10 + (int(self.id) % 10)
+ new_inputId = int(parentId)*10 + (int(self.inputId) % 10)
+
+ #If this proc unit has not inputs
+ if self.inputId == '0':
+ new_inputId = 0
+
+ n = 1
+ for opConfObj in self.opConfObjList:
+
+ idOp = str(int(new_id)*10 + n)
+ opConfObj.updateId(idOp)
+
+ n += 1
+
+ self.parentId = str(parentId)
+ self.id = str(new_id)
+ self.inputId = str(new_inputId)
+
+
+ def getInputId(self):
+
+ return self.inputId
+
+ def getOperationObjList(self):
+
+ return self.opConfObjList
+
+ def getOperationObj(self, name=None):
+
+ for opConfObj in self.opConfObjList:
+
+ if opConfObj.name != name:
+ continue
+
+ return opConfObj
+
+ return None
+
+ def getOpObjfromParamValue(self, value=None):
+
+ for opConfObj in self.opConfObjList:
+ if opConfObj.getParameterObjfromValue(parameterValue=value) != value:
+ continue
+ return opConfObj
+ return None
+
+ def getProcUnitObj(self):
+
+ return self.procUnitObj
+
+ def setup(self, id, name, datatype, inputId, parentId=None):
+
+ #Compatible with old signal chain version
+ if datatype==None and name==None:
+ raise ValueError, "datatype or name should be defined"
+
+ if name==None:
+ if 'Proc' in datatype:
+ name = datatype
+ else:
+ name = '%sProc' %(datatype)
+
+ if datatype==None:
+ datatype = name.replace('Proc','')
+
+ self.id = str(id)
+ self.name = name
+ self.datatype = datatype
+ self.inputId = inputId
+ self.parentId = parentId
+
+ self.opConfObjList = []
+
+ self.addOperation(name='run', optype='self')
+
+ def removeOperations(self):
+
+ for obj in self.opConfObjList:
+ del obj
+
+ self.opConfObjList = []
+ self.addOperation(name='run')
+
+ def addParameter(self, **kwargs):
+ '''
+ Add parameters to "run" operation
+ '''
+ opObj = self.opConfObjList[0]
+
+ opObj.addParameter(**kwargs)
+
+ return opObj
+
+ def addOperation(self, name, optype='self'):
+
+ id = self.__getNewId()
+ priority = self.__getPriority()
+
+ opConfObj = OperationConf()
+ opConfObj.setup(id, name=name, priority=priority, type=optype)
+
+ self.opConfObjList.append(opConfObj)
+
+ return opConfObj
+
+ def makeXml(self, projectElement):
+
+ procUnitElement = SubElement(projectElement, self.ELEMENTNAME)
+ procUnitElement.set('id', str(self.id))
+ procUnitElement.set('name', self.name)
+ procUnitElement.set('datatype', self.datatype)
+ procUnitElement.set('inputId', str(self.inputId))
+
+ for opConfObj in self.opConfObjList:
+ opConfObj.makeXml(procUnitElement)
+
+ def readXml(self, upElement):
+
+ self.id = upElement.get('id')
+ self.name = upElement.get('name')
+ self.datatype = upElement.get('datatype')
+ self.inputId = upElement.get('inputId')
+
+ if self.ELEMENTNAME == "ReadUnit":
+ self.datatype = self.datatype.replace("Reader", "")
+
+ if self.ELEMENTNAME == "ProcUnit":
+ self.datatype = self.datatype.replace("Proc", "")
+
+ if self.inputId == 'None':
+ self.inputId = '0'
+
+ self.opConfObjList = []
+
+ opElementList = upElement.getiterator(OperationConf().getElementName())
+
+ for opElement in opElementList:
+ opConfObj = OperationConf()
+ opConfObj.readXml(opElement)
+ self.opConfObjList.append(opConfObj)
+
+ def printattr(self):
+
+ print "%s[%s]: name = %s, datatype = %s, inputId = %s" %(self.ELEMENTNAME,
+ self.id,
+ self.name,
+ self.datatype,
+ self.inputId)
+
+ for opConfObj in self.opConfObjList:
+ opConfObj.printattr()
+
+ def createObjects(self, plotter_queue=None):
+
+ className = eval(self.name)
+ procUnitObj = className()
+
+ for opConfObj in self.opConfObjList:
+
+ if opConfObj.type == 'self':
+ continue
+
+ opObj = opConfObj.createObject(plotter_queue)
+
+ self.opObjDict[opConfObj.id] = opObj
+ procUnitObj.addOperation(opObj, opConfObj.id)
+
+ self.procUnitObj = procUnitObj
+
+ return procUnitObj
+
+ def run(self):
+
+ is_ok = False
+
+ for opConfObj in self.opConfObjList:
+
+ kwargs = {}
+ for parmConfObj in opConfObj.getParameterObjList():
+ if opConfObj.name == 'run' and parmConfObj.name == 'datatype':
+ continue
+
+ kwargs[parmConfObj.name] = parmConfObj.getValue()
+
+ ini = time.time()
+
+ #print "\tRunning the '%s' operation with %s" %(opConfObj.name, opConfObj.id)
+ sts = self.procUnitObj.call(opType = opConfObj.type,
+ opName = opConfObj.name,
+ opId = opConfObj.id,
+ **kwargs)
+
+# total_time = time.time() - ini
+#
+# if total_time > 0.002:
+# print "%s::%s took %f seconds" %(self.name, opConfObj.name, total_time)
+
+ is_ok = is_ok or sts
+
+ return is_ok
+
+ def close(self):
+
+ for opConfObj in self.opConfObjList:
+ if opConfObj.type == 'self':
+ continue
+
+ opObj = self.procUnitObj.getOperationObj(opConfObj.id)
+ opObj.close()
+
+ self.procUnitObj.close()
+
+ return
+
+class ReadUnitConf(ProcUnitConf):
+
+ path = None
+ startDate = None
+ endDate = None
+ startTime = None
+ endTime = None
+
+ ELEMENTNAME = 'ReadUnit'
+
+ def __init__(self):
+
+ self.id = None
+ self.datatype = None
+ self.name = None
+ self.inputId = None
+
+ self.parentId = None
+
+ self.opConfObjList = []
+ self.opObjList = []
+
+ def getElementName(self):
+
+ return self.ELEMENTNAME
+
+ def setup(self, id, name, datatype, path, startDate="", endDate="", startTime="", endTime="", parentId=None, **kwargs):
+
+ #Compatible with old signal chain version
+ if datatype==None and name==None:
+ raise ValueError, "datatype or name should be defined"
+
+ if name==None:
+ if 'Reader' in datatype:
+ name = datatype
+ else:
+ name = '%sReader' %(datatype)
+
+ if datatype==None:
+ datatype = name.replace('Reader','')
+
+ self.id = id
+ self.name = name
+ self.datatype = datatype
+
+ self.path = os.path.abspath(path)
+ self.startDate = startDate
+ self.endDate = endDate
+ self.startTime = startTime
+ self.endTime = endTime
+
+ self.inputId = '0'
+ self.parentId = parentId
+
+ self.addRunOperation(**kwargs)
+
+ def update(self, datatype, path, startDate, endDate, startTime, endTime, parentId=None, name=None, **kwargs):
+
+ #Compatible with old signal chain version
+ if datatype==None and name==None:
+ raise ValueError, "datatype or name should be defined"
+
+ if name==None:
+ if 'Reader' in datatype:
+ name = datatype
+ else:
+ name = '%sReader' %(datatype)
+
+ if datatype==None:
+ datatype = name.replace('Reader','')
+
+ self.datatype = datatype
+ self.name = name
+ self.path = path
+ self.startDate = startDate
+ self.endDate = endDate
+ self.startTime = startTime
+ self.endTime = endTime
+
+ self.inputId = '0'
+ self.parentId = parentId
+
+ self.updateRunOperation(**kwargs)
+
+ def removeOperations(self):
+
+ for obj in self.opConfObjList:
+ del obj
+
+ self.opConfObjList = []
+
+ def addRunOperation(self, **kwargs):
+
+ opObj = self.addOperation(name = 'run', optype = 'self')
+
+ opObj.addParameter(name='datatype' , value=self.datatype, format='str')
+ opObj.addParameter(name='path' , value=self.path, format='str')
+ opObj.addParameter(name='startDate' , value=self.startDate, format='date')
+ opObj.addParameter(name='endDate' , value=self.endDate, format='date')
+ opObj.addParameter(name='startTime' , value=self.startTime, format='time')
+ opObj.addParameter(name='endTime' , value=self.endTime, format='time')
+
+ for key, value in kwargs.items():
+ opObj.addParameter(name=key, value=value, format=type(value).__name__)
+
+ return opObj
+
+ def updateRunOperation(self, **kwargs):
+
+ opObj = self.getOperationObj(name = 'run')
+ opObj.removeParameters()
+
+ opObj.addParameter(name='datatype' , value=self.datatype, format='str')
+ opObj.addParameter(name='path' , value=self.path, format='str')
+ opObj.addParameter(name='startDate' , value=self.startDate, format='date')
+ opObj.addParameter(name='endDate' , value=self.endDate, format='date')
+ opObj.addParameter(name='startTime' , value=self.startTime, format='time')
+ opObj.addParameter(name='endTime' , value=self.endTime, format='time')
+
+ for key, value in kwargs.items():
+ opObj.addParameter(name=key, value=value, format=type(value).__name__)
+
+ return opObj
+
+# def makeXml(self, projectElement):
+#
+# procUnitElement = SubElement(projectElement, self.ELEMENTNAME)
+# procUnitElement.set('id', str(self.id))
+# procUnitElement.set('name', self.name)
+# procUnitElement.set('datatype', self.datatype)
+# procUnitElement.set('inputId', str(self.inputId))
+#
+# for opConfObj in self.opConfObjList:
+# opConfObj.makeXml(procUnitElement)
+
+ def readXml(self, upElement):
+
+ self.id = upElement.get('id')
+ self.name = upElement.get('name')
+ self.datatype = upElement.get('datatype')
+ self.inputId = upElement.get('inputId')
+
+ if self.ELEMENTNAME == "ReadUnit":
+ self.datatype = self.datatype.replace("Reader", "")
+
+ if self.inputId == 'None':
+ self.inputId = '0'
+
+ self.opConfObjList = []
+
+ opElementList = upElement.getiterator(OperationConf().getElementName())
+
+ for opElement in opElementList:
+ opConfObj = OperationConf()
+ opConfObj.readXml(opElement)
+ self.opConfObjList.append(opConfObj)
+
+ if opConfObj.name == 'run':
+ self.path = opConfObj.getParameterValue('path')
+ self.startDate = opConfObj.getParameterValue('startDate')
+ self.endDate = opConfObj.getParameterValue('endDate')
+ self.startTime = opConfObj.getParameterValue('startTime')
+ self.endTime = opConfObj.getParameterValue('endTime')
+
+class Project():
+
+ id = None
+ name = None
+ description = None
+ filename = None
+
+ procUnitConfObjDict = None
+
+ ELEMENTNAME = 'Project'
+
+ plotterQueue = None
+
+ def __init__(self, plotter_queue=None):
+
+ self.id = None
+ self.name = None
+ self.description = None
+
+ self.plotterQueue = plotter_queue
+
+ self.procUnitConfObjDict = {}
+
+ def __getNewId(self):
+
+ idList = self.procUnitConfObjDict.keys()
+
+ id = int(self.id)*10
+
+ while True:
+ id += 1
+
+ if str(id) in idList:
+ continue
+
+ break
+
+ return str(id)
+
+ def getElementName(self):
+
+ return self.ELEMENTNAME
+
+ def getId(self):
+
+ return self.id
+
+ def updateId(self, new_id):
+
+ self.id = str(new_id)
+
+ keyList = self.procUnitConfObjDict.keys()
+ keyList.sort()
+
+ n = 1
+ newProcUnitConfObjDict = {}
+
+ for procKey in keyList:
+
+ procUnitConfObj = self.procUnitConfObjDict[procKey]
+ idProcUnit = str(int(self.id)*10 + n)
+ procUnitConfObj.updateId(idProcUnit, parentId = self.id)
+
+ newProcUnitConfObjDict[idProcUnit] = procUnitConfObj
+ n += 1
+
+ self.procUnitConfObjDict = newProcUnitConfObjDict
+
+ def setup(self, id, name, description):
+
+ self.id = str(id)
+ self.name = name
+ self.description = description
+
+ def update(self, name, description):
+
+ self.name = name
+ self.description = description
+
+ def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
+
+ if id is None:
+ idReadUnit = self.__getNewId()
+ else:
+ idReadUnit = str(id)
+
+ readUnitConfObj = ReadUnitConf()
+ readUnitConfObj.setup(idReadUnit, name, datatype, parentId=self.id, **kwargs)
+
+ self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
+
+ return readUnitConfObj
+
+ def addProcUnit(self, inputId='0', datatype=None, name=None):
+
+ idProcUnit = self.__getNewId()
+
+ procUnitConfObj = ProcUnitConf()
+ procUnitConfObj.setup(idProcUnit, name, datatype, inputId, parentId=self.id)
+
+ self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
+
+ return procUnitConfObj
+
+ def removeProcUnit(self, id):
+
+ if id in self.procUnitConfObjDict.keys():
+ self.procUnitConfObjDict.pop(id)
+
+ def getReadUnitId(self):
+
+ readUnitConfObj = self.getReadUnitObj()
+
+ return readUnitConfObj.id
+
+ def getReadUnitObj(self):
+
+ for obj in self.procUnitConfObjDict.values():
+ if obj.getElementName() == "ReadUnit":
+ return obj
+
+ return None
+
+ def getProcUnitObj(self, id=None, name=None):
+
+ if id != None:
+ return self.procUnitConfObjDict[id]
+
+ if name != None:
+ return self.getProcUnitObjByName(name)
+
+ return None
+
+ def getProcUnitObjByName(self, name):
+
+ for obj in self.procUnitConfObjDict.values():
+ if obj.name == name:
+ return obj
+
+ return None
+
+ def procUnitItems(self):
+
+ return self.procUnitConfObjDict.items()
+
+ def makeXml(self):
+
+ projectElement = Element('Project')
+ projectElement.set('id', str(self.id))
+ projectElement.set('name', self.name)
+ projectElement.set('description', self.description)
+
+ for procUnitConfObj in self.procUnitConfObjDict.values():
+ procUnitConfObj.makeXml(projectElement)
+
+ self.projectElement = projectElement
+
+ def writeXml(self, filename=None):
+
+ if filename == None:
+ if self.filename:
+ filename = self.filename
+ else:
+ filename = "schain.xml"
+
+ if not filename:
+ print "filename has not been defined. Use setFilename(filename) for do it."
+ return 0
+
+ abs_file = os.path.abspath(filename)
+
+ if not os.access(os.path.dirname(abs_file), os.W_OK):
+ print "No write permission on %s" %os.path.dirname(abs_file)
+ return 0
+
+ if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
+ print "File %s already exists and it could not be overwriten" %abs_file
+ return 0
+
+ self.makeXml()
+
+ ElementTree(self.projectElement).write(abs_file, method='xml')
+
+ self.filename = abs_file
+
+ return 1
+
+ def readXml(self, filename = None):
+
+ if not filename:
+ print "filename is not defined"
+ return 0
+
+ abs_file = os.path.abspath(filename)
+
+ if not os.path.isfile(abs_file):
+ print "%s file does not exist" %abs_file
+ return 0
+
+ self.projectElement = None
+ self.procUnitConfObjDict = {}
+
+ try:
+ self.projectElement = ElementTree().parse(abs_file)
+ except:
+ print "Error reading %s, verify file format" %filename
+ return 0
+
+ self.project = self.projectElement.tag
+
+ self.id = self.projectElement.get('id')
+ self.name = self.projectElement.get('name')
+ self.description = self.projectElement.get('description')
+
+ readUnitElementList = self.projectElement.getiterator(ReadUnitConf().getElementName())
+
+ for readUnitElement in readUnitElementList:
+ readUnitConfObj = ReadUnitConf()
+ readUnitConfObj.readXml(readUnitElement)
+
+ if readUnitConfObj.parentId == None:
+ readUnitConfObj.parentId = self.id
+
+ self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
+
+ procUnitElementList = self.projectElement.getiterator(ProcUnitConf().getElementName())
+
+ for procUnitElement in procUnitElementList:
+ procUnitConfObj = ProcUnitConf()
+ procUnitConfObj.readXml(procUnitElement)
+
+ if procUnitConfObj.parentId == None:
+ procUnitConfObj.parentId = self.id
+
+ self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
+
+ self.filename = abs_file
+
+ return 1
+
+ def printattr(self):
+
+ print "Project[%s]: name = %s, description = %s" %(self.id,
+ self.name,
+ self.description)
+
+ for procUnitConfObj in self.procUnitConfObjDict.values():
+ procUnitConfObj.printattr()
+
+ def createObjects(self):
+
+ for procUnitConfObj in self.procUnitConfObjDict.values():
+ procUnitConfObj.createObjects(self.plotterQueue)
+
+ def __connect(self, objIN, thisObj):
+
+ thisObj.setInput(objIN.getOutputObj())
+
+ def connectObjects(self):
+
+ for thisPUConfObj in self.procUnitConfObjDict.values():
+
+ inputId = thisPUConfObj.getInputId()
+
+ if int(inputId) == 0:
+ continue
+
+ #Get input object
+ puConfINObj = self.procUnitConfObjDict[inputId]
+ puObjIN = puConfINObj.getProcUnitObj()
+
+ #Get current object
+ thisPUObj = thisPUConfObj.getProcUnitObj()
+
+ self.__connect(puObjIN, thisPUObj)
+
+ def __handleError(self, procUnitConfObj, send_email=True):
+
+ import socket
+
+ err = traceback.format_exception(sys.exc_info()[0],
+ sys.exc_info()[1],
+ sys.exc_info()[2])
+
+ print "***** Error occurred in %s *****" %(procUnitConfObj.name)
+ print "***** %s" %err[-1]
+
+ message = "".join(err)
+
+ sys.stderr.write(message)
+
+ if not send_email:
+ return
+
+ subject = "SChain v%s: Error running %s\n" %(schainpy.__version__, procUnitConfObj.name)
+
+ subtitle = "%s: %s\n" %(procUnitConfObj.getElementName() ,procUnitConfObj.name)
+ subtitle += "Hostname: %s\n" %socket.gethostbyname(socket.gethostname())
+ subtitle += "Working directory: %s\n" %os.path.abspath("./")
+ subtitle += "Configuration file: %s\n" %self.filename
+ subtitle += "Time: %s\n" %str(datetime.datetime.now())
+
+ readUnitConfObj = self.getReadUnitObj()
+ if readUnitConfObj:
+ subtitle += "\nInput parameters:\n"
+ subtitle += "[Data path = %s]\n" %readUnitConfObj.path
+ subtitle += "[Data type = %s]\n" %readUnitConfObj.datatype
+ subtitle += "[Start date = %s]\n" %readUnitConfObj.startDate
+ subtitle += "[End date = %s]\n" %readUnitConfObj.endDate
+ subtitle += "[Start time = %s]\n" %readUnitConfObj.startTime
+ subtitle += "[End time = %s]\n" %readUnitConfObj.endTime
+
+ adminObj = schainpy.admin.SchainNotify()
+ adminObj.sendAlert(message=message,
+ subject=subject,
+ subtitle=subtitle,
+ filename=self.filename)
+
+ def isPaused(self):
+ return 0
+
+ def isStopped(self):
+ return 0
+
+ def runController(self):
+ """
+ returns 0 when this process has been stopped, 1 otherwise
+ """
+
+ if self.isPaused():
+ print "Process suspended"
+
+ while True:
+ sleep(0.1)
+
+ if not self.isPaused():
+ break
+
+ if self.isStopped():
+ break
+
+ print "Process reinitialized"
+
+ if self.isStopped():
+ print "Process stopped"
+ return 0
+
+ return 1
+
+ def setFilename(self, filename):
+
+ self.filename = filename
+
+ def setPlotterQueue(self, plotter_queue):
+
+ raise NotImplementedError, "Use schainpy.controller_api.ControllerThread instead Project class"
+
+ def getPlotterQueue(self):
+
+ raise NotImplementedError, "Use schainpy.controller_api.ControllerThread instead Project class"
+
+ def useExternalPlotter(self):
+
+ raise NotImplementedError, "Use schainpy.controller_api.ControllerThread instead Project class"
+
+ def run(self):
+
+ print
+ print "*"*60
+ print " Starting SIGNAL CHAIN PROCESSING v%s " %schainpy.__version__
+ print "*"*60
+ print
+
+ keyList = self.procUnitConfObjDict.keys()
+ keyList.sort()
+
+ while(True):
+
+ is_ok = False
+
+ for procKey in keyList:
+# print "Running the '%s' process with %s" %(procUnitConfObj.name, procUnitConfObj.id)
+
+ procUnitConfObj = self.procUnitConfObjDict[procKey]
+
+ try:
+ sts = procUnitConfObj.run()
+ is_ok = is_ok or sts
+ except KeyboardInterrupt:
+ is_ok = False
+ break
+ except ValueError, e:
+ sleep(0.5)
+ self.__handleError(procUnitConfObj, send_email=True)
+ is_ok = False
+ break
+ except:
+ sleep(0.5)
+ self.__handleError(procUnitConfObj)
+ is_ok = False
+ break
+
+ #If every process unit finished so end process
+ if not(is_ok):
+# print "Every process unit have finished"
+ break
+
+ if not self.runController():
+ break
+
+ #Closing every process
+ for procKey in keyList:
+ procUnitConfObj = self.procUnitConfObjDict[procKey]
+ procUnitConfObj.close()
+
+ print "Process finished"
+
+ def start(self):
+
+ self.writeXml()
+
+ self.createObjects()
+ self.connectObjects()
+ self.run()
+
+if __name__ == '__main__':
+
+ desc = "Segundo Test"
+ filename = "schain.xml"
+
+ controllerObj = Project()
+
+ controllerObj.setup(id = '191', name='test01', description=desc)
+
+ readUnitConfObj = controllerObj.addReadUnit(datatype='Voltage',
+ path='data/rawdata/',
+ startDate='2011/01/01',
+ endDate='2012/12/31',
+ startTime='00:00:00',
+ endTime='23:59:59',
+ online=1,
+ walk=1)
+
+ procUnitConfObj0 = controllerObj.addProcUnit(datatype='Voltage', inputId=readUnitConfObj.getId())
+
+ opObj10 = procUnitConfObj0.addOperation(name='selectChannels')
+ opObj10.addParameter(name='channelList', value='3,4,5', format='intlist')
+
+ opObj10 = procUnitConfObj0.addOperation(name='selectHeights')
+ opObj10.addParameter(name='minHei', value='90', format='float')
+ opObj10.addParameter(name='maxHei', value='180', format='float')
+
+ opObj12 = procUnitConfObj0.addOperation(name='CohInt', optype='external')
+ opObj12.addParameter(name='n', value='10', format='int')
+
+ procUnitConfObj1 = controllerObj.addProcUnit(datatype='Spectra', inputId=procUnitConfObj0.getId())
+ procUnitConfObj1.addParameter(name='nFFTPoints', value='32', format='int')
+# procUnitConfObj1.addParameter(name='pairList', value='(0,1),(0,2),(1,2)', format='')
+
+
+ opObj11 = procUnitConfObj1.addOperation(name='SpectraPlot', optype='external')
+ opObj11.addParameter(name='idfigure', value='1', format='int')
+ opObj11.addParameter(name='wintitle', value='SpectraPlot0', format='str')
+ opObj11.addParameter(name='zmin', value='40', format='int')
+ opObj11.addParameter(name='zmax', value='90', format='int')
+ opObj11.addParameter(name='showprofile', value='1', format='int')
+
+ print "Escribiendo el archivo XML"
+
+ controllerObj.writeXml(filename)
+
+ print "Leyendo el archivo XML"
+ controllerObj.readXml(filename)
+ #controllerObj.printattr()
+
+ controllerObj.createObjects()
+ controllerObj.connectObjects()
+ controllerObj.run()
+
+
\ No newline at end of file
diff --git a/schainpy/controller.pyc b/schainpy/controller.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..21fbb6161b82dcad4dfb19e402a4ab5c8613b9b9
GIT binary patch
literal 30573
zc%0RJ3ve7qdS1`$d$Axu00am=mpoAfbrc_ZL?=o*JxGe=NrHF_>ZpUvTP-mIV!_4k
zVrL)%XHbrhcXnc*VpqjiCtsA<=iJ$Mik*rRD~=r}YNpG+g}cKl$TV7nJ_9lm0zJ
z|AJOZDNm_+x;n~pRl`y9j!C;}-ZklznopT@TFs|TI-}+@CY?3ulxpPEN?y(9)k;Cl
z7t~5o%@@_mkeVM-4r-)Tqoh`b)%>vBXH;W{x`I?zHAd9RsG1+8lAQWHHEyT!@@kQq
zSitQar9M4Bro19&4cV-5<&`*V*k(;AZ-??H)FQoi#OCf&-Y8exX|pDkKc&1eb<M5?@|69wY*n(^zfwes4`Wc(%n>=a!|HUd3%&cH7K!Pc?Xnt
zP>8?tEGKWwm^W
zzxM#;IP-^wNYxgVv
ze)G&T{LHiQXKdMXTy~br&UKZY=d$PfK6fETk?yjKJ>T;#sS6j;#iPofR(BlY&QIu^
z8IyyXW9Txc94=oqnkJ
zOl>V(YIV+(i}gRFKeIDwdLkU6%lU@C;y1%99p4Xg(S2B?^xWEYbDKx~RuFdT%^Ncg
zZcurp-mH7A70JNm0ZC@isD|&i7jT=>|IQ-!1j?1#WEpYCRks~Hx$LS<2fe;c30Ezr
z&^em<#CLPt*5G4wsrcbqr&+F*+Z{g)Hy&(LYtZ9YUwW}DO)D?9I^}T5FY9)nD3<9@
zfcC6~iw}M*%u=e}^r$FsDOoP_+bd{Z#nPl*>jeHBzmV_4mV9u1r7?q=A!_>cg|I}4
zPHXMPQdPdsbn5v00-BffhcCe>T~3@hxzK8comQjacTTi7xGulAzPK@tT4W*$Jk2<-s!slQEzFa>{)E
zHj`pm*j<79i6%EwsxzZ+=QdeaLW6t)gpkPr^0~GKt4Y+TW5UsBq9Cg#Kj$hE4tPPD
zi+>1DFXu3#m|#>d)%7M9!;Y$dpoo~u1v3}Zip0QX8fhXDG5aEYFsC}-R>Yr@e}k*x
zd+FYn=J=%_cLsXt35V!8z)SP|(r-GtQw80r8w&k8cWq4F&T#X%x1Vv<>g&$!tO`fe
z@~GO(f^(-gd1~-~B{h8~rEcfcX0G>B!~CfUSAS~9JwNrY&8K#5{i(d#%=dn3gg^EB
z?m(ov>SDl0QB9Aw)WZk6>weV@$Mid>1>mtS^*l|*mgMWFaC`3BjJjP=c(f3E^c%@X
zSHI!X->dybX(#vR=~SXWMQ&%&wo~YPQdc62iRw*}y)-42(XwLit0(xW`4lKG?{y5r
z@8Y7h6gVkX6po`5w?k@ksNZConS?l~jEZuixq65$M}jluD@*mD+%|%({6?*@=9ekU
zUulOMETJ0pAY|QloK+%eB+h|ATx_&za)*i@X=ko@vW`#Gk*vE$(1rCCDLuoFwrllH
zfJcKP+>-KAEhvYr@^zooU%1w8_+`>`s8DV#mbo@Rx3bm<>$XWVd_Be=xZY|tSl&_#
zXC{o6<_=Y0!G{MRMiV-xS`~5ZdsVK-@0o2ieIXP~gij&=e5cduaA6YLGuw
zMr|oEo#?H#M%AZRNsl+$QkT0^nS#{4&$Nq4$C91NM#QP?MTPySfYξ<6g1*Rcv>
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
literal 0
Hc$@k*fq-cRh7~!uAPz+Ab&10(gU})XL^Cvr5(!n}LPCv5kboeoEHpCc!zOrj7FysnSZIUS
zWT69Iiv@f{n}rSVIxO_SI_+;D2v=mVNW*&s?TlEViVPSFn4@w~tE!Ss<_6pfFi;ws
zq#NF3eWDI=)vkjtKsAWU4*e6bL(5GfdD^Fk94V6?qoSB~8#}X9_FMGOCJn4GKfF*i
zoN4vpIe3KahrY6H%gAp{rP_Do6m?ApK1*hjg~Q05un>?yk9g_?crRJb)rRR4VGTnD
z=c-FE(1c1R_9dH|Y{f%L)*6hWsT|0}cPE3FQ8Gzm$CZQB9XWoOM3EY#(JU!e;_HE1
z*xz=Xmhyi16u^Vg}o1!avhD&6OMeV<#wLfPApb~dkZ-n>ABET$Kbc#jhV;{77
zIowrZW`)_dCj;BwqGJU^e;x88(0Ca#x`CnCRmSYkyV;J(J9o*Db*xSvSB`r*^AlOJ
zU$Be5Q))PZWkY$(D3-r&E(zxXy@w2aoxZ&Lh(S
z>#8MMMyt%oMy|0|;T*R_nbxz`Kzo_(1pbS4rl-ut)+`LMF7CtYskp$}Uc}m21Z%wu
z>#Y_o2Kf|=bUKpWw|7vIcbGZK-y!cXFuJaO1MPL%-S&UJgd40MB6GT%3bh&Y3i%wm
z>qJ1Z2bT{a1i0Gg+iLn}J8)yd+=OwRJelsBz~u?uM~e;WTqZS0PN=2A6>L;+7r$qC
z*cm%B;XCqSDQ>g2pid^SxNB&atA~E76a{;nMDBC!PO$GgM^E1OUB$Wkg%iwV%Bs1L
z>L83~>cC_7_Cx(kTt1Fv;wV1~@t1re;ZWDH?q)(~Ds`FUbon9eQ6#Am=C|kB0~xBH
z9pB7$k7L|fy`70ac2g%>1?eG8@3Wzs;!V*J_l%m@!q%on?MW;fC6Ps)C+1?Ttey06j;Z-lfYbmrIuQ{}O+EEr^x_4kMDftT>Ul=a8TGa-W
zi5=Zf=lfd@KQsmgT9(tx;^vdjYQKY=qV=c8?tx|+>e7D!cXTANSS^LR>~GoGN9-mSG3ymbG_RZ&VGOR>NNhS`_5Gh13s;|ab`|@+ClXdFY3H=
zYtMCBrMo?@DayMyxwu(-hhMf{tj5-_oQu8xow;fK;_`xk2WQtDc3k(dsqs3;mam=m
zzU52KD$ecXn0F{T+&?-#;mR+YjOAO+Ura83EBrxI$HMuy;ImV=ez_=}eCS*hXZGJa
z;NzV`f1(bs7@Vv0EBz>-GJk#KpT)O6F#g{8Sg|S2(&nXF0r$K%!P@5Bsp4Xp%M^<{
zPnE{`-pSonlzR4V*_^
zF{#3Qnm_+u=`-`ym#vDszQX2<aX40H^Q=#@$p^i*dfa~WtANJ?^<_AE83e~43w)qUHx3v
IIVCg!0EM8%#sB~S
literal 0
Hc$@jZo;Ptn
zCXmHIkf|&R4IyB#0V{?TVB}i{jYrlKFhZGJi~tAw6M>QMSHeh`-k%WOQ5?*h=%Q!K
z;?VSVAj}ac7#^&rr-$WGgD@mJ`=4~Vhl3sA@z@w7lF#QO_}dXIPB0Q}Wo3m#nIX;0
zOyvkuu8_$i3rv|@gC9wL<*}o2137dykIrK1t@vaL>lhCQgZ;$(u%Gv2u>Vtt$^EHH
zt`8|7vyo^73i)>=9z7`N?^!D+KWO;>^04wE7+VgF%wuufS*%d}o)x?vfk6(Yk!WP9
z5R3dP;(y31DKQ5)bedf2iXuE3i~PUXFZIa3$p6t>~f!SYJK9tsaOLbT%m03eZI
zx5wQZ^hhL2>h)OD+&MM4;U4?^C+|R>D?uEVO-Gr*GB$yqh<2}ze-UBir0!)@ApO_OAn~svf<_J9f;&DX&|-yuAD!HCH2F(F&f+?K+Z4Q|b-*{7x!$rCFiQ
z1U$*=Xnlz(^HG_(WWg|g|FYI!GI-0Q5F-p#ozJt$MIF!~m=iYnrjNe+{B@OusyJHk
zX)
zbAmHr4Thq}lEkMv+2_ANkDu_^xD@eZW3_$Vs;e++8ZhpAX0}P-ntRf9U{I2NrkJv^
z!F#+xZJ*J>2RzmAH<=>KY)nDU#{;`j>#VLpPu}FoM$4aQG1~C+(zJ0FA84k
z3tBW8uPU}XLs#q$9h^m%)22vlFW*L~*_2Jq*g$Du3?)WZ%6Z+oSU-^P(%G@rJ;iti
zs=akQv14HLU_B?>ihI))A+ipt?MuH;L)z}pT@{_Pz~#->B&|pKZJ#NlJ)X?U$zh_1
z>MhrbO4>(9M+5Rm3*coS>RBMva|nYrc5`!^MINqXw+xWgu_4;2lmJVk!t^MGIc((o
zjo_+^iZ8^`qmJz6mX;P)aeKxa91eGuQm$0XBFu9~H7POLMH*E4uAt%V#?sfTiNwmw
z%F~ecKqye;&tk{&%lVPHrUT2Nw+HqEo$D`(sn!g=qLIuG+@WGuW)tC?EP=UH>Q?_YYlA+2b$mcMzYPq
zFzym1O1|2wx$q{n3-+$kg%S-daq_`))bW$T=~*{V`j$;QHgt$Ge1eP`T7?Nt|8kS0
z{9eETZKZT1p|OlxaFx;JDCRJ_J<*3tom;4A&mEJ3F+bRp)0`?9eWoDWZ0ZD>g}0zVi5d
zYj}b;D7`?P2ui*muK>|D4mBLR6jf-YU$-mcv%=^LcCo_;Gsu_Z6Nt;HY0CAtCzR%x
zXjtEy(~Pnvvx2zl&1pN^>eQM1h<&D151D!VcQ__uweQ|Z*IDDq5!}a9qldFF?;ol(
zsH!fVm3Qpsz@5p8iVw-9vo)bEx|O9k%NnZ7#plko0hNyz6=MFGmh90^o-Ces$AnlE
zaA|KV{bYAcNLiYdr}4vk`wTM0tF&gLUM=klJoWU|qoe~c0iq+x{4QviIPNN*czw}#~S&b>{I$+&2XV4O^8&WSoO@rHz{Xy_T9j=XvTi!yvGT;7Vh
zKlsqx(`9Jnk5X9!VQAvDyM46ELOGLmCXbaLtK|@S^TBL$qjGh4d+J!_l@1H_!nsbz
zN&{4BR`;}rE-;=Qx%Z?+y@Nlx5xSk?bNNkWfg<7JH}jUoM{Oe=%T`3fbhSZD=Xa&5
W64}fGO~+{ES3ub7Y*%6v5dUvWeYQ
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
DB~=*Y
literal 0
Hc$@NSwWJ?9znhg
z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!CBxDSY3;nDA{o-C@9zzrKDK}xwt{K19`Se86_nJR{Hwo
z<>h+i#(Mch>H3D2mX`VkM*2oZx=P7{r
ziAnjTCALaRP&E($v8W_74PjGWG1OZ?59)(t^bPe4^x#An4GAd<
zJOkrpQ^)r7Yl7+XZsda>VlpHzYajE0N+lz9!Yj=H}x+~^oSgDoTzLcw#
z@Asa!TmI_a!3X>Q6|%Lhei45=JAw0&dgFWc(iF+o!^CJ)_3^X69jM7
zUAs81`Su6*oeQ+3vsR01@}>wGf1Q(Py=m9_h>haj?GKE%{GHJlUck;~rlj8^{@5U<
zLH|OWNAc03xhwmNbJw@#Z(uFa>#fz6cAVSlnW=rVeDNn2hLa7)dc$HHKYtLN#j&z{
z;_I!oY<`V)cV1Mln8L8_q80n=hr)Z9kH_2zm3tnxgJp99gIueZW!A@%MdFK7W+i7!
z?XFH(nEKzS)YL@CP&M3frrPEE;`$pMWmxo|F#qsfc9X&9`sAuBw`VP0x!X#dZG-f;
zgSr-s$(MFc4pG{&eoD>TD}p;Buhvzjd@q~b$bW(F)IYmZ(I%}EZ(NTvvn`X3H~4TS
z@QROwskQyx9xJZAcMEy1+&G`7yVs;&)^%x}*4c(_WsTnx*seq{l&M_$ZN{ZN`=eaU
z`rPLkQpY=A1lk@nUpVDa4p;NZf;z+53_?rApX%<=a14CAH065rgYawHbAxr#49>+F
zeb^%B6aTDCck|4-5+CGzoa=tf;>ozPWp?Kh&B($v>p$6A^exPOARVYFxnbhwUDi^o
z=A|uU*;p%7o%X}@MfJ+RC(riHH(s!cb8*(j=NoUWvokwfqjb5sw0yU$-}T(CN1y&5
zya>RXmR-vAH
z;6G!&g5<&|m%M^~+qMXFPY%i{nfz<>GXIwwv*M?o`*7mbeY<*wuK4S(PX6AZ0m|W?
Lu6{1-oD!M<4c5`*
literal 0
Hc$@h?X&sHg;
zq@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6GOr}DLN~8i8Da>`9GBGMsb3~lr=#9(gGM{^9sr}|K@+Hu+F!-LI^%jb}KBm)CWx~Gd{h=pKksJC~rr^vc!
z^N+bT3l}M6x^pZNbS!!3mf2LOZQRk(&1l}c_8-H+R_nwAXEV%MuJ03YpLx$iDzoJ3
z4ndQSW3G>zJ37|?Fx&b4-1pGsmoAq$-gUoQyzlee^?q}+JLC_)c=>Xox3{<0^kvJI
zWzCy6&q}z{<-#VN{f{lC#+dUcr_D+`^0usf^XAR={XIQ3kF9Eaf844l`H}abDY2)&
zzxdV+ISbysd-m*MUh)0w*HD$oC*OyyTz&efkffv}QQ#H7_H>;Pk0eE?id{WSAP~K7XEGSXrt0?fdt&YuD;>
zJ`*~l{Nvy8BS&1O%<$rJ`N;4_eu=yTTj#oUdcq5g%+13aIvbW{Eo)#63ZKl#$It(^
zz#^w{f;7vug}>h)=-#a%&9fr2!DsjG-DjUYOPe`)vhsl@t4l5pa;514e6Q-t%hf#^
zgx0QEbK?X5gG!G1>Ss1?+&Js^@8A2^uUp4;`}Xa%+qRia-c@L0XV=x<&c0N)d4g>Y
zYmTRz=Mjeu>CeJcgc>{7@Uk`k_i}mJ@^SX0NkSK|Tv6GX$dYKfX6@R}lP5hlZr;3@
z>Eouodv)2^*a}aP0^^N$nvnYOpFejp
zwQsC?-YU6f-MUo?H$0ZwzU}Vr=AC~&-B>uuE93QY#lkdtbo+cl}l
znz