diff --git a/.gitignore b/.gitignore index c31424d..3ae6144 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +<<<<<<< HEAD # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -100,3 +101,9 @@ ENV/ # eclipse .project .pydevproject +======= +build/ +dist/ +schainpy.egg-info/ +.svn/ +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 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..660da29 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + schain + + + + + + 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/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 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 \ 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/__init__.pyc b/schainpy/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..67ef1fb3577917f9a99b9f4f60ab8e3574857ecc GIT binary patch literal 314 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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.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 znz6Y+Wz3E8FZ6EVr_wL2X zOVqWry(wWj$Wql18ydQ_OP*0ALr1LmMnPG5`Ba|?*|H1Xi;Iibn^avo=F$B9`}gVq zRp%F+?{_RL2sn3TT65{CI)_e%3Km~ypZc=0Z`0!^7ae%IeE!P=2M**HyhvHjB=NiR w*G#1h9!I4=6PZkGY;FJcGOV-@{FVMoeg)SRg_^J@pu(QP)78&qol`;+0PD(~e*gdg literal 0 Hc$@DDLE!tv_-i{e2@^D|>;5SdIs0zhPBq+aAPJv=cGFhC#>fIbX> z!F2fuT@nRH_KDKPk<@lczVev)lYEK61adGQ2NC2x7x3X^V<>bFvunGJ$iV^scEXYN zWbp+8f)l_%PapWkEua@vk+#HOe|~2HKiU8V{IB+P7T`a_>?#HJq@pEIz_({ZOIWvR zxq(0;ZkA>yjz+SfPM$%^PV(CU5hrpUmT8E?1F$Jdv0j^|mnB^19rCEM>Uq_+pPo^j z+ka7-Go`jOse_%=qx9y-G8hvNY-LRbLswT5o~)hhU1P)E#5KHr(Yw&A+(HTrc#;bK z+}lLD(!4QtZ1zEQh1+^N1`x^6i0{U<*~!V6A53zXl8@sK)y8QB^yJ3Gz<)?UKbH)5 zuG1&YzLLGnt-=oLwv8^j7koEbGP-Km0dA=s#$Eq2k3cWC_8+4GiYb|CJv#~UcU9va zId304FSc;!G-Ydi$VGMQEoZV12=s&MR?YQZx{lQ% z`!RR2Qq5Rv#t(_DK%rBV6Xa+z*P2Vb7%(Va$}4i<=W&OQm*iHI@X+K^e7+(voqHGw zF0@-Ncpu%Wu`g|{KT=w)Jpvb&Gd{tlZdWeAjLbGsstxOB`j+YsFd;qRw>NK|Vc|s1 zYw)%?_U0?sYw&Tk_eL2AsT;NoCdiJlUqK}_i{nxQSQhZ)=A`{ z^#jo>HoRnXfAwlt`SeFyPAOY1#Z{q{`%0xTOgrTdhNLU2E^4{==v!GytB+tbPc218 zYnf;8?oC=k>U2g?I#X$?qGqP?zE<`${bI=9DtK(u&$*a|n@KOGS>+A9nE1OczG|s* z((?6zhbp`l7ne||7{zICp^ES6^j% zKXt_Yh)iebxT5bh+=#nxZZf=I!GWe4#F$BVQ@>t31_vi;GI^ZE+j1Rk4zcO1Fk+I= z=i|3&hSagag0yQQvTqMo%}r%62QlfIh=C%uWFfKJFjnYsf4pkE)flTTTcroS?p|3` zI3w&@^6n%qC=s{W)swxJ9|Edt7~G!^dq3x$01u;s@m;}wD+`adq;u^sA)fk-w0xvv zF%9ft6!F_if1$EZwu05KrC16_HQNIpWSZsQ!qyKT616(i747QIB_wMobm(l55GM5K z>2tU4H8`+X>oo*oC81{`({qkh?Np7)Qkx31HI)Yp&HFPd79&XC8#*;(Rdfn!5%d~& z$xB9Bwb^~`9B*-%&>a|BCZfqiH2+>1ew{qms(yq%4w>I4>bycMSC?$0U}>q(OG~Vu z-KEUA40~#`T{eu4 zy)nO{)X)*J=BM-2W9NPD_{-pd#8bH?b>`03BaRu+z!o}) zR~phA5;Ib$`Int=qEcg4sgToE@PvMuNSS)dnZ>JWeHSy4(E%pqEDG%DOb?P<+=S?) zByto3QHPBTXJ?sMbt80^m{F}u?T>9cs2Vi+1k=|dyp!9wvAUGKjByhk&K&;G_mg%3 o{VFdgUKJZTuI!a17F)C<+%n+Bv>bi-yWqdJG(T%re#)Er58YPAXaE2J 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)CWil>WXh=pKn=-q6YP?7&< z-?&dY+wK`H9NGLL_<)w1XFx!9^CH13EJw1s5*!8oH)XlLI@Z48in`zz$DDYRjnm8) zdTDNq$~d@Xp=svDRVad!{p)@3KIv@~wtAhIvrNK*EM!sJHzS6e?Sm;iIjbJ#*&RACcSkzz+3MIRl{I8lAHJT=m6o2=2x8}H{|x?uQ*cjJ#)9#4P1%>Q`m#TiCE-$tv({s;G? zR+Vi#`|{VLJ9XbT9)8h(;Gnpw-)j1`WHK+Fo1FOcMA=!XlKDE@mwZvJcE0&D z=X}z7tMJVK{D0GTILx}zYWtrpuD0^`hu5*WdxMe;^-SNs|Fhm=zU<*g&s;_3zP>SS zm$ad6wLQAsF@eFI>KE4U`f~nl@j-A6p0ZUw87}SNq9AVt(>& z#h8nsb6*^unvfPq-cfrejmqj!#?Or+EvG{hc61xeNu7~5Z|c>K3ca0{A`$r(k?X|F8J_V* zYMc+9qFY<!YH6*?UAV6_b))K3w`ynpaF+AEw-wK*P3l?t-$`|~jqG3NTxrn$b1ujb40Sx%cS3 z{0+{or`O2eJ@Bq@kFt(x%b`afKFl!w^FP)6+G#8P-EXA7Tz$jw)~d_AS)}E^=@XqR z>N;Cr>1^m1D%@xJM_|g6A3`s?w=OU}cu%4F-kXbtHrhI0?@ravT=+pc_txt(1!6nr z9WI_}w#Iapx!&cA-t!Cn^Bx`~PkV&p4tO!R4T|wl3g5E2B$B!n!|Ye4wJ+)78&qol`;+0G+PH Ay8r+H 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)DBho_5Uh=pKnXl#Z|sK~!( z=khMi3ea4e?J2SsnauY_p7D?RRBo&FXKT{dXj#EbZOLImX7fds+GK%-s3>&gZ$s=kHtm z;1^7o;mWr@B4r=@u9yYJmZvsl*$4Q1V~=?5d(Ys$n$5p`evt?6vbG$u#lQc)dmH=uPKngD&nNZ=&G>Bh^V4QUAoq5`QQ9_Po1sDEGR;brM&|S2D zIm_u!pDJ1R9Ga$D{ZRO6QOVD(3qP1_&}Y0}aLh3Dp8kQ`Px>~MxN~5AUWr7 z>C36%e}xY?2*(JSZd_V#vu|I8*Q6y0Wz+sV3gyxk{TikyX%iEXP&ct@XXU1%#U~c1 z|J-q*_`Sw)%T)^d4t1+~hKL03l>2L3*7QvNw&T)$b*uRJgCm}{7_u%E3jMacd(7qF|?d8JuJ!!Ugs{dm%m)Y*}qx}0j|JvP|C8+EtRDAi~vbm4G*|8K~ zm(8)$tGs?7=N3zO@%n4a4{u%D)ptrZ{V>~>x3@MQ^>Fw6xH$OmBL%Ai`vRtfu0OOO zNAK3g8T~u%B*d9A^+-?IE1GhAXC?2_yw~r%I9}mRs5;+_7LObuT^)W}&fo{5zP}%E!FlbH8qRVTv0c)9NSp zqz)L)+iSCQ4UdSLe%@uZ8Fhc|uSrl>i@y<_KIiN!UFOsB&YjV}OJ@ds{4>>2-V^gTe~DWM4flGv?F 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)DBtfz}(h=pKmsBcb4sK~!} zvo&QCGc+VjV;j6Xx$i0(9+dFakY0UIs8>7usH?E=1cAkw$vukiLYjOH|23@MWw2E7 zn1ai#BO;;~(NfSAX}jIP=5Zb_}VT`C#;On6P%uh;jwo6=r?V2Rt7 zUKT&`zJJ%1b)6oq%Ifddd3-gWxLRGs>hB5v-a?z{Kc5xWEU8jxZf^Y`(s$~OwbI4- zt|t~c?vs_z@!nk>r?N+{>{suNc}FIS?U;7?y2;g+_=mMWza~dr-_yP0#?CYsk0gtK z?q((O(aRTIcy!I>+5O2MxMj{AP-KdKULd1?^3ClntF<$pBwr1kt>M?MqSX|Bnek ztzLh_C;D0+zj5Scy4`uYe8wZaiLK?F^WqYItUs~!uu`#q$L!nM@Ai8~a_wQ>b*^6J zY~dUJ9}&%m{@&<*yZftslE*KR)iukma@WL(H{SYg^N=|#^V&}Pqm^Q5f2|knoATo5 z#wEuRkINm|TVa>5^LNVU3&|R`E7+p)RjpE~oHUOK(_yTqd2lE-+PXj;ZM42bQ->G&y)?xC-jb&1_pMmv4MEVaYMU z!X*aadV?W+|gO@Yj>_bUgE#DHf>en7C(Kx%f)3}UiSh*)26>m zcrW3?ZQk6Q9Py-G9>-Vt`J6hPm(vEfgcgy9J6EA4L`H*^T%`8(#qv#^%-dOQX%(17GUxn}0x@c~3 z`h?f_9Z5XQXJ1~Qt1iNSuW#y`n&55n6>>@$dz8NYS^fG+m#ya(ufmlr@sD&RdaRSLeUi{<;E(*5-V#FP4015u6qCo_N-NJG3Fx$IOD{@;P?Tc+C8s$WvL zU6r0B(8?UY{Ju?4{1={`rP6F$zHjxt8Q9hz-}K^`Z}?2B<=gMq3Z!!`;=f#PvWfrI Z|6TcAS7*EIy$C9EJzf1=);T3K0RSM(j+_7h literal 0 Hc$@@n2KS>z6@Ei4F)4)FoPjQ=!(doENLP;zwNsA zCCYNe*h$wCw`99fw~!?LGwI&@KmG1`p6{G*dEf7R=X~dRPJ)#MT7XxY7XSbV7-LX2 z%vFLV+?>q0yUza%b73Rfp!ES&L$a$(gC`K>BjCI$OIpt`!c5Dgdv22*Du z)XCui6dYAOfGmHI%cHxI!|2Dc(m@&1k|0udiTW|oH3(m_BD4ID~z_$Q*n zp+r_4aAP9Q2X9aCqWB`A2*~%Y@6ndQ1U&OXS=aU#{C|CiX2;+OKE9N%CHUe#AC*bZU0N`kfG3vanj)`2zrI%-1qG>Yb!F$!D-7;9#9VIq+VO3@ zHx(OC;g2K4w>0A1ogc-RCS>*IIRZCnQ+ZxU;sC z-=G;4J=$1Y#?F49%Mpq@0sH7WR6|`&^Hr1Nip-W$>KLxK+4h~fP`_)}UNiA5cx_N) zG|E}DjI*5m2w67IBn38*lrJ$Uy|-nKVPEn~fsLgH6$fdm&9w{}%x&y%zPjbMQ~bL? z;#il(=vD4ybV{H?*fs0IJln4Sh?YkFAvL?F#}0(Als$hKn=N##P$fswzkB)80HI9wcFB+XuBJW=Ibn& z`5=6<$7Vvmq;K53;z1*NXK~G+D7g9nyZXKi>}~4wB&A7g<~r!abt!}7pfiVZKHUbVp2)LxqofCFc6%u_Yb_krDiv zrSW}Fr(Z6COJ!8}LeyHKvy}`j>IL^A&Paj)I77ky)zz0g39I@7>6=sOCzpv{@m_64 zrgk#(RG3tXM*e{Qa8I!Xd<@Mx|~gc9ULboXBf# zSQ(J_)@3-8ElBy?`?%FV+Kf6w{IFK7<(yViu*7GoNF#YVG%^?2XwDZ&6Lg1E3qK1L z9+gVVZFQneD;@PHe&^gM`ZA5G!e9jZ-&U{(niPncwKU3n;#Nq_%XkjWsa?t2B11Of ztM2vX#39U?!1x~d*@;!p^KV3bOa{*|dWxS`VfPkxUbLlRlBI6X&rZ5E zpJ@eRW@#wniZZq*dX*Yj4rx2XPK;tfJ5|%A>YSb=c<^TPfPIsc@^spuC)Y0}%LR_3 z!aD^rtDDjLzC_@caq*6nMb9lt(3pU}pM*9fYYhQYM4KE*8uOW;^J?X`%KD9)8jVaM zeidsf=(qd?uQqNP}mRj25NzHAgq721sL6j$>v! zcild|-3XJ+4!vX~1kZU#8Aqc@{@_y#AI{Gc2`=rl-f&k3xwriajrMMjH{`ic743Jj zGmNiv7XH3lS}nFXO((dvhNkZ*XH4H!PDm$zKHab{w`m<=@?2hFPUJ?^ZtCGK4GQ<#=IWDQi$wiq3 zC7Jno3Lt)BQhsTPt&$Q{4Fo{lnOgw2D6bgmE1>`MD-sLz4fPE4v1uyFOiRPA3nT;4 zW{1#c1GL1-xhOTUB)=#mKR?IL5u{$hGdD3kH7GSPrP4+pT?LY6kdapYMVYBUzk+;Z zXK163AqMlkKAQI-VXF@fTstnHO|XcvbSYs)*pS#oe+|6(6bVV0^E=YfN=6mh)GnU51jCq%~ zyh}5W)S8*!s;GKpiQ{&`w+ga~v(E9psg&V}bXt+ez`O9;FaHZm@*m!L&i}}&Yci+K zxy5F_7EE&Q-|xD=Y0cUx7q*>RW#J*{&C@@<+muX@0`5V z>(Jf1Z;!sMuP%(9tN-V3*_@E{O_3S}bp;hKs@l^&t!;n4_gkFV+L_Duw7kkBQ>KDcc}kVZTN9#)oI-;%27b|80vj zS|+r2e_mC`tpdNSi`%yp9$w_oIiG2=*b@bD(}2|~cdQ;Bn6l(z!}A|a%^Z8@as()R zzjj6^*{QPMYr@`bC$|gk=D*JKOj!RxgACsu!Q6>qh1D4c)TTsx>voIo$mUYftDSqt z!ac(>mB)3Tv9IY*%a?G@td0yo&Mu{n1=O?+$VA`#~Q$DL;mHNty8Y}O=_s$Qv z#IWPR`O=avEpabon~GA)l*0-h%1!i{v2lCfgcheBmByR0MStq9bZqewXPG?D;K5t< z@HcDc3C6!m*)!+bD{rTa?wu;{_ubm^c{9KNx)>kM(`%!?6c+vNoVvQ<}^Z>zaNfXaDC9o5W|hmTRtc^kg=A7b>wWIBV;aqc^1& z1{}yqTDRTk^{b=XqxavEEevFj)=Zj{;3wS4;<`Zdgwea|a7DF-P^}BwUVUuYt+s_p z;0W_^O`ac)8+bOJaMa6k$@MxS?3PsIYH*3id^YQEqQZ2^4a&17 z*1p%boigu)w%Gm(2BnA5Usab!#jpAI^VGWCe*ZV7Z@aetxKhyXCEFD@xz={dNG|&K zB_W(u{M%eJ-qjromfYENHhRsLDYLpROx@ztZ+3OPr~41--}Rz)_Iq|4y?>TAbFpiV zYpA35+K2}YDWS(2mu^|ByDIax{$9?p8Mq+js30 zv^U+fB(Zkd?9cPNp9deDVJs#vG4+V@@%1@|>yLjid%9L4-i{}{c*6M)H-Bxb=sU1- zb7IIxb@4S{d5@XzS1)>Y#=R~3)Q<(Zb^gzuyZ)>GxUBu7y-q!I*vW}beSg)zgDMYC LS3j3^P6GK4GQ<#=IWDQi$wiq3 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 literal 0 Hc$@MzCV_|S* zE^l&Yo9;Xs0007CNklTJ^-NtaC6FHZ?MqQLnc#`bzHl-0uUx?E;eD6A=A4EMr4#!e*wIqo4I{U@WYAkU9nMX9MZcO%5JaVx zX^-3&hx-=H5h@=|mEU!}Wn4?2Jr^XPR5)?uC(GK>w?AJ=_ge9X!!wsn>i3MghaS76 zE)ir>iMGFV)Ly^;RZ>ix4DyD4b$wE7`OGE~shWnScW^RTOeDSW+;c9d$)pmw1Aq9! zf&-*#>Y6Uf^~RGpc4|PblnBTj+SB#Ghkis*)8~>?aV&|Wg&}nW0Z%;fuc!X8>r;!4 zq*5;_#L+B@2m;_YTmE+9yz}}*5Cl<_#f>oZyGjK}W$F@{bLL$^Pi0#WHI&( zi!YtZmhR3GD$KO2&ED{_SIs!1Pb#RCj@|Q6L$(`6?sN$im~K}KaW>cRycfMJ_|>)@ zN9vNLaQ$umjP9QGB$3^sv#I6A>F zp>zsN521_Df}4V2Fc_NdAAoYkT5nw!W+w1JCNm5L04x>@!O}s5(oX~0Mn*<}77{=r zHH8RGMkI~t8=*;KsBV&c6Xm{sp=X#TaQGHx(>5D1g985TL}P5p z5()%FCxA9W3;510q8C+BczO^;*jdDHs*MKzSNk>#@SkBel>%E*O~Gj3`?HyX9ctAH zAdmzLhqZ7ul%cqJIS}3Ut#=Fxx_ThCyqI41nCN-+l!BW6f&3ACy?kb-zUiH#j)jeJ zaVby=S#l=ULZExsn(U|hJ~puUUPY-{PC0nTn7XXHM!7lorWfR96>DiIe4JC+nj^lH zrSqvaTLZfL{dAIjyK8U07hzo59x`I#s_Pl}%djnwy)=YE}FzU6N|5 z&Krw5^wx_V@usQ!X~Fulsx}%5P}}82p0NtsrLIRzUP`kDC1Lgh#&j(86 zBqbuG3DXCfeqAogP(oSX>aCetEsS$9i+<&6o?K)vT}3y=<;wO?UoA*5R9tWQ1lq&v$A`l&T?$5B1fsy zht?wplREa9e!+$?f2gujwm`~+oc*Z!ZUvkvphD$|a&1r2A2erd&xkt!B}2-%A4dez z-pf=u!O52%EeCZ=A)b&5P3wppG`G((TI*=qhCAjr|J=cYI`P*!+*IoLg8dZ_f>YyN z6l+}^_*2y-K0ZSiN0YI@av?gWpyY&;sw+%kPx?N+fyT5UpCVADLn-{~A-|G3rDkIn zqv^j*Vl&D$+>JD(EiLk5K5GP>>*iXe>^(c*8)T=L z@iwUq{NZs`5@{hf`$0e5!_GL>b7%6xk@UNYD|a>wv6r54ye(e!)Amz?SW{4w-j*sA z3h$-sV;mli9CSo+CTZwIn@Oif7oJ6}?ig<8*O_i#cN*Y4S;VEKB#bQSDfZR{H1v7R z0h3d<_7?WBRvOFv;if$MMI!M|O(c8Vo%j=jh>>DHEGA_v7X1C1J6ulf$KMuT3}5qf zmW>=XV0#`OIG!11Q@(;L`BM3(Ltc*3IOoG;&xaK|-=lq(A48VOGwnZ1B)!A~$%s+F($;AKw 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)D>1Wy;o5DUTF(6`yqsUrXH zR!?4*y;*H;^hJ}&yi-rPgr&b`Dcz=VtMS&Uf+#^5jz{qZb5HpE4VYRd?C4nd+sOKP zOms<4pmrdybMC^%jq7UC?eBd&c<^P*lPmERwG4NkFYo)z>3#0Re1_nA zr#}~*{A^>Ia_;>m^}~}oe*OC~#p-v#jpL89m8L#V-*;4d@BXhFvbnBIJM4E)?efm4 zZ2k<~+kQwaHrghUvQg*MrRmfAtor9WMRUs31Wvk~^kW)B*P4{)883c`o9z73&A;H< zQ3pebRF63c8^zvcTK!7C%^~g)5qslv{-dqax@FvvTUnO*QC_Mes7rY zS9V#lVoFP3s37BXCHJTg-uGO8tPGV7)J?Z8KVQil&a`Kl`8B(*Z`MUje$$=ltgrQY zSEI)Yxpmw7RN4GzUtY2PX7k&NcXJf9eogXn3-v$vO|Hj&mA%Q`3xWsKJFbSCzVBn( z-ZgK9NX!Ju?sJ>H7E8@;5;WV;IP;3@oin~la+MNaC&qHT5cTTk`n$xnxwNA_I*OS` zH0G7Cq}6z+a%X=tMPN(L1hny7P|a{L(7BX4jPaQ1-&th84-d z3C6j6*N%p)Wc|vuRYQ6^cl+@;X@eUL2P@6LC`hjeJfD&!5&q0iIaya*{mGgq$}8F< zW*`0bCaC}Po*0#Ox&NP@eA=|o#_X=?)Z5kD-=z1?7F>B}*|SG2A>DJ$1s%8~U)D*3pz>`D!ur)}xkY_RsR z?H}EiOE}f*Z2_om^=oxc+AMvE6(R=B=$3?!CAA%UhSW1VpqLh-h|9EGi3T<9eg^ds@RhiTBHz(?3jO()~Mi;^u()8>R@< z1d8mi*R*TZtGuhs8E<17z!&xGjqaxO?Ebk&>JnGVud8)Ec_!2=(%kanvPFTXZ!Rz` z?p$_BxFqe7@wu16%}YQ0T=W0pkMiT4&;ObCuUx;BF}He~$(G}*qoS7jE?vCiN9Su3 sO;yul+v^|7uocQI>x#3{tqb_icsQr%@67#Hb)aJ2)78&qol`;+07t#acmMzZ 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)CWs;7%%h=pKmXlzbMsKCE> zd*5z55ViKISCqlUUnw;P3p+2ea~dj&Zb;bDVyAJ?MX=UzqDilvhsoM$F7rc74t`K@ zye!dSfAPvOb;qS#OC7j!xBXw6+4%O_yGw8P?*86)f6ngjyGl20u0A(s=KC{eX3pID z!CvUVG7p`imnZ%SW)w7}EIGCL>DvSMFaG1mz4x%~lftCJzw%$1&cz)F_mmHaXMPhG z|3AU|>*w8arDo<=ET>N8hzaMqY;1n_{Qi9f(lh6aHNG!rl-#Ph{rX--QMcEh9e!WU zz1@CE-M_P^w=<=9Q`^5tF-gg(t@?f^ran_=JIAzkVy`U|W-pER6U6XzSViOKuHZy}LR zQIZk!rkWEokp-(4cpon@VV%BMf<8}fr}c^z$;57hiR9eI?`laW(q;>C;H zqBgUqUNpa_^M`HAkq5s5W?c^Yk@ukT*tNOyrX4*jyXn&R%`Xa^w?aB-}v5?ahM|#Z-6}zp=Jghi9&7F*Nqo00TIXNh1MtH09 zNIk}QE1iGGs=x2Q5V?K%R21@NrN7R3tD#$`;v1zCs+8k%Z5PX$tXpBx8)nNjT)xwk zkiziu`mKp?-?f=na0Y2?2<6?CdN)#8bhecAmfFN{wMTqC;(}Y8JwruzPP+H;)Ys4r zv*g&!Y+2T?=HA)7ezAqM__S$^n{}-xZqO>xeV29T@zZ-!IrD|CD__<&TfXLrV2m_N zm{wrv7mZcX<%=KvJDb2IsWUfWU+r~QR^Lsxen*_U*E-9(MT$-T*QC&_3ZL^@vJ(6G zcABz1UpYNs>vG;s-Lr{(p)=nv&+|?@`AI!pt@p1$*8WTP)LTOZuc@w13c6%n?ltSz zORHONs>8zeSu5A21(x!e%NQ9f`^PNq8S(wrLQqO;HEa&nXW`sO< zb8z>r4sTn3QsC8Ze}=0c*H|3Cd0JC+irbRar*7SHw6JyxU^N$Pk6tVs_rgm}S$Vz8 zDZ%HSk9FstnldNv#;yF9Q!X_+U20sIH_Puz<$_ETnYe_aQ^m|ycYkj4+aAuF@#W~k zK)WZ_C0?Fgx^h+N2RH-#6j%89wb_6Av@pgpW9R0N8?K-J(f?tKpQfzFt=~smrGrwu zYL>axcYpr;C|1UV-?XLr*W(YF(v~}yT?~=<`@C>&&Xb(G2kxkU+m>&fd#W$#W4FDj x@zc5Q{;KlVRLj1wXV`Em(#mJ`wvKiGS#Jh%dp+Ce5C$r{Jzf1=);T3K0RR$Lq_F@1 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)CWs;7%%h=pKmXlzbMsKCE> zd*5z55ViKISCqlUUnw;P3p+2ea~dj&Zb;bDVyAJ?MX=UzqDilvhsoM$F7rc74t`K@ zye!dSfAPvOb;qS#OC7j!xBXw6+4%O_yGw8P?*86)f6ngjyGl20u0A(s=KC{eX3pID z!CvUVG7p`imnZ%SW)w7}EIGCL>DvSMFaG1mz4x%~lftCJzw%$1&cz)F_mmHaXMPhG z|3AU|>*w8arDo<=ET>N8hzaMqY;1n_{Qi9f(lh6aHNG!rl-#Ph{rX--QMcEh9e!WU zz1@CE-M_P^w=<=9Q`^5tF-gg(t@?f^ran_=JIAzkVy`U|W-pER6U6XzSViOKuHZy}LR zQIZk!rkWEokp-(4cpon@VV%BMf<8}fr}c^z$;57hiR9eI?`laW(q;>C;H zqBgUqUNpa_^M`HAkq5s5W?c^Yk@ukT*tNOyrX4*jyXn&R%`Xa^w?aB-}v5?ahM|#Z-6}zp=Jghi9&7F*Nqo00TIXNh1MtH09 zNIk}QE1iGGs=x2Q5V?K%R21@NrN7R3tD#$`;v1zCs+8k%Z5PX$tXpBx8)nNjT)xwk zkiziu`mKp?-?f=na0Y2?2<6?CdN)#8bhecAmfFN{wMTqC;(}Y8JwruzPP+H;)Ys4r zv*g&!Y+2T?=HA)7ezAqM__S$^n{}-xZqO>xeV29T@zZ-!IrD|CD__<&TfXLrV2m_N zm{wrv7mZcX<%=KvJDb2IsWUfWU+r~QR^Lsxen*_U*E-9(MT$-T*QC&_3ZL^@vJ(6G zcABz1UpYNs>vG;s-Lr{(p)=nv&+|?@`AI!pt@p1$*8WTP)LTOZuc@w13c6%n?ltSz zORHONs>8zeSu5A21(x!e%NQ9f`^PNq8S(wrLQqO;HEa&nXW`sO< zb8z>r4sTn3QsC8Ze}=0c*H|3Cd0JC+irbRar*7SHw6JyxU^N$Pk6tVs_rgm}S$Vz8 zDZ%HSk9FstnldNv#;yF9Q!X_+U20sIH_Puz<$_ETnYe_aQ^m|ycYkj4+aAuF@#W~k zK)WZ_C0?Fgx^h+N2RH-#6j%89wb_6Av@pgpW9R0N8?K-J(f?tKpQfzFt=~smrGrwu zYL>axcYpr;C|1UV-?XLr*W(YF(v~}yT?~=<`@C>&&Xb(G2kxkU+m>&fd#W$#W4FDj x@zc5Q{;KlVRLj1wXV`Em(#mJ`wvKiGS#Jh%dp+Ce5C$r{Jzf1=);T3K0RR$Lq_F@1 literal 0 Hc$@MzCV_|S* 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 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)DBkEe@ch=pKlXmmzQs7UPh zGiMi{-D0-U_mWCf>6U;A8e*)jEx#_hCFi(G-{N1WWEb=&U`oK3!;jke1z0~eF8Jac zc+%Zb#I;GoOf)*zAU7a5=*;08K9dZS(`J1+SDSO)&bZvj)75;A<@Yz6zuWzOv-!Fd z`)U^k=cyJlOLaf9UYNu%X`|+Mu`;ImW3LZ?shr3CYH`Hz_o*+Lh3-16n6zy2y0JzI9$kB{N|v3*ku-+1o2xV=38k^6(E z9}nwy{4rd*QHgK9@&gX-wsoQUpMKBivAZlikA?5(!CXsk)2+MaH;6yKU*(>X=^1O& zxky7tMCH@pM;uL0^Y1@jI8pA6r=9-G>2ZShwwUv+(@%N*hj~N3kFhSBuFFETum6QU z8gwmxYW4fc<$vED+%0$5UHQ;A*Lmsd>c9ih#xo6Oi~j$!h2`ZJRp+k@uSI?4+v>$* zXQh=MbX`7q?&NiD_ZjYN|M`&lZANZjvzB_|fdwb_{$pG8zVBen-qyX3Hm|(VDQJBv zwY+DJbCSRKwXZg8!QsmjW0nMERJ?ldHr%eTV7k_sm&>jM{{B@Xa4qzwso9%;V70GR#$QN$e*A?lJ=sb+;Q?pzDFQeM`%f0Z`Za<;A7 z_cpt0d7tHxxqp4fSF7uVvAW&KKW4mZWEbS)`S8_TT;3}_E`P~PKfi^q-to;a)!ApY zW8J-LbN)Yz)?u6<_4K*J-w)rS{WTT_bnH=@<6P8`CX!+_o$u9Q?(VGpJ$vHorYf3z zlV{929aA{xj`y@KmFeNp>sf;T{`1#7Tv-?ACinKF@i|$u=s2JMhHECwofkSy>tlYS zptEbp%)3d`w9koUZu!{asLp4*{LQxtnbYS~dc7vS51kg|q}gfI(^|PkW3BV)S$qDS zP`3SfYQfZ#(@w_uOEJ6)nl`KIb8g@p_Lq{J9?MUiwPL?~IY>fg%E$2dWMA`d)7Sgo zw>T+!AuzT4rG5YXlVL^LmD$^q;uF1GEOY8OkEkc)I$ztaD0e0svZ1r=$P? literal 0 Hc$@!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD8X6a5n0T@z~m3YjNd0( zOkiMOjLZy)D2ed(u}aR*)k{ptPfFFR$Sq(10hlpi<;HsXMd|v6mX?DWr0I{efGYw%=UNO{LKo9DJWb_U74D{hTKN}crUGpSnQv!k zqmLm5bBjKjV<0}&hkDhH%SIm_Y<65ehtwm1k+#m$#WBP}us8H?_mohPx_kYR*CW&K zh@PIQqskv=!pAH_Fy6^UVx%c}R=Tu0Z=-@Yu`StlY-|y0tK(pJ8FV-K( zetEb09Iw3XvMWpLl8+th4LlXGGNeaR)^zGUJL4OrDjxg)9eY`PVB1@V*sJjchZ?dM z^lbWQb7A7|4w@xU&+;UQ`#{PW5tz8XljMKNY$ougz7uPfM z@s-!5ov~0hS*D|~D=1KgX;G=7GEX^q2d;>nbQcFh1lFzjb2U z0#&P!_kM5hDV3>CK0o`+Kj!~m7@}FPOzs!SI{D64UZ?W+*`*#TOnN^9PK7>x9Pm?c z#!Al@osZTSGKOkwC>Oc2%ZgnuTda50k43Hcn}4l)TzTQBXGm4mf_;{JI?+tQNvGW;+*@_y%=urff4$~Z%nV(9 zE~cJq*Vb=*y7AY=uhQ`!B$JzJZ@sabFeQV>d2=p%|8s+&H4$9jJH_68$h;zGp|IhK zd+38>$%)US{F9^4c&o%bT3ePWR4(*g*P+L4GtVlkIS=@*GWgjVO2z#1@``9P%1?L` zy=fVb#+$p9yz9Ov7`^nKbl1b>k^-A?r--(@-h=7_71pmYo#!^PHW(GyeEhTC!lmT3 zQlG!d;?s@OxDJ0l6rBFXGPK8Qo&DOxj;*G``KxH!S9Ozw*ukzI8Enueraj zRrkJImFbOmlE#eJuWe z#w?4=f1B4H;0=m@bLHf`Ba^k~yJhX1k*RNYfA02T^)q4n0u&EREqLSATRB0x_twFg z%UT!z{vG(^<#XdB)~RQoC|{XgyFS^4|4)i8v3uCHNm9zp{MNU-D(Bp|vo!mn ztWP_Z-BQ<4ZE@OoX6e*TZ_Ezo94a_e_GJ4iUss3Cvh7_<&XseB+8H=L4}G(wyGHBE z^t<&5H@@&sFgf~NPO1IR&Fs8wd#i&T>=~b(IVOBJbA1!{{BIL}{faK1EAi(~cc-*Ik{rx=l$$E&-ruzy}hkIe(yfsb#1}A8xsyEM%}q3|58w4 zCX?CmYx!08yqAVmpL7X|o1!^2XFl7@)9KymyXyDw%~^6@mvO>u;S2jd*E6QuFeX3n RG;RY`0-mmZF6*2UngHrL<6Qs% literal 0 Hc$@W+$BJ8w_rgg7A(O-a0?#X-Tjia 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%0DT-OvSZ!fG? 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 0: + self.proComEndDate.setCurrentIndex(self.proComEndDate.count() - stopIndex - 1) + else: + self.proComEndDate.setCurrentIndex(self.proComEndDate.count() - 1) + + @pyqtSignature("int") + def on_proComEndDate_activated(self, index): + """ + SELECCION DEL RANGO DE FECHAS-END DATE + """ + pass + + @pyqtSignature("") + def on_proOk_clicked(self): + """ + Añade al Obj XML de Projecto, name,datatype,date,time,readmode,wait,etc, crea el readUnitProcess del archivo xml. + Prepara la configuración del diágrama del Arbol del treeView numero 2 + """ + + self._disable_play_button() + self._disable_save_button() + + self.console.clear() + + if self.create: + + projectId = self.__getNewProjectId() + + if not projectId: + return 0 + + projectObjView = self.createProjectView(projectId) + + if not projectObjView: + return 0 + + self.create = False + + readUnitObj = self.createReadUnitView(projectObjView) + + if not readUnitObj: + return 0 + + else: + projectObjView = self.updateProjectView() + + if not projectObjView: + return 0 + + projectId = projectObjView.getId() + idReadUnit = projectObjView.getReadUnitId() + readUnitObj = self.updateReadUnitView(projectObjView, idReadUnit) + + if not readUnitObj: + return 0 + + self.__itemTreeDict[projectId].setText(projectObjView.name) + # Project Properties + self.refreshProjectProperties(projectObjView) + # Disable tabProject after finish the creation + + self._enable_play_button() + self._enable_save_button() + + self.console.clear() + self.console.append("The project parameters were validated") + + return 1 + + @pyqtSignature("") + def on_proClear_clicked(self): + + self.console.clear() + + @pyqtSignature("int") + def on_volOpCebChannels_stateChanged(self, p0): + """ + Check Box habilita operaciones de Selecci�n de Canales + """ + if p0 == 2: + self.volOpComChannels.setEnabled(True) + self.volOpChannel.setEnabled(True) + + if p0 == 0: + self.volOpComChannels.setEnabled(False) + self.volOpChannel.setEnabled(False) +# self.volOpChannel.clear() + + @pyqtSignature("int") + def on_volOpCebHeights_stateChanged(self, p0): + """ + Check Box habilita operaciones de Selecci�n de Alturas + """ + if p0 == 2: + self.volOpHeights.setEnabled(True) + self.volOpComHeights.setEnabled(True) + + if p0 == 0: + self.volOpHeights.setEnabled(False) +# self.volOpHeights.clear() + self.volOpComHeights.setEnabled(False) + + @pyqtSignature("int") + def on_volOpCebSplitter_stateChanged(self, p0): + """ + Name='Splitter', optype='other' + """ + if p0 == 2: + self.volOpSplitter.setEnabled(True) + + if p0 == 0: + self.volOpSplitter.setEnabled(False) + + @pyqtSignature("int") + def on_volOpCebCombiner_stateChanged(self, p0): + """ + Name='Combiner', optype='other' + """ + if p0 == 2: + self.volOpCombiner.setEnabled(True) + + if p0 == 0: + self.volOpCombiner.setEnabled(False) + + @pyqtSignature("int") + def on_volOpCebFilter_stateChanged(self, p0): + """ + Name='Decoder', optype='other' + """ + if p0 == 2: + self.volOpFilter.setEnabled(True) + + if p0 == 0: + self.volOpFilter.setEnabled(False) +# self.volOpFilter.clear() + + @pyqtSignature("int") + def on_volOpCebProfile_stateChanged(self, p0): + """ + Check Box habilita ingreso del rango de Perfiles + """ + if p0 == 2: + self.volOpComProfile.setEnabled(True) + self.volOpProfile.setEnabled(True) + + if p0 == 0: + self.volOpComProfile.setEnabled(False) + self.volOpProfile.setEnabled(False) +# self.volOpProfile.clear() + + @pyqtSignature("int") + def on_volOpComProfile_activated(self, index): + """ + Check Box habilita ingreso del rango de Perfiles + """ + #Profile List + if index == 0: + self.volOpProfile.setToolTip('List of selected profiles. Example: 0, 1, 2, 3, 4, 5, 6, 7') + + #Profile Range + if index == 1: + self.volOpProfile.setToolTip('Minimum and maximum profile index. Example: 0, 7') + + #Profile Range List + if index == 2: + self.volOpProfile.setToolTip('List of profile ranges. Example: (0, 7), (12, 19), (100, 200)') + + @pyqtSignature("int") + def on_volOpCebDecodification_stateChanged(self, p0): + """ + Check Box habilita + """ + if p0 == 2: + self.volOpComCode.setEnabled(True) + self.volOpComMode.setEnabled(True) + if p0 == 0: + self.volOpComCode.setEnabled(False) + self.volOpComMode.setEnabled(False) + + @pyqtSignature("int") + def on_volOpComCode_activated(self, index): + """ + Check Box habilita ingreso + """ + if index == 13: + self.volOpCode.setEnabled(True) + else: + self.volOpCode.setEnabled(False) + + if index == 0: +# code = '' +# self.volOpCode.setText(str(code)) + return + + if index == 1: + code = '(1,1,-1)' + nCode = '1' + nBaud = '3' + if index == 2: + code = '(1,1,-1,1)' + nCode = '1' + nBaud = '4' + if index == 3: + code = '(1,1,1,-1,1)' + nCode = '1' + nBaud = '5' + if index == 4: + code = '(1,1,1,-1,-1,1,-1)' + nCode = '1' + nBaud = '7' + if index == 5: + code = '(1,1,1,-1,-1,-1,1,-1,-1,1,-1)' + nCode = '1' + nBaud = '11' + if index == 6: + code = '(1,1,1,1,1,-1,-1,1,1,-1,1,-1,1)' + nCode = '1' + nBaud = '13' + if index == 7: + code = '(1,1,-1,-1,-1,1)' + nCode = '2' + nBaud = '3' + if index == 8: + code = '(1,1,-1,1,-1,-1,1,-1)' + nCode = '2' + nBaud = '4' + if index == 9: + code = '(1,1,1,-1,1,-1,-1,-1,1,-1)' + nCode = '2' + nBaud = '5' + if index == 10: + code = '(1,1,1,-1,-1,1,-1,-1,-1,-1,1,1,-1,1)' + nCode = '2' + nBaud = '7' + if index == 11: + code = '(1,1,1,-1,-1,-1,1,-1,-1,1,-1,-1 ,-1 ,-1 ,1 ,1,1,-1 ,1 ,1 ,-1 ,1)' + nCode = '2' + nBaud = '11' + if index == 12: + code = '(1,1,1,1,1,-1,-1,1,1,-1,1,-1,1,-1,-1,-1,-1,-1,1,1,-1,-1,1,-1,1,-1)' + nCode = '2' + nBaud = '13' + + code = ast.literal_eval(code) + nCode = int(nCode) + nBaud = int(nBaud) + + code = numpy.asarray(code).reshape((nCode, nBaud)).tolist() + + self.volOpCode.setText(str(code)) + + @pyqtSignature("int") + def on_volOpCebFlip_stateChanged(self, p0): + """ + Check Box habilita ingresode del numero de Integraciones a realizar + """ + if p0 == 2: + self.volOpFlip.setEnabled(True) + if p0 == 0: + self.volOpFlip.setEnabled(False) +# self.volOpFlip.clear() + + @pyqtSignature("int") + def on_volOpCebCohInt_stateChanged(self, p0): + """ + Check Box habilita ingresode del numero de Integraciones a realizar + """ + if p0 == 2: + self.volOpCohInt.setEnabled(True) + if p0 == 0: + self.volOpCohInt.setEnabled(False) +# self.volOpCohInt.clear() + + @pyqtSignature("int") + def on_volOpCebRadarfrequency_stateChanged(self, p0): + """ + Check Box habilita ingresode del numero de Integraciones a realizar + """ + if p0 == 2: + self.volOpRadarfrequency.setEnabled(True) + if p0 == 0: + self.volOpRadarfrequency.clear() + self.volOpRadarfrequency.setEnabled(False) + + @pyqtSignature("") + def on_volOutputToolPath_clicked(self): + dirOutPath = str(QtGui.QFileDialog.getExistingDirectory(self, 'Open Directory', './', QtGui.QFileDialog.ShowDirsOnly)) + self.volOutputPath.setText(dirOutPath) + + @pyqtSignature("") + def on_specOutputToolPath_clicked(self): + dirOutPath = str(QtGui.QFileDialog.getExistingDirectory(self, 'Open Directory', './', QtGui.QFileDialog.ShowDirsOnly)) + self.specOutputPath.setText(dirOutPath) + + @pyqtSignature("") + def on_specHeisOutputToolPath_clicked(self): + dirOutPath = str(QtGui.QFileDialog.getExistingDirectory(self, 'Open Directory', './', QtGui.QFileDialog.ShowDirsOnly)) + self.specHeisOutputPath.setText(dirOutPath) + + @pyqtSignature("") + def on_specHeisOutputMetadaToolPath_clicked(self): + + filename = str(QtGui.QFileDialog.getOpenFileName(self, "Open text file", self.pathWorkSpace, self.tr("Text Files (*.xml)"))) + self.specHeisOutputMetada.setText(filename) + + @pyqtSignature("") + def on_volOpOk_clicked(self): + """ + BUSCA EN LA LISTA DE OPERACIONES DEL TIPO VOLTAJE Y LES A�ADE EL PARAMETRO ADECUADO ESPERANDO LA ACEPTACION DEL USUARIO + PARA AGREGARLO AL ARCHIVO DE CONFIGURACION XML + """ + + checkPath = False + + self._disable_play_button() + self._disable_save_button() + + self.console.clear() + self.console.append("Checking input parameters:\n") + + puObj = self.getSelectedItemObj() + puObj.removeOperations() + + if self.volOpCebRadarfrequency.isChecked(): + value = str(self.volOpRadarfrequency.text()) + format = 'float' + name_operation = 'setRadarFrequency' + name_parameter = 'frequency' + + if not isFloat(value): + self.console.append("Invalid value '%s' for Radar Frequency" %value) + return 0 + + opObj = puObj.addOperation(name=name_operation) + opObj.addParameter(name=name_parameter, value=radarfreq, format=format) + + if self.volOpCebChannels.isChecked(): + + format = 'intlist' + if self.volOpComChannels.currentIndex() == 0: + name_operation = "selectChannels" + name_parameter = 'channelList' + else: + name_operation = "selectChannelsByIndex" + name_parameter = 'channelIndexList' + + value = str(self.volOpChannel.text()) + + if not isIntList(value): + self.console.append("Invalid value '%s' for %s" %(value,name_parameter)) + return 0 + + opObj = puObj.addOperation(name=name_operation) + opObj.addParameter(name=name_parameter, value=value, format=format) + + if self.volOpCebHeights.isChecked(): + value = str(self.volOpHeights.text()) + + if not isFloatRange(value): + self.console.append("Invalid value '%s' for Height range" %value) + return 0 + + valueList = value.split(',') + + if self.volOpComHeights.currentIndex() == 0: + format = 'float' + name_operation = 'selectHeights' + name_parameter1 = 'minHei' + name_parameter2 = 'maxHei' + else: + format = 'int' + name_operation = 'selectHeightsByIndex' + name_parameter1 = 'minIndex' + name_parameter2 = 'maxIndex' + + opObj = puObj.addOperation(name=name_operation) + opObj.addParameter(name=name_parameter1, value=valueList[0], format=format) + opObj.addParameter(name=name_parameter2, value=valueList[1], format=format) + + if self.volOpCebSplitter.isChecked(): + value = str(self.volOpSplitter.text()) + + if not isInt(value): + self.console.append("Invalid value '%s' for Profile Splitter" %value) + return 0 + + opObj = puObj.addOperation(name="SplitProfiles", optype='external') + opObj.addParameter(name='n', value=value, format='int') + + if self.volOpCebProfile.isChecked(): + value = str(self.volOpProfile.text()) + + format = 'intlist' + optype = 'other' + name_operation = 'ProfileSelector' + + if self.volOpComProfile.currentIndex() == 0: + name_parameter = 'profileList' + if self.volOpComProfile.currentIndex() == 1: + name_parameter = 'profileRangeList' + if self.volOpComProfile.currentIndex() == 2: + name_parameter = 'rangeList' + + if not isIntList(value): + self.console.append("Invalid value '%s' for %s" %(value, name_parameter) ) + return 0 + + opObj = puObj.addOperation(name='ProfileSelector', optype='other') + opObj.addParameter(name=name_parameter, value=value, format=format) + + if self.volOpCebCombiner.isChecked(): + value = str(self.volOpCombiner.text()) + + if not isInt(value): + self.console.append("Invalid value '%s' for Profile Combiner" %value) + return 0 + + opObj = puObj.addOperation(name="CombineProfiles", optype='external') + opObj.addParameter(name='n', value=value, format='int') + + if self.volOpCebFilter.isChecked(): + value = str(self.volOpFilter.text()) + + if not isInt(value): + self.console.append("Invalid value '%s' for Filter" %value) + return 0 + + format = 'int' + name_operation = 'filterByHeights' + name_parameter = 'window' + opObj = puObj.addOperation(name=name_operation) + opObj.addParameter(name=name_parameter, value=value, format=format) + + if self.volOpCebDecodification.isChecked(): + name_operation = 'Decoder' + opObj = puObj.addOperation(name=name_operation, optype='other') + + if self.volOpComCode.currentIndex() != 0: + + code = str(self.volOpCode.text()) + + if not isMultiList(code): + self.console.append("Please write a valid Code (Example: [1,1,-1], [1,-1,1])") + return 0 + + real_code = getCode(code) + nCode = len(real_code) + nBaud = len(real_code[0]) + + opObj.addParameter(name='code', value=code, format='intlist') + opObj.addParameter(name='nCode', value=nCode, format='int') + opObj.addParameter(name='nBaud', value=nBaud, format='int') + + name_parameter = 'mode' + format = 'int' + value = str(self.volOpComMode.currentIndex()) + + opObj.addParameter(name=name_parameter, value=value, format=format) + + + if self.volOpCebFlip.isChecked(): + name_operation = 'deFlip' + optype = 'self' + + opObj = puObj.addOperation(name=name_operation, optype=optype) + + value = str(self.volOpFlip.text()) + + if value: + + name_parameter = 'channelList' + format = 'intlist' + + if not isIntList(value): + self.console.append("Invalid value '%s' for '%s'" %(value,name_parameter)) + return 0 + + opObj.addParameter(name=name_parameter, value=value, format=format) + + if self.volOpCebCohInt.isChecked(): + name_operation = 'CohInt' + optype = 'other' + value = str(self.volOpCohInt.text()) + + if not isInt(value): + self.console.append("Invalid value '%s' for '%s'" %(value,name_parameter)) + return 0 + + name_parameter = 'n' + format = 'int' + + opObj = puObj.addOperation(name=name_operation, optype=optype) + opObj.addParameter(name=name_parameter, value=value, format=format) + + if self.volGraphCebshow.isChecked(): + name_operation = 'Scope' + optype = 'other' + + name_parameter1 = 'id' + format1 = 'int' + + opObj = puObj.addOperation(name=name_operation, optype=optype) + opObj.addParameter(name=name_parameter1, value=opObj.id, format=format1) + + channelList = str(self.volGraphChannelList.text()).strip() + xvalue = str(self.volGraphHeightrange.text()).strip() + yvalue = str(self.volGraphIntensityRange.text()).strip() + figpath = str(self.volGraphPath.text()).strip() + figfile = str(self.volGraphPrefix.text()).strip() + + if channelList != "": + if not isIntList(channelList): + self.console.append("Invalid value '%s' for 'Graphics:ChannelList'" %(channelList)) + return 0 + + if xvalue != "": + if not isFloatRange(xvalue): + self.console.append("Invalid value '%s' for 'Graphics:Height-Range'" %(xvalue)) + return 0 + + if yvalue != "": + if not isFloatRange(yvalue): + self.console.append("Invalid value '%s' for 'Graphics:Amplitude-Range'" %(yvalue)) + return 0 + + + if channelList: + opObj.addParameter(name='channelList', value=channelList, format='intlist') + + if xvalue: + xvalueList = xvalue.split(',') + + opObj.addParameter(name='xmin', value=xvalueList[0], format='float') + opObj.addParameter(name='xmax', value=xvalueList[1], format='float') + + if yvalue: + yvalueList = yvalue.split(",") + + opObj.addParameter(name='ymin', value=yvalueList[0], format='int') + opObj.addParameter(name='ymax', value=yvalueList[1], format='int') + + plot_type = self.volComScopeType.currentIndex() + + if plot_type == 0: + opObj.addParameter(name='type', value="iq") + if plot_type == 1: + opObj.addParameter(name='type', value="power") + + if self.volGraphCebSave.isChecked(): + checkPath = True + + opObj.addParameter(name='save', value='1', format='int') + opObj.addParameter(name='figpath', value=figpath, format='str') + + if figfile: + opObj.addParameter(name='figfile', value=value, format='str') + + if checkPath: + + if not figpath: + self.console.clear() + self.console.append("Graphic path should be defined") + return 0 + +# if os.path.isdir(figpath): +# self.console.clear() +# self.console.append("Graphic path does not exist, it has to be created") +# return 0 + + self.console.clear() + + # if something happend + parms_ok, output_path, blocksperfile, profilesperblock = self.checkInputsPUSave(datatype='Voltage') + if parms_ok: + name_operation = 'VoltageWriter' + optype = 'other' + name_parameter1 = 'path' + name_parameter2 = 'blocksPerFile' + name_parameter3 = 'profilesPerBlock' + value1 = output_path + value2 = blocksperfile + value3 = profilesperblock + format = "int" + opObj = puObj.addOperation(name=name_operation, optype=optype) + opObj.addParameter(name=name_parameter1, value=value1) + opObj.addParameter(name=name_parameter2, value=value2, format=format) + opObj.addParameter(name=name_parameter3, value=value3, format=format) + + try: + self.refreshPUProperties(puObj) + except: + self.console.append("An error reading input parameters was found ...Check them!") + return 0 + + self.console.append("Save your project and press Play button to start signal processing") + + self._enable_play_button() + self._enable_save_button() + + return 1 + + @pyqtSignature("") + def on_volGraphClear_clicked(self): + + self.console.clear() + + """ + Voltage Graph + """ + @pyqtSignature("int") + def on_volGraphCebSave_stateChanged(self, p0): + """ + Check Box habilita ingresode del numero de Integraciones a realizar + """ + if p0 == 2: + self.volGraphPath.setEnabled(True) + self.volGraphPrefix.setEnabled(True) + self.volGraphToolPath.setEnabled(True) + + if p0 == 0: + self.volGraphPath.setEnabled(False) + self.volGraphPrefix.setEnabled(False) + self.volGraphToolPath.setEnabled(False) + + @pyqtSignature("") + def on_volGraphToolPath_clicked(self): + """ + Donde se guardan los DATOS + """ + save_path = str(QtGui.QFileDialog.getExistingDirectory(self, 'Open Directory', './', QtGui.QFileDialog.ShowDirsOnly)) + self.volGraphPath.setText(save_path) + + if not os.path.exists(save_path): + self.console.clear() + self.console.append("Set a valid path") + self.volGraphOk.setEnabled(False) + return + + @pyqtSignature("int") + def on_volGraphCebshow_stateChanged(self, p0): + """ + Check Box habilita ingresode del numero de Integraciones a realizar + """ + if p0 == 0: + + self.volGraphChannelList.setEnabled(False) + self.volGraphIntensityRange.setEnabled(False) + self.volGraphHeightrange.setEnabled(False) + if p0 == 2: + + self.volGraphChannelList.setEnabled(True) + self.volGraphIntensityRange.setEnabled(True) + self.volGraphHeightrange.setEnabled(True) + + """ + Spectra operation + """ + @pyqtSignature("int") + def on_specOpCebRadarfrequency_stateChanged(self, p0): + """ + Check Box habilita ingresode del numero de Integraciones a realizar + """ + if p0 == 2: + self.specOpRadarfrequency.setEnabled(True) + if p0 == 0: +# self.specOpRadarfrequency.clear() + self.specOpRadarfrequency.setEnabled(False) + + + @pyqtSignature("int") + def on_specOpCebCrossSpectra_stateChanged(self, p0): + """ + Habilita la opcion de a�adir el par�metro CrossSpectra a la Unidad de Procesamiento . + """ + if p0 == 2: + # self.specOpnFFTpoints.setEnabled(True) + self.specOpComCrossSpectra.setEnabled(True) + self.specOppairsList.setEnabled(True) + + if p0 == 0: + # self.specOpnFFTpoints.setEnabled(False) + self.specOpComCrossSpectra.setEnabled(False) + self.specOppairsList.setEnabled(False) + + @pyqtSignature("int") + def on_specOpCebChannel_stateChanged(self, p0): + """ + Habilita la opcion de a�adir el par�metro numero de Canales a la Unidad de Procesamiento . + """ + if p0 == 2: + self.specOpChannel.setEnabled(True) + self.specOpComChannel.setEnabled(True) + if p0 == 0: + self.specOpChannel.setEnabled(False) + self.specOpComChannel.setEnabled(False) + + @pyqtSignature("int") + def on_specOpCebHeights_stateChanged(self, p0): + """ + Habilita la opcion de a�adir el par�metro de alturas a la Unidad de Procesamiento . + """ + if p0 == 2: + self.specOpComHeights.setEnabled(True) + self.specOpHeights.setEnabled(True) + if p0 == 0: + self.specOpComHeights.setEnabled(False) + self.specOpHeights.setEnabled(False) + + + @pyqtSignature("int") + def on_specOpCebIncoherent_stateChanged(self, p0): + """ + Habilita la opcion de a�adir el par�metro integraciones incoherentes a la Unidad de Procesamiento . + """ + if p0 == 2: + self.specOpIncoherent.setEnabled(True) + if p0 == 0: + self.specOpIncoherent.setEnabled(False) + + @pyqtSignature("int") + def on_specOpCebRemoveDC_stateChanged(self, p0): + """ + Habilita la opcion de a�adir el par�metro remover DC a la Unidad de Procesamiento . + """ + if p0 == 2: + self.specOpComRemoveDC.setEnabled(True) + if p0 == 0: + self.specOpComRemoveDC.setEnabled(False) + + @pyqtSignature("int") + def on_specOpCebgetNoise_stateChanged(self, p0): + """ + Habilita la opcion de a�adir la estimacion de ruido a la Unidad de Procesamiento . + """ + if p0 == 2: + self.specOpgetNoise.setEnabled(True) + + if p0 == 0: + self.specOpgetNoise.setEnabled(False) + + @pyqtSignature("") + def on_specOpOk_clicked(self): + """ + AÑADE OPERACION SPECTRA + """ + + addFTP = False + checkPath = False + + self._disable_play_button() + self._disable_save_button() + + self.console.clear() + self.console.append("Checking input parameters:\n") + + projectObj = self.getSelectedProjectObj() + + if not projectObj: + self.console.append("Please select a project before update it") + return + + puObj = self.getSelectedItemObj() + + puObj.removeOperations() + + if self.specOpCebRadarfrequency.isChecked(): + value = str(self.specOpRadarfrequency.text()) + format = 'float' + name_operation = 'setRadarFrequency' + name_parameter = 'frequency' + + if not isFloat(value): + self.console.clear() + self.console.append("Invalid value [%s] for '%s'" %(value, name_parameter)) + return 0 + + radarfreq = float(value)*1e6 + opObj = puObj.addOperation(name=name_operation) + opObj.addParameter(name=name_parameter, value=radarfreq, format=format) + + inputId = puObj.getInputId() + inputPuObj = projectObj.getProcUnitObj(inputId) + + if inputPuObj.datatype == 'Voltage' or inputPuObj.datatype == 'USRP': + + value = str(self.specOpnFFTpoints.text()) + + if not isInt(value): + self.console.append("Invalid value [%s] for '%s'" %(value, 'nFFTPoints')) + return 0 + + puObj.addParameter(name='nFFTPoints', value=value, format='int') + + value = str(self.specOpProfiles.text()) + if not isInt(value): + self.console.append("Please write a value on Profiles field") + else: + puObj.addParameter(name='nProfiles', value=value, format='int') + + value = str(self.specOpippFactor.text()) + if not isInt(value): + self.console.append("Please write a value on IppFactor field") + else: + puObj.addParameter(name='ippFactor' , value=value , format='int') + + if self.specOpCebCrossSpectra.isChecked(): + name_parameter = 'pairsList' + format = 'pairslist' + value = str(self.specOppairsList.text()) + + if not isPairList(value): + self.console.append("Invalid value [%s] for '%s'" %(value, name_parameter)) + return 0 + + puObj.addParameter(name=name_parameter, value=value, format=format) + + if self.specOpCebHeights.isChecked(): + value = str(self.specOpHeights.text()) + + if not isFloatRange(value): + self.console.append("Invalid value [%s] for Height range" %value) + return 0 + + valueList = value.split(',') + value0 = valueList[0] + value1 = valueList[1] + + if self.specOpComHeights.currentIndex() == 0: + name_operation = 'selectHeights' + name_parameter1 = 'minHei' + name_parameter2 = 'maxHei' + else: + name_operation = 'selectHeightsByIndex' + name_parameter1 = 'minIndex' + name_parameter2 = 'maxIndex' + + format = 'float' + + opObj = puObj.addOperation(name=name_operation) + opObj.addParameter(name=name_parameter1, value=value0, format=format) + opObj.addParameter(name=name_parameter2, value=value1, format=format) + + if self.specOpCebChannel.isChecked(): + + if self.specOpComChannel.currentIndex() == 0: + name_operation = "selectChannels" + name_parameter = 'channelList' + else: + name_operation = "selectChannelsByIndex" + name_parameter = 'channelIndexList' + + format = 'intlist' + value = str(self.specOpChannel.text()) + + if not isIntList(value): + self.console.append("Invalid value [%s] for '%s'" %(value, name_parameter)) + return 0 + + opObj = puObj.addOperation(name=name_operation) + opObj.addParameter(name=name_parameter, value=value, format=format) + + if self.specOpCebIncoherent.isChecked(): + + name_operation = 'IncohInt' + optype = 'other' + + if self.specOpCobIncInt.currentIndex() == 0: + name_parameter = 'timeInterval' + format = 'float' + else: + name_parameter = 'n' + format = 'int' + + value = str(self.specOpIncoherent.text()) + + if not isFloat(value): + self.console.append("Invalid value [%s] for '%s'" %(value, name_parameter)) + return 0 + + opObj = puObj.addOperation(name=name_operation, optype=optype) + opObj.addParameter(name=name_parameter, value=value, format=format) + + if self.specOpCebRemoveDC.isChecked(): + name_operation = 'removeDC' + name_parameter = 'mode' + format = 'int' + + if self.specOpComRemoveDC.currentIndex() == 0: + value = 1 + else: + value = 2 + + opObj = puObj.addOperation(name=name_operation) + opObj.addParameter(name=name_parameter, value=value, format=format) + + if self.specOpCebRemoveInt.isChecked(): + name_operation = 'removeInterference' + opObj = puObj.addOperation(name=name_operation) + + + if self.specOpCebgetNoise.isChecked(): + value = str(self.specOpgetNoise.text()) + valueList = value.split(',') + format = 'float' + name_operation = "getNoise" + opObj = puObj.addOperation(name=name_operation) + + if not value == '': + valueList = value.split(',') + length = len(valueList) + if length == 1: + try: + value1 = float(valueList[0]) + except: + self.console.clear() + self.console.append("Please Write correct parameter Get Noise") + return 0 + name1 = 'minHei' + opObj.addParameter(name=name1, value=value1, format=format) + elif length == 2: + try: + value1 = float(valueList[0]) + value2 = float(valueList[1]) + except: + self.console.clear() + self.console.append("Please Write corrects parameter Get Noise") + return 0 + name1 = 'minHei' + name2 = 'maxHei' + opObj.addParameter(name=name1, value=value1, format=format) + opObj.addParameter(name=name2, value=value2, format=format) + + elif length == 3: + try: + value1 = float(valueList[0]) + value2 = float(valueList[1]) + value3 = float(valueList[2]) + except: + self.console.clear() + self.console.append("Please Write corrects parameter Get Noise") + return 0 + name1 = 'minHei' + name2 = 'maxHei' + name3 = 'minVel' + opObj.addParameter(name=name1, value=value1, format=format) + opObj.addParameter(name=name2, value=value2, format=format) + opObj.addParameter(name=name3, value=value3, format=format) + + elif length == 4: + try: + value1 = float(valueList[0]) + value2 = float(valueList[1]) + value3 = float(valueList[2]) + value4 = float(valueList[3]) + except: + self.console.clear() + self.console.append("Please Write corrects parameter Get Noise") + return 0 + name1 = 'minHei' + name2 = 'maxHei' + name3 = 'minVel' + name4 = 'maxVel' + opObj.addParameter(name=name1, value=value1, format=format) + opObj.addParameter(name=name2, value=value2, format=format) + opObj.addParameter(name=name3, value=value3, format=format) + opObj.addParameter(name=name4, value=value4, format=format) + + elif length > 4: + self.console.clear() + self.console.append("Get Noise Operation only accepts 4 parameters") + return 0 + + channelList = str(self.specGgraphChannelList.text()).strip() + vel_range = str(self.specGgraphFreq.text()).strip() + hei_range = str(self.specGgraphHeight.text()).strip() + db_range = str(self.specGgraphDbsrange.text()).strip() + + trange = str(self.specGgraphTminTmax.text()).strip() + magrange = str(self.specGgraphmagnitud.text()).strip() + phaserange = str(self.specGgraphPhase.text()).strip() + timerange = str(self.specGgraphTimeRange.text()).strip() + + figpath = str(self.specGraphPath.text()).strip() + figfile = str(self.specGraphPrefix.text()).strip() + + try: + wrperiod = int(str(self.specGgraphftpratio.text()).strip()) + except: + wrperiod = None + + #-----Spectra Plot----- + if self.specGraphCebSpectraplot.isChecked() or self.specGraphSaveSpectra.isChecked(): + + opObj = puObj.addOperation(name='SpectraPlot', optype='other') + opObj.addParameter(name='id', value=opObj.id, format='int') + + if channelList: + + if not isList(channelList): + self.console.append("Invalid value [%s] for 'Graphic:ChannelList" %(channelList)) + return 0 + + opObj.addParameter(name='channelList', value=channelList, format='intlist') + + if vel_range: + + if not isFloatRange(vel_range): + self.console.append("Invalid value [%s] for 'Graphic:Velocity-Range" %(vel_range)) + return 0 + + xvalueList = vel_range.split(',') + value1 = float(xvalueList[0]) + value2 = float(xvalueList[1]) + + opObj.addParameter(name='xmin', value=value1, format='float') + opObj.addParameter(name='xmax', value=value2, format='float') + + if hei_range: + + if not isFloatRange(hei_range): + self.console.append("Invalid value [%s] for 'Graphic:Height-Range" %(hei_range)) + return 0 + + yvalueList = hei_range.split(",") + value1 = float(yvalueList[0]) + value2 = float(yvalueList[1]) + + opObj.addParameter(name='ymin', value=value1, format='float') + opObj.addParameter(name='ymax', value=value2, format='float') + + if db_range: + + if not isFloatRange(db_range): + self.console.append("Invalid value [%s] for 'Graphic:dB-Range" %(db_range)) + return 0 + + zvalueList = db_range.split(",") + value1 = float(zvalueList[0]) + value2 = float(zvalueList[1]) + + opObj.addParameter(name='zmin', value=value1, format='float') + opObj.addParameter(name='zmax', value=value2, format='float') + + if not self.specGraphCebSpectraplot.isChecked(): + + opObj.addParameter(name='show', value=0 , format='bool') + + if self.specGraphSaveSpectra.isChecked(): + + checkPath = True + opObj.addParameter(name='save', value=1 , format='bool') + opObj.addParameter(name='figpath', value=figpath, format='str') + if figfile: + opObj.addParameter(name='figfile', value=figfile, format='str') + if wrperiod: + opObj.addParameter(name='wr_period', value=wrperiod,format='int') + + if self.specGraphftpSpectra.isChecked(): + + opObj.addParameter(name='ftp', value='1', format='int') + self.addFTPConf2Operation(puObj, opObj) + addFTP = True + + if self.specGraphCebCrossSpectraplot.isChecked() or self.specGraphSaveCross.isChecked(): + + opObj = puObj.addOperation(name='CrossSpectraPlot', optype='other') + opObj.addParameter(name='id', value=opObj.id, format='int') + + if vel_range: + + if not isFloatRange(vel_range): + self.console.append("Invalid value [%s] for 'Graphic:Velocity-Range" %(vel_range)) + return 0 + + xvalueList = vel_range.split(',') + value1 = float(xvalueList[0]) + value2 = float(xvalueList[1]) + + opObj.addParameter(name='xmin', value=value1, format='float') + opObj.addParameter(name='xmax', value=value2, format='float') + + if hei_range: + + if not isFloatRange(hei_range): + self.console.append("Invalid value [%s] for 'Graphic:Height-Range" %(hei_range)) + return 0 + + yvalueList = hei_range.split(",") + value1 = float(yvalueList[0]) + value2 = float(yvalueList[1]) + + opObj.addParameter(name='ymin', value=value1, format='float') + opObj.addParameter(name='ymax', value=value2, format='float') + + if db_range: + + if not isFloatRange(db_range): + self.console.append("Invalid value [%s] for 'Graphic:dB-Range" %(db_range)) + return 0 + + zvalueList = db_range.split(",") + value1 = float(zvalueList[0]) + value2 = float(zvalueList[1]) + + opObj.addParameter(name='zmin', value=value1, format='float') + opObj.addParameter(name='zmax', value=value2, format='float') + + if magrange: + + if not isFloatRange(magrange): + self.console.append("Invalid value [%s] for 'Graphic:Magnitud-Range" %(magrange)) + return 0 + + zvalueList = magrange.split(",") + value1 = float(zvalueList[0]) + value2 = float(zvalueList[1]) + + opObj.addParameter(name='coh_min', value=value1, format='float') + opObj.addParameter(name='coh_max', value=value2, format='float') + + if phaserange: + + if not isFloatRange(phaserange): + self.console.append("Invalid value [%s] for 'Graphic:Phase-Range" %(phaserange)) + return 0 + + zvalueList = phaserange.split(",") + value1 = float(zvalueList[0]) + value2 = float(zvalueList[1]) + + opObj.addParameter(name='phase_min', value=value1, format='float') + opObj.addParameter(name='phase_max', value=value2, format='float') + + if not self.specGraphCebCrossSpectraplot.isChecked(): + + opObj.addParameter(name='show', value=0 , format='bool') + + if self.specGraphSaveCross.isChecked(): + + checkPath = True + opObj.addParameter(name='save', value='1', format='bool') + opObj.addParameter(name='figpath', value=figpath, format='str') + if figfile: + opObj.addParameter(name='figfile', value=figfile, format='str') + if wrperiod: + opObj.addParameter(name='wr_period', value=wrperiod,format='int') + + if self.specGraphftpCross.isChecked(): + + opObj.addParameter(name='ftp', value='1', format='int') + self.addFTPConf2Operation(puObj, opObj) + addFTP = True + + if self.specGraphCebRTIplot.isChecked() or self.specGraphSaveRTIplot.isChecked(): + + opObj = puObj.addOperation(name='RTIPlot', optype='other') + opObj.addParameter(name='id', value=opObj.id, format='int') + + if channelList: + + if not isIntList(channelList): + self.console.append("Invalid value [%s] for 'Graphic:ChannelList" %(channelList)) + return 0 + + opObj.addParameter(name='channelList', value=channelList, format='intlist') + + if trange: + + if not isFloatRange(trange): + self.console.append("Invalid value [%s] for 'Graphic:Time-Range" %(trange)) + return 0 + + zvalueList = trange.split(",") + value1 = float(zvalueList[0]) + value2 = float(zvalueList[1]) + + opObj.addParameter(name='xmin', value=value1, format='float') + opObj.addParameter(name='xmax', value=value2, format='float') + + if timerange: + try: + timerange = int(timerange) + except: + return 0 + opObj.addParameter(name='timerange', value=timerange, format='int') + + if hei_range: + + if not isFloatRange(hei_range): + self.console.append("Invalid value [%s] for 'Graphic:Height-Range" %(hei_range)) + return 0 + + yvalueList = hei_range.split(",") + value1 = float(yvalueList[0]) + value2 = float(yvalueList[1]) + + opObj.addParameter(name='ymin', value=value1, format='float') + opObj.addParameter(name='ymax', value=value2, format='float') + + if db_range: + + if not isFloatRange(db_range): + self.console.append("Invalid value [%s] for 'Graphic:dB-Range" %(db_range)) + return 0 + + zvalueList = db_range.split(",") + value1 = float(zvalueList[0]) + value2 = float(zvalueList[1]) + + opObj.addParameter(name='zmin', value=value1, format='float') + opObj.addParameter(name='zmax', value=value2, format='float') + + if not self.specGraphCebRTIplot.isChecked(): + + opObj.addParameter(name='show', value=0 , format='bool') + + if self.specGraphSaveRTIplot.isChecked(): + + checkPath = True + opObj.addParameter(name='save', value='1', format='bool') + opObj.addParameter(name='figpath', value=figpath, format='str') + if figfile: + opObj.addParameter(name='figfile', value=value, format='str') + if wrperiod: + opObj.addParameter(name='wr_period', value=wrperiod,format='int') + + if self.specGraphftpRTIplot.isChecked(): + + opObj.addParameter(name='ftp', value='1', format='int') + self.addFTPConf2Operation(puObj, opObj) + addFTP = True + + if self.specGraphCebCoherencmap.isChecked() or self.specGraphSaveCoherencemap.isChecked(): + + opObj = puObj.addOperation(name='CoherenceMap', optype='other') + opObj.addParameter(name='id', value=opObj.id, format='int') + + if trange: + + if not isFloatRange(trange): + self.console.append("Invalid value [%s] for 'Graphic:Time-Range" %(trange)) + return 0 + + zvalueList = trange.split(",") + value1 = float(zvalueList[0]) + value2 = float(zvalueList[1]) + + opObj.addParameter(name='xmin', value=value1, format='float') + opObj.addParameter(name='xmax', value=value2, format='float') + + if hei_range: + + if not isFloatRange(hei_range): + self.console.append("Invalid value [%s] for 'Graphic:Height-Range" %(hei_range)) + return 0 + + yvalueList = hei_range.split(",") + value1 = float(yvalueList[0]) + value2 = float(yvalueList[1]) + + opObj.addParameter(name='ymin', value=value1, format='float') + opObj.addParameter(name='ymax', value=value2, format='float') + + if magrange: + + if not isFloatRange(magrange): + self.console.append("Invalid value [%s] for 'Graphic:Magnitud-Range" %(magrange)) + return 0 + + zvalueList = magrange.split(",") + value1 = float(zvalueList[0]) + value2 = float(zvalueList[1]) + + opObj.addParameter(name='zmin', value=value1, format='float') + opObj.addParameter(name='zmax', value=value2, format='float') + + if phaserange: + + if not isFloatRange(phaserange): + self.console.append("Invalid value [%s] for 'Graphic:Phase-Range" %(phaserange)) + return 0 + + zvalueList = phaserange.split(",") + value1 = float(zvalueList[0]) + value2 = float(zvalueList[1]) + + opObj.addParameter(name='phase_min', value=value1, format='float') + opObj.addParameter(name='phase_max', value=value2, format='float') + + if not self.specGraphCebCoherencmap.isChecked(): + opObj.addParameter(name='show', value=0 , format='bool') + + if self.specGraphSaveCoherencemap.isChecked(): + checkPath = True + opObj.addParameter(name='save', value='1', format='bool') + opObj.addParameter(name='figpath', value=figpath, format='str') + if figfile: + opObj.addParameter(name='figfile', value=value, format='str') + if wrperiod: + opObj.addParameter(name='wr_period', value=wrperiod,format='int') + + if self.specGraphftpCoherencemap.isChecked(): + opObj.addParameter(name='ftp', value='1', format='int') + self.addFTPConf2Operation(puObj, opObj) + addFTP = True + + if self.specGraphPowerprofile.isChecked() or self.specGraphSavePowerprofile.isChecked(): + + opObj = puObj.addOperation(name='PowerProfilePlot', optype='other') + opObj.addParameter(name='id', value=opObj.id, format='int') + + if channelList: + + if not isList(channelList): + self.console.append("Invalid value [%s] for 'Graphic:ChannelList" %(channelList)) + return 0 + + opObj.addParameter(name='channelList', value=channelList, format='intlist') + + if hei_range: + + if not isFloatRange(hei_range): + self.console.append("Invalid value [%s] for 'Graphic:Height-Range" %(hei_range)) + return 0 + + yvalueList = hei_range.split(",") + value1 = float(yvalueList[0]) + value2 = float(yvalueList[1]) + + opObj.addParameter(name='ymin', value=value1, format='float') + opObj.addParameter(name='ymax', value=value2, format='float') + + if db_range: + + if not isFloatRange(db_range): + self.console.append("Invalid value [%s] for 'Graphic:dB-Range" %(db_range)) + return 0 + + zvalueList = db_range.split(",") + value1 = float(zvalueList[0]) + value2 = float(zvalueList[1]) + + opObj.addParameter(name='xmin', value=value1, format='float') + opObj.addParameter(name='xmax', value=value2, format='float') + + if not self.specGraphPowerprofile.isChecked(): + opObj.addParameter(name='show', value=0 , format='bool') + + if self.specGraphSavePowerprofile.isChecked(): + checkPath = True + opObj.addParameter(name='save', value='1', format='bool') + opObj.addParameter(name='figpath', value=figpath, format='str') + if figfile: + opObj.addParameter(name='figfile', value=value, format='str') + if wrperiod: + opObj.addParameter(name='wr_period', value=wrperiod,format='int') + + if self.specGraphftpPowerprofile.isChecked(): + opObj.addParameter(name='ftp', value='1', format='int') + self.addFTPConf2Operation(puObj, opObj) + addFTP = True + # rti noise + + if self.specGraphCebRTInoise.isChecked() or self.specGraphSaveRTInoise.isChecked(): + + opObj = puObj.addOperation(name='Noise', optype='other') + opObj.addParameter(name='id', value=opObj.id, format='int') + + if channelList: + + if not isList(channelList): + self.console.append("Invalid value [%s] for 'Graphic:ChannelList" %(channelList)) + return 0 + + opObj.addParameter(name='channelList', value=channelList, format='intlist') + + if trange: + + if not isFloatRange(trange): + self.console.append("Invalid value [%s] for 'Graphic:Time-Range" %(trange)) + return 0 + + zvalueList = trange.split(",") + value1 = float(zvalueList[0]) + value2 = float(zvalueList[1]) + + opObj.addParameter(name='xmin', value=value1, format='float') + opObj.addParameter(name='xmax', value=value2, format='float') + + if db_range: + + if not isFloatRange(db_range): + self.console.append("Invalid value [%s] for 'Graphic:dB-Range" %(db_range)) + return 0 + + zvalueList = db_range.split(",") + value1 = float(zvalueList[0]) + value2 = float(zvalueList[1]) + + opObj.addParameter(name='ymin', value=value1, format='float') + opObj.addParameter(name='ymax', value=value2, format='float') + + if not self.specGraphCebRTInoise.isChecked(): + opObj.addParameter(name='show', value=0 , format='bool') + + if self.specGraphSaveRTInoise.isChecked(): + checkPath = True + opObj.addParameter(name='save', value='1', format='bool') + opObj.addParameter(name='figpath', value=figpath, format='str') + if figfile: + opObj.addParameter(name='figfile', value=value, format='str') + if wrperiod: + opObj.addParameter(name='wr_period', value=wrperiod,format='int') + + # test_ftp + if self.specGraphftpRTInoise.isChecked(): + opObj.addParameter(name='ftp', value='1', format='int') + self.addFTPConf2Operation(puObj, opObj) + addFTP = True + + if checkPath: + if not figpath: + self.console.clear() + self.console.append("Graphic path should be defined") + return 0 + + if addFTP and not figpath: + self.console.clear() + self.console.append("You have to save the plots before sending them to FTP Server") + return 0 + + self.console.clear() + +# if something happend + parms_ok, output_path, blocksperfile, profilesperblock = self.checkInputsPUSave(datatype='Spectra') + if parms_ok: + opObj = puObj.addOperation(name='SpectraWriter', optype='other') + opObj.addParameter(name='path', value=output_path) + opObj.addParameter(name='blocksPerFile', value=blocksperfile, format='int') + + try: + self.refreshPUProperties(puObj) + except: + self.console.append("An error reading input parameters was found ... Check them!") + return 0 + + self.console.append("Save your project and press Play button to start signal processing") + + self._enable_play_button() + self._enable_save_button() + + return 1 + + + @pyqtSignature("") + def on_specGraphClear_clicked(self): + + self.console.clear() + + """ + Spectra Graph + """ + @pyqtSignature("int") + def on_specGraphCebSpectraplot_stateChanged(self, p0): + + self.__checkSpecGraphFilters() + + + @pyqtSignature("int") + def on_specGraphCebCrossSpectraplot_stateChanged(self, p0): + + self.__checkSpecGraphFilters() + + @pyqtSignature("int") + def on_specGraphCebRTIplot_stateChanged(self, p0): + + self.__checkSpecGraphFilters() + + + @pyqtSignature("int") + def on_specGraphCebRTInoise_stateChanged(self, p0): + + self.__checkSpecGraphFilters() + + + @pyqtSignature("int") + def on_specGraphCebCoherencmap_stateChanged(self, p0): + + self.__checkSpecGraphFilters() + + @pyqtSignature("int") + def on_specGraphPowerprofile_stateChanged(self, p0): + + self.__checkSpecGraphFilters() + + @pyqtSignature("int") + def on_specGraphPhase_stateChanged(self, p0): + + self.__checkSpecGraphFilters() + + @pyqtSignature("int") + def on_specGraphSaveSpectra_stateChanged(self, p0): + """ + """ + self.__checkSpecGraphFilters() + self.__checkSpecGraphSaving() + + @pyqtSignature("int") + def on_specGraphSaveCross_stateChanged(self, p0): + + self.__checkSpecGraphFilters() + self.__checkSpecGraphSaving() + + @pyqtSignature("int") + def on_specGraphSaveRTIplot_stateChanged(self, p0): + + self.__checkSpecGraphFilters() + self.__checkSpecGraphSaving() + + @pyqtSignature("int") + def on_specGraphSaveRTInoise_stateChanged(self, p0): + + self.__checkSpecGraphFilters() + self.__checkSpecGraphSaving() + + @pyqtSignature("int") + def on_specGraphSaveCoherencemap_stateChanged(self, p0): + + self.__checkSpecGraphFilters() + self.__checkSpecGraphSaving() + + @pyqtSignature("int") + def on_specGraphSavePowerprofile_stateChanged(self, p0): + + self.__checkSpecGraphFilters() + self.__checkSpecGraphSaving() + + @pyqtSignature("int") + def on_specGraphftpSpectra_stateChanged(self, p0): + """ + """ + self.__checkSpecGraphFTP() + + + @pyqtSignature("int") + def on_specGraphftpCross_stateChanged(self, p0): + + self.__checkSpecGraphFTP() + + @pyqtSignature("int") + def on_specGraphftpRTIplot_stateChanged(self, p0): + + self.__checkSpecGraphFTP() + + @pyqtSignature("int") + def on_specGraphftpRTInoise_stateChanged(self, p0): + + self.__checkSpecGraphFTP() + + @pyqtSignature("int") + def on_specGraphftpCoherencemap_stateChanged(self, p0): + + self.__checkSpecGraphFTP() + + @pyqtSignature("int") + def on_specGraphftpPowerprofile_stateChanged(self, p0): + + self.__checkSpecGraphFTP() + + @pyqtSignature("") + def on_specGraphToolPath_clicked(self): + """ + """ + save_path = str(QtGui.QFileDialog.getExistingDirectory(self, 'Open Directory', './', QtGui.QFileDialog.ShowDirsOnly)) + self.specGraphPath.setText(save_path) + if not os.path.exists(save_path): + self.console.clear() + self.console.append("Write a valid path") + return + + @pyqtSignature("") + def on_specHeisGraphToolPath_clicked(self): + """ + """ + save_path = str(QtGui.QFileDialog.getExistingDirectory(self, 'Open Directory', './', QtGui.QFileDialog.ShowDirsOnly)) + self.specHeisGraphPath.setText(save_path) + if not os.path.exists(save_path): + self.console.clear() + self.console.append("Write a valid path") + return + + @pyqtSignature("int") + def on_specHeisOpCebIncoherent_stateChanged(self, p0): + """ + Habilita la opcion de a�adir el par�metro integraciones incoherentes a la Unidad de Procesamiento . + """ + if p0 == 2: + self.specHeisOpIncoherent.setEnabled(True) + self.specHeisOpCobIncInt.setEnabled(True) + if p0 == 0: + self.specHeisOpIncoherent.setEnabled(False) + self.specHeisOpCobIncInt.setEnabled(False) + + @pyqtSignature("") + def on_specHeisOpOk_clicked(self): + """ + AÑADE OPERACION SPECTRAHEIS + """ + addFTP = False + checkPath = False + + self._disable_play_button() + self._disable_save_button() + + self.console.clear() + self.console.append("Checking input parameters ...") + + puObj = self.getSelectedItemObj() + puObj.removeOperations() + + if self.specHeisOpCebIncoherent.isChecked(): + value = str(self.specHeisOpIncoherent.text()) + name_operation = 'IncohInt4SpectraHeis' + optype = 'other' + + name_parameter = 'timeInterval' + format = 'float' + + if self.specOpCobIncInt.currentIndex() == 0: + name_parameter = 'timeInterval' + format = 'float' + + if not isFloat(value): + self.console.append("Invalid value '%s' for '%s'" %(value, name_parameter)) + return 0 + + opObj = puObj.addOperation(name=name_operation, optype=optype) + + if not opObj.addParameter(name=name_parameter, value=value, format=format): + self.console.append("Invalid value '%s' for '%s'" %(value, name_parameter)) + return 0 + + channelList = str(self.specHeisGgraphChannelList.text()) + freq_range = str(self.specHeisGgraphXminXmax.text()) + power_range = str(self.specHeisGgraphYminYmax.text()) + time_range = str(self.specHeisGgraphTminTmax.text()) + timerange = str(self.specHeisGgraphTimeRange.text()) + + if self.specHeisGraphCebSpectraplot.isChecked(): + + name_operation = 'SpectraHeisScope' + optype = 'other' + opObj = puObj.addOperation(name=name_operation, optype=optype) + + name_parameter = 'id' + format = 'int' + value = opObj.id + + if not opObj.addParameter(name=name_parameter, value=value, format=format): + self.console.append("Invalid value '%s' for '%s'" %(value, name_parameter)) + return 0 + + if not (channelList == ''): + name_parameter = 'channelList' + format = 'intlist' + + if not isList(channelList): + self.console.append("Invalid value '%s' for '%s'" %(channelList, name_parameter)) + return 0 + + opObj.addParameter(name=name_parameter, value=channelList, format=format) + + if not freq_range == '': + xvalueList = freq_range.split(',') + + if len(xvalueList) != 2: + self.console.append("Invalid value '%s' for '%s'" %(freq_range, "xrange")) + return 0 + + value1 = xvalueList[0] + value2 = xvalueList[1] + + if not isFloat(value1) or not isFloat(value2): + self.console.append("Invalid value '%s' for '%s'" %(freq_range, "xrange")) + return 0 + + name1 = 'xmin' + name2 = 'xmax' + format = 'float' + + opObj.addParameter(name=name1, value=value1, format=format) + opObj.addParameter(name=name2, value=value2, format=format) + + if not power_range == '': + yvalueList = power_range.split(",") + + if len(yvalueList) != 2: + self.console.append("Invalid value '%s' for '%s'" %(power_range, "xrange")) + return 0 + + value1 = yvalueList[0] + value2 = yvalueList[1] + + if not isFloat(value1) or not isFloat(value2): + self.console.append("Invalid value '%s' for '%s'" %(power_range, "yrange")) + return 0 + + name1 = 'ymin' + name2 = 'ymax' + format = 'float' + opObj.addParameter(name=name1, value=value1, format=format) + opObj.addParameter(name=name2, value=value2, format=format) + + if self.specHeisGraphSaveSpectra.isChecked(): + checkPath = True + name_parameter1 = 'save' + name_parameter2 = 'figpath' + name_parameter3 = 'figfile' + value1 = '1' + value2 = str(self.specHeisGraphPath.text()) + value3 = str(self.specHeisGraphPrefix.text()) + format1 = 'bool' + format2 = 'str' + opObj.addParameter(name=name_parameter1, value=value1 , format=format1) + opObj.addParameter(name=name_parameter2, value=value2, format=format2) + if not value3 == "": + try: + value3 = str(self.specHeisGraphPrefix.text()) + except: + self.console.clear() + self.console.append("Please Write prefix") + return 0 + opObj.addParameter(name='figfile', value=str(self.specHeisGraphPrefix.text()), format='str') + + # opObj.addParameter(name=name_parameter3, value=value3, format=format2) + # opObj.addParameter(name='wr_period', value='5',format='int') + + if self.specHeisGraphftpSpectra.isChecked(): + opObj.addParameter(name='ftp', value='1', format='int') + self.addFTPConf2Operation(puObj, opObj) + addFTP = True + + if self.specHeisGraphCebRTIplot.isChecked(): + name_operation = 'RTIfromSpectraHeis' + optype = 'other' + + name_parameter = 'id' + format = 'int' + + opObj = puObj.addOperation(name=name_operation, optype=optype) + value = opObj.id + opObj.addParameter(name=name_parameter, value=value, format=format) + + if not channelList == '': + opObj.addParameter(name='channelList', value=channelList, format='intlist') + + if not time_range == '': + xvalueList = time_range.split(',') + try: + value = float(xvalueList[0]) + value = float(xvalueList[1]) + except: + return 0 + format = 'float' + opObj.addParameter(name='xmin', value=xvalueList[0], format=format) + opObj.addParameter(name='xmax', value=xvalueList[1], format=format) + + if not timerange == '': + format = 'int' + try: + timerange = int(timerange) + except: + return 0 + opObj.addParameter(name='timerange', value=timerange, format=format) + + + if not power_range == '': + yvalueList = power_range.split(",") + try: + value = float(yvalueList[0]) + value = float(yvalueList[1]) + except: + return 0 + + format = 'float' + opObj.addParameter(name='ymin', value=yvalueList[0], format=format) + opObj.addParameter(name='ymax', value=yvalueList[1], format=format) + + if self.specHeisGraphSaveRTIplot.isChecked(): + checkPath = True + opObj.addParameter(name='save', value='1', format='bool') + opObj.addParameter(name='figpath', value=str(self.specHeisGraphPath.text()), format='str') + value = str(self.specHeisGraphPrefix.text()) + if not value == "": + try: + value = str(self.specHeisGraphPrefix.text()) + except: + self.console.clear() + self.console.append("Please Write prefix") + return 0 + opObj.addParameter(name='figfile', value=value, format='str') + + # test_ftp + if self.specHeisGraphftpRTIplot.isChecked(): + opObj.addParameter(name='ftp', value='1', format='int') + self.addFTPConf2Operation(puObj, opObj) + addFTP = True + + localfolder = None + if checkPath: + localfolder = str(self.specHeisGraphPath.text()) + if localfolder == '': + self.console.clear() + self.console.append("Graphic path should be defined") + return 0 + + if addFTP and not localfolder: + self.console.clear() + self.console.append("You should save plots before send them to FTP Server") + return 0 + + # if something happened + parms_ok, output_path, blocksperfile, metadata_file = self.checkInputsPUSave(datatype='SpectraHeis') + if parms_ok: + name_operation = 'FitsWriter' + optype = 'other' + name_parameter1 = 'path' + name_parameter2 = 'dataBlocksPerFile' + name_parameter3 = 'metadatafile' + value1 = output_path + value2 = blocksperfile + value3 = metadata_file + format2 = "int" + format3 = "str" + opObj = puObj.addOperation(name=name_operation, optype=optype) + + opObj.addParameter(name=name_parameter1, value=value1) + + if blocksperfile: + opObj.addParameter(name=name_parameter2, value=value2, format=format2) + + if metadata_file: + opObj.addParameter(name=name_parameter3, value=value3, format=format3) + + self.console.clear() + try: + self.refreshPUProperties(puObj) + except: + self.console.append("An error reading input parameters was found ... Check them!") + return 0 + + self.console.append("Save your project and press Play button to start signal processing") + + self._enable_save_button() + self._enable_play_button() + + return 1 + + @pyqtSignature("") + def on_specHeisGraphClear_clicked(self): + + self.console.clear() + + @pyqtSignature("int") + def on_specHeisGraphCebSpectraplot_stateChanged(self, p0): + + if p0 == 2: + self.specHeisGgraphChannelList.setEnabled(True) + self.specHeisGgraphXminXmax.setEnabled(True) + self.specHeisGgraphYminYmax.setEnabled(True) + if p0 == 0: + self.specHeisGgraphXminXmax.setEnabled(False) + self.specHeisGgraphYminYmax.setEnabled(False) + + @pyqtSignature("int") + def on_specHeisGraphCebRTIplot_stateChanged(self, p0): + + if p0 == 2: + self.specHeisGgraphChannelList.setEnabled(True) + self.specHeisGgraphTminTmax.setEnabled(True) + self.specHeisGgraphYminYmax.setEnabled(True) + self.specHeisGgraphTimeRange.setEnabled(True) + + if p0 == 0: + self.specHeisGgraphTminTmax.setEnabled(False) + self.specHeisGgraphYminYmax.setEnabled(False) + self.specHeisGgraphTimeRange.setEnabled(False) + + @pyqtSignature("int") + def on_specHeisGraphSaveSpectra_stateChanged(self, p0): + """ + """ + if p0 == 2: + self.specHeisGraphPath.setEnabled(True) + self.specHeisGraphPrefix.setEnabled(True) + self.specHeisGraphToolPath.setEnabled(True) + if p0 == 0: + self.specHeisGraphPath.setEnabled(False) + self.specHeisGraphPrefix.setEnabled(False) + self.specHeisGraphToolPath.setEnabled(False) + + @pyqtSignature("int") + def on_specHeisGraphSaveRTIplot_stateChanged(self, p0): + if p0 == 2: + self.specHeisGraphPath.setEnabled(True) + self.specHeisGraphPrefix.setEnabled(True) + self.specHeisGraphToolPath.setEnabled(True) + + @pyqtSignature("int") + def on_specHeisGraphftpSpectra_stateChanged(self, p0): + """ + """ + if p0 == 2: + self.specHeisGgraphftpratio.setEnabled(True) + + if p0 == 0: + self.specHeisGgraphftpratio.setEnabled(False) + + @pyqtSignature("int") + def on_specHeisGraphftpRTIplot_stateChanged(self, p0): + if p0 == 2: + self.specHeisGgraphftpratio.setEnabled(True) + + def __checkSpecGraphSaving(self): + + enable = False + + if self.specGraphSaveSpectra.checkState(): + enable = True + + if self.specGraphSaveCross.checkState(): + enable = True + + if self.specGraphSaveRTIplot.checkState(): + enable = True + + if self.specGraphSaveCoherencemap.checkState(): + enable = True + + if self.specGraphSavePowerprofile.checkState(): + enable = True + + if self.specGraphSaveRTInoise.checkState(): + enable = True + + self.specGraphPath.setEnabled(enable) + self.specGraphPrefix.setEnabled(enable) + self.specGraphToolPath.setEnabled(enable) + + self.specGgraphftpratio.setEnabled(enable) + + def __checkSpecGraphFTP(self): + + enable = False + + if self.specGraphftpSpectra.checkState(): + enable = True + + if self.specGraphftpCross.checkState(): + enable = True + + if self.specGraphftpRTIplot.checkState(): + enable = True + + if self.specGraphftpCoherencemap.checkState(): + enable = True + + if self.specGraphftpPowerprofile.checkState(): + enable = True + + if self.specGraphftpRTInoise.checkState(): + enable = True + +# self.specGgraphftpratio.setEnabled(enable) + + def __checkSpecGraphFilters(self): + + freq = False + height = False + db = False + timerange = False + magnitud = False + phase = False + channelList = False + + if self.specGraphCebSpectraplot.checkState() or self.specGraphSaveSpectra.checkState(): + freq = True + height = True + db = True + channelList = True + + if self.specGraphCebCrossSpectraplot.checkState() or self.specGraphSaveCross.checkState(): + freq = True + height = True + db = True + magnitud = True + phase = True + + if self.specGraphCebRTIplot.checkState() or self.specGraphSaveRTIplot.checkState(): + height = True + db = True + timerange = True + channelList = True + + if self.specGraphCebCoherencmap.checkState() or self.specGraphSaveCoherencemap.checkState(): + height = True + timerange = True + magnitud = True + phase = True + + if self.specGraphPowerprofile.checkState() or self.specGraphSavePowerprofile.checkState(): + height = True + db = True + channelList = True + + if self.specGraphCebRTInoise.checkState() or self.specGraphSaveRTInoise.checkState(): + db = True + timerange = True + channelList = True + + + self.specGgraphFreq.setEnabled(freq) + self.specGgraphHeight.setEnabled(height) + self.specGgraphDbsrange.setEnabled(db) + self.specGgraphTminTmax.setEnabled(timerange) + self.specGgraphTimeRange.setEnabled(timerange) + + self.specGgraphmagnitud.setEnabled(magnitud) + self.specGgraphPhase.setEnabled(phase) + self.specGgraphChannelList.setEnabled(channelList) + + def __getParmsFromProjectWindow(self): + """ + Check Inputs Project: + - project_name + - datatype + - ext + - data_path + - readmode + - delay + - set + - walk + """ + parms_ok = True + + project_name = str(self.proName.text()) + + if project_name == '' or project_name == None: + outputstr = "Enter a project Name" + self.console.append(outputstr) + parms_ok = False + project_name = None + + description = str(self.proDescription.toPlainText()) + + datatype = str(self.proComDataType.currentText()) + + ext = str(self.proDataType.text()) + + dpath = str(self.proDataPath.text()) + + if dpath == '': + outputstr = 'Datapath is empty' + self.console.append(outputstr) + parms_ok = False + dpath = None + + if dpath != None: + if not os.path.isdir(dpath): + outputstr = 'Datapath (%s) does not exist' % dpath + self.console.append(outputstr) + parms_ok = False + dpath = None + + online = int(self.proComReadMode.currentIndex()) + + delay = None + if online==1: + try: + delay = int(str(self.proDelay.text())) + except: + outputstr = 'Delay value (%s) must be a integer number' %str(self.proDelay.text()) + self.console.append(outputstr) + parms_ok = False + + + set = None + value = str(self.proSet.text()) + try: + set = int(value) + except: + pass + + ippKm = None + + value = str(self.proIPPKm.text()) + + try: + ippKm = float(value) + except: + if datatype=="USRP": + outputstr = 'IPP value "%s" must be a float number' % str(self.proIPPKm.text()) + self.console.append(outputstr) + parms_ok = False + + walk = int(self.proComWalk.currentIndex()) + expLabel = str(self.proExpLabel.text()) + + startDate = str(self.proComStartDate.currentText()).strip() + endDate = str(self.proComEndDate.currentText()).strip() + + if not startDate: + parms_ok = False + + if not endDate: + parms_ok = False + +# startDateList = startDate.split("/") +# endDateList = endDate.split("/") +# +# startDate = datetime.date(int(startDateList[0]), int(startDateList[1]), int(startDateList[2])) +# endDate = datetime.date(int(endDateList[0]), int(endDateList[1]), int(endDateList[2])) + + startTime = self.proStartTime.time() + endTime = self.proEndTime.time() + + startTime = str(startTime.toString("H:m:s")) + endTime = str(endTime.toString("H:m:s")) + + projectParms = ProjectParms() + + projectParms.name = project_name + projectParms.description = description + projectParms.datatype = datatype + projectParms.ext = ext + projectParms.dpath = dpath + projectParms.online = online + projectParms.startDate = startDate + projectParms.endDate = endDate + projectParms.startTime = startTime + projectParms.endTime = endTime + projectParms.delay = delay + projectParms.walk = walk + projectParms.expLabel = expLabel + projectParms.set = set + projectParms.ippKm = ippKm + projectParms.parmsOk = parms_ok + + return projectParms + + + def __getParmsFromProjectObj(self, projectObjView): + + parms_ok = True + + project_name, description = projectObjView.name, projectObjView.description + + readUnitObj = projectObjView.getReadUnitObj() + datatype = readUnitObj.datatype + + operationObj = readUnitObj.getOperationObj(name='run') + + dpath = operationObj.getParameterValue(parameterName='path') + startDate = operationObj.getParameterValue(parameterName='startDate') + endDate = operationObj.getParameterValue(parameterName='endDate') + + startDate = startDate.strftime("%Y/%m/%d") + endDate = endDate.strftime("%Y/%m/%d") + + startTime = operationObj.getParameterValue(parameterName='startTime') + endTime = operationObj.getParameterValue(parameterName='endTime') + + startTime = startTime.strftime("%H:%M:%S") + endTime = endTime.strftime("%H:%M:%S") + + online = 0 + try: + online = operationObj.getParameterValue(parameterName='online') + except: + pass + + delay = '' + try: + delay = operationObj.getParameterValue(parameterName='delay') + except: + pass + + walk = 0 + try: + walk = operationObj.getParameterValue(parameterName='walk') + except: + pass + + set = '' + try: + set = operationObj.getParameterValue(parameterName='set') + except: + pass + + expLabel = '' + try: + expLabel = operationObj.getParameterValue(parameterName='expLabel') + except: + pass + + ippKm = '' + if datatype.lower() == 'usrp': + try: + ippKm = operationObj.getParameterValue(parameterName='ippKm') + except: + pass + + projectParms = ProjectParms() + + projectParms.name = project_name + projectParms.description = description + projectParms.datatype = datatype + projectParms.ext = None + projectParms.dpath = dpath + projectParms.online = online + projectParms.startDate = startDate + projectParms.endDate = endDate + projectParms.startTime = startTime + projectParms.endTime = endTime + projectParms.delay=delay + projectParms.walk=walk + projectParms.set=set + projectParms.ippKm=ippKm + projectParms.expLabel = expLabel + projectParms.parmsOk=parms_ok + + return projectParms + + def refreshProjectWindow(self, projectObjView): + + self.proOk.setEnabled(False) + + projectParms = self.__getParmsFromProjectObj(projectObjView) + + index = projectParms.getDatatypeIndex() + + self.proName.setText(projectParms.name) + self.proDescription.clear() + self.proDescription.append(projectParms.description) + + self.on_proComDataType_activated(index=index) + self.proDataPath.setText(projectParms.dpath) + self.proComDataType.setCurrentIndex(index) + self.proComReadMode.setCurrentIndex(projectParms.online) + self.proDelay.setText(str(projectParms.delay)) + self.proSet.setText(str(projectParms.set)) + self.proIPPKm.setText(str(projectParms.ippKm)) + self.proComWalk.setCurrentIndex(projectParms.walk) + self.proExpLabel.setText(str(projectParms.expLabel).strip()) + + self.on_proComReadMode_activated(projectParms.online) + self.on_proComWalk_activated(projectParms.walk) + + dateList = self.loadDays(data_path = projectParms.dpath, + ext = projectParms.getExt(), + walk = projectParms.walk, + expLabel = projectParms.expLabel) + + if not dateList: + return 0 + + try: + startDateIndex = dateList.index(projectParms.startDate) + except: + startDateIndex = 0 + + try: + endDateIndex = dateList.index(projectParms.endDate) + except: + endDateIndex = int(self.proComEndDate.count()-1) + + self.proComStartDate.setCurrentIndex(startDateIndex) + self.proComEndDate.setCurrentIndex(endDateIndex) + + startlist = projectParms.startTime.split(":") + endlist = projectParms.endTime.split(":") + + self.time.setHMS(int(startlist[0]), int(startlist[1]), int(startlist[2])) + self.proStartTime.setTime(self.time) + + self.time.setHMS(int(endlist[0]), int(endlist[1]), int(endlist[2])) + self.proEndTime.setTime(self.time) + + self.proOk.setEnabled(True) + + return 1 + + def __refreshVoltageWindow(self, puObj): + + opObj = puObj.getOperationObj(name='setRadarFrequency') + if opObj == None: + self.volOpRadarfrequency.clear() + self.volOpCebRadarfrequency.setCheckState(0) + else: + value = opObj.getParameterValue(parameterName='frequency') + value = str(float(value)/1e6) + self.volOpRadarfrequency.setText(value) + self.volOpRadarfrequency.setEnabled(True) + self.volOpCebRadarfrequency.setCheckState(QtCore.Qt.Checked) + + opObj = puObj.getOperationObj(name="selectChannels") + + if opObj == None: + opObj = puObj.getOperationObj(name="selectChannelsByIndex") + + if opObj == None: + self.volOpChannel.clear() + self.volOpCebChannels.setCheckState(0) + else: + channelEnabled = False + try: + value = opObj.getParameterValue(parameterName='channelList') + value = str(value)[1:-1] + channelEnabled = True + channelMode = 0 + except: + pass + try: + value = opObj.getParameterValue(parameterName='channelIndexList') + value = str(value)[1:-1] + channelEnabled = True + channelMode = 1 + except: + pass + + if channelEnabled: + self.volOpChannel.setText(value) + self.volOpChannel.setEnabled(True) + self.volOpCebChannels.setCheckState(QtCore.Qt.Checked) + self.volOpComChannels.setCurrentIndex(channelMode) + + opObj = puObj.getOperationObj(name="selectHeights") + if opObj == None: + self.volOpHeights.clear() + self.volOpCebHeights.setCheckState(0) + else: + value1 = str(opObj.getParameterValue(parameterName='minHei')) + value2 = str(opObj.getParameterValue(parameterName='maxHei')) + value = value1 + "," + value2 + self.volOpHeights.setText(value) + self.volOpHeights.setEnabled(True) + self.volOpCebHeights.setCheckState(QtCore.Qt.Checked) + + opObj = puObj.getOperationObj(name="SplitProfiles") + if opObj == None: + self.volOpSplitter.clear() + self.volOpCebSplitter.setCheckState(0) + else: + value = opObj.getParameterValue(parameterName='n') + value = str(value) + self.volOpSplitter.setText(value) + self.volOpSplitter.setEnabled(True) + self.volOpCebSplitter.setCheckState(QtCore.Qt.Checked) + + opObj = puObj.getOperationObj(name="CombineProfiles") + if opObj == None: + self.volOpCombiner.clear() + self.volOpCebCombiner.setCheckState(0) + else: + value = opObj.getParameterValue(parameterName='n') + value = str(value) + self.volOpCombiner.setText(value) + self.volOpCombiner.setEnabled(True) + self.volOpCebCombiner.setCheckState(QtCore.Qt.Checked) + + opObj = puObj.getOperationObj(name="filterByHeights") + if opObj == None: + self.volOpFilter.clear() + self.volOpCebFilter.setCheckState(0) + else: + value = opObj.getParameterValue(parameterName='window') + value = str(value) + self.volOpFilter.setText(value) + self.volOpFilter.setEnabled(True) + self.volOpCebFilter.setCheckState(QtCore.Qt.Checked) + + opObj = puObj.getOperationObj(name="ProfileSelector") + if opObj == None: + self.volOpProfile.clear() + self.volOpCebProfile.setCheckState(0) + else: + for parmObj in opObj.getParameterObjList(): + + if parmObj.name == "profileList": + value = parmObj.getValue() + value = str(value)[1:-1] + self.volOpProfile.setText(value) + self.volOpProfile.setEnabled(True) + self.volOpCebProfile.setCheckState(QtCore.Qt.Checked) + self.volOpComProfile.setCurrentIndex(0) + + if parmObj.name == "profileRangeList": + value = parmObj.getValue() + value = str(value)[1:-1] + self.volOpProfile.setText(value) + self.volOpProfile.setEnabled(True) + self.volOpCebProfile.setCheckState(QtCore.Qt.Checked) + self.volOpComProfile.setCurrentIndex(1) + + if parmObj.name == "rangeList": + value = parmObj.getValue() + value = str(value)[1:-1] + self.volOpProfile.setText(value) + self.volOpProfile.setEnabled(True) + self.volOpCebProfile.setCheckState(QtCore.Qt.Checked) + self.volOpComProfile.setCurrentIndex(2) + + opObj = puObj.getOperationObj(name="Decoder") + self.volOpCode.setText("") + if opObj == None: + self.volOpCebDecodification.setCheckState(0) + else: + self.volOpCebDecodification.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj('code') + + if parmObj == None: + self.volOpComCode.setCurrentIndex(0) + else: + + parmObj1 = opObj.getParameterObj('nCode') + parmObj2 = opObj.getParameterObj('nBaud') + + if parmObj1 == None or parmObj2 == None: + self.volOpComCode.setCurrentIndex(0) + else: + code = ast.literal_eval(str(parmObj.getValue())) + nCode = parmObj1.getValue() + nBaud = parmObj2.getValue() + + code = numpy.asarray(code).reshape((nCode, nBaud)).tolist() + + #User defined by default + self.volOpComCode.setCurrentIndex(13) + self.volOpCode.setText(str(code)) + + if nCode == 1: + if nBaud == 3: + self.volOpComCode.setCurrentIndex(1) + if nBaud == 4: + self.volOpComCode.setCurrentIndex(2) + if nBaud == 5: + self.volOpComCode.setCurrentIndex(3) + if nBaud == 7: + self.volOpComCode.setCurrentIndex(4) + if nBaud == 11: + self.volOpComCode.setCurrentIndex(5) + if nBaud == 13: + self.volOpComCode.setCurrentIndex(6) + + if nCode == 2: + if nBaud == 3: + self.volOpComCode.setCurrentIndex(7) + if nBaud == 4: + self.volOpComCode.setCurrentIndex(8) + if nBaud == 5: + self.volOpComCode.setCurrentIndex(9) + if nBaud == 7: + self.volOpComCode.setCurrentIndex(10) + if nBaud == 11: + self.volOpComCode.setCurrentIndex(11) + if nBaud == 13: + self.volOpComCode.setCurrentIndex(12) + + + opObj = puObj.getOperationObj(name="deFlip") + if opObj == None: + self.volOpFlip.clear() + self.volOpFlip.setEnabled(False) + self.volOpCebFlip.setCheckState(0) + else: + try: + value = opObj.getParameterValue(parameterName='channelList') + value = str(value)[1:-1] + except: + value = "" + + self.volOpFlip.setText(value) + self.volOpFlip.setEnabled(True) + self.volOpCebFlip.setCheckState(QtCore.Qt.Checked) + + opObj = puObj.getOperationObj(name="CohInt") + if opObj == None: + self.volOpCohInt.clear() + self.volOpCebCohInt.setCheckState(0) + else: + value = opObj.getParameterValue(parameterName='n') + self.volOpCohInt.setText(str(value)) + self.volOpCohInt.setEnabled(True) + self.volOpCebCohInt.setCheckState(QtCore.Qt.Checked) + + opObj = puObj.getOperationObj(name='Scope') + if opObj == None: + self.volGraphCebshow.setCheckState(0) + else: + self.volGraphCebshow.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName='channelList') + + if parmObj == None: + self.volGraphChannelList.clear() + else: + value = parmObj.getValue() + value = str(value) + self.volGraphChannelList.setText(value) +# self.volOpChannel.setEnabled(True) + + parmObj1 = opObj.getParameterObj(parameterName='ymin') + parmObj2 = opObj.getParameterObj(parameterName='ymax') + + if parmObj1 == None or parmObj2 ==None: + self.volGraphIntensityRange.clear() + else: + value1 = parmObj1.getValue() + value1 = str(value1) + value2 = parmObj2.getValue() + value2 = str(value2) + value = value1 + "," + value2 + self.volGraphIntensityRange.setText(value) + + parmObj1 = opObj.getParameterObj(parameterName='xmin') + parmObj2 = opObj.getParameterObj(parameterName='xmax') + + if parmObj1 == None or parmObj2 ==None: + self.volGraphHeightrange.clear() + else: + value1 = parmObj1.getValue() + value1 = str(value1) + value2 = parmObj2.getValue() + value2 = str(value2) + value = value1 + "," + value2 + value2 = str(value2) + self.volGraphHeightrange.setText(value) + + parmObj = opObj.getParameterObj(parameterName='type') + + if parmObj == None: + self.volComScopeType.setCurrentIndex(0) + else: + value = parmObj.getValue() + if value == "iq": + self.volComScopeType.setCurrentIndex(0) + if value == "power": + self.volComScopeType.setCurrentIndex(1) + + parmObj = opObj.getParameterObj(parameterName='save') + + if parmObj == None: + self.volGraphCebSave.setCheckState(QtCore.Qt.Unchecked) + else: + value = parmObj.getValue() + if value: + self.volGraphCebSave.setCheckState(QtCore.Qt.Checked) + else: + self.volGraphCebSave.setCheckState(QtCore.Qt.Unchecked) + + parmObj = opObj.getParameterObj(parameterName='figpath') + if parmObj == None: + self.volGraphPath.clear() + else: + value = parmObj.getValue() + path = str(value) + self.volGraphPath.setText(path) + + parmObj = opObj.getParameterObj(parameterName='figfile') + if parmObj == None: + self.volGraphPrefix.clear() + else: + value = parmObj.getValue() + figfile = str(value) + self.volGraphPrefix.setText(figfile) + + # outputVoltageWrite + opObj = puObj.getOperationObj(name='VoltageWriter') + + if opObj == None: + self.volOutputPath.clear() + self.volOutputblocksperfile.clear() + self.volOutputprofilesperblock.clear() + else: + parmObj = opObj.getParameterObj(parameterName='path') + if parmObj == None: + self.volOutputPath.clear() + else: + value = parmObj.getValue() + path = str(value) + self.volOutputPath.setText(path) + + parmObj = opObj.getParameterObj(parameterName='blocksPerFile') + if parmObj == None: + self.volOutputblocksperfile.clear() + else: + value = parmObj.getValue() + blocksperfile = str(value) + self.volOutputblocksperfile.setText(blocksperfile) + + parmObj = opObj.getParameterObj(parameterName='profilesPerBlock') + if parmObj == None: + self.volOutputprofilesperblock.clear() + else: + value = parmObj.getValue() + profilesPerBlock = str(value) + self.volOutputprofilesperblock.setText(profilesPerBlock) + + return + + def __refreshSpectraWindow(self, puObj): + + inputId = puObj.getInputId() + inputPUObj = self.__puObjDict[inputId] + + if inputPUObj.datatype == 'Voltage': + self.specOpnFFTpoints.setEnabled(True) + self.specOpProfiles.setEnabled(True) + self.specOpippFactor.setEnabled(True) + else: + self.specOpnFFTpoints.setEnabled(False) + self.specOpProfiles.setEnabled(False) + self.specOpippFactor.setEnabled(False) + + opObj = puObj.getOperationObj(name='setRadarFrequency') + if opObj == None: + self.specOpRadarfrequency.clear() + self.specOpCebRadarfrequency.setCheckState(0) + else: + value = opObj.getParameterValue(parameterName='frequency') + value = str(float(value)/1e6) + self.specOpRadarfrequency.setText(value) + self.specOpRadarfrequency.setEnabled(True) + self.specOpCebRadarfrequency.setCheckState(QtCore.Qt.Checked) + + opObj = puObj.getOperationObj(name="run") + if opObj == None: + self.specOpnFFTpoints.clear() + self.specOpProfiles.clear() + self.specOpippFactor.clear() + else: + parmObj = opObj.getParameterObj(parameterName='nFFTPoints') + if parmObj == None: + self.specOpnFFTpoints.clear() + else: + self.specOpnFFTpoints.setEnabled(True) + value = opObj.getParameterValue(parameterName='nFFTPoints') + self.specOpnFFTpoints.setText(str(value)) + + parmObj = opObj.getParameterObj(parameterName='nProfiles') + if parmObj == None: + self.specOpProfiles.clear() + else: + self.specOpProfiles.setEnabled(True) + value = opObj.getParameterValue(parameterName='nProfiles') + self.specOpProfiles.setText(str(value)) + + parmObj = opObj.getParameterObj(parameterName='ippFactor') + if parmObj == None: + self.specOpippFactor.clear() + else: + self.specOpippFactor.setEnabled(True) + value = opObj.getParameterValue(parameterName='ippFactor') + self.specOpippFactor.setText(str(value)) + + opObj = puObj.getOperationObj(name="run") + if opObj == None: + self.specOppairsList.clear() + self.specOpCebCrossSpectra.setCheckState(0) + else: + parmObj = opObj.getParameterObj(parameterName='pairsList') + if parmObj == None: + self.specOppairsList.clear() + self.specOpCebCrossSpectra.setCheckState(0) + else: + value = opObj.getParameterValue(parameterName='pairsList') + value = str(value)[1:-1] + self.specOppairsList.setText(str(value)) + self.specOppairsList.setEnabled(True) + self.specOpCebCrossSpectra.setCheckState(QtCore.Qt.Checked) + + opObj = puObj.getOperationObj(name="selectChannels") + + if opObj == None: + opObj = puObj.getOperationObj(name="selectChannelsByIndex") + + if opObj == None: + self.specOpChannel.clear() + self.specOpCebChannel.setCheckState(0) + else: + channelEnabled = False + try: + value = opObj.getParameterValue(parameterName='channelList') + value = str(value)[1:-1] + channelEnabled = True + channelMode = 0 + except: + pass + try: + value = opObj.getParameterValue(parameterName='channelIndexList') + value = str(value)[1:-1] + channelEnabled = True + channelMode = 1 + except: + pass + + if channelEnabled: + self.specOpChannel.setText(value) + self.specOpChannel.setEnabled(True) + self.specOpCebChannel.setCheckState(QtCore.Qt.Checked) + self.specOpComChannel.setCurrentIndex(channelMode) + + opObj = puObj.getOperationObj(name="selectHeights") + if opObj == None: + self.specOpHeights.clear() + self.specOpCebHeights.setCheckState(0) + else: + value1 = int(opObj.getParameterValue(parameterName='minHei')) + value1 = str(value1) + value2 = int(opObj.getParameterValue(parameterName='maxHei')) + value2 = str(value2) + value = value1 + "," + value2 + self.specOpHeights.setText(value) + self.specOpHeights.setEnabled(True) + self.specOpCebHeights.setCheckState(QtCore.Qt.Checked) + + opObj = puObj.getOperationObj(name="IncohInt") + if opObj == None: + self.specOpIncoherent.clear() + self.specOpCebIncoherent.setCheckState(0) + else: + for parmObj in opObj.getParameterObjList(): + if parmObj.name == 'timeInterval': + value = opObj.getParameterValue(parameterName='timeInterval') + self.specOpIncoherent.setText(str(value)) + self.specOpIncoherent.setEnabled(True) + self.specOpCebIncoherent.setCheckState(QtCore.Qt.Checked) + self.specOpCobIncInt.setCurrentIndex(0) + + if parmObj.name == 'n': + value = opObj.getParameterValue(parameterName='n') + self.specOpIncoherent.setText(str(value)) + self.specOpIncoherent.setEnabled(True) + self.specOpCebIncoherent.setCheckState(QtCore.Qt.Checked) + self.specOpCobIncInt.setCurrentIndex(1) + + opObj = puObj.getOperationObj(name="removeDC") + if opObj == None: + self.specOpCebRemoveDC.setCheckState(0) + else: + self.specOpCebRemoveDC.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName='mode') + + value = 1 + if parmObj: + value = parmObj.getValue() + + if value == 1: + self.specOpComRemoveDC.setCurrentIndex(0) + elif value == 2: + self.specOpComRemoveDC.setCurrentIndex(1) + + opObj = puObj.getOperationObj(name="removeInterference") + if opObj == None: + self.specOpCebRemoveInt.setCheckState(0) + else: + self.specOpCebRemoveInt.setCheckState(QtCore.Qt.Checked) + + opObj = puObj.getOperationObj(name='getNoise') + if opObj == None: + self.specOpCebgetNoise.setCheckState(0) + self.specOpgetNoise.clear() + else: + self.specOpCebgetNoise.setCheckState(QtCore.Qt.Checked) + parmObj = opObj.getParameterObj(parameterName='minHei') + if parmObj == None: + self.specOpgetNoise.clear() + value1 = None + else: + value1 = opObj.getParameterValue(parameterName='minHei') + value1 = str(value1) + parmObj = opObj.getParameterObj(parameterName='maxHei') + if parmObj == None: + value2 = None + value = value1 + self.specOpgetNoise.setText(value) + self.specOpgetNoise.setEnabled(True) + else: + value2 = opObj.getParameterValue(parameterName='maxHei') + value2 = str(value2) + parmObj = opObj.getParameterObj(parameterName='minVel') + if parmObj == None: + value3 = None + value = value1 + "," + value2 + self.specOpgetNoise.setText(value) + self.specOpgetNoise.setEnabled(True) + else: + value3 = opObj.getParameterValue(parameterName='minVel') + value3 = str(value3) + parmObj = opObj.getParameterObj(parameterName='maxVel') + if parmObj == None: + value4 = None + value = value1 + "," + value2 + "," + value3 + self.specOpgetNoise.setText(value) + self.specOpgetNoise.setEnabled(True) + else: + value4 = opObj.getParameterValue(parameterName='maxVel') + value4 = str(value4) + value = value1 + "," + value2 + "," + value3 + ',' + value4 + self.specOpgetNoise.setText(value) + self.specOpgetNoise.setEnabled(True) + + self.specGraphPath.clear() + self.specGraphPrefix.clear() + self.specGgraphFreq.clear() + self.specGgraphHeight.clear() + self.specGgraphDbsrange.clear() + self.specGgraphmagnitud.clear() + self.specGgraphPhase.clear() + self.specGgraphChannelList.clear() + self.specGgraphTminTmax.clear() + self.specGgraphTimeRange.clear() + self.specGgraphftpratio.clear() + + opObj = puObj.getOperationObj(name='SpectraPlot') + + if opObj == None: + self.specGraphCebSpectraplot.setCheckState(0) + self.specGraphSaveSpectra.setCheckState(0) + self.specGraphftpSpectra.setCheckState(0) + else: +# operationSpectraPlot = "Enable" + self.specGraphCebSpectraplot.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName='show') + if parmObj: + if not parmObj.getValue(): + self.specGraphCebSpectraplot.setCheckState(0) + + parmObj = opObj.getParameterObj(parameterName='channelList') + if parmObj == None: + self.specGgraphChannelList.clear() + else: + value = opObj.getParameterValue(parameterName='channelList') + channelListSpectraPlot = str(value)[1:-1] + self.specGgraphChannelList.setText(channelListSpectraPlot) + self.specGgraphChannelList.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='xmin') + if parmObj == None: + self.specGgraphFreq.clear() + else: + value1 = opObj.getParameterValue(parameterName='xmin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='xmax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphFreq.setText(value) + self.specGgraphFreq.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='ymin') + if parmObj == None: + self.specGgraphHeight.clear() + else: + value1 = opObj.getParameterValue(parameterName='ymin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='ymax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphHeight.setText(value) + self.specGgraphHeight.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='zmin') + if parmObj == None: + self.specGgraphDbsrange.clear() + else: + value1 = opObj.getParameterValue(parameterName='zmin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='zmax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphDbsrange.setText(value) + self.specGgraphDbsrange.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName="save") + if parmObj == None: + self.specGraphSaveSpectra.setCheckState(0) + else: + self.specGraphSaveSpectra.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="ftp") + if parmObj == None: + self.specGraphftpSpectra.setCheckState(0) + else: + self.specGraphftpSpectra.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="figpath") + if parmObj: + value = parmObj.getValue() + self.specGraphPath.setText(value) + + parmObj = opObj.getParameterObj(parameterName="wr_period") + if parmObj: + value = parmObj.getValue() + self.specGgraphftpratio.setText(str(value)) + + opObj = puObj.getOperationObj(name='CrossSpectraPlot') + + if opObj == None: + self.specGraphCebCrossSpectraplot.setCheckState(0) + self.specGraphSaveCross.setCheckState(0) + self.specGraphftpCross.setCheckState(0) + else: +# operationCrossSpectraPlot = "Enable" + self.specGraphCebCrossSpectraplot.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName='show') + if parmObj: + if not parmObj.getValue(): + self.specGraphCebCrossSpectraplot.setCheckState(0) + + parmObj = opObj.getParameterObj(parameterName='xmin') + if parmObj == None: + self.specGgraphFreq.clear() + else: + value1 = opObj.getParameterValue(parameterName='xmin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='xmax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphFreq.setText(value) + self.specGgraphFreq.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='ymin') + if parmObj == None: + self.specGgraphHeight.clear() + else: + value1 = opObj.getParameterValue(parameterName='ymin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='ymax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphHeight.setText(value) + self.specGgraphHeight.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='zmin') + if parmObj == None: + self.specGgraphDbsrange.clear() + else: + value1 = opObj.getParameterValue(parameterName='zmin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='zmax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphDbsrange.setText(value) + self.specGgraphDbsrange.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='coh_min') + if parmObj == None: + self.specGgraphmagnitud.clear() + else: + value1 = opObj.getParameterValue(parameterName='coh_min') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='coh_max') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphmagnitud.setText(value) + self.specGgraphmagnitud.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='phase_min') + if parmObj == None: + self.specGgraphPhase.clear() + else: + value1 = opObj.getParameterValue(parameterName='phase_min') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='phase_max') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphPhase.setText(value) + self.specGgraphPhase.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName="save") + if parmObj == None: + self.specGraphSaveCross.setCheckState(0) + else: + self.specGraphSaveCross.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="ftp") + if parmObj == None: + self.specGraphftpCross.setCheckState(0) + else: + self.specGraphftpCross.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="figpath") + if parmObj: + value = parmObj.getValue() + self.specGraphPath.setText(value) + + parmObj = opObj.getParameterObj(parameterName="wr_period") + if parmObj: + value = parmObj.getValue() + self.specGgraphftpratio.setText(str(value)) + + opObj = puObj.getOperationObj(name='RTIPlot') + + if opObj == None: + self.specGraphCebRTIplot.setCheckState(0) + self.specGraphSaveRTIplot.setCheckState(0) + self.specGraphftpRTIplot.setCheckState(0) + else: + self.specGraphCebRTIplot.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName='show') + if parmObj: + if not parmObj.getValue(): + self.specGraphCebRTIplot.setCheckState(0) + + parmObj = opObj.getParameterObj(parameterName='channelList') + if parmObj == None: + self.specGgraphChannelList.clear() + else: + value = opObj.getParameterValue(parameterName='channelList') + channelListRTIPlot = str(value)[1:-1] + self.specGgraphChannelList.setText(channelListRTIPlot) + self.specGgraphChannelList.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='xmin') + if parmObj == None: + self.specGgraphTminTmax.clear() + else: + value1 = opObj.getParameterValue(parameterName='xmin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='xmax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphTminTmax.setText(value) + self.specGgraphTminTmax.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='timerange') + if parmObj == None: + self.specGgraphTimeRange.clear() + else: + value1 = opObj.getParameterValue(parameterName='timerange') + value1 = str(value1) + self.specGgraphTimeRange.setText(value1) + self.specGgraphTimeRange.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='ymin') + if parmObj == None: + self.specGgraphHeight.clear() + else: + value1 = opObj.getParameterValue(parameterName='ymin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='ymax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphHeight.setText(value) + self.specGgraphHeight.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='zmin') + if parmObj == None: + self.specGgraphDbsrange.clear() + else: + value1 = opObj.getParameterValue(parameterName='zmin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='zmax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphDbsrange.setText(value) + self.specGgraphDbsrange.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName="save") + if parmObj == None: + self.specGraphSaveRTIplot.setCheckState(0) + else: + self.specGraphSaveRTIplot.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="ftp") + if parmObj == None: + self.specGraphftpRTIplot.setCheckState(0) + else: + self.specGraphftpRTIplot.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="figpath") + if parmObj: + value = parmObj.getValue() + self.specGraphPath.setText(value) + + parmObj = opObj.getParameterObj(parameterName="wr_period") + if parmObj: + value = parmObj.getValue() + self.specGgraphftpratio.setText(str(value)) + + opObj = puObj.getOperationObj(name='CoherenceMap') + + if opObj == None: + self.specGraphCebCoherencmap.setCheckState(0) + self.specGraphSaveCoherencemap.setCheckState(0) + self.specGraphftpCoherencemap.setCheckState(0) + else: +# operationCoherenceMap = "Enable" + self.specGraphCebCoherencmap.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName='show') + if parmObj: + if not parmObj.getValue(): + self.specGraphCebCoherencmap.setCheckState(0) + + parmObj = opObj.getParameterObj(parameterName='xmin') + if parmObj == None: + self.specGgraphTminTmax.clear() + else: + value1 = opObj.getParameterValue(parameterName='xmin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='xmax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphTminTmax.setText(value) + self.specGgraphTminTmax.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='timerange') + if parmObj == None: + self.specGgraphTimeRange.clear() + else: + value1 = opObj.getParameterValue(parameterName='timerange') + value1 = str(value1) + self.specGgraphTimeRange.setText(value1) + self.specGgraphTimeRange.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='ymin') + if parmObj == None: + self.specGgraphHeight.clear() + else: + value1 = opObj.getParameterValue(parameterName='ymin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='ymax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphHeight.setText(value) + self.specGgraphHeight.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='zmin') + if parmObj == None: + self.specGgraphmagnitud.clear() + else: + value1 = opObj.getParameterValue(parameterName='zmin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='zmax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphmagnitud.setText(value) + self.specGgraphmagnitud.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='coh_min') + if parmObj == None: + self.specGgraphmagnitud.clear() + else: + value1 = opObj.getParameterValue(parameterName='coh_min') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='coh_max') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphmagnitud.setText(value) + self.specGgraphmagnitud.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='phase_min') + if parmObj == None: + self.specGgraphPhase.clear() + else: + value1 = opObj.getParameterValue(parameterName='phase_min') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='phase_max') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphPhase.setText(value) + self.specGgraphPhase.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName="save") + if parmObj == None: + self.specGraphSaveCoherencemap.setCheckState(0) + else: + self.specGraphSaveCoherencemap.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="ftp") + if parmObj == None: + self.specGraphftpCoherencemap.setCheckState(0) + else: + self.specGraphftpCoherencemap.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="figpath") + if parmObj: + value = parmObj.getValue() + self.specGraphPath.setText(value) + + parmObj = opObj.getParameterObj(parameterName="wr_period") + if parmObj: + value = parmObj.getValue() + self.specGgraphftpratio.setText(str(value)) + + opObj = puObj.getOperationObj(name='PowerProfilePlot') + + if opObj == None: + self.specGraphPowerprofile.setCheckState(0) + self.specGraphSavePowerprofile.setCheckState(0) + self.specGraphftpPowerprofile.setCheckState(0) + operationPowerProfilePlot = "Disabled" + channelList = None + freq_vel = None + heightsrange = None + else: +# operationPowerProfilePlot = "Enable" + self.specGraphPowerprofile.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName='show') + if parmObj: + if not parmObj.getValue(): + self.specGraphPowerprofile.setCheckState(0) + + parmObj = opObj.getParameterObj(parameterName='xmin') + if parmObj == None: + self.specGgraphDbsrange.clear() + else: + value1 = opObj.getParameterValue(parameterName='xmin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='xmax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphDbsrange.setText(value) + self.specGgraphDbsrange.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='ymin') + if parmObj == None: + self.specGgraphHeight.clear() + else: + value1 = opObj.getParameterValue(parameterName='ymin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='ymax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphHeight.setText(value) + self.specGgraphHeight.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName="save") + if parmObj == None: + self.specGraphSavePowerprofile.setCheckState(0) + else: + self.specGraphSavePowerprofile.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="ftp") + if parmObj == None: + self.specGraphftpPowerprofile.setCheckState(0) + else: + self.specGraphftpPowerprofile.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="figpath") + if parmObj: + value = parmObj.getValue() + self.specGraphPath.setText(value) + + parmObj = opObj.getParameterObj(parameterName="wr_period") + if parmObj: + value = parmObj.getValue() + self.specGgraphftpratio.setText(str(value)) + + opObj = puObj.getOperationObj(name='Noise') + + if opObj == None: + self.specGraphCebRTInoise.setCheckState(0) + self.specGraphSaveRTInoise.setCheckState(0) + self.specGraphftpRTInoise.setCheckState(0) + else: + self.specGraphCebRTInoise.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName='show') + if parmObj: + if not parmObj.getValue(): + self.specGraphCebRTInoise.setCheckState(0) + + parmObj = opObj.getParameterObj(parameterName='channelList') + if parmObj == None: + self.specGgraphChannelList.clear() + else: + value = opObj.getParameterValue(parameterName='channelList') + channelListRTINoise = str(value)[1:-1] + self.specGgraphChannelList.setText(channelListRTINoise) + self.specGgraphChannelList.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='xmin') + if parmObj == None: + self.specGgraphTminTmax.clear() + else: + value1 = opObj.getParameterValue(parameterName='xmin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='xmax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphTminTmax.setText(value) + self.specGgraphTminTmax.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='timerange') + if parmObj == None: + self.specGgraphTimeRange.clear() + else: + value1 = opObj.getParameterValue(parameterName='timerange') + value1 = str(value1) + self.specGgraphTimeRange.setText(value1) + self.specGgraphTimeRange.setEnabled(True) + + + parmObj = opObj.getParameterObj(parameterName='ymin') + if parmObj == None: + self.specGgraphDbsrange.clear() + else: + value1 = opObj.getParameterValue(parameterName='ymin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='ymax') + value2 = str(value2) + value = value1 + "," + value2 + self.specGgraphDbsrange.setText(value) + self.specGgraphDbsrange.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName="save") + if parmObj == None: + self.specGraphSaveRTInoise.setCheckState(0) + else: + self.specGraphSaveRTInoise.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="ftp") + if parmObj == None: + self.specGraphftpRTInoise.setCheckState(0) + else: + self.specGraphftpRTInoise.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="figpath") + if parmObj: + value = parmObj.getValue() + self.specGraphPath.setText(value) + + parmObj = opObj.getParameterObj(parameterName="wr_period") + if parmObj: + value = parmObj.getValue() + self.specGgraphftpratio.setText(str(value)) + + opObj = puObj.getOperationObj(name='SpectraWriter') + if opObj == None: + self.specOutputPath.clear() + self.specOutputblocksperfile.clear() + else: + value = opObj.getParameterObj(parameterName='path') + if value == None: + self.specOutputPath.clear() + else: + value = opObj.getParameterValue(parameterName='path') + path = str(value) + self.specOutputPath.setText(path) + value = opObj.getParameterObj(parameterName='blocksPerFile') + if value == None: + self.specOutputblocksperfile.clear() + else: + value = opObj.getParameterValue(parameterName='blocksPerFile') + blocksperfile = str(value) + self.specOutputblocksperfile.setText(blocksperfile) + + return + + def __refreshSpectraHeisWindow(self, puObj): + + opObj = puObj.getOperationObj(name="IncohInt4SpectraHeis") + if opObj == None: + self.specHeisOpIncoherent.clear() + self.specHeisOpCebIncoherent.setCheckState(0) + else: + for parmObj in opObj.getParameterObjList(): + if parmObj.name == 'timeInterval': + value = opObj.getParameterValue(parameterName='timeInterval') + self.specHeisOpIncoherent.setText(str(value)) + self.specHeisOpIncoherent.setEnabled(True) + self.specHeisOpCebIncoherent.setCheckState(QtCore.Qt.Checked) + self.specHeisOpCobIncInt.setCurrentIndex(0) + + # SpectraHeis Graph + + self.specHeisGgraphXminXmax.clear() + self.specHeisGgraphYminYmax.clear() + + self.specHeisGgraphChannelList.clear() + self.specHeisGgraphTminTmax.clear() + self.specHeisGgraphTimeRange.clear() + self.specHeisGgraphftpratio.clear() + + opObj = puObj.getOperationObj(name='SpectraHeisScope') + if opObj == None: + self.specHeisGraphCebSpectraplot.setCheckState(0) + self.specHeisGraphSaveSpectra.setCheckState(0) + self.specHeisGraphftpSpectra.setCheckState(0) + else: + operationSpectraHeisScope = "Enable" + self.specHeisGraphCebSpectraplot.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName='channelList') + if parmObj == None: + self.specHeisGgraphChannelList.clear() + else: + value = opObj.getParameterValue(parameterName='channelList') + channelListSpectraHeisScope = str(value)[1:-1] + self.specHeisGgraphChannelList.setText(channelListSpectraHeisScope) + self.specHeisGgraphChannelList.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='xmin') + if parmObj == None: + self.specHeisGgraphXminXmax.clear() + else: + value1 = opObj.getParameterValue(parameterName='xmin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='xmax') + value2 = str(value2) + value = value1 + "," + value2 + self.specHeisGgraphXminXmax.setText(value) + self.specHeisGgraphXminXmax.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='ymin') + if parmObj == None: + self.specHeisGgraphYminYmax.clear() + else: + value1 = opObj.getParameterValue(parameterName='ymin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='ymax') + value2 = str(value2) + value = value1 + "," + value2 + self.specHeisGgraphYminYmax.setText(value) + self.specHeisGgraphYminYmax.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName="save") + if parmObj == None: + self.specHeisGraphSaveSpectra.setCheckState(0) + else: + self.specHeisGraphSaveSpectra.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="ftp") + if parmObj == None: + self.specHeisGraphftpSpectra.setCheckState(0) + else: + self.specHeisGraphftpSpectra.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="figpath") + if parmObj: + value = parmObj.getValue() + self.specHeisGraphPath.setText(value) + + parmObj = opObj.getParameterObj(parameterName="wr_period") + if parmObj: + value = parmObj.getValue() + self.specHeisGgraphftpratio.setText(str(value)) + + opObj = puObj.getOperationObj(name='RTIfromSpectraHeis') + + if opObj == None: + self.specHeisGraphCebRTIplot.setCheckState(0) + self.specHeisGraphSaveRTIplot.setCheckState(0) + self.specHeisGraphftpRTIplot.setCheckState(0) + else: + self.specHeisGraphCebRTIplot.setCheckState(QtCore.Qt.Checked) + parmObj = opObj.getParameterObj(parameterName='channelList') + if parmObj == None: + self.specHeisGgraphChannelList.clear() + else: + value = opObj.getParameterValue(parameterName='channelList') + channelListRTIPlot = str(value)[1:-1] + self.specGgraphChannelList.setText(channelListRTIPlot) + self.specGgraphChannelList.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='xmin') + if parmObj == None: + self.specHeisGgraphTminTmax.clear() + else: + value1 = opObj.getParameterValue(parameterName='xmin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='xmax') + value2 = str(value2) + value = value1 + "," + value2 + self.specHeisGgraphTminTmax.setText(value) + self.specHeisGgraphTminTmax.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='timerange') + if parmObj == None: + self.specGgraphTimeRange.clear() + else: + value1 = opObj.getParameterValue(parameterName='timerange') + value1 = str(value1) + self.specHeisGgraphTimeRange.setText(value1) + self.specHeisGgraphTimeRange.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName='ymin') + if parmObj == None: + self.specHeisGgraphYminYmax.clear() + else: + value1 = opObj.getParameterValue(parameterName='ymin') + value1 = str(value1) + value2 = opObj.getParameterValue(parameterName='ymax') + value2 = str(value2) + value = value1 + "," + value2 + self.specHeisGgraphYminYmax.setText(value) + self.specHeisGgraphYminYmax.setEnabled(True) + + parmObj = opObj.getParameterObj(parameterName="save") + if parmObj == None: + self.specHeisGraphSaveRTIplot.setCheckState(0) + else: + self.specHeisGraphSaveRTIplot.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="ftp") + if parmObj == None: + self.specHeisGraphftpRTIplot.setCheckState(0) + else: + self.specHeisGraphftpRTIplot.setCheckState(QtCore.Qt.Checked) + + parmObj = opObj.getParameterObj(parameterName="figpath") + if parmObj: + value = parmObj.getValue() + self.specHeisGraphPath.setText(value) + + parmObj = opObj.getParameterObj(parameterName="wr_period") + if parmObj: + value = parmObj.getValue() + self.specHeisGgraphftpratio.setText(str(value)) + + # outputSpectraHeisWrite + opObj = puObj.getOperationObj(name='FitsWriter') + if opObj == None: + self.specHeisOutputPath.clear() + self.specHeisOutputblocksperfile.clear() + self.specHeisOutputMetada.clear() + else: + value = opObj.getParameterObj(parameterName='path') + if value == None: + self.specHeisOutputPath.clear() + else: + value = opObj.getParameterValue(parameterName='path') + path = str(value) + self.specHeisOutputPath.setText(path) + value = opObj.getParameterObj(parameterName='dataBlocksPerFile') + if value == None: + self.specHeisOutputblocksperfile.clear() + else: + value = opObj.getParameterValue(parameterName='dataBlocksPerFile') + blocksperfile = str(value) + self.specHeisOutputblocksperfile.setText(blocksperfile) + value = opObj.getParameterObj(parameterName='metadatafile') + if value == None: + self.specHeisOutputMetada.clear() + else: + value = opObj.getParameterValue(parameterName='metadatafile') + metadata_file = str(value) + self.specHeisOutputMetada.setText(metadata_file) + + return + + def __refreshCorrelationWindow(self, puObj): + pass + + def refreshPUWindow(self, puObj): + + if puObj.datatype == 'Voltage': + self.__refreshVoltageWindow(puObj) + + if puObj.datatype == 'Spectra': + self.__refreshSpectraWindow(puObj) + + if puObj.datatype == 'SpectraHeis': + self.__refreshSpectraHeisWindow(puObj) + + def refreshProjectProperties(self, projectObjView): + + propertyBuffObj = PropertyBuffer() + name = projectObjView.name + + propertyBuffObj.append("Properties", "Name", projectObjView.name), + propertyBuffObj.append("Properties", "Description", projectObjView.description) + propertyBuffObj.append("Properties", "Workspace", self.pathWorkSpace) + + readUnitObj = projectObjView.getReadUnitObj() + runOperationObj = readUnitObj.getOperationObj(name='run') + + for thisParmObj in runOperationObj.getParameterObjList(): + propertyBuffObj.append("Reading parms", thisParmObj.name, str(thisParmObj.getValue())) + + propertiesModel = propertyBuffObj.getPropertyModel() + + self.treeProjectProperties.setModel(propertiesModel) + self.treeProjectProperties.expandAll() + self.treeProjectProperties.resizeColumnToContents(0) + self.treeProjectProperties.resizeColumnToContents(1) + + def refreshPUProperties(self, puObjView): + + ############ FTP CONFIG ################################ + #Deleting FTP Conf. This processing unit have not got any + #FTP configuration by default + if puObjView.id in self.__puLocalFolder2FTP.keys(): + self.__puLocalFolder2FTP.pop(puObjView.id) + ######################################################## + + propertyBuffObj = PropertyBuffer() + + for thisOp in puObjView.getOperationObjList(): + + operationName = thisOp.name + + if operationName == 'run': + operationName = 'Properties' + + else: + if not thisOp.getParameterObjList(): + propertyBuffObj.append(operationName, '--', '--') + continue + + for thisParmObj in thisOp.getParameterObjList(): + propertyBuffObj.append(operationName, thisParmObj.name, str(thisParmObj.getValue())) + + ############ FTP CONFIG ################################ + if thisParmObj.name == "ftp_wei" and thisParmObj.getValue(): + value = thisParmObj.getValue() + self.temporalFTP.ftp_wei = value + + if thisParmObj.name == "exp_code" and thisParmObj.getValue(): + value = thisParmObj.getValue() + self.temporalFTP.exp_code = value + + if thisParmObj.name == "sub_exp_code" and thisParmObj.getValue(): + value = thisParmObj.getValue() + self.temporalFTP.sub_exp_code = value + + if thisParmObj.name == "plot_pos" and thisParmObj.getValue(): + value = thisParmObj.getValue() + self.temporalFTP.plot_pos = value + + if thisParmObj.name == 'ftp' and thisParmObj.getValue(): + figpathObj = thisOp.getParameterObj('figpath') + if figpathObj: + self.__puLocalFolder2FTP[puObjView.id] = figpathObj.getValue() + + ######################################################## + + propertiesModel = propertyBuffObj.getPropertyModel() + + self.treeProjectProperties.setModel(propertiesModel) + self.treeProjectProperties.expandAll() + self.treeProjectProperties.resizeColumnToContents(0) + self.treeProjectProperties.resizeColumnToContents(1) + + def refreshGraphicsId(self): + + projectObj = self.getSelectedProjectObj() + + if not projectObj: + return + + for idPU, puObj in projectObj.procUnitConfObjDict.items(): + + for opObj in puObj.getOperationObjList(): + + if opObj.name not in ('Scope', 'SpectraPlot', 'CrossSpectraPlot', 'RTIPlot', 'CoherenceMap', 'PowerProfilePlot', 'Noise', 'SpectraHeisScope', 'RTIfromSpectraHeis'): + continue + + opObj.changeParameter(name='id', value=opObj.id, format='int') + + def on_click(self, index): + + self._disable_save_button() + self._disable_play_button() + + self.console.clear() + + self.selectedItemTree = self.projectExplorerModel.itemFromIndex(index) + + projectObjView = self.getSelectedProjectObj() + + if not projectObjView: + return + + self.create = False + selectedObjView = self.getSelectedItemObj() + + self.refreshProjectWindow(projectObjView) + self.refreshProjectProperties(projectObjView) + + #A project has been selected + if projectObjView == selectedObjView: + + self.tabProject.setEnabled(True) + self.tabVoltage.setEnabled(False) + self.tabSpectra.setEnabled(False) + self.tabCorrelation.setEnabled(False) + self.tabSpectraHeis.setEnabled(False) + self.tabWidgetProject.setCurrentWidget(self.tabProject) + + if self.dateList: + self._enable_save_button() + self._enable_play_button() + + return + + #A processing unit has been selected + voltEnable = False + specEnable = False + corrEnable = False + specHeisEnable = False + tabSelected = self.tabProject + + puObj = selectedObjView + + self.refreshPUWindow(puObj) + self.refreshPUProperties(puObj) + self.showtabPUCreated(puObj.datatype) + + if self.dateList: + self._enable_save_button() + self._enable_play_button() + + def on_right_click(self, pos): + + self.menu = QtGui.QMenu() + quitAction0 = self.menu.addAction("Create a New Project") + quitAction1 = self.menu.addAction("Create a New Processing Unit") + quitAction2 = self.menu.addAction("Delete Item") + quitAction3 = self.menu.addAction("Quit") + + if len(self.__itemTreeDict) == 0: + quitAction2.setEnabled(False) + else: + quitAction2.setEnabled(True) + + action = self.menu.exec_(self.mapToGlobal(pos)) + + if action == quitAction0: + self. setInputsProject_View() + self.create = True + + if action == quitAction1: + if len(self.__projectObjDict) == 0: + outputstr = "You need to create a Project before adding a Processing Unit" + self.console.clear() + self.console.append(outputstr) + return 0 + else: + self.addPUWindow() + self.console.clear() + self.console.append("Please, Choose the type of Processing Unit") +# self.console.append("If your Datatype is rawdata, you will start with processing unit Type Voltage") +# self.console.append("If your Datatype is pdata, you will choose between processing unit Type Spectra or Correlation") +# self.console.append("If your Datatype is fits, you will start with processing unit Type SpectraHeis") + + if action == quitAction2: + index = self.selectedItemTree + try: + index.parent() + except: + self.console.append('Please, first at all select a Project or Processing Unit') + return 0 + # print index.parent(),index + if index.parent() == None: + self.projectExplorerModel.removeRow(index.row()) + else: + index.parent().removeRow(index.row()) + self.removeItemTreeFromProject() + self.console.clear() + # for i in self.projectExplorerTree.selectionModel().selection().indexes(): + # print i.row() + + if action == quitAction3: + self.close() + return 0 + + def createProjectView(self, id): + +# project_name, description, datatype, data_path, starDate, endDate, startTime, endTime, online, delay, walk, set = self.getParmsFromProjectWindow() + id = str(id) + projectParms = self.__getParmsFromProjectWindow() + + if not projectParms.isValid(): + return None + + projectObjView = Project() + projectObjView.setup(id=id, name=projectParms.name, description=projectParms.description) + + self.__projectObjDict[id] = projectObjView + self.addProject2ProjectExplorer(id=id, name=projectObjView.name) + + return projectObjView + + def updateProjectView(self): + +# project_name, description, datatype, data_path, starDate, endDate, startTime, endTime, online, delay, walk, set = self.getParmsFromProjectWindow() + + projectParms = self.__getParmsFromProjectWindow() + + if not projectParms.isValid(): + return None + + projectObjView = self.getSelectedProjectObj() + + if not projectObjView: + self.console.append("Please select a project before update it") + return None + + projectObjView.update(name=projectParms.name, description=projectParms.description) + + return projectObjView + + def createReadUnitView(self, projectObjView, idReadUnit=None): + + projectParms = self.__getParmsFromProjectWindow() + + if not projectParms.isValid(): + return None + + if projectParms.datatype in ("Voltage", "Spectra", "Fits"): + readUnitConfObj = projectObjView.addReadUnit(id=idReadUnit, + datatype=projectParms.datatype, + path=projectParms.dpath, + startDate=projectParms.startDate, + endDate=projectParms.endDate, + startTime=projectParms.startTime, + endTime=projectParms.endTime, + online=projectParms.online, + walk=projectParms.walk + ) + + if projectParms.set: + readUnitConfObj.addParameter(name="set", value=projectParms.set, format="int") + + if projectParms.delay: + readUnitConfObj.addParameter(name="delay", value=projectParms.delay, format="int") + + if projectParms.expLabel: + readUnitConfObj.addParameter(name="expLabel", value=projectParms.expLabel) + + readUnitConfObj.addOperation(name="printInfo") + + if projectParms.datatype == "USRP": + readUnitConfObj = projectObjView.addReadUnit(id=idReadUnit, + datatype=projectParms.datatype, + path=projectParms.dpath, + startDate=projectParms.startDate, + endDate=projectParms.endDate, + startTime=projectParms.startTime, + endTime=projectParms.endTime, + online=projectParms.online, + ippKm=projectParms.ippKm + ) + + if projectParms.delay: + readUnitConfObj.addParameter(name="delay", value=projectParms.delay, format="int") + + return readUnitConfObj + + def updateReadUnitView(self, projectObjView, idReadUnit): + + projectObjView.removeProcUnit(idReadUnit) + + readUnitConfObj = self.createReadUnitView(projectObjView, idReadUnit) + + return readUnitConfObj + + def createProcUnitView(self, projectObjView, datatype, inputId): + + procUnitConfObj = projectObjView.addProcUnit(datatype=datatype, inputId=inputId) + + self.__puObjDict[procUnitConfObj.getId()] = procUnitConfObj + + return procUnitConfObj + + def updateProcUnitView(self, id): + + pass + + def addPUWindow(self): + + self.configUPWindowObj = UnitProcessWindow(self) + fatherObj = self.getSelectedItemObj() + try: + fatherObj.getElementName() + except: + self.console.append("First left click on Project or Processing Unit") + return 0 + + if fatherObj.getElementName() == 'Project': + readUnitConfObj = fatherObj.getReadUnitObj() + self.configUPWindowObj.dataTypeProject = str(readUnitConfObj.datatype) + + self.configUPWindowObj.getfromWindowList.append(fatherObj) + self.configUPWindowObj.loadTotalList() + self.configUPWindowObj.show() + self.configUPWindowObj.closed.connect(self.createPUWindow) + + def createPUWindow(self): + + if not self.configUPWindowObj.create: + return + + fatherObj = self.configUPWindowObj.getFromWindow + datatype = self.configUPWindowObj.typeofUP + + if fatherObj.getElementName() == 'Project': + inputId = fatherObj.getReadUnitId() + projectObjView = fatherObj + else: + inputId = fatherObj.getId() + projectObjView = self.getSelectedProjectObj() + + if not projectObjView: + return + + puObj = self.createProcUnitView(projectObjView, datatype, inputId) + + self.addPU2ProjectExplorer(puObj) + + self.showtabPUCreated(datatype) + + self.clearPUWindow(datatype) + + self.showPUinitView() + + def addFTPConf2Operation(self, puObj, opObj): + + if not self.temporalFTP.create: + self.temporalFTP.setwithoutconfiguration() + +# opObj.addParameter(name='server', value=self.temporalFTP.server, format='str') +# opObj.addParameter(name='remotefolder', value=self.temporalFTP.remotefolder, format='str') +# opObj.addParameter(name='username', value=self.temporalFTP.username, format='str') +# opObj.addParameter(name='password', value=self.temporalFTP.password, format='str') + + if self.temporalFTP.ftp_wei: + opObj.addParameter(name='ftp_wei', value=int(self.temporalFTP.ftp_wei), format='int') + if self.temporalFTP.exp_code: + opObj.addParameter(name='exp_code', value=int(self.temporalFTP.exp_code), format='int') + if self.temporalFTP.sub_exp_code: + opObj.addParameter(name='sub_exp_code', value=int(self.temporalFTP.sub_exp_code), format='int') + if self.temporalFTP.plot_pos: + opObj.addParameter(name='plot_pos', value=int(self.temporalFTP.plot_pos), format='int') + +# def __checkFTPProcUnit(self, projectObj, localfolder): +# +# puId = None +# puObj = None +# +# for thisPuId, thisPuObj in projectObj.procUnitItems(): +# +# if not thisPuObj.name == "SendToServer": +# continue +# +# opObj = thisPuObj.getOperationObj(name='run') +# +# parmObj = opObj.getParameterObj('localfolder') +# +# #localfolder parameter should always be set, if it is not set then ProcUnit should be removed +# if not parmObj: +# projectObj.removeProcUnit(thisPuId) +# continue +# +# thisLocalfolder = parmObj.getValue() +# +# if localfolder != thisLocalfolder: +# continue +# +# puId = thisPuId +# puObj = thisPuObj +# break +# +# return puObj + + def createFTPProcUnitView(self): + + if not self.temporalFTP.create: + self.temporalFTP.setwithoutconfiguration() + + projectObj = self.getSelectedProjectObj() + + if not projectObj: + return + + self.removeAllFTPProcUnitView(projectObj) + + if not self.__puLocalFolder2FTP: + return + + folderList = ",".join(self.__puLocalFolder2FTP.values()) + + procUnitConfObj = projectObj.addProcUnit(name="SendToServer") + + procUnitConfObj.addParameter(name='server', value=self.temporalFTP.server, format='str') + procUnitConfObj.addParameter(name='username', value=self.temporalFTP.username, format='str') + procUnitConfObj.addParameter(name='password', value=self.temporalFTP.password, format='str') + procUnitConfObj.addParameter(name='localfolder', value=folderList, format='list') + procUnitConfObj.addParameter(name='remotefolder', value=self.temporalFTP.remotefolder, format='str') + procUnitConfObj.addParameter(name='ext', value=self.temporalFTP.extension, format='str') + procUnitConfObj.addParameter(name='period', value=self.temporalFTP.period, format='int') + procUnitConfObj.addParameter(name='protocol', value=self.temporalFTP.protocol, format='str') + + procUnitConfObj.addParameter(name='ftp_wei', value=self.temporalFTP.ftp_wei, format='int') + procUnitConfObj.addParameter(name='exp_code', value=self.temporalFTP.exp_code, format='int') + procUnitConfObj.addParameter(name='sub_exp_code', value=self.temporalFTP.sub_exp_code, format='int') + procUnitConfObj.addParameter(name='plot_pos', value=self.temporalFTP.plot_pos, format='int') + + self.__puObjDict[procUnitConfObj.getId()] = procUnitConfObj + + def removeAllFTPProcUnitView(self, projectObj): + + for thisPuId, thisPuObj in projectObj.procUnitItems(): + + if not thisPuObj.name == "SendToServer": + continue + + projectObj.removeProcUnit(thisPuId) + + if thisPuId not in self.__puObjDict.keys(): + continue + + self.__puObjDict.pop(thisPuId) + + def showPUinitView(self): + + self.propertiesModel = TreeModel() + self.propertiesModel.initPUVoltageView() + self.treeProjectProperties.setModel(self.propertiesModel) + self.treeProjectProperties.expandAll() + self.treeProjectProperties.allColumnsShowFocus() + self.treeProjectProperties.resizeColumnToContents(1) + + def saveFTPFromOpObj(self, operationObj): + + if operationObj.name != "SendByFTP": + return + + server = operationObj.getParameterValue("server") + username = operationObj.getParameterValue("username") + password = operationObj.getParameterValue("password") + localfolder = operationObj.getParameterValue("localfolder") + remotefolder = operationObj.getParameterValue("remotefolder") + ext = operationObj.getParameterValue("ext") + period = operationObj.getParameterValue("period") + + self.temporalFTP.save(server=server, + remotefolder=remotefolder, + username=username, + password=password, + localfolder=localfolder, + extension=ext) + + return + + def saveFTPFromProcUnitObj(self, puObj): + + opObj = puObj.getOperationObj(name="run") + + parmObj = opObj.getParameterObj(parameterName="server") + if parmObj == None: + server = 'jro-app.igp.gob.pe' + else: + server = parmObj.getValue() + + parmObj = opObj.getParameterObj(parameterName="remotefolder") + if parmObj == None: + remotefolder = '/home/wmaster/graficos' + else: + remotefolder = parmObj.getValue() + + parmObj = opObj.getParameterObj(parameterName="username") + if parmObj == None: + username = 'wmaster' + else: + username = parmObj.getValue() + + parmObj = opObj.getParameterObj(parameterName="password") + if parmObj == None: + password = 'mst2010vhf' + else: + password = parmObj.getValue() + + parmObj = opObj.getParameterObj(parameterName="ftp_wei") + if parmObj == None: + ftp_wei = 0 + else: + ftp_wei = parmObj.getValue() + + parmObj = opObj.getParameterObj(parameterName="exp_code") + if parmObj == None: + exp_code = 0 + else: + exp_code = parmObj.getValue() + + parmObj = opObj.getParameterObj(parameterName="sub_exp_code") + if parmObj == None: + sub_exp_code = 0 + else: + sub_exp_code = parmObj.getValue() + + parmObj = opObj.getParameterObj(parameterName="plot_pos") + if parmObj == None: + plot_pos = 0 + else: + plot_pos = parmObj.getValue() + + parmObj = opObj.getParameterObj(parameterName="localfolder") + if parmObj == None: + localfolder = None + else: + localfolder = parmObj.getValue() + + parmObj = opObj.getParameterObj(parameterName="ext") + if parmObj == None: + extension = '.png' + else: + extension = parmObj.getValue() + + self.temporalFTP.save(server=server, + remotefolder=remotefolder, + username=username, + password=password, + ftp_wei=ftp_wei, + exp_code=exp_code, + sub_exp_code=sub_exp_code, + plot_pos=plot_pos, + localfolder=localfolder, + extension=extension) + + def addProject2ProjectExplorer(self, id, name): + + itemTree = QtGui.QStandardItem(QtCore.QString(str(name))) + + parentItem = self.projectExplorerModel.invisibleRootItem() + parentItem.appendRow(itemTree) + + self.projectExplorerTree.setCurrentIndex(itemTree.index()) + + self.selectedItemTree = itemTree + + self.__itemTreeDict[id] = itemTree + + def addPU2ProjectExplorer(self, puObj): + + id, name = puObj.id, puObj.datatype + + itemTree = QtGui.QStandardItem(QtCore.QString(str(name))) + + parentItem = self.selectedItemTree + parentItem.appendRow(itemTree) + self.projectExplorerTree.expandAll() + + self.projectExplorerTree.setCurrentIndex(itemTree.index()) + + self.selectedItemTree = itemTree + + self.__itemTreeDict[id] = itemTree + + def addPU2PELoadXML(self, puObj): + + id, name, inputId = puObj.id, puObj.datatype, puObj.inputId + + itemTree = QtGui.QStandardItem(QtCore.QString(str(name))) + + if self.__itemTreeDict.has_key(inputId): + parentItem = self.__itemTreeDict[inputId] + else: + #If parent is a Reader object + parentItem = self.__itemTreeDict[id[:-1]] + + parentItem.appendRow(itemTree) + self.projectExplorerTree.expandAll() + parentItem = itemTree + self.projectExplorerTree.setCurrentIndex(parentItem.index()) + + self.__itemTreeDict[id] = itemTree + self.selectedItemTree = itemTree + + def getSelectedProjectObj(self): + """ + Return the current project object selected. If a processing unit is + actually selected this function returns associated project. + + None if any project or processing unit is selected + """ + for key in self.__itemTreeDict.keys(): + if self.__itemTreeDict[key] != self.selectedItemTree: + continue + + if self.__projectObjDict.has_key(key): + projectObj = self.__projectObjDict[key] + return projectObj + + puObj = self.__puObjDict[key] + + if puObj.parentId == None: + projectId = puObj.getId()[0] + else: + projectId = puObj.parentId + + projectObj = self.__projectObjDict[projectId] + return projectObj + + return None + + def getSelectedItemObj(self): + """ + Return the current project or processing unit object selected + + None if any project or processing unit is selected + """ + for key in self.__itemTreeDict.keys(): + if self.__itemTreeDict[key] != self.selectedItemTree: + continue + + if self.__projectObjDict.has_key(key) == True: + fatherObj = self.__projectObjDict[key] + else: + fatherObj = self.__puObjDict[key] + + return fatherObj + + return None + + def _WarningWindow(self, text, information): + + msgBox = QtGui.QMessageBox() + msgBox.setText(text) + msgBox.setInformativeText(information) + msgBox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) + msgBox.setDefaultButton(QtGui.QMessageBox.Ok) + ret = msgBox.exec_() + + answer = False + + if ret == QtGui.QMessageBox.Ok: + answer = True + + return answer + + def __getNewProjectId(self): + + loadProject = False + + for thisId in range(1,10): + newId = str(thisId) + if newId in self.__projectObjDict.keys(): + continue + + loadProject = True + projectId = newId + break + + if not loadProject: + self.console.clear() + self.console.append("The maximum number of projects has been loaded, a new project can not be loaded") + return None + + return projectId + + def openProject(self): + + self._disable_save_button() + self._disable_play_button() + + self.console.clear() + + self.frame_2.setEnabled(True) + + # print self.dir + filename = str(QtGui.QFileDialog.getOpenFileName(self, "Open a project file", self.pathWorkSpace, self.tr("Html Files (*.xml)"))) + + projectObjLoad = Project() + + if not projectObjLoad.readXml(filename): + self.console.append("The selected xml file could not be loaded ...") + return 0 + + self.create = False + self.refreshProjectWindow(projectObjLoad) + self.refreshProjectProperties(projectObjLoad) + + projectId = projectObjLoad.id + + if projectId in self.__projectObjDict.keys(): + + projectId = self.__getNewProjectId() + + if not projectId: + return 0 + + projectObjLoad.updateId(projectId) + + self.__projectObjDict[projectId] = projectObjLoad + + self.addProject2ProjectExplorer(id=projectId, name=projectObjLoad.name) + + self.tabWidgetProject.setEnabled(True) + self.tabWidgetProject.setCurrentWidget(self.tabProject) + # Disable tabProject after finish the creation + self.tabProject.setEnabled(True) + puObjorderList = OrderedDict(sorted(projectObjLoad.procUnitConfObjDict.items(), key=lambda x: x[0])) + + for puId, puObj in puObjorderList.items(): + + self.__puObjDict[puId] = puObj + + if puObj.name == "SendToServer": + self.saveFTPFromProcUnitObj(puObj) + + ############## COMPATIBLE WITH OLD VERSIONS ################ + operationObj = puObj.getOperationObj("SendByFTP") + + if operationObj: + self.saveFTPFromOpObj(operationObj) + ############################################################ + + if puObj.inputId == '0': + continue + + self.addPU2PELoadXML(puObj) + + self.refreshPUWindow(puObj) + self.refreshPUProperties(puObj) + self.showtabPUCreated(datatype=puObj.datatype) + +# self.console.clear() + self.console.append("\nThe selected xml file has been loaded successfully") + + if self.dateList: + self._disable_save_button() + self._enable_play_button() + + def create_updating_timer(self): + + self.comm_data_timer = QtCore.QTimer(self) + self.comm_data_timer.timeout.connect(self.on_comm_updating_timer) + self.comm_data_timer.start(1000) + + def on_comm_updating_timer(self): + # Verifica si algun proceso ha sido inicializado y sigue ejecutandose + # Si el proceso se ha parado actualizar el GUI (stopProject) + if not self.threadStarted: + return + + if self.controllerThread.isFinished(): + self.stopProject() + return + + def use_plotmanager(self, controllerThread): + + self.plotManager = controllerThread.useExternalPlotter() + + self.plot_timer = QtCore.QTimer() + self.plot_timer.timeout.connect(self.on_plotmanager_timer) + self.plot_timer.start(10) + + def on_plotmanager_timer(self): + + if not self.plotManager: + return + + self.plotManager.run() + + if self.plotManager.isErrorDetected(): + self.stopProject() + return + + def playProject(self, ext=".xml", save=1): + + self._disable_play_button() + self._disable_save_button() + + if self.controllerThread: + if self.controllerThread.isRunning(): + self.console.append("There is already another process running") + self._enable_stop_button() + return + + if not self.dateList: + self.console.append("No data found, check datapath") + + projectObj = self.getSelectedProjectObj() + + if not projectObj: + self.console.append("Please, select a project to start it") + return + + if save: + filename = self.saveProject() + if filename == None: + self.console.append("Process not initialized.") + return + else: + filename = TEMPORAL_FILE + projectObj.writeXml( os.path.join(self.pathWorkSpace,filename) ) + + self.console.clear() + self.console.append("Please wait...") + + self.controllerThread = ControllerThread() + self.controllerThread.readXml(filename) + + self.use_plotmanager(self.controllerThread) + + self.console.clear() + + self.controllerThread.start() + + sleep(0.5) + + + self.threadStarted = True + + self._disable_play_button() + self._disable_save_button() + self._enable_stop_button() + + def stopProject(self): + + self.threadStarted = False + self.controllerThread.stop() + self.plot_timer.stop() + + self.plotManager.join() + self.plotManager = None + + while self.controllerThread.isRunning(): + sleep(0.5) + + self._disable_stop_button() + self._enable_play_button() + + def pauseProject(self): + +# self.commCtrlPThread.cmd_q.put(ProcessCommand(ProcessCommand.PAUSE, data=True)) + paused = self.controllerThread.pause() + + self.changePauseIcon(paused) + + def saveProject(self, filename=None): + + self._disable_save_button() + self._disable_play_button() + + projectObj = self.getSelectedProjectObj() + + if not projectObj: + + if self.create: + self.console.append("Please press Ok before save it") + else: + self.console.append("Please select a project before save it") + return + + self.refreshGraphicsId() + + sts = True + selectedItemObj = self.getSelectedItemObj() + + #A Processing Unit has been selected + if projectObj == selectedItemObj: + if not self.on_proOk_clicked(): + return None + + #A Processing Unit has been selected + if projectObj != selectedItemObj: + puObj = selectedItemObj + + if puObj.name == 'VoltageProc': + sts = self.on_volOpOk_clicked() + if puObj.name == 'SpectraProc': + sts = self.on_specOpOk_clicked() + if puObj.name == 'SpectraHeisProc': + sts = self.on_specHeisOpOk_clicked() + + if not sts: + return None + + self.createFTPProcUnitView() + + if not filename: + filename = os.path.join( str(self.pathWorkSpace), "%s%s" %(str(projectObj.name), '.xml') ) + + projectObj.writeXml(filename) + self.console.clear() + self.console.append("Project saved") + self.console.append("Press Play button to start data processing ...") + + self._disable_save_button() + self._enable_play_button() + + return filename + + def removeItemTreeFromProject(self): + """ + Metodo para eliminar el proyecto en el dictionario de proyectos y en el dictionario de vista de arbol + """ + for key in self.__itemTreeDict.keys(): + + #Check again because an item can delete multiple items (childs) + if key not in self.__itemTreeDict.keys(): + continue + + if self.__itemTreeDict[key] != self.selectedItemTree: + continue + + if self.__projectObjDict.has_key(key) == True: + + del self.__projectObjDict[key] + del self.__itemTreeDict[key] + + else: + puObj = self.__puObjDict[key] + idProjectParent = puObj.parentId + projectObj = self.__projectObjDict[idProjectParent] + + del self.__puObjDict[key] + del self.__itemTreeDict[key] + del projectObj.procUnitConfObjDict[key] + + for key in projectObj.procUnitConfObjDict.keys(): + if projectObj.procUnitConfObjDict[key].inputId != puObj.getId(): + continue + del self.__puObjDict[projectObj.procUnitConfObjDict[key].getId()] + del self.__itemTreeDict[projectObj.procUnitConfObjDict[key].getId()] + del projectObj.procUnitConfObjDict[key] + # print projectObj.procUnitConfObjDict + # print self.__itemTreeDict,self.__projectObjDict,self.__puObjDict + + def setInputsProject_View(self): + + self.tabWidgetProject.setEnabled(True) + self.tabWidgetProject.setCurrentWidget(self.tabProject) + self.tabProject.setEnabled(True) + self.frame_2.setEnabled(False) + self.proName.clear() + self.proName.setFocus() + self.proName.setSelection(0, 0) + self.proName.setCursorPosition(0) + self.proDataType.setText('.r') + self.proDataPath.clear() + self.proComDataType.clear() + self.proComDataType.addItem("Voltage") + self.proComDataType.addItem("Spectra") + self.proComDataType.addItem("Fits") + self.proComDataType.addItem("USRP") + + self.proComStartDate.clear() + self.proComEndDate.clear() + + startTime = "00:00:00" + endTime = "23:59:59" + starlist = startTime.split(":") + endlist = endTime.split(":") + self.proDelay.setText("60") + self.proSet.setText("") + + self.labelSet.show() + self.proSet.show() + + self.labelIPPKm.hide() + self.proIPPKm.hide() + + self.time.setHMS(int(starlist[0]), int(starlist[1]), int(starlist[2])) + self.proStartTime.setTime(self.time) + self.time.setHMS(int(endlist[0]), int(endlist[1]), int(endlist[2])) + self.proEndTime.setTime(self.time) + self.proDescription.clear() + self.proOk.setEnabled(False) +# self.console.append("Please, Write a name Project") +# self.console.append("Introduce Project Parameters")DC +# self.console.append("Select data type Voltage( .rawdata) or Spectra(.pdata)") + + def clearPUWindow(self, datatype): + + projectObjView = self.getSelectedProjectObj() + + if not projectObjView: + return + + puObj = self.getSelectedItemObj() + inputId = puObj.getInputId() + inputPUObj = projectObjView.getProcUnitObj(inputId) + + if datatype == 'Voltage': + self.volOpComChannels.setEnabled(False) + self.volOpComHeights.setEnabled(False) + self.volOpFilter.setEnabled(False) + self.volOpComProfile.setEnabled(False) + self.volOpComCode.setEnabled(False) + self.volOpCohInt.setEnabled(False) + self.volOpChannel.setEnabled(False) + self.volOpHeights.setEnabled(False) + self.volOpProfile.setEnabled(False) + self.volOpRadarfrequency.setEnabled(False) + self.volOpSplitter.setEnabled(False) + self.volOpCombiner.setEnabled(False) + + self.volOpCebChannels.setCheckState(0) + self.volOpCebRadarfrequency.setCheckState(0) + self.volOpCebHeights.setCheckState(0) + self.volOpCebFilter.setCheckState(0) + self.volOpCebProfile.setCheckState(0) + self.volOpCebDecodification.setCheckState(0) + self.volOpCebCohInt.setCheckState(0) + self.volOpCebSplitter.setCheckState(0) + self.volOpCebCombiner.setCheckState(0) + + self.volOpChannel.clear() + self.volOpHeights.clear() + self.volOpProfile.clear() + self.volOpFilter.clear() + self.volOpCohInt.clear() + self.volOpRadarfrequency.clear() + self.volOpSplitter.clear() + self.volOpCombiner.clear() + + if datatype == 'Spectra': + + if inputPUObj.datatype == 'Spectra': + self.specOpnFFTpoints.setEnabled(False) + self.specOpProfiles.setEnabled(False) + self.specOpippFactor.setEnabled(False) + else: + self.specOpnFFTpoints.setEnabled(True) + self.specOpProfiles.setEnabled(True) + self.specOpippFactor.setEnabled(True) + + self.specOpCebCrossSpectra.setCheckState(0) + self.specOpCebChannel.setCheckState(0) + self.specOpCebHeights.setCheckState(0) + self.specOpCebIncoherent.setCheckState(0) + self.specOpCebRemoveDC.setCheckState(0) + self.specOpCebRemoveInt.setCheckState(0) + self.specOpCebgetNoise.setCheckState(0) + self.specOpCebRadarfrequency.setCheckState(0) + + self.specOpRadarfrequency.setEnabled(False) + self.specOppairsList.setEnabled(False) + self.specOpChannel.setEnabled(False) + self.specOpHeights.setEnabled(False) + self.specOpIncoherent.setEnabled(False) + self.specOpgetNoise.setEnabled(False) + + self.specOpRadarfrequency.clear() + self.specOpnFFTpoints.clear() + self.specOpProfiles.clear() + self.specOpippFactor.clear + self.specOppairsList.clear() + self.specOpChannel.clear() + self.specOpHeights.clear() + self.specOpIncoherent.clear() + self.specOpgetNoise.clear() + + self.specGraphCebSpectraplot.setCheckState(0) + self.specGraphCebCrossSpectraplot.setCheckState(0) + self.specGraphCebRTIplot.setCheckState(0) + self.specGraphCebRTInoise.setCheckState(0) + self.specGraphCebCoherencmap.setCheckState(0) + self.specGraphPowerprofile.setCheckState(0) + + self.specGraphSaveSpectra.setCheckState(0) + self.specGraphSaveCross.setCheckState(0) + self.specGraphSaveRTIplot.setCheckState(0) + self.specGraphSaveRTInoise.setCheckState(0) + self.specGraphSaveCoherencemap.setCheckState(0) + self.specGraphSavePowerprofile.setCheckState(0) + + self.specGraphftpRTIplot.setCheckState(0) + self.specGraphftpRTInoise.setCheckState(0) + self.specGraphftpCoherencemap.setCheckState(0) + + self.specGraphPath.clear() + self.specGraphPrefix.clear() + + self.specGgraphftpratio.clear() + + self.specGgraphChannelList.clear() + self.specGgraphFreq.clear() + self.specGgraphHeight.clear() + self.specGgraphDbsrange.clear() + self.specGgraphmagnitud.clear() + self.specGgraphTminTmax.clear() + self.specGgraphTimeRange.clear() + + if datatype == 'SpectraHeis': + self.specHeisOpCebIncoherent.setCheckState(0) + self.specHeisOpIncoherent.setEnabled(False) + self.specHeisOpIncoherent.clear() + + self.specHeisGraphCebSpectraplot.setCheckState(0) + self.specHeisGraphCebRTIplot.setCheckState(0) + + self.specHeisGraphSaveSpectra.setCheckState(0) + self.specHeisGraphSaveRTIplot.setCheckState(0) + + self.specHeisGraphftpSpectra.setCheckState(0) + self.specHeisGraphftpRTIplot.setCheckState(0) + + self.specHeisGraphPath.clear() + self.specHeisGraphPrefix.clear() + self.specHeisGgraphChannelList.clear() + self.specHeisGgraphXminXmax.clear() + self.specHeisGgraphYminYmax.clear() + self.specHeisGgraphTminTmax.clear() + self.specHeisGgraphTimeRange.clear() + self.specHeisGgraphftpratio.clear() + + def showtabPUCreated(self, datatype): + + if datatype == "Voltage": + self.tabVoltage.setEnabled(True) + self.tabProject.setEnabled(False) + self.tabSpectra.setEnabled(False) + self.tabCorrelation.setEnabled(False) + self.tabSpectraHeis.setEnabled(False) + self.tabWidgetProject.setCurrentWidget(self.tabVoltage) + + if datatype == "Spectra": + self.tabVoltage.setEnabled(False) + self.tabProject.setEnabled(False) + self.tabSpectra.setEnabled(True) + self.tabCorrelation.setEnabled(False) + self.tabSpectraHeis.setEnabled(False) + self.tabWidgetProject.setCurrentWidget(self.tabSpectra) + + if datatype == "SpectraHeis": + self.tabVoltage.setEnabled(False) + self.tabProject.setEnabled(False) + self.tabSpectra.setEnabled(False) + self.tabCorrelation.setEnabled(False) + self.tabSpectraHeis.setEnabled(True) + self.tabWidgetProject.setCurrentWidget(self.tabSpectraHeis) + + def checkInputsProject(self): + """ + Check Inputs Project: + - project_name + - datatype + - ext + - data_path + - readmode + - delay + - set + - walk + """ + parms_ok = True + project_name = str(self.proName.text()) + if project_name == '' or project_name == None: + outputstr = "Enter the Project Name" + self.console.append(outputstr) + parms_ok = False + project_name = None + + datatype = str(self.proComDataType.currentText()) + if not(datatype in ['Voltage', 'Spectra', 'Fits', 'USRP']): + outputstr = 'datatype = %s, this must be either Voltage, Spectra, SpectraHeis or USRP' % datatype + self.console.append(outputstr) + parms_ok = False + datatype = None + + ext = str(self.proDataType.text()) + if not(ext in ['.r', '.pdata', '.fits', '.hdf5']): + outputstr = "extension files must be .r , .pdata, .fits or .hdf5" + self.console.append(outputstr) + parms_ok = False + ext = None + + data_path = str(self.proDataPath.text()) + + if data_path == '': + outputstr = 'Datapath is empty' + self.console.append(outputstr) + parms_ok = False + data_path = None + + if data_path != None: + if not os.path.isdir(data_path): + outputstr = 'Datapath:%s does not exist' % data_path + self.console.append(outputstr) + parms_ok = False + data_path = None + + read_mode = str(self.proComReadMode.currentText()) + if not(read_mode in ['Online', 'Offline']): + outputstr = 'Read Mode: %s, this must be either Online or Offline' % read_mode + self.console.append(outputstr) + parms_ok = False + read_mode = None + + delay = None + if read_mode == "Online": + parms_ok = False + try: + delay = int(str(self.proDelay.text())) + parms_ok = True + except: + outputstr = 'Delay: %s, this must be a integer number' % str(self.proDelay.text()) + self.console.append(outputstr) + + try: + set = int(str(self.proSet.text())) + except: + # outputstr = 'Set: %s, this must be a integer number' % str(self.proName.text()) + # self.console.append(outputstr) + # parms_ok = False + set = None + + walk = int(self.proComWalk.currentIndex()) + expLabel = str(self.proExpLabel.text()) + + return parms_ok, project_name, datatype, ext, data_path, read_mode, delay, walk, set, expLabel + + def checkInputsPUSave(self, datatype): + """ + Check Inputs Spectra Save: + - path + - blocks Per File + - sufix + - dataformat + """ + parms_ok = True + + if datatype == "Voltage": + output_path = str(self.volOutputPath.text()) + blocksperfile = str(self.volOutputblocksperfile.text()) + profilesperblock = str(self.volOutputprofilesperblock.text()) + + if datatype == "Spectra": + output_path = str(self.specOutputPath.text()) + blocksperfile = str(self.specOutputblocksperfile.text()) + profilesperblock = 0 + + if datatype == "SpectraHeis": + output_path = str(self.specHeisOutputPath.text()) + blocksperfile = str(self.specHeisOutputblocksperfile.text()) + metadata_file = str(self.specHeisOutputMetada.text()) + + message = '' + + if not os.path.isdir(output_path): + message += 'OutputPath:%s does not exist\n' % output_path + parms_ok = False + + try: + profilesperblock = int(profilesperblock) + except: + if datatype == "Voltage": + message += 'Profilesperblock: %s, this must be a integer number\n' % str(self.volOutputprofilesperblock.text()) + parms_ok = False + profilesperblock = None + + try: + blocksperfile = int(blocksperfile) + except: + if datatype == "Voltage": + message += 'Blocksperfile: %s, this must be a integer number\n' % str(self.volOutputblocksperfile.text()) + elif datatype == "Spectra": + message += 'Blocksperfile: %s, this must be a integer number\n' % str(self.specOutputblocksperfile.text()) + elif datatype == "SpectraHeis": + message += 'Blocksperfile: %s, this must be a integer number\n' % str(self.specHeisOutputblocksperfile.text()) + + parms_ok = False + blocksperfile = None + + if datatype == "SpectraHeis": + if metadata_file != '': + if not os.path.isfile(metadata_file): + message += 'Metadata file %s does not exist\n' % metadata_file + parms_ok = False + + if str.strip(output_path) != '': + self.console.append(message) + + if datatype == "Voltage": + return parms_ok, output_path, blocksperfile, profilesperblock + + + if datatype == "Spectra": + return parms_ok, output_path, blocksperfile, profilesperblock + + + if datatype == "SpectraHeis": + return parms_ok, output_path, blocksperfile, metadata_file + + def findDatafiles(self, data_path, ext, walk, expLabel=''): + + dateList = [] + fileList = [] + + if ext == ".r": + from schainpy.model.io.jroIO_base import JRODataReader + + readerObj = JRODataReader() + dateList = readerObj.findDatafiles(path=data_path, + expLabel=expLabel, + ext=ext, + walk=walk) + + if ext == ".pdata": + from schainpy.model.io.jroIO_base import JRODataReader + + readerObj = JRODataReader() + dateList = readerObj.findDatafiles(path=data_path, + expLabel=expLabel, + ext=ext, + walk=walk) + + if ext == ".fits": + from schainpy.model.io.jroIO_base import JRODataReader + + readerObj = JRODataReader() + dateList = readerObj.findDatafiles(path=data_path, + expLabel=expLabel, + ext=ext, + walk=walk) + + if ext == ".hdf5": + from schainpy.model.io.jroIO_usrp import USRPReader + + readerObj = USRPReader() + dateList = readerObj.findDatafiles(path=data_path) + + return dateList + + def loadDays(self, data_path, ext, walk, expLabel=''): + """ + Method to loads day + """ +# self._disable_save_button() +# self._disable_play_button() +# self.proOk.setEnabled(False) + + self.proComStartDate.clear() + self.proComEndDate.clear() + + self.dateList = [] + + if not data_path: + self.console.append("Datapath has not been set") + return [] + + if not os.path.isdir(data_path): + self.console.append("Directory %s does not exist" %data_path) + return [] + + self.dataPath = data_path + + dateList = self.findDatafiles(data_path, ext=ext, walk=walk, expLabel=expLabel) + + if not dateList: +# self.console.clear() + if walk: + if expLabel: + outputstr = "No files (*%s) were found on %s/DOYPATH/%s" % (ext, data_path, expLabel) + else: + outputstr = "No files (*%s) were found on %s" % (ext, data_path) + else: + outputstr = "No files (*%s) were found on %s" % (ext, data_path) + + self.console.append(outputstr) + return [] + + dateStrList = [] + for thisDate in dateList: + dateStr = thisDate.strftime("%Y/%m/%d") + + self.proComStartDate.addItem(dateStr) + self.proComEndDate.addItem(dateStr) + dateStrList.append(dateStr) + + self.proComStartDate.setCurrentIndex(0) + self.proComEndDate.setCurrentIndex(self.proComEndDate.count() - 1) + + self.dateList = dateStrList + + self.console.clear() + self.console.append("Successful load") + +# self.proOk.setEnabled(True) +# self._enable_play_button() +# self._enable_save_button() + + return self.dateList + + def setWorkSpaceGUI(self, pathWorkSpace=None): + + if pathWorkSpace == None: + home = os.path.expanduser("~") + pathWorkSpace = os.path.join(home,'schain_workspace') + + self.pathWorkSpace = pathWorkSpace + + """ + Comandos Usados en Console + """ + def __del__(self): + sys.stdout = sys.__stdout__ + sys.stderr = sys.__stderr__ + + def normalOutputWritten(self, text): + color_black = QtGui.QColor(0,0,0) + self.console.setTextColor(color_black) + self.console.append(text) + + def errorOutputWritten(self, text): + color_red = QtGui.QColor(255,0,0) + color_black = QtGui.QColor(0,0,0) + + self.console.setTextColor(color_red) + self.console.append(text) + self.console.setTextColor(color_black) + + def _enable_save_button(self): + + self.actionSaveToolbar.setEnabled(True) + self.actionSave.setEnabled(True) + + def _disable_save_button(self): + + self.actionSaveToolbar.setEnabled(False) + self.actionSave.setEnabled(False) + + def _enable_play_button(self): + + if self.controllerThread: + if self.controllerThread.isRunning(): + return + + self.actionStart.setEnabled(True) + self.actionStarToolbar.setEnabled(True) + + self.changeStartIcon(started=False) + + def _disable_play_button(self): + + self.actionStart.setEnabled(False) + self.actionStarToolbar.setEnabled(False) + + self.changeStartIcon(started=True) + + def _enable_stop_button(self): + + self.actionPause.setEnabled(True) + self.actionStop.setEnabled(True) + + self.actionPauseToolbar.setEnabled(True) + self.actionStopToolbar.setEnabled(True) + + self.changePauseIcon(paused=False) + self.changeStopIcon(started=True) + + def _disable_stop_button(self): + + self.actionPause.setEnabled(False) + self.actionStop.setEnabled(False) + + self.actionPauseToolbar.setEnabled(False) + self.actionStopToolbar.setEnabled(False) + + self.changePauseIcon(paused=False) + self.changeStopIcon(started=False) + + def setGUIStatus(self): + + self.setWindowTitle("ROJ-Signal Chain") + self.setWindowIcon(QtGui.QIcon( os.path.join(FIGURES_PATH,"logo.png") )) + + self.tabWidgetProject.setEnabled(False) + self.tabVoltage.setEnabled(False) + self.tabSpectra.setEnabled(False) + self.tabCorrelation.setEnabled(False) + self.frame_2.setEnabled(False) + + self.actionCreate.setShortcut('Ctrl+N') + self.actionOpen.setShortcut('Ctrl+O') + self.actionSave.setShortcut('Ctrl+S') + self.actionClose.setShortcut('Ctrl+X') + + self.actionStart.setShortcut('Ctrl+1') + self.actionPause.setShortcut('Ctrl+2') + self.actionStop.setShortcut('Ctrl+3') + + self.actionFTP.setShortcut('Ctrl+F') + + self.actionStart.setEnabled(False) + self.actionPause.setEnabled(False) + self.actionStop.setEnabled(False) + + self.actionStarToolbar.setEnabled(False) + self.actionPauseToolbar.setEnabled(False) + self.actionStopToolbar.setEnabled(False) + + self.proName.clear() + self.proDataPath.setText('') + self.console.setReadOnly(True) + self.console.append("Welcome to Signal Chain\n\n") + self.console.append("Open a project or Create a new one\n") + self.proStartTime.setDisplayFormat("hh:mm:ss") + self.proDataType.setEnabled(False) + self.time = QtCore.QTime() + self.proEndTime.setDisplayFormat("hh:mm:ss") + startTime = "00:00:00" + endTime = "23:59:59" + starlist = startTime.split(":") + endlist = endTime.split(":") + self.time.setHMS(int(starlist[0]), int(starlist[1]), int(starlist[2])) + self.proStartTime.setTime(self.time) + self.time.setHMS(int(endlist[0]), int(endlist[1]), int(endlist[2])) + self.proEndTime.setTime(self.time) + self.proOk.setEnabled(False) + # set model Project Explorer + self.projectExplorerModel = QtGui.QStandardItemModel() + self.projectExplorerModel.setHorizontalHeaderLabels(("Project Explorer",)) + layout = QtGui.QVBoxLayout() + layout.addWidget(self.projectExplorerTree) + self.projectExplorerTree.setModel(self.projectExplorerModel) + self.projectExplorerTree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + self.projectExplorerTree.customContextMenuRequested.connect(self.on_right_click) + self.projectExplorerTree.clicked.connect(self.on_click) + self.projectExplorerTree.expandAll() + # set model Project Properties + + self.propertiesModel = TreeModel() + self.propertiesModel.initProjectView() + self.treeProjectProperties.setModel(self.propertiesModel) + self.treeProjectProperties.expandAll() + self.treeProjectProperties.allColumnsShowFocus() + self.treeProjectProperties.resizeColumnToContents(1) + + # set Project + self.pronTxs.setEnabled(False) + self.proComByBlock.setEnabled(False) + self.proExpLabel.setEnabled(False) + self.proDelay.setEnabled(False) + self.proSet.setEnabled(True) + self.proDataType.setReadOnly(True) + + # set Operation Voltage + self.volOpComChannels.setEnabled(False) + self.volOpComHeights.setEnabled(False) + self.volOpFilter.setEnabled(False) + self.volOpComProfile.setEnabled(False) + self.volOpComCode.setEnabled(False) + self.volOpFlip.setEnabled(False) + self.volOpCohInt.setEnabled(False) + self.volOpRadarfrequency.setEnabled(False) + + self.volOpChannel.setEnabled(False) + self.volOpHeights.setEnabled(False) + self.volOpProfile.setEnabled(False) + self.volOpComMode.setEnabled(False) + + self.volOpSplitter.setEnabled(False) + self.volOpCombiner.setEnabled(False) + self.volOpAdjustHei.setEnabled(False) + + self.volOpCebAdjustHei.setEnabled(False) + + self.volGraphPath.setEnabled(False) + self.volGraphPrefix.setEnabled(False) + self.volGraphToolPath.setEnabled(False) + + # set Graph Voltage + self.volGraphChannelList.setEnabled(False) + self.volGraphIntensityRange.setEnabled(False) + self.volGraphHeightrange.setEnabled(False) + + # set Operation Spectra + self.specOpnFFTpoints.setEnabled(False) + self.specOpProfiles.setEnabled(False) + self.specOpippFactor.setEnabled(False) + self.specOppairsList.setEnabled(False) + + self.specOpComCrossSpectra.setEnabled(False) + self.specOpComChannel.setEnabled(False) + self.specOpComHeights.setEnabled(False) + self.specOpIncoherent.setEnabled(False) + self.specOpgetNoise.setEnabled(False) + self.specOpRadarfrequency.setEnabled(False) + + + self.specOpChannel.setEnabled(False) + self.specOpHeights.setEnabled(False) + # set Graph Spectra + self.specGgraphChannelList.setEnabled(False) + self.specGgraphFreq.setEnabled(False) + self.specGgraphHeight.setEnabled(False) + self.specGgraphDbsrange.setEnabled(False) + self.specGgraphmagnitud.setEnabled(False) + self.specGgraphTminTmax.setEnabled(False) + self.specGgraphTimeRange.setEnabled(False) + self.specGraphPath.setEnabled(False) + self.specGraphToolPath.setEnabled(False) + self.specGraphPrefix.setEnabled(False) + + self.specGgraphftpratio.setEnabled(False) + # set Operation SpectraHeis + self.specHeisOpIncoherent.setEnabled(False) + self.specHeisOpCobIncInt.setEnabled(False) + # set Graph SpectraHeis + self.specHeisGgraphChannelList.setEnabled(False) + self.specHeisGgraphXminXmax.setEnabled(False) + self.specHeisGgraphYminYmax.setEnabled(False) + self.specHeisGgraphTminTmax.setEnabled(False) + self.specHeisGgraphTimeRange.setEnabled(False) + self.specHeisGgraphftpratio.setEnabled(False) + self.specHeisGraphPath.setEnabled(False) + self.specHeisGraphPrefix.setEnabled(False) + self.specHeisGraphToolPath.setEnabled(False) + + self.proComWalk.setCurrentIndex(0) + + # tool tip gui + QtGui.QToolTip.setFont(QtGui.QFont('SansSerif', 10)) + self.projectExplorerTree.setToolTip('Right clik to add Project or Unit Process') + # tool tip gui project + + # tool tip gui volOp +# self.volOpChannel.setToolTip('Example: 1,2,3,4,5') +# self.volOpHeights.setToolTip('Example: 90,180') +# self.volOpFilter.setToolTip('Example: 2') +# self.volOpProfile.setToolTip('Example:0,127') +# self.volOpCohInt.setToolTip('Example: 128') +# self.volOpFlip.setToolTip('ChannelList where flip will be applied. Example: 0,2,3') +# self.volOpOk.setToolTip('If you have finished, please Ok ') +# # tool tip gui volGraph +# self.volGraphIntensityRange.setToolTip('Height range. Example: 50,100') +# self.volGraphHeightrange.setToolTip('Amplitude. Example: 0,10000') + # tool tip gui specOp +# self.specOpnFFTpoints.setToolTip('Example: 128') +# self.specOpProfiles.setToolTip('Example: 128') +# self.specOpippFactor.setToolTip('Example:1.0') +# self.specOpIncoherent.setToolTip('Example: 10') +# self.specOpgetNoise.setToolTip('Example:20,180,30,120 (minHei,maxHei,minVel,maxVel)') +# +# self.specOpChannel.setToolTip('Example: 0,1,2,3') +# self.specOpHeights.setToolTip('Example: 90,180') +# self.specOppairsList.setToolTip('Example: (0,1),(2,3)') +# # tool tip gui specGraph +# +# self.specGgraphChannelList.setToolTip('Example: 0,3,4') +# self.specGgraphFreq.setToolTip('Example: -20,20') +# self.specGgraphHeight.setToolTip('Example: 100,400') +# self.specGgraphDbsrange.setToolTip('Example: 30,170') +# +# self.specGraphPrefix.setToolTip('Example: EXPERIMENT_NAME') +# +# +# self.specHeisOpIncoherent.setToolTip('Example: 10') +# +# self.specHeisGgraphChannelList.setToolTip('Example: 0,2,3') +# self.specHeisGgraphXminXmax.setToolTip('Example (Hz): -1000, 1000') +# self.specHeisGgraphYminYmax.setToolTip('Example (dB): 5, 35') +# self.specHeisGgraphTminTmax.setToolTip('Example (hours): 0, 24') +# self.specHeisGgraphTimeRange.setToolTip('Example (hours): 8') + + self.labelSet.show() + self.proSet.show() + + self.labelIPPKm.hide() + self.proIPPKm.hide() + + sys.stdout = ShowMeConsole(textWritten=self.normalOutputWritten) +# sys.stderr = ShowMeConsole(textWritten=self.errorOutputWritten) + + +class UnitProcessWindow(QMainWindow, Ui_UnitProcess): + """ + Class documentation goes here. + """ + closed = pyqtSignal() + create = False + + def __init__(self, parent=None): + """ + Constructor + """ + QMainWindow.__init__(self, parent) + self.setupUi(self) + self.getFromWindow = None + self.getfromWindowList = [] + self.dataTypeProject = None + + self.listUP = None + + @pyqtSignature("") + def on_unitPokbut_clicked(self): + """ + Slot documentation goes here. + """ + self.create = True + self.getFromWindow = self.getfromWindowList[int(self.comboInputBox.currentIndex())] + # self.nameofUP= str(self.nameUptxt.text()) + self.typeofUP = str(self.comboTypeBox.currentText()) + self.close() + + + @pyqtSignature("") + def on_unitPcancelbut_clicked(self): + """ + Slot documentation goes here. + """ + self.create = False + self.close() + + def loadTotalList(self): + self.comboInputBox.clear() + for i in self.getfromWindowList: + + name = i.getElementName() + if name == 'Project': + id = i.id + name = i.name + if self.dataTypeProject == 'Voltage': + self.comboTypeBox.clear() + self.comboTypeBox.addItem("Voltage") + + if self.dataTypeProject == 'Spectra': + self.comboTypeBox.clear() + self.comboTypeBox.addItem("Spectra") + self.comboTypeBox.addItem("Correlation") + if self.dataTypeProject == 'Fits': + self.comboTypeBox.clear() + self.comboTypeBox.addItem("SpectraHeis") + + + if name == 'ProcUnit': + id = int(i.id) - 1 + name = i.datatype + if name == 'Voltage': + self.comboTypeBox.clear() + self.comboTypeBox.addItem("Spectra") + self.comboTypeBox.addItem("SpectraHeis") + self.comboTypeBox.addItem("Correlation") + if name == 'Spectra': + self.comboTypeBox.clear() + self.comboTypeBox.addItem("Spectra") + self.comboTypeBox.addItem("SpectraHeis") + self.comboTypeBox.addItem("Correlation") + if name == 'SpectraHeis': + self.comboTypeBox.clear() + self.comboTypeBox.addItem("SpectraHeis") + + self.comboInputBox.addItem(str(name)) + # self.comboInputBox.addItem(str(name)+str(id)) + + def closeEvent(self, event): + self.closed.emit() + event.accept() + +class Ftp(QMainWindow, Ui_Ftp): + """ + Class documentation goes here. + """ + create = False + closed = pyqtSignal() + server = None + remotefolder = None + username = None + password = None + ftp_wei = None + exp_code = None + sub_exp_code = None + plot_pos = None + + def __init__(self, parent=None): + """ + Constructor + """ + QMainWindow.__init__(self, parent) + self.setupUi(self) + self.setGUIStatus() + + def setGUIStatus(self): + self.setWindowTitle("ROJ-Signal Chain") + self.serverFTP.setToolTip('Example: jro-app.igp.gob.pe') + self.folderFTP.setToolTip('Example: /home/wmaster/graficos') + self.usernameFTP.setToolTip('Example: myusername') + self.passwordFTP.setToolTip('Example: mypass ') + self.weightFTP.setToolTip('Example: 0') + self.expcodeFTP.setToolTip('Example: 0') + self.subexpFTP.setToolTip('Example: 0') + self.plotposFTP.setToolTip('Example: 0') + + def setParmsfromTemporal(self, server, remotefolder, username, password, ftp_wei, exp_code, sub_exp_code, plot_pos): + self.serverFTP.setText(str(server)) + self.folderFTP.setText(str(remotefolder)) + self.usernameFTP.setText(str(username)) + self.passwordFTP.setText(str(password)) + self.weightFTP.setText(str(ftp_wei)) + self.expcodeFTP.setText(str(exp_code)) + self.subexpFTP.setText(str(sub_exp_code)) + self.plotposFTP.setText(str(plot_pos)) + + def getParmsFromFtpWindow(self): + """ + Return Inputs Project: + - server + - remotefolder + - username + - password + - ftp_wei + - exp_code + - sub_exp_code + - plot_pos + """ + name_server_ftp = str(self.serverFTP.text()) + if not name_server_ftp: + self.console.clear() + self.console.append("Please Write a FTP Server") + return 0 + + folder_server_ftp = str(self.folderFTP.text()) + if not folder_server_ftp: + self.console.clear() + self.console.append("Please Write a Folder") + return 0 + + username_ftp = str(self.usernameFTP.text()) + if not username_ftp: + self.console.clear() + self.console.append("Please Write a User Name") + return 0 + + password_ftp = str(self.passwordFTP.text()) + if not password_ftp: + self.console.clear() + self.console.append("Please Write a passwordFTP") + return 0 + + ftp_wei = str(self.weightFTP.text()) + if not ftp_wei == "": + try: + ftp_wei = int(self.weightFTP.text()) + except: + self.console.clear() + self.console.append("Please Write a ftp_wei number") + return 0 + + exp_code = str(self.expcodeFTP.text()) + if not exp_code == "": + try: + exp_code = int(self.expcodeFTP.text()) + except: + self.console.clear() + self.console.append("Please Write a exp_code number") + return 0 + + + sub_exp_code = str(self.subexpFTP.text()) + if not sub_exp_code == "": + try: + sub_exp_code = int(self.subexpFTP.text()) + except: + self.console.clear() + self.console.append("Please Write a sub_exp_code number") + return 0 + + plot_pos = str(self.plotposFTP.text()) + if not plot_pos == "": + try: + plot_pos = int(self.plotposFTP.text()) + except: + self.console.clear() + self.console.append("Please Write a plot_pos number") + return 0 + + return name_server_ftp, folder_server_ftp, username_ftp, password_ftp, ftp_wei, exp_code, sub_exp_code, plot_pos + + @pyqtSignature("") + def on_ftpOkButton_clicked(self): + server, remotefolder, username, password, ftp_wei, exp_code, sub_exp_code, plot_pos = self.getParmsFromFtpWindow() + self.create = True + self.close() + + @pyqtSignature("") + def on_ftpCancelButton_clicked(self): + self.create = False + self.close() + + def closeEvent(self, event): + self.closed.emit() + event.accept() + +class ftpBuffer(): + + server = None + remotefolder = None + username = None + password = None + ftp_wei = None + exp_code = None + sub_exp_code = None + plot_pos = None + create = False + withoutconfig = False + createforView = False + localfolder = None + extension = None + period = None + protocol = None + + def __init__(self): + + self.create = False + self.server = None + self.remotefolder = None + self.username = None + self.password = None + self.ftp_wei = None + self.exp_code = None + self.sub_exp_code = None + self.plot_pos = None + # self.create = False + self.localfolder = None + self.extension = None + self.period = None + self.protocol = None + + def setwithoutconfiguration(self): + + self.create = False + self.server = "jro-app.igp.gob.pe" + self.remotefolder = "/home/wmaster/graficos" + self.username = "wmaster" + self.password = "mst2010vhf" + self.withoutconfig = True + self.localfolder = './' + self.extension = '.png' + self.period = 60 + self.protocol = 'ftp' + self.createforView = True + + if not self.ftp_wei: + self.ftp_wei = 0 + + if not self.exp_code: + self.exp_code = 0 + + if not self.sub_exp_code: + self.sub_exp_code = 0 + + if not self.plot_pos: + self.plot_pos = 0 + + def save(self, server, remotefolder, username, password, ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, localfolder='./', extension='.png', period=60, protocol='ftp'): + + self.server = server + self.remotefolder = remotefolder + self.username = username + self.password = password + self.ftp_wei = ftp_wei + self.exp_code = exp_code + self.sub_exp_code = sub_exp_code + self.plot_pos = plot_pos + self.create = True + self.withoutconfig = False + self.createforView = True + self.localfolder = localfolder + self.extension = extension + self.period = period + self.protocol = protocol + + def recover(self): + + return self.server, self.remotefolder, self.username, self.password, self.ftp_wei, self.exp_code, self.sub_exp_code, self.plot_pos, self.extension, self.period, self.protocol + +class ShowMeConsole(QtCore.QObject): + + textWritten = QtCore.pyqtSignal(str) + + def write(self, text): + + if len(text) == 0: + self.textWritten.emit("\n") + return + + if text[-1] == "\n": + text = text[:-1] + + self.textWritten.emit(str(text)) diff --git a/schainpy/gui/viewcontroller/.svn/text-base/ftp.py.svn-base b/schainpy/gui/viewcontroller/.svn/text-base/ftp.py.svn-base new file mode 100644 index 0000000..5b08bbc --- /dev/null +++ b/schainpy/gui/viewcontroller/.svn/text-base/ftp.py.svn-base @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- + +""" +Module implementing Ftp. +""" + +from PyQt4.QtGui import QMainWindow +from PyQt4.QtCore import pyqtSignature + +from schainpy.gui.viewer.ftp import Ui_Ftp + +class Ftp(QMainWindow, Ui_MainWindow): + """ + Class documentation goes here. + """ + def __init__(self, parent = None): + """ + Constructor + """ + QMainWindow.__init__(self, parent) + self.setupUi(self) diff --git a/schainpy/gui/viewcontroller/.svn/text-base/initwindow.py.svn-base b/schainpy/gui/viewcontroller/.svn/text-base/initwindow.py.svn-base new file mode 100644 index 0000000..3ee1396 --- /dev/null +++ b/schainpy/gui/viewcontroller/.svn/text-base/initwindow.py.svn-base @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- + +""" +Module implementing InitWindow. +""" +import os + +from PyQt4.QtGui import QDialog +from PyQt4.QtCore import pyqtSignature +from PyQt4 import QtCore +from PyQt4 import QtGui + +from schainpy.gui.viewer.ui_initwindow import Ui_InitWindow +from schainpy.gui.figures import tools + +FIGURES_PATH = tools.get_path() + +class InitWindow(QDialog, Ui_InitWindow): + """ + Class documentation goes here. + """ + def __init__(self, parent = None): + """ + Constructor + """ + QDialog.__init__(self, parent) + self.setupUi(self) + self.setWindowTitle("ROJ-Signal Chain") + self.setWindowIcon(QtGui.QIcon( os.path.join(FIGURES_PATH,"logo.png") )) + + @pyqtSignature("") + def on_ExitBtn_clicked(self): + """ + Exit cierra la ventana de Bienvenida + """ + self.close() + + @pyqtSignature("") + def on_ContinueBtn_clicked(self): + """ + Continue cierra la ventana de Bienvenida, a este evento se le complementa con la accion + conectar con la ventana de configuracion de Workspace + """ + # TODO: not implemented yet + #raise NotImplementedError + self.accept() diff --git a/schainpy/gui/viewcontroller/.svn/text-base/parametersModel.py.svn-base b/schainpy/gui/viewcontroller/.svn/text-base/parametersModel.py.svn-base new file mode 100644 index 0000000..a3f1c17 --- /dev/null +++ b/schainpy/gui/viewcontroller/.svn/text-base/parametersModel.py.svn-base @@ -0,0 +1,94 @@ +""" +Classes to save parameters from Windows. + +-Project window +-Voltage window +-Spectra window +-SpectraHeis window +-Correlation window + +""" + +class ProjectParms(): + + parmsOk = False + name = None + description = None + datatype = None + ext = None + dpath = None + startDate = None + endDate = None + startTime = None + endTime = None + online = None + delay = None + walk = None + expLabel = None + set = None + ippKm = None + + def __init__(self): + + self.parmsOk = True + self.description = '' + self.expLabel = '' + self.set = '' + self.ippKm = '' + self.walk = None + self.delay = '' + + def getDatatypeIndex(self): + + indexDatatype = None + + if 'voltage' in self.datatype.lower(): + indexDatatype = 0 + if 'spectra' in self.datatype.lower(): + indexDatatype = 1 + if 'fits' in self.datatype.lower(): + indexDatatype = 2 + if 'usrp' in self.datatype.lower(): + indexDatatype = 3 + + return indexDatatype + + def getExt(self): + + ext = None + + if self.datatype.lower() == 'voltage': + ext = '.r' + if self.datatype.lower() == 'spectra': + ext = '.pdata' + if self.datatype.lower() == 'fits': + ext = '.fits' + if self.datatype.lower() == 'usrp': + ext = '.hdf5' + + return ext + + def set(self, project_name, datatype, ext, dpath, online, + startDate=None, endDate=None, startTime=None, endTime=None, + delay=None, walk=None, set=None, ippKm=None, parmsOk=True, expLabel=''): + + name = project_name + datatype = datatype + ext = ext + dpath = dpath + startDate = startDate + endDate = endDate + startTime = startTime + endTime = endTime + online = online + delay = delay + walk = walk + set = set + ippKm = ippKm + expLabel = expLabel + + self.parmsOk = parmsOk + + def isValid(self): + + return self.parmsOk \ No newline at end of file diff --git a/schainpy/gui/viewcontroller/.svn/text-base/propertiesViewModel.py.svn-base b/schainpy/gui/viewcontroller/.svn/text-base/propertiesViewModel.py.svn-base new file mode 100644 index 0000000..1a278ee --- /dev/null +++ b/schainpy/gui/viewcontroller/.svn/text-base/propertiesViewModel.py.svn-base @@ -0,0 +1,211 @@ +# -*- coding: utf-8 -*- +""" +This module contains every model class to create, modify and show a property tree on a GUI. +""" + +from PyQt4 import QtCore +import itertools + +HORIZONTAL_HEADERS = ("Property","Value " ) + +HORIZONTAL = ("RAMA :",) + +class PropertyBuffer(): + + def __init__(self): + + self.clear() + + def clear(self): + + self.headerList = [] + self.parmList = [] + self.valueList = [] + + def append(self, header, parm, value): + + self.headerList.append(header) + self.parmList.append(parm) + self.valueList.append(value) + + return + + def get(self): + + return self.headerList, self.parmList, self.valueList + + def getPropertyModel(self): + + propertiesModel = TreeModel() + propertiesModel.showProperties(self.headerList, self.parmList, self.valueList) + + return propertiesModel + + +class TreeModel(QtCore.QAbstractItemModel): + ''' + a model to display a few names, ordered by encabezado + + ''' + def __init__(self ,parent=None): + super(TreeModel, self).__init__(parent) + self.people = [] + + def initProjectView(self): + """ + Reemplazo del método showtree + """ + HORIZONTAL_HEADERS = ("Property","Value " ) + HORIZONTAL = ("RAMA :",) + self.rootItem = TreeItem(None, "ALL", None) + self.parents = {0 : self.rootItem} + self.__setupModelData() + + def initPUVoltageView(self): + HORIZONTAL_HEADERS = ("Operation"," Parameter Value " ) + HORIZONTAL = ("RAMA :",) + self.rootItem = TreeItem(None, "ALL", None) + self.parents = {0 : self.rootItem} + self.__setupModelData() + + def showProperties(self,headerList, parmList, valueList): + """ + set2Obje + """ + for header, parameter, value in itertools.izip(headerList, parmList, valueList): + person = person_class(header, parameter, value) + self.people.append(person) + + self.rootItem = TreeItem(None, "ALL", None) + self.parents = {0 : self.rootItem} + self.__setupModelData() + + def columnCount(self, parent=None): + if parent and parent.isValid(): + return parent.internalPointer().columnCount() + else: + return len(HORIZONTAL_HEADERS) + + def data(self, index, role): + if not index.isValid(): + return QtCore.QVariant() + + item = index.internalPointer() + if role == QtCore.Qt.DisplayRole: + return item.data(index.column()) + if role == QtCore.Qt.UserRole: + if item: + return item.person + + return QtCore.QVariant() + + def index(self, row, column, parent): + if not self.hasIndex(row, column, parent): + return QtCore.QModelIndex() + + if not parent.isValid(): + parentItem = self.rootItem + else: + parentItem = parent.internalPointer() + + childItem = parentItem.child(row) + if childItem: + return self.createIndex(row, column, childItem) + else: + return QtCore.QModelIndex() + + def parent(self, index): + if not index.isValid(): + return QtCore.QModelIndex() + + childItem = index.internalPointer() + if not childItem: + return QtCore.QModelIndex() + + parentItem = childItem.parent() + + if parentItem == self.rootItem: + return QtCore.QModelIndex() + + return self.createIndex(parentItem.row(), 0, parentItem) + + def rowCount(self, parent=QtCore.QModelIndex()): + if parent.column() > 0: + return 0 + if not parent.isValid(): + p_Item = self.rootItem + else: + p_Item = parent.internalPointer() + return p_Item.childCount() + + def __setupModelData(self): + for person in self.people: + if person.value: + encabezado = person.header + + if not self.parents.has_key(encabezado): + newparent = TreeItem(None, encabezado, self.rootItem) + self.rootItem.appendChild(newparent) + + self.parents[encabezado] = newparent + + parentItem = self.parents[encabezado] + newItem = TreeItem(person, "", parentItem) + parentItem.appendChild(newItem) + +class person_class(object): + ''' + a trivial custom data object + ''' + def __init__(self, header, parameter, value): + self.header = header + self.parameter = parameter + self.value = value + + def __repr__(self): + return "PERSON - %s %s"% (self.parameter, self.header) + +class TreeItem(object): + ''' + a python object used to return row/column data, and keep note of + it's parents and/or children + ''' + def __init__(self, person, header, parentItem): + self.person = person + self.parentItem = parentItem + self.header = header + self.childItems = [] + + def appendChild(self, item): + self.childItems.append(item) + + def child(self, row): + return self.childItems[row] + + def childCount(self): + return len(self.childItems) + + def columnCount(self): + return 2 + + def data(self, column): + if self.person == None: + if column == 0: + return QtCore.QVariant(self.header) + if column == 1: + return QtCore.QVariant("") + else: + if column == 0: + return QtCore.QVariant(self.person.parameter) + if column == 1: + return QtCore.QVariant(self.person.value) + return QtCore.QVariant() + + def parent(self): + return self.parentItem + + def row(self): + if self.parentItem: + return self.parentItem.childItems.index(self) + return 0 + \ No newline at end of file diff --git a/schainpy/gui/viewcontroller/.svn/text-base/workspace.py.svn-base b/schainpy/gui/viewcontroller/.svn/text-base/workspace.py.svn-base new file mode 100644 index 0000000..4ad7729 --- /dev/null +++ b/schainpy/gui/viewcontroller/.svn/text-base/workspace.py.svn-base @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +import os +from os.path import expanduser + +from PyQt4.QtGui import QDialog +from PyQt4.QtCore import pyqtSignature +from PyQt4.QtCore import pyqtSignal +from PyQt4 import QtGui, QtCore + +from schainpy.gui.viewer.ui_workspace import Ui_Workspace +from schainpy.gui.figures import tools + +FIGURES_PATH = tools.get_path() + +class Workspace(QDialog, Ui_Workspace): + """ + Class documentation goes here. + """ + + def __init__(self, parent = None): + """ + Constructor + """ + QDialog.__init__(self, parent) + self.dirList=[] + self.setupUi(self) + self.setWindowTitle("ROJ-Signal Chain") + self.setWindowIcon(QtGui.QIcon( os.path.join(FIGURES_PATH,"logo.png") )) + #*####### DIRECTORIO DE TRABAJO #########*# + #self.dirCmbBox.setItemText(0, QtGui.QApplication.translate("MainWindow", "C:\WorkSpaceGui", None, QtGui.QApplication.UnicodeUTF8)) + home=expanduser("~") + self.dir=os.path.join(home,'schain_workspace') + if not os.path.exists(self.dir): + os.makedirs(self.dir) + self.dirComBox.addItem(self.dir) + self.i=0 + + + @pyqtSignature("") + def on_dirToolPath_clicked(self): + """ + Slot documentation goes here. + """ + self.i +=1 + self.dirBrowse = str(QtGui.QFileDialog.getExistingDirectory(self, 'Open Directory', './', QtGui.QFileDialog.ShowDirsOnly)) + self.dirComBox.addItem(self.dirBrowse) + self.dirComBox.setCurrentIndex(self.i) + + + + @pyqtSignature("") + def on_dirOkBtn_clicked(self): + """ + VISTA DE INTERFAZ GRÁFICA + """ + self.accept() + # self.close() +# + @pyqtSignature("") + def on_dirCancelBtn_clicked(self): + """ + Cerrar + """ + self.close() + + + + + + \ No newline at end of file diff --git a/schainpy/gui/viewer/.svn/all-wcprops b/schainpy/gui/viewer/.svn/all-wcprops new file mode 100644 index 0000000..0cdde18 --- /dev/null +++ b/schainpy/gui/viewer/.svn/all-wcprops @@ -0,0 +1,47 @@ +K 25 +svn:wc:ra_dav:version-url +V 81 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer +END +ui_ftp.py +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/ui_ftp.py +END +ui_mainwindow.py +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/ui_mainwindow.py +END +ui_unitprocess.py +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/ui_unitprocess.py +END +__init__.py +K 25 +svn:wc:ra_dav:version-url +V 93 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/__init__.py +END +ui_initwindow.py +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/ui_initwindow.py +END +ui_window.py +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/ui_window.py +END +ui_workspace.py +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/ui_workspace.py +END diff --git a/schainpy/gui/viewer/.svn/entries b/schainpy/gui/viewer/.svn/entries new file mode 100644 index 0000000..56cbef5 --- /dev/null +++ b/schainpy/gui/viewer/.svn/entries @@ -0,0 +1,272 @@ +10 + +dir +1608 +http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainpy/gui/viewer +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 + +__init__.py +file + + + + +2017-04-17T17:05:33.000000Z +8fca33843ded8faaaa8c31b89a403410 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +106 + +ui_ftp.py +file + + + + +2017-04-17T17:05:33.000000Z +1c8f688981bfc6319fbefbf910a75d24 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +6874 + +ui_initwindow.py +file + + + + +2017-04-17T17:05:33.000000Z +4f0a4abe15aaa95cf1aacb1e646372a9 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4130 + +ui_mainwindow.py +file + + + + +2017-04-17T17:05:33.000000Z +2cffdf379c23b5562f7fdce6860649a3 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +16157 + +ui_unitprocess.py +file + + + + +2017-04-17T17:05:33.000000Z +88962cea52c360164738ac5365ce2e63 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +5359 + +ui_window.py +file + + + + +2017-04-17T17:05:33.000000Z +fc5340959f1a2acc23b28a111560472b +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3459 + +ui_workspace.py +file + + + + +2017-04-17T17:05:33.000000Z +4d11dae0eddbeb0462eb32eecaf08e02 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +5958 + +viewer_ui +dir + +windows +dir + diff --git a/schainpy/gui/viewer/.svn/text-base/__init__.py.svn-base b/schainpy/gui/viewer/.svn/text-base/__init__.py.svn-base new file mode 100644 index 0000000..416f53f --- /dev/null +++ b/schainpy/gui/viewer/.svn/text-base/__init__.py.svn-base @@ -0,0 +1,5 @@ +# import ui_initwindow +# import ui_workspace +# import ui_mainwindow +# import ui_window +# import ui_ftp \ No newline at end of file diff --git a/schainpy/gui/viewer/.svn/text-base/ui_ftp.py.svn-base b/schainpy/gui/viewer/.svn/text-base/ui_ftp.py.svn-base new file mode 100644 index 0000000..b785509 --- /dev/null +++ b/schainpy/gui/viewer/.svn/text-base/ui_ftp.py.svn-base @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/alex/ui/ftpConfig4.ui' +# +# Created: Tue Aug 20 08:24:35 2013 +# by: PyQt4 UI code generator 4.10 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) + +class Ui_Ftp(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName(_fromUtf8("MainWindow")) + MainWindow.resize(374, 399) + MainWindow.setMinimumSize(QtCore.QSize(374, 399)) + MainWindow.setMaximumSize(QtCore.QSize(374, 399)) + self.centralWidget = QtGui.QWidget(MainWindow) + self.centralWidget.setObjectName(_fromUtf8("centralWidget")) + self.label = QtGui.QLabel(self.centralWidget) + self.label.setGeometry(QtCore.QRect(9, 38, 47, 17)) + self.label.setObjectName(_fromUtf8("label")) + self.label_2 = QtGui.QLabel(self.centralWidget) + self.label_2.setGeometry(QtCore.QRect(9, 133, 77, 17)) + self.label_2.setObjectName(_fromUtf8("label_2")) + self.label_3 = QtGui.QLabel(self.centralWidget) + self.label_3.setGeometry(QtCore.QRect(9, 166, 68, 17)) + self.label_3.setObjectName(_fromUtf8("label_3")) + self.label_4 = QtGui.QLabel(self.centralWidget) + self.label_4.setGeometry(QtCore.QRect(9, 9, 101, 17)) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label_4.setFont(font) + self.label_4.setObjectName(_fromUtf8("label_4")) + self.label_5 = QtGui.QLabel(self.centralWidget) + self.label_5.setGeometry(QtCore.QRect(9, 104, 87, 17)) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label_5.setFont(font) + self.label_5.setObjectName(_fromUtf8("label_5")) + self.label_6 = QtGui.QLabel(self.centralWidget) + self.label_6.setGeometry(QtCore.QRect(9, 71, 47, 17)) + self.label_6.setObjectName(_fromUtf8("label_6")) + self.serverFTP = QtGui.QLineEdit(self.centralWidget) + self.serverFTP.setGeometry(QtCore.QRect(130, 40, 231, 27)) + self.serverFTP.setObjectName(_fromUtf8("serverFTP")) + self.folderFTP = QtGui.QLineEdit(self.centralWidget) + self.folderFTP.setGeometry(QtCore.QRect(130, 70, 231, 27)) + self.folderFTP.setObjectName(_fromUtf8("folderFTP")) + self.usernameFTP = QtGui.QLineEdit(self.centralWidget) + self.usernameFTP.setGeometry(QtCore.QRect(130, 130, 231, 27)) + self.usernameFTP.setObjectName(_fromUtf8("usernameFTP")) + self.passwordFTP = QtGui.QLineEdit(self.centralWidget) + self.passwordFTP.setEchoMode(QtGui.QLineEdit.Password) + self.passwordFTP.setGeometry(QtCore.QRect(130, 160, 231, 27)) + self.passwordFTP.setObjectName(_fromUtf8("passwordFTP")) + self.ftpCancelButton = QtGui.QPushButton(self.centralWidget) + self.ftpCancelButton.setGeometry(QtCore.QRect(130, 360, 111, 27)) + self.ftpCancelButton.setObjectName(_fromUtf8("ftpCancelButton")) + self.ftpOkButton = QtGui.QPushButton(self.centralWidget) + self.ftpOkButton.setGeometry(QtCore.QRect(250, 360, 111, 27)) + self.ftpOkButton.setObjectName(_fromUtf8("ftpOkButton")) + self.label_7 = QtGui.QLabel(self.centralWidget) + self.label_7.setGeometry(QtCore.QRect(10, 200, 66, 17)) + font = QtGui.QFont() + font.setBold(True) + font.setWeight(75) + self.label_7.setFont(font) + self.label_7.setObjectName(_fromUtf8("label_7")) + self.label_8 = QtGui.QLabel(self.centralWidget) + self.label_8.setGeometry(QtCore.QRect(10, 230, 81, 17)) + self.label_8.setObjectName(_fromUtf8("label_8")) + self.label_9 = QtGui.QLabel(self.centralWidget) + self.label_9.setGeometry(QtCore.QRect(10, 260, 81, 17)) + self.label_9.setObjectName(_fromUtf8("label_9")) + self.label_10 = QtGui.QLabel(self.centralWidget) + self.label_10.setGeometry(QtCore.QRect(10, 290, 81, 17)) + self.label_10.setObjectName(_fromUtf8("label_10")) + self.label_11 = QtGui.QLabel(self.centralWidget) + self.label_11.setGeometry(QtCore.QRect(10, 320, 81, 17)) + self.label_11.setObjectName(_fromUtf8("label_11")) + self.weightFTP = QtGui.QLineEdit(self.centralWidget) + self.weightFTP.setGeometry(QtCore.QRect(130, 230, 231, 27)) + self.weightFTP.setObjectName(_fromUtf8("weightFTP")) + self.expcodeFTP = QtGui.QLineEdit(self.centralWidget) + self.expcodeFTP.setGeometry(QtCore.QRect(130, 260, 231, 27)) + self.expcodeFTP.setObjectName(_fromUtf8("expcodeFTP")) + self.subexpFTP = QtGui.QLineEdit(self.centralWidget) + self.subexpFTP.setGeometry(QtCore.QRect(130, 290, 231, 27)) + self.subexpFTP.setObjectName(_fromUtf8("subexpFTP")) + self.plotposFTP = QtGui.QLineEdit(self.centralWidget) + self.plotposFTP.setGeometry(QtCore.QRect(130, 320, 231, 27)) + self.plotposFTP.setObjectName(_fromUtf8("plotposFTP")) + MainWindow.setCentralWidget(self.centralWidget) + + self.retranslateUi(MainWindow) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) + self.label.setText(_translate("MainWindow", "Server:", None)) + self.label_2.setText(_translate("MainWindow", "User Name:", None)) + self.label_3.setText(_translate("MainWindow", "Password:", None)) + self.label_4.setText(_translate("MainWindow", "Server Details", None)) + self.label_5.setText(_translate("MainWindow", "User Details", None)) + self.label_6.setText(_translate("MainWindow", "Remote Folder:", None)) + self.ftpCancelButton.setText(_translate("MainWindow", "Cancel", None)) + self.ftpOkButton.setText(_translate("MainWindow", "Ok", None)) + self.label_7.setText(_translate("MainWindow", "Project Details", None)) + self.label_8.setText(_translate("MainWindow", "Ftp_wei:", None)) + self.label_9.setText(_translate("MainWindow", "Exp_code:", None)) + self.label_10.setText(_translate("MainWindow", "Sub_exp:", None)) + self.label_11.setText(_translate("MainWindow", "Plot_pos:", None)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + MainWindow = QtGui.QMainWindow() + ui = Ui_Ftp() + ui.setupUi(MainWindow) + MainWindow.show() + sys.exit(app.exec_()) + diff --git a/schainpy/gui/viewer/.svn/text-base/ui_initwindow.py.svn-base b/schainpy/gui/viewer/.svn/text-base/ui_initwindow.py.svn-base new file mode 100644 index 0000000..d6bc947 --- /dev/null +++ b/schainpy/gui/viewer/.svn/text-base/ui_initwindow.py.svn-base @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/roj-idl71/SignalChain/initwindowv2.ui' +# +# Created: Wed Mar 6 15:32:39 2013 +# by: PyQt4 UI code generator 4.8.6 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + _fromUtf8 = lambda s: s + +import os +from schainpy.gui.figures import tools +from schainpy import __version__ + +INITIAL_MSG = "Signal Chain GUI - v%s" %__version__ +FIGURES_PATH = tools.get_path() + +class Ui_InitWindow(object): + def setupUi(self, Dialog): + Dialog.setObjectName(_fromUtf8("Dialog")) + Dialog.resize(652, 496) + Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8)) + self.gridLayout = QtGui.QGridLayout(Dialog) + self.gridLayout.setObjectName(_fromUtf8("gridLayout")) + self.verticalLayout_3 = QtGui.QVBoxLayout() + self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3")) + self.verticalLayout_4 = QtGui.QVBoxLayout() + self.verticalLayout_4.setObjectName(_fromUtf8("verticalLayout_4")) + self.label_3 = QtGui.QLabel(Dialog) + font = QtGui.QFont() + font.setFamily(_fromUtf8("Cambria")) + font.setPointSize(22) + font.setBold(False) + font.setWeight(50) + self.label_3.setFont(font) + self.label_3.setText(QtGui.QApplication.translate("Dialog", INITIAL_MSG, None, QtGui.QApplication.UnicodeUTF8)) + self.label_3.setObjectName(_fromUtf8("label_3")) + self.verticalLayout_4.addWidget(self.label_3) + self.line_2 = QtGui.QFrame(Dialog) + self.line_2.setFrameShape(QtGui.QFrame.HLine) + self.line_2.setFrameShadow(QtGui.QFrame.Sunken) + self.line_2.setObjectName(_fromUtf8("line_2")) + self.verticalLayout_4.addWidget(self.line_2) + self.label_4 = QtGui.QLabel(Dialog) + self.label_4.setText(_fromUtf8("")) + self.label_4.setPixmap(QtGui.QPixmap(_fromUtf8( os.path.join(FIGURES_PATH,"w.jpg") ))) + self.label_4.setScaledContents(True) + self.label_4.setObjectName(_fromUtf8("label_4")) + self.verticalLayout_4.addWidget(self.label_4) + self.verticalLayout_3.addLayout(self.verticalLayout_4) + self.horizontalLayout_3 = QtGui.QHBoxLayout() + self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3")) + self.horizontalLayout_4 = QtGui.QHBoxLayout() + self.horizontalLayout_4.setObjectName(_fromUtf8("horizontalLayout_4")) + spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem) + self.ExitBtn = QtGui.QPushButton(Dialog) + self.ExitBtn.setText(QtGui.QApplication.translate("Dialog", "Exit", None, QtGui.QApplication.UnicodeUTF8)) + self.ExitBtn.setObjectName(_fromUtf8("ExitBtn")) + self.horizontalLayout_4.addWidget(self.ExitBtn) + self.ContinueBtn = QtGui.QPushButton(Dialog) + self.ContinueBtn.setText(QtGui.QApplication.translate("Dialog", "Continue", None, QtGui.QApplication.UnicodeUTF8)) + self.ContinueBtn.setObjectName(_fromUtf8("ContinueBtn")) + self.horizontalLayout_4.addWidget(self.ContinueBtn) + spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout_4.addItem(spacerItem1) + self.horizontalLayout_3.addLayout(self.horizontalLayout_4) + self.verticalLayout_3.addLayout(self.horizontalLayout_3) + self.gridLayout.addLayout(self.verticalLayout_3, 0, 0, 1, 1) + + self.retranslateUi(Dialog) + QtCore.QMetaObject.connectSlotsByName(Dialog) + + def retranslateUi(self, Dialog): + pass + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + Dialog = QtGui.QDialog() + ui = Ui_InitWindow() + ui.setupUi(Dialog) + Dialog.show() + sys.exit(app.exec_()) + + + + diff --git a/schainpy/gui/viewer/.svn/text-base/ui_mainwindow.py.svn-base b/schainpy/gui/viewer/.svn/text-base/ui_mainwindow.py.svn-base new file mode 100644 index 0000000..fb097e4 --- /dev/null +++ b/schainpy/gui/viewer/.svn/text-base/ui_mainwindow.py.svn-base @@ -0,0 +1,352 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/alex/ui/MainWindow_21_02_13_v49.ui' +# +# Created: Mon Mar 24 13:28:36 2014 +# by: PyQt4 UI code generator 4.10 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui +from windows import * + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) + +import os +from schainpy.gui.figures import tools +from schainpy import __version__ + +FIGURES_PATH = tools.get_path() + +ICON_START = "start_green.png" +ICON_PAUSE = "pause_yellow.png" +ICON_STOP = "stop_red.png" + +ICON_PAUSE_ENA = "restart_yellow.png" + +ICON_START_DIS = "start.png" +ICON_PAUSE_DIS = "pause.png" +ICON_STOP_DIS = "stop.png" + +class Ui_EnvWindow(object): + + def changeStartIcon(self, started=False): + + if started == False: + icon_name = ICON_START + else: + icon_name = ICON_START_DIS + + iconStart = QtGui.QIcon() + iconStart.addPixmap(QtGui.QPixmap(_fromUtf8( os.path.join(FIGURES_PATH, icon_name) )), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionStarToolbar.setIcon(iconStart) + + return + + def changePauseIcon(self, paused=False): + + if paused == True: + icon_name = ICON_PAUSE_ENA + else: + icon_name = ICON_PAUSE + + iconPause = QtGui.QIcon() + iconPause.addPixmap(QtGui.QPixmap(_fromUtf8( os.path.join(FIGURES_PATH, icon_name) )), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionPauseToolbar.setIcon(iconPause) + + return + + def changeStopIcon(self, started=False): + + if started == True: + icon_name = ICON_STOP + else: + icon_name = ICON_STOP_DIS + + iconStop = QtGui.QIcon() + iconStop.addPixmap(QtGui.QPixmap(_fromUtf8( os.path.join(FIGURES_PATH, icon_name) )), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.actionStopToolbar.setIcon(iconStop) + + return + + def setupUi(self, MainWindow): + + self.paused=False + + MainWindow.setObjectName(_fromUtf8("MainWindow")) + MainWindow.resize(1200, 800) + + self.centralWidget = QtGui.QWidget(MainWindow) + self.centralWidget.setObjectName(_fromUtf8("centralWidget")) + self.gridLayout_16 = QtGui.QGridLayout(self.centralWidget) + self.gridLayout_16.setObjectName(_fromUtf8("gridLayout_16")) + self.splitter_2 = QtGui.QSplitter(self.centralWidget) + self.splitter_2.setOrientation(QtCore.Qt.Horizontal) + self.splitter_2.setObjectName(_fromUtf8("splitter_2")) + self.projectExplorerTree = QtGui.QTreeView(self.splitter_2) + self.projectExplorerTree.setObjectName(_fromUtf8("projectExplorerTree")) + self.splitter = QtGui.QSplitter(self.splitter_2) + self.splitter.setOrientation(QtCore.Qt.Vertical) + self.splitter.setObjectName(_fromUtf8("splitter")) + self.tabWidgetProject = QtGui.QTabWidget(self.splitter) + self.tabWidgetProject.setMinimumSize(QtCore.QSize(0, 278)) + self.tabWidgetProject.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.tabWidgetProject.setObjectName(_fromUtf8("tabWidgetProject")) + + self.tabConsole = QtGui.QTabWidget(self.splitter) + self.tabConsole.setMinimumSize(QtCore.QSize(0, 0)) + self.tabConsole.setObjectName(_fromUtf8("tabConsole")) + self.tab_5 = QtGui.QWidget() + self.tab_5.setObjectName(_fromUtf8("tab_5")) + self.gridLayout_4 = QtGui.QGridLayout(self.tab_5) + self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4")) + self.console = QtGui.QTextEdit(self.tab_5) + self.console.setObjectName(_fromUtf8("console")) + self.gridLayout_4.addWidget(self.console, 0, 0, 1, 1) + self.tabConsole.addTab(self.tab_5, _fromUtf8("")) + self.tabWidget = QtGui.QTabWidget(self.splitter_2) + self.tabWidget.setObjectName(_fromUtf8("tabWidget")) + self.tabProjectProperty = QtGui.QWidget() + self.tabProjectProperty.setObjectName(_fromUtf8("tabProjectProperty")) + self.gridLayout_8 = QtGui.QGridLayout(self.tabProjectProperty) + self.gridLayout_8.setObjectName(_fromUtf8("gridLayout_8")) + self.treeProjectProperties = QtGui.QTreeView(self.tabProjectProperty) + self.treeProjectProperties.setObjectName(_fromUtf8("treeProjectProperties")) + self.gridLayout_8.addWidget(self.treeProjectProperties, 0, 0, 1, 1) + self.tabWidget.addTab(self.tabProjectProperty, _fromUtf8("")) + self.gridLayout_16.addWidget(self.splitter_2, 1, 0, 1, 1) + + MainWindow.setCentralWidget(self.centralWidget) + self.toolBar = QtGui.QToolBar(MainWindow) + self.toolBar.setObjectName(_fromUtf8("toolBar")) + MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) + + self.menuBar = QtGui.QMenuBar(MainWindow) + self.menuBar.setGeometry(QtCore.QRect(0, 0, 1065, 25)) + self.menuBar.setObjectName(_fromUtf8("menuBar")) + self.menuProject = QtGui.QMenu(self.menuBar) + self.menuProject.setObjectName(_fromUtf8("menuProject")) + self.menuRun = QtGui.QMenu(self.menuBar) + self.menuRun.setObjectName(_fromUtf8("menuRun")) + self.menuOptions = QtGui.QMenu(self.menuBar) + self.menuOptions.setObjectName(_fromUtf8("menuOptions")) + self.menuHelp = QtGui.QMenu(self.menuBar) + self.menuHelp.setObjectName(_fromUtf8("menuHelp")) + MainWindow.setMenuBar(self.menuBar) + + iconOpen = QtGui.QIcon() + iconOpen.addPixmap(QtGui.QPixmap(_fromUtf8( os.path.join(FIGURES_PATH,"open.png") )), QtGui.QIcon.Normal, QtGui.QIcon.Off) + iconCreate = QtGui.QIcon() + iconCreate.addPixmap(QtGui.QPixmap(_fromUtf8( os.path.join(FIGURES_PATH,"new.png") )), QtGui.QIcon.Normal, QtGui.QIcon.Off) + iconSave = QtGui.QIcon() + iconSave.addPixmap(QtGui.QPixmap(_fromUtf8( os.path.join(FIGURES_PATH,"save.png") )), QtGui.QIcon.Normal, QtGui.QIcon.Off) + iconStart = QtGui.QIcon() + iconStart.addPixmap(QtGui.QPixmap(_fromUtf8( os.path.join(FIGURES_PATH, ICON_START_DIS) )), QtGui.QIcon.Normal, QtGui.QIcon.Off) + iconStop = QtGui.QIcon() + iconStop.addPixmap(QtGui.QPixmap(_fromUtf8( os.path.join(FIGURES_PATH, ICON_STOP_DIS) )), QtGui.QIcon.Normal, QtGui.QIcon.Off) + iconPause = QtGui.QIcon() + iconPause.addPixmap(QtGui.QPixmap(_fromUtf8( os.path.join(FIGURES_PATH, ICON_PAUSE_DIS) )), QtGui.QIcon.Normal, QtGui.QIcon.Off) + iconAddPU = QtGui.QIcon() + iconAddPU.addPixmap(QtGui.QPixmap(_fromUtf8( os.path.join(FIGURES_PATH,"branch.png") )), QtGui.QIcon.Normal, QtGui.QIcon.Off) + iconClose = QtGui.QIcon() + iconClose.addPixmap(QtGui.QPixmap(_fromUtf8( os.path.join(FIGURES_PATH,"close.png") )), QtGui.QIcon.Normal, QtGui.QIcon.Off) + + + self.actionOpen = QtGui.QAction(MainWindow) + self.actionOpen.setIcon(iconOpen) + self.actionOpen.setObjectName(_fromUtf8("actionOpen")) + self.actionCreate = QtGui.QAction(MainWindow) + self.actionCreate.setIcon(iconCreate) + self.actionCreate.setObjectName(_fromUtf8("actionCreate")) + self.actionSave = QtGui.QAction(MainWindow) + self.actionSave.setIcon(iconSave) + self.actionSave.setObjectName(_fromUtf8("actionSave")) + self.actionClose = QtGui.QAction(MainWindow) + self.actionClose.setIcon(iconClose) + self.actionClose.setObjectName(_fromUtf8("actionClose")) + self.actionStart = QtGui.QAction(MainWindow) + self.actionStart.setIcon(iconStart) + self.actionStart.setObjectName(_fromUtf8("actionStart")) + self.actionPause = QtGui.QAction(MainWindow) + self.actionPause.setIcon(iconPause) + self.actionPause.setObjectName(_fromUtf8("actionPause")) + self.actionStop = QtGui.QAction(MainWindow) + self.actionStop.setIcon(iconStop) + self.actionStop.setObjectName(_fromUtf8("actionStop")) + self.actionAbout = QtGui.QAction(MainWindow) + self.actionAbout.setObjectName(_fromUtf8("actionAbout")) + + self.actionOpenToolbar = QtGui.QAction(MainWindow) + self.actionOpenToolbar.setIcon(iconOpen) + self.actionOpenToolbar.setObjectName(_fromUtf8("actionOpenToolbar")) + self.actionCreateToolbar = QtGui.QAction(MainWindow) + self.actionCreateToolbar.setIcon(iconCreate) + self.actionCreateToolbar.setObjectName(_fromUtf8("actionCreateToolbar")) + self.actionSaveToolbar = QtGui.QAction(MainWindow) + self.actionSaveToolbar.setIcon(iconSave) + self.actionSaveToolbar.setObjectName(_fromUtf8("actionSaveToolbar")) + self.actionStarToolbar = QtGui.QAction(MainWindow) + self.actionStarToolbar.setIcon(iconStart) + self.actionStarToolbar.setObjectName(_fromUtf8("actionStarToolbar")) + self.actionStopToolbar = QtGui.QAction(MainWindow) + self.actionStopToolbar.setIcon(iconStop) + self.actionStopToolbar.setObjectName(_fromUtf8("actionStopToolbar")) + self.actionPauseToolbar = QtGui.QAction(MainWindow) + self.actionPauseToolbar.setIcon(iconPause) + self.actionPauseToolbar.setObjectName(_fromUtf8("actionPauseToolbar")) + self.actionAddPU = QtGui.QAction(MainWindow) + self.actionAddPU.setIcon(iconAddPU) + self.actionAddPU.setObjectName(_fromUtf8("actionAddPU")) + self.actionFTP = QtGui.QAction(MainWindow) + self.actionFTP.setObjectName(_fromUtf8("actionFTP")) + self.toolBar.addAction(self.actionOpenToolbar) + self.toolBar.addSeparator() + self.toolBar.addAction(self.actionCreateToolbar) + self.toolBar.addSeparator() + self.toolBar.addAction(self.actionAddPU) + self.toolBar.addSeparator() + self.toolBar.addAction(self.actionSaveToolbar) + self.toolBar.addSeparator() + self.toolBar.addAction(self.actionStarToolbar) + self.toolBar.addSeparator() + self.toolBar.addAction(self.actionPauseToolbar) + self.toolBar.addSeparator() + self.toolBar.addAction(self.actionStopToolbar) + self.toolBar.addSeparator() + +# self.actionPause.triggered.connect(self.changePauseIcon) +# self.actionPauseToolbar.triggered.connect(self.changePauseIcon) + + self.menuProject.addAction(self.actionOpen) + self.menuProject.addAction(self.actionCreate) + self.menuProject.addAction(self.actionSave) + self.menuProject.addAction(self.actionClose) + self.menuRun.addAction(self.actionStart) + self.menuRun.addAction(self.actionPause) + self.menuRun.addAction(self.actionStop) + self.menuOptions.addAction(self.actionFTP) + self.menuHelp.addAction(self.actionAbout) + self.menuBar.addAction(self.menuProject.menuAction()) + self.menuBar.addAction(self.menuRun.menuAction()) + self.menuBar.addAction(self.menuOptions.menuAction()) + self.menuBar.addAction(self.menuHelp.menuAction()) + + self.tabConsole.setCurrentIndex(0) + self.tabWidget.setCurrentIndex(0) + + def retranslateUi(self, MainWindow): + + MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) + + self.tabConsole.setTabText(self.tabConsole.indexOf(self.tab_5), _translate("MainWindow", "Console", None)) + + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabProjectProperty), _translate("MainWindow", "Project Property", None)) + self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar", None)) + self.menuProject.setTitle(_translate("MainWindow", "Project", None)) + self.menuRun.setTitle(_translate("MainWindow", "Run", None)) + self.menuOptions.setTitle(_translate("MainWindow", "Options", None)) + self.menuHelp.setTitle(_translate("MainWindow", "Help", None)) + self.actionOpen.setText(_translate("MainWindow", "Open", None)) + self.actionCreate.setText(_translate("MainWindow", "Create", None)) + self.actionSave.setText(_translate("MainWindow", "Save", None)) + self.actionClose.setText(_translate("MainWindow", "Close", None)) + self.actionStart.setText(_translate("MainWindow", "Start", None)) + self.actionPause.setText(_translate("MainWindow", "Pause", None)) + self.actionStop.setText(_translate("MainWindow", "Stop", None)) + self.actionAbout.setText(_translate("MainWindow", "About SChain", None)) + self.actionOpenToolbar.setText(_translate("MainWindow", "openToolbar", None)) + self.actionOpenToolbar.setToolTip(_translate("MainWindow", "Open a project", None)) + self.actionCreateToolbar.setText(_translate("MainWindow", "createToolbar", None)) + self.actionCreateToolbar.setToolTip(_translate("MainWindow", "Create a new project", None)) + self.actionSaveToolbar.setText(_translate("MainWindow", "saveToolbar", None)) + self.actionSaveToolbar.setToolTip(_translate("MainWindow", "Save a project", None)) + self.actionStarToolbar.setText(_translate("MainWindow", "starToolbar", None)) + self.actionStarToolbar.setToolTip(_translate("MainWindow", "Start process", None)) + self.actionStopToolbar.setText(_translate("MainWindow", "stopToolbar", None)) + self.actionStopToolbar.setToolTip(_translate("MainWindow", "Stop process", None)) + self.actionPauseToolbar.setText(_translate("MainWindow", "pauseToolbar", None)) + self.actionPauseToolbar.setToolTip(_translate("MainWindow", "Pause process", None)) + self.actionAddPU.setText(_translate("MainWindow", "Add Processing Unit", None)) + self.actionFTP.setText(_translate("MainWindow", "FTP", None)) + + def closeEvent(self, event): + + reply = QtGui.QMessageBox.question(self, 'Message', + "Are you sure to quit?", QtGui.QMessageBox.Yes | + QtGui.QMessageBox.No, QtGui.QMessageBox.No) + if reply == QtGui.QMessageBox.Yes: + event.accept() + else: + event.ignore() + + def aboutEvent(self): + title = "Signal Chain Processing Software v%s" %__version__ + message = """ + Developed by: + Miguel Urco + miguel.urco@jro.igp.gob.pe +Jicamarca Radio Observatory +""" + QtGui.QMessageBox.about(self, title, message) + + +class Ui_BasicWindow(Ui_EnvWindow, Ui_ProjectTab, Ui_VoltageTab, Ui_SpectraTab, Ui_SpectraHeisTab, Ui_CorrelationTab): + + def setupUi(self, MainWindow): + + Ui_EnvWindow.setupUi(self, MainWindow) + + Ui_ProjectTab.setupUi(self) + Ui_VoltageTab.setupUi(self) + Ui_SpectraTab.setupUi(self) + Ui_SpectraHeisTab.setupUi(self) + Ui_CorrelationTab.setupUi(self) + + self.retranslateUi(MainWindow) + + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + + Ui_EnvWindow.retranslateUi(self, MainWindow) + + Ui_ProjectTab.retranslateUi(self) + Ui_VoltageTab.retranslateUi(self) + Ui_SpectraTab.retranslateUi(self) + Ui_SpectraHeisTab.retranslateUi(self) + Ui_CorrelationTab.retranslateUi(self) + + +class Ui_AdvancedWindow(Ui_EnvWindow): + + def setupUi(self, AdvancedWindow): + + Ui_MainWindow.setupUi(self, AdvancedWindow) + + def retranslateUi(self, AdvancedWindow): + + Ui_MainWindow.retranslateUi(self, AdvancedWindow) + + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + MainWindow = QtGui.QMainWindow() + ui = Ui_BasicWindow() + ui.setupUi(MainWindow) + MainWindow.show() + sys.exit(app.exec_()) + diff --git a/schainpy/gui/viewer/.svn/text-base/ui_unitprocess.py.svn-base b/schainpy/gui/viewer/.svn/text-base/ui_unitprocess.py.svn-base new file mode 100644 index 0000000..63b61c8 --- /dev/null +++ b/schainpy/gui/viewer/.svn/text-base/ui_unitprocess.py.svn-base @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/alex/ui/unitProcess4.ui' +# +# Created: Fri May 24 05:23:03 2013 +# by: PyQt4 UI code generator 4.10 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) + +class Ui_UnitProcess(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName(_fromUtf8("MainWindow")) + MainWindow.resize(312, 195) + self.centralWidget = QtGui.QWidget(MainWindow) + self.centralWidget.setObjectName(_fromUtf8("centralWidget")) + self.gridLayout = QtGui.QGridLayout(self.centralWidget) + self.gridLayout.setObjectName(_fromUtf8("gridLayout")) + self.inputLabel = QtGui.QLabel(self.centralWidget) + font = QtGui.QFont() + font.setPointSize(12) + font.setBold(False) + font.setWeight(50) + self.inputLabel.setFont(font) + self.inputLabel.setObjectName(_fromUtf8("inputLabel")) + self.gridLayout.addWidget(self.inputLabel, 2, 0, 1, 1) + self.unitPcancelbut = QtGui.QPushButton(self.centralWidget) + font = QtGui.QFont() + font.setBold(False) + font.setWeight(50) + self.unitPcancelbut.setFont(font) + self.unitPcancelbut.setObjectName(_fromUtf8("unitPcancelbut")) + self.gridLayout.addWidget(self.unitPcancelbut, 5, 2, 1, 2) + self.unitPokbut = QtGui.QPushButton(self.centralWidget) + font = QtGui.QFont() + font.setBold(False) + font.setWeight(50) + self.unitPokbut.setFont(font) + self.unitPokbut.setObjectName(_fromUtf8("unitPokbut")) + self.gridLayout.addWidget(self.unitPokbut, 5, 0, 1, 2) + self.typeLabel = QtGui.QLabel(self.centralWidget) + font = QtGui.QFont() + font.setPointSize(12) + font.setBold(False) + font.setWeight(50) + self.typeLabel.setFont(font) + self.typeLabel.setObjectName(_fromUtf8("typeLabel")) + self.gridLayout.addWidget(self.typeLabel, 3, 0, 1, 1) + self.nameUP = QtGui.QLabel(self.centralWidget) + font = QtGui.QFont() + font.setPointSize(13) + font.setBold(False) + font.setWeight(50) + self.nameUP.setFont(font) + self.nameUP.setObjectName(_fromUtf8("nameUP")) + self.gridLayout.addWidget(self.nameUP, 0, 1, 1, 2) + spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.gridLayout.addItem(spacerItem, 0, 3, 1, 1) + self.comboInputBox = QtGui.QComboBox(self.centralWidget) + font = QtGui.QFont() + font.setPointSize(12) + self.comboInputBox.setFont(font) + self.comboInputBox.setObjectName(_fromUtf8("comboInputBox")) + self.gridLayout.addWidget(self.comboInputBox, 2, 1, 1, 3) + self.comboTypeBox = QtGui.QComboBox(self.centralWidget) + font = QtGui.QFont() + font.setPointSize(12) + self.comboTypeBox.setFont(font) + self.comboTypeBox.setObjectName(_fromUtf8("comboTypeBox")) + self.comboTypeBox.addItem(_fromUtf8("")) + self.comboTypeBox.addItem(_fromUtf8("")) + self.comboTypeBox.addItem(_fromUtf8("")) + self.gridLayout.addWidget(self.comboTypeBox, 3, 1, 1, 3) + spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.gridLayout.addItem(spacerItem1, 0, 0, 1, 1) + spacerItem2 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.gridLayout.addItem(spacerItem2, 4, 0, 1, 1) + self.line = QtGui.QFrame(self.centralWidget) + self.line.setFrameShape(QtGui.QFrame.HLine) + self.line.setFrameShadow(QtGui.QFrame.Sunken) + self.line.setObjectName(_fromUtf8("line")) + self.gridLayout.addWidget(self.line, 1, 0, 1, 4) + MainWindow.setCentralWidget(self.centralWidget) + + self.retranslateUi(MainWindow) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None)) + self.inputLabel.setText(_translate("MainWindow", "Input:", None)) + self.unitPcancelbut.setText(_translate("MainWindow", "Cancel", None)) + self.unitPokbut.setText(_translate("MainWindow", "Ok", None)) + self.typeLabel.setText(_translate("MainWindow", "Type:", None)) + self.nameUP.setText(_translate("MainWindow", "Processing Unit", None)) + self.comboTypeBox.setItemText(0, _translate("MainWindow", "Voltage", None)) + self.comboTypeBox.setItemText(1, _translate("MainWindow", "Spectra", None)) + self.comboTypeBox.setItemText(2, _translate("MainWindow", "Correlation", None)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + MainWindow = QtGui.QMainWindow() + ui = Ui_UnitProcess() + ui.setupUi(MainWindow) + MainWindow.show() + sys.exit(app.exec_()) + diff --git a/schainpy/gui/viewer/.svn/text-base/ui_window.py.svn-base b/schainpy/gui/viewer/.svn/text-base/ui_window.py.svn-base new file mode 100644 index 0000000..efe81e3 --- /dev/null +++ b/schainpy/gui/viewer/.svn/text-base/ui_window.py.svn-base @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'C:\Users\alex\ericworkspace\UIDOS\window.ui' +# +# Created: Thu Dec 06 08:56:59 2012 +# by: PyQt4 UI code generator 4.9.4 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + _fromUtf8 = lambda s: s + +class Ui_window(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName(_fromUtf8("MainWindow")) + MainWindow.resize(220, 198) + self.centralWidget = QtGui.QWidget(MainWindow) + self.centralWidget.setObjectName(_fromUtf8("centralWidget")) + self.label = QtGui.QLabel(self.centralWidget) + self.label.setGeometry(QtCore.QRect(20, 10, 131, 20)) + font = QtGui.QFont() + font.setPointSize(12) + self.label.setFont(font) + self.label.setObjectName(_fromUtf8("label")) + self.label_2 = QtGui.QLabel(self.centralWidget) + self.label_2.setGeometry(QtCore.QRect(20, 60, 131, 20)) + font = QtGui.QFont() + font.setPointSize(12) + self.label_2.setFont(font) + self.label_2.setObjectName(_fromUtf8("label_2")) + self.cancelButton = QtGui.QPushButton(self.centralWidget) + self.cancelButton.setGeometry(QtCore.QRect(150, 160, 51, 23)) + self.cancelButton.setObjectName(_fromUtf8("cancelButton")) + self.okButton = QtGui.QPushButton(self.centralWidget) + self.okButton.setGeometry(QtCore.QRect(80, 160, 61, 23)) + self.okButton.setObjectName(_fromUtf8("okButton")) + self.proyectNameLine = QtGui.QLineEdit(self.centralWidget) + self.proyectNameLine.setGeometry(QtCore.QRect(20, 30, 181, 20)) + self.proyectNameLine.setObjectName(_fromUtf8("proyectNameLine")) + self.descriptionTextEdit = QtGui.QTextEdit(self.centralWidget) + self.descriptionTextEdit.setGeometry(QtCore.QRect(20, 80, 181, 71)) + self.descriptionTextEdit.setObjectName(_fromUtf8("descriptionTextEdit")) + self.saveButton = QtGui.QPushButton(self.centralWidget) + self.saveButton.setGeometry(QtCore.QRect(20, 160, 51, 23)) + self.saveButton.setObjectName(_fromUtf8("saveButton")) + MainWindow.setCentralWidget(self.centralWidget) + + self.retranslateUi(MainWindow) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)) + self.label.setText(QtGui.QApplication.translate("MainWindow", "Project Name:", None, QtGui.QApplication.UnicodeUTF8)) + self.label_2.setText(QtGui.QApplication.translate("MainWindow", "Description :", None, QtGui.QApplication.UnicodeUTF8)) + self.cancelButton.setText(QtGui.QApplication.translate("MainWindow", "Cancel", None, QtGui.QApplication.UnicodeUTF8)) + self.okButton.setText(QtGui.QApplication.translate("MainWindow", "Ok", None, QtGui.QApplication.UnicodeUTF8)) + self.saveButton.setText(QtGui.QApplication.translate("MainWindow", "Save", None, QtGui.QApplication.UnicodeUTF8)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + MainWindow = QtGui.QMainWindow() + ui = Ui_window() + ui.setupUi(MainWindow) + MainWindow.show() + sys.exit(app.exec_()) + diff --git a/schainpy/gui/viewer/.svn/text-base/ui_workspace.py.svn-base b/schainpy/gui/viewer/.svn/text-base/ui_workspace.py.svn-base new file mode 100644 index 0000000..3775c09 --- /dev/null +++ b/schainpy/gui/viewer/.svn/text-base/ui_workspace.py.svn-base @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '/home/alex/ui/workspacev5.ui' +# +# Created: Sun May 12 16:45:47 2013 +# by: PyQt4 UI code generator 4.10 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) + +class Ui_Workspace(object): + def setupUi(self, Dialog): + Dialog.setObjectName(_fromUtf8("Dialog")) + Dialog.setEnabled(True) + Dialog.resize(730, 295) + Dialog.setMinimumSize(QtCore.QSize(730, 295)) + Dialog.setMaximumSize(QtCore.QSize(730, 295)) + self.dirLabel = QtGui.QTextEdit(Dialog) + self.dirLabel.setGeometry(QtCore.QRect(0, 0, 731, 71)) + self.dirLabel.setReadOnly(True) + self.dirLabel.setObjectName(_fromUtf8("dirLabel")) + self.dirWork = QtGui.QLabel(Dialog) + self.dirWork.setGeometry(QtCore.QRect(10, 90, 91, 16)) + font = QtGui.QFont() + font.setPointSize(11) + self.dirWork.setFont(font) + self.dirWork.setObjectName(_fromUtf8("dirWork")) + self.dirComBox = QtGui.QComboBox(Dialog) + self.dirComBox.setGeometry(QtCore.QRect(110, 80, 501, 31)) + palette = QtGui.QPalette() + brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Button, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Button, brush) + brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) + brush.setStyle(QtCore.Qt.SolidPattern) + palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Button, brush) + self.dirComBox.setPalette(palette) + self.dirComBox.setObjectName(_fromUtf8("dirComBox")) + self.dirToolPath = QtGui.QToolButton(Dialog) + self.dirToolPath.setGeometry(QtCore.QRect(620, 80, 101, 31)) + font = QtGui.QFont() + font.setPointSize(11) + self.dirToolPath.setFont(font) + self.dirToolPath.setObjectName(_fromUtf8("dirToolPath")) + self.widget = QtGui.QWidget(Dialog) + self.widget.setGeometry(QtCore.QRect(10, 120, 711, 121)) + self.widget.setObjectName(_fromUtf8("widget")) + self.horizontalLayout_3 = QtGui.QHBoxLayout(self.widget) + self.horizontalLayout_3.setMargin(0) + self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3")) + spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.horizontalLayout_3.addItem(spacerItem) + spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.horizontalLayout_3.addItem(spacerItem1) + spacerItem2 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.horizontalLayout_3.addItem(spacerItem2) + spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.horizontalLayout_3.addItem(spacerItem3) + spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.horizontalLayout_3.addItem(spacerItem4) + self.dirCancelBtn = QtGui.QPushButton(Dialog) + self.dirCancelBtn.setGeometry(QtCore.QRect(490, 250, 111, 31)) + self.dirCancelBtn.setObjectName(_fromUtf8("dirCancelBtn")) + self.dirOkBtn = QtGui.QPushButton(Dialog) + self.dirOkBtn.setGeometry(QtCore.QRect(610, 250, 111, 31)) + font = QtGui.QFont() + font.setPointSize(11) + self.dirOkBtn.setFont(font) + self.dirOkBtn.setObjectName(_fromUtf8("dirOkBtn")) + + self.retranslateUi(Dialog) + QtCore.QMetaObject.connectSlotsByName(Dialog) + + def retranslateUi(self, Dialog): + Dialog.setWindowTitle(_translate("Dialog", "Dialog", None)) + self.dirLabel.setHtml(_translate("Dialog", "\n" +"\n" +"

Select a workspace

\n" +"

Signal Chain stores your projects in a folder called a workspace.

\n" +"

Choose a workspace folder to use for this session.

", None)) + self.dirWork.setText(_translate("Dialog", "Workspace :", None)) + self.dirToolPath.setText(_translate("Dialog", "Browse...", None)) + self.dirCancelBtn.setText(_translate("Dialog", "Cancel", None)) + self.dirOkBtn.setText(_translate("Dialog", "OK", None)) + + +if __name__ == "__main__": + import sys + app = QtGui.QApplication(sys.argv) + Dialog = QtGui.QDialog() + ui = Ui_Workspace() + ui.setupUi(Dialog) + Dialog.show() + sys.exit(app.exec_()) + diff --git a/schainpy/gui/viewer/viewer_ui/.svn/all-wcprops b/schainpy/gui/viewer/viewer_ui/.svn/all-wcprops new file mode 100644 index 0000000..10dc143 --- /dev/null +++ b/schainpy/gui/viewer/viewer_ui/.svn/all-wcprops @@ -0,0 +1,59 @@ +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/viewer_ui +END +MainWindow_21_02_13_v49.ui +K 25 +svn:wc:ra_dav:version-url +V 118 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/viewer_ui/MainWindow_21_02_13_v49.ui +END +MainWindow_21_02_13_v48.ui +K 25 +svn:wc:ra_dav:version-url +V 118 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/viewer_ui/MainWindow_21_02_13_v48.ui +END +ftpConfig4.ui +K 25 +svn:wc:ra_dav:version-url +V 105 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/viewer_ui/ftpConfig4.ui +END +MainWindow_21_02_13_v47.ui +K 25 +svn:wc:ra_dav:version-url +V 118 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/viewer_ui/MainWindow_21_02_13_v47.ui +END +MainWindow_21_02_13_v46.ui +K 25 +svn:wc:ra_dav:version-url +V 118 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/viewer_ui/MainWindow_21_02_13_v46.ui +END +initwindowv2.ui +K 25 +svn:wc:ra_dav:version-url +V 107 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/viewer_ui/initwindowv2.ui +END +MainWindow_21_02_13_v44.ui +K 25 +svn:wc:ra_dav:version-url +V 118 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/viewer_ui/MainWindow_21_02_13_v44.ui +END +unitProcess4.ui +K 25 +svn:wc:ra_dav:version-url +V 107 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/viewer_ui/unitProcess4.ui +END +workspacev5.ui +K 25 +svn:wc:ra_dav:version-url +V 106 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/viewer_ui/workspacev5.ui +END diff --git a/schainpy/gui/viewer/viewer_ui/.svn/entries b/schainpy/gui/viewer/viewer_ui/.svn/entries new file mode 100644 index 0000000..ae97ca7 --- /dev/null +++ b/schainpy/gui/viewer/viewer_ui/.svn/entries @@ -0,0 +1,334 @@ +10 + +dir +1608 +http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainpy/gui/viewer/viewer_ui +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 + +MainWindow_21_02_13_v44.ui +file + + + + +2017-04-17T17:05:33.000000Z +8627a07682a0f8442ecedc8dcc7a697d +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +62425 + +MainWindow_21_02_13_v46.ui +file + + + + +2017-04-17T17:05:33.000000Z +94819c4f32b76b7c3261fb5dd6c8b245 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +77864 + +MainWindow_21_02_13_v47.ui +file + + + + +2017-04-17T17:05:33.000000Z +0fe5befaaa40c1dafd3ebf5c5453e09d +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +78114 + +MainWindow_21_02_13_v48.ui +file + + + + +2017-04-17T17:05:33.000000Z +be4690733cfc2dac5d85480892e43d7b +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +78889 + +MainWindow_21_02_13_v49.ui +file + + + + +2017-04-17T17:05:33.000000Z +5328080ef7a09e6da36632c30ec004eb +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +78925 + +ftpConfig4.ui +file + + + + +2017-04-17T17:05:33.000000Z +516372c420332f892c9d07ddb290eb3f +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +6491 + +initwindowv2.ui +file + + + + +2017-04-17T17:05:33.000000Z +b5a73ba8aafa2a96fdd550f02dfd164c +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3005 + +unitProcess4.ui +file + + + + +2017-04-17T17:05:33.000000Z +890ea2bdaf1024a6b0da2b880d63903f +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4210 + +workspacev5.ui +file + + + + +2017-04-17T17:05:33.000000Z +866bc5c68f6882ae2062bee31ad11b26 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +6546 + diff --git a/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v44.ui.svn-base b/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v44.ui.svn-base new file mode 100644 index 0000000..02e8a90 --- /dev/null +++ b/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v44.ui.svn-base @@ -0,0 +1,1765 @@ + + + MainWindow + + + + 0 + 0 + 1065 + 711 + + + + MainWindow + + + + + + + Qt::Horizontal + + + + + Qt::Vertical + + + + + 0 + 278 + + + + + 16777215 + 16777215 + + + + 0 + + + + Project + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Project Name : + + + + + + + + + + DataType : + + + + + + + + Voltage + + + + + Spectra + + + + + + + + + + + DataPath : + + + + + + + ... + + + + + + + + + + Read Mode: + + + + + + + + Off Line + + + + + On Line + + + + + + + + Delay: + + + + + + + + + + Walk : + + + + + + + + Search 0 + + + + + Search 1 + + + + + + + + Load + + + + + + + Set: + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Star Date: + + + + + + + + + + End Date: + + + + + + + + + + Start Time: + + + + + + + + + + End Time: + + + + + + + + + + Description: + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + + Voltage + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + 0 + + + + Operation + + + + + + + + + + Value + + + + + Index + + + + + + + + + Value + + + + + Index + + + + + + + + Profile Selector + + + + + + + + Profile List + + + + + Profile Range List + + + + + + + + Decoder + + + + + + + Coherent Integration + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Code: + + + + + + + Select Channels + + + + + + + Select Heights + + + + + + + Filter + + + + + + + + + + Radar Frequency + + + + + + + Mode: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Barker 3 + + + + + Barker 4 + + + + + Barker 5 + + + + + Barker 7 + + + + + Barker 11 + + + + + Barker 13 + + + + + Barker 3 + Comp. + + + + + Barker 4 + Comp. + + + + + Barker 5 + Comp. + + + + + Barker 7 + Comp. + + + + + Barker 11+ Comp. + + + + + Barker 13+ Comp. + + + + + None + + + + + + + + + Time + + + + + Freq 1 + + + + + + + + + Graphics + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + ... + + + + + + + + + + Scope + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Channel List + + + + + + + Show + + + + + + + Freq/Vel + + + + + + + + + + + + + + Path : + + + + + + + Prefix: + + + + + + + Height range + + + + + + + Qt::Horizontal + + + + 40 + 12 + + + + + + + + Qt::Horizontal + + + + 18 + 12 + + + + + + + + + + + + + + Save + + + + + + + + + + + + + + + Output + + + + + + Type: + + + + + + + Path: + + + + + + + + + + ... + + + + + + + + .rawdata + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Blocks per File : + + + + + + + Profiles per Block: + + + + + + + + + + + + + + + Spectra + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + 0 + + + + Operation + + + + + + Select Cross Spectra + + + + + + + + Value + + + + + Index + + + + + + + + + + + + Value + + + + + Index + + + + + + + + + + + + + + Remove DC + + + + + + + Select Heights + + + + + + + Select Channel + + + + + + + + + + + + + x-y pairs + + + + + + + nFFTPoints + + + + + + + Incoherent Integration + + + + + + + + Time Interval + + + + + Profiles + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Radar Frequency + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Profiles + + + + + + + + + + + Graphics + + + + + + Coherence Map + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Tmin, Tmax: + + + + + + + + + + + + + + + + + + + + + + + + + + + Prefix + + + + + + + + + + Qt::Horizontal + + + + 28 + 15 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + RTI Plot + + + + + + + Height range: + + + + + + + dBs range: + + + + + + + magnitud [0-1] + + + + + + + + + + + + + Qt::Horizontal + + + + 49 + 15 + + + + + + + + Path + + + + + + + + + + + + + Power Profile + + + + + + + Freq/Vel: + + + + + + + + + + Cross Spectra Plot + + + + + + + ... + + + + + + + Channel List: + + + + + + + Spectra Plot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 39 + 15 + + + + + + + + + + + Show + + + + + + + + + + + + + + Wr Period: + + + + + + + Save + + + + + + + + + + + + + + + + + + + + + + + + + + + + ftp + + + + + + + + + + + + + + RTI Noise + + + + + + + + + + + + + + + + + + + + + Time Range: + + + + + + + + + + + Output + + + + + + Type: + + + + + + + + .pdata + + + + + + + + Path: + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + + + + + + + Blocks per File: + + + + + + + Profile per Block: + + + + + + + + + + + + + + + Correlation + + + + + + 0 + + + + Operation + + + + + Graphics + + + + + + + + + + + 0 + 0 + + + + 0 + + + + Console + + + + + + + + + + + + 0 + + + + Project Property + + + + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1065 + 25 + + + + + Project + + + + + + + + + Run + + + + + + + Options + + + + + + Help + + + + + + + + + + + + ../Documents/figure/open.png../Documents/figure/open.png + + + Open + + + + + + ../Documents/figure/create_class_obj.png../Documents/figure/create_class_obj.png + + + Create + + + + + + ../Documents/figure/save.gif../Documents/figure/save.gif + + + Save + + + + + Close + + + + + + ../Documents/figure/startServer.png../Documents/figure/startServer.png + + + Start + + + + + Pause + + + + + About + + + + + + ../Documents/figure/open.png../Documents/figure/open.png + + + openToolbar + + + Open + + + + + + ../Documents/figure/create_class_obj.png../Documents/figure/create_class_obj.png + + + createToolbar + + + Create + + + + + + ../Documents/figure/save.gif../Documents/figure/save.gif + + + saveToolbar + + + Save + + + + + + ../Documents/figure/startServer.png../Documents/figure/startServer.png + + + starToolbar + + + Start + + + + + + ../Documents/figure/stopServer.png../Documents/figure/stopServer.png + + + stopToolbar + + + Stop + + + + + + ../workspace/branch_gui_may/gui/figure/pause.png../workspace/branch_gui_may/gui/figure/pause.png + + + pauseToolbar + + + Pause + + + + + + ../addpu.jpg../addpu.jpg + + + addPU + + + + + FTP + + + + + + diff --git a/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v46.ui.svn-base b/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v46.ui.svn-base new file mode 100644 index 0000000..789d5d2 --- /dev/null +++ b/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v46.ui.svn-base @@ -0,0 +1,2179 @@ + + + MainWindow + + + + 0 + 0 + 1065 + 711 + + + + MainWindow + + + + + + + Qt::Horizontal + + + + + Qt::Vertical + + + + + 0 + 278 + + + + + 16777215 + 16777215 + + + + 0 + + + + Project + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Project Name : + + + + + + + + + + DataType : + + + + + + + + Voltage + + + + + Spectra + + + + + Fits + + + + + + + + + + + DataPath : + + + + + + + ... + + + + + + + + + + Read Mode: + + + + + + + + Off Line + + + + + On Line + + + + + + + + Delay: + + + + + + + + + + Walk : + + + + + + + + Search 0 + + + + + Search 1 + + + + + + + + Load + + + + + + + Set: + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Star Date: + + + + + + + + + + End Date: + + + + + + + + + + Start Time: + + + + + + + + + + End Time: + + + + + + + + + + Description: + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + + Voltage + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + 0 + + + + Operation + + + + + + + + + + Value + + + + + Index + + + + + + + + + Value + + + + + Index + + + + + + + + Profile Selector + + + + + + + + Profile List + + + + + Profile Range List + + + + + + + + Decoder + + + + + + + Coherent Integration + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Code: + + + + + + + Select Channels + + + + + + + Select Heights + + + + + + + Filter + + + + + + + + + + Radar Frequency + + + + + + + Mode: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Barker 3 + + + + + Barker 4 + + + + + Barker 5 + + + + + Barker 7 + + + + + Barker 11 + + + + + Barker 13 + + + + + Barker 3 + Comp. + + + + + Barker 4 + Comp. + + + + + Barker 5 + Comp. + + + + + Barker 7 + Comp. + + + + + Barker 11+ Comp. + + + + + Barker 13+ Comp. + + + + + None + + + + + + + + + Time + + + + + Freq 1 + + + + + + + + + Graphics + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + ... + + + + + + + + + + Scope + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Channel List + + + + + + + Show + + + + + + + Freq/Vel + + + + + + + + + + + + + + Path : + + + + + + + Prefix: + + + + + + + Height range + + + + + + + Qt::Horizontal + + + + 40 + 12 + + + + + + + + Qt::Horizontal + + + + 18 + 12 + + + + + + + + + + + + + + Save + + + + + + + + + + + + + + + Output + + + + + + Type: + + + + + + + Path: + + + + + + + + + + ... + + + + + + + + .rawdata + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Blocks per File : + + + + + + + Profiles per Block: + + + + + + + + + + + + + + + Spectra + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + 0 + + + + Operation + + + + + + Select Cross Spectra + + + + + + + + Value + + + + + Index + + + + + + + + + + + + Value + + + + + Index + + + + + + + + + + + + + + Remove DC + + + + + + + Select Heights + + + + + + + Select Channel + + + + + + + + + + + + + x-y pairs + + + + + + + nFFTPoints + + + + + + + Incoherent Integration + + + + + + + + Time Interval + + + + + Profiles + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Radar Frequency + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Profiles + + + + + + + + + + Remove Interference + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Mode 1 + + + + + Mode 2 + + + + + + + + + Graphics + + + + + + Coherence Map + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Tmin, Tmax: + + + + + + + + + + + + + + + + + + + + + + + + + + + Prefix : + + + + + + + + + + Qt::Horizontal + + + + 28 + 15 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + RTI Plot + + + + + + + Height range: + + + + + + + dBs range: + + + + + + + magnitud [0-1] + + + + + + + + + + + + + Qt::Horizontal + + + + 49 + 15 + + + + + + + + Path : + + + + + + + + + + + + + Power Profile + + + + + + + Freq/Vel: + + + + + + + + + + Cross Spectra Plot + + + + + + + ... + + + + + + + Channel List: + + + + + + + Spectra Plot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 39 + 15 + + + + + + + + + + + Show + + + + + + + + + + + + + + Wr Period: + + + + + + + Save + + + + + + + + + + + + + + + + + + + + + + + + + + + + ftp + + + + + + + + + + + + + + RTI Noise + + + + + + + + + + + + + + + + + + + + + Time Range: + + + + + + + + + + + Output + + + + + + Type: + + + + + + + + .pdata + + + + + + + + Path: + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + + + + + + + Blocks per File: + + + + + + + Profile per Block: + + + + + + + + + + + + + + + SpectraHeis + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Clear + + + + + + + Ok + + + + + + + + + + 0 + + + + Operation + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Time Interval + + + + + + + + Incoherent Intergration + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Graphics + + + + + + Prefix + + + + + + + ... + + + + + + + + + + + + + + ymin - ymax + + + + + + + Tmin - Tmax: + + + + + + + Time Range: + + + + + + + Wr Period + + + + + + + Qt::Horizontal + + + + 134 + 20 + + + + + + + + + + + + + + + + + + + + + Channel List: + + + + + + + xmin - xmax + + + + + + + + + + Save + + + + + + + ftp + + + + + + + Spectra Plot + + + + + + + + + + + + + + + + + Path + + + + + + + Show + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 106 + 20 + + + + + + + + + + + + + + + + + + + + + + RTI PLot + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Output + + + + + + Path: + + + + + + + Blocks per File: + + + + + + + Type: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + + + + + + + + .fits + + + + + + + + Profile per Block: + + + + + + + + + + + + + + + + + + Correlation + + + + + + 0 + + + + Operation + + + + + Graphics + + + + + + + + + + + 0 + 0 + + + + 0 + + + + Console + + + + + + + + + + + + 0 + + + + Project Property + + + + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1065 + 25 + + + + + Project + + + + + + + + + Run + + + + + + + Options + + + + + + Help + + + + + + + + + + + + ../Documents/figure/open.png../Documents/figure/open.png + + + Open + + + + + + ../Documents/figure/create_class_obj.png../Documents/figure/create_class_obj.png + + + Create + + + + + + ../Documents/figure/save.gif../Documents/figure/save.gif + + + Save + + + + + Close + + + + + + ../Documents/figure/startServer.png../Documents/figure/startServer.png + + + Start + + + + + Pause + + + + + About + + + + + + ../Documents/figure/open.png../Documents/figure/open.png + + + openToolbar + + + Open + + + + + + ../Documents/figure/create_class_obj.png../Documents/figure/create_class_obj.png + + + createToolbar + + + Create + + + + + + ../Documents/figure/save.gif../Documents/figure/save.gif + + + saveToolbar + + + Save + + + + + + ../Documents/figure/startServer.png../Documents/figure/startServer.png + + + starToolbar + + + Start + + + + + + ../Documents/figure/stopServer.png../Documents/figure/stopServer.png + + + stopToolbar + + + Stop + + + + + + ../workspace/branch_gui_may/gui/figure/pause.png../workspace/branch_gui_may/gui/figure/pause.png + + + pauseToolbar + + + Pause + + + + + + ../addpu.jpg../addpu.jpg + + + addPU + + + + + FTP + + + + + + diff --git a/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v47.ui.svn-base b/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v47.ui.svn-base new file mode 100644 index 0000000..2035e1a --- /dev/null +++ b/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v47.ui.svn-base @@ -0,0 +1,2186 @@ + + + MainWindow + + + + 0 + 0 + 1065 + 711 + + + + MainWindow + + + + + + + Qt::Horizontal + + + + + Qt::Vertical + + + + + 0 + 278 + + + + + 16777215 + 16777215 + + + + 0 + + + + Project + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Project Name : + + + + + + + + + + DataType : + + + + + + + + Voltage + + + + + Spectra + + + + + Fits + + + + + + + + + + + DataPath : + + + + + + + ... + + + + + + + + + + Read Mode: + + + + + + + + Off Line + + + + + On Line + + + + + + + + Delay: + + + + + + + + + + Walk : + + + + + + + + Search 0 + + + + + Search 1 + + + + + + + + Load + + + + + + + Set: + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Star Date: + + + + + + + + + + End Date: + + + + + + + + + + Start Time: + + + + + + + + + + End Time: + + + + + + + + + + Description: + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + + Voltage + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + 0 + + + + Operation + + + + + + + + + + Value + + + + + Index + + + + + + + + + Value + + + + + Index + + + + + + + + Profile Selector + + + + + + + + Profile List + + + + + Profile Range List + + + + + + + + Decoder + + + + + + + Coherent Integration + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Code: + + + + + + + Select Channels + + + + + + + Select Heights + + + + + + + Filter + + + + + + + + + + Radar Frequency + + + + + + + Mode: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Barker 3 + + + + + Barker 4 + + + + + Barker 5 + + + + + Barker 7 + + + + + Barker 11 + + + + + Barker 13 + + + + + Barker 3 + Comp. + + + + + Barker 4 + Comp. + + + + + Barker 5 + Comp. + + + + + Barker 7 + Comp. + + + + + Barker 11+ Comp. + + + + + Barker 13+ Comp. + + + + + None + + + + + + + + + Time + + + + + Freq 1 + + + + + + + + + Graphics + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + ... + + + + + + + + + + Scope + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Channel List + + + + + + + Show + + + + + + + Freq/Vel + + + + + + + + + + + + + + Path : + + + + + + + Prefix: + + + + + + + Height range + + + + + + + Qt::Horizontal + + + + 40 + 12 + + + + + + + + Qt::Horizontal + + + + 18 + 12 + + + + + + + + + + + + + + Save + + + + + + + + + + + + + + + Output + + + + + + Type: + + + + + + + Path: + + + + + + + + + + ... + + + + + + + + .rawdata + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Blocks per File : + + + + + + + Profiles per Block: + + + + + + + + + + + + + + + Spectra + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + 0 + + + + Operation + + + + + + Select Cross Spectra + + + + + + + + Value + + + + + Index + + + + + + + + + + + + Value + + + + + Index + + + + + + + + + + + + + + Remove DC + + + + + + + Select Heights + + + + + + + Select Channel + + + + + + + + + + + + + x-y pairs + + + + + + + nFFTPoints + + + + + + + Incoherent Integration + + + + + + + + Time Interval + + + + + Profiles + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Radar Frequency + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Profiles + + + + + + + + + + Remove Interference + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Mode 1 + + + + + Mode 2 + + + + + + + + + Graphics + + + + + + Coherence Map + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Tmin, Tmax: + + + + + + + + + + + + + + + + + + + + + + + + + + + Prefix : + + + + + + + + + + Qt::Horizontal + + + + 28 + 15 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + RTI Plot + + + + + + + Height range: + + + + + + + dBs range: + + + + + + + magnitud [0-1] + + + + + + + + + + + + + Qt::Horizontal + + + + 49 + 15 + + + + + + + + Path : + + + + + + + + + + + + + Power Profile + + + + + + + Freq/Vel: + + + + + + + + + + Cross Spectra Plot + + + + + + + ... + + + + + + + Channel List: + + + + + + + Spectra Plot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 39 + 15 + + + + + + + + + + + Show + + + + + + + + + + + + + + Wr Period: + + + + + + + Save + + + + + + + + + + + + + + + + + + + + + + + + + + + + ftp + + + + + + + + + + + + + + RTI Noise + + + + + + + + + + + + + + + + + + + + + Time Range: + + + + + + + + + + + Output + + + + + + Type: + + + + + + + + .pdata + + + + + + + + Path: + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + + + + + + + Blocks per File: + + + + + + + Profile per Block: + + + + + + + + + + + + + + + SpectraHeis + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Clear + + + + + + + Ok + + + + + + + + + + 0 + + + + Operation + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Time Interval + + + + + + + + Incoherent Intergration + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Graphics + + + + + + Prefix + + + + + + + ... + + + + + + + + + + + + + + ymin - ymax + + + + + + + Tmin - Tmax: + + + + + + + Time Range: + + + + + + + Wr Period + + + + + + + Qt::Horizontal + + + + 134 + 20 + + + + + + + + + + + + + + + + + + + + + Channel List: + + + + + + + xmin - xmax + + + + + + + + + + Save + + + + + + + ftp + + + + + + + Spectra Plot + + + + + + + + + + + + + + + + + Path + + + + + + + Show + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 106 + 20 + + + + + + + + + + + + + + + + + + + + + + RTI PLot + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Output + + + + + + Path: + + + + + + + Blocks per File: + + + + + + + Type: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + + + + + + + + .fits + + + + + + + + Metada + + + + + + + + + + + + + ... + + + + + + + + + + + + Correlation + + + + + + 0 + + + + Operation + + + + + Graphics + + + + + + + + + + + 0 + 0 + + + + 0 + + + + Console + + + + + + + + + + + + 0 + + + + Project Property + + + + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1065 + 25 + + + + + Project + + + + + + + + + Run + + + + + + + Options + + + + + + Help + + + + + + + + + + + + ../Documents/figure/open.png../Documents/figure/open.png + + + Open + + + + + + ../Documents/figure/create_class_obj.png../Documents/figure/create_class_obj.png + + + Create + + + + + + ../Documents/figure/save.gif../Documents/figure/save.gif + + + Save + + + + + Close + + + + + + ../Documents/figure/startServer.png../Documents/figure/startServer.png + + + Start + + + + + Pause + + + + + About + + + + + + ../Documents/figure/open.png../Documents/figure/open.png + + + openToolbar + + + Open + + + + + + ../Documents/figure/create_class_obj.png../Documents/figure/create_class_obj.png + + + createToolbar + + + Create + + + + + + ../Documents/figure/save.gif../Documents/figure/save.gif + + + saveToolbar + + + Save + + + + + + ../Documents/figure/startServer.png../Documents/figure/startServer.png + + + starToolbar + + + Start + + + + + + ../Documents/figure/stopServer.png../Documents/figure/stopServer.png + + + stopToolbar + + + Stop + + + + + + ../workspace/branch_gui_may/gui/figure/pause.png../workspace/branch_gui_may/gui/figure/pause.png + + + pauseToolbar + + + Pause + + + + + + ../addpu.jpg../addpu.jpg + + + addPU + + + + + FTP + + + + + + diff --git a/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v48.ui.svn-base b/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v48.ui.svn-base new file mode 100644 index 0000000..d34bd2e --- /dev/null +++ b/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v48.ui.svn-base @@ -0,0 +1,2206 @@ + + + MainWindow + + + + 0 + 0 + 1065 + 711 + + + + MainWindow + + + + + + + Qt::Horizontal + + + + + Qt::Vertical + + + + + 0 + 278 + + + + + 16777215 + 16777215 + + + + 0 + + + + Project + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Project Name : + + + + + + + + + + DataType : + + + + + + + + Voltage + + + + + Spectra + + + + + Fits + + + + + + + + + + + DataPath : + + + + + + + ... + + + + + + + + + + Read Mode: + + + + + + + + Off Line + + + + + On Line + + + + + + + + Delay: + + + + + + + + + + Walk : + + + + + + + + Search 0 + + + + + Search 1 + + + + + + + + Load + + + + + + + Set: + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Star Date: + + + + + + + + + + End Date: + + + + + + + + + + Start Time: + + + + + + + + + + End Time: + + + + + + + + + + Description: + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + + Voltage + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + 0 + + + + Operation + + + + + + + + + + Value + + + + + Index + + + + + + + + + Value + + + + + Index + + + + + + + + Profile Selector + + + + + + + + Profile List + + + + + Profile Range List + + + + + + + + Decoder + + + + + + + Coherent Integration + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Code: + + + + + + + Select Channels + + + + + + + Select Heights + + + + + + + Filter + + + + + + + + + + Radar Frequency + + + + + + + Mode: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Barker 3 + + + + + Barker 4 + + + + + Barker 5 + + + + + Barker 7 + + + + + Barker 11 + + + + + Barker 13 + + + + + Barker 3 + Comp. + + + + + Barker 4 + Comp. + + + + + Barker 5 + Comp. + + + + + Barker 7 + Comp. + + + + + Barker 11+ Comp. + + + + + Barker 13+ Comp. + + + + + None + + + + + + + + + Time + + + + + Freq 1 + + + + + + + + + Graphics + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + ... + + + + + + + + + + Scope + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Channel List + + + + + + + Show + + + + + + + Freq/Vel + + + + + + + + + + + + + + Path : + + + + + + + Prefix: + + + + + + + Height range + + + + + + + Qt::Horizontal + + + + 40 + 12 + + + + + + + + Qt::Horizontal + + + + 18 + 12 + + + + + + + + + + + + + + Save + + + + + + + + + + + + + + + Output + + + + + + Type: + + + + + + + Path: + + + + + + + + + + ... + + + + + + + + .rawdata + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Blocks per File : + + + + + + + Profiles per Block: + + + + + + + + + + + + + + + Spectra + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + 0 + + + + Operation + + + + + + Select Cross Spectra + + + + + + + + Value + + + + + Index + + + + + + + + + + + + Value + + + + + Index + + + + + + + + + + + + + + Remove DC + + + + + + + Select Heights + + + + + + + Select Channel + + + + + + + + + + + + + x-y pairs + + + + + + + nFFTPoints + + + + + + + Incoherent Integration + + + + + + + + Time Interval + + + + + Profiles + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Radar Frequency + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Profiles + + + + + + + + + + Remove Interference + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Mode 1 + + + + + Mode 2 + + + + + + + + IppFactor + + + + + + + + + + Get Noise + + + + + + + + + + + Graphics + + + + + + Coherence Map + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Tmin, Tmax: + + + + + + + + + + + + + + + + + + + + + + + + + + + Prefix : + + + + + + + + + + Qt::Horizontal + + + + 28 + 15 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + RTI Plot + + + + + + + Height range: + + + + + + + dBs range: + + + + + + + magnitud [0-1] + + + + + + + + + + + + + Qt::Horizontal + + + + 49 + 15 + + + + + + + + Path : + + + + + + + + + + + + + Power Profile + + + + + + + Freq/Vel: + + + + + + + + + + Cross Spectra Plot + + + + + + + ... + + + + + + + Channel List: + + + + + + + Spectra Plot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 39 + 15 + + + + + + + + + + + Show + + + + + + + + + + + + + + Wr Period: + + + + + + + Save + + + + + + + + + + + + + + + + + + + + + + + + + + + + ftp + + + + + + + + + + + + + + RTI Noise + + + + + + + + + + + + + + + + + + + + + Time Range: + + + + + + + + + + + Output + + + + + + Type: + + + + + + + + .pdata + + + + + + + + Path: + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + + + + + + + Blocks per File: + + + + + + + Profile per Block: + + + + + + + + + + + + + + + SpectraHeis + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Clear + + + + + + + Ok + + + + + + + + + + 0 + + + + Operation + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Time Interval + + + + + + + + Incoherent Intergration + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Graphics + + + + + + Prefix + + + + + + + ... + + + + + + + + + + + + + + ymin - ymax + + + + + + + Tmin - Tmax: + + + + + + + Time Range: + + + + + + + Wr Period + + + + + + + Qt::Horizontal + + + + 134 + 20 + + + + + + + + + + + + + + + + + + + + + Channel List: + + + + + + + xmin - xmax + + + + + + + + + + Save + + + + + + + ftp + + + + + + + Spectra Plot + + + + + + + + + + + + + + + + + Path + + + + + + + Show + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 106 + 20 + + + + + + + + + + + + + + + + + + + + + + RTI PLot + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Output + + + + + + Path: + + + + + + + Blocks per File: + + + + + + + Type: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + + + + + + + + .fits + + + + + + + + Metada + + + + + + + + + + + + + ... + + + + + + + + + + + + Correlation + + + + + + 0 + + + + Operation + + + + + Graphics + + + + + + + + + + + 0 + 0 + + + + 0 + + + + Console + + + + + + + + + + + + 0 + + + + Project Property + + + + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1065 + 25 + + + + + Project + + + + + + + + + Run + + + + + + + Options + + + + + + Help + + + + + + + + + + + + ../Documents/figure/open.png../Documents/figure/open.png + + + Open + + + + + + ../Documents/figure/create_class_obj.png../Documents/figure/create_class_obj.png + + + Create + + + + + + ../Documents/figure/save.gif../Documents/figure/save.gif + + + Save + + + + + Close + + + + + + ../Documents/figure/startServer.png../Documents/figure/startServer.png + + + Start + + + + + Pause + + + + + About + + + + + + ../Documents/figure/open.png../Documents/figure/open.png + + + openToolbar + + + Open + + + + + + ../Documents/figure/create_class_obj.png../Documents/figure/create_class_obj.png + + + createToolbar + + + Create + + + + + + ../Documents/figure/save.gif../Documents/figure/save.gif + + + saveToolbar + + + Save + + + + + + ../Documents/figure/startServer.png../Documents/figure/startServer.png + + + starToolbar + + + Start + + + + + + ../Documents/figure/stopServer.png../Documents/figure/stopServer.png + + + stopToolbar + + + Stop + + + + + + ../workspace/branch_gui_may/gui/figure/pause.png../workspace/branch_gui_may/gui/figure/pause.png + + + pauseToolbar + + + Pause + + + + + + ../addpu.jpg../addpu.jpg + + + addPU + + + + + FTP + + + + + + diff --git a/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v49.ui.svn-base b/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v49.ui.svn-base new file mode 100644 index 0000000..31cff87 --- /dev/null +++ b/schainpy/gui/viewer/viewer_ui/.svn/text-base/MainWindow_21_02_13_v49.ui.svn-base @@ -0,0 +1,2206 @@ + + + MainWindow + + + + 0 + 0 + 1065 + 711 + + + + MainWindow + + + + + + + Qt::Horizontal + + + + + Qt::Vertical + + + + + 0 + 278 + + + + + 16777215 + 16777215 + + + + 0 + + + + Project + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Project Name : + + + + + + + + + + DataType : + + + + + + + + Voltage + + + + + Spectra + + + + + Fits + + + + + + + + + + + DataPath : + + + + + + + ... + + + + + + + + + + Read Mode: + + + + + + + + Off Line + + + + + On Line + + + + + + + + Delay: + + + + + + + + + + Walk : + + + + + + + + Search 0 + + + + + Search 1 + + + + + + + + Load + + + + + + + Set: + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Star Date: + + + + + + + + + + End Date: + + + + + + + + + + Start Time: + + + + + + + + + + End Time: + + + + + + + + + + Description: + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + + Voltage + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + 0 + + + + Operation + + + + + + + + + + Value + + + + + Index + + + + + + + + + Value + + + + + Index + + + + + + + + Profile Selector + + + + + + + + Profile List + + + + + Profile Range List + + + + + + + + Decoder + + + + + + + Coherent Integration + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Code: + + + + + + + Select Channels + + + + + + + Select Heights + + + + + + + Filter + + + + + + + + + + Radar Frequency + + + + + + + Mode: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Barker 3 + + + + + Barker 4 + + + + + Barker 5 + + + + + Barker 7 + + + + + Barker 11 + + + + + Barker 13 + + + + + Barker 3 + Comp. + + + + + Barker 4 + Comp. + + + + + Barker 5 + Comp. + + + + + Barker 7 + Comp. + + + + + Barker 11+ Comp. + + + + + Barker 13+ Comp. + + + + + None + + + + + + + + + Time + + + + + Freq 1 + + + + + + + + + Graphics + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + ... + + + + + + + + + + Scope + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Channel List + + + + + + + Show + + + + + + + Freq/Vel + + + + + + + + + + + + + + Path : + + + + + + + Prefix: + + + + + + + Height range + + + + + + + Qt::Horizontal + + + + 40 + 12 + + + + + + + + Qt::Horizontal + + + + 18 + 12 + + + + + + + + + + + + + + Save + + + + + + + + + + + + + + + Output + + + + + + Type: + + + + + + + Path: + + + + + + + + + + ... + + + + + + + + .rawdata + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Blocks per File : + + + + + + + Profiles per Block: + + + + + + + + + + + + + + + Spectra + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Ok + + + + + + + Clear + + + + + + + + + + 0 + + + + Operation + + + + + + Select Cross Spectra + + + + + + + + Value + + + + + Index + + + + + + + + + + + + Value + + + + + Index + + + + + + + + + + + + + + Remove DC + + + + + + + Select Heights + + + + + + + Select Channel + + + + + + + + + + + + + x-y pairs + + + + + + + nFFTPoints + + + + + + + Incoherent Integration + + + + + + + + Time Interval + + + + + Profiles + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Radar Frequency + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Profiles + + + + + + + + + + Remove Interference + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + IppFactor + + + + + + + Get Noise + + + + + + + + + + + Mode 1 + + + + + Mode 2 + + + + + + + + + + + + Graphics + + + + + + Coherence Map + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Tmin, Tmax: + + + + + + + + + + + + + + + + + + + + + + + + + + + Prefix : + + + + + + + + + + Qt::Horizontal + + + + 28 + 15 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + RTI Plot + + + + + + + Height range: + + + + + + + dBs range: + + + + + + + magnitud [0-1] + + + + + + + + + + + + + Qt::Horizontal + + + + 49 + 15 + + + + + + + + Path : + + + + + + + + + + + + + Power Profile + + + + + + + Freq/Vel: + + + + + + + + + + Cross Spectra Plot + + + + + + + ... + + + + + + + Channel List: + + + + + + + Spectra Plot + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 39 + 15 + + + + + + + + + + + Show + + + + + + + + + + + + + + Wr Period: + + + + + + + Save + + + + + + + + + + + + + + + + + + + + + + + + + + + + ftp + + + + + + + + + + + + + + RTI Noise + + + + + + + + + + + + + + + + + + + + + Time Range: + + + + + + + + + + + Output + + + + + + Type: + + + + + + + + .pdata + + + + + + + + Path: + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + + + + + + + Blocks per File: + + + + + + + Profile per Block: + + + + + + + + + + + + + + + SpectraHeis + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Clear + + + + + + + Ok + + + + + + + + + + 0 + + + + Operation + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Time Interval + + + + + + + + Incoherent Intergration + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Graphics + + + + + + Prefix + + + + + + + ... + + + + + + + + + + + + + + ymin - ymax + + + + + + + Tmin - Tmax: + + + + + + + Time Range: + + + + + + + Wr Period + + + + + + + Qt::Horizontal + + + + 134 + 20 + + + + + + + + + + + + + + + + + + + + + Channel List: + + + + + + + xmin - xmax + + + + + + + + + + Save + + + + + + + ftp + + + + + + + Spectra Plot + + + + + + + + + + + + + + + + + Path + + + + + + + Show + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 106 + 20 + + + + + + + + + + + + + + + + + + + + + + RTI PLot + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Output + + + + + + Path: + + + + + + + Blocks per File: + + + + + + + Type: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + + + + + + + + .fits + + + + + + + + Metada + + + + + + + + + + + + + ... + + + + + + + + + + + + Correlation + + + + + + 0 + + + + Operation + + + + + Graphics + + + + + + + + + + + 0 + 0 + + + + 0 + + + + Console + + + + + + + + + + + + 0 + + + + Project Property + + + + + + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + + + + + + + + + + + + + 0 + 0 + 1065 + 25 + + + + + Project + + + + + + + + + Run + + + + + + + Options + + + + + + Help + + + + + + + + + + + + ../Documents/figure/open.png../Documents/figure/open.png + + + Open + + + + + + ../Documents/figure/create_class_obj.png../Documents/figure/create_class_obj.png + + + Create + + + + + + ../Documents/figure/save.gif../Documents/figure/save.gif + + + Save + + + + + Close + + + + + + ../Documents/figure/startServer.png../Documents/figure/startServer.png + + + Start + + + + + Pause + + + + + About + + + + + + ../Documents/figure/open.png../Documents/figure/open.png + + + openToolbar + + + Open + + + + + + ../Documents/figure/create_class_obj.png../Documents/figure/create_class_obj.png + + + createToolbar + + + Create + + + + + + ../Documents/figure/save.gif../Documents/figure/save.gif + + + saveToolbar + + + Save + + + + + + ../Documents/figure/startServer.png../Documents/figure/startServer.png + + + starToolbar + + + Start + + + + + + ../Documents/figure/stopServer.png../Documents/figure/stopServer.png + + + stopToolbar + + + Stop + + + + + + ../workspace/branch_gui_may/gui/figure/pause.png../workspace/branch_gui_may/gui/figure/pause.png + + + pauseToolbar + + + Pause + + + + + + ../addpu.jpg../addpu.jpg + + + addPU + + + + + FTP + + + + + + diff --git a/schainpy/gui/viewer/viewer_ui/.svn/text-base/ftpConfig4.ui.svn-base b/schainpy/gui/viewer/viewer_ui/.svn/text-base/ftpConfig4.ui.svn-base new file mode 100644 index 0000000..ec05dbf --- /dev/null +++ b/schainpy/gui/viewer/viewer_ui/.svn/text-base/ftpConfig4.ui.svn-base @@ -0,0 +1,300 @@ + + + MainWindow + + + + 0 + 0 + 374 + 399 + + + + + 374 + 399 + + + + + 374 + 399 + + + + MainWindow + + + + + + 9 + 38 + 47 + 17 + + + + Server: + + + + + + 9 + 133 + 77 + 17 + + + + User Name: + + + + + + 9 + 166 + 68 + 17 + + + + Password: + + + + + + 9 + 9 + 101 + 17 + + + + + 75 + true + + + + Server Details + + + + + + 9 + 104 + 87 + 17 + + + + + 75 + true + + + + User Details + + + + + + 9 + 71 + 47 + 17 + + + + Folder: + + + + + + 130 + 40 + 231 + 27 + + + + + + + 130 + 70 + 231 + 27 + + + + + + + 130 + 130 + 231 + 27 + + + + + + + 130 + 160 + 231 + 27 + + + + + + + 130 + 360 + 111 + 27 + + + + Cancel + + + + + + 250 + 360 + 111 + 27 + + + + Ok + + + + + + 10 + 200 + 66 + 17 + + + + + 75 + true + + + + Others + + + + + + 10 + 230 + 81 + 17 + + + + Ftp_wei: + + + + + + 10 + 260 + 81 + 17 + + + + Exp_code: + + + + + + 10 + 290 + 81 + 17 + + + + Sub_exp: + + + + + + 10 + 320 + 81 + 17 + + + + Plot_pos: + + + + + + 130 + 230 + 231 + 27 + + + + + + + 130 + 260 + 231 + 27 + + + + + + + 130 + 290 + 231 + 27 + + + + + + + 130 + 320 + 231 + 27 + + + + + + + + diff --git a/schainpy/gui/viewer/viewer_ui/.svn/text-base/initwindowv2.ui.svn-base b/schainpy/gui/viewer/viewer_ui/.svn/text-base/initwindowv2.ui.svn-base new file mode 100644 index 0000000..d254434 --- /dev/null +++ b/schainpy/gui/viewer/viewer_ui/.svn/text-base/initwindowv2.ui.svn-base @@ -0,0 +1,112 @@ + + + Dialog + + + + 0 + 0 + 652 + 496 + + + + Dialog + + + + + + + + + + + Cambria + 22 + 50 + false + + + + Signal Chain - Ver. 1.0 + + + + + + + Qt::Horizontal + + + + + + + + + + ../../Downloads/IMAGENES/w.jpg + + + true + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Exit + + + + + + + Continue + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + diff --git a/schainpy/gui/viewer/viewer_ui/.svn/text-base/unitProcess4.ui.svn-base b/schainpy/gui/viewer/viewer_ui/.svn/text-base/unitProcess4.ui.svn-base new file mode 100644 index 0000000..d077917 --- /dev/null +++ b/schainpy/gui/viewer/viewer_ui/.svn/text-base/unitProcess4.ui.svn-base @@ -0,0 +1,170 @@ + + + MainWindow + + + + 0 + 0 + 312 + 195 + + + + MainWindow + + + + + + + + 12 + 50 + false + + + + Input: + + + + + + + + 50 + false + + + + Cancel + + + + + + + + 50 + false + + + + Ok + + + + + + + + 12 + 50 + false + + + + Type: + + + + + + + + 13 + 50 + false + + + + Processing Unit + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 12 + + + + + + + + + 12 + + + + + Voltage + + + + + Spectra + + + + + Correlation + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + + + + + + diff --git a/schainpy/gui/viewer/viewer_ui/.svn/text-base/workspacev5.ui.svn-base b/schainpy/gui/viewer/viewer_ui/.svn/text-base/workspacev5.ui.svn-base new file mode 100644 index 0000000..5aad07a --- /dev/null +++ b/schainpy/gui/viewer/viewer_ui/.svn/text-base/workspacev5.ui.svn-base @@ -0,0 +1,247 @@ + + + Dialog + + + true + + + + 0 + 0 + 730 + 295 + + + + + 730 + 295 + + + + + 730 + 295 + + + + Dialog + + + + + 0 + 0 + 731 + 71 + + + + true + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell'; font-size:12pt; font-weight:600;">Select a workspace</span></p> +<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell';">Signal Chain stores your projects in a folder called a workspace.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Cantarell';">Choose a workspace folder to use for this session.</span></p></body></html> + + + + + + 10 + 90 + 91 + 16 + + + + + 11 + + + + Workspace : + + + + + + 110 + 80 + 501 + 31 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + + + + + 620 + 80 + 101 + 31 + + + + + 11 + + + + Browse... + + + + + + 10 + 120 + 711 + 121 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 490 + 250 + 111 + 31 + + + + Cancel + + + + + + 610 + 250 + 111 + 31 + + + + + 11 + + + + OK + + + + + + diff --git a/schainpy/gui/viewer/windows/.svn/all-wcprops b/schainpy/gui/viewer/windows/.svn/all-wcprops new file mode 100644 index 0000000..a489a6f --- /dev/null +++ b/schainpy/gui/viewer/windows/.svn/all-wcprops @@ -0,0 +1,41 @@ +K 25 +svn:wc:ra_dav:version-url +V 89 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/windows +END +ui_correlation.py +K 25 +svn:wc:ra_dav:version-url +V 107 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/windows/ui_correlation.py +END +ui_voltage.py +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/windows/ui_voltage.py +END +__init__.py +K 25 +svn:wc:ra_dav:version-url +V 101 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/windows/__init__.py +END +ui_project.py +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/windows/ui_project.py +END +ui_spectra.py +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/windows/ui_spectra.py +END +ui_spectra_heis.py +K 25 +svn:wc:ra_dav:version-url +V 108 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/gui/viewer/windows/ui_spectra_heis.py +END diff --git a/schainpy/gui/viewer/windows/.svn/entries b/schainpy/gui/viewer/windows/.svn/entries new file mode 100644 index 0000000..8c57f33 --- /dev/null +++ b/schainpy/gui/viewer/windows/.svn/entries @@ -0,0 +1,232 @@ +10 + +dir +1608 +http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainpy/gui/viewer/windows +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 + +__init__.py +file + + + + +2017-04-17T17:05:33.000000Z +113187ac3f8d701c0ef1c7717aa6b7eb +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +133 + +ui_correlation.py +file + + + + +2017-04-17T17:05:33.000000Z +eccb65ea68c38cf568c278f39527ac0b +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +2053 + +ui_project.py +file + + + + +2017-04-17T17:05:33.000000Z +cabbb9dc85ff983cca982338182c2cd7 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +12905 + +ui_spectra.py +file + + + + +2017-04-17T17:05:33.000000Z +0058160656fe59592074d9ad079eaafd +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +30909 + +ui_spectra_heis.py +file + + + + +2017-04-17T17:05:33.000000Z +7e73c99d4f58545197395a8049b287a0 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +16937 + +ui_voltage.py +file + + + + +2017-04-17T17:05:33.000000Z +d00abf84f52ee0ccf4ec87196c2d735d +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +23996 + diff --git a/schainpy/gui/viewer/windows/.svn/text-base/__init__.py.svn-base b/schainpy/gui/viewer/windows/.svn/text-base/__init__.py.svn-base new file mode 100644 index 0000000..af97a97 --- /dev/null +++ b/schainpy/gui/viewer/windows/.svn/text-base/__init__.py.svn-base @@ -0,0 +1,5 @@ +from ui_project import * +from ui_voltage import * +from ui_spectra import * +from ui_spectra_heis import * +from ui_correlation import * \ No newline at end of file diff --git a/schainpy/gui/viewer/windows/.svn/text-base/ui_correlation.py.svn-base b/schainpy/gui/viewer/windows/.svn/text-base/ui_correlation.py.svn-base new file mode 100644 index 0000000..0c80785 --- /dev/null +++ b/schainpy/gui/viewer/windows/.svn/text-base/ui_correlation.py.svn-base @@ -0,0 +1,45 @@ + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) + +class Ui_CorrelationTab(object): + + def setupUi(self): + + self.tabCorrelation = QtGui.QWidget() + self.tabCorrelation.setObjectName(_fromUtf8("tabCorrelation")) + self.gridLayout_13 = QtGui.QGridLayout(self.tabCorrelation) + self.gridLayout_13.setObjectName(_fromUtf8("gridLayout_13")) + self.tabWidgetCorrelation = QtGui.QTabWidget(self.tabCorrelation) + self.tabWidgetCorrelation.setObjectName(_fromUtf8("tabWidgetCorrelation")) + self.tabopCorrelation = QtGui.QWidget() + self.tabopCorrelation.setObjectName(_fromUtf8("tabopCorrelation")) + self.tabWidgetCorrelation.addTab(self.tabopCorrelation, _fromUtf8("")) + self.tabopCorrelation1 = QtGui.QWidget() + self.tabopCorrelation1.setObjectName(_fromUtf8("tabopCorrelation1")) + self.tabWidgetCorrelation.addTab(self.tabopCorrelation1, _fromUtf8("")) + self.gridLayout_13.addWidget(self.tabWidgetCorrelation, 0, 0, 1, 1) + + self.tabWidgetProject.addTab(self.tabCorrelation, _fromUtf8("")) + + self.tabWidgetCorrelation.setCurrentIndex(0) + + def retranslateUi(self): + + self.tabWidgetCorrelation.setTabText(self.tabWidgetCorrelation.indexOf(self.tabopCorrelation), _translate("MainWindow", "Operation", None)) + self.tabWidgetCorrelation.setTabText(self.tabWidgetCorrelation.indexOf(self.tabopCorrelation1), _translate("MainWindow", "Graphics", None)) + self.tabWidgetProject.setTabText(self.tabWidgetProject.indexOf(self.tabCorrelation), _translate("MainWindow", "Correlation", None)) + \ No newline at end of file diff --git a/schainpy/gui/viewer/windows/.svn/text-base/ui_project.py.svn-base b/schainpy/gui/viewer/windows/.svn/text-base/ui_project.py.svn-base new file mode 100644 index 0000000..7b22c32 --- /dev/null +++ b/schainpy/gui/viewer/windows/.svn/text-base/ui_project.py.svn-base @@ -0,0 +1,257 @@ + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) + +class Ui_ProjectTab(object): + + def setupUi(self): + + self.tabProject = QtGui.QWidget() + self.tabProject.setObjectName(_fromUtf8("tabProject")) + self.gridLayout_15 = QtGui.QGridLayout(self.tabProject) + self.gridLayout_15.setObjectName(_fromUtf8("gridLayout_15")) + + self.frame = QtGui.QFrame(self.tabProject) + self.frame.setFrameShape(QtGui.QFrame.StyledPanel) + self.frame.setFrameShadow(QtGui.QFrame.Raised) + self.frame.setObjectName(_fromUtf8("frame")) + + self.gridLayout_2 = QtGui.QGridLayout(self.frame) + self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2")) + + self.label = QtGui.QLabel(self.frame) + self.label.setObjectName(_fromUtf8("label")) + self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1) + + self.proName = QtGui.QLineEdit(self.frame) + self.proName.setObjectName(_fromUtf8("proName")) + self.gridLayout_2.addWidget(self.proName, 0, 1, 1, 8) + + self.labDatatype = QtGui.QLabel(self.frame) + self.labDatatype.setObjectName(_fromUtf8("labDatatype")) + self.gridLayout_2.addWidget(self.labDatatype, 1, 0, 1, 1) + + self.proComDataType = QtGui.QComboBox(self.frame) + self.proComDataType.setObjectName(_fromUtf8("proComDataType")) + self.proComDataType.addItem(_fromUtf8("")) + self.proComDataType.addItem(_fromUtf8("")) + self.proComDataType.addItem(_fromUtf8("")) + self.proComDataType.addItem(_fromUtf8("")) + self.gridLayout_2.addWidget(self.proComDataType, 1, 1, 1, 6) + + self.proDataType = QtGui.QLineEdit(self.frame) + self.proDataType.setObjectName(_fromUtf8("proDataType")) + self.gridLayout_2.addWidget(self.proDataType, 1, 7, 1, 2) + + self.labDatapath = QtGui.QLabel(self.frame) + self.labDatapath.setObjectName(_fromUtf8("labDatapath")) + self.gridLayout_2.addWidget(self.labDatapath, 2, 0, 1, 1) + + self.proToolPath = QtGui.QToolButton(self.frame) + self.proToolPath.setObjectName(_fromUtf8("proToolPath")) + self.gridLayout_2.addWidget(self.proToolPath, 2, 1, 1, 1) + + self.proDataPath = QtGui.QLineEdit(self.frame) + self.proDataPath.setObjectName(_fromUtf8("proDataPath")) + self.gridLayout_2.addWidget(self.proDataPath, 2, 2, 1, 7) + + self.labelWalk = QtGui.QLabel(self.frame) + self.labelWalk.setObjectName(_fromUtf8("labelWalk")) + self.gridLayout_2.addWidget(self.labelWalk, 3, 0, 1, 1) + + self.proComWalk = QtGui.QComboBox(self.frame) + self.proComWalk.setObjectName(_fromUtf8("proComWalk")) + self.proComWalk.addItem(_fromUtf8("")) + self.proComWalk.addItem(_fromUtf8("")) + self.gridLayout_2.addWidget(self.proComWalk, 3, 1, 1, 4) + + self.labExpLabel = QtGui.QLabel(self.frame) + self.labExpLabel.setObjectName(_fromUtf8("labExpLabel")) + self.gridLayout_2.addWidget(self.labExpLabel, 3, 5, 1, 1) + + self.proExpLabel = QtGui.QLineEdit(self.frame) + self.proExpLabel.setObjectName(_fromUtf8("proExpLabel")) + self.gridLayout_2.addWidget(self.proExpLabel, 3, 6, 1, 1) + + self.labReadMode = QtGui.QLabel(self.frame) + self.labReadMode.setObjectName(_fromUtf8("labReadMode")) + self.gridLayout_2.addWidget(self.labReadMode, 4, 0, 1, 1) + + self.proComReadMode = QtGui.QComboBox(self.frame) + self.proComReadMode.setObjectName(_fromUtf8("proComReadMode")) + self.proComReadMode.addItem(_fromUtf8("")) + self.proComReadMode.addItem(_fromUtf8("")) + self.gridLayout_2.addWidget(self.proComReadMode, 4, 1, 1, 4) + + self.labDelay = QtGui.QLabel(self.frame) + self.labDelay.setObjectName(_fromUtf8("labDelay")) + self.gridLayout_2.addWidget(self.labDelay, 4, 5, 1, 1) + + self.proDelay = QtGui.QLineEdit(self.frame) + self.proDelay.setObjectName(_fromUtf8("proDelay")) + self.gridLayout_2.addWidget(self.proDelay, 4, 6, 1, 1) + + self.labelSet = QtGui.QLabel(self.frame) + self.labelSet.setObjectName(_fromUtf8("labelSet")) + self.gridLayout_2.addWidget(self.labelSet, 4, 7, 1, 1) + + self.proSet = QtGui.QLineEdit(self.frame) + self.proSet.setObjectName(_fromUtf8("proSet")) + self.gridLayout_2.addWidget(self.proSet, 4, 8, 1, 1) + + + self.proLoadButton = QtGui.QPushButton(self.frame) + self.proLoadButton.setObjectName(_fromUtf8("proLoadButton")) + self.gridLayout_2.addWidget(self.proLoadButton, 5, 0, 1, 9) + + self.frame_data = QtGui.QFrame(self.tabProject) + self.frame_data.setFrameShape(QtGui.QFrame.StyledPanel) + self.frame_data.setFrameShadow(QtGui.QFrame.Raised) + self.frame_data.setObjectName(_fromUtf8("frame_data")) + + self.gridLayout_data = QtGui.QGridLayout(self.frame_data) + self.gridLayout_data.setObjectName(_fromUtf8("gridLayout_data")) + + self.labelIPPKm = QtGui.QLabel(self.frame_data) + self.labelIPPKm.setObjectName(_fromUtf8("labelIPPKm")) + self.gridLayout_data.addWidget(self.labelIPPKm, 6, 0, 1, 1) + + self.proIPPKm = QtGui.QLineEdit(self.frame_data) + self.proIPPKm.setObjectName(_fromUtf8("proIPPKm")) + self.gridLayout_data.addWidget(self.proIPPKm, 6, 1, 1, 6) + + self.labnTxs = QtGui.QLabel(self.frame_data) + self.labnTxs.setObjectName(_fromUtf8("labnTxs")) + self.gridLayout_data.addWidget(self.labnTxs, 6, 0, 1, 1) + + self.pronTxs = QtGui.QLineEdit(self.frame_data) + self.pronTxs.setObjectName(_fromUtf8("pronTxs")) + self.gridLayout_data.addWidget(self.pronTxs, 6, 1, 1, 6) + + self.labByBlock = QtGui.QLabel(self.frame_data) + self.labByBlock.setObjectName(_fromUtf8("labByBlock")) + self.gridLayout_data.addWidget(self.labByBlock, 6, 7, 1, 1) + + self.proComByBlock = QtGui.QComboBox(self.frame_data) + self.proComByBlock.setObjectName(_fromUtf8("proComByBlock")) + self.proComByBlock.addItem(_fromUtf8("")) + self.proComByBlock.addItem(_fromUtf8("")) + self.gridLayout_data.addWidget(self.proComByBlock, 6, 8, 1, 1) + + + self.frame_2 = QtGui.QFrame(self.tabProject) + self.frame_2.setFrameShape(QtGui.QFrame.StyledPanel) + self.frame_2.setFrameShadow(QtGui.QFrame.Raised) + self.frame_2.setObjectName(_fromUtf8("frame_2")) + + self.gridLayout_10 = QtGui.QGridLayout(self.frame_2) + self.gridLayout_10.setObjectName(_fromUtf8("gridLayout_10")) + + self.label_27 = QtGui.QLabel(self.frame_2) + self.label_27.setObjectName(_fromUtf8("label_27")) + self.gridLayout_10.addWidget(self.label_27, 0, 0, 1, 1) + self.proComStartDate = QtGui.QComboBox(self.frame_2) + self.proComStartDate.setObjectName(_fromUtf8("proComStartDate")) + self.gridLayout_10.addWidget(self.proComStartDate, 0, 1, 1, 1) + self.label_28 = QtGui.QLabel(self.frame_2) + self.label_28.setObjectName(_fromUtf8("label_28")) + self.gridLayout_10.addWidget(self.label_28, 1, 0, 1, 1) + self.proComEndDate = QtGui.QComboBox(self.frame_2) + self.proComEndDate.setObjectName(_fromUtf8("proComEndDate")) + self.gridLayout_10.addWidget(self.proComEndDate, 1, 1, 1, 1) + self.label_2 = QtGui.QLabel(self.frame_2) + self.label_2.setObjectName(_fromUtf8("label_2")) + self.gridLayout_10.addWidget(self.label_2, 2, 0, 1, 1) + self.proStartTime = QtGui.QTimeEdit(self.frame_2) + self.proStartTime.setObjectName(_fromUtf8("proStartTime")) + self.gridLayout_10.addWidget(self.proStartTime, 2, 1, 1, 1) + self.label_3 = QtGui.QLabel(self.frame_2) + self.label_3.setObjectName(_fromUtf8("label_3")) + self.gridLayout_10.addWidget(self.label_3, 3, 0, 1, 1) + self.proEndTime = QtGui.QTimeEdit(self.frame_2) + self.proEndTime.setObjectName(_fromUtf8("proEndTime")) + self.gridLayout_10.addWidget(self.proEndTime, 3, 1, 1, 1) + self.label_30 = QtGui.QLabel(self.frame_2) + self.label_30.setObjectName(_fromUtf8("label_30")) + self.gridLayout_10.addWidget(self.label_30, 4, 0, 1, 1) + self.proDescription = QtGui.QTextEdit(self.frame_2) + self.proDescription.setObjectName(_fromUtf8("proDescription")) + self.gridLayout_10.addWidget(self.proDescription, 4, 1, 1, 1) + + self.frame_3 = QtGui.QFrame(self.tabProject) + self.frame_3.setFrameShape(QtGui.QFrame.StyledPanel) + self.frame_3.setFrameShadow(QtGui.QFrame.Raised) + self.frame_3.setObjectName(_fromUtf8("frame_3")) + self.gridLayout_14 = QtGui.QGridLayout(self.frame_3) + self.gridLayout_14.setObjectName(_fromUtf8("gridLayout_14")) + self.proOk = QtGui.QPushButton(self.frame_3) + self.proOk.setObjectName(_fromUtf8("proOk")) + self.gridLayout_14.addWidget(self.proOk, 0, 0, 1, 1) + self.proClear = QtGui.QPushButton(self.frame_3) + self.proClear.setObjectName(_fromUtf8("proClear")) + self.gridLayout_14.addWidget(self.proClear, 0, 1, 1, 1) + + self.gridLayout_15.addWidget(self.frame, 0, 0, 8, 1) + self.gridLayout_15.addWidget(self.frame_data, 8, 0, 2, 1) + self.gridLayout_15.addWidget(self.frame_2, 10, 0, 7, 1) + self.gridLayout_15.addWidget(self.frame_3, 17, 0, 2, 1) + + self.tabWidgetProject.addTab(self.tabProject, _fromUtf8("")) + + def retranslateUi(self): + + self.label.setText(_translate("MainWindow", "Project Name :", None)) + self.labDatatype.setText(_translate("MainWindow", "Data type :", None)) + self.proComDataType.setItemText(0, _translate("MainWindow", "Voltage", None)) + self.proComDataType.setItemText(1, _translate("MainWindow", "Spectra", None)) + self.proComDataType.setItemText(2, _translate("MainWindow", "Fits", None)) + self.proComDataType.setItemText(3, _translate("MainWindow", "USRP", None)) + self.labDatapath.setText(_translate("MainWindow", "Data path :", None)) + self.proToolPath.setText(_translate("MainWindow", "...", None)) + self.labReadMode.setText(_translate("MainWindow", "Read mode:", None)) + self.proComReadMode.setItemText(0, _translate("MainWindow", "Offline", None)) + self.proComReadMode.setItemText(1, _translate("MainWindow", "Online", None)) + self.labDelay.setText(_translate("MainWindow", "Delay:", None)) + self.labExpLabel.setText(_translate("MainWindow", "Exp. Label:", None)) + self.labelWalk.setText(_translate("MainWindow", "Search data :", None)) + self.proComWalk.setItemText(0, _translate("MainWindow", "On files", None)) + self.proComWalk.setItemText(1, _translate("MainWindow", "On sub-folders", None)) + self.proComByBlock.setItemText(0, _translate("MainWindow", "By profile", None)) + self.proComByBlock.setItemText(1, _translate("MainWindow", "By block", None)) + self.labByBlock.setText(_translate("MainWindow", "Get data:", None)) + + + self.proLoadButton.setText(_translate("MainWindow", "Load", None)) + self.labelSet.setText(_translate("MainWindow", "File set:", None)) + self.labelIPPKm.setText(_translate("MainWindow", "IPP (km):", None)) + self.labnTxs.setText(_translate("MainWindow", "Number of Txs:", None)) + + self.label_27.setText(_translate("MainWindow", "Star Date:", None)) + self.label_28.setText(_translate("MainWindow", "End Date:", None)) + self.label_2.setText(_translate("MainWindow", "Start Time:", None)) + self.label_3.setText(_translate("MainWindow", "End Time:", None)) + self.label_30.setText(_translate("MainWindow", "Description:", None)) + self.proOk.setText(_translate("MainWindow", "Ok", None)) + self.proClear.setText(_translate("MainWindow", "Clear", None)) + + self.tabWidgetProject.setTabText(self.tabWidgetProject.indexOf(self.tabProject), _translate("MainWindow", "Project", None)) + + self.__setToolTip() + + def __setToolTip(self): + + self.proComWalk.setToolTip('On Files:Search file in format .r or pdata On Folders:Search file in a directory DYYYYDOY') + \ No newline at end of file diff --git a/schainpy/gui/viewer/windows/.svn/text-base/ui_spectra.py.svn-base b/schainpy/gui/viewer/windows/.svn/text-base/ui_spectra.py.svn-base new file mode 100644 index 0000000..c1d09ab --- /dev/null +++ b/schainpy/gui/viewer/windows/.svn/text-base/ui_spectra.py.svn-base @@ -0,0 +1,528 @@ +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) + +class Ui_SpectraTab(object): + + def setupUi(self): + + self.tabSpectra = QtGui.QWidget() + self.tabSpectra.setObjectName(_fromUtf8("tabSpectra")) + self.gridLayout_7 = QtGui.QGridLayout(self.tabSpectra) + self.gridLayout_7.setObjectName(_fromUtf8("gridLayout_7")) + self.frame_5 = QtGui.QFrame(self.tabSpectra) + self.frame_5.setFrameShape(QtGui.QFrame.StyledPanel) + self.frame_5.setFrameShadow(QtGui.QFrame.Raised) + self.frame_5.setObjectName(_fromUtf8("frame_5")) + self.gridLayout_18 = QtGui.QGridLayout(self.frame_5) + self.gridLayout_18.setObjectName(_fromUtf8("gridLayout_18")) + + self.specOpOk = QtGui.QPushButton(self.frame_5) + self.specOpOk.setObjectName(_fromUtf8("specOpOk")) + self.gridLayout_18.addWidget(self.specOpOk, 0, 0, 1, 1) + + self.specGraphClear = QtGui.QPushButton(self.frame_5) + self.specGraphClear.setObjectName(_fromUtf8("specGraphClear")) + self.gridLayout_18.addWidget(self.specGraphClear, 0, 1, 1, 1) + + self.gridLayout_7.addWidget(self.frame_5, 1, 1, 1, 1) + + self.tabWidgetSpectra = QtGui.QTabWidget(self.tabSpectra) + self.tabWidgetSpectra.setObjectName(_fromUtf8("tabWidgetSpectra")) + + self.tabopSpectra = QtGui.QWidget() + self.tabopSpectra.setObjectName(_fromUtf8("tabopSpectra")) + + self.gridLayout_5 = QtGui.QGridLayout(self.tabopSpectra) + self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5")) + + + + self.specOpCebRadarfrequency = QtGui.QCheckBox(self.tabopSpectra) + self.specOpCebRadarfrequency.setObjectName(_fromUtf8("specOpCebRadarfrequency")) + self.gridLayout_5.addWidget(self.specOpCebRadarfrequency, 0, 0, 1, 1) + + self.specOpRadarfrequency = QtGui.QLineEdit(self.tabopSpectra) + self.specOpRadarfrequency.setObjectName(_fromUtf8("specOpRadarfrequency")) + self.gridLayout_5.addWidget(self.specOpRadarfrequency, 0, 1, 1, 4) + + + self.specLabProfiles = QtGui.QLabel(self.tabopSpectra) + self.specLabProfiles.setObjectName(_fromUtf8("specLabProfiles")) + self.gridLayout_5.addWidget(self.specLabProfiles, 1, 0, 1, 1) + + self.specOpProfiles = QtGui.QLineEdit(self.tabopSpectra) + self.specOpProfiles.setObjectName(_fromUtf8("specOpProfiles")) + self.gridLayout_5.addWidget(self.specOpProfiles, 1, 1, 1, 4) + + + self.specLabnFFTPoints = QtGui.QLabel(self.tabopSpectra) + self.specLabnFFTPoints.setObjectName(_fromUtf8("specLabnFFTPoints")) + self.gridLayout_5.addWidget(self.specLabnFFTPoints, 2, 0, 1, 1) + + self.specOpnFFTpoints = QtGui.QLineEdit(self.tabopSpectra) + self.specOpnFFTpoints.setObjectName(_fromUtf8("specOpnFFTpoints")) + self.gridLayout_5.addWidget(self.specOpnFFTpoints, 2, 1, 1, 4) + + + self.specLabippFactor = QtGui.QLabel(self.tabopSpectra) + self.specLabippFactor.setObjectName(_fromUtf8("specLabippFactor")) + self.gridLayout_5.addWidget(self.specLabippFactor, 3, 0, 1, 1) + + self.specOpippFactor = QtGui.QLineEdit(self.tabopSpectra) + self.specOpippFactor.setObjectName(_fromUtf8("specOpippFactor")) + self.gridLayout_5.addWidget(self.specOpippFactor, 3, 1, 1, 4) + + + self.specOpCebChannel = QtGui.QCheckBox(self.tabopSpectra) + self.specOpCebChannel.setObjectName(_fromUtf8("specOpCebChannel")) + self.gridLayout_5.addWidget(self.specOpCebChannel, 4, 0, 1, 1) + + self.specOpComChannel = QtGui.QComboBox(self.tabopSpectra) + self.specOpComChannel.setObjectName(_fromUtf8("specOpComChannel")) + self.specOpComChannel.addItem(_fromUtf8("")) + self.specOpComChannel.addItem(_fromUtf8("")) + self.gridLayout_5.addWidget(self.specOpComChannel, 4, 1, 1, 2) + + self.specOpChannel = QtGui.QLineEdit(self.tabopSpectra) + self.specOpChannel.setObjectName(_fromUtf8("specOpChannel")) + self.gridLayout_5.addWidget(self.specOpChannel, 4, 3, 1, 2) + + + self.specOpCebCrossSpectra = QtGui.QCheckBox(self.tabopSpectra) + self.specOpCebCrossSpectra.setObjectName(_fromUtf8("specOpCebCrossSpectra")) + self.gridLayout_5.addWidget(self.specOpCebCrossSpectra, 5, 0, 1, 1) + + self.specOpComCrossSpectra = QtGui.QComboBox(self.tabopSpectra) + self.specOpComCrossSpectra.setObjectName(_fromUtf8("specOpComCrossSpectra")) + self.specOpComCrossSpectra.addItem(_fromUtf8("")) + self.gridLayout_5.addWidget(self.specOpComCrossSpectra, 5, 1, 1, 2) + + self.specOppairsList = QtGui.QLineEdit(self.tabopSpectra) + self.specOppairsList.setObjectName(_fromUtf8("specOppairsList")) + self.gridLayout_5.addWidget(self.specOppairsList, 5, 3, 1, 2) + + + self.specOpCebHeights = QtGui.QCheckBox(self.tabopSpectra) + self.specOpCebHeights.setObjectName(_fromUtf8("specOpCebHeights")) + self.gridLayout_5.addWidget(self.specOpCebHeights, 6, 0, 1, 1) + + self.specOpComHeights = QtGui.QComboBox(self.tabopSpectra) + self.specOpComHeights.setObjectName(_fromUtf8("specOpComHeights")) + self.specOpComHeights.addItem(_fromUtf8("")) + self.specOpComHeights.addItem(_fromUtf8("")) + self.gridLayout_5.addWidget(self.specOpComHeights, 6, 1, 1, 2) + + self.specOpHeights = QtGui.QLineEdit(self.tabopSpectra) + self.specOpHeights.setObjectName(_fromUtf8("specOpHeights")) + self.gridLayout_5.addWidget(self.specOpHeights, 6, 3, 1, 2) + + + self.specOpCebIncoherent = QtGui.QCheckBox(self.tabopSpectra) + self.specOpCebIncoherent.setObjectName(_fromUtf8("specOpCebIncoherent")) + self.gridLayout_5.addWidget(self.specOpCebIncoherent, 7, 0, 1, 1) + + self.specOpCobIncInt = QtGui.QComboBox(self.tabopSpectra) + self.specOpCobIncInt.setObjectName(_fromUtf8("specOpCobIncInt")) + self.specOpCobIncInt.addItem(_fromUtf8("")) + self.specOpCobIncInt.addItem(_fromUtf8("")) + self.gridLayout_5.addWidget(self.specOpCobIncInt, 7, 1, 1, 2) + + self.specOpIncoherent = QtGui.QLineEdit(self.tabopSpectra) + self.specOpIncoherent.setObjectName(_fromUtf8("specOpIncoherent")) + self.gridLayout_5.addWidget(self.specOpIncoherent, 7, 3, 1, 2) + + + self.specOpCebRemoveDC = QtGui.QCheckBox(self.tabopSpectra) + self.specOpCebRemoveDC.setObjectName(_fromUtf8("specOpCebRemoveDC")) + self.gridLayout_5.addWidget(self.specOpCebRemoveDC, 8, 0, 1, 1) + + self.specOpComRemoveDC = QtGui.QComboBox(self.tabopSpectra) + self.specOpComRemoveDC.setObjectName(_fromUtf8("specOpComRemoveDC")) + self.specOpComRemoveDC.addItem(_fromUtf8("")) + self.specOpComRemoveDC.addItem(_fromUtf8("")) + self.gridLayout_5.addWidget(self.specOpComRemoveDC, 8, 1, 1, 2) + + + self.specOpCebRemoveInt = QtGui.QCheckBox(self.tabopSpectra) + self.specOpCebRemoveInt.setObjectName(_fromUtf8("specOpCebRemoveInt")) + self.gridLayout_5.addWidget(self.specOpCebRemoveInt, 9, 0, 1, 1) + + + self.specOpCebgetNoise = QtGui.QCheckBox(self.tabopSpectra) + self.specOpCebgetNoise.setObjectName(_fromUtf8("specOpCebgetNoise")) + self.gridLayout_5.addWidget(self.specOpCebgetNoise, 10, 0, 1, 1) + + self.specOpgetNoise = QtGui.QLineEdit(self.tabopSpectra) + self.specOpgetNoise.setObjectName(_fromUtf8("specOpgetNoise")) + self.gridLayout_5.addWidget(self.specOpgetNoise, 10, 1, 1, 4) + +# spacerItem9 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout_5.addItem(spacerItem9, 12, 3, 1, 1) +# +# spacerItem10 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout_5.addItem(spacerItem10, 9, 3, 1, 1) +# +# spacerItem11 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout_5.addItem(spacerItem11, 7, 3, 1, 1) +# +# spacerItem12 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout_5.addItem(spacerItem12, 4, 3, 1, 1) +# +# spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout_5.addItem(spacerItem13, 15, 3, 1, 1) + + + self.tabWidgetSpectra.addTab(self.tabopSpectra, _fromUtf8("")) + + ################################################################ + ################################################################ + + self.tabgraphSpectra = QtGui.QWidget() + self.tabgraphSpectra.setObjectName(_fromUtf8("tabgraphSpectra")) + self.gridLayout_9 = QtGui.QGridLayout(self.tabgraphSpectra) + self.gridLayout_9.setObjectName(_fromUtf8("gridLayout_9")) + +# spacerItem14 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) +# self.gridLayout_9.addItem(spacerItem14, 14, 2, 1, 1) + xi = 0 + + self.label_24 = QtGui.QLabel(self.tabgraphSpectra) + self.label_24.setObjectName(_fromUtf8("label_24")) + self.gridLayout_9.addWidget(self.label_24, xi, 0, 1, 1) + + self.specGraphPath = QtGui.QLineEdit(self.tabgraphSpectra) + self.specGraphPath.setObjectName(_fromUtf8("specGraphPath")) + self.gridLayout_9.addWidget(self.specGraphPath, xi, 1, 1, 6) + + self.specGraphToolPath = QtGui.QToolButton(self.tabgraphSpectra) + self.specGraphToolPath.setObjectName(_fromUtf8("specGraphToolPath")) + self.gridLayout_9.addWidget(self.specGraphToolPath, xi, 7, 1, 1) + + self.label_25 = QtGui.QLabel(self.tabgraphSpectra) + self.label_25.setObjectName(_fromUtf8("label_25")) + self.gridLayout_9.addWidget(self.label_25, xi+1, 0, 1, 1) + self.specGraphPrefix = QtGui.QLineEdit(self.tabgraphSpectra) + self.specGraphPrefix.setObjectName(_fromUtf8("specGraphPrefix")) + self.gridLayout_9.addWidget(self.specGraphPrefix, xi+1, 1, 1, 7) + + xi = 2 + + self.label_40 = QtGui.QLabel(self.tabgraphSpectra) + self.label_40.setObjectName(_fromUtf8("label_40")) + self.gridLayout_9.addWidget(self.label_40, xi+1, 0, 1, 1) + self.label_41 = QtGui.QLabel(self.tabgraphSpectra) + self.label_41.setObjectName(_fromUtf8("label_41")) + self.gridLayout_9.addWidget(self.label_41, xi+2, 0, 1, 1) + self.label_42 = QtGui.QLabel(self.tabgraphSpectra) + self.label_42.setObjectName(_fromUtf8("label_42")) + self.gridLayout_9.addWidget(self.label_42, xi+3, 0, 1, 1) + self.label_44 = QtGui.QLabel(self.tabgraphSpectra) + self.label_44.setObjectName(_fromUtf8("label_44")) + self.gridLayout_9.addWidget(self.label_44, xi+4, 0, 1, 1) + self.label_46 = QtGui.QLabel(self.tabgraphSpectra) + self.label_46.setObjectName(_fromUtf8("label_46")) + self.gridLayout_9.addWidget(self.label_46, xi+5, 0, 1, 1) + self.label_45 = QtGui.QLabel(self.tabgraphSpectra) + self.label_45.setObjectName(_fromUtf8("label_45")) + self.gridLayout_9.addWidget(self.label_45, xi+6, 0, 1, 1) + + self.label_43 = QtGui.QLabel(self.tabgraphSpectra) + self.label_43.setObjectName(_fromUtf8("label_43")) + self.gridLayout_9.addWidget(self.label_43, xi, 3, 1, 1) + self.specGraphCebSpectraplot = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphCebSpectraplot.setText(_fromUtf8("")) + self.specGraphCebSpectraplot.setObjectName(_fromUtf8("specGraphCebSpectraplot")) + self.gridLayout_9.addWidget(self.specGraphCebSpectraplot, xi+1, 3, 1, 1) + self.specGraphCebCrossSpectraplot = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphCebCrossSpectraplot.setText(_fromUtf8("")) + self.specGraphCebCrossSpectraplot.setObjectName(_fromUtf8("specGraphCebCrossSpectraplot")) + self.gridLayout_9.addWidget(self.specGraphCebCrossSpectraplot, xi+2, 3, 1, 1) + self.specGraphCebRTIplot = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphCebRTIplot.setText(_fromUtf8("")) + self.specGraphCebRTIplot.setObjectName(_fromUtf8("specGraphCebRTIplot")) + self.gridLayout_9.addWidget(self.specGraphCebRTIplot, xi+3, 3, 1, 1) + self.specGraphCebCoherencmap = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphCebCoherencmap.setText(_fromUtf8("")) + self.specGraphCebCoherencmap.setObjectName(_fromUtf8("specGraphCebCoherencmap")) + self.gridLayout_9.addWidget(self.specGraphCebCoherencmap, xi+4, 3, 1, 1) + self.specGraphPowerprofile = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphPowerprofile.setText(_fromUtf8("")) + self.specGraphPowerprofile.setObjectName(_fromUtf8("specGraphPowerprofile")) + self.gridLayout_9.addWidget(self.specGraphPowerprofile, xi+5, 3, 1, 1) + self.specGraphCebRTInoise = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphCebRTInoise.setText(_fromUtf8("")) + self.specGraphCebRTInoise.setObjectName(_fromUtf8("specGraphCebRTInoise")) + self.gridLayout_9.addWidget(self.specGraphCebRTInoise, xi+6, 3, 1, 1) + +# spacerItem18 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout_9.addItem(spacerItem18, 4, 3, 1, 1) + + self.label_47 = QtGui.QLabel(self.tabgraphSpectra) + self.label_47.setObjectName(_fromUtf8("label_47")) + self.gridLayout_9.addWidget(self.label_47, xi, 5, 1, 1) + self.specGraphSaveSpectra = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphSaveSpectra.setText(_fromUtf8("")) + self.specGraphSaveSpectra.setObjectName(_fromUtf8("specGraphSaveSpectra")) + self.gridLayout_9.addWidget(self.specGraphSaveSpectra, xi+1, 5, 1, 1) + self.specGraphSaveCross = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphSaveCross.setText(_fromUtf8("")) + self.specGraphSaveCross.setObjectName(_fromUtf8("specGraphSaveCross")) + self.gridLayout_9.addWidget(self.specGraphSaveCross, xi+2, 5, 1, 1) + self.specGraphSaveRTIplot = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphSaveRTIplot.setText(_fromUtf8("")) + self.specGraphSaveRTIplot.setObjectName(_fromUtf8("specGraphSaveRTIplot")) + self.gridLayout_9.addWidget(self.specGraphSaveRTIplot, xi+3, 5, 1, 1) + self.specGraphSaveCoherencemap = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphSaveCoherencemap.setText(_fromUtf8("")) + self.specGraphSaveCoherencemap.setObjectName(_fromUtf8("specGraphSaveCoherencemap")) + self.gridLayout_9.addWidget(self.specGraphSaveCoherencemap, xi+4, 5, 1, 1) + self.specGraphSavePowerprofile = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphSavePowerprofile.setText(_fromUtf8("")) + self.specGraphSavePowerprofile.setObjectName(_fromUtf8("specGraphSavePowerprofile")) + self.gridLayout_9.addWidget(self.specGraphSavePowerprofile, xi+5, 5, 1, 1) + self.specGraphSaveRTInoise = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphSaveRTInoise.setText(_fromUtf8("")) + self.specGraphSaveRTInoise.setObjectName(_fromUtf8("specGraphSaveRTInoise")) + self.gridLayout_9.addWidget(self.specGraphSaveRTInoise, xi+6, 5, 1, 1) + + self.label_19 = QtGui.QLabel(self.tabgraphSpectra) + self.label_19.setObjectName(_fromUtf8("label_19")) + self.gridLayout_9.addWidget(self.label_19, xi, 7, 1, 1) + self.specGraphftpSpectra = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphftpSpectra.setText(_fromUtf8("")) + self.specGraphftpSpectra.setObjectName(_fromUtf8("specGraphftpSpectra")) + self.gridLayout_9.addWidget(self.specGraphftpSpectra, xi+1, 7, 1, 1) + self.specGraphftpCross = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphftpCross.setText(_fromUtf8("")) + self.specGraphftpCross.setObjectName(_fromUtf8("specGraphftpCross")) + self.gridLayout_9.addWidget(self.specGraphftpCross, xi+2, 7, 1, 1) + self.specGraphftpRTIplot = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphftpRTIplot.setText(_fromUtf8("")) + self.specGraphftpRTIplot.setObjectName(_fromUtf8("specGraphftpRTIplot")) + self.gridLayout_9.addWidget(self.specGraphftpRTIplot, xi+3, 7, 1, 1) + self.specGraphftpCoherencemap = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphftpCoherencemap.setText(_fromUtf8("")) + self.specGraphftpCoherencemap.setObjectName(_fromUtf8("specGraphftpCoherencemap")) + self.gridLayout_9.addWidget(self.specGraphftpCoherencemap, xi+4, 7, 1, 1) + self.specGraphftpPowerprofile = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphftpPowerprofile.setText(_fromUtf8("")) + self.specGraphftpPowerprofile.setObjectName(_fromUtf8("specGraphftpPowerprofile")) + self.gridLayout_9.addWidget(self.specGraphftpPowerprofile, xi+5, 7, 1, 1) + self.specGraphftpRTInoise = QtGui.QCheckBox(self.tabgraphSpectra) + self.specGraphftpRTInoise.setText(_fromUtf8("")) + self.specGraphftpRTInoise.setObjectName(_fromUtf8("specGraphftpRTInoise")) + self.gridLayout_9.addWidget(self.specGraphftpRTInoise, xi+6, 7, 1, 1) + +# spacerItem19 = QtGui.QSpacerItem(39, 15, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout_9.addItem(spacerItem19, 27, 4, 1, 1) + + xi = 11 + + self.label_22 = QtGui.QLabel(self.tabgraphSpectra) + self.label_22.setObjectName(_fromUtf8("label_22")) + self.gridLayout_9.addWidget(self.label_22, xi, 0, 1, 1) + self.specGgraphFreq = QtGui.QLineEdit(self.tabgraphSpectra) + self.specGgraphFreq.setObjectName(_fromUtf8("specGgraphFreq")) + self.gridLayout_9.addWidget(self.specGgraphFreq, xi, 2, 1, 2) + + self.label_16 = QtGui.QLabel(self.tabgraphSpectra) + self.label_16.setObjectName(_fromUtf8("label_16")) + self.gridLayout_9.addWidget(self.label_16, xi+1, 0, 1, 1) + self.specGgraphHeight = QtGui.QLineEdit(self.tabgraphSpectra) + self.specGgraphHeight.setObjectName(_fromUtf8("specGgraphHeight")) + self.gridLayout_9.addWidget(self.specGgraphHeight, xi+1, 2, 1, 2) + + self.label_17 = QtGui.QLabel(self.tabgraphSpectra) + self.label_17.setObjectName(_fromUtf8("label_17")) + self.gridLayout_9.addWidget(self.label_17, xi+2, 0, 1, 1) + self.specGgraphDbsrange = QtGui.QLineEdit(self.tabgraphSpectra) + self.specGgraphDbsrange.setObjectName(_fromUtf8("specGgraphDbsrange")) + self.gridLayout_9.addWidget(self.specGgraphDbsrange, xi+2, 2, 1, 2) + + self.specGraphTminTmaxLabel = QtGui.QLabel(self.tabgraphSpectra) + self.specGraphTminTmaxLabel.setObjectName(_fromUtf8("specGraphTminTmaxLabel")) + self.gridLayout_9.addWidget(self.specGraphTminTmaxLabel, xi+3, 0, 1, 2) + self.specGgraphTminTmax = QtGui.QLineEdit(self.tabgraphSpectra) + self.specGgraphTminTmax.setObjectName(_fromUtf8("specGgraphTminTmax")) + self.gridLayout_9.addWidget(self.specGgraphTminTmax, xi+3, 2, 1, 2) + + self.label_48 = QtGui.QLabel(self.tabgraphSpectra) + self.label_48.setObjectName(_fromUtf8("label_48")) + self.gridLayout_9.addWidget(self.label_48, xi+4, 0, 1, 2) + self.specGgraphTimeRange = QtGui.QLineEdit(self.tabgraphSpectra) + self.specGgraphTimeRange.setObjectName(_fromUtf8("specGgraphTimeRange")) + self.gridLayout_9.addWidget(self.specGgraphTimeRange, xi+4, 2, 1, 2) + + self.specGraphMagLabel = QtGui.QLabel(self.tabgraphSpectra) + self.specGraphMagLabel.setObjectName(_fromUtf8("specGraphMagLabel")) + self.gridLayout_9.addWidget(self.specGraphMagLabel, xi, 4, 1, 2) + self.specGgraphmagnitud = QtGui.QLineEdit(self.tabgraphSpectra) + self.specGgraphmagnitud.setObjectName(_fromUtf8("specGgraphmagnitud")) + self.gridLayout_9.addWidget(self.specGgraphmagnitud, xi, 6, 1, 2) + + self.specGraphPhaseLabel = QtGui.QLabel(self.tabgraphSpectra) + self.specGraphPhaseLabel.setObjectName(_fromUtf8("specGraphPhaseLabel")) + self.gridLayout_9.addWidget(self.specGraphPhaseLabel, xi+1, 4, 1, 2) + self.specGgraphPhase = QtGui.QLineEdit(self.tabgraphSpectra) + self.specGgraphPhase.setObjectName(_fromUtf8("specGgraphPhase")) + self.gridLayout_9.addWidget(self.specGgraphPhase, xi+1, 6, 1, 2) + + self.label_6 = QtGui.QLabel(self.tabgraphSpectra) + self.label_6.setObjectName(_fromUtf8("label_6")) + self.gridLayout_9.addWidget(self.label_6, xi+2, 4, 1, 1) + self.specGgraphChannelList = QtGui.QLineEdit(self.tabgraphSpectra) + self.specGgraphChannelList.setObjectName(_fromUtf8("specGgraphChannelList")) + self.gridLayout_9.addWidget(self.specGgraphChannelList, xi+2, 6, 1, 2) + + self.label_29 = QtGui.QLabel(self.tabgraphSpectra) + self.label_29.setObjectName(_fromUtf8("label_29")) + self.gridLayout_9.addWidget(self.label_29, xi+3, 4, 1, 2) + self.specGgraphftpratio = QtGui.QLineEdit(self.tabgraphSpectra) + self.specGgraphftpratio.setObjectName(_fromUtf8("specGgraphftpratio")) + self.gridLayout_9.addWidget(self.specGgraphftpratio, xi+3, 6, 1, 2) + +# spacerItem15 = QtGui.QSpacerItem(28, 15, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout_9.addItem(spacerItem15, 27, 6, 1, 2) +# spacerItem16 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) +# self.gridLayout_9.addItem(spacerItem16, 3, 5, 1, 1) +# spacerItem17 = QtGui.QSpacerItem(49, 15, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout_9.addItem(spacerItem17, 27, 0, 1, 1) + + + + self.tabWidgetSpectra.addTab(self.tabgraphSpectra, _fromUtf8("")) + self.taboutputSpectra = QtGui.QWidget() + self.taboutputSpectra.setObjectName(_fromUtf8("taboutputSpectra")) + self.gridLayout_11 = QtGui.QGridLayout(self.taboutputSpectra) + self.gridLayout_11.setObjectName(_fromUtf8("gridLayout_11")) + self.label_39 = QtGui.QLabel(self.taboutputSpectra) + self.label_39.setObjectName(_fromUtf8("label_39")) + self.gridLayout_11.addWidget(self.label_39, 0, 0, 1, 1) + self.specOutputComData = QtGui.QComboBox(self.taboutputSpectra) + self.specOutputComData.setObjectName(_fromUtf8("specOutputComData")) + self.specOutputComData.addItem(_fromUtf8("")) + self.gridLayout_11.addWidget(self.specOutputComData, 0, 2, 1, 2) + self.label_34 = QtGui.QLabel(self.taboutputSpectra) + self.label_34.setObjectName(_fromUtf8("label_34")) + self.gridLayout_11.addWidget(self.label_34, 1, 0, 1, 1) + self.specOutputPath = QtGui.QLineEdit(self.taboutputSpectra) + self.specOutputPath.setObjectName(_fromUtf8("specOutputPath")) + self.gridLayout_11.addWidget(self.specOutputPath, 1, 2, 1, 1) + spacerItem20 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.gridLayout_11.addItem(spacerItem20, 4, 2, 1, 1) + self.specOutputToolPath = QtGui.QToolButton(self.taboutputSpectra) + self.specOutputToolPath.setObjectName(_fromUtf8("specOutputToolPath")) + self.gridLayout_11.addWidget(self.specOutputToolPath, 1, 3, 1, 1) + self.specOutputblocksperfile = QtGui.QLineEdit(self.taboutputSpectra) + self.specOutputblocksperfile.setObjectName(_fromUtf8("specOutputblocksperfile")) + self.gridLayout_11.addWidget(self.specOutputblocksperfile, 2, 2, 1, 1) + self.label_9 = QtGui.QLabel(self.taboutputSpectra) + self.label_9.setObjectName(_fromUtf8("label_9")) + self.gridLayout_11.addWidget(self.label_9, 2, 0, 1, 2) + + self.tabWidgetSpectra.addTab(self.taboutputSpectra, _fromUtf8("")) + self.gridLayout_7.addWidget(self.tabWidgetSpectra, 0, 1, 1, 1) + + self.tabWidgetProject.addTab(self.tabSpectra, _fromUtf8("")) + + self.tabWidgetSpectra.setCurrentIndex(0) + + def retranslateUi(self): + + self.specOpOk.setText(_translate("MainWindow", "Ok", None)) + self.specGraphClear.setText(_translate("MainWindow", "Clear", None)) + self.specOpCebCrossSpectra.setText(_translate("MainWindow", "Select Cross Spectra:", None)) + self.specOpComChannel.setItemText(0, _translate("MainWindow", "Value", None)) + self.specOpComChannel.setItemText(1, _translate("MainWindow", "Index", None)) + self.specOpComHeights.setItemText(0, _translate("MainWindow", "Value", None)) + self.specOpComHeights.setItemText(1, _translate("MainWindow", "Index", None)) + self.specOpCebRemoveDC.setText(_translate("MainWindow", "Remove DC:", None)) + self.specOpCebHeights.setText(_translate("MainWindow", "Select Heights:", None)) + self.specOpCebChannel.setText(_translate("MainWindow", "Select Channel:", None)) + + self.specOpComCrossSpectra.setItemText(0, _translate("MainWindow", "x-y pairs", None)) + + self.specLabnFFTPoints.setText(_translate("MainWindow", "Number of FFT points:", None)) + self.specOpCebIncoherent.setText(_translate("MainWindow", "Incoherent Integration:", None)) + self.specOpCobIncInt.setItemText(0, _translate("MainWindow", "Time Interval", None)) + self.specOpCobIncInt.setItemText(1, _translate("MainWindow", "Number of Profiles", None)) + self.specOpCebRadarfrequency.setText(_translate("MainWindow", "Radar frequency (MHz):", None)) + self.specLabProfiles.setText(_translate("MainWindow", "Number of Profiles", None)) + self.specOpCebRemoveInt.setText(_translate("MainWindow", "Remove Interference:", None)) + self.specLabippFactor.setText(_translate("MainWindow", "Ipp Factor:", None)) + self.specOpCebgetNoise.setText(_translate("MainWindow", "Set Noise area:", None)) + self.specOpComRemoveDC.setItemText(0, _translate("MainWindow", "Mode 1", None)) + self.specOpComRemoveDC.setItemText(1, _translate("MainWindow", "Mode 2", None)) + self.tabWidgetSpectra.setTabText(self.tabWidgetSpectra.indexOf(self.tabopSpectra), _translate("MainWindow", "Operation", None)) + + self.label_44.setText(_translate("MainWindow", "Coherence Map:", None)) + self.specGraphTminTmaxLabel.setText(_translate("MainWindow", "Time range (hours):", None)) + self.label_25.setText(_translate("MainWindow", "Prefix:", None)) + self.label_42.setText(_translate("MainWindow", "RTI Plot:", None)) + self.label_16.setText(_translate("MainWindow", "Height range:", None)) + self.label_17.setText(_translate("MainWindow", "dB range:", None)) + self.specGraphMagLabel.setText(_translate("MainWindow", "Coh. Magnitud:", None)) + self.label_24.setText(_translate("MainWindow", "Path:", None)) + self.label_46.setText(_translate("MainWindow", "Power Profile:", None)) + self.label_22.setText(_translate("MainWindow", "Freq/Vel range:", None)) + self.label_41.setText(_translate("MainWindow", "Cross Spectra Plot:", None)) + self.specGraphToolPath.setText(_translate("MainWindow", "...", None)) + self.label_6.setText(_translate("MainWindow", "Channel List:", None)) + self.label_40.setText(_translate("MainWindow", "Spectra Plot:", None)) + self.label_43.setText(_translate("MainWindow", "Show:", None)) + self.label_29.setText(_translate("MainWindow", "Writing Period:", None)) + self.label_47.setText(_translate("MainWindow", "Save:", None)) + self.label_19.setText(_translate("MainWindow", "Ftp:", None)) + self.label_45.setText(_translate("MainWindow", "Noise:", None)) + self.label_48.setText(_translate("MainWindow", "Time window (seconds):", None)) + self.specGraphPhaseLabel.setText(_translate("MainWindow", "Coh. Phase:", None)) +# self.label_48.hide() +# self.specGgraphTimeRange.hide() + self.tabWidgetSpectra.setTabText(self.tabWidgetSpectra.indexOf(self.tabgraphSpectra), _translate("MainWindow", "Graphics", None)) + + self.label_39.setText(_translate("MainWindow", "Type:", None)) + self.specOutputComData.setItemText(0, _translate("MainWindow", ".pdata", None)) + self.label_34.setText(_translate("MainWindow", "Path:", None)) + self.specOutputToolPath.setText(_translate("MainWindow", "...", None)) + self.label_9.setText(_translate("MainWindow", "Blocks per File: ", None)) + + self.tabWidgetSpectra.setTabText(self.tabWidgetSpectra.indexOf(self.taboutputSpectra), _translate("MainWindow", "Output", None)) + + self.tabWidgetProject.setTabText(self.tabWidgetProject.indexOf(self.tabSpectra), _translate("MainWindow", "Spectra", None)) + + self.__setToolTip() + + def __setToolTip(self): + + self.specOpnFFTpoints.setToolTip('Number of FFT points used in FFT function. Example: 128') + self.specOpProfiles.setToolTip('Number of data points used in FFT function. Example: 128') + self.specOpippFactor.setToolTip('This factor is multiplied to IPP value to get velocity and frequency range. Example: 4') + self.specOpIncoherent.setToolTip('Example: 10') + self.specOpgetNoise.setToolTip('Example:20,180,30,120 (minHei,maxHei,minVel,maxVel)') + + self.specOpChannel.setToolTip('Example: 0,1,2,3') + self.specOpHeights.setToolTip('Example: 90,180') + self.specOppairsList.setToolTip('Example: (0,1),(2,3)') + # tool tip gui specGraph + + self.specGgraphChannelList.setToolTip('Example: 0,3,4') + self.specGgraphFreq.setToolTip('Example: -20,20') + self.specGgraphHeight.setToolTip('Example: 100,400') + self.specGgraphDbsrange.setToolTip('Example: 30,170') + + self.specGraphPrefix.setToolTip('Example: EXPERIMENT_NAME') + + \ No newline at end of file diff --git a/schainpy/gui/viewer/windows/.svn/text-base/ui_spectra_heis.py.svn-base b/schainpy/gui/viewer/windows/.svn/text-base/ui_spectra_heis.py.svn-base new file mode 100644 index 0000000..7fcbcd3 --- /dev/null +++ b/schainpy/gui/viewer/windows/.svn/text-base/ui_spectra_heis.py.svn-base @@ -0,0 +1,252 @@ +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) + +class Ui_SpectraHeisTab(object): + + def setupUi(self): + + self.tabSpectraHeis = QtGui.QWidget() + self.tabSpectraHeis.setObjectName(_fromUtf8("tabSpectraHeis")) + self.gridLayout_23 = QtGui.QGridLayout(self.tabSpectraHeis) + self.gridLayout_23.setObjectName(_fromUtf8("gridLayout_23")) + self.frame_6 = QtGui.QFrame(self.tabSpectraHeis) + self.frame_6.setFrameShape(QtGui.QFrame.StyledPanel) + self.frame_6.setFrameShadow(QtGui.QFrame.Raised) + self.frame_6.setObjectName(_fromUtf8("frame_6")) + self.gridLayout_22 = QtGui.QGridLayout(self.frame_6) + self.gridLayout_22.setObjectName(_fromUtf8("gridLayout_22")) + self.specHeisGraphClear = QtGui.QPushButton(self.frame_6) + self.specHeisGraphClear.setObjectName(_fromUtf8("specHeisGraphClear")) + self.gridLayout_22.addWidget(self.specHeisGraphClear, 0, 1, 1, 1) + self.specHeisOpOk = QtGui.QPushButton(self.frame_6) + self.specHeisOpOk.setObjectName(_fromUtf8("specHeisOpOk")) + self.gridLayout_22.addWidget(self.specHeisOpOk, 0, 0, 1, 1) + self.gridLayout_23.addWidget(self.frame_6, 1, 0, 1, 1) + self.tabWidgetSpectraHeis = QtGui.QTabWidget(self.tabSpectraHeis) + self.tabWidgetSpectraHeis.setObjectName(_fromUtf8("tabWidgetSpectraHeis")) + self.tabopSpectraHeis = QtGui.QWidget() + self.tabopSpectraHeis.setObjectName(_fromUtf8("tabopSpectraHeis")) + self.gridLayout_21 = QtGui.QGridLayout(self.tabopSpectraHeis) + self.gridLayout_21.setObjectName(_fromUtf8("gridLayout_21")) + spacerItem21 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.gridLayout_21.addItem(spacerItem21, 0, 1, 1, 1) + self.specHeisOpCobIncInt = QtGui.QComboBox(self.tabopSpectraHeis) + self.specHeisOpCobIncInt.setObjectName(_fromUtf8("specHeisOpCobIncInt")) + self.specHeisOpCobIncInt.addItem(_fromUtf8("")) + self.gridLayout_21.addWidget(self.specHeisOpCobIncInt, 1, 0, 1, 1) + self.specHeisOpCebIncoherent = QtGui.QCheckBox(self.tabopSpectraHeis) + self.specHeisOpCebIncoherent.setObjectName(_fromUtf8("specHeisOpCebIncoherent")) + self.gridLayout_21.addWidget(self.specHeisOpCebIncoherent, 0, 0, 1, 1) + self.specHeisOpIncoherent = QtGui.QLineEdit(self.tabopSpectraHeis) + self.specHeisOpIncoherent.setObjectName(_fromUtf8("specHeisOpIncoherent")) + self.gridLayout_21.addWidget(self.specHeisOpIncoherent, 1, 1, 1, 1) + spacerItem22 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.gridLayout_21.addItem(spacerItem22, 2, 0, 1, 1) + self.tabWidgetSpectraHeis.addTab(self.tabopSpectraHeis, _fromUtf8("")) + self.tabgraphSpectraHeis = QtGui.QWidget() + self.tabgraphSpectraHeis.setObjectName(_fromUtf8("tabgraphSpectraHeis")) + self.gridLayout_20 = QtGui.QGridLayout(self.tabgraphSpectraHeis) + self.gridLayout_20.setObjectName(_fromUtf8("gridLayout_20")) + self.label_54 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_54.setObjectName(_fromUtf8("label_54")) + self.gridLayout_20.addWidget(self.label_54, 1, 0, 1, 1) + self.specHeisGraphToolPath = QtGui.QToolButton(self.tabgraphSpectraHeis) + self.specHeisGraphToolPath.setObjectName(_fromUtf8("specHeisGraphToolPath")) + self.gridLayout_20.addWidget(self.specHeisGraphToolPath, 0, 6, 1, 1) + self.specHeisGraphCebRTIplot = QtGui.QCheckBox(self.tabgraphSpectraHeis) + self.specHeisGraphCebRTIplot.setText(_fromUtf8("")) + self.specHeisGraphCebRTIplot.setObjectName(_fromUtf8("specHeisGraphCebRTIplot")) + self.gridLayout_20.addWidget(self.specHeisGraphCebRTIplot, 4, 2, 1, 1) + self.label_62 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_62.setObjectName(_fromUtf8("label_62")) + self.gridLayout_20.addWidget(self.label_62, 7, 0, 1, 1) + self.label_63 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_63.setObjectName(_fromUtf8("label_63")) + self.gridLayout_20.addWidget(self.label_63, 8, 0, 1, 1) + self.label_64 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_64.setObjectName(_fromUtf8("label_64")) + self.gridLayout_20.addWidget(self.label_64, 9, 0, 1, 1) + self.label_65 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_65.setObjectName(_fromUtf8("label_65")) + self.gridLayout_20.addWidget(self.label_65, 10, 0, 1, 1) + spacerItem23 = QtGui.QSpacerItem(134, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.gridLayout_20.addItem(spacerItem23, 11, 0, 1, 2) + self.specHeisGgraphftpratio = QtGui.QLineEdit(self.tabgraphSpectraHeis) + self.specHeisGgraphftpratio.setObjectName(_fromUtf8("specHeisGgraphftpratio")) + self.gridLayout_20.addWidget(self.specHeisGgraphftpratio, 10, 1, 1, 6) + self.specHeisGraphftpRTIplot = QtGui.QCheckBox(self.tabgraphSpectraHeis) + self.specHeisGraphftpRTIplot.setText(_fromUtf8("")) + self.specHeisGraphftpRTIplot.setObjectName(_fromUtf8("specHeisGraphftpRTIplot")) + self.gridLayout_20.addWidget(self.specHeisGraphftpRTIplot, 4, 6, 1, 1) + self.specHeisGgraphTminTmax = QtGui.QLineEdit(self.tabgraphSpectraHeis) + self.specHeisGgraphTminTmax.setObjectName(_fromUtf8("specHeisGgraphTminTmax")) + self.gridLayout_20.addWidget(self.specHeisGgraphTminTmax, 8, 1, 1, 6) + self.label_60 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_60.setObjectName(_fromUtf8("label_60")) + self.gridLayout_20.addWidget(self.label_60, 5, 0, 1, 1) + self.label_61 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_61.setObjectName(_fromUtf8("label_61")) + self.gridLayout_20.addWidget(self.label_61, 6, 0, 1, 1) + self.specHeisGraphPrefix = QtGui.QLineEdit(self.tabgraphSpectraHeis) + self.specHeisGraphPrefix.setObjectName(_fromUtf8("specHeisGraphPrefix")) + self.gridLayout_20.addWidget(self.specHeisGraphPrefix, 1, 1, 1, 6) + self.label_56 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_56.setObjectName(_fromUtf8("label_56")) + self.gridLayout_20.addWidget(self.label_56, 2, 4, 1, 1) + self.label_57 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_57.setObjectName(_fromUtf8("label_57")) + self.gridLayout_20.addWidget(self.label_57, 2, 6, 1, 1) + self.label_58 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_58.setObjectName(_fromUtf8("label_58")) + self.gridLayout_20.addWidget(self.label_58, 3, 0, 1, 1) + self.specHeisGraphCebSpectraplot = QtGui.QCheckBox(self.tabgraphSpectraHeis) + self.specHeisGraphCebSpectraplot.setText(_fromUtf8("")) + self.specHeisGraphCebSpectraplot.setObjectName(_fromUtf8("specHeisGraphCebSpectraplot")) + self.gridLayout_20.addWidget(self.specHeisGraphCebSpectraplot, 3, 2, 1, 1) + self.specHeisGgraphYminYmax = QtGui.QLineEdit(self.tabgraphSpectraHeis) + self.specHeisGgraphYminYmax.setObjectName(_fromUtf8("specHeisGgraphYminYmax")) + self.gridLayout_20.addWidget(self.specHeisGgraphYminYmax, 7, 1, 1, 6) + self.label_53 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_53.setObjectName(_fromUtf8("label_53")) + self.gridLayout_20.addWidget(self.label_53, 0, 0, 1, 1) + self.label_55 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_55.setObjectName(_fromUtf8("label_55")) + self.gridLayout_20.addWidget(self.label_55, 2, 2, 1, 1) + self.specHeisGraphSaveRTIplot = QtGui.QCheckBox(self.tabgraphSpectraHeis) + self.specHeisGraphSaveRTIplot.setText(_fromUtf8("")) + self.specHeisGraphSaveRTIplot.setObjectName(_fromUtf8("specHeisGraphSaveRTIplot")) + self.gridLayout_20.addWidget(self.specHeisGraphSaveRTIplot, 4, 4, 1, 1) + spacerItem24 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.gridLayout_20.addItem(spacerItem24, 2, 3, 1, 1) + self.specHeisGgraphXminXmax = QtGui.QLineEdit(self.tabgraphSpectraHeis) + self.specHeisGgraphXminXmax.setObjectName(_fromUtf8("specHeisGgraphXminXmax")) + self.gridLayout_20.addWidget(self.specHeisGgraphXminXmax, 6, 1, 1, 6) + self.specHeisGgraphChannelList = QtGui.QLineEdit(self.tabgraphSpectraHeis) + self.specHeisGgraphChannelList.setObjectName(_fromUtf8("specHeisGgraphChannelList")) + self.gridLayout_20.addWidget(self.specHeisGgraphChannelList, 5, 1, 1, 6) + self.specHeisGgraphTimeRange = QtGui.QLineEdit(self.tabgraphSpectraHeis) + self.specHeisGgraphTimeRange.setObjectName(_fromUtf8("specHeisGgraphTimeRange")) + self.gridLayout_20.addWidget(self.specHeisGgraphTimeRange, 9, 1, 1, 6) + spacerItem25 = QtGui.QSpacerItem(106, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.gridLayout_20.addItem(spacerItem25, 11, 3, 1, 3) + self.specHeisGraphSaveSpectra = QtGui.QCheckBox(self.tabgraphSpectraHeis) + self.specHeisGraphSaveSpectra.setText(_fromUtf8("")) + self.specHeisGraphSaveSpectra.setObjectName(_fromUtf8("specHeisGraphSaveSpectra")) + self.gridLayout_20.addWidget(self.specHeisGraphSaveSpectra, 3, 4, 1, 1) + self.specHeisGraphftpSpectra = QtGui.QCheckBox(self.tabgraphSpectraHeis) + self.specHeisGraphftpSpectra.setText(_fromUtf8("")) + self.specHeisGraphftpSpectra.setObjectName(_fromUtf8("specHeisGraphftpSpectra")) + self.gridLayout_20.addWidget(self.specHeisGraphftpSpectra, 3, 6, 1, 1) + self.label_59 = QtGui.QLabel(self.tabgraphSpectraHeis) + self.label_59.setObjectName(_fromUtf8("label_59")) + self.gridLayout_20.addWidget(self.label_59, 4, 0, 1, 1) + spacerItem26 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.gridLayout_20.addItem(spacerItem26, 2, 5, 1, 1) + self.specHeisGraphPath = QtGui.QLineEdit(self.tabgraphSpectraHeis) + self.specHeisGraphPath.setObjectName(_fromUtf8("specHeisGraphPath")) + self.gridLayout_20.addWidget(self.specHeisGraphPath, 0, 1, 1, 5) + self.tabWidgetSpectraHeis.addTab(self.tabgraphSpectraHeis, _fromUtf8("")) + self.taboutputSpectraHeis = QtGui.QWidget() + self.taboutputSpectraHeis.setObjectName(_fromUtf8("taboutputSpectraHeis")) + self.gridLayout_19 = QtGui.QGridLayout(self.taboutputSpectraHeis) + self.gridLayout_19.setObjectName(_fromUtf8("gridLayout_19")) + self.label_67 = QtGui.QLabel(self.taboutputSpectraHeis) + self.label_67.setObjectName(_fromUtf8("label_67")) + self.gridLayout_19.addWidget(self.label_67, 1, 0, 1, 1) + self.label_68 = QtGui.QLabel(self.taboutputSpectraHeis) + self.label_68.setObjectName(_fromUtf8("label_68")) + self.gridLayout_19.addWidget(self.label_68, 2, 0, 1, 2) + self.label_66 = QtGui.QLabel(self.taboutputSpectraHeis) + self.label_66.setObjectName(_fromUtf8("label_66")) + self.gridLayout_19.addWidget(self.label_66, 0, 0, 1, 1) + spacerItem27 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.gridLayout_19.addItem(spacerItem27, 4, 0, 1, 1) + self.specHeisOutputToolPath = QtGui.QToolButton(self.taboutputSpectraHeis) + self.specHeisOutputToolPath.setObjectName(_fromUtf8("specHeisOutputToolPath")) + self.gridLayout_19.addWidget(self.specHeisOutputToolPath, 1, 4, 1, 1) + self.specHeisOutputPath = QtGui.QLineEdit(self.taboutputSpectraHeis) + self.specHeisOutputPath.setObjectName(_fromUtf8("specHeisOutputPath")) + self.gridLayout_19.addWidget(self.specHeisOutputPath, 1, 3, 1, 1) + self.specHeisOutputComdata = QtGui.QComboBox(self.taboutputSpectraHeis) + self.specHeisOutputComdata.setObjectName(_fromUtf8("specHeisOutputComdata")) + self.specHeisOutputComdata.addItem(_fromUtf8("")) + self.gridLayout_19.addWidget(self.specHeisOutputComdata, 0, 3, 1, 2) + self.label_69 = QtGui.QLabel(self.taboutputSpectraHeis) + self.label_69.setObjectName(_fromUtf8("label_69")) + self.gridLayout_19.addWidget(self.label_69, 3, 0, 1, 2) + self.specHeisOutputblocksperfile = QtGui.QLineEdit(self.taboutputSpectraHeis) + self.specHeisOutputblocksperfile.setObjectName(_fromUtf8("specHeisOutputblocksperfile")) + self.gridLayout_19.addWidget(self.specHeisOutputblocksperfile, 2, 3, 1, 1) + self.specHeisOutputMetada = QtGui.QLineEdit(self.taboutputSpectraHeis) + self.specHeisOutputMetada.setObjectName(_fromUtf8("specHeisOutputMetada")) + self.gridLayout_19.addWidget(self.specHeisOutputMetada, 3, 3, 1, 1) + self.specHeisOutputMetadaToolPath = QtGui.QToolButton(self.taboutputSpectraHeis) + self.specHeisOutputMetadaToolPath.setObjectName(_fromUtf8("specHeisOutputMetadaToolPath")) + self.gridLayout_19.addWidget(self.specHeisOutputMetadaToolPath, 3, 4, 1, 1) + self.tabWidgetSpectraHeis.addTab(self.taboutputSpectraHeis, _fromUtf8("")) + self.gridLayout_23.addWidget(self.tabWidgetSpectraHeis, 0, 0, 1, 1) + + self.tabWidgetProject.addTab(self.tabSpectraHeis, _fromUtf8("")) + + self.tabWidgetSpectraHeis.setCurrentIndex(0) + + def retranslateUi(self): + + self.specHeisGraphClear.setText(_translate("MainWindow", "Clear", None)) + self.specHeisOpOk.setText(_translate("MainWindow", "Ok", None)) + self.specHeisOpCobIncInt.setItemText(0, _translate("MainWindow", "Time Interval", None)) + self.specHeisOpCebIncoherent.setText(_translate("MainWindow", "Incoherent Intergration", None)) + + self.tabWidgetSpectraHeis.setTabText(self.tabWidgetSpectraHeis.indexOf(self.tabopSpectraHeis), _translate("MainWindow", "Operation", None)) + self.label_54.setText(_translate("MainWindow", "Prefix", None)) + self.specHeisGraphToolPath.setText(_translate("MainWindow", "...", None)) + self.label_62.setText(_translate("MainWindow", "Intensity range (dB)", None)) + self.label_63.setText(_translate("MainWindow", "Time range (hours):", None)) + self.label_64.setText(_translate("MainWindow", "Time interval:", None)) + self.label_65.setText(_translate("MainWindow", "Wr Period", None)) + self.label_60.setText(_translate("MainWindow", "Channel List:", None)) + self.label_61.setText(_translate("MainWindow", "Frequency range", None)) + self.label_56.setText(_translate("MainWindow", "Save", None)) + self.label_57.setText(_translate("MainWindow", "ftp", None)) + self.label_58.setText(_translate("MainWindow", "Spectra Plot", None)) + self.label_53.setText(_translate("MainWindow", "Path", None)) + self.label_55.setText(_translate("MainWindow", "Show", None)) + self.label_59.setText(_translate("MainWindow", "RTI Plot", None)) + + self.tabWidgetSpectraHeis.setTabText(self.tabWidgetSpectraHeis.indexOf(self.tabgraphSpectraHeis), _translate("MainWindow", "Graphics", None)) + self.label_67.setText(_translate("MainWindow", "Path:", None)) + self.label_68.setText(_translate("MainWindow", "Blocks per file:", None)) + self.label_66.setText(_translate("MainWindow", "Type:", None)) + + self.tabWidgetSpectraHeis.setTabText(self.tabWidgetSpectraHeis.indexOf(self.taboutputSpectraHeis), _translate("MainWindow", "Output", None)) + self.specHeisOutputToolPath.setText(_translate("MainWindow", "...", None)) + self.specHeisOutputComdata.setItemText(0, _translate("MainWindow", ".fits", None)) + self.label_69.setText(_translate("MainWindow", "Metadata file:", None)) + self.specHeisOutputMetadaToolPath.setText(_translate("MainWindow", "...", None)) + + self.tabWidgetProject.setTabText(self.tabWidgetProject.indexOf(self.tabSpectraHeis), _translate("MainWindow", "SpectraHeis", None)) + + self.__setToolTip() + + def __setToolTip(self): + + self.specHeisOpIncoherent.setToolTip('Example: 10') + + self.specHeisGgraphChannelList.setToolTip('Example: 0,2,3') + self.specHeisGgraphXminXmax.setToolTip('Example (Hz): -1000, 1000') + self.specHeisGgraphYminYmax.setToolTip('Example (dB): 5, 35') + self.specHeisGgraphTminTmax.setToolTip('Example (hours): 0, 24') + self.specHeisGgraphTimeRange.setToolTip('Example (hours): 8') \ No newline at end of file diff --git a/schainpy/gui/viewer/windows/.svn/text-base/ui_voltage.py.svn-base b/schainpy/gui/viewer/windows/.svn/text-base/ui_voltage.py.svn-base new file mode 100644 index 0000000..4536b0f --- /dev/null +++ b/schainpy/gui/viewer/windows/.svn/text-base/ui_voltage.py.svn-base @@ -0,0 +1,414 @@ + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + def _fromUtf8(s): + return s + +try: + _encoding = QtGui.QApplication.UnicodeUTF8 + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig, _encoding) +except AttributeError: + def _translate(context, text, disambig): + return QtGui.QApplication.translate(context, text, disambig) + +class Ui_VoltageTab(object): + + def setupUi(self): + + self.tabVoltage = QtGui.QWidget() + self.tabVoltage.setObjectName(_fromUtf8("tabVoltage")) + + self.gridLayout_3 = QtGui.QGridLayout(self.tabVoltage) + self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3")) + + self.frame_4 = QtGui.QFrame(self.tabVoltage) + self.frame_4.setFrameShape(QtGui.QFrame.StyledPanel) + self.frame_4.setFrameShadow(QtGui.QFrame.Raised) + self.frame_4.setObjectName(_fromUtf8("frame_4")) + + self.gridLayout_17 = QtGui.QGridLayout(self.frame_4) + self.gridLayout_17.setObjectName(_fromUtf8("gridLayout_17")) + self.volOpOk = QtGui.QPushButton(self.frame_4) + self.volOpOk.setObjectName(_fromUtf8("volOpOk")) + self.gridLayout_17.addWidget(self.volOpOk, 0, 0, 1, 1) + self.volGraphClear = QtGui.QPushButton(self.frame_4) + self.volGraphClear.setObjectName(_fromUtf8("volGraphClear")) + self.gridLayout_17.addWidget(self.volGraphClear, 0, 1, 1, 1) + self.gridLayout_3.addWidget(self.frame_4, 1, 1, 1, 1) + + + self.tabWidgetVoltage = QtGui.QTabWidget(self.tabVoltage) + self.tabWidgetVoltage.setObjectName(_fromUtf8("tabWidgetVoltage")) + self.tabopVoltage = QtGui.QWidget() + self.tabopVoltage.setObjectName(_fromUtf8("tabopVoltage")) + self.gridLayout = QtGui.QGridLayout(self.tabopVoltage) + self.gridLayout.setObjectName(_fromUtf8("gridLayout")) + + self.volOpCebRadarfrequency = QtGui.QCheckBox(self.tabopVoltage) + self.volOpCebRadarfrequency.setObjectName(_fromUtf8("volOpCebRadarfrequency")) + self.gridLayout.addWidget(self.volOpCebRadarfrequency, 0, 0, 1, 1) + + self.volOpRadarfrequency = QtGui.QLineEdit(self.tabopVoltage) + self.volOpRadarfrequency.setObjectName(_fromUtf8("volOpRadarfrequency")) + self.gridLayout.addWidget(self.volOpRadarfrequency, 0, 1, 1, 4) + + self.volOpCebChannels = QtGui.QCheckBox(self.tabopVoltage) + self.volOpCebChannels.setObjectName(_fromUtf8("volOpCebChannels")) + self.gridLayout.addWidget(self.volOpCebChannels, 1, 0, 1, 1) + + self.volOpComChannels = QtGui.QComboBox(self.tabopVoltage) + self.volOpComChannels.setObjectName(_fromUtf8("volOpComChannels")) + self.volOpComChannels.addItem(_fromUtf8("")) + self.volOpComChannels.addItem(_fromUtf8("")) + self.gridLayout.addWidget(self.volOpComChannels, 1, 1, 1, 2) + + self.volOpChannel = QtGui.QLineEdit(self.tabopVoltage) + self.volOpChannel.setObjectName(_fromUtf8("volOpChannel")) + self.gridLayout.addWidget(self.volOpChannel, 1, 3, 1, 2) + + + self.volOpCebHeights = QtGui.QCheckBox(self.tabopVoltage) + self.volOpCebHeights.setObjectName(_fromUtf8("volOpCebHeights")) + self.gridLayout.addWidget(self.volOpCebHeights, 3, 0, 1, 1) + + self.volOpComHeights = QtGui.QComboBox(self.tabopVoltage) + self.volOpComHeights.setObjectName(_fromUtf8("volOpComHeights")) + self.volOpComHeights.addItem(_fromUtf8("")) + self.volOpComHeights.addItem(_fromUtf8("")) + self.gridLayout.addWidget(self.volOpComHeights, 3, 1, 1, 2) + + self.volOpHeights = QtGui.QLineEdit(self.tabopVoltage) + self.volOpHeights.setObjectName(_fromUtf8("volOpHeights")) + self.gridLayout.addWidget(self.volOpHeights, 3, 3, 1, 2) + + self.volOpCebSplitter = QtGui.QCheckBox(self.tabopVoltage) + self.volOpCebSplitter.setObjectName(_fromUtf8("volOpCebSplitter")) + self.gridLayout.addWidget(self.volOpCebSplitter, 5, 0, 1, 1) + + self.volOpSplitter = QtGui.QLineEdit(self.tabopVoltage) + self.volOpSplitter.setObjectName(_fromUtf8("volOpSplitter")) + self.gridLayout.addWidget(self.volOpSplitter, 5, 1, 1, 4) + + self.volOpCebProfile = QtGui.QCheckBox(self.tabopVoltage) + self.volOpCebProfile.setObjectName(_fromUtf8("volOpCebProfile")) + self.gridLayout.addWidget(self.volOpCebProfile, 6, 0, 1, 1) + + self.volOpComProfile = QtGui.QComboBox(self.tabopVoltage) + self.volOpComProfile.setObjectName(_fromUtf8("volOpComProfile")) + self.volOpComProfile.addItem(_fromUtf8("")) + self.volOpComProfile.addItem(_fromUtf8("")) + self.volOpComProfile.addItem(_fromUtf8("")) + self.gridLayout.addWidget(self.volOpComProfile, 6, 1, 1, 2) + + self.volOpProfile = QtGui.QLineEdit(self.tabopVoltage) + self.volOpProfile.setObjectName(_fromUtf8("volOpProfile")) + self.gridLayout.addWidget(self.volOpProfile, 6, 3, 1, 2) + + self.volOpCebCombiner = QtGui.QCheckBox(self.tabopVoltage) + self.volOpCebCombiner.setObjectName(_fromUtf8("volOpCebCombiner")) + self.gridLayout.addWidget(self.volOpCebCombiner, 7, 0, 1, 1) + + self.volOpCombiner = QtGui.QLineEdit(self.tabopVoltage) + self.volOpCombiner.setObjectName(_fromUtf8("volOpCombiner")) + self.gridLayout.addWidget(self.volOpCombiner, 7, 1, 1, 4) + + self.volOpCebFilter = QtGui.QCheckBox(self.tabopVoltage) + self.volOpCebFilter.setObjectName(_fromUtf8("volOpCebFilter")) + self.gridLayout.addWidget(self.volOpCebFilter, 8, 0, 1, 1) + + self.volOpFilter = QtGui.QLineEdit(self.tabopVoltage) + self.volOpFilter.setObjectName(_fromUtf8("volOpFilter")) + self.gridLayout.addWidget(self.volOpFilter, 8, 1, 1, 4) + +# spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout.addItem(spacerItem, 6, 4, 1, 1) +# spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout.addItem(spacerItem1, 8, 4, 1, 1) +# spacerItem2 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout.addItem(spacerItem2, 3, 4, 1, 1) + + + +# spacerItem3 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.gridLayout.addItem(spacerItem3, 1, 4, 1, 1) + + + self.volOpCebDecodification = QtGui.QCheckBox(self.tabopVoltage) + self.volOpCebDecodification.setObjectName(_fromUtf8("volOpCebDecodification")) + self.gridLayout.addWidget(self.volOpCebDecodification, 9, 0, 1, 1) + + self.volLabCodeMode = QtGui.QLabel(self.tabopVoltage) + self.volLabCodeMode.setObjectName(_fromUtf8("volLabCodeMode")) + self.gridLayout.addWidget(self.volLabCodeMode, 9, 1, 1, 1) + + self.volOpComMode = QtGui.QComboBox(self.tabopVoltage) + self.volOpComMode.setObjectName(_fromUtf8("volOpComMode")) + self.volOpComMode.addItem(_fromUtf8("")) + self.volOpComMode.addItem(_fromUtf8("")) + self.gridLayout.addWidget(self.volOpComMode, 9, 2, 1, 3) + + self.volLabCodeType = QtGui.QLabel(self.tabopVoltage) + self.volLabCodeType.setObjectName(_fromUtf8("volLabCodeType")) + self.gridLayout.addWidget(self.volLabCodeType, 10, 1, 1, 1) + + self.volOpComCode = QtGui.QComboBox(self.tabopVoltage) + self.volOpComCode.setObjectName(_fromUtf8("volOpComCode")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.volOpComCode.addItem(_fromUtf8("")) + self.gridLayout.addWidget(self.volOpComCode, 10, 2, 1, 3) + + self.volLabCode = QtGui.QLabel(self.tabopVoltage) + self.volLabCode.setObjectName(_fromUtf8("volLabCode")) + self.gridLayout.addWidget(self.volLabCode, 11, 1, 1, 1) + + self.volOpCode = QtGui.QLineEdit(self.tabopVoltage) + self.volOpCode.setObjectName(_fromUtf8("volOpCode")) + self.gridLayout.addWidget(self.volOpCode, 11, 2, 1, 3) + + self.volOpCebFlip = QtGui.QCheckBox(self.tabopVoltage) + self.volOpCebFlip.setObjectName(_fromUtf8("volOpCebFlip")) + self.gridLayout.addWidget(self.volOpCebFlip, 12, 0, 1, 1) + + self.volOpFlip = QtGui.QLineEdit(self.tabopVoltage) + self.volOpFlip.setObjectName(_fromUtf8("volOpFlip")) + self.gridLayout.addWidget(self.volOpFlip, 13, 1, 1, 4) + + self.volOpCebCohInt = QtGui.QCheckBox(self.tabopVoltage) + self.volOpCebCohInt.setObjectName(_fromUtf8("volOpCebCohInt")) + self.gridLayout.addWidget(self.volOpCebCohInt, 13, 0, 1, 1) + + self.volOpCohInt = QtGui.QLineEdit(self.tabopVoltage) + self.volOpCohInt.setObjectName(_fromUtf8("volOpCohInt")) + self.gridLayout.addWidget(self.volOpCohInt, 13, 1, 1, 4) + + self.volOpCebAdjustHei = QtGui.QCheckBox(self.tabopVoltage) + self.volOpCebAdjustHei.setObjectName(_fromUtf8("volOpCebAdjustHei")) + self.gridLayout.addWidget(self.volOpCebAdjustHei, 14, 0, 1, 1) + + self.volOpAdjustHei = QtGui.QLineEdit(self.tabopVoltage) + self.volOpAdjustHei.setObjectName(_fromUtf8("volOpAdjustHei")) + self.gridLayout.addWidget(self.volOpAdjustHei, 14, 1, 1, 4) + + self.tabWidgetVoltage.addTab(self.tabopVoltage, _fromUtf8("")) + + self.tabgraphVoltage = QtGui.QWidget() + self.tabgraphVoltage.setObjectName(_fromUtf8("tabgraphVoltage")) + self.gridLayout_6 = QtGui.QGridLayout(self.tabgraphVoltage) + self.gridLayout_6.setObjectName(_fromUtf8("gridLayout_6")) + spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.gridLayout_6.addItem(spacerItem4, 12, 3, 1, 1) + self.volGraphIntensityRange = QtGui.QLineEdit(self.tabgraphVoltage) + self.volGraphIntensityRange.setObjectName(_fromUtf8("volGraphIntensityRange")) + self.gridLayout_6.addWidget(self.volGraphIntensityRange, 9, 1, 1, 6) + self.volGraphPrefix = QtGui.QLineEdit(self.tabgraphVoltage) + self.volGraphPrefix.setObjectName(_fromUtf8("volGraphPrefix")) + self.gridLayout_6.addWidget(self.volGraphPrefix, 2, 1, 1, 6) + self.volGraphToolPath = QtGui.QToolButton(self.tabgraphVoltage) + self.volGraphToolPath.setObjectName(_fromUtf8("volGraphToolPath")) + self.gridLayout_6.addWidget(self.volGraphToolPath, 1, 5, 1, 2) + self.volGraphPath = QtGui.QLineEdit(self.tabgraphVoltage) + self.volGraphPath.setObjectName(_fromUtf8("volGraphPath")) + self.gridLayout_6.addWidget(self.volGraphPath, 1, 1, 1, 4) + self.label_14 = QtGui.QLabel(self.tabgraphVoltage) + self.label_14.setObjectName(_fromUtf8("label_14")) + self.gridLayout_6.addWidget(self.label_14, 6, 0, 1, 1) + spacerItem5 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.gridLayout_6.addItem(spacerItem5, 3, 3, 1, 1) + self.label_8 = QtGui.QLabel(self.tabgraphVoltage) + self.label_8.setObjectName(_fromUtf8("label_8")) + self.gridLayout_6.addWidget(self.label_8, 8, 0, 1, 1) + self.label_49 = QtGui.QLabel(self.tabgraphVoltage) + self.label_49.setObjectName(_fromUtf8("label_49")) + self.gridLayout_6.addWidget(self.label_49, 4, 3, 1, 1) + self.label_51 = QtGui.QLabel(self.tabgraphVoltage) + self.label_51.setObjectName(_fromUtf8("label_51")) + self.gridLayout_6.addWidget(self.label_51, 9, 0, 1, 1) + self.volGraphCebshow = QtGui.QCheckBox(self.tabgraphVoltage) + self.volGraphCebshow.setText(_fromUtf8("")) + self.volGraphCebshow.setObjectName(_fromUtf8("volGraphCebshow")) + self.gridLayout_6.addWidget(self.volGraphCebshow, 6, 3, 1, 1) + self.label_12 = QtGui.QLabel(self.tabgraphVoltage) + self.label_12.setObjectName(_fromUtf8("label_12")) + self.gridLayout_6.addWidget(self.label_12, 1, 0, 1, 1) + self.label_13 = QtGui.QLabel(self.tabgraphVoltage) + self.label_13.setObjectName(_fromUtf8("label_13")) + self.gridLayout_6.addWidget(self.label_13, 2, 0, 1, 1) + self.label_52 = QtGui.QLabel(self.tabgraphVoltage) + self.label_52.setObjectName(_fromUtf8("label_52")) + + self.gridLayout_6.addWidget(self.label_52, 11, 0, 1, 1) + spacerItem6 = QtGui.QSpacerItem(40, 12, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.gridLayout_6.addItem(spacerItem6, 14, 5, 1, 2) + spacerItem7 = QtGui.QSpacerItem(18, 12, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.gridLayout_6.addItem(spacerItem7, 14, 3, 1, 1) + + self.volLabScopeType = QtGui.QLabel(self.tabgraphVoltage) + self.volLabScopeType.setObjectName(_fromUtf8("volLabScopeType")) + self.gridLayout_6.addWidget(self.volLabScopeType, 7, 0, 1, 1) + + self.volComScopeType = QtGui.QComboBox(self.tabgraphVoltage) + self.volComScopeType.setObjectName(_fromUtf8("volComScopeType")) + self.volComScopeType.addItem(_fromUtf8("")) + self.volComScopeType.addItem(_fromUtf8("")) + self.gridLayout_6.addWidget(self.volComScopeType, 7, 1, 1, 6) + + self.volGraphChannelList = QtGui.QLineEdit(self.tabgraphVoltage) + self.volGraphChannelList.setObjectName(_fromUtf8("volGraphChannelList")) + self.gridLayout_6.addWidget(self.volGraphChannelList, 8, 1, 1, 6) + + + self.volGraphHeightrange = QtGui.QLineEdit(self.tabgraphVoltage) + self.volGraphHeightrange.setObjectName(_fromUtf8("volGraphHeightrange")) + self.gridLayout_6.addWidget(self.volGraphHeightrange, 11, 1, 1, 6) + self.label_50 = QtGui.QLabel(self.tabgraphVoltage) + self.label_50.setObjectName(_fromUtf8("label_50")) + self.gridLayout_6.addWidget(self.label_50, 4, 4, 1, 1) + self.volGraphCebSave = QtGui.QCheckBox(self.tabgraphVoltage) + self.volGraphCebSave.setText(_fromUtf8("")) + self.volGraphCebSave.setObjectName(_fromUtf8("volGraphCebSave")) + self.gridLayout_6.addWidget(self.volGraphCebSave, 6, 4, 1, 1) + self.tabWidgetVoltage.addTab(self.tabgraphVoltage, _fromUtf8("")) + + self.taboutputVoltage = QtGui.QWidget() + self.taboutputVoltage.setObjectName(_fromUtf8("taboutputVoltage")) + self.gridLayout_12 = QtGui.QGridLayout(self.taboutputVoltage) + self.gridLayout_12.setObjectName(_fromUtf8("gridLayout_12")) + self.label_36 = QtGui.QLabel(self.taboutputVoltage) + self.label_36.setObjectName(_fromUtf8("label_36")) + self.gridLayout_12.addWidget(self.label_36, 0, 0, 1, 1) + self.label_37 = QtGui.QLabel(self.taboutputVoltage) + self.label_37.setObjectName(_fromUtf8("label_37")) + self.gridLayout_12.addWidget(self.label_37, 1, 0, 1, 1) + self.volOutputPath = QtGui.QLineEdit(self.taboutputVoltage) + self.volOutputPath.setObjectName(_fromUtf8("volOutputPath")) + self.gridLayout_12.addWidget(self.volOutputPath, 1, 2, 1, 1) + self.volOutputToolPath = QtGui.QToolButton(self.taboutputVoltage) + self.volOutputToolPath.setObjectName(_fromUtf8("volOutputToolPath")) + self.gridLayout_12.addWidget(self.volOutputToolPath, 1, 3, 1, 1) + self.volOutputComData = QtGui.QComboBox(self.taboutputVoltage) + self.volOutputComData.setObjectName(_fromUtf8("volOutputComData")) + self.volOutputComData.addItem(_fromUtf8("")) + self.gridLayout_12.addWidget(self.volOutputComData, 0, 2, 1, 2) + spacerItem8 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.gridLayout_12.addItem(spacerItem8, 5, 2, 1, 1) + self.volOutputblocksperfile = QtGui.QLineEdit(self.taboutputVoltage) + self.volOutputblocksperfile.setObjectName(_fromUtf8("volOutputblocksperfile")) + self.gridLayout_12.addWidget(self.volOutputblocksperfile, 3, 2, 1, 1) + self.label_7 = QtGui.QLabel(self.taboutputVoltage) + self.label_7.setObjectName(_fromUtf8("label_7")) + self.gridLayout_12.addWidget(self.label_7, 3, 0, 1, 1) + self.label_35 = QtGui.QLabel(self.taboutputVoltage) + self.label_35.setObjectName(_fromUtf8("label_35")) + self.gridLayout_12.addWidget(self.label_35, 4, 0, 1, 1) + self.volOutputprofilesperblock = QtGui.QLineEdit(self.taboutputVoltage) + self.volOutputprofilesperblock.setObjectName(_fromUtf8("volOutputprofilesperblock")) + self.gridLayout_12.addWidget(self.volOutputprofilesperblock, 4, 2, 1, 1) + self.tabWidgetVoltage.addTab(self.taboutputVoltage, _fromUtf8("")) + self.gridLayout_3.addWidget(self.tabWidgetVoltage, 0, 1, 1, 1) + + self.tabWidgetProject.addTab(self.tabVoltage, _fromUtf8("")) + + self.tabWidgetVoltage.setCurrentIndex(0) + + def retranslateUi(self): + + self.volOpOk.setText(_translate("MainWindow", "Ok", None)) + self.volGraphClear.setText(_translate("MainWindow", "Clear", None)) + self.volOpComHeights.setItemText(0, _translate("MainWindow", "Value", None)) + self.volOpComHeights.setItemText(1, _translate("MainWindow", "Index", None)) + self.volOpComChannels.setItemText(0, _translate("MainWindow", "Value", None)) + self.volOpComChannels.setItemText(1, _translate("MainWindow", "Index", None)) + self.volOpCebProfile.setText(_translate("MainWindow", "Select Profiles", None)) + self.volOpComProfile.setItemText(0, _translate("MainWindow", "Profile List", None)) + self.volOpComProfile.setItemText(1, _translate("MainWindow", "Profile Range", None)) + self.volOpComProfile.setItemText(2, _translate("MainWindow", "List of Profile Ranges", None)) + self.volOpCebDecodification.setText(_translate("MainWindow", "Decoder:", None)) + self.volOpCebCohInt.setText(_translate("MainWindow", "Coherent Integration:", None)) + self.volOpCebFlip.setText(_translate("MainWindow", "Flip:", None)) + self.volLabCodeType.setText(_translate("MainWindow", "Code type:", None)) + self.volOpCebChannels.setText(_translate("MainWindow", "Select Channels:", None)) + self.volOpCebHeights.setText(_translate("MainWindow", "Select Heights:", None)) + self.volOpCebFilter.setText(_translate("MainWindow", "Range Window Filter:", None)) + self.volOpCebSplitter.setText(_translate("MainWindow", "Split Profiles: ", None)) + self.volOpCebCombiner.setText(_translate("MainWindow", "Combine Profiles: ", None)) + self.volOpCebRadarfrequency.setText(_translate("MainWindow", "Radar frequency (MHz):", None)) + self.volLabCodeMode.setText(_translate("MainWindow", "Mode:", None)) + self.volLabCode.setText(_translate("MainWindow", "Code:", None)) + self.volOpComCode.setItemText(0, _translate("MainWindow", "Read from header", None)) + self.volOpComCode.setItemText(1, _translate("MainWindow", "Barker 3", None)) + self.volOpComCode.setItemText(2, _translate("MainWindow", "Barker 4", None)) + self.volOpComCode.setItemText(3, _translate("MainWindow", "Barker 5", None)) + self.volOpComCode.setItemText(4, _translate("MainWindow", "Barker 7", None)) + self.volOpComCode.setItemText(5, _translate("MainWindow", "Barker 11", None)) + self.volOpComCode.setItemText(6, _translate("MainWindow", "Barker 13", None)) + self.volOpComCode.setItemText(7, _translate("MainWindow", "Barker 3 + Comp.", None)) + self.volOpComCode.setItemText(8, _translate("MainWindow", "Barker 4 + Comp.", None)) + self.volOpComCode.setItemText(9, _translate("MainWindow", "Barker 5 + Comp.", None)) + self.volOpComCode.setItemText(10, _translate("MainWindow", "Barker 7 + Comp.", None)) + self.volOpComCode.setItemText(11, _translate("MainWindow", "Barker 11+ Comp.", None)) + self.volOpComCode.setItemText(12, _translate("MainWindow", "Barker 13+ Comp.", None)) + self.volOpComCode.setItemText(13, _translate("MainWindow", "User defined", None)) + self.volOpComMode.setItemText(0, _translate("MainWindow", "Time", None)) + self.volOpComMode.setItemText(1, _translate("MainWindow", "Frequency", None)) + self.volOpCebAdjustHei.setText(_translate("MainWindow", "Calibrate H0:", None)) + + self.tabWidgetVoltage.setTabText(self.tabWidgetVoltage.indexOf(self.tabopVoltage), _translate("MainWindow", "Operation", None)) + + self.volGraphToolPath.setText(_translate("MainWindow", "...", None)) + self.label_14.setText(_translate("MainWindow", "Scope:", None)) + self.label_8.setText(_translate("MainWindow", "Channel List:", None)) + self.label_49.setText(_translate("MainWindow", "Show:", None)) + self.label_51.setText(_translate("MainWindow", "Amplitude/Intensity:", None)) + self.label_12.setText(_translate("MainWindow", "Path :", None)) + self.label_13.setText(_translate("MainWindow", "Figure name:", None)) + self.label_52.setText(_translate("MainWindow", "Height range:", None)) + self.label_50.setText(_translate("MainWindow", "Save:", None)) + + self.volLabScopeType.setText(_translate("MainWindow", "Scope type:", None)) + self.volComScopeType.setItemText(0, _translate("MainWindow", "I&Q", None)) + self.volComScopeType.setItemText(1, _translate("MainWindow", "Power", None)) + + self.tabWidgetVoltage.setTabText(self.tabWidgetVoltage.indexOf(self.tabgraphVoltage), _translate("MainWindow", "Graphics", None)) + + self.label_36.setText(_translate("MainWindow", "Type:", None)) + self.label_37.setText(_translate("MainWindow", "Path:", None)) + self.volOutputToolPath.setText(_translate("MainWindow", "...", None)) + self.volOutputComData.setItemText(0, _translate("MainWindow", ".rawdata", None)) + self.label_7.setText(_translate("MainWindow", "Blocks per File: ", None)) + self.label_35.setText(_translate("MainWindow", "Profiles per Block: ", None)) + self.tabWidgetVoltage.setTabText(self.tabWidgetVoltage.indexOf(self.taboutputVoltage), _translate("MainWindow", "Output", None)) + + self.tabWidgetProject.setTabText(self.tabWidgetProject.indexOf(self.tabVoltage), _translate("MainWindow", "Voltage", None)) + + self.__setToolTip() + + def __setToolTip(self): + + self.volOpChannel.setToolTip('Example: 1,2,3,4,5') + self.volOpHeights.setToolTip('Example: 90,180') + self.volOpFilter.setToolTip('Example: 2') + self.volOpProfile.setToolTip('Example:0,127') + self.volOpCohInt.setToolTip('Example: 128') + self.volOpFlip.setToolTip('ChannelList where flip will be applied. Example: 0,2,3') + self.volOpOk.setToolTip('If you have finished, please Ok ') + # tool tip gui volGraph + self.volGraphIntensityRange.setToolTip('Height range. Example: 50,100') + self.volGraphHeightrange.setToolTip('Amplitude. Example: 0,10000') + + \ No newline at end of file diff --git a/schainpy/meteor20130812.xml b/schainpy/meteor20130812.xml new file mode 100644 index 0000000..a1466f1 --- /dev/null +++ b/schainpy/meteor20130812.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/schainpy/model/.svn/all-wcprops b/schainpy/model/.svn/all-wcprops new file mode 100644 index 0000000..d6c612f --- /dev/null +++ b/schainpy/model/.svn/all-wcprops @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 76 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/model +END +__init__.py +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/model/__init__.py +END +__init__.pyc +K 25 +svn:wc:ra_dav:version-url +V 89 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/model/__init__.pyc +END diff --git a/schainpy/model/.svn/entries b/schainpy/model/.svn/entries new file mode 100644 index 0000000..1e42251 --- /dev/null +++ b/schainpy/model/.svn/entries @@ -0,0 +1,114 @@ +10 + +dir +1608 +http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainpy/model +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 + +__init__.py +file + + + + +2017-04-17T17:05:34.000000Z +7bf009dfba276f9ddaba77d4e12257f0 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +366 + +__init__.pyc +file + + + + +2017-04-17T17:05:34.000000Z +a6cce343bbb5473844e244d8b52b7651 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +275 + +data +dir + +graphics +dir + +io +dir + +proc +dir + +serializer +dir + +utils +dir + diff --git a/schainpy/model/.svn/prop-base/__init__.pyc.svn-base b/schainpy/model/.svn/prop-base/__init__.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/model/.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/model/.svn/text-base/__init__.py.svn-base b/schainpy/model/.svn/text-base/__init__.py.svn-base new file mode 100644 index 0000000..6dea354 --- /dev/null +++ b/schainpy/model/.svn/text-base/__init__.py.svn-base @@ -0,0 +1,12 @@ +#from schainpy.model.data.jrodata import * +# from schainpy.model.io.jrodataIO import * +# from schainpy.model.proc.jroprocessing import * +# from schainpy.model.graphics.jroplot import * +# from schainpy.model.utils.jroutils import * +# from schainpy.serializer import * + +from data import * +from io import * +from proc import * +from graphics import * +from utils import * diff --git a/schainpy/model/.svn/text-base/__init__.pyc.svn-base b/schainpy/model/.svn/text-base/__init__.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..f2217fc19215de86309304d868b6d3a8f5b7362b GIT binary patch literal 275 zc$`I!Q47K#5P)@C5QF~52+Eh}DI)p-y%h8);-tyk6ulAq-91O0YuM?1d>*G~{#uor z-TN-d92w>bGwcyHZb}Rxx7ld2ELoncK+DLr%JHiHU{n+hBG#8`5xt173J?(IXgi&q zw-S~p4=-G!Wq{Z^fHt9uU-~1Q5v;MDV#;gTvZwWJa6&2;WFvI%tpyhB;8Vqoth2Q; ZjC0*<;C$=GY1jeFgHgxmA)=(e^#v<_Jud(N literal 0 Hc$@UQ2D>6ogxx)-=#1%IshLF=}bh2!+e6j*9BS)6wQ}|#oiWU==2R2Jyq^>f`nC5^T z&dysE=O{NXT?Hz{bhV3M0!v@|BkU2pvW@22gR1%6`Z_qNG!Lqh& vertical) + ('AntennaCoord',' endFp: + sys.stderr.write("Warning %s: Size value read from System Header is lower than it has to be\n" %fp.name) + return 0 + + if fp.tell() < endFp: + sys.stderr.write("Warning %s: Size value read from System Header size is greater than it has to be\n" %fp.name) + return 0 + + return 1 + + def write(self, fp): + + headerTuple = (self.RecMgcNumber, + self.RecCounter, + self.Off2StartNxtRec, + self.EpTimeStamp, + self.msCompTimeStamp, + self.ExpTagName, + self.ExpComment, + self.SiteLatDegrees, + self.SiteLongDegrees, + self.RTCgpsStatus, + self.TransmitFrec, + self.ReceiveFrec, + self.FirstOsciFrec, + self.Polarisation, + self.ReceiverFiltSett, + self.nModesInUse, + self.DualModeIndex, + self.DualModeRange, + self.nDigChannels, + self.SampResolution, + self.nRangeGatesSamp, + self.StartRangeSamp, + self.PRFhz, + self.Integrations, + self.nDataPointsTrsf, + self.nReceiveBeams, + self.nSpectAverages, + self.FFTwindowingInd, + self.BeamAngleAzim, + self.BeamAngleZen, + self.AntennaCoord, + self.RecPhaseCalibr, + self.RecAmpCalibr, + self.ReceiverGaindB) + +# self.size,self.nSamples, +# self.nProfiles, +# self.nChannels, +# self.adcResolution, +# self.pciDioBusWidth + + header = numpy.array(headerTuple,RECORD_STRUCTURE) + header.tofile(fp) + + return 1 + + +def get_dtype_index(numpy_dtype): + + index = None + + for i in range(len(NUMPY_DTYPE_LIST)): + if numpy_dtype == NUMPY_DTYPE_LIST[i]: + index = i + break + + return index + +def get_numpy_dtype(index): + + #dtype4 = numpy.dtype([('real','?zvwMo+&Ps zz1;j_xbsRon}*y!+!+CxsT3%yMFB5k3)gU=z=@3O+8X1*nbuB|ri02zRYJ%D#&oSc WW4os7a}Ky`OLYu?b2CIj6Z!+gb33>I literal 0 Hc$@X!^J1O}228VC*}XXxM=Mx#n+TaJ8Ebth7H z(x>!4=9z)rl~y**v$5mL@AmfgdsnLbwYu`<-rvuCQG6=!`wo8k0G0s$ED;GYD6u65 zmI!PS)J0GcZ-uxP;`agUt0HKKpjMJ9$lmWXK}`4$e0rt|@IZRgQkR7U)O80IDM+$F z0U*!mcktM^3O*ZthsgU7mXQ!wLbxTc7}zKvzuD`cD+cxZaUf4aZOkp$c(220X2!H% zf&FW#!hB2D$Vx4vVFxXwMgIs(cN|Y;SEiwV(Y=h*3!Qkr>}r4Pg({6>)75d7mXu`H zor2P+8+gX+PSV($hB|$k%*YK%yWte|UyoCy>Vuc{FRusvgjs=3CA!JiXs+4P6 z3|h3UVL9P;1@qoq%zKsd9>dOXx`P~47*tU+f*NW@P-oC!(B$hazO};O7V?a832k9k z#bk}VX^N38u5kxDPpSO)vUJtBltZxmvx zI#@OOU7k4=8B6NtEblzcB-Qya@O}eZ4*dy}qz~5>_=tBeLlwlAXT#$#GBPC>F%-Zp(?7k41PoL8GLy>B zrw%5C;)l}4G8~N!`9i9GP2*u0Nll!}0Yxb&!r7#7Wb54H11}45bO?S>BG4hy{sP#L zdKCHwIw&VNo*LzpWsX5 zN|W2EE^jcR&uD@^EvGenE5&~s*S57~6S5bnC69GuhupSr7elq2b3em!MHB9#Dbj6W zEHR-u0duJT>I*!ZRK%o;t$OswJ@LjaNLRMl2DTjSzkDK|FFXs;0cVwC=Eud8D3CHK zH?A8%rr@cAEEjU7>48LHrE>^SX0RJ7`T3G!y~mFj)G6$?wQ6r#H{S!u8JboTi(*rF ziVS37B$e|REnISO&~O+@(|blerGMfFsIW_`Ew&mfA5ETThOBGj}>9xw&|_#WOuq_ z#&TzOaS-nAz}QG&LeBL4MIKdTYkvN;*TGCWIFKBSl~Xni)ui(^F8jEA!!5yg$@hGA z7IK&QnudDNRE-aUy4Cus-E7rb)mDAoT2Mo GZsT9O3$phB literal 0 Hc$@ nums_min: + rtest = float(j)/(j-1) + 1.0/navg + if ((sumq*j) > (rtest*sump**2)): + j = j - 1 + sump = sump - sortdata[j] + sumq = sumq - sortdata[j]**2 + cont = 0 + + j += 1 + + lnoise = sump /j +# stdv = numpy.sqrt((sumq - lnoise**2)/(j - 1)) + return lnoise + +class Beam: + def __init__(self): + self.codeList = [] + self.azimuthList = [] + self.zenithList = [] + +class GenericData(object): + + flagNoData = True + + def __init__(self): + + raise NotImplementedError + + def copy(self, inputObj=None): + + if inputObj == None: + return copy.deepcopy(self) + + for key in inputObj.__dict__.keys(): + + attribute = inputObj.__dict__[key] + + #If this attribute is a tuple or list + if type(inputObj.__dict__[key]) in (tuple, list): + self.__dict__[key] = attribute[:] + continue + + #If this attribute is another object or instance + if hasattr(attribute, '__dict__'): + self.__dict__[key] = attribute.copy() + continue + + self.__dict__[key] = inputObj.__dict__[key] + + def deepcopy(self): + + return copy.deepcopy(self) + + def isEmpty(self): + + return self.flagNoData + +class JROData(GenericData): + +# m_BasicHeader = BasicHeader() +# m_ProcessingHeader = ProcessingHeader() + + systemHeaderObj = SystemHeader() + + radarControllerHeaderObj = RadarControllerHeader() + +# data = None + + type = None + + datatype = None #dtype but in string + +# dtype = None + +# nChannels = None + +# nHeights = None + + nProfiles = None + + heightList = None + + channelList = None + + flagDiscontinuousBlock = False + + useLocalTime = False + + utctime = None + + timeZone = None + + dstFlag = None + + errorCount = None + + blocksize = None + +# nCode = None +# +# nBaud = None +# +# code = None + + flagDecodeData = False #asumo q la data no esta decodificada + + flagDeflipData = False #asumo q la data no esta sin flip + + flagShiftFFT = False + +# ippSeconds = None + +# timeInterval = None + + nCohInt = None + +# noise = None + + windowOfFilter = 1 + + #Speed of ligth + C = 3e8 + + frequency = 49.92e6 + + realtime = False + + beacon_heiIndexList = None + + last_block = None + + blocknow = None + + azimuth = None + + zenith = None + + beam = Beam() + + profileIndex = None + + def __init__(self): + + raise NotImplementedError + + def getNoise(self): + + raise NotImplementedError + + def getNChannels(self): + + return len(self.channelList) + + def getChannelIndexList(self): + + return range(self.nChannels) + + def getNHeights(self): + + return len(self.heightList) + + def getHeiRange(self, extrapoints=0): + + heis = self.heightList +# deltah = self.heightList[1] - self.heightList[0] +# +# heis.append(self.heightList[-1]) + + return heis + + def getDeltaH(self): + + delta = self.heightList[1] - self.heightList[0] + + return delta + + def getltctime(self): + + if self.useLocalTime: + return self.utctime - self.timeZone*60 + + return self.utctime + + def getDatatime(self): + + datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime) + return datatimeValue + + def getTimeRange(self): + + datatime = [] + + datatime.append(self.ltctime) + datatime.append(self.ltctime + self.timeInterval+1) + + datatime = numpy.array(datatime) + + return datatime + + def getFmaxTimeResponse(self): + + period = (10**-6)*self.getDeltaH()/(0.15) + + PRF = 1./(period * self.nCohInt) + + fmax = PRF + + return fmax + + def getFmax(self): + + PRF = 1./(self.ippSeconds * self.nCohInt) + + fmax = PRF + + return fmax + + def getVmax(self): + + _lambda = self.C/self.frequency + + vmax = self.getFmax() * _lambda/2 + + return vmax + + def get_ippSeconds(self): + ''' + ''' + return self.radarControllerHeaderObj.ippSeconds + + def set_ippSeconds(self, ippSeconds): + ''' + ''' + + self.radarControllerHeaderObj.ippSeconds = ippSeconds + + return + + def get_dtype(self): + ''' + ''' + return getNumpyDtype(self.datatype) + + def set_dtype(self, numpyDtype): + ''' + ''' + + self.datatype = getDataTypeCode(numpyDtype) + + def get_code(self): + ''' + ''' + return self.radarControllerHeaderObj.code + + def set_code(self, code): + ''' + ''' + self.radarControllerHeaderObj.code = code + + return + + def get_ncode(self): + ''' + ''' + return self.radarControllerHeaderObj.nCode + + def set_ncode(self, nCode): + ''' + ''' + self.radarControllerHeaderObj.nCode = nCode + + return + + def get_nbaud(self): + ''' + ''' + return self.radarControllerHeaderObj.nBaud + + def set_nbaud(self, nBaud): + ''' + ''' + self.radarControllerHeaderObj.nBaud = nBaud + + return + + nChannels = property(getNChannels, "I'm the 'nChannel' property.") + channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.") + nHeights = property(getNHeights, "I'm the 'nHeights' property.") + #noise = property(getNoise, "I'm the 'nHeights' property.") + datatime = property(getDatatime, "I'm the 'datatime' property") + ltctime = property(getltctime, "I'm the 'ltctime' property") + ippSeconds = property(get_ippSeconds, set_ippSeconds) + dtype = property(get_dtype, set_dtype) +# timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property") + code = property(get_code, set_code) + nCode = property(get_ncode, set_ncode) + nBaud = property(get_nbaud, set_nbaud) + +class Voltage(JROData): + + #data es un numpy array de 2 dmensiones (canales, alturas) + data = None + + def __init__(self): + ''' + Constructor + ''' + + self.useLocalTime = True + + self.radarControllerHeaderObj = RadarControllerHeader() + + self.systemHeaderObj = SystemHeader() + + self.type = "Voltage" + + self.data = None + +# self.dtype = None + +# self.nChannels = 0 + +# self.nHeights = 0 + + self.nProfiles = None + + self.heightList = None + + self.channelList = None + +# self.channelIndexList = None + + self.flagNoData = True + + self.flagDiscontinuousBlock = False + + self.utctime = None + + self.timeZone = None + + self.dstFlag = None + + self.errorCount = None + + self.nCohInt = None + + self.blocksize = None + + self.flagDecodeData = False #asumo q la data no esta decodificada + + self.flagDeflipData = False #asumo q la data no esta sin flip + + self.flagShiftFFT = False + + self.flagDataAsBlock = False #Asumo que la data es leida perfil a perfil + + self.profileIndex = 0 + + def getNoisebyHildebrand(self, channel = None): + """ + Determino el nivel de ruido usando el metodo Hildebrand-Sekhon + + Return: + noiselevel + """ + + if channel != None: + data = self.data[channel] + nChannels = 1 + else: + data = self.data + nChannels = self.nChannels + + noise = numpy.zeros(nChannels) + power = data * numpy.conjugate(data) + + for thisChannel in range(nChannels): + if nChannels == 1: + daux = power[:].real + else: + daux = power[thisChannel,:].real + noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt) + + return noise + + def getNoise(self, type = 1, channel = None): + + if type == 1: + noise = self.getNoisebyHildebrand(channel) + + return noise + + def getPower(self, channel = None): + + if channel != None: + data = self.data[channel] + else: + data = self.data + + power = data * numpy.conjugate(data) + powerdB = 10*numpy.log10(power.real) + powerdB = numpy.squeeze(powerdB) + + return powerdB + + def getTimeInterval(self): + + timeInterval = self.ippSeconds * self.nCohInt + + return timeInterval + + noise = property(getNoise, "I'm the 'nHeights' property.") + timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property") + +class Spectra(JROData): + + #data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas) + data_spc = None + + #data cspc es un numpy array de 2 dmensiones (canales, pares, alturas) + data_cspc = None + + #data dc es un numpy array de 2 dmensiones (canales, alturas) + data_dc = None + + #data power + data_pwr = None + + nFFTPoints = None + +# nPairs = None + + pairsList = None + + nIncohInt = None + + wavelength = None #Necesario para cacular el rango de velocidad desde la frecuencia + + nCohInt = None #se requiere para determinar el valor de timeInterval + + data_SNR = None #Signal to Noise Ratio + + ippFactor = None + + profileIndex = 0 + + plotting = "spectra" + + def __init__(self): + ''' + Constructor + ''' + + self.useLocalTime = True + + self.radarControllerHeaderObj = RadarControllerHeader() + + self.systemHeaderObj = SystemHeader() + + self.type = "Spectra" + +# self.data = None + +# self.dtype = None + +# self.nChannels = 0 + +# self.nHeights = 0 + + self.nProfiles = None + + self.heightList = None + + self.channelList = None + +# self.channelIndexList = None + + self.pairsList = None + + self.flagNoData = True + + self.flagDiscontinuousBlock = False + + self.utctime = None + + self.nCohInt = None + + self.nIncohInt = None + + self.blocksize = None + + self.nFFTPoints = None + + self.wavelength = None + + self.flagDecodeData = False #asumo q la data no esta decodificada + + self.flagDeflipData = False #asumo q la data no esta sin flip + + self.flagShiftFFT = False + + self.ippFactor = 1 + + #self.noise = None + + self.beacon_heiIndexList = [] + + self.noise_estimation = None + + + def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None): + """ + Determino el nivel de ruido usando el metodo Hildebrand-Sekhon + + Return: + noiselevel + """ + + noise = numpy.zeros(self.nChannels) + + for channel in range(self.nChannels): + daux = self.data_spc[channel,xmin_index:xmax_index,ymin_index:ymax_index] + noise[channel] = hildebrand_sekhon(daux, self.nIncohInt) + + return noise + + def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None): + + if self.noise_estimation is not None: + return self.noise_estimation #this was estimated by getNoise Operation defined in jroproc_spectra.py + else: + noise = self.getNoisebyHildebrand(xmin_index, xmax_index, ymin_index, ymax_index) + return noise + + def getFreqRangeTimeResponse(self, extrapoints=0): + + deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints*self.ippFactor) + freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2 + + return freqrange + + def getAcfRange(self, extrapoints=0): + + deltafreq = 10./(self.getFmax() / (self.nFFTPoints*self.ippFactor)) + freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2 + + return freqrange + + def getFreqRange(self, extrapoints=0): + + deltafreq = self.getFmax() / (self.nFFTPoints*self.ippFactor) + freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2 + + return freqrange + + def getVelRange(self, extrapoints=0): + + deltav = self.getVmax() / (self.nFFTPoints*self.ippFactor) + velrange = deltav*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) #- deltav/2 + + return velrange + + def getNPairs(self): + + return len(self.pairsList) + + def getPairsIndexList(self): + + return range(self.nPairs) + + def getNormFactor(self): + + pwcode = 1 + + if self.flagDecodeData: + pwcode = numpy.sum(self.code[0]**2) + + #print self.nProfiles, self.nIncohInt , self.nCohInt, pwcode, self.windowOfFilter + #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter + normFactor = self.nProfiles*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter + + return normFactor + + def getFlagCspc(self): + + if self.data_cspc is None: + return True + + return False + + def getFlagDc(self): + + if self.data_dc is None: + return True + + return False + + def getTimeInterval(self): + + timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles + + return timeInterval + + def getPower(self): + + factor = self.normFactor + z = self.data_spc/factor + z = numpy.where(numpy.isfinite(z), z, numpy.NAN) + avg = numpy.average(z, axis=1) + + return 10*numpy.log10(avg) + + def setValue(self, value): + + print "This property should not be initialized" + + return + + nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.") + pairsIndexList = property(getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.") + normFactor = property(getNormFactor, setValue, "I'm the 'getNormFactor' property.") + flag_cspc = property(getFlagCspc, setValue) + flag_dc = property(getFlagDc, setValue) + noise = property(getNoise, setValue, "I'm the 'nHeights' property.") + timeInterval = property(getTimeInterval, setValue, "I'm the 'timeInterval' property") + +class SpectraHeis(Spectra): + + data_spc = None + + data_cspc = None + + data_dc = None + + nFFTPoints = None + +# nPairs = None + + pairsList = None + + nCohInt = None + + nIncohInt = None + + def __init__(self): + + self.radarControllerHeaderObj = RadarControllerHeader() + + self.systemHeaderObj = SystemHeader() + + self.type = "SpectraHeis" + +# self.dtype = None + +# self.nChannels = 0 + +# self.nHeights = 0 + + self.nProfiles = None + + self.heightList = None + + self.channelList = None + +# self.channelIndexList = None + + self.flagNoData = True + + self.flagDiscontinuousBlock = False + +# self.nPairs = 0 + + self.utctime = None + + self.blocksize = None + + self.profileIndex = 0 + + self.nCohInt = 1 + + self.nIncohInt = 1 + + def getNormFactor(self): + pwcode = 1 + if self.flagDecodeData: + pwcode = numpy.sum(self.code[0]**2) + + normFactor = self.nIncohInt*self.nCohInt*pwcode + + return normFactor + + def getTimeInterval(self): + + timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt + + return timeInterval + + normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.") + timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property") + +class Fits(JROData): + + heightList = None + + channelList = None + + flagNoData = True + + flagDiscontinuousBlock = False + + useLocalTime = False + + utctime = None + + timeZone = None + +# ippSeconds = None + +# timeInterval = None + + nCohInt = None + + nIncohInt = None + + noise = None + + windowOfFilter = 1 + + #Speed of ligth + C = 3e8 + + frequency = 49.92e6 + + realtime = False + + + def __init__(self): + + self.type = "Fits" + + self.nProfiles = None + + self.heightList = None + + self.channelList = None + +# self.channelIndexList = None + + self.flagNoData = True + + self.utctime = None + + self.nCohInt = 1 + + self.nIncohInt = 1 + + self.useLocalTime = True + + self.profileIndex = 0 + +# self.utctime = None +# self.timeZone = None +# self.ltctime = None +# self.timeInterval = None +# self.header = None +# self.data_header = None +# self.data = None +# self.datatime = None +# self.flagNoData = False +# self.expName = '' +# self.nChannels = None +# self.nSamples = None +# self.dataBlocksPerFile = None +# self.comments = '' +# + + + def getltctime(self): + + if self.useLocalTime: + return self.utctime - self.timeZone*60 + + return self.utctime + + def getDatatime(self): + + datatime = datetime.datetime.utcfromtimestamp(self.ltctime) + return datatime + + def getTimeRange(self): + + datatime = [] + + datatime.append(self.ltctime) + datatime.append(self.ltctime + self.timeInterval) + + datatime = numpy.array(datatime) + + return datatime + + def getHeiRange(self): + + heis = self.heightList + + return heis + + def getNHeights(self): + + return len(self.heightList) + + def getNChannels(self): + + return len(self.channelList) + + def getChannelIndexList(self): + + return range(self.nChannels) + + def getNoise(self, type = 1): + + #noise = numpy.zeros(self.nChannels) + + if type == 1: + noise = self.getNoisebyHildebrand() + + if type == 2: + noise = self.getNoisebySort() + + if type == 3: + noise = self.getNoisebyWindow() + + return noise + + def getTimeInterval(self): + + timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt + + return timeInterval + + datatime = property(getDatatime, "I'm the 'datatime' property") + nHeights = property(getNHeights, "I'm the 'nHeights' property.") + nChannels = property(getNChannels, "I'm the 'nChannel' property.") + channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.") + noise = property(getNoise, "I'm the 'nHeights' property.") + + ltctime = property(getltctime, "I'm the 'ltctime' property") + timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property") + + +class Correlation(JROData): + + noise = None + + SNR = None + + #-------------------------------------------------- + + mode = None + + split = False + + data_cf = None + + lags = None + + lagRange = None + + pairsList = None + + normFactor = None + + #-------------------------------------------------- + +# calculateVelocity = None + + nLags = None + + nPairs = None + + nAvg = None + + + def __init__(self): + ''' + Constructor + ''' + self.radarControllerHeaderObj = RadarControllerHeader() + + self.systemHeaderObj = SystemHeader() + + self.type = "Correlation" + + self.data = None + + self.dtype = None + + self.nProfiles = None + + self.heightList = None + + self.channelList = None + + self.flagNoData = True + + self.flagDiscontinuousBlock = False + + self.utctime = None + + self.timeZone = None + + self.dstFlag = None + + self.errorCount = None + + self.blocksize = None + + self.flagDecodeData = False #asumo q la data no esta decodificada + + self.flagDeflipData = False #asumo q la data no esta sin flip + + self.pairsList = None + + self.nPoints = None + + def getPairsList(self): + + return self.pairsList + + def getNoise(self, mode = 2): + + indR = numpy.where(self.lagR == 0)[0][0] + indT = numpy.where(self.lagT == 0)[0][0] + + jspectra0 = self.data_corr[:,:,indR,:] + jspectra = copy.copy(jspectra0) + + num_chan = jspectra.shape[0] + num_hei = jspectra.shape[2] + + freq_dc = jspectra.shape[1]/2 + ind_vel = numpy.array([-2,-1,1,2]) + freq_dc + + if ind_vel[0]<0: + ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof + + if mode == 1: + jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION + + if mode == 2: + + vel = numpy.array([-2,-1,1,2]) + xx = numpy.zeros([4,4]) + + for fil in range(4): + xx[fil,:] = vel[fil]**numpy.asarray(range(4)) + + xx_inv = numpy.linalg.inv(xx) + xx_aux = xx_inv[0,:] + + for ich in range(num_chan): + yy = jspectra[ich,ind_vel,:] + jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy) + + junkid = jspectra[ich,freq_dc,:]<=0 + cjunkid = sum(junkid) + + if cjunkid.any(): + jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2 + + noise = jspectra0[:,freq_dc,:] - jspectra[:,freq_dc,:] + + return noise + + def getTimeInterval(self): + + timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles + + return timeInterval + + def splitFunctions(self): + + pairsList = self.pairsList + ccf_pairs = [] + acf_pairs = [] + ccf_ind = [] + acf_ind = [] + for l in range(len(pairsList)): + chan0 = pairsList[l][0] + chan1 = pairsList[l][1] + + #Obteniendo pares de Autocorrelacion + if chan0 == chan1: + acf_pairs.append(chan0) + acf_ind.append(l) + else: + ccf_pairs.append(pairsList[l]) + ccf_ind.append(l) + + data_acf = self.data_cf[acf_ind] + data_ccf = self.data_cf[ccf_ind] + + return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf + + def getNormFactor(self): + acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions() + acf_pairs = numpy.array(acf_pairs) + normFactor = numpy.zeros((self.nPairs,self.nHeights)) + + for p in range(self.nPairs): + pair = self.pairsList[p] + + ch0 = pair[0] + ch1 = pair[1] + + ch0_max = numpy.max(data_acf[acf_pairs==ch0,:,:], axis=1) + ch1_max = numpy.max(data_acf[acf_pairs==ch1,:,:], axis=1) + normFactor[p,:] = numpy.sqrt(ch0_max*ch1_max) + + return normFactor + + timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property") + normFactor = property(getNormFactor, "I'm the 'normFactor property'") + +class Parameters(JROData): + + experimentInfo = None #Information about the experiment + + #Information from previous data + + inputUnit = None #Type of data to be processed + + operation = None #Type of operation to parametrize + + normFactor = None #Normalization Factor + + groupList = None #List of Pairs, Groups, etc + + #Parameters + + data_param = None #Parameters obtained + + data_pre = None #Data Pre Parametrization + + data_SNR = None #Signal to Noise Ratio + +# heightRange = None #Heights + + abscissaList = None #Abscissa, can be velocities, lags or time + + noise = None #Noise Potency + + utctimeInit = None #Initial UTC time + + paramInterval = None #Time interval to calculate Parameters in seconds + + useLocalTime = True + + #Fitting + + data_error = None #Error of the estimation + + constants = None + + library = None + + #Output signal + + outputInterval = None #Time interval to calculate output signal in seconds + + data_output = None #Out signal + + nAvg = None + + + def __init__(self): + ''' + Constructor + ''' + self.radarControllerHeaderObj = RadarControllerHeader() + + self.systemHeaderObj = SystemHeader() + + self.type = "Parameters" + + def getTimeRange1(self, interval): + + datatime = [] + + if self.useLocalTime: + time1 = self.utctimeInit - self.timeZone*60 + else: + time1 = self.utctimeInit + +# datatime.append(self.utctimeInit) +# datatime.append(self.utctimeInit + self.outputInterval) + datatime.append(time1) + print "interval", interval + datatime.append(time1 + interval) + + datatime = numpy.array(datatime) + + return datatime diff --git a/schainpy/model/data/.svn/text-base/jrodata.pyc.svn-base b/schainpy/model/data/.svn/text-base/jrodata.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..edc9b77e501ea54c8395f7aedf7aafb42d634f0e GIT binary patch literal 29117 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 bCY_RVvQ#KPRQ}U)T>cN`uPT48{4@U#vN13i literal 0 Hc$@ endFp: + sys.stderr.write("Warning %s: Size value read from System Header is lower than it has to be\n" %fp.name) + return 0 + + if fp.tell() < endFp: + sys.stderr.write("Warning %s: Size value read from System Header size is greater than it has to be\n" %fp.name) + return 0 + + return 1 + + def write(self, fp): + + headerTuple = (self.size,self.nSamples,self.nProfiles,self.nChannels,self.adcResolution,self.pciDioBusWidth) + header = numpy.array(headerTuple,SYSTEM_STRUCTURE) + header.tofile(fp) + + return 1 + +class RadarControllerHeader(Header): + + expType = None + nTx = None + ipp = None + txA = None + txB = None + nWindows = None + numTaus = None + codeType = None + line6Function = None + line5Function = None + fClock = None + prePulseBefore = None + prePulserAfter = None + rangeIpp = None + rangeTxA = None + rangeTxB = None + + __size = None + + def __init__(self, expType=2, nTx=1, + ippKm=None, txA=0, txB=0, + nWindows=None, nHeights=None, firstHeight=None, deltaHeight=None, + numTaus=0, line6Function=0, line5Function=0, fClock=None, + prePulseBefore=0, prePulseAfter=0, + codeType=0, nCode=0, nBaud=0, code=None, + flip1=0, flip2=0): + +# self.size = 116 + self.expType = expType + self.nTx = nTx + self.ipp = ippKm + self.txA = txA + self.txB = txB + + self.nWindows = nWindows + self.numTaus = numTaus + self.codeType = codeType + self.line6Function = line6Function + self.line5Function = line5Function + self.fClock = fClock + self.prePulseBefore = prePulseBefore + self.prePulserAfter = prePulseAfter + + self.rangeIpp = ippKm + self.rangeTxA = txA + self.rangeTxB = txB + + + self.nHeights = nHeights + self.firstHeight = firstHeight + self.deltaHeight = deltaHeight + self.samplesWin = nHeights + + self.nCode = nCode + self.nBaud = nBaud + self.code = code + self.flip1 = flip1 + self.flip2 = flip2 + + self.code_size = int(numpy.ceil(self.nBaud/32.))*self.nCode*4 +# self.dynamic = numpy.array([],numpy.dtype('byte')) + + if self.fClock is None and self.deltaHeight is not None: + self.fClock = 0.15/(deltaHeight*1e-6) #0.15Km / (height * 1u) + + def read(self, fp): + + startFp = fp.tell() + try: + header = numpy.fromfile(fp,RADAR_STRUCTURE,1) + except Exception, e: + print "RadarControllerHeader: " + e + return 0 + + size = int(header['nSize'][0]) + self.expType = int(header['nExpType'][0]) + self.nTx = int(header['nNTx'][0]) + self.ipp = float(header['fIpp'][0]) + self.txA = float(header['fTxA'][0]) + self.txB = float(header['fTxB'][0]) + self.nWindows = int(header['nNumWindows'][0]) + self.numTaus = int(header['nNumTaus'][0]) + self.codeType = int(header['nCodeType'][0]) + self.line6Function = int(header['nLine6Function'][0]) + self.line5Function = int(header['nLine5Function'][0]) + self.fClock = float(header['fClock'][0]) + self.prePulseBefore = int(header['nPrePulseBefore'][0]) + self.prePulserAfter = int(header['nPrePulseAfter'][0]) + self.rangeIpp = header['sRangeIPP'][0] + self.rangeTxA = header['sRangeTxA'][0] + self.rangeTxB = header['sRangeTxB'][0] + + samplingWindow = numpy.fromfile(fp,SAMPLING_STRUCTURE,self.nWindows) + + self.nHeights = int(numpy.sum(samplingWindow['nsa'])) + + self.firstHeight = samplingWindow['h0'] + self.deltaHeight = samplingWindow['dh'] + self.samplesWin = samplingWindow['nsa'] + + self.Taus = numpy.fromfile(fp,' endFp: + sys.stderr.write("Warning %s: Size value read from Radar Controller header is lower than it has to be\n" %fp.name) +# return 0 + + if fp.tell() < endFp: + sys.stderr.write("Warning %s: Size value read from Radar Controller header is greater than it has to be\n" %fp.name) + + + return 1 + + def write(self, fp): + + headerTuple = (self.size, + self.expType, + self.nTx, + self.ipp, + self.txA, + self.txB, + self.nWindows, + self.numTaus, + self.codeType, + self.line6Function, + self.line5Function, + self.fClock, + self.prePulseBefore, + self.prePulserAfter, + self.rangeIpp, + self.rangeTxA, + self.rangeTxB) + + header = numpy.array(headerTuple,RADAR_STRUCTURE) + header.tofile(fp) + + sampleWindowTuple = (self.firstHeight,self.deltaHeight,self.samplesWin) + samplingWindow = numpy.array(sampleWindowTuple,SAMPLING_STRUCTURE) + samplingWindow.tofile(fp) + + if self.numTaus > 0: + self.Taus.tofile(fp) + + if self.codeType !=0: + nCode = numpy.array(self.nCode, ' 0: + self.flag_cspc = True + + endFp = size + startFp + + if fp.tell() > endFp: + sys.stderr.write("Warning: Processing header size is lower than it has to be") + return 0 + + if fp.tell() < endFp: + sys.stderr.write("Warning: Processing header size is greater than it is considered") + + return 1 + + def write(self, fp): + #Clear DEFINE_PROCESS_CODE + self.processFlags = self.processFlags & (~PROCFLAG.DEFINE_PROCESS_CODE) + + headerTuple = (self.size, + self.dtype, + self.blockSize, + self.profilesPerBlock, + self.dataBlocksPerFile, + self.nWindows, + self.processFlags, + self.nCohInt, + self.nIncohInt, + self.totalSpectra) + + header = numpy.array(headerTuple,PROCESSING_STRUCTURE) + header.tofile(fp) + + if self.nWindows != 0: + sampleWindowTuple = (self.firstHeight,self.deltaHeight,self.samplesWin) + samplingWindow = numpy.array(sampleWindowTuple,SAMPLING_STRUCTURE) + samplingWindow.tofile(fp) + + if self.totalSpectra != 0: +# spectraComb = numpy.array([],numpy.dtype('u1')) + spectraComb = self.spectraComb + spectraComb.tofile(fp) + +# if self.processFlags & PROCFLAG.DEFINE_PROCESS_CODE == PROCFLAG.DEFINE_PROCESS_CODE: +# nCode = numpy.array([self.nCode], numpy.dtype('u4')) #Probar con un dato que almacene codigo, hasta el momento no se hizo la prueba +# nCode.tofile(fp) +# +# nBaud = numpy.array([self.nBaud], numpy.dtype('u4')) +# nBaud.tofile(fp) +# +# code = self.code.reshape(self.nCode*self.nBaud) +# code = code.astype(numpy.dtype('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 G4*6f_0@(Nf literal 0 Hc$@ vertical) + ('AntennaCoord',' endFp: + sys.stderr.write("Warning %s: Size value read from System Header is lower than it has to be\n" %fp.name) + return 0 + + if fp.tell() < endFp: + sys.stderr.write("Warning %s: Size value read from System Header size is greater than it has to be\n" %fp.name) + return 0 + + return 1 + + def write(self, fp): + + headerTuple = (self.RecMgcNumber, + self.RecCounter, + self.Off2StartNxtRec, + self.EpTimeStamp, + self.msCompTimeStamp, + self.ExpTagName, + self.ExpComment, + self.SiteLatDegrees, + self.SiteLongDegrees, + self.RTCgpsStatus, + self.TransmitFrec, + self.ReceiveFrec, + self.FirstOsciFrec, + self.Polarisation, + self.ReceiverFiltSett, + self.nModesInUse, + self.DualModeIndex, + self.DualModeRange, + self.nDigChannels, + self.SampResolution, + self.nRangeGatesSamp, + self.StartRangeSamp, + self.PRFhz, + self.Integrations, + self.nDataPointsTrsf, + self.nReceiveBeams, + self.nSpectAverages, + self.FFTwindowingInd, + self.BeamAngleAzim, + self.BeamAngleZen, + self.AntennaCoord, + self.RecPhaseCalibr, + self.RecAmpCalibr, + self.ReceiverGaindB) + +# self.size,self.nSamples, +# self.nProfiles, +# self.nChannels, +# self.adcResolution, +# self.pciDioBusWidth + + header = numpy.array(headerTuple,RECORD_STRUCTURE) + header.tofile(fp) + + return 1 + + +def get_dtype_index(numpy_dtype): + + index = None + + for i in range(len(NUMPY_DTYPE_LIST)): + if numpy_dtype == NUMPY_DTYPE_LIST[i]: + index = i + break + + return index + +def get_numpy_dtype(index): + + #dtype4 = numpy.dtype([('real','dvI@ zq)+MJ$v*)+!|qBeoA%kYn*emw3w|0@ql+0SpL4D)Y^S5P5UtPmvDiXs`*u|NI@nTntZ**w^kV3K%P-9 zp)Jg+n5>aEO);{?bxvPn=5+=)8Qeni5xm3THXm&;c$dK@gZJ35Ev9TUxWnLm26q|U zWAFik`wVs%JYeu4gO3JR;g(Km>S=NaZWU|R8p%T zWq_>65omJ+Qb?T4vLri5rplN$Ue@vi`XD+(30r8R7kF^4OqN8E%$`awklE?^#H^#e zGi_u%r{Um$-cd?MG&ry^)HH^EMih`Wn}rXDq4q&+sHVwO??;J$Vb=Ia;wT~)=cHj2 zribjKI!MOHU@}Ht9VuhupSr7elq2b3edxMHB9# zDY9*0EHR-u0duJT{4+e8RK%o;t$O(T9r4mGNLRMl2DTjSJ$od6S$Gzr1I{YP%uk9Z zQ6ObnZd^BjOus;&CEwV;-AvQ=7-G`hJ&%P0bS`RnReSS|E+ K+qT;F?Z$tP2(wcF literal 0 Hc$@jkk`5LP`eJ|Vjp6!igS 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 literal 0 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 Ka~a<^`}_y$Fk!C% literal 0 Hc$@= xmin and hour <= xmax: + return 1 + else: + return 0 + + else: + + if hour >= xmin or hour <= (xmax % 24): + return 1 + else: + return 0 + + return 0 + +def isRealtime(utcdatatime): + + utcnow = time.mktime(time.localtime()) + delta = abs(utcnow - utcdatatime) # abs + if delta >= 30.: + return False + return True + +class Figure(Operation): + + __driver = mpldriver + fig = None + + id = None + wintitle = None + width = None + height = None + nplots = None + timerange = None + + axesObjList = [] + + WIDTH = 300 + HEIGHT = 200 + PREFIX = 'fig' + + xmin = None + xmax = None + + counter_imagwr = 0 + + figfile = None + + created = False + + def __init__(self): + + raise NotImplementedError + + def __del__(self): + + self.__driver.closeFigure() + + def getFilename(self, name, ext='.png'): + + path = '%s%03d' %(self.PREFIX, self.id) + filename = '%s_%s%s' %(self.PREFIX, name, ext) + return os.path.join(path, filename) + + def getAxesObjList(self): + + return self.axesObjList + + def getSubplots(self): + + raise NotImplementedError + + def getScreenDim(self, widthplot, heightplot): + + nrow, ncol = self.getSubplots() + + widthscreen = widthplot*ncol + heightscreen = heightplot*nrow + + return widthscreen, heightscreen + + def getTimeLim(self, x, xmin=None, xmax=None, timerange=None): + +# if self.xmin != None and self.xmax != None: +# if timerange == None: +# timerange = self.xmax - self.xmin +# xmin = self.xmin + timerange +# xmax = self.xmax + timerange +# +# return xmin, xmax + + if timerange == None and (xmin==None or xmax==None): + timerange = 14400 #seconds + + if timerange != None: + txmin = x[0] #- x[0] % min(timerange/10, 10*60) + else: + txmin = x[0] #- x[0] % 10*60 + + thisdatetime = datetime.datetime.utcfromtimestamp(txmin) + thisdate = datetime.datetime.combine(thisdatetime.date(), datetime.time(0,0,0)) + + if timerange != None: + xmin = (thisdatetime - thisdate).seconds/(60*60.) + xmax = xmin + timerange/(60*60.) + + d1970 = datetime.datetime(1970,1,1) + + mindt = thisdate + datetime.timedelta(hours=xmin) #- datetime.timedelta(seconds=time.timezone) + xmin_sec = (mindt - d1970).total_seconds() #time.mktime(mindt.timetuple()) - time.timezone + + maxdt = thisdate + datetime.timedelta(hours=xmax) #- datetime.timedelta(seconds=time.timezone) + xmax_sec = (maxdt - d1970).total_seconds() #time.mktime(maxdt.timetuple()) - time.timezone + + return xmin_sec, xmax_sec + + def init(self, id, nplots, wintitle): + + raise NotImplementedError, "This method has been replaced by createFigure" + + def createFigure(self, id, wintitle, widthplot=None, heightplot=None, show=True): + + """ + Crea la figura de acuerdo al driver y parametros seleccionados seleccionados. + Las dimensiones de la pantalla es calculada a partir de los atributos self.WIDTH + y self.HEIGHT y el numero de subplots (nrow, ncol) + + Input: + id : Los parametros necesarios son + wintitle : + + """ + + if widthplot == None: + widthplot = self.WIDTH + + if heightplot == None: + heightplot = self.HEIGHT + + self.id = id + + self.wintitle = wintitle + + self.widthscreen, self.heightscreen = self.getScreenDim(widthplot, heightplot) + +# if self.created: +# self.__driver.closeFigure(self.fig) + + if not self.created: + self.fig = self.__driver.createFigure(id=self.id, + wintitle=self.wintitle, + width=self.widthscreen, + height=self.heightscreen, + show=show) + else: + self.__driver.clearFigure(self.fig) + + self.axesObjList = [] + self.counter_imagwr = 0 + + self.created = True + + def setDriver(self, driver=mpldriver): + + self.__driver = driver + + def setTitle(self, title): + + self.__driver.setTitle(self.fig, title) + + def setWinTitle(self, title): + + self.__driver.setWinTitle(self.fig, title=title) + + def setTextFromAxes(self, text): + + raise NotImplementedError, "This method has been replaced with Axes.setText" + + def makeAxes(self, nrow, ncol, xpos, ypos, colspan, rowspan): + + raise NotImplementedError, "This method has been replaced with Axes.addAxes" + + def addAxes(self, *args): + """ + + Input: + *args : Los parametros necesarios son + nrow, ncol, xpos, ypos, colspan, rowspan + """ + + axesObj = Axes(self.fig, *args) + self.axesObjList.append(axesObj) + + def saveFigure(self, figpath, figfile, *args): + + filename = os.path.join(figpath, figfile) + + fullpath = os.path.split(filename)[0] + + if not os.path.exists(fullpath): + subpath = os.path.split(fullpath)[0] + + if not os.path.exists(subpath): + os.mkdir(subpath) + + os.mkdir(fullpath) + + self.__driver.saveFigure(self.fig, filename, *args) + + def save(self, figpath, figfile=None, save=True, ftp=False, wr_period=1, thisDatetime=None, update_figfile=True): + + self.counter_imagwr += 1 + if self.counter_imagwr < wr_period: + return + + self.counter_imagwr = 0 + + if save: + + if not figfile: + + if not thisDatetime: + raise ValueError, "Saving figure: figfile or thisDatetime should be defined" + return + + str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S") + figfile = self.getFilename(name = str_datetime) + + if self.figfile == None: + self.figfile = figfile + + if update_figfile: + self.figfile = figfile + + # store png plot to local folder + self.saveFigure(figpath, self.figfile) + + + if not ftp: + return + + if not thisDatetime: + return + + # store png plot to FTP server according to RT-Web format + ftp_filename = self.getNameToFtp(thisDatetime, self.FTP_WEI, self.EXP_CODE, self.SUB_EXP_CODE, self.PLOT_CODE, self.PLOT_POS) +# ftp_filename = os.path.join(figpath, name) + self.saveFigure(figpath, ftp_filename) + + def getNameToFtp(self, thisDatetime, FTP_WEI, EXP_CODE, SUB_EXP_CODE, PLOT_CODE, PLOT_POS): + YEAR_STR = '%4.4d'%thisDatetime.timetuple().tm_year + DOY_STR = '%3.3d'%thisDatetime.timetuple().tm_yday + FTP_WEI = '%2.2d'%FTP_WEI + EXP_CODE = '%3.3d'%EXP_CODE + SUB_EXP_CODE = '%2.2d'%SUB_EXP_CODE + PLOT_CODE = '%2.2d'%PLOT_CODE + PLOT_POS = '%2.2d'%PLOT_POS + name = YEAR_STR + DOY_STR + FTP_WEI + EXP_CODE + SUB_EXP_CODE + PLOT_CODE + PLOT_POS + return name + + def draw(self): + + self.__driver.draw(self.fig) + + def run(self): + + raise NotImplementedError + + def close(self, show=False): + + self.__driver.closeFigure(show=show, fig=self.fig) + + axesList = property(getAxesObjList) + + +class Axes: + + __driver = mpldriver + fig = None + ax = None + plot = None + __missing = 1E30 + __firsttime = None + + __showprofile = False + + xmin = None + xmax = None + ymin = None + ymax = None + zmin = None + zmax = None + + x_buffer = None + z_buffer = None + + decimationx = None + decimationy = None + + __MAXNUMX = 200 + __MAXNUMY = 400 + + __MAXNUMTIME = 500 + + def __init__(self, *args): + + """ + + Input: + *args : Los parametros necesarios son + fig, nrow, ncol, xpos, ypos, colspan, rowspan + """ + + ax = self.__driver.createAxes(*args) + self.fig = args[0] + self.ax = ax + self.plot = None + + self.__firsttime = True + self.idlineList = [] + + self.x_buffer = numpy.array([]) + self.z_buffer = numpy.array([]) + + def setText(self, text): + + self.__driver.setAxesText(self.ax, text) + + def setXAxisAsTime(self): + pass + + def pline(self, x, y, + xmin=None, xmax=None, + ymin=None, ymax=None, + xlabel='', ylabel='', + title='', + **kwargs): + + """ + + Input: + x : + y : + xmin : + xmax : + ymin : + ymax : + xlabel : + ylabel : + title : + **kwargs : Los parametros aceptados son + + ticksize + ytick_visible + """ + + if self.__firsttime: + + if xmin == None: xmin = numpy.nanmin(x) + if xmax == None: xmax = numpy.nanmax(x) + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + + self.plot = self.__driver.createPline(self.ax, x, y, + xmin, xmax, + ymin, ymax, + xlabel=xlabel, + ylabel=ylabel, + title=title, + **kwargs) + + self.idlineList.append(0) + self.__firsttime = False + return + + self.__driver.pline(self.plot, x, y, xlabel=xlabel, + ylabel=ylabel, + title=title) + +# self.__driver.pause() + + def addpline(self, x, y, idline, **kwargs): + lines = self.ax.lines + + if idline in self.idlineList: + self.__driver.set_linedata(self.ax, x, y, idline) + + if idline not in(self.idlineList): + self.__driver.addpline(self.ax, x, y, **kwargs) + self.idlineList.append(idline) + + return + + def pmultiline(self, x, y, + xmin=None, xmax=None, + ymin=None, ymax=None, + xlabel='', ylabel='', + title='', + **kwargs): + + if self.__firsttime: + + if xmin == None: xmin = numpy.nanmin(x) + if xmax == None: xmax = numpy.nanmax(x) + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + + self.plot = self.__driver.createPmultiline(self.ax, x, y, + xmin, xmax, + ymin, ymax, + xlabel=xlabel, + ylabel=ylabel, + title=title, + **kwargs) + self.__firsttime = False + return + + self.__driver.pmultiline(self.plot, x, y, xlabel=xlabel, + ylabel=ylabel, + title=title) + +# self.__driver.pause() + + def pmultilineyaxis(self, x, y, + xmin=None, xmax=None, + ymin=None, ymax=None, + xlabel='', ylabel='', + title='', + **kwargs): + + if self.__firsttime: + + if xmin == None: xmin = numpy.nanmin(x) + if xmax == None: xmax = numpy.nanmax(x) + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + + self.plot = self.__driver.createPmultilineYAxis(self.ax, x, y, + xmin, xmax, + ymin, ymax, + xlabel=xlabel, + ylabel=ylabel, + title=title, + **kwargs) + if self.xmin == None: self.xmin = xmin + if self.xmax == None: self.xmax = xmax + if self.ymin == None: self.ymin = ymin + if self.ymax == None: self.ymax = ymax + + self.__firsttime = False + return + + self.__driver.pmultilineyaxis(self.plot, x, y, xlabel=xlabel, + ylabel=ylabel, + title=title) + +# self.__driver.pause() + + def pcolor(self, x, y, z, + xmin=None, xmax=None, + ymin=None, ymax=None, + zmin=None, zmax=None, + xlabel='', ylabel='', + title='', colormap='jet', + **kwargs): + + """ + Input: + x : + y : + x : + xmin : + xmax : + ymin : + ymax : + zmin : + zmax : + xlabel : + ylabel : + title : + **kwargs : Los parametros aceptados son + ticksize=9, + cblabel='' + """ + + #Decimating data + xlen = len(x) + ylen = len(y) + + decimationx = numpy.floor(xlen/self.__MAXNUMX) - 1 if numpy.floor(xlen/self.__MAXNUMX)>1 else 1 + decimationy = numpy.floor(ylen/self.__MAXNUMY) + 1 + + + x_buffer = x#[::decimationx] + y_buffer = y#[::decimationy] + z_buffer = z#[::decimationx, ::decimationy] + #=================================================== + + if self.__firsttime: + + if xmin == None: xmin = numpy.nanmin(x) + if xmax == None: xmax = numpy.nanmax(x) + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + if zmin == None: zmin = numpy.nanmin(z) + if zmax == None: zmax = numpy.nanmax(z) + + + self.plot = self.__driver.createPcolor(self.ax, x_buffer, + y_buffer, + z_buffer, + xmin, xmax, + ymin, ymax, + zmin, zmax, + xlabel=xlabel, + ylabel=ylabel, + title=title, + colormap=colormap, + **kwargs) + + if self.xmin == None: self.xmin = xmin + if self.xmax == None: self.xmax = xmax + if self.ymin == None: self.ymin = ymin + if self.ymax == None: self.ymax = ymax + if self.zmin == None: self.zmin = zmin + if self.zmax == None: self.zmax = zmax + + self.__firsttime = False + return + + self.__driver.pcolor(self.plot, + z_buffer, + xlabel=xlabel, + ylabel=ylabel, + title=title) + +# self.__driver.pause() + + def pcolorbuffer(self, x, y, z, + xmin=None, xmax=None, + ymin=None, ymax=None, + zmin=None, zmax=None, + xlabel='', ylabel='', + title='', rti = True, colormap='jet', + maxNumX = None, maxNumY = None, + **kwargs): + + if maxNumX == None: + maxNumX = self.__MAXNUMTIME + + if maxNumY == None: + maxNumY = self.__MAXNUMY + + if self.__firsttime: + self.z_buffer = z + self.x_buffer = numpy.hstack((self.x_buffer, x)) + + if xmin == None: xmin = numpy.nanmin(x) + if xmax == None: xmax = numpy.nanmax(x) + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + if zmin == None: zmin = numpy.nanmin(z) + if zmax == None: zmax = numpy.nanmax(z) + + self.plot = self.__driver.createPcolor(self.ax, self.x_buffer, y, z, + xmin, xmax, + ymin, ymax, + zmin, zmax, + xlabel=xlabel, + ylabel=ylabel, + title=title, + colormap=colormap, + **kwargs) + + if self.xmin == None: self.xmin = xmin + if self.xmax == None: self.xmax = xmax + if self.ymin == None: self.ymin = ymin + if self.ymax == None: self.ymax = ymax + if self.zmin == None: self.zmin = zmin + if self.zmax == None: self.zmax = zmax + + self.__firsttime = False + return + + self.x_buffer = numpy.hstack((self.x_buffer[:-1], x[0], x[-1])) + self.z_buffer = numpy.hstack((self.z_buffer, z)) + z_buffer = self.z_buffer.reshape(-1,len(y)) + + #Decimating data + xlen = len(self.x_buffer) + ylen = len(y) + + decimationx = numpy.floor(xlen/maxNumX) + 1 + decimationy = numpy.floor(ylen/maxNumY) + 1 + + x_buffer = self.x_buffer#[::decimationx] + y_buffer = y#[::decimationy] + z_buffer = z_buffer#[::decimationx, ::decimationy] + #=================================================== + + x_buffer, y_buffer, z_buffer = self.__fillGaps(x_buffer, y_buffer, z_buffer) + + self.__driver.addpcolorbuffer(self.ax, x_buffer, y_buffer, z_buffer, self.zmin, self.zmax, + xlabel=xlabel, + ylabel=ylabel, + title=title, + colormap=colormap) + +# self.__driver.pause() + + def polar(self, x, y, + title='', xlabel='',ylabel='',**kwargs): + + if self.__firsttime: + self.plot = self.__driver.createPolar(self.ax, x, y, title = title, xlabel = xlabel, ylabel = ylabel) + self.__firsttime = False + self.x_buffer = x + self.y_buffer = y + return + + self.x_buffer = numpy.hstack((self.x_buffer,x)) + self.y_buffer = numpy.hstack((self.y_buffer,y)) + self.__driver.polar(self.plot, self.x_buffer, self.y_buffer, xlabel=xlabel, + ylabel=ylabel, + title=title) + +# self.__driver.pause() + + def __fillGaps(self, x_buffer, y_buffer, z_buffer): + + if x_buffer.shape[0] < 2: + return x_buffer, y_buffer, z_buffer + + deltas = x_buffer[1:] - x_buffer[0:-1] + x_median = numpy.median(deltas) + + index = numpy.where(deltas > 5*x_median) + + if len(index[0]) != 0: + z_buffer[index[0],::] = self.__missing + z_buffer = numpy.ma.masked_inside(z_buffer,0.99*self.__missing,1.01*self.__missing) + + return x_buffer, y_buffer, z_buffer + + + + \ No newline at end of file diff --git a/schainpy/model/graphics/.svn/text-base/figure.pyc.svn-base b/schainpy/model/graphics/.svn/text-base/figure.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..bb32043522b7c4948c41a47e47decabbf7048cc6 GIT binary patch literal 17894 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 JLVoI7{{zi52SES; literal 0 Hc$@= self.nplots: + break + + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + if showprofile: + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1) + + counter += 1 + + def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False, + xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, + save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False): + + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + zmin : None, + zmax : None + """ + + if dataOut.flagNoData: + return None + + if realtime: + if not(isRealtime(utcdatatime = dataOut.utctime)): + print 'Skipping this plot function' + return + + if channelList == None: + channelIndexList = dataOut.channelIndexList + else: + channelIndexList = [] + for channel in channelList: + if channel not in dataOut.channelList: + raise ValueError, "Channel %d is not in dataOut.channelList" + channelIndexList.append(dataOut.channelList.index(channel)) + + factor = dataOut.normFactor + lenfactor = factor.shape[1] + x = dataOut.getLagTRange(1) + y = dataOut.getHeiRange() + + z = copy.copy(dataOut.data_corr[:,:,0,:]) + for i in range(dataOut.data_corr.shape[0]): + z[i,:,:] = z[i,:,:]/factor[i,:] + zdB = numpy.abs(z) + + avg = numpy.average(z, axis=1) +# avg = numpy.nanmean(z, axis=1) +# noise = dataOut.noise/factor + + #thisDatetime = dataOut.datatime + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) + title = wintitle + " Correlation" + xlabel = "Lag T (s)" + ylabel = "Range (Km)" + + if not self.isConfig: + + nplots = dataOut.data_corr.shape[0] + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + if xmin == None: xmin = numpy.nanmin(x) + if xmax == None: xmax = numpy.nanmax(x) + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + if zmin == None: zmin = 0 + if zmax == None: zmax = 1 + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.isConfig = True + + self.setWinTitle(title) + + for i in range(self.nplots): + str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S")) + title = "Channel %d and %d: : %s" %(dataOut.pairsList[i][0],dataOut.pairsList[i][1] , str_datetime) + axes = self.axesList[i*self.__nsubplots] + axes.pcolor(x, y, zdB[i,:,:], + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax, + xlabel=xlabel, ylabel=ylabel, title=title, + ticksize=9, cblabel='') + +# if self.__showprofile: +# axes = self.axesList[i*self.__nsubplots +1] +# axes.pline(avgdB[i], y, +# xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax, +# xlabel='dB', ylabel='', title='', +# ytick_visible=False, +# grid='x') +# +# noiseline = numpy.repeat(noisedB[i], len(y)) +# axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2) + + self.draw() + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime) diff --git a/schainpy/model/graphics/.svn/text-base/jroplot_correlation.pyc.svn-base b/schainpy/model/graphics/.svn/text-base/jroplot_correlation.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..2e0a1a8267f47b0fae5590a7bdd278dd67cdc6cd GIT binary patch literal 5427 zc$~dh&2Jmm5uaU(6iJEJhpjJ5iWysUDBHE_)@>2hO={V4q{fwnm1-qI19r__QcID` z)$Y=w1oBe5J@k@mQK0Cd|3m+Z7CH1^=rM-^y%i|Z`OVu$%Z3v8WRW|XH*fa6`F``5 z`cEPMy}SS0t5Wip;^*i5M89F+@YkRw(f$B8Xy4GdN&BY8Q?#EF+@$6ZwbHbordEdb zGh{d^a?@1f*M{gN(F>x__lNP)PC3n+c;E2fR@r1U&MhU}eDsOnCQt_kCvw*QkUfbJzxVs@v-B{oJWMenZ zY2vo^tyKnutX^RI$xhkO9*Ep#tt=V>L{Ay49JE{RiW_>>!t+zw7;|4PO4J+{pR_L{|x zX3ogrQJ(=OL6J%x35xqFC}M*e5(teHy^!db;eUN22^gkwoLuS|G^MAQo4*FtO!hLC z+p7QL@A&)rZD==WdsgmHe7@GKuLj; zWLk=RWn7hVhNM{v`3|C_Tq8p>oaew4%Vxe#_q%RXF6hX$P_fj)3t%5fgwtDI0Wq6IH%F~6%OtpkGsZ&lCR8a? zF${Dfu={S(AT8A^?gYy~zAp)oks^{Y^k>u@V>r&AVRMq{7mbTd88Vj`ziGxIB3yZU zML8IRDvWcBpLv}?->}~~>Kkm+0&-%fcbURF2m%~4hLj>QqC3c)Pd31SXc_|Rp-JJU z@C;FZp8QXVYYrpbH84EB*e~qK3 zvm{`9>D;`?}`jZk$e3j#RX~0-hZFE z4dRYNz0;6Geoj);qW)Fty-&TX=PXrA(HskPc8<&M+|+mQ-#Z#N_Tq7BOkh>)eT^`j z#1LHs6f*it6kntUe=mtlQ_w7tsb7++#FeLiT?)(x!ZJApS>pmKm&0n0srr@CzMMB9(=7F_h=>{S(XgKVP-f@!?6Ayc_3WO0wnVh`4v zoy|&@$ytC}<PQk#mI{Rw*@N9DQx>Ve{*V7daG|pM#O}nWf@vxQ1iFS)$%JIV{!$ zIoF}`3(BBr-zk59LhvUp68U2CH$XQ1pcAhShWK;r*nZN92jkagJ?DJ7K1t4>vR<@smFs{rU9Z@s~0ci)2TE@vAsQwj!KS50qJpC8x*?KF_l_iT`e&vH7b5 zLe6r#>qQX`pbJHlD~*sd3Mi{)rJlJgj+aIySpYx#{s*IEL=NgLrLD@Dap6yeM* zeZEp^t&|)!*jO$7a<#M*&AcwE?K}K$m90>UL>_oJLF}#|Cz^7iDW{qOTS`mYZQ9S= zrl2PZg)FL_$qH6IjJ#9V%MFhEXToRQ)C9f&1$KO(aRi`hcI@Y_bkwytP_0o|3AhPp zJJQF%9S^yafuqXsgEUOFrd{7^Gu^hNSuyl3>{hw^jza`xhE3mbyYP(o{fwt%rKfhY z@IwGBW_<{- zsx!g52k@eB4Tgs+^9Yx$zIx76)pmOYbGU0Xu_KTzZ$v5%J zfFQ4-pA6cO48r7x73=;W$W<_@omGIqTus+kBMU93B~gnAJr(GQ<4>J66#&oc)<@v_ zF~D7bAL;y8GR0wK5D`O(`QJ_F4Ee&2{}|i6#Aeeu?uj$Tq><)6d6c{6j8QPgj8S8e zFXV!mca243+ZZ#a(hEi&y|tM$$ECZ*hu@+}(4ea%2H&(+>Wd*T|um0Xsv4Mo=3VC a%DV4P4ROak<$#Z{zZ_{CAo!Tm=KlfNWLsST literal 0 Hc$@= self.nplots: + break + + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + if showprofile: + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1) + + counter += 1 + + + def run(self, dataOut, id, wintitle="", channelList=None, + xmin=None, xmax=None, ymin=None, ymax=None, save=False, + figpath='./', figfile=None, ftp=False, wr_period=1, show=True, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): + + """ + + Input: + dataOut : + id : + wintitle : + channelList : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + """ + + if dataOut.realtime: + if not(isRealtime(utcdatatime = dataOut.utctime)): + print 'Skipping this plot function' + return + + if channelList == None: + channelIndexList = dataOut.channelIndexList + else: + channelIndexList = [] + for channel in channelList: + if channel not in dataOut.channelList: + raise ValueError, "Channel %d is not in dataOut.channelList" + channelIndexList.append(dataOut.channelList.index(channel)) + +# x = dataOut.heightList + c = 3E8 + deltaHeight = dataOut.heightList[1] - dataOut.heightList[0] + #deberia cambiar para el caso de 1Mhz y 100KHz + x = numpy.arange(-1*dataOut.nHeights/2.,dataOut.nHeights/2.)*(c/(2*deltaHeight*dataOut.nHeights*1000)) + #para 1Mhz descomentar la siguiente linea + #x= x/(10000.0) +# y = dataOut.data[channelIndexList,:] * numpy.conjugate(dataOut.data[channelIndexList,:]) +# y = y.real + factor = dataOut.normFactor + data = dataOut.data_spc / factor + datadB = 10.*numpy.log10(data) + y = datadB + + #thisDatetime = dataOut.datatime + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) + title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S")) + xlabel = "" + #para 1Mhz descomentar la siguiente linea + #xlabel = "Frequency x 10000" + ylabel = "Intensity (dB)" + + if not self.isConfig: + nplots = len(channelIndexList) + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + show=show) + + if xmin == None: xmin = numpy.nanmin(x) + if xmax == None: xmax = numpy.nanmax(x) + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.isConfig = True + + self.setWinTitle(title) + + for i in range(len(self.axesList)): + ychannel = y[i,:] + str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S")) + title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[channelIndexList[i]], numpy.max(ychannel), str_datetime) + axes = self.axesList[i] + axes.pline(x, ychannel, + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, + xlabel=xlabel, ylabel=ylabel, title=title, grid='both') + + + self.draw() + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime) + +class RTIfromSpectraHeis(Figure): + + isConfig = None + __nsubplots = None + + PREFIX = 'rtinoise' + + def __init__(self): + + self.timerange = 24*60*60 + self.isConfig = False + self.__nsubplots = 1 + + self.WIDTH = 820 + self.HEIGHT = 200 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.counter_imagwr = 0 + self.xdata = None + self.ydata = None + self.figfile = None + + self.PLOT_CODE = RTI_CODE + + def getSubplots(self): + + ncol = 1 + nrow = 1 + + return nrow, ncol + + def setup(self, id, nplots, wintitle, showprofile=True, show=True): + + self.__showprofile = showprofile + self.nplots = nplots + + ncolspan = 7 + colspan = 6 + self.__nsubplots = 2 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH+self.WIDTHPROF, + heightplot = self.HEIGHT+self.HEIGHTPROF, + show = show) + + nrow, ncol = self.getSubplots() + + self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1) + + + def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True', + xmin=None, xmax=None, ymin=None, ymax=None, + timerange=None, + save=False, figpath='./', figfile=None, ftp=False, wr_period=1, show=True, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): + + if channelList == None: + channelIndexList = dataOut.channelIndexList + channelList = dataOut.channelList + else: + channelIndexList = [] + for channel in channelList: + if channel not in dataOut.channelList: + raise ValueError, "Channel %d is not in dataOut.channelList" + channelIndexList.append(dataOut.channelList.index(channel)) + + if timerange != None: + self.timerange = timerange + + x = dataOut.getTimeRange() + y = dataOut.getHeiRange() + + factor = dataOut.normFactor + data = dataOut.data_spc / factor + data = numpy.average(data,axis=1) + datadB = 10*numpy.log10(data) + +# factor = dataOut.normFactor +# noise = dataOut.getNoise()/factor +# noisedB = 10*numpy.log10(noise) + + #thisDatetime = dataOut.datatime + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) + title = wintitle + " RTI: %s" %(thisDatetime.strftime("%d-%b-%Y")) + xlabel = "Local Time" + ylabel = "Intensity (dB)" + + if not self.isConfig: + + nplots = 1 + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + self.tmin, self.tmax = self.getTimeLim(x, xmin, xmax) + + if ymin == None: ymin = numpy.nanmin(datadB) + if ymax == None: ymax = numpy.nanmax(datadB) + + self.name = thisDatetime.strftime("%Y%m%d_%H%M%S") + self.isConfig = True + self.figfile = figfile + self.xdata = numpy.array([]) + self.ydata = numpy.array([]) + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.setWinTitle(title) + + +# title = "RTI %s" %(thisDatetime.strftime("%d-%b-%Y")) + title = "RTI - %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S")) + + legendlabels = ["channel %d"%idchannel for idchannel in channelList] + axes = self.axesList[0] + + self.xdata = numpy.hstack((self.xdata, x[0:1])) + + if len(self.ydata)==0: + self.ydata = datadB[channelIndexList].reshape(-1,1) + else: + self.ydata = numpy.hstack((self.ydata, datadB[channelIndexList].reshape(-1,1))) + + + axes.pmultilineyaxis(x=self.xdata, y=self.ydata, + xmin=self.tmin, xmax=self.tmax, ymin=ymin, ymax=ymax, + xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='.', markersize=8, linestyle="solid", grid='both', + XAxisAsTime=True + ) + + self.draw() + + update_figfile = False + + if dataOut.ltctime >= self.tmax: + self.counter_imagwr = wr_period + self.isConfig = False + update_figfile = True + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime, + update_figfile=update_figfile) diff --git a/schainpy/model/graphics/.svn/text-base/jroplot_heispectra.pyc.svn-base b/schainpy/model/graphics/.svn/text-base/jroplot_heispectra.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..275cd64d9e4474ee1141c8180dbaaaa09ca8a68d GIT binary patch literal 8935 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 C&E^CE literal 0 Hc$@= self.nplots: + break + + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + if showprofile: + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1) + + counter += 1 + + def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True, + xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, + save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False): + + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + zmin : None, + zmax : None + """ + + if dataOut.flagNoData: + return None + + if realtime: + if not(isRealtime(utcdatatime = dataOut.utctime)): + print 'Skipping this plot function' + return + + if channelList == None: + channelIndexList = dataOut.channelIndexList + else: + channelIndexList = [] + for channel in channelList: + if channel not in dataOut.channelList: + raise ValueError, "Channel %d is not in dataOut.channelList" + channelIndexList.append(dataOut.channelList.index(channel)) + + factor = dataOut.normFactor + x = dataOut.abscissaList + y = dataOut.heightList + + z = dataOut.data_pre[channelIndexList,:,:]/factor + z = numpy.where(numpy.isfinite(z), z, numpy.NAN) + avg = numpy.average(z, axis=1) + noise = dataOut.noise/factor + + zdB = 10*numpy.log10(z) + avgdB = 10*numpy.log10(avg) + noisedB = 10*numpy.log10(noise) + + #thisDatetime = dataOut.datatime + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) + title = wintitle + " Parameters" + xlabel = "Velocity (m/s)" + ylabel = "Range (Km)" + + update_figfile = False + + if not self.isConfig: + + nplots = len(channelIndexList) + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + if xmin == None: xmin = numpy.nanmin(x) + if xmax == None: xmax = numpy.nanmax(x) + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + if zmin == None: zmin = numpy.nanmin(avgdB)*0.9 + if zmax == None: zmax = numpy.nanmax(avgdB)*0.9 + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.isConfig = True + update_figfile = True + + self.setWinTitle(title) + + for i in range(self.nplots): + str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S")) + title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[i], noisedB[i], str_datetime) + axes = self.axesList[i*self.__nsubplots] + axes.pcolor(x, y, zdB[i,:,:], + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax, + xlabel=xlabel, ylabel=ylabel, title=title, + ticksize=9, cblabel='') + #Mean Line + mean = dataOut.data_param[i, 1, :] + axes.addpline(mean, y, idline=0, color="black", linestyle="solid", lw=1) + + if self.__showprofile: + axes = self.axesList[i*self.__nsubplots +1] + axes.pline(avgdB[i], y, + xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax, + xlabel='dB', ylabel='', title='', + ytick_visible=False, + grid='x') + + noiseline = numpy.repeat(noisedB[i], len(y)) + axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2) + + self.draw() + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime) + + + +class SkyMapPlot(Figure): + + __isConfig = None + __nsubplots = None + + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'mmap' + + def __init__(self): + + self.isConfig = False + self.__nsubplots = 1 + +# self.WIDTH = 280 +# self.HEIGHT = 250 + self.WIDTH = 600 + self.HEIGHT = 600 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.counter_imagwr = 0 + + self.PLOT_CODE = MSKYMAP_CODE + + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + + def getSubplots(self): + + ncol = int(numpy.sqrt(self.nplots)+0.9) + nrow = int(self.nplots*1./ncol + 0.9) + + return nrow, ncol + + def setup(self, id, nplots, wintitle, showprofile=False, show=True): + + self.__showprofile = showprofile + self.nplots = nplots + + ncolspan = 1 + colspan = 1 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH, #+ self.WIDTHPROF, + heightplot = self.HEIGHT,# + self.HEIGHTPROF, + show=show) + + nrow, ncol = 1,1 + counter = 0 + x = 0 + y = 0 + self.addAxes(1, 1, 0, 0, 1, 1, True) + + def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False, + tmin=0, tmax=24, timerange=None, + save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False): + + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + zmin : None, + zmax : None + """ + + arrayParameters = dataOut.data_param + error = arrayParameters[:,-1] + indValid = numpy.where(error == 0)[0] + finalMeteor = arrayParameters[indValid,:] + finalAzimuth = finalMeteor[:,3] + finalZenith = finalMeteor[:,4] + + x = finalAzimuth*numpy.pi/180 + y = finalZenith + x1 = [dataOut.ltctime, dataOut.ltctime] + + #thisDatetime = dataOut.datatime + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime) + title = wintitle + " Parameters" + xlabel = "Zonal Zenith Angle (deg) " + ylabel = "Meridional Zenith Angle (deg)" + update_figfile = False + + if not self.isConfig: + + nplots = 1 + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + if self.xmin is None and self.xmax is None: + self.xmin, self.xmax = self.getTimeLim(x1, tmin, tmax, timerange) + + if timerange != None: + self.timerange = timerange + else: + self.timerange = self.xmax - self.xmin + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + self.name = thisDatetime.strftime("%Y%m%d_%H%M%S") + self.firstdate = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S")) + self.isConfig = True + update_figfile = True + + self.setWinTitle(title) + + i = 0 + str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S")) + + axes = self.axesList[i*self.__nsubplots] + nevents = axes.x_buffer.shape[0] + x.shape[0] + title = "Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n" %(self.firstdate,str_datetime,nevents) + axes.polar(x, y, + title=title, xlabel=xlabel, ylabel=ylabel, + ticksize=9, cblabel='') + + self.draw() + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime, + update_figfile=update_figfile) + + if dataOut.ltctime >= self.xmax: + self.isConfigmagwr = wr_period + self.isConfig = False + update_figfile = True + axes.__firsttime = True + self.xmin += self.timerange + self.xmax += self.timerange + + + + +class WindProfilerPlot(Figure): + + __isConfig = None + __nsubplots = None + + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'wind' + + def __init__(self): + + self.timerange = None + self.isConfig = False + self.__nsubplots = 1 + + self.WIDTH = 800 + self.HEIGHT = 300 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.counter_imagwr = 0 + + self.PLOT_CODE = WIND_CODE + + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + self.tmin = None + self.tmax = None + + self.xmin = None + self.xmax = None + + self.figfile = None + + def getSubplots(self): + + ncol = 1 + nrow = self.nplots + + return nrow, ncol + + def setup(self, id, nplots, wintitle, showprofile=True, show=True): + + self.__showprofile = showprofile + self.nplots = nplots + + ncolspan = 1 + colspan = 1 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH + self.WIDTHPROF, + heightplot = self.HEIGHT + self.HEIGHTPROF, + show=show) + + nrow, ncol = self.getSubplots() + + counter = 0 + for y in range(nrow): + if counter >= self.nplots: + break + + self.addAxes(nrow, ncol*ncolspan, y, 0, colspan, 1) + counter += 1 + + def run(self, dataOut, id, wintitle="", channelList=None, showprofile='False', + xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, + zmax_ver = None, zmin_ver = None, SNRmin = None, SNRmax = None, + timerange=None, SNRthresh = None, + save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + zmin : None, + zmax : None + """ + +# if timerange is not None: +# self.timerange = timerange +# +# tmin = None +# tmax = None + + + x = dataOut.getTimeRange() + y = dataOut.getHeiRange() + #x = dataOut.getTimeRange1(dataOut.outputInterval) + #y = dataOut.heightList + + z = dataOut.data_output.copy() + #print 'dataOut_JI',z + nplots = z.shape[0] #Number of wind dimensions estimated + nplotsw = nplots + + + #If there is a SNR function defined + if dataOut.data_SNR is not None: + nplots += 1 + SNR = dataOut.data_SNR + SNRavg = numpy.average(SNR, axis=0) + + SNRdB = 10*numpy.log10(SNR) + SNRavgdB = 10*numpy.log10(SNRavg) + + if SNRthresh == None: SNRthresh = -5.0 + ind = numpy.where(SNRavg < 10**(SNRthresh/10))[0] + + for i in range(nplotsw): + z[i,ind] = numpy.nan + + +# showprofile = False +# thisDatetime = dataOut.datatime + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime) + title = wintitle + "Wind" + xlabel = "" + ylabel = "Height (km)" + update_figfile = False + + if not self.isConfig: + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + if timerange is not None: + self.timerange = timerange + + self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange) + + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + + if zmax == None: zmax = numpy.nanmax(abs(z[range(2),:])) + #if numpy.isnan(zmax): zmax = 50 + if zmin == None: zmin = -zmax + + if nplotsw == 3: + if zmax_ver == None: zmax_ver = numpy.nanmax(abs(z[2,:])) + if zmin_ver == None: zmin_ver = -zmax_ver + + if dataOut.data_SNR is not None: + if SNRmin == None: SNRmin = numpy.nanmin(SNRavgdB) + if SNRmax == None: SNRmax = numpy.nanmax(SNRavgdB) + + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.name = thisDatetime.strftime("%Y%m%d_%H%M%S") + self.isConfig = True + self.figfile = figfile + update_figfile = True + + self.setWinTitle(title) + + if ((self.xmax - x[1]) < (x[1]-x[0])): + x[1] = self.xmax + + strWind = ['Zonal', 'Meridional', 'Vertical'] + strCb = ['Velocity (m/s)','Velocity (m/s)','Velocity (cm/s)'] + zmaxVector = [zmax, zmax, zmax_ver] + zminVector = [zmin, zmin, zmin_ver] + windFactor = [1,1,100] + + for i in range(nplotsw): + + title = "%s Wind: %s" %(strWind[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + axes = self.axesList[i*self.__nsubplots] + + z1 = z[i,:].reshape((1,-1))*windFactor[i] + #z1=numpy.ma.masked_where(z1==0.,z1) + + axes.pcolorbuffer(x, y, z1, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zminVector[i], zmax=zmaxVector[i], + xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True, + ticksize=9, cblabel=strCb[i], cbsize="1%", colormap="seismic" ) + + if dataOut.data_SNR is not None: + i += 1 + title = "Signal Noise Ratio (SNR): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + axes = self.axesList[i*self.__nsubplots] + + SNRavgdB = SNRavgdB.reshape((1,-1)) + + axes.pcolorbuffer(x, y, SNRavgdB, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax, + xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True, + ticksize=9, cblabel='', cbsize="1%", colormap="jet") + + self.draw() + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime, + update_figfile=update_figfile) + + if dataOut.ltctime + dataOut.outputInterval >= self.xmax: + self.counter_imagwr = wr_period + self.isConfig = False + update_figfile = True + + +class ParametersPlot(Figure): + + __isConfig = None + __nsubplots = None + + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'param' + + nplots = None + nchan = None + + def __init__(self): + + self.timerange = None + self.isConfig = False + self.__nsubplots = 1 + + self.WIDTH = 800 + self.HEIGHT = 180 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.counter_imagwr = 0 + + self.PLOT_CODE = RTI_CODE + + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + self.tmin = None + self.tmax = None + + self.xmin = None + self.xmax = None + + self.figfile = None + + def getSubplots(self): + + ncol = 1 + nrow = self.nplots + + return nrow, ncol + + def setup(self, id, nplots, wintitle, show=True): + + self.nplots = nplots + + ncolspan = 1 + colspan = 1 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH + self.WIDTHPROF, + heightplot = self.HEIGHT + self.HEIGHTPROF, + show=show) + + nrow, ncol = self.getSubplots() + + counter = 0 + for y in range(nrow): + for x in range(ncol): + + if counter >= self.nplots: + break + + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + counter += 1 + + def run(self, dataOut, id, wintitle="", channelList=None, paramIndex = 0, colormap=True, + xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, timerange=None, + showSNR=False, SNRthresh = -numpy.inf, SNRmin=None, SNRmax=None, + save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): + + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + zmin : None, + zmax : None + """ + + if colormap: + colormap="jet" + else: + colormap="RdBu_r" + + if not isTimeInHourRange(dataOut.datatime, xmin, xmax): + return + + if channelList == None: + channelIndexList = range(dataOut.data_param.shape[0]) + else: + channelIndexList = [] + for channel in channelList: + if channel not in dataOut.channelList: + raise ValueError, "Channel %d is not in dataOut.channelList" + channelIndexList.append(dataOut.channelList.index(channel)) + + x = dataOut.getTimeRange1(dataOut.paramInterval) + y = dataOut.getHeiRange() + + if dataOut.data_param.ndim == 3: + z = dataOut.data_param[channelIndexList,paramIndex,:] + else: + z = dataOut.data_param[channelIndexList,:] + + if showSNR: + #SNR data + SNRarray = dataOut.data_SNR[channelIndexList,:] + SNRdB = 10*numpy.log10(SNRarray) + ind = numpy.where(SNRdB < SNRthresh) + z[ind] = numpy.nan + + thisDatetime = dataOut.datatime +# thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) + title = wintitle + " Parameters Plot" #: %s" %(thisDatetime.strftime("%d-%b-%Y")) + xlabel = "" + ylabel = "Range (Km)" + + update_figfile = False + + if not self.isConfig: + + nchan = len(channelIndexList) + self.nchan = nchan + self.plotFact = 1 + nplots = nchan + + if showSNR: + nplots = nchan*2 + self.plotFact = 2 + if SNRmin == None: SNRmin = numpy.nanmin(SNRdB) + if SNRmax == None: SNRmax = numpy.nanmax(SNRdB) + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + show=show) + + if timerange != None: + self.timerange = timerange + + self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange) + + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + if zmin == None: zmin = numpy.nanmin(z) + if zmax == None: zmax = numpy.nanmax(z) + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.name = thisDatetime.strftime("%Y%m%d_%H%M%S") + self.isConfig = True + self.figfile = figfile + update_figfile = True + + self.setWinTitle(title) + + for i in range(self.nchan): + index = channelIndexList[i] + title = "Channel %d: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + axes = self.axesList[i*self.plotFact] + z1 = z[i,:].reshape((1,-1)) + axes.pcolorbuffer(x, y, z1, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax, + xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True, + ticksize=9, cblabel='', cbsize="1%",colormap=colormap) + + if showSNR: + title = "Channel %d SNR: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + axes = self.axesList[i*self.plotFact + 1] + SNRdB1 = SNRdB[i,:].reshape((1,-1)) + axes.pcolorbuffer(x, y, SNRdB1, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax, + xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True, + ticksize=9, cblabel='', cbsize="1%",colormap='jet') + + + self.draw() + + if dataOut.ltctime >= self.xmax: + self.counter_imagwr = wr_period + self.isConfig = False + update_figfile = True + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime, + update_figfile=update_figfile) + + + +class Parameters1Plot(Figure): + + __isConfig = None + __nsubplots = None + + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'prm' + + def __init__(self): + + self.timerange = 2*60*60 + self.isConfig = False + self.__nsubplots = 1 + + self.WIDTH = 800 + self.HEIGHT = 150 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.counter_imagwr = 0 + + self.PLOT_CODE = PARMS_CODE + + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + self.tmin = None + self.tmax = None + + self.xmin = None + self.xmax = None + + self.figfile = None + + def getSubplots(self): + + ncol = 1 + nrow = self.nplots + + return nrow, ncol + + def setup(self, id, nplots, wintitle, showprofile=True, show=True): + + self.__showprofile = showprofile + self.nplots = nplots + + ncolspan = 1 + colspan = 1 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH + self.WIDTHPROF, + heightplot = self.HEIGHT + self.HEIGHTPROF, + show=show) + + nrow, ncol = self.getSubplots() + + counter = 0 + for y in range(nrow): + for x in range(ncol): + + if counter >= self.nplots: + break + + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + if showprofile: + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1) + + counter += 1 + + def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False, + xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,timerange=None, + parameterIndex = None, onlyPositive = False, + SNRthresh = -numpy.inf, SNR = True, SNRmin = None, SNRmax = None, onlySNR = False, + DOP = True, + zlabel = "", parameterName = "", parameterObject = "data_param", + save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): + + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + zmin : None, + zmax : None + """ + + data_param = getattr(dataOut, parameterObject) + + if channelList == None: + channelIndexList = numpy.arange(data_param.shape[0]) + else: + channelIndexList = numpy.array(channelList) + + nchan = len(channelIndexList) #Number of channels being plotted + + if nchan < 1: + return + + nGraphsByChannel = 0 + + if SNR: + nGraphsByChannel += 1 + if DOP: + nGraphsByChannel += 1 + + if nGraphsByChannel < 1: + return + + nplots = nGraphsByChannel*nchan + + if timerange is not None: + self.timerange = timerange + + #tmin = None + #tmax = None + if parameterIndex == None: + parameterIndex = 1 + + x = dataOut.getTimeRange1(dataOut.paramInterval) + y = dataOut.heightList + z = data_param[channelIndexList,parameterIndex,:].copy() + + zRange = dataOut.abscissaList +# nChannels = z.shape[0] #Number of wind dimensions estimated +# thisDatetime = dataOut.datatime + + if dataOut.data_SNR is not None: + SNRarray = dataOut.data_SNR[channelIndexList,:] + SNRdB = 10*numpy.log10(SNRarray) +# SNRavgdB = 10*numpy.log10(SNRavg) + ind = numpy.where(SNRdB < 10**(SNRthresh/10)) + z[ind] = numpy.nan + + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) + title = wintitle + " Parameters Plot" #: %s" %(thisDatetime.strftime("%d-%b-%Y")) + xlabel = "" + ylabel = "Range (Km)" + + if (SNR and not onlySNR): nplots = 2*nplots + + if onlyPositive: + colormap = "jet" + zmin = 0 + else: colormap = "RdBu_r" + + if not self.isConfig: + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange) + + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + if zmin == None: zmin = numpy.nanmin(zRange) + if zmax == None: zmax = numpy.nanmax(zRange) + + if SNR: + if SNRmin == None: SNRmin = numpy.nanmin(SNRdB) + if SNRmax == None: SNRmax = numpy.nanmax(SNRdB) + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.name = thisDatetime.strftime("%Y%m%d_%H%M%S") + self.isConfig = True + self.figfile = figfile + + self.setWinTitle(title) + + if ((self.xmax - x[1]) < (x[1]-x[0])): + x[1] = self.xmax + + for i in range(nchan): + + if (SNR and not onlySNR): j = 2*i + else: j = i + + j = nGraphsByChannel*i + + if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)): + title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith) + + if not onlySNR: + axes = self.axesList[j*self.__nsubplots] + z1 = z[i,:].reshape((1,-1)) + axes.pcolorbuffer(x, y, z1, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax, + xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap=colormap, + ticksize=9, cblabel=zlabel, cbsize="1%") + + if DOP: + title = "%s Channel %d: %s" %(parameterName, channelIndexList[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + + if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)): + title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith) + axes = self.axesList[j] + z1 = z[i,:].reshape((1,-1)) + axes.pcolorbuffer(x, y, z1, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax, + xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap=colormap, + ticksize=9, cblabel=zlabel, cbsize="1%") + + if SNR: + title = "Channel %d Signal Noise Ratio (SNR): %s" %(channelIndexList[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + axes = self.axesList[(j)*self.__nsubplots] + if not onlySNR: + axes = self.axesList[(j + 1)*self.__nsubplots] + + axes = self.axesList[(j + nGraphsByChannel-1)] + + z1 = SNRdB[i,:].reshape((1,-1)) + axes.pcolorbuffer(x, y, z1, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax, + xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap="jet", + ticksize=9, cblabel=zlabel, cbsize="1%") + + + + self.draw() + + if x[1] >= self.axesList[0].xmax: + self.counter_imagwr = wr_period + self.isConfig = False + self.figfile = None + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime, + update_figfile=False) + +class SpectralFittingPlot(Figure): + + __isConfig = None + __nsubplots = None + + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'prm' + + + N = None + ippSeconds = None + + def __init__(self): + self.isConfig = False + self.__nsubplots = 1 + + self.PLOT_CODE = SPECFIT_CODE + + self.WIDTH = 450 + self.HEIGHT = 250 + self.WIDTHPROF = 0 + self.HEIGHTPROF = 0 + + def getSubplots(self): + + ncol = int(numpy.sqrt(self.nplots)+0.9) + nrow = int(self.nplots*1./ncol + 0.9) + + return nrow, ncol + + def setup(self, id, nplots, wintitle, showprofile=False, show=True): + + showprofile = False + self.__showprofile = showprofile + self.nplots = nplots + + ncolspan = 5 + colspan = 4 + if showprofile: + ncolspan = 5 + colspan = 4 + self.__nsubplots = 2 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH + self.WIDTHPROF, + heightplot = self.HEIGHT + self.HEIGHTPROF, + show=show) + + nrow, ncol = self.getSubplots() + + counter = 0 + for y in range(nrow): + for x in range(ncol): + + if counter >= self.nplots: + break + + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + if showprofile: + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1) + + counter += 1 + + def run(self, dataOut, id, cutHeight=None, fit=False, wintitle="", channelList=None, showprofile=True, + xmin=None, xmax=None, ymin=None, ymax=None, + save=False, figpath='./', figfile=None, show=True): + + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + zmin : None, + zmax : None + """ + + if cutHeight==None: + h=270 + heightindex = numpy.abs(cutHeight - dataOut.heightList).argmin() + cutHeight = dataOut.heightList[heightindex] + + factor = dataOut.normFactor + x = dataOut.abscissaList[:-1] + #y = dataOut.getHeiRange() + + z = dataOut.data_pre[:,:,heightindex]/factor + z = numpy.where(numpy.isfinite(z), z, numpy.NAN) + avg = numpy.average(z, axis=1) + listChannels = z.shape[0] + + #Reconstruct Function + if fit==True: + groupArray = dataOut.groupList + listChannels = groupArray.reshape((groupArray.size)) + listChannels.sort() + spcFitLine = numpy.zeros(z.shape) + constants = dataOut.constants + + nGroups = groupArray.shape[0] + nChannels = groupArray.shape[1] + nProfiles = z.shape[1] + + for f in range(nGroups): + groupChann = groupArray[f,:] + p = dataOut.data_param[f,:,heightindex] +# p = numpy.array([ 89.343967,0.14036615,0.17086219,18.89835291,1.58388365,1.55099167]) + fitLineAux = dataOut.library.modelFunction(p, constants)*nProfiles + fitLineAux = fitLineAux.reshape((nChannels,nProfiles)) + spcFitLine[groupChann,:] = fitLineAux +# spcFitLine = spcFitLine/factor + + z = z[listChannels,:] + spcFitLine = spcFitLine[listChannels,:] + spcFitLinedB = 10*numpy.log10(spcFitLine) + + zdB = 10*numpy.log10(z) + #thisDatetime = dataOut.datatime + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) + title = wintitle + " Doppler Spectra: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S")) + xlabel = "Velocity (m/s)" + ylabel = "Spectrum" + + if not self.isConfig: + + nplots = listChannels.size + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + if xmin == None: xmin = numpy.nanmin(x) + if xmax == None: xmax = numpy.nanmax(x) + if ymin == None: ymin = numpy.nanmin(zdB) + if ymax == None: ymax = numpy.nanmax(zdB)+2 + + self.isConfig = True + + self.setWinTitle(title) + for i in range(self.nplots): +# title = "Channel %d: %4.2fdB" %(dataOut.channelList[i]+1, noisedB[i]) + title = "Height %4.1f km\nChannel %d:" %(cutHeight, listChannels[i]) + axes = self.axesList[i*self.__nsubplots] + if fit == False: + axes.pline(x, zdB[i,:], + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, + xlabel=xlabel, ylabel=ylabel, title=title + ) + if fit == True: + fitline=spcFitLinedB[i,:] + y=numpy.vstack([zdB[i,:],fitline] ) + legendlabels=['Data','Fitting'] + axes.pmultilineyaxis(x, y, + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, + xlabel=xlabel, ylabel=ylabel, title=title, + legendlabels=legendlabels, marker=None, + linestyle='solid', grid='both') + + self.draw() + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime) + + +class EWDriftsPlot(Figure): + + __isConfig = None + __nsubplots = None + + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'drift' + + def __init__(self): + + self.timerange = 2*60*60 + self.isConfig = False + self.__nsubplots = 1 + + self.WIDTH = 800 + self.HEIGHT = 150 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.counter_imagwr = 0 + + self.PLOT_CODE = EWDRIFT_CODE + + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + self.tmin = None + self.tmax = None + + self.xmin = None + self.xmax = None + + self.figfile = None + + def getSubplots(self): + + ncol = 1 + nrow = self.nplots + + return nrow, ncol + + def setup(self, id, nplots, wintitle, showprofile=True, show=True): + + self.__showprofile = showprofile + self.nplots = nplots + + ncolspan = 1 + colspan = 1 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH + self.WIDTHPROF, + heightplot = self.HEIGHT + self.HEIGHTPROF, + show=show) + + nrow, ncol = self.getSubplots() + + counter = 0 + for y in range(nrow): + if counter >= self.nplots: + break + + self.addAxes(nrow, ncol*ncolspan, y, 0, colspan, 1) + counter += 1 + + def run(self, dataOut, id, wintitle="", channelList=None, + xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, + zmaxVertical = None, zminVertical = None, zmaxZonal = None, zminZonal = None, + timerange=None, SNRthresh = -numpy.inf, SNRmin = None, SNRmax = None, SNR_1 = False, + save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + zmin : None, + zmax : None + """ + + if timerange is not None: + self.timerange = timerange + + tmin = None + tmax = None + + x = dataOut.getTimeRange1(dataOut.outputInterval) +# y = dataOut.heightList + y = dataOut.heightList + + z = dataOut.data_output + nplots = z.shape[0] #Number of wind dimensions estimated + nplotsw = nplots + + #If there is a SNR function defined + if dataOut.data_SNR is not None: + nplots += 1 + SNR = dataOut.data_SNR + + if SNR_1: + SNR += 1 + + SNRavg = numpy.average(SNR, axis=0) + + SNRdB = 10*numpy.log10(SNR) + SNRavgdB = 10*numpy.log10(SNRavg) + + ind = numpy.where(SNRavg < 10**(SNRthresh/10))[0] + + for i in range(nplotsw): + z[i,ind] = numpy.nan + + + showprofile = False +# thisDatetime = dataOut.datatime + thisDatetime = datetime.datetime.utcfromtimestamp(x[1]) + title = wintitle + " EW Drifts" + xlabel = "" + ylabel = "Height (Km)" + + if not self.isConfig: + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange) + + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + + if zmaxZonal == None: zmaxZonal = numpy.nanmax(abs(z[0,:])) + if zminZonal == None: zminZonal = -zmaxZonal + if zmaxVertical == None: zmaxVertical = numpy.nanmax(abs(z[1,:])) + if zminVertical == None: zminVertical = -zmaxVertical + + if dataOut.data_SNR is not None: + if SNRmin == None: SNRmin = numpy.nanmin(SNRavgdB) + if SNRmax == None: SNRmax = numpy.nanmax(SNRavgdB) + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.name = thisDatetime.strftime("%Y%m%d_%H%M%S") + self.isConfig = True + + + self.setWinTitle(title) + + if ((self.xmax - x[1]) < (x[1]-x[0])): + x[1] = self.xmax + + strWind = ['Zonal','Vertical'] + strCb = 'Velocity (m/s)' + zmaxVector = [zmaxZonal, zmaxVertical] + zminVector = [zminZonal, zminVertical] + + for i in range(nplotsw): + + title = "%s Drifts: %s" %(strWind[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + axes = self.axesList[i*self.__nsubplots] + + z1 = z[i,:].reshape((1,-1)) + + axes.pcolorbuffer(x, y, z1, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zminVector[i], zmax=zmaxVector[i], + xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True, + ticksize=9, cblabel=strCb, cbsize="1%", colormap="RdBu_r") + + if dataOut.data_SNR is not None: + i += 1 + if SNR_1: + title = "Signal Noise Ratio + 1 (SNR+1): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + else: + title = "Signal Noise Ratio (SNR): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + axes = self.axesList[i*self.__nsubplots] + SNRavgdB = SNRavgdB.reshape((1,-1)) + + axes.pcolorbuffer(x, y, SNRavgdB, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax, + xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True, + ticksize=9, cblabel='', cbsize="1%", colormap="jet") + + self.draw() + + if x[1] >= self.axesList[0].xmax: + self.counter_imagwr = wr_period + self.isConfig = False + self.figfile = None + + + + +class PhasePlot(Figure): + + __isConfig = None + __nsubplots = None + + PREFIX = 'mphase' + + def __init__(self): + + self.timerange = 24*60*60 + self.isConfig = False + self.__nsubplots = 1 + self.counter_imagwr = 0 + self.WIDTH = 600 + self.HEIGHT = 300 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.xdata = None + self.ydata = None + + self.PLOT_CODE = MPHASE_CODE + + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + + + self.filename_phase = None + + self.figfile = None + + def getSubplots(self): + + ncol = 1 + nrow = 1 + + return nrow, ncol + + def setup(self, id, nplots, wintitle, showprofile=True, show=True): + + self.__showprofile = showprofile + self.nplots = nplots + + ncolspan = 7 + colspan = 6 + self.__nsubplots = 2 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH+self.WIDTHPROF, + heightplot = self.HEIGHT+self.HEIGHTPROF, + show=show) + + nrow, ncol = self.getSubplots() + + self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1) + + + def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True', + xmin=None, xmax=None, ymin=None, ymax=None, + timerange=None, + save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): + + + tmin = None + tmax = None + x = dataOut.getTimeRange1(dataOut.outputInterval) + y = dataOut.getHeiRange() + + + #thisDatetime = dataOut.datatime + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime) + title = wintitle + " Phase of Beacon Signal" # : %s" %(thisDatetime.strftime("%d-%b-%Y")) + xlabel = "Local Time" + ylabel = "Phase" + + + #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList))) + phase_beacon = dataOut.data_output + update_figfile = False + + if not self.isConfig: + + self.nplots = phase_beacon.size + + self.setup(id=id, + nplots=self.nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + if timerange is not None: + self.timerange = timerange + + self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange) + + if ymin == None: ymin = numpy.nanmin(phase_beacon) - 10.0 + if ymax == None: ymax = numpy.nanmax(phase_beacon) + 10.0 + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.name = thisDatetime.strftime("%Y%m%d_%H%M%S") + self.isConfig = True + self.figfile = figfile + self.xdata = numpy.array([]) + self.ydata = numpy.array([]) + + #open file beacon phase + path = '%s%03d' %(self.PREFIX, self.id) + beacon_file = os.path.join(path,'%s.txt'%self.name) + self.filename_phase = os.path.join(figpath,beacon_file) + update_figfile = True + + + #store data beacon phase + #self.save_data(self.filename_phase, phase_beacon, thisDatetime) + + self.setWinTitle(title) + + + title = "Phase Offset %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + + legendlabels = ["phase %d"%(chan) for chan in numpy.arange(self.nplots)] + + axes = self.axesList[0] + + self.xdata = numpy.hstack((self.xdata, x[0:1])) + + if len(self.ydata)==0: + self.ydata = phase_beacon.reshape(-1,1) + else: + self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1))) + + + axes.pmultilineyaxis(x=self.xdata, y=self.ydata, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, + xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid", + XAxisAsTime=True, grid='both' + ) + + self.draw() + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime, + update_figfile=update_figfile) + + if dataOut.ltctime + dataOut.outputInterval >= self.xmax: + self.counter_imagwr = wr_period + self.isConfig = False + update_figfile = True + + + +class NSMeteorDetection1Plot(Figure): + + isConfig = None + __nsubplots = None + + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'nsm' + + zminList = None + zmaxList = None + cmapList = None + titleList = None + nPairs = None + nChannels = None + nParam = None + + def __init__(self): + + self.isConfig = False + self.__nsubplots = 1 + + self.WIDTH = 750 + self.HEIGHT = 250 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.counter_imagwr = 0 + + self.PLOT_CODE = SPEC_CODE + + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + + self.__xfilter_ena = False + self.__yfilter_ena = False + + def getSubplots(self): + + ncol = 3 + nrow = int(numpy.ceil(self.nplots/3.0)) + + return nrow, ncol + + def setup(self, id, nplots, wintitle, show=True): + + self.nplots = nplots + + ncolspan = 1 + colspan = 1 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH + self.WIDTHPROF, + heightplot = self.HEIGHT + self.HEIGHTPROF, + show=show) + + nrow, ncol = self.getSubplots() + + counter = 0 + for y in range(nrow): + for x in range(ncol): + + if counter >= self.nplots: + break + + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + counter += 1 + + def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True, + xmin=None, xmax=None, ymin=None, ymax=None, SNRmin=None, SNRmax=None, + vmin=None, vmax=None, wmin=None, wmax=None, mode = 'SA', + save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False, + xaxis="frequency"): + + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + zmin : None, + zmax : None + """ + #SEPARAR EN DOS PLOTS + nParam = dataOut.data_param.shape[1] - 3 + + utctime = dataOut.data_param[0,0] + tmet = dataOut.data_param[:,1].astype(int) + hmet = dataOut.data_param[:,2].astype(int) + + x = dataOut.abscissaList + y = dataOut.heightList + + z = numpy.zeros((nParam, y.size, x.size - 1)) + z[:,:] = numpy.nan + z[:,hmet,tmet] = dataOut.data_param[:,3:].T + z[0,:,:] = 10*numpy.log10(z[0,:,:]) + + xlabel = "Time (s)" + ylabel = "Range (km)" + + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime) + + if not self.isConfig: + + nplots = nParam + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + show=show) + + if xmin is None: xmin = numpy.nanmin(x) + if xmax is None: xmax = numpy.nanmax(x) + if ymin is None: ymin = numpy.nanmin(y) + if ymax is None: ymax = numpy.nanmax(y) + if SNRmin is None: SNRmin = numpy.nanmin(z[0,:]) + if SNRmax is None: SNRmax = numpy.nanmax(z[0,:]) + if vmax is None: vmax = numpy.nanmax(numpy.abs(z[1,:])) + if vmin is None: vmin = -vmax + if wmin is None: wmin = 0 + if wmax is None: wmax = 50 + + pairsList = dataOut.groupList + self.nPairs = len(dataOut.groupList) + + zminList = [SNRmin, vmin, cmin] + [pmin]*self.nPairs + zmaxList = [SNRmax, vmax, cmax] + [pmax]*self.nPairs + titleList = ["SNR","Radial Velocity","Coherence"] + cmapList = ["jet","RdBu_r","jet"] + + for i in range(self.nPairs): + strAux1 = "Phase Difference "+ str(pairsList[i][0]) + str(pairsList[i][1]) + titleList = titleList + [strAux1] + cmapList = cmapList + ["RdBu_r"] + + self.zminList = zminList + self.zmaxList = zmaxList + self.cmapList = cmapList + self.titleList = titleList + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.isConfig = True + + str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S")) + + for i in range(nParam): + title = self.titleList[i] + ": " +str_datetime + axes = self.axesList[i] + axes.pcolor(x, y, z[i,:].T, + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=self.zminList[i], zmax=self.zmaxList[i], + xlabel=xlabel, ylabel=ylabel, title=title, colormap=self.cmapList[i],ticksize=9, cblabel='') + self.draw() + + if figfile == None: + str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S") + name = str_datetime + if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)): + name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith) + figfile = self.getFilename(name) + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime) + + +class NSMeteorDetection2Plot(Figure): + + isConfig = None + __nsubplots = None + + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'nsm' + + zminList = None + zmaxList = None + cmapList = None + titleList = None + nPairs = None + nChannels = None + nParam = None + + def __init__(self): + + self.isConfig = False + self.__nsubplots = 1 + + self.WIDTH = 750 + self.HEIGHT = 250 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.counter_imagwr = 0 + + self.PLOT_CODE = SPEC_CODE + + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + + self.__xfilter_ena = False + self.__yfilter_ena = False + + def getSubplots(self): + + ncol = 3 + nrow = int(numpy.ceil(self.nplots/3.0)) + + return nrow, ncol + + def setup(self, id, nplots, wintitle, show=True): + + self.nplots = nplots + + ncolspan = 1 + colspan = 1 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH + self.WIDTHPROF, + heightplot = self.HEIGHT + self.HEIGHTPROF, + show=show) + + nrow, ncol = self.getSubplots() + + counter = 0 + for y in range(nrow): + for x in range(ncol): + + if counter >= self.nplots: + break + + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + counter += 1 + + def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True, + xmin=None, xmax=None, ymin=None, ymax=None, SNRmin=None, SNRmax=None, + vmin=None, vmax=None, wmin=None, wmax=None, mode = 'SA', + save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False, + xaxis="frequency"): + + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + zmin : None, + zmax : None + """ + #Rebuild matrix + utctime = dataOut.data_param[0,0] + cmet = dataOut.data_param[:,1].astype(int) + tmet = dataOut.data_param[:,2].astype(int) + hmet = dataOut.data_param[:,3].astype(int) + + nParam = 3 + nChan = len(dataOut.groupList) + x = dataOut.abscissaList + y = dataOut.heightList + + z = numpy.full((nChan, nParam, y.size, x.size - 1),numpy.nan) + z[cmet,:,hmet,tmet] = dataOut.data_param[:,4:] + z[:,0,:,:] = 10*numpy.log10(z[:,0,:,:]) #logarithmic scale + z = numpy.reshape(z, (nChan*nParam, y.size, x.size-1)) + + xlabel = "Time (s)" + ylabel = "Range (km)" + + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime) + + if not self.isConfig: + + nplots = nParam*nChan + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + show=show) + + if xmin is None: xmin = numpy.nanmin(x) + if xmax is None: xmax = numpy.nanmax(x) + if ymin is None: ymin = numpy.nanmin(y) + if ymax is None: ymax = numpy.nanmax(y) + if SNRmin is None: SNRmin = numpy.nanmin(z[0,:]) + if SNRmax is None: SNRmax = numpy.nanmax(z[0,:]) + if vmax is None: vmax = numpy.nanmax(numpy.abs(z[1,:])) + if vmin is None: vmin = -vmax + if wmin is None: wmin = 0 + if wmax is None: wmax = 50 + + self.nChannels = nChan + + zminList = [] + zmaxList = [] + titleList = [] + cmapList = [] + for i in range(self.nChannels): + strAux1 = "SNR Channel "+ str(i) + strAux2 = "Radial Velocity Channel "+ str(i) + strAux3 = "Spectral Width Channel "+ str(i) + + titleList = titleList + [strAux1,strAux2,strAux3] + cmapList = cmapList + ["jet","RdBu_r","jet"] + zminList = zminList + [SNRmin,vmin,wmin] + zmaxList = zmaxList + [SNRmax,vmax,wmax] + + self.zminList = zminList + self.zmaxList = zmaxList + self.cmapList = cmapList + self.titleList = titleList + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.isConfig = True + + str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S")) + + for i in range(self.nplots): + title = self.titleList[i] + ": " +str_datetime + axes = self.axesList[i] + axes.pcolor(x, y, z[i,:].T, + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=self.zminList[i], zmax=self.zmaxList[i], + xlabel=xlabel, ylabel=ylabel, title=title, colormap=self.cmapList[i],ticksize=9, cblabel='') + self.draw() + + if figfile == None: + str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S") + name = str_datetime + if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)): + name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith) + figfile = self.getFilename(name) + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime) + + diff --git a/schainpy/model/graphics/.svn/text-base/jroplot_parameters.pyc.svn-base b/schainpy/model/graphics/.svn/text-base/jroplot_parameters.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..732018e36a9159ec7e9879493fd6920bce80be7f GIT binary patch literal 49274 zc%1E>33OZ8dEf7Q009C7_XUJRQ4qyd8%1d}Gaiqd(adO;c!nc`%4kORn1%?D0!4xp z@F-DJ;Ka7ZN!&DXmZm37;?uNodrsCSO`1K9n=Xm#q;8tJr>D)*Hf@@8$!SkppOdZW z{r|sv-+KT-iJF;6V_On=d2!!%-(B9j-w*%$-N^s$Og{YGpM7OXnST-e`-J|jKISM@ z&_9k^Q|gi*chn`v#$9#EW!zP35w#vwm!fLDOoIjHrW|aGsI|DdfLIhqthcL6 z?Rra_Dn`|^K2=P;q0}vkjYg7CD)NWPix2XeuYL6-m+SDOGwO19=Hg(uf?L*NlOlNc%mi}D-o1aFJ zdNCb5Q(D=o6ul%iRddDsnpavcdcFL3K}Vl2Kew?}$>qx{#c2lzAvhvYoMb*f?{(T+J@)X8?N^x>g_vqP*kj?gt`=A7-iVTFoqht6h|&~mUUg|+CxMaauPqf z!rsso+kyHjFj0q1KSf>8ZDuRtvBn+Z!4J0Tx*S%z7IF*INqZ}smGvdu7k*v+`xLUi ziLFZ2lv;FE<_flQ8Du+ z z{^<+PvF4vU_x!WZUGNe%@qF&3XV?y813z}@k4qa{Wv^ISEUo8PZdAM!D*L4u&&^+0 zSbXZGr_b>O=U;f~f_#c1>l@{w7f1dsoL{_n?s?|$+$-m051e4(Yo1*66WZ+w&cC!E z4GSl!7T1=idAkUzU!#NBEBd}>ixm8;dw{8DkYx^yL9Dpxi(yxFR5s(#Am z&Dr&hLUC<&rIO#gQd+9cu2wcs5R04nN?teeVx@Xw^CmC9xL7KebXoP`Qp32Qn{X2N zmH)1dvw=j+FB`~NX&|~^tg=z8M$|2~l(ha+cTD5ask+S!)EqTvH|f3gkE51dUE}OZ zE5G)u`1jwxYDN0b|NN@ysBN63vd8)>Z>{S*vw*HuJXU0xwaZiFhHUYbmp0ZUQrWn1 zPs$Nbft8}SU|QQat`=iajyU_>B}6;*Z-*_ohjdZaq}M1Gh3#VX7{fTWRvt&WAtizo z)7@NE_DeO2GDKgCpwAIxNNC5i@dNtg?W)daL_Mjt zKdE$kuC=2IpMLEVs@|ctzm7=>N!nKRl&U3pMn_$3Q7Y4Z|JsC z^45y%nKyLe6;uej_LX93<%-9TY(iHyZpb4Awc=%VJUg(%W@Tf!v{uaRNBhDl*@KrV z#k^OPw?_`A&LK62^W;#?xl#L&s^Hzh$3ebOIJ;e}PIuatnmdSqC(dH`4wEN)$-_u& zH?3K>(lSqD;<*DjZUno;gU1x#Pd6EE-;-wF#%GncwRseg6aKR!=Ggx!w_Arj`hVQ* z)9L+AzfOs|<2ruS^_V|Y--%hNR3t2+Q0DaSe%oDsLsyt?>8rXxJJAmoYWq}W4i%5L zlEdeYa;kIaFV8-Q9m?!qI(F4nmFKxnRMq#Z@_Utj!05>Kli1#5mg)E9&PGs zTvcvhaG<-^N2RCjNB5Dfy4&bIbzjgw&b61-MI`IKbAa2Esy@m{hpHcBB!#03d{KVP z4I;}Cm8l(2gY~TPI@M|y!){f};=DCU>`}LLr`)y{|xeULwF$QXG8{1=SeY&`Z0`mYm;hq0%Kh?0f`SFu3wNt_2U@sN)xOd(`{!${v1b38q#%y^GzZRktsEh zsh?1_6KZuD#ivW5b{HF5H$**tMxCTt_QNdW49jvK%WOZ(MVEzc1Nz2iRAChNQaGpz zx=kKZ1>Kw?9S$-#!;8ckPhX#9PIRl8MNSHb(Z~wAJ?a~rR0VyeX|`)O%9q1YRr!M3 zd^>u3+TPMJ)C%wZAcp?PVwzbDXMIE!W{_Q-Ih|dEN6>Z)x=|j}mrAhZ9ap9t(Tv$r zZt3^oNt@l1HoLJy@wT3*W+$pu3@avHot;>pohZnM=N_AQ@v(`8YPuow zk7XwwI&o^b@T87ZnOD@giR8B#xoJ~w+LYIA3QCuw^zF6$<>DHnHzkU^$Uv=~v8Aik z((A=i!XMFG=6<i`R8=U)Fmfiz}5!&(DHdcQvmYx$M=4V|9P0WstpdllWf2p)QHZ&LQp zmkY&hHjs`Wk)LswvPxf8Zh%K0)Hl#S-MbFfr% z{RjpS3@T&yU8rmoWgK1fE|$s{(7tk$wqGz?Rj;zlY_+rF6{{!#8QJ3ko6@$DeuAo+$lpXZE-%C#+IE~;T z1b8Xr9!Bs80-P-OEQ053m(G1Pg7?}?SBn*08H_G(tQB+=8Q#*#<-EDm&3v`0hy4X< z$=>GTjbe!#irbruOM0l!8mVqwUi1@q7>E2DReq=#K$d&S@1)W$<;rYp>`J*~%CNH6 zS)2LmE4dHYs(oE|#WqRQvAAtLg(q__;LyhqJc{65I0BEotxdG0MbrPJD*3dOJbRTz zzpX`0r82T!)HYMXUI3MKPi!LGWM!-TBChhixYkfY+dDC*&uP;(P)b`wF{jh%c2dp( z;VSN=bI2KVI^BL)N0AXH3Cqcixd~USC;Zn(sy?UjcL=|(PigdTr#s|~Iit>ibJQ8v zSL}30oN2vfSf6=Vf5v%6oLM*NpEu^rPj}hQvABo^v$)9izqqJxcWX_5l*bizU`G*S zx6`)1^SN`+JpW1#FAmzhxdH<8Ug^{yvt@oSNamSKJ+-HuP9W$u0&Z z9zwH1P&yh~R*r3wxOL&ZufBLzXlV}b5^0SsUIE0XeB$1dmWBrZc@;*c(RT(i%^^d4 zkLS<{_`nPRDWMVZ(LE_8JQ03Z-GPRFle!}fRVc0k3jpmmV%jXqsm*{-5KtkUx=RIY zGY+E!*w zAv_DKgn|jvz9l3e?>)999E(`cS04slk(&7!t6n$!Og&?JPR7uhTWk=S`aZ&#eZdjj zeLo4Df0C%Ajx?sWN$LT>J&!OE$YBsP?|?;lQ4_AXq;hSY~2>03$uBHpob?gOLSnG=$oyjiu{H0MW4HAox}7i14y89x!6q7|7ZfQPN?eq;a66LI(V+uwUJB zr4kPKglCjAEJ+&HK^m3-4FmJZlKC7$whLpROSe?qF^z|1jjv3mBYG!+hF-j(NKisE zV2C;~x+-6@bg4&NsmrLTE2gks`L#A42@eR8{CkHIqC%DJrSYDc~!5tQOQ27{}6Iz_1i70UvEi$X!baQWOjaQ{c^FA-B`{Ruj5O!$FdV= zPMlm$Hkov}cjNA9N8rqSJA}+zTD!h^D>mWR;&sNCZ^<9oyrRtaew!s4k!!+Gav#LT zMHL=;iY-DTn?pxf+8qBI0P#X;on|7A=l6B32A8>IWxrfTWnus2Ql;v_^c0JyhyWw8 z+&3y?Pi-$=-dbKR3ahGK$!`iI+1yymS90t2c1fnJhCy@&I|j?V7ID&1e}qtO9G&<) zfw}Z7gYy7PzSS?<-9SQa0|88k+%*Ih1XTq1jxM)_;5vdEI48#T`AQ{!GibZKvm%)k znNhj$avl(_gC(WgtF$4G>G}EW>!tNA?@F+PwC4~(K=p3Vwc-M764J&$jNl^(KB^3s zC`$vpC&M6ExBm~9;8&U2)E{y(`d9yVd-dR_FES|RJS2scL1r4`|zcK*~tl?iejz)D6tMS1Jt_JURp|_#aSj#e#3rU5Q_ou>-_gv3}d?nj%Ad;PX8>@@EGu2R=X;&1g^90>soiN)r6-4iDe8Q1*N zAxO~b5&kz2e3w#T;)+M%eEbbtdy0o5RQA{5wuAAy$n`rc-`R-#tUP zr}*HnqFH2ZC-Ct>SS$poP*xBEpA?oJ;2=Q=C{~OM4%@c$FWM|Z&^2zvG7jTojJu*1 zf`zV4K5!#P8~@|5{9ve4WuYzbs|i*4W154muH136LEG+nhyfkYBy|oB6**IAj7U%L z+kMDurb9_nk~BjBKsO~OKZK`oy%%O2c1luH5#s$_N1@@|`oyiyDp;k{9>e21>YeIZ-7TxeCiFSC)@Aqm0oUB~4A0WVvvk|7pEFlB zTf5b@&+%*rSa$n}D|CdSCqza_engLSj9jAEBAJ8A%UWzBMSln>y0!y7(s5!Jd>A6I z(04a%{^E~rdc(RERz463@A5dXLm!AtVL+`!RDBNo1V2OkcnY;7qE37~&F5(nMTL(K z;S~5u^Wzz{{oleZ`?t`tq2rlDv(A{C%7j!<$cnUi3aAD$^@mL-Xs9KKrygcmoZ*=U z>W`?}!_*WVLX)aJLR}NN5MT~(5Imo$bxkF6~cQmtyJL)2# z>Q;Na6O2#&yEwtSFs*0Ghhfu{JM~lUG)TEqALUL%lsly_2p&q(aQ*hG3v6K;Px$J0hcVX!&UNSA?k(pEUdlOWA1G!r-%JgBhNcY$ zIeeEBd_6}6N_P6{ZNy6@8Ovhux)Wa!IS`i-=LBes1mfjl#Val4*IG%Zx*L*~kX9<# zd`(od$S5RF)m{}~v8+X6=Eid?AEKd+}RTgZ*|H!IC{k{&IC!c$fP&W!VNxBj9zgty#8}qCh%~ zphXEJ{4T`m(3s?IpNHc9dVY;2C?8O_$8xuCFf1+fvBm2~zk`0cXmvfh2(1PRQG@ho z`0CHz734esd_qL?RZn+Mx!IuBIsV@(?DJV%?sa84s1P<9dJz zv1bNx9=z;iLba(7#Ef zY70K4I`y8iZ7^cFK%e>B=^l1^^mg;#?RO721MXC$&pG9c>T4nw{W_&vA8|ydjO>7k z8J?*%Mnr|TFim}!h@P`MOuVl`pik*DUq-zkD-AGlUn1T;EGRMN3<4=S z?AZ^JF@6n`3}bwjj4@%#7N*bN_8DWl(Qwq-)BtSe4vEEl&X^F+m{8X~t}b4?ez&YK zVJqydgTy;CM2;Np8Ax1r1CZDfBicEKfflJjhJ@n6aLi|jD`1E*Rp~a3r5rOeaXn>t zqS4z#Fzb;M68*`B3mA%u>SL7}%Z$i_%*?|>;hBeHG~OMwCd@qi2-=Enc4p?`AvOwb z1x6h6XC8h?W*#QZY(t#?u$gcOusLoo---7H^7KEfhUpMlUc&^f302Mnn}cmGx7E5- zm7@pCT~I^9Y*W__B8eVlMLO^76g2#OKGn~GAM1o=-Az|!ki z27(Oe0*-itW+tOd0uz=9I;kURq+phr&S=~P*huMY%o1D5<{n!!zvmzu!v@IKdsxW5 zc5B?l){NcStFFae(>3=If4Y=s%~GBf;gm)I(Wq17lvL=e&bm4-kj@-ALOvz^x-$es z1?r84CN17_P3Fd1Os4ngB7&e}W7>4B%I>Y{9`K-n4CTAGDD%tFnu z@bkD>s1QDf^DTKfysKs{raO)fDlMU*0h|Cj z1P+`g4xAwlJVG3JlsNDhN#$|UXBC$@keDC!K*1*e-l1eK_xF{7Q`)ZITCB{=EA(zA zI*RfQgN`aj(IL@W7GrUtf{im8Wt8vkGX7|xX6sT-a~Iz>ewX`U1V4hHNxt^?>{w!M zBKM<+_ca#E!h8-HdFvF8Ux9LBqUCDTyY>1*HfrMl-UK=Cc$CB6uuntCWh|1-au`A1{X@ABTNK63cc4v2YPwIXK0YHloIYPoN zTd15(y(@zwCo=b2C~mW|?$8E^*odU`BLEQdGf4e3f?xD&k`?<8{k*Ihe6c z$jygn5ZmSc36g)=Z#AtnasNiCurLmFPb8N6HD$Um;oQArV_%Q4`A_3QX;^46cTkVS zQ%)u{3$D*e>EDB{PIEJQv_9zc=y7~#7M#f4^bsIxhJ+c4)x^&1ue+0z4e6t^&VX~! z5fX+RWSwFEb2gIn_YM=X`DwP(CNf5MG0i-|=VHH({hGMge!qHlC1jj?E2MP!9^*31 zWO~AyQDIzWky&bA3Kb*34BwvwH$T@v%wS!Tn4!14jRHKduH8jdZ#A_1Y zD0pjy_}O1qVSXmD?1&|4O%QE=W22wjGeyIO^JjA}F6?0%-#ZDWjYPhZVA{ixoie?K zd3r;4_FDEAA=CS0Sf=OuC2PNpU$P(EO}W?7FPUf=cHMJVzhvL0F1|_0-+`7L=}jyC z-pZ`Odr#}$gJw2qJJoG@9ejj|_z#7*Q~Za!#{+H3w$RgYWf+|{H{s7`D&z+2A$+%i zmN;c)e*&k<-Q3VdyeqgW22f>mHZy3?&_XSe^r4|2fxTVXrgaSsk2rc7P?c|NN;+bX z{cfRzM{v3U_{$PJlTejkU{mAkz^KY3xBrsJu~QjZCL}On6@B7w>^L#Pv^gq(dVqq8 zw2V*?c+4RVluOnf`3R>@4M6WCRf{fR-$?;_^s)xg&K$dPcUYiUKgEqbgmR|{_Pk!u zzf}P|{d6j3%K0>(25l-09as$VFLdvRS(2Z1YW*su|G-P(Q5FzxyGvDm+W{ARgpZdb zIcyRi4H`TfF`6fTCgsr`Gbu;?hszLsN{Ko#6@qaBHHJg}#V)$IuZ&U2HTxIa;?{k3 zYZI#bc6;n>D^&Mm_So4Fs?#O#MK>UkU$AGGGb9rG^x3Unv}cg5ed^j5$te$8dEmH} z2ToYjIB99)X|;MVGW}gke1~T=>*hU}S4Y<8q)gB{oJBC`Vz1vP4O?8yvIMSub434y$*bvR%szUWzAVNye-bm`{+RNP+W~&0 zvFDy3e$5cS?k9d7CVm|uemy|^dK%!|3qe?nv>!lN`S%Wmu)(lr{w_Hx5h@UF?l*2X zMrQiKddm?T%E1-&V7Gp}JKL0z>5WHsZ*) zj$>QUS)#&~qL=r)N}zWX4{b89n6gMZzaq{9J{1%D3kd!-f|n8e0|Xd^3xsXruYpMN zLrR79k-JGF?+&z1+FLPI&KrV?3Z~K_jr)8+yVcxD}7iQ=V+?|^}T1P_x&*Jeh(Mg z*GCd(cfpyPb>!;bM<#ou758PV&b@lTdOe=#BY6IE;K# zMi|+TGwE|AU5FuLKK>ndhJb&Os&f`jJD~T8Is4r~*QV}^Cf$8Jcd7{tlVdf3;U=Nk zToV~)=h>@blHb1k4uX3Nga5rgb3ZB*>|%#@ax~!#I_S9pBQaP9PS@B51*1g}0|{7xWJ8+WU6U*e@dZ@TsdqcSF5*|v(_CDLX|0b4gh*)qn$o5Osop}aC%-RjZx5SN_0_>6` zZB=LL5j*SJ>cw=^&({0-A>P8Dy*`L*EA*+s`T#G|&M*Pa0_G)&Nv^FR@eU-)cZ8V9 zJ&2F1{IW1pA40d&!$oBN&y5DMo(5S44^4BC27O0EfH$kXG~7K|nStlPwqe6T>lq$k zPQ1^4XcHH81OA5*wf$GHFhgyhbg~*3mq^oYZy>d@(!^lH26OwyW8Dy^8gpraTQ1E1 zfqE9=KIDBrJ}=XGo+QF|-e|)m9>4Y;=OWy|4K-bPfIBy*4pR#15CjejIX=YMn||tm zq>kac^VJLqrUO@PK*TXY#D~dj+c__P1kWMNhD~GjiX`UdV-bo;ql2sVM^NfL$}E2{ z8d`f|Dnx(d;k74xzWeAQa4yfQ?%$D?aeXjqAH86nMDsPemX;oTLlC zu^nW;&`)MHz`Gpe-3&3;Y0iTmrauFbm%4FB7EduP|6~Nh&E{_kj<8y%T3xGl1YQzl zSrGA}2d9aY{y_=ZPe{M#{P;>nTw^p?c;c4Z;aocz(Ldy7Gya_9BgAW+oZ8$4!iKL} zCX{y+JkdKwiQ-}9FTsGvYxRW(**Sw(bWuETYyI}Khq+*bnQJ`p(22R_?A7&T2q?8A5lz!~F}Q%^ zep%Q}MhP60uN7B{DKL+N78JpRrlN1Y?P8RAgnf*Nc^n zDtBMnC|A9F*{cSsLYYolx?IUuZjzpGT=9%q@IvrZ6OU%DzxW_@eTE5UR7O{|d-Ov4QdPRgtiHOYN!c~a@JPD9Dt3xI0jB9Amhywu5( z30z_!chip1WM=GNR>ocRnl5P5xT@l05XFBMypJENn@hU=ynuxSqK=(S`z-d6;xGFL z^ONcMRpw$jI3f39;-;)EA?G~1C5SAzO5w>|&9<**Vid>(eb;&VJY3{}L(o4}_YfYP z#}E`eQuRUaH{x_^L$WhseB(z_bpDpqzX`X~>7=*(A!o$R=&k!A;&88D8(C>Hw>Gh> z=lmfzrOzv&2ZKcPQ$(@TEJ8EEp5-wO25ZBt9j!G}F;-Hot^bv7?c zj&5!)6m@qiRNpBM`2Mdxb60ey1HK5$v?CGkJ`BYso7lOFPghFIO^cqwnj+}Iw9L10 z(bGHr6jRVM1oLDuJ+{rPgKDPAHm#c)3;ndKH?oEd`BP;JxVs0UKjY0jT-$qg-LDVI zJ^##wFEP#EuSCC+G=KjwAXE=r^X<^-?c3S*zx>_u{Xz6@-16-d<>6NFm99UV7H*~? z9P6a`Y#4EAMc@OSbd}#}XRW$+IZwxWC{ZBi{?2wt!8?3x3TYr;V z({^jS)hx=^9#^({oMa2#EH^cJ&+9bWK6A_@Ce3yjZ+IOx^-|-R+?HqZC%Vcpo8sLs zWhIk-qxdw%b+XeZU2}WK8^v|z=FMfz);@LZ(-haqV*KvVZbB)rSx;sveHLy&R?R0+DtP81hX9zkis z<(`f|seUtq(Nm44PiXWHOkbddkwMS;L?PG7#ahp*9pb=C!g{Ktc5`04Ox5 zNyw#)GHSq1P95B_oam#xI0RCUNNhhfNLD1Ji>1Kg!X(wu%Aycb9S)Y?q*UsLIMVa$ z_IMj|ihfN`bd`@p0eC{UiF+)|oYbb&mUn)fGkDqAA+HVJ>G3_>X)k49eQJ+)h|#Bi zhcjU(dlLe*CVU~7IAzqA#QSff&8#>(i3f-o4+>(OGLO}TX}mQaIL$Nv-tnrgz-b=! zTiJ6Lvoh}3=`rti%YDx8lyT+Y3O)Bj%6w1TW&FP_ z&b^%qs=z#K;gK%)O9-d|`^N|V6&gzj+uO1@fbpkTNqQZN)viy5$r6imoh%#yFTDz@Xtkgvq9%T54f z$vTql!BUdJPkZPmq23q*M6=6F@C%Af$!e5JxF1hB;hcl{Ij`@YY{zGp|||hFLoiSELo(LQVy46`FNfA+p6=xt~z$hucC> zD<)72_3A?{yiaz8T48yW6{@w+Rt0|H;)ZJp%xcnBwKveMW@05UIuJ&MR845HC9ZtF zS5;HefBuG=_YPh)gNN|#q1BW<+uif3dq$~#0(I;!y((hi22LgOM(Nc#gZh*sq1V;84=N|pR9%&T1V4B0)xRkc=WrMj^{tPEugg-ypCljG^4jBsJB| zhuJY-WpkX4&{DuMz<*OjchkhYGo+$NC`~&`A(Zj_A2S^)E!hIc_|}M7LgYlS_OxGH zd>CS^KVQXDEz74G78rc8m|wyogtP)_Ex)j#ZIvv%8}aSTJ$HR>8PV|g6D@p5;ek6* zoj7^AV4^3yZIAxqoTHKKUha5$|~M z!G9%RmIee<_MTa>zk*jX%yQL^*Ri&fqQ>2MROazOOPpwO+cZQ;Mx(o?KBq4-33(`PIt^5bcWrj$bM~u9&tJ&ySXvvc&5oFMe_@fiF|`}#&2)$5U=G^Iz!)N zM>fXzbQ2j_{xIc4WC27p-uVStP}5(Nwb2Wc@3$PTsEiHTK^wG#HfRTJ(2kH2qk}Sx z4w{}FoNv=X0fr7!3_BTiSBpN1@VMm*lQL&%WD z)&xcr@Mt~&a~8EMt435?_%o-RX~!I%g74VepUe}rwrrcVW!sD`>%WbB6ZSSD4bR%L zUdWbh@KyeYuAKrD_$u#hc)ofV(J!{H)jcnQh&e)gkXv};x4YK1evat&xTuZQ+wXWY z*zrCXvS)Sih8CZ1VZyqhSx8aaHt>us*!f1`xk$Qs44Us1cTPB>`${uzXn&$0;uFXwnU7P5Rt9{5B5%Jhf+TI_E8p>vqEaCV24EQ?%Mir2P^<)xc+l8)~T4%nvj zb^bz&t0H}XgAKFbqJl?}j9GC}89#g<F~+%U zhhVv&p-dpu=N?{`W2U%A!mO%jPHZC(Uo>CT4Yp--2)uHTh~uD=40`&^$tI7y~9r^Z_5$ye4^qk`S_|Yot>8#Nif<;FcNmf!%;c?0ZWbWVU((4)jbHgT68e0&&KBwd&``wgWFGycb8nAi5OMN-G1 zbitYZg;Y-vp!5--^wV)qFCF&`!f_8K-_25^hDl6O{nCSU;DP%d`S(s0dhop(u`gF6 z%%~wV|?7OGM!iXHc5K7?tZgQzyzEH}qWv!}%Z|$cxt`sZ!tz8V<{*YG* z!+N@eMeVRT3uz|Q9}`vP!tyNnV3`(j`dIevv>&Y;`%uTS)5#FZWHJ9bhpmfrDI`g+ zm+vrL%C&_l13KSNr1;t4oT;jJbF(NTbJ%z z4Er|0vm45OD~ritw*2*2I5%%|W08&RC}rpH_8K!QR)@0a{@2zn8`ir^i>=-{*CWXzz1CRgdfe>X7*r|E#1-K2Ki zyKuWxUuoPf_im?^Q3#I)t!1Lu)05b$FREG6ZUJY`^xFM z;tx3815P&>zZ*`MJL|O2vgDq0%nF7WjQDWw=X^Lv5a&}lK2gPI4y|gg_lkZrwquWI z(;kO+?9tY=$2gMe6Tt$ANDNQjq6h%~)#Ge8lV(LgA$6;Cz%slX<>n;ax6kajX3RwB zX=DcS0)Lw!bx}e#oTI}yZ#RcJp}37KM-8&u!;X*RoSa%CIUm@O^@zzd@Sa`K(CY-@ zgF43n*fajyN%g9eQQ;i}X0^j!B0iUh?>G@(gwr|#(B~3a{h@=b^xL%xeb6UcQ!cg+ z*sVV3b1kfsW2YNIpKN{39y{F#`ef^Md+ba@A?*NtviGO#xmxe-gFe~&-k#v!yWp3hOq54uv6^}a382#jmsZGYttu5b7XU*i#q>IIzc!` zrl@nzq*-q-+L_1I|kj9!Fdu7aNfge z`{!+09QKKx%$^#-y$aELSZ7lF@{cnSPTwD;+Dg27&u|V@xIW>-{PsjIBc~Ulw@*Hd za?<8Og77SziVM-(FPoc*-YY`%rhKC3lIVTB&D^IDy@vtdjPrR;9|gj@L83Pk`uMIe z(VK20dNUw;@3Q>v2xg8o5WS;&AbQ7y=(!Jw-j@W?Q-P^K6h*j4KZI`@>s9ILb3W&L zyrvMO3GoFRF}AiYNU|481@DT#EkyqAKjX_i?U?bd0KVKgN8LfI)=c*}IwReC#<2r> z>bywc8sQ$1&+^vVS^)S2?NJkUSA383fkVp|8_`feDQ?f<0$)djanJgKG@r=ja*ip2 z>Bsz$>zl)Hxdoi+0!swJ%Lp#o)4x5)E%yow!WQ!q$l4_&z2AZwSrQTraWBYiH`tZ4YP!Q*<*t+nD`!i{h;TZ)tX g;9|YU9r}f#?-}~-q2Cz#lc66Q`sYL6H}up0AL?LeiU0rr literal 0 Hc$@= self.nplots: + break + + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + if showprofile: + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1) + + counter += 1 + + def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True, + xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, + save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False, + xaxis="frequency", colormap='jet'): + + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + zmin : None, + zmax : None + """ + + if realtime: + if not(isRealtime(utcdatatime = dataOut.utctime)): + print 'Skipping this plot function' + return + + if channelList == None: + channelIndexList = dataOut.channelIndexList + else: + channelIndexList = [] + for channel in channelList: + if channel not in dataOut.channelList: + raise ValueError, "Channel %d is not in dataOut.channelList" %channel + channelIndexList.append(dataOut.channelList.index(channel)) + + factor = dataOut.normFactor + + if xaxis == "frequency": + x = dataOut.getFreqRange(1)/1000. + xlabel = "Frequency (kHz)" + + elif xaxis == "time": + x = dataOut.getAcfRange(1) + xlabel = "Time (ms)" + + else: + x = dataOut.getVelRange(1) + xlabel = "Velocity (m/s)" + + ylabel = "Range (Km)" + + y = dataOut.getHeiRange() + + z = dataOut.data_spc/factor + z = numpy.where(numpy.isfinite(z), z, numpy.NAN) + zdB = 10*numpy.log10(z) + + avg = numpy.average(z, axis=1) + avgdB = 10*numpy.log10(avg) + + noise = dataOut.getNoise()/factor + noisedB = 10*numpy.log10(noise) + + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) + title = wintitle + " Spectra" + if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)): + title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith) + + if not self.isConfig: + + nplots = len(channelIndexList) + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + if xmin == None: xmin = numpy.nanmin(x) + if xmax == None: xmax = numpy.nanmax(x) + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3 + if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3 + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.isConfig = True + + self.setWinTitle(title) + + for i in range(self.nplots): + index = channelIndexList[i] + str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S")) + title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[index], noisedB[index], str_datetime) + if len(dataOut.beam.codeList) != 0: + title = "Ch%d:%4.2fdB,%2.2f,%2.2f:%s" %(dataOut.channelList[index], noisedB[index], dataOut.beam.azimuthList[index], dataOut.beam.zenithList[index], str_datetime) + + axes = self.axesList[i*self.__nsubplots] + axes.pcolor(x, y, zdB[index,:,:], + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax, + xlabel=xlabel, ylabel=ylabel, title=title, colormap=colormap, + ticksize=9, cblabel='') + + if self.__showprofile: + axes = self.axesList[i*self.__nsubplots +1] + axes.pline(avgdB[index,:], y, + xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax, + xlabel='dB', ylabel='', title='', + ytick_visible=False, + grid='x') + + noiseline = numpy.repeat(noisedB[index], len(y)) + axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2) + + self.draw() + + if figfile == None: + str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S") + name = str_datetime + if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)): + name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith) + figfile = self.getFilename(name) + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime) + +class CrossSpectraPlot(Figure): + + isConfig = None + __nsubplots = None + + WIDTH = None + HEIGHT = None + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'cspc' + + def __init__(self): + + self.isConfig = False + self.__nsubplots = 4 + self.counter_imagwr = 0 + self.WIDTH = 250 + self.HEIGHT = 250 + self.WIDTHPROF = 0 + self.HEIGHTPROF = 0 + + self.PLOT_CODE = CROSS_CODE + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + + def getSubplots(self): + + ncol = 4 + nrow = self.nplots + + return nrow, ncol + + def setup(self, id, nplots, wintitle, showprofile=True, show=True): + + self.__showprofile = showprofile + self.nplots = nplots + + ncolspan = 1 + colspan = 1 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH + self.WIDTHPROF, + heightplot = self.HEIGHT + self.HEIGHTPROF, + show=True) + + nrow, ncol = self.getSubplots() + + counter = 0 + for y in range(nrow): + for x in range(ncol): + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + counter += 1 + + def run(self, dataOut, id, wintitle="", pairsList=None, + xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, + coh_min=None, coh_max=None, phase_min=None, phase_max=None, + save=False, figpath='./', figfile=None, ftp=False, wr_period=1, + power_cmap='jet', coherence_cmap='jet', phase_cmap='RdBu_r', show=True, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, + xaxis='frequency'): + + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + zmin : None, + zmax : None + """ + + if pairsList == None: + pairsIndexList = dataOut.pairsIndexList + else: + pairsIndexList = [] + for pair in pairsList: + if pair not in dataOut.pairsList: + raise ValueError, "Pair %s is not in dataOut.pairsList" %str(pair) + pairsIndexList.append(dataOut.pairsList.index(pair)) + + if not pairsIndexList: + return + + if len(pairsIndexList) > 4: + pairsIndexList = pairsIndexList[0:4] + + factor = dataOut.normFactor + x = dataOut.getVelRange(1) + y = dataOut.getHeiRange() + z = dataOut.data_spc[:,:,:]/factor + z = numpy.where(numpy.isfinite(z), z, numpy.NAN) + + noise = dataOut.noise/factor + + zdB = 10*numpy.log10(z) + noisedB = 10*numpy.log10(noise) + + if coh_min == None: + coh_min = 0.0 + if coh_max == None: + coh_max = 1.0 + + if phase_min == None: + phase_min = -180 + if phase_max == None: + phase_max = 180 + + #thisDatetime = dataOut.datatime + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) + title = wintitle + " Cross-Spectra: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S")) +# xlabel = "Velocity (m/s)" + ylabel = "Range (Km)" + + if xaxis == "frequency": + x = dataOut.getFreqRange(1)/1000. + xlabel = "Frequency (kHz)" + + elif xaxis == "time": + x = dataOut.getAcfRange(1) + xlabel = "Time (ms)" + + else: + x = dataOut.getVelRange(1) + xlabel = "Velocity (m/s)" + + if not self.isConfig: + + nplots = len(pairsIndexList) + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=False, + show=show) + + avg = numpy.abs(numpy.average(z, axis=1)) + avgdB = 10*numpy.log10(avg) + + if xmin == None: xmin = numpy.nanmin(x) + if xmax == None: xmax = numpy.nanmax(x) + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3 + if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3 + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.isConfig = True + + self.setWinTitle(title) + + for i in range(self.nplots): + pair = dataOut.pairsList[pairsIndexList[i]] + + chan_index0 = dataOut.channelList.index(pair[0]) + chan_index1 = dataOut.channelList.index(pair[1]) + + str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S")) + title = "Ch%d: %4.2fdB: %s" %(pair[0], noisedB[chan_index0], str_datetime) + zdB = 10.*numpy.log10(dataOut.data_spc[chan_index0,:,:]/factor) + axes0 = self.axesList[i*self.__nsubplots] + axes0.pcolor(x, y, zdB, + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax, + xlabel=xlabel, ylabel=ylabel, title=title, + ticksize=9, colormap=power_cmap, cblabel='') + + title = "Ch%d: %4.2fdB: %s" %(pair[1], noisedB[chan_index1], str_datetime) + zdB = 10.*numpy.log10(dataOut.data_spc[chan_index1,:,:]/factor) + axes0 = self.axesList[i*self.__nsubplots+1] + axes0.pcolor(x, y, zdB, + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax, + xlabel=xlabel, ylabel=ylabel, title=title, + ticksize=9, colormap=power_cmap, cblabel='') + + coherenceComplex = dataOut.data_cspc[pairsIndexList[i],:,:]/numpy.sqrt(dataOut.data_spc[chan_index0,:,:]*dataOut.data_spc[chan_index1,:,:]) + coherence = numpy.abs(coherenceComplex) +# phase = numpy.arctan(-1*coherenceComplex.imag/coherenceComplex.real)*180/numpy.pi + phase = numpy.arctan2(coherenceComplex.imag, coherenceComplex.real)*180/numpy.pi + + title = "Coherence Ch%d * Ch%d" %(pair[0], pair[1]) + axes0 = self.axesList[i*self.__nsubplots+2] + axes0.pcolor(x, y, coherence, + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=coh_min, zmax=coh_max, + xlabel=xlabel, ylabel=ylabel, title=title, + ticksize=9, colormap=coherence_cmap, cblabel='') + + title = "Phase Ch%d * Ch%d" %(pair[0], pair[1]) + axes0 = self.axesList[i*self.__nsubplots+3] + axes0.pcolor(x, y, phase, + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=phase_min, zmax=phase_max, + xlabel=xlabel, ylabel=ylabel, title=title, + ticksize=9, colormap=phase_cmap, cblabel='') + + + + self.draw() + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime) + + +class RTIPlot(Figure): + + __isConfig = None + __nsubplots = None + + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'rti' + + def __init__(self): + + self.timerange = None + self.isConfig = False + self.__nsubplots = 1 + + self.WIDTH = 800 + self.HEIGHT = 180 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.counter_imagwr = 0 + + self.PLOT_CODE = RTI_CODE + + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + self.tmin = None + self.tmax = None + + self.xmin = None + self.xmax = None + + self.figfile = None + + def getSubplots(self): + + ncol = 1 + nrow = self.nplots + + return nrow, ncol + + def setup(self, id, nplots, wintitle, showprofile=True, show=True): + + self.__showprofile = showprofile + self.nplots = nplots + + ncolspan = 1 + colspan = 1 + if showprofile: + ncolspan = 7 + colspan = 6 + self.__nsubplots = 2 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH + self.WIDTHPROF, + heightplot = self.HEIGHT + self.HEIGHTPROF, + show=show) + + nrow, ncol = self.getSubplots() + + counter = 0 + for y in range(nrow): + for x in range(ncol): + + if counter >= self.nplots: + break + + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + if showprofile: + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1) + + counter += 1 + + def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True', + xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, + timerange=None, colormap='jet', + save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): + + """ + + Input: + dataOut : + id : + wintitle : + channelList : + showProfile : + xmin : None, + xmax : None, + ymin : None, + ymax : None, + zmin : None, + zmax : None + """ + + if not isTimeInHourRange(dataOut.datatime, xmin, xmax): + return + + if channelList == None: + channelIndexList = dataOut.channelIndexList + else: + channelIndexList = [] + for channel in channelList: + if channel not in dataOut.channelList: + raise ValueError, "Channel %d is not in dataOut.channelList" + channelIndexList.append(dataOut.channelList.index(channel)) + + if hasattr(dataOut, 'normFactor'): + factor = dataOut.normFactor + else: + factor = 1 + +# factor = dataOut.normFactor + x = dataOut.getTimeRange() + y = dataOut.getHeiRange() + +# z = dataOut.data_spc/factor +# z = numpy.where(numpy.isfinite(z), z, numpy.NAN) +# avg = numpy.average(z, axis=1) +# avgdB = 10.*numpy.log10(avg) + avgdB = dataOut.getPower() + + thisDatetime = dataOut.datatime +# thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) + title = wintitle + " RTI" #: %s" %(thisDatetime.strftime("%d-%b-%Y")) + xlabel = "" + ylabel = "Range (Km)" + + update_figfile = False + + if dataOut.ltctime >= self.xmax: + self.counter_imagwr = wr_period + self.isConfig = False + update_figfile = True + + if not self.isConfig: + + nplots = len(channelIndexList) + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + if timerange != None: + self.timerange = timerange + + self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange) + + noise = dataOut.noise/factor + noisedB = 10*numpy.log10(noise) + + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3 + if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3 + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.name = thisDatetime.strftime("%Y%m%d_%H%M%S") + self.isConfig = True + self.figfile = figfile + update_figfile = True + + self.setWinTitle(title) + + for i in range(self.nplots): + index = channelIndexList[i] + title = "Channel %d: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)): + title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith) + axes = self.axesList[i*self.__nsubplots] + zdB = avgdB[index].reshape((1,-1)) + axes.pcolorbuffer(x, y, zdB, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax, + xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True, + ticksize=9, cblabel='', cbsize="1%", colormap=colormap) + + if self.__showprofile: + axes = self.axesList[i*self.__nsubplots +1] + axes.pline(avgdB[index], y, + xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax, + xlabel='dB', ylabel='', title='', + ytick_visible=False, + grid='x') + + self.draw() + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime, + update_figfile=update_figfile) + +class CoherenceMap(Figure): + isConfig = None + __nsubplots = None + + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'cmap' + + def __init__(self): + self.timerange = 2*60*60 + self.isConfig = False + self.__nsubplots = 1 + + self.WIDTH = 800 + self.HEIGHT = 180 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.counter_imagwr = 0 + + self.PLOT_CODE = COH_CODE + + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + self.counter_imagwr = 0 + + self.xmin = None + self.xmax = None + + def getSubplots(self): + ncol = 1 + nrow = self.nplots*2 + + return nrow, ncol + + def setup(self, id, nplots, wintitle, showprofile=True, show=True): + self.__showprofile = showprofile + self.nplots = nplots + + ncolspan = 1 + colspan = 1 + if showprofile: + ncolspan = 7 + colspan = 6 + self.__nsubplots = 2 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH + self.WIDTHPROF, + heightplot = self.HEIGHT + self.HEIGHTPROF, + show=True) + + nrow, ncol = self.getSubplots() + + for y in range(nrow): + for x in range(ncol): + + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + if showprofile: + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1) + + def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True', + xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, + timerange=None, phase_min=None, phase_max=None, + save=False, figpath='./', figfile=None, ftp=False, wr_period=1, + coherence_cmap='jet', phase_cmap='RdBu_r', show=True, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): + + if not isTimeInHourRange(dataOut.datatime, xmin, xmax): + return + + if pairsList == None: + pairsIndexList = dataOut.pairsIndexList + else: + pairsIndexList = [] + for pair in pairsList: + if pair not in dataOut.pairsList: + raise ValueError, "Pair %s is not in dataOut.pairsList" %(pair) + pairsIndexList.append(dataOut.pairsList.index(pair)) + + if pairsIndexList == []: + return + + if len(pairsIndexList) > 4: + pairsIndexList = pairsIndexList[0:4] + + if phase_min == None: + phase_min = -180 + if phase_max == None: + phase_max = 180 + + x = dataOut.getTimeRange() + y = dataOut.getHeiRange() + + thisDatetime = dataOut.datatime + + title = wintitle + " CoherenceMap" #: %s" %(thisDatetime.strftime("%d-%b-%Y")) + xlabel = "" + ylabel = "Range (Km)" + update_figfile = False + + if not self.isConfig: + nplots = len(pairsIndexList) + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + if timerange != None: + self.timerange = timerange + + self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange) + + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + if zmin == None: zmin = 0. + if zmax == None: zmax = 1. + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.name = thisDatetime.strftime("%Y%m%d_%H%M%S") + + self.isConfig = True + update_figfile = True + + self.setWinTitle(title) + + for i in range(self.nplots): + + pair = dataOut.pairsList[pairsIndexList[i]] + + ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i],:,:],axis=0) + powa = numpy.average(dataOut.data_spc[pair[0],:,:],axis=0) + powb = numpy.average(dataOut.data_spc[pair[1],:,:],axis=0) + + + avgcoherenceComplex = ccf/numpy.sqrt(powa*powb) + coherence = numpy.abs(avgcoherenceComplex) + + z = coherence.reshape((1,-1)) + + counter = 0 + + title = "Coherence Ch%d * Ch%d: %s" %(pair[0], pair[1], thisDatetime.strftime("%d-%b-%Y %H:%M:%S")) + axes = self.axesList[i*self.__nsubplots*2] + axes.pcolorbuffer(x, y, z, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax, + xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True, + ticksize=9, cblabel='', colormap=coherence_cmap, cbsize="1%") + + if self.__showprofile: + counter += 1 + axes = self.axesList[i*self.__nsubplots*2 + counter] + axes.pline(coherence, y, + xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax, + xlabel='', ylabel='', title='', ticksize=7, + ytick_visible=False, nxticks=5, + grid='x') + + counter += 1 + + phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi + + z = phase.reshape((1,-1)) + + title = "Phase Ch%d * Ch%d: %s" %(pair[0], pair[1], thisDatetime.strftime("%d-%b-%Y %H:%M:%S")) + axes = self.axesList[i*self.__nsubplots*2 + counter] + axes.pcolorbuffer(x, y, z, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=phase_min, zmax=phase_max, + xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True, + ticksize=9, cblabel='', colormap=phase_cmap, cbsize="1%") + + if self.__showprofile: + counter += 1 + axes = self.axesList[i*self.__nsubplots*2 + counter] + axes.pline(phase, y, + xmin=phase_min, xmax=phase_max, ymin=ymin, ymax=ymax, + xlabel='', ylabel='', title='', ticksize=7, + ytick_visible=False, nxticks=4, + grid='x') + + self.draw() + + if dataOut.ltctime >= self.xmax: + self.counter_imagwr = wr_period + self.isConfig = False + update_figfile = True + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime, + update_figfile=update_figfile) + +class PowerProfilePlot(Figure): + + isConfig = None + __nsubplots = None + + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'spcprofile' + + def __init__(self): + self.isConfig = False + self.__nsubplots = 1 + + self.PLOT_CODE = POWER_CODE + + self.WIDTH = 300 + self.HEIGHT = 500 + self.counter_imagwr = 0 + + def getSubplots(self): + ncol = 1 + nrow = 1 + + return nrow, ncol + + def setup(self, id, nplots, wintitle, show): + + self.nplots = nplots + + ncolspan = 1 + colspan = 1 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH, + heightplot = self.HEIGHT, + show=show) + + nrow, ncol = self.getSubplots() + + counter = 0 + for y in range(nrow): + for x in range(ncol): + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + def run(self, dataOut, id, wintitle="", channelList=None, + xmin=None, xmax=None, ymin=None, ymax=None, + save=False, figpath='./', figfile=None, show=True, + ftp=False, wr_period=1, server=None, + folder=None, username=None, password=None): + + + if channelList == None: + channelIndexList = dataOut.channelIndexList + channelList = dataOut.channelList + else: + channelIndexList = [] + for channel in channelList: + if channel not in dataOut.channelList: + raise ValueError, "Channel %d is not in dataOut.channelList" + channelIndexList.append(dataOut.channelList.index(channel)) + + factor = dataOut.normFactor + + y = dataOut.getHeiRange() + + #for voltage + if dataOut.type == 'Voltage': + x = dataOut.data[channelIndexList,:] * numpy.conjugate(dataOut.data[channelIndexList,:]) + x = x.real + x = numpy.where(numpy.isfinite(x), x, numpy.NAN) + + #for spectra + if dataOut.type == 'Spectra': + x = dataOut.data_spc[channelIndexList,:,:]/factor + x = numpy.where(numpy.isfinite(x), x, numpy.NAN) + x = numpy.average(x, axis=1) + + + xdB = 10*numpy.log10(x) + + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) + title = wintitle + " Power Profile %s" %(thisDatetime.strftime("%d-%b-%Y")) + xlabel = "dB" + ylabel = "Range (Km)" + + if not self.isConfig: + + nplots = 1 + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + show=show) + + if ymin == None: ymin = numpy.nanmin(y) + if ymax == None: ymax = numpy.nanmax(y) + if xmin == None: xmin = numpy.nanmin(xdB)*0.9 + if xmax == None: xmax = numpy.nanmax(xdB)*1.1 + + self.isConfig = True + + self.setWinTitle(title) + + title = "Power Profile: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S")) + axes = self.axesList[0] + + legendlabels = ["channel %d"%x for x in channelList] + axes.pmultiline(xdB, y, + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, + xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, + ytick_visible=True, nxticks=5, + grid='x') + + self.draw() + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime) + +class SpectraCutPlot(Figure): + + isConfig = None + __nsubplots = None + + WIDTHPROF = None + HEIGHTPROF = None + PREFIX = 'spc_cut' + + def __init__(self): + self.isConfig = False + self.__nsubplots = 1 + + self.PLOT_CODE = POWER_CODE + + self.WIDTH = 700 + self.HEIGHT = 500 + self.counter_imagwr = 0 + + def getSubplots(self): + ncol = 1 + nrow = 1 + + return nrow, ncol + + def setup(self, id, nplots, wintitle, show): + + self.nplots = nplots + + ncolspan = 1 + colspan = 1 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH, + heightplot = self.HEIGHT, + show=show) + + nrow, ncol = self.getSubplots() + + counter = 0 + for y in range(nrow): + for x in range(ncol): + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) + + def run(self, dataOut, id, wintitle="", channelList=None, + xmin=None, xmax=None, ymin=None, ymax=None, + save=False, figpath='./', figfile=None, show=True, + ftp=False, wr_period=1, server=None, + folder=None, username=None, password=None, + xaxis="frequency"): + + + if channelList == None: + channelIndexList = dataOut.channelIndexList + channelList = dataOut.channelList + else: + channelIndexList = [] + for channel in channelList: + if channel not in dataOut.channelList: + raise ValueError, "Channel %d is not in dataOut.channelList" + channelIndexList.append(dataOut.channelList.index(channel)) + + factor = dataOut.normFactor + + y = dataOut.getHeiRange() + + z = dataOut.data_spc/factor + z = numpy.where(numpy.isfinite(z), z, numpy.NAN) + + hei_index = numpy.arange(25)*3 + 20 + + if xaxis == "frequency": + x = dataOut.getFreqRange()/1000. + zdB = 10*numpy.log10(z[0,:,hei_index]) + xlabel = "Frequency (kHz)" + ylabel = "Power (dB)" + + elif xaxis == "time": + x = dataOut.getAcfRange() + zdB = z[0,:,hei_index] + xlabel = "Time (ms)" + ylabel = "ACF" + + else: + x = dataOut.getVelRange() + zdB = 10*numpy.log10(z[0,:,hei_index]) + xlabel = "Velocity (m/s)" + ylabel = "Power (dB)" + + thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) + title = wintitle + " Range Cuts %s" %(thisDatetime.strftime("%d-%b-%Y")) + + if not self.isConfig: + + nplots = 1 + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + show=show) + + if xmin == None: xmin = numpy.nanmin(x)*0.9 + if xmax == None: xmax = numpy.nanmax(x)*1.1 + if ymin == None: ymin = numpy.nanmin(zdB) + if ymax == None: ymax = numpy.nanmax(zdB) + + self.isConfig = True + + self.setWinTitle(title) + + title = "Spectra Cuts: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S")) + axes = self.axesList[0] + + legendlabels = ["Range = %dKm" %y[i] for i in hei_index] + + axes.pmultilineyaxis( x, zdB, + xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, + xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, + ytick_visible=True, nxticks=5, + grid='x') + + self.draw() + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime) + +class Noise(Figure): + + isConfig = None + __nsubplots = None + + PREFIX = 'noise' + + def __init__(self): + + self.timerange = 24*60*60 + self.isConfig = False + self.__nsubplots = 1 + self.counter_imagwr = 0 + self.WIDTH = 800 + self.HEIGHT = 400 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.xdata = None + self.ydata = None + + self.PLOT_CODE = NOISE_CODE + + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + self.figfile = None + + self.xmin = None + self.xmax = None + + def getSubplots(self): + + ncol = 1 + nrow = 1 + + return nrow, ncol + + def openfile(self, filename): + dirname = os.path.dirname(filename) + + if not os.path.exists(dirname): + os.mkdir(dirname) + + f = open(filename,'w+') + f.write('\n\n') + f.write('JICAMARCA RADIO OBSERVATORY - Noise \n') + f.write('DD MM YYYY HH MM SS Channel0 Channel1 Channel2 Channel3\n\n' ) + f.close() + + def save_data(self, filename_phase, data, data_datetime): + + f=open(filename_phase,'a') + + timetuple_data = data_datetime.timetuple() + day = str(timetuple_data.tm_mday) + month = str(timetuple_data.tm_mon) + year = str(timetuple_data.tm_year) + hour = str(timetuple_data.tm_hour) + minute = str(timetuple_data.tm_min) + second = str(timetuple_data.tm_sec) + + data_msg = '' + for i in range(len(data)): + data_msg += str(data[i]) + ' ' + + f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' ' + data_msg + '\n') + f.close() + + + def setup(self, id, nplots, wintitle, showprofile=True, show=True): + + self.__showprofile = showprofile + self.nplots = nplots + + ncolspan = 7 + colspan = 6 + self.__nsubplots = 2 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH+self.WIDTHPROF, + heightplot = self.HEIGHT+self.HEIGHTPROF, + show=show) + + nrow, ncol = self.getSubplots() + + self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1) + + + def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True', + xmin=None, xmax=None, ymin=None, ymax=None, + timerange=None, + save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): + + if not isTimeInHourRange(dataOut.datatime, xmin, xmax): + return + + if channelList == None: + channelIndexList = dataOut.channelIndexList + channelList = dataOut.channelList + else: + channelIndexList = [] + for channel in channelList: + if channel not in dataOut.channelList: + raise ValueError, "Channel %d is not in dataOut.channelList" + channelIndexList.append(dataOut.channelList.index(channel)) + + x = dataOut.getTimeRange() + #y = dataOut.getHeiRange() + factor = dataOut.normFactor + noise = dataOut.noise[channelIndexList]/factor + noisedB = 10*numpy.log10(noise) + + thisDatetime = dataOut.datatime + + title = wintitle + " Noise" # : %s" %(thisDatetime.strftime("%d-%b-%Y")) + xlabel = "" + ylabel = "Intensity (dB)" + update_figfile = False + + if not self.isConfig: + + nplots = 1 + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + if timerange != None: + self.timerange = timerange + + self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange) + + if ymin == None: ymin = numpy.floor(numpy.nanmin(noisedB)) - 10.0 + if ymax == None: ymax = numpy.nanmax(noisedB) + 10.0 + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + + self.name = thisDatetime.strftime("%Y%m%d_%H%M%S") + self.isConfig = True + self.figfile = figfile + self.xdata = numpy.array([]) + self.ydata = numpy.array([]) + + update_figfile = True + + #open file beacon phase + path = '%s%03d' %(self.PREFIX, self.id) + noise_file = os.path.join(path,'%s.txt'%self.name) + self.filename_noise = os.path.join(figpath,noise_file) + + self.setWinTitle(title) + + title = "Noise %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + + legendlabels = ["channel %d"%(idchannel) for idchannel in channelList] + axes = self.axesList[0] + + self.xdata = numpy.hstack((self.xdata, x[0:1])) + + if len(self.ydata)==0: + self.ydata = noisedB.reshape(-1,1) + else: + self.ydata = numpy.hstack((self.ydata, noisedB.reshape(-1,1))) + + + axes.pmultilineyaxis(x=self.xdata, y=self.ydata, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, + xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid", + XAxisAsTime=True, grid='both' + ) + + self.draw() + + if dataOut.ltctime >= self.xmax: + self.counter_imagwr = wr_period + self.isConfig = False + update_figfile = True + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime, + update_figfile=update_figfile) + + #store data beacon phase + if save: + self.save_data(self.filename_noise, noisedB, thisDatetime) + +class BeaconPhase(Figure): + + __isConfig = None + __nsubplots = None + + PREFIX = 'beacon_phase' + + def __init__(self): + + self.timerange = 24*60*60 + self.isConfig = False + self.__nsubplots = 1 + self.counter_imagwr = 0 + self.WIDTH = 800 + self.HEIGHT = 400 + self.WIDTHPROF = 120 + self.HEIGHTPROF = 0 + self.xdata = None + self.ydata = None + + self.PLOT_CODE = BEACON_CODE + + self.FTP_WEI = None + self.EXP_CODE = None + self.SUB_EXP_CODE = None + self.PLOT_POS = None + + self.filename_phase = None + + self.figfile = None + + self.xmin = None + self.xmax = None + + def getSubplots(self): + + ncol = 1 + nrow = 1 + + return nrow, ncol + + def setup(self, id, nplots, wintitle, showprofile=True, show=True): + + self.__showprofile = showprofile + self.nplots = nplots + + ncolspan = 7 + colspan = 6 + self.__nsubplots = 2 + + self.createFigure(id = id, + wintitle = wintitle, + widthplot = self.WIDTH+self.WIDTHPROF, + heightplot = self.HEIGHT+self.HEIGHTPROF, + show=show) + + nrow, ncol = self.getSubplots() + + self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1) + + def save_phase(self, filename_phase): + f = open(filename_phase,'w+') + f.write('\n\n') + f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n') + f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' ) + f.close() + + def save_data(self, filename_phase, data, data_datetime): + f=open(filename_phase,'a') + timetuple_data = data_datetime.timetuple() + day = str(timetuple_data.tm_mday) + month = str(timetuple_data.tm_mon) + year = str(timetuple_data.tm_year) + hour = str(timetuple_data.tm_hour) + minute = str(timetuple_data.tm_min) + second = str(timetuple_data.tm_sec) + f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n') + f.close() + + + def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True', + xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None, + timerange=None, + save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1, + server=None, folder=None, username=None, password=None, + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): + + if not isTimeInHourRange(dataOut.datatime, xmin, xmax): + return + + if pairsList == None: + pairsIndexList = dataOut.pairsIndexList[:10] + else: + pairsIndexList = [] + for pair in pairsList: + if pair not in dataOut.pairsList: + raise ValueError, "Pair %s is not in dataOut.pairsList" %(pair) + pairsIndexList.append(dataOut.pairsList.index(pair)) + + if pairsIndexList == []: + return + +# if len(pairsIndexList) > 4: +# pairsIndexList = pairsIndexList[0:4] + + hmin_index = None + hmax_index = None + + if hmin != None and hmax != None: + indexes = numpy.arange(dataOut.nHeights) + hmin_list = indexes[dataOut.heightList >= hmin] + hmax_list = indexes[dataOut.heightList <= hmax] + + if hmin_list.any(): + hmin_index = hmin_list[0] + + if hmax_list.any(): + hmax_index = hmax_list[-1]+1 + + x = dataOut.getTimeRange() + #y = dataOut.getHeiRange() + + + thisDatetime = dataOut.datatime + + title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y")) + xlabel = "Local Time" + ylabel = "Phase (degrees)" + + update_figfile = False + + nplots = len(pairsIndexList) + #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList))) + phase_beacon = numpy.zeros(len(pairsIndexList)) + for i in range(nplots): + pair = dataOut.pairsList[pairsIndexList[i]] + ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0) + powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0) + powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0) + avgcoherenceComplex = ccf/numpy.sqrt(powa*powb) + phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi + + #print "Phase %d%d" %(pair[0], pair[1]) + #print phase[dataOut.beacon_heiIndexList] + + if dataOut.beacon_heiIndexList: + phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList]) + else: + phase_beacon[i] = numpy.average(phase) + + if not self.isConfig: + + nplots = len(pairsIndexList) + + self.setup(id=id, + nplots=nplots, + wintitle=wintitle, + showprofile=showprofile, + show=show) + + if timerange != None: + self.timerange = timerange + + self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange) + + if ymin == None: ymin = 0 + if ymax == None: ymax = 360 + + self.FTP_WEI = ftp_wei + self.EXP_CODE = exp_code + self.SUB_EXP_CODE = sub_exp_code + self.PLOT_POS = plot_pos + + self.name = thisDatetime.strftime("%Y%m%d_%H%M%S") + self.isConfig = True + self.figfile = figfile + self.xdata = numpy.array([]) + self.ydata = numpy.array([]) + + update_figfile = True + + #open file beacon phase + path = '%s%03d' %(self.PREFIX, self.id) + beacon_file = os.path.join(path,'%s.txt'%self.name) + self.filename_phase = os.path.join(figpath,beacon_file) + #self.save_phase(self.filename_phase) + + + #store data beacon phase + #self.save_data(self.filename_phase, phase_beacon, thisDatetime) + + self.setWinTitle(title) + + + title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S")) + + legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList] + + axes = self.axesList[0] + + self.xdata = numpy.hstack((self.xdata, x[0:1])) + + if len(self.ydata)==0: + self.ydata = phase_beacon.reshape(-1,1) + else: + self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1))) + + + axes.pmultilineyaxis(x=self.xdata, y=self.ydata, + xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, + xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid", + XAxisAsTime=True, grid='both' + ) + + self.draw() + + if dataOut.ltctime >= self.xmax: + self.counter_imagwr = wr_period + self.isConfig = False + update_figfile = True + + self.save(figpath=figpath, + figfile=figfile, + save=save, + ftp=ftp, + wr_period=wr_period, + thisDatetime=thisDatetime, + update_figfile=update_figfile) diff --git a/schainpy/model/graphics/.svn/text-base/jroplot_spectra.pyc.svn-base b/schainpy/model/graphics/.svn/text-base/jroplot_spectra.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..90a5a229727091c7e66bb5e617e6975aa4d4af49 GIT binary patch literal 39380 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 P_y2nT`}^QT_h0;Z&``WA27`OJiO+i!;Sx5sS z2gyO?iKPZH4XJt6rUvlo~$1S;ghIq zwVd^+bzr%E7zFWp6!gMzPj|5132et(-w&y`6~&3?>q5!@39E8jIDBso;lTmYl{3#r&|63T57**b#**QJ`HswOmWU+6vhl> z&(91RWoeW{h>r4z&(SpXuTq==qi2flJbH&l1z|Qt!z>MRG?b7X=4m)h&vK-WKBZlW zEtu&+3}d>sIOy2*V>k939Tx||vDnyEF9e=hfOSiVD9Kx$f@Ud=$e zRSRk^B={me{HM}BlzipCUrCIvB63To4sbA+;TCv03%A zn$640E|5JZn;UrrPIJPk{3<7YpC@~P>_xJd$X+IUh3r*cH>HktmCmELkVg^XxF(0t zMy(!2bNpJj*Xobg>JMx6&5io~jrz7sGLay)#>bs^BV@rAqp}~l@u0R=+xqcKDH2nf zC$jYRf#v&-SF78SqWumhtR}3!5QDU5fF58^-?JV&o{$4g%IP6#o|Dw~T;Gu#ml00D zAdHdsp<~Ao1mjUW@bobo1s-14D9O0p7Ig)aG@sJRpN96?*o*In1&fi@;AF1uO`IzMuwSXg%< zzV5bdd1)++&j@JUmv$hAk8w1$w2`-b+vy7%fwluTy2EHE+MIyb3K|?%CW65HQfkG4 z*g_~6!~8NvFQU0L_U~e92FQE<@Rk>2aG!gGsw;XQo2gZ`YAg%56;w&U4schZs?yI_ z@faneY+O`DRW{yMD{9_&6$bxsIt<2gsGTyv`MrQc-2egtDaU}AIRV770AfV|aW*;A zqPG;=H33A8lDP>$yzm-8{3FuoOhEixM$ZDozou&i-Cl;jib~e%Q4My*q>f9#ZYDuP z)qf5kgc1UQDcE&@?*O|w2D@^Kk8=!mRl&Hq7YzsqtkPjcfQupOHIP>k$eR_&D+}Zu zeULy`^}mHKL54AOy?n4QpMhGZ<;z4`AWIsOS6@eN6a@o#*U(6fhg=aP zG2cb=4K#>ra~;i9G|3pLrgV zIx7jVf-ppBvq1jGv`--Vw=m((qYWA@(r{5`81y7h;XRxMobJCgBsmtOR+UjMZg{3n z33XJbT|NmozYp^=K8+IC*61->lCA=Ue^LF<6|zks$t0K7)Mz=apqGIpE0QBqB5PL4 z>5|MZOIwkPUKXjv)5ml>L#u$U1sd{ZE0Tq}qSm$a3@L~|58wggpR1%o`5!SRR5+}$ z;#r4M=|S&R8K?r}hFpm79lJow@jN!*;bjINj4ue36a^P%CUBu5xKI{cSmM<=b@UtB z^?#jOi-lgKr5mHnguyNuuNv$`{LB~H<&p8KUEW~*sp_Z7ikzbFEB5%0Ex=CMZpfu{ zouj^3OFm;_%kTE$jqxi!wiR2S^y2aRi=(c6dVhMqI(;;O4U`4lgi};;cISG^Mkm?>=PSZnb1pakr7N?`{}1)(017tAMmP2HS;Eo zFQZ2hV7dOV-l^No`eyxpeOq7Rt&StbT2qRdw!7c8;)9e1GktNjo;p%3w&SjxA;)2} z%eWiZ0`iTMLj%AsW#oj20;)f;yq2ovzf3d=1_~xhNN6oGNY4+UFwD`Y^iX1+6E#Vugf$VvNZA0ZHXRbl|xA2eC*r zrFXN;@1_-_9a_h77N$Qr+~dV!9_Y`;Y;sAXL zFQ#Tm^W~ao!fG{Bqo4oTDmS2>e}pZ5i;b!!K1y?ZSk9`Fx@2553dWLAF}PQ~tuilt zi)Z#1`8cj6M>4*Z%$&^4ox$U@{-RM+)d?OC8l|-OXf|Q)W>aFQ*3~%m%<6N zP+OGuAZ#axaV$W6X`6@MS+nsxM0Z_a)sH#R|@as#L|s%xHg-1&|=LX pXAqh9DXkN88UXMs6hsxC{~z(i%XnW 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 literal 0 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 Xl-@gCL~O#Ccwu^s^UqEf3M2mqKJUzG literal 0 Hc$@Rc@3LBS1)k!@7v+JCv{ zO5K4ri&U@nC%>85x3gZCezlFWi{JAIf1iSyS88TI6&N7J0;m8kf{Nf0s01#9%HRs9 z0HD{7^8GC4_2oMwmX2d-IW7uHg0i3@s0wO=x}YKG2)crv zK(mqf;S4&!Kq>{Hetv~6o$FDd4UsJ?#Rx?)t}kcUKvVRp6mO2DV3Hx z)|J;o-_|M5o$FpkS0lPX2~{vifkUu`-GQk^EO>n{|@s@xyHx jsd#q2dE9-?52|XrUVfCnAd}6i#cJWdv5%Dw-V1*KfL4{c literal 0 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 Lg{eY*>f8SVO63DT literal 0 Hc$@= self.nplots: break - + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) - + if showprofile: self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1) - + counter += 1 - + def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False, xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1, server=None, folder=None, username=None, password=None, ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False): - + """ - + Input: dataOut : id : @@ -94,15 +94,15 @@ class CorrelationPlot(Figure): zmin : None, zmax : None """ - + if dataOut.flagNoData: return None - + if realtime: if not(isRealtime(utcdatatime = dataOut.utctime)): print 'Skipping this plot function' return - + if channelList == None: channelIndexList = dataOut.channelIndexList else: @@ -111,53 +111,53 @@ class CorrelationPlot(Figure): if channel not in dataOut.channelList: raise ValueError, "Channel %d is not in dataOut.channelList" channelIndexList.append(dataOut.channelList.index(channel)) - + factor = dataOut.normFactor lenfactor = factor.shape[1] x = dataOut.getLagTRange(1) y = dataOut.getHeiRange() - + z = copy.copy(dataOut.data_corr[:,:,0,:]) for i in range(dataOut.data_corr.shape[0]): - z[i,:,:] = z[i,:,:]/factor[i,:] + z[i,:,:] = z[i,:,:]/factor[i,:] zdB = numpy.abs(z) - + avg = numpy.average(z, axis=1) # avg = numpy.nanmean(z, axis=1) # noise = dataOut.noise/factor - + #thisDatetime = dataOut.datatime thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) - title = wintitle + " Correlation" + title = wintitle + " Correlation" xlabel = "Lag T (s)" ylabel = "Range (Km)" - + if not self.isConfig: - - nplots = dataOut.data_corr.shape[0] - + + nplots = dataOut.data_corr.shape[0] + self.setup(id=id, nplots=nplots, wintitle=wintitle, showprofile=showprofile, show=show) - + if xmin == None: xmin = numpy.nanmin(x) if xmax == None: xmax = numpy.nanmax(x) if ymin == None: ymin = numpy.nanmin(y) if ymax == None: ymax = numpy.nanmax(y) if zmin == None: zmin = 0 if zmax == None: zmax = 1 - + self.FTP_WEI = ftp_wei self.EXP_CODE = exp_code self.SUB_EXP_CODE = sub_exp_code self.PLOT_POS = plot_pos - + self.isConfig = True - + self.setWinTitle(title) - + for i in range(self.nplots): str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S")) title = "Channel %d and %d: : %s" %(dataOut.pairsList[i][0],dataOut.pairsList[i][1] , str_datetime) @@ -166,7 +166,7 @@ class CorrelationPlot(Figure): xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax, xlabel=xlabel, ylabel=ylabel, title=title, ticksize=9, cblabel='') - + # if self.__showprofile: # axes = self.axesList[i*self.__nsubplots +1] # axes.pline(avgdB[i], y, @@ -174,15 +174,15 @@ class CorrelationPlot(Figure): # xlabel='dB', ylabel='', title='', # ytick_visible=False, # grid='x') -# +# # noiseline = numpy.repeat(noisedB[i], len(y)) # axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2) - + self.draw() - + self.save(figpath=figpath, figfile=figfile, save=save, ftp=ftp, wr_period=wr_period, - thisDatetime=thisDatetime) + thisDatetime=thisDatetime) diff --git a/schainpy/model/graphics/jroplot_correlation.pyc b/schainpy/model/graphics/jroplot_correlation.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e45721e507c64b8f943dcb0a9ba2026c20fc94f GIT binary patch literal 5427 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 self.nplots: break - + self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1) - + if showprofile: self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1) - + counter += 1 - + def run(self, dataOut, id, wintitle="", channelList=None, xmin=None, xmax=None, ymin=None, ymax=None, save=False, figpath='./', figfile=None, ftp=False, wr_period=1, show=True, server=None, folder=None, username=None, password=None, ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): - + """ - + Input: dataOut : id : @@ -95,12 +94,12 @@ class SpectraHeisScope(Figure): ymin : None, ymax : None, """ - + if dataOut.realtime: if not(isRealtime(utcdatatime = dataOut.utctime)): print 'Skipping this plot function' return - + if channelList == None: channelIndexList = dataOut.channelIndexList else: @@ -109,9 +108,9 @@ class SpectraHeisScope(Figure): if channel not in dataOut.channelList: raise ValueError, "Channel %d is not in dataOut.channelList" channelIndexList.append(dataOut.channelList.index(channel)) - + # x = dataOut.heightList - c = 3E8 + c = 3E8 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0] #deberia cambiar para el caso de 1Mhz y 100KHz x = numpy.arange(-1*dataOut.nHeights/2.,dataOut.nHeights/2.)*(c/(2*deltaHeight*dataOut.nHeights*1000)) @@ -123,7 +122,7 @@ class SpectraHeisScope(Figure): data = dataOut.data_spc / factor datadB = 10.*numpy.log10(data) y = datadB - + #thisDatetime = dataOut.datatime thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S")) @@ -131,29 +130,29 @@ class SpectraHeisScope(Figure): #para 1Mhz descomentar la siguiente linea #xlabel = "Frequency x 10000" ylabel = "Intensity (dB)" - + if not self.isConfig: nplots = len(channelIndexList) - + self.setup(id=id, nplots=nplots, wintitle=wintitle, show=show) - + if xmin == None: xmin = numpy.nanmin(x) if xmax == None: xmax = numpy.nanmax(x) if ymin == None: ymin = numpy.nanmin(y) if ymax == None: ymax = numpy.nanmax(y) - + self.FTP_WEI = ftp_wei self.EXP_CODE = exp_code self.SUB_EXP_CODE = sub_exp_code self.PLOT_POS = plot_pos - + self.isConfig = True - + self.setWinTitle(title) - + for i in range(len(self.axesList)): ychannel = y[i,:] str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S")) @@ -162,10 +161,10 @@ class SpectraHeisScope(Figure): axes.pline(x, ychannel, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, xlabel=xlabel, ylabel=ylabel, title=title, grid='both') - - + + self.draw() - + self.save(figpath=figpath, figfile=figfile, save=save, @@ -174,18 +173,18 @@ class SpectraHeisScope(Figure): thisDatetime=thisDatetime) class RTIfromSpectraHeis(Figure): - + isConfig = None __nsubplots = None PREFIX = 'rtinoise' - - def __init__(self, **kwargs): - Figure.__init__(self, **kwargs) + + def __init__(self): + self.timerange = 24*60*60 self.isConfig = False self.__nsubplots = 1 - + self.WIDTH = 820 self.HEIGHT = 200 self.WIDTHPROF = 120 @@ -194,43 +193,43 @@ class RTIfromSpectraHeis(Figure): self.xdata = None self.ydata = None self.figfile = None - + self.PLOT_CODE = RTI_CODE - + def getSubplots(self): - + ncol = 1 nrow = 1 - + return nrow, ncol - + def setup(self, id, nplots, wintitle, showprofile=True, show=True): - + self.__showprofile = showprofile self.nplots = nplots - + ncolspan = 7 colspan = 6 self.__nsubplots = 2 - + self.createFigure(id = id, wintitle = wintitle, widthplot = self.WIDTH+self.WIDTHPROF, heightplot = self.HEIGHT+self.HEIGHTPROF, show = show) - + nrow, ncol = self.getSubplots() - + self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1) - - + + def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True', xmin=None, xmax=None, ymin=None, ymax=None, timerange=None, save=False, figpath='./', figfile=None, ftp=False, wr_period=1, show=True, server=None, folder=None, username=None, password=None, ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0): - + if channelList == None: channelIndexList = dataOut.channelIndexList channelList = dataOut.channelList @@ -240,86 +239,86 @@ class RTIfromSpectraHeis(Figure): if channel not in dataOut.channelList: raise ValueError, "Channel %d is not in dataOut.channelList" channelIndexList.append(dataOut.channelList.index(channel)) - + if timerange != None: self.timerange = timerange - + x = dataOut.getTimeRange() y = dataOut.getHeiRange() - + factor = dataOut.normFactor data = dataOut.data_spc / factor data = numpy.average(data,axis=1) datadB = 10*numpy.log10(data) - + # factor = dataOut.normFactor # noise = dataOut.getNoise()/factor # noisedB = 10*numpy.log10(noise) - + #thisDatetime = dataOut.datatime thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) title = wintitle + " RTI: %s" %(thisDatetime.strftime("%d-%b-%Y")) xlabel = "Local Time" ylabel = "Intensity (dB)" - + if not self.isConfig: - + nplots = 1 - + self.setup(id=id, nplots=nplots, wintitle=wintitle, showprofile=showprofile, show=show) - + self.tmin, self.tmax = self.getTimeLim(x, xmin, xmax) - + if ymin == None: ymin = numpy.nanmin(datadB) if ymax == None: ymax = numpy.nanmax(datadB) - + self.name = thisDatetime.strftime("%Y%m%d_%H%M%S") self.isConfig = True self.figfile = figfile self.xdata = numpy.array([]) self.ydata = numpy.array([]) - + self.FTP_WEI = ftp_wei self.EXP_CODE = exp_code self.SUB_EXP_CODE = sub_exp_code self.PLOT_POS = plot_pos - + self.setWinTitle(title) - - + + # title = "RTI %s" %(thisDatetime.strftime("%d-%b-%Y")) title = "RTI - %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S")) - + legendlabels = ["channel %d"%idchannel for idchannel in channelList] axes = self.axesList[0] - + self.xdata = numpy.hstack((self.xdata, x[0:1])) - + if len(self.ydata)==0: self.ydata = datadB[channelIndexList].reshape(-1,1) else: self.ydata = numpy.hstack((self.ydata, datadB[channelIndexList].reshape(-1,1))) - - + + axes.pmultilineyaxis(x=self.xdata, y=self.ydata, xmin=self.tmin, xmax=self.tmax, ymin=ymin, ymax=ymax, xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='.', markersize=8, linestyle="solid", grid='both', XAxisAsTime=True ) - + self.draw() - + update_figfile = False - + if dataOut.ltctime >= self.tmax: self.counter_imagwr = wr_period self.isConfig = False update_figfile = True - + self.save(figpath=figpath, figfile=figfile, save=save, diff --git a/schainpy/model/graphics/jroplot_heispectra.pyc b/schainpy/model/graphics/jroplot_heispectra.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3b8be0586b7eac7a3738f3730a94e6f9c30f5dd5 GIT binary patch literal 8935 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 DH+JSD literal 0 Hc$@32{Btei%?xB^vyIg8WFL!B4@DMWq2LuM- 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 4: pairsIndexList = pairsIndexList[0:4] - - factor = dataOut.normFactor + + if normFactor is None: + factor = dataOut.normFactor + else: + factor = normFactor x = dataOut.getVelRange(1) y = dataOut.getHeiRange() z = dataOut.data_spc[:,:,:]/factor @@ -517,10 +522,10 @@ class RTIPlot(Figure): def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True', xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, - timerange=None, + timerange=None, colormap='jet', save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True, server=None, folder=None, username=None, password=None, - ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, **kwargs): + ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, normFactor=None): """ @@ -551,20 +556,21 @@ class RTIPlot(Figure): raise ValueError, "Channel %d is not in dataOut.channelList" channelIndexList.append(dataOut.channelList.index(channel)) - if hasattr(dataOut, 'normFactor'): + if normFactor is None: factor = dataOut.normFactor else: - factor = 1 + factor = normFactor # factor = dataOut.normFactor x = dataOut.getTimeRange() y = dataOut.getHeiRange() -# z = dataOut.data_spc/factor -# z = numpy.where(numpy.isfinite(z), z, numpy.NAN) -# avg = numpy.average(z, axis=1) -# avgdB = 10.*numpy.log10(avg) - avgdB = dataOut.getPower() + z = dataOut.data_spc/factor + z = numpy.where(numpy.isfinite(z), z, numpy.NAN) + avg = numpy.average(z, axis=1) + avgdB = 10.*numpy.log10(avg) + # avgdB = dataOut.getPower() + thisDatetime = dataOut.datatime # thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0]) @@ -1111,6 +1117,7 @@ class Noise(Figure): PREFIX = 'noise' + def __init__(self, **kwargs): Figure.__init__(self, **kwargs) self.timerange = 24*60*60 diff --git a/schainpy/model/graphics/jroplot_spectra.pyc b/schainpy/model/graphics/jroplot_spectra.pyc new file mode 100644 index 0000000000000000000000000000000000000000..458f38a008bffd954fef2ae29ea66c51f0529203 GIT binary patch literal 39550 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 T_-8H}i>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 def addpcolorbuffer(ax, x, y, z, zmin, zmax, xlabel='', ylabel='', title='', colormap='jet'): @@ -262,12 +276,13 @@ def addpcolorbuffer(ax, x, y, z, zmin, zmax, xlabel='', ylabel='', title='', col ax.collections.remove(ax.collections[0]) z = numpy.ma.masked_invalid(z) - + cmap=matplotlib.pyplot.get_cmap(colormap) - cmap.set_bad('black', 1.) - + cmap.set_bad('white',1.) ax.pcolormesh(x,y,z.T,vmin=zmin,vmax=zmax, cmap=cmap) + ax.grid(True) + def createPmultiline(ax, x, y, xmin, xmax, ymin, ymax, xlabel='', ylabel='', title='', legendlabels=None, ticksize=9, xtick_visible=True, ytick_visible=True, @@ -326,7 +341,7 @@ def createPmultiline(ax, x, y, xmin, xmax, ymin, ymax, xlabel='', ylabel='', tit def pmultiline(iplot, x, y, xlabel='', ylabel='', title=''): - ax = iplot.axes + ax = iplot.get_axes() printLabels(ax, xlabel, ylabel, title) @@ -403,8 +418,7 @@ def createPmultilineYAxis(ax, x, y, xmin, xmax, ymin, ymax, xlabel='', ylabel='' def pmultilineyaxis(iplot, x, y, xlabel='', ylabel='', title=''): - ax = iplot.axes - + ax = iplot.get_axes() printLabels(ax, xlabel, ylabel, title) for i in range(len(ax.lines)): @@ -425,7 +439,7 @@ def createPolar(ax, x, y, # ax.text(0, -110, ylabel, rotation='vertical', va ='center', ha = 'center' ,size='11') # ax.text(0, 50, ylabel, rotation='vertical', va ='center', ha = 'left' ,size='11') # ax.text(100, 100, 'example', ha='left', va='center', rotation='vertical') - ax.yaxis.labelpad = 40 + ax.yaxis.labelpad = 230 printLabels(ax, xlabel, ylabel, title) iplot = ax.lines[-1] @@ -449,7 +463,7 @@ def createPolar(ax, x, y, def polar(iplot, x, y, xlabel='', ylabel='', title=''): - ax = iplot.axes + ax = iplot.get_axes() # ax.text(0, -110, ylabel, rotation='vertical', va ='center', ha = 'center',size='11') printLabels(ax, xlabel, ylabel, title) diff --git a/schainpy/model/graphics/mpldriver.pyc b/schainpy/model/graphics/mpldriver.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e98c39818dc24c4e695b1f6c68ccc3f19e2c82dd GIT binary patch literal 14837 zc%0o^U2r7VRleOLjWp7X{zfyB_Q$KWE$`U7mb^|J!UA3|HXA3|Y)tPK8;dwY&va|l zQqS~kcaK(DMihxQfufQ)JcN*dt5Q(l;xCvV7e$dgKmjk|fd{In0v_OnCkRxi6mP)! z&b_z0N78x|%CkiwY3|&<_xAlc=bm%EbM95{KS~oHjxM~~6zXT1J}=NG8qEpe(4QfE zA=Z<;A=V9@H^sWC^Et7e6OJidQ*4ch?Ysy-D%_md8Wm1X92mmrP`i;#b?0cc>?zMZ zQGQhTW1>AS*2jf`=e+O>qCFwjCq#QvtWOF9Jru=ONjPJ|85ajMybxPcoHy|26ofM& z&aO|3wCSX9ikYUxOw$rIo#CdlVrx!pm4!3K?dF9`<Z~?lcN@az@-E0zD?2Wp4j?ru|u-(u!~%<*FwJx&i?y z^B9l*xVT4DKbL8+!td5HCDi^2ac@MdKRH-r`ag?-Zq(jG;^6%^ z{alYnDeHTk-Y(~Ee)vkO73V4E*x?oj zy-xFL5Vq|&c0(??=5<^12tz&Ou++YQ1ouZElO(HsQ_T1C zqJnHrX0iW8ZhuVl#~{ZfzFT?GXZg`Rjd8dAQ4!wNBaL$rNjSZAqXx=d=UI1pZC=%e z-E^CQPfN#qH@sHl-E~`1AN~8~8k)otOx3vS2eI!pnCRU-Jn_1{U}J;J=;dDMa<*xA zcI=3|Y}*~XMYNt_62^7nl@r{l$6oBaJQFYIa6i#zaHj@>#o(6b#N$lMj%+!~4^F(v z{cpNnYcsZrl(njw5l+|RZ<0$Mx5!sJrPkqqTO|cS3K+4OhE+F$Qght{uBqdBG##&THnrz@O`>&M6;GEZX{(+TE=@?^3wKw=B$NT zSknnnK-KF(M-s2;2ayy6uCz{R3Jr-&lX^@^r6&_Aje3S8CKL$?(TXT=U>KR@TPLvqERXkEWbe4d{ge(&o>p^1wlnp*d24NWzT2_e?l6fk zp(Z71@I0O{36X0;QRvT$nl^IX*c7}()LoZ~EyvW{;D?9AI?{@A+Ak&3K4w!dB-55V zI!S%_5| zGE>Io8h8QMG7HcqCNVR&#r@1oUrA6>G>SEnsUg!sR)&lZWnha&*%swti^yyon7RFN z(I1DsAu-FmFO3V;+^DgxVId@ILJRG1J`C<~9$fAQz8$hb$>=Fq1q&o+wN6H7(-`b2IF@Rt1DEB)bUZ9U4q#Xa=0w?FJEN_9$arKQ5{51Q z(o|fbk$?)KdFEQlC>wJ|(a6(pfu2f6vJs1#k86h%A)#eL1BA>8j7!Wd5jKJ917lQf z(-Lz5-R$nQzVc=K{PE@1*FNx1cjv$MZX7OSE^Nd6&Qli6U)cZiKK#LcRE2#^pOb7 zWS;P7vAY{T1eE~3+@zsCfyW~AMsfweO-w|8m?uAUm?tJ1q&|y7-#k>rQiY;iYPO`D zFx~-?FbxlcU^OZ21%aep-)^{m^0+4-3+hp-9`s>d(W0Z?KvuRMx9wlZp98#yzMB(O z>i83;xV?)Js4a$_KtuMD-_P$(a#w^)ib9P?&lM_|M+rOB3x{9bJ@y%lAfONQ=k{sFz&#w|3f zC_4asPwh>)eXGznOZ)TCIbhI&(mZDoLimP33g`nb_vgh8QbTF=gslFDw7NeHFCE}^ z%tW_K&{**a)@LO+`P6_M8{lBI4Nhjw)+xCssH5797Qu;$W%~JGr`wA!aTY%?5cs}? z1hDtQ^0`J3Z=R#?T_k(wxUC1}6JbBDtX|xZ*cc8FyP0fNpIP;I_aYy?A0}thT}~aK zWfFjhwB_=q9WBSfa>HHjbsbV-4xTQqUR(~s<&JxYT49untJELM00wSIPlm*4lXGo* zi+nF>jJ)W2?etOms7*g<1+Sev?9qb-mx8+?%c(E|xyUTmTx^G-y~nu?KOmns(J!RH zw1uK$B>&p6$7kLfki|t~%No!t3U3SWTIxC~1dQY2#r1@T^ zb2Q)M&OikADwU`2%8~1JMelmuIs=+qMDi?FjsaqLf_2~C3wp7H1(ifGg5bNH?nyw< z_Btw~%*>uH*`pE*z|i`jP-u?H$!o&gOWYSdC1faZzu6M#w2q=J=eatPGyaHBfdttA z*aS24q`9LaUbhDd3?1AvCV2%kZetKQCStM##ch^zGe*U@Kt9@e6D6}|)tJwzZ~ByS zRYDshrc8^*8EREB6H}SfYW-wtDsy59=8;v*fjNMv89zJOO-_Pjr?$<4S+O>?mGd0T zdDz}Prh#!VmERI6)XpojmDg+hev$Fn_Vd_qWT2G68D*OkGm!3Q(Lqi@0g&ptwTor( zf^wP+5D`FA7H?}0br{y_4G`qeZe?-}lQN9qL6+YYiKQ=^Wl0u%5)b4FkwHmv-Thn| z-U4OJTm}xMq9LVzk3m! zSb~TOjEE+HDgXtr`z8Qbwlpx=&*@2(M1P7)$n;k@7SFB)q*J00$vJwB00h}}0$F7F z31^X6rxy-#x&0)JMPR22UxX)X>@SG^0%MG6iG9u~v_fD+BaubXUj*tPh#|q0al4ve zmW2nje1Td%&SNYBOlS}!Tc*vn2-=i++!HdQGQsmbsSY6+rTmUT2!v2dl|al?rg~ad z|5aK&2u5Z_xL`Un2wLwi=}Dg!@gt(Yq>eNUReDCm%Q%%#r5!05XGQ#I){%Zp_DciR z=2#*Sb77m@wH@U@{l;Yt9pW@V%f@3z8?hZ2v4VcJY3~jb&Lkcy#=3#Nfn5->)8Qbw z;Yk44ClXbq@_14!Q3RPNDYMnE9Uh{~kd~;n$spqFOOI(j#MWY zPC~X5N0mFz`>utpYi%LfM&b+QOWxIc{_auWX0`QZl2lOiX*NE7WCI53KuDFDhpCE7Y1mc5 z12+AbPkJsjr3J+LERxR+O5o>_ypH7Ok=)fHm2CXfFAD7)5`knpN}%;sBwrFoF;+qE z(_ykYpUCfb&_C3PFz1M^GsLi>f#^yT0y(KZ%&yN$b^!q7RaArlfIdA*0YGweSm2Tg zAO_-?0;gsIEfN4wV9++g$C9HQ3>fT!z<}arJejgC&#W8Zn)OML?^BwPwc>!PdjKcD zkgzjl*5pyOA=&neNWOdw1HY0CK12qhe}F~ip=l(MMZ|m|n(s~dmjK2u9nZghB7vMC zCM_{+&|;Xfm1A973Mp0&N+D$8I%9};=I2x*XY6DK zzVC8aSq2(Hw;k-b|Ib)Gon>{Sx3S@dlSXnLTs9Y!;MNQdeB$Ia34DIbI6m+xPk&h! zRUmN`fka}DmQh1F5qUlo9n<%Cl;9o?oE8oRPA858PGjjKutz|Q*Ky4$71t~!aZTx? zOliMFMIxsY5H9_enIsbV%_OeLVMmSXWixgObOiLnW}kC%rY%CxQ{`6v>cYFR%D4N-e!P@owHH?=IY4)EQU z+i_SyG6)WB0$qtw_Pd+*aUj@w6$vilSRX_3<48U(G)z4NT>)4nrbS#yV%5R8AwyRQ zJgdj3m17|1;mBYyS&NKfGUBv4NCG5XB)5}6Ilz^Z?^q#9fEziUGfd?K1}Mzf?)kBY z;KdTO(;tXx?rmbbo)noV+w6VL&Dg+$#3n~~ zr1_|%<^vbZDoPRJXum3;c&o~qu;P^=oH2Em)3|*@-1=YJ7NylE4+Uz9iH&$Gu@NPh zmchu+GzY$vR{z_?M$8=TP1%V5%37Rv>}^Hbh&hC=miCu~3J{g~aD7r5fo+3yJQ;x{ zvJs_B^^~msxwM)rqElrX@wOqY7@3T?Dx4X0Clw}hz(y?SgRM}QxTH#wb3&70QN&B4 zePlUJ z;xT&Zn0T^`C;SqUUrw~jun~ObupYN3-^9LL#!#arbIF`BPK_WQIG`M;rj&aaN7We_ z|37j>%@;erX{4vqxw4sDv`#Mgt_dA!JK%uYwkg6#Ko45*r%a(v==7EI?E10oBP{7h z!jQJB6WVvYPV3V0Rj;+&wb_>?tQ2hqJ>S6&x3dDEu383-Ew>q~r&@9~F5c_9yqkZ_ z_Iob(&v&M|5(7Pyo8Q)-Q-^<(5^&Banyt_M>)T)b&%b=@`Jkz?qY=4+b`U~pt?~UZdp8umrDhl8^b`zt$i08?3>iTw!b1bf*+43n? z%EwjppD)1KG!8-Gz~A=bXqErt2>AM%-S?uHU)qUcTiq<`@IfIUdg!*O-VOQa zP(ruUnnPD@KXN6oJBwrm$vGtW4-V@*5~z3U#YFmdvf#j5QbmA!9W6p^!v~wm(=R1QdLzU#wk_{rnV*8xmeU=1vdmE?5N7M|FgfM z?Y%pYc9H7UKJq&=`|hmQrJrr%$M0XCBHTX(HP6+|zAG?5iUm*sTm%)tB~S@m29?1T zPz78CRlzk-4O|D+!3|IYY=8`K6VwE^KrL_^)CM1cj=;yDV{ix50e3-Na1Yc2pMXxl zeNZ2K3V-lGdg&_|=Zo8XnQmV{-=<&B5?;M}X(ZBdA}uFHK}k>+R0LH)O;8s!1RX(F z&=ZJ#@=)+d@L2Ff@Ko?jVLCWf%*7@QIgP?F7dJ0(LdzZ5xw!f>+uAEbDa&(xe=nud za>u&zV(8mC<+*dcEO3M22Q5dQa~bSqQ^~RIyc-8PJsbaX+DUhAdsw2XaRm*+&I) zncl=^yiKBO^IN*T&NhoEHnV8CNY-KeC5;yA_-ebjk8JMDo0Q{~sY07&5@qIQmF9V} lz6v81&t7cqc3<<2s=8gpZ{;t@WV33qTKI45W2J-l!XK{tmjnO+ literal 0 Hc$@7EScWL5FfS~q7qXiW(`e(`B_ye`SM?dZ^8xg9 zblDQ}onO9i&LOAuI|zQ%_X|VK^5I;;F>{a%Aqbg=G9MKldTz*f)N<5z)N#~x)N|Aa zYN4m7UH7;H34-BuWpk;Mu&gwb;V>A^vLw8JOmC>Av-DW4!uaeWoQ&hiD2_)lV4R$u zC*za3OA&vtA`j}>T8 dateFile)): + continue + + self.fileList.append(thisFile) + self.dateFileList.append(dateFile) + + return 1 + + + def setNextFile(self): + + idFile = self.fileIndex + + while (True): + idFile += 1 + if idFile >= len(self.fileList): + print '\nNo more files in the folder' + print 'Total number of file(s) read : {}'.format(self.fileIndex + 1) + print 'Time of processing : {}'.format(datetime.datetime.now()- self.hoy) + self.flagNoMoreFiles = 1 + return 0 + if self.isConfig: print '------------------------[Next File]---------------------------' + filename = os.path.join(self.path, self.fileList[idFile]) + self.Open(filename) + + print '\n[Setting file] (%s) ...' % self.fileList[idFile] + + break + + self.flagIsNewFile =0 + + self.fileIndex = idFile + self.filename = filename + print 'File:',self.filename + + return 1 + + def readDataBlock(self): + + + self.readHeader() + self.dataRecords(0) + + print '[New Record] record: {} /{} // file {}/{}'.format(self.counter_records,self.nrecords,self.fileIndex+1,len(self.fileList)) + + self.setDataBuffer() + + self.flagIsNewBlock = 1 + + if self.counter_records > self.nrecords: + self.flagIsNewFile = 1 + return 0 + + return 1 + + def setDataBuffer(self): + + ''' + Storing data from one block + + ''' + self.t = datetime.datetime(self.year, self.month, self.day) + self.doy = time.localtime(time.mktime(self.t.timetuple())).tm_yday + self.buffer = numpy.squeeze(numpy.array([[self.one_snr],[self.one_zonal],[self.one_vertical],[self.one_meridional], + [self.time],[self.height],[self.fileIndex], + [self.year],[self.month],[self.day],[self.t],[self.doy]])) + + self.dataOut.time1 = self.time1 + + def Open(self, filename): + ''' + Opening BLTR rawdata file defined by filename + + Inputs: + + filename - Full path name of BLTR rawdata file + + ''' + [dir, name] = os.path.split(filename) + strFile = name.split('.') + self.siteFile = strFile[0] # 'peru2' ---> Piura - 'peru1' ---> Huancayo or Porcuya + + self.filename = filename + if os.path.isfile(self.filename) == False: + print 'File do not exist. Check "filename"' + sys.exit(0) + + self.h_file = numpy.dtype([ + ('FMN', '= 0., self.dataOut.height[0, :] <= self.hcm, numpy.isfinite(self.dataOut.height[0, :]))) + else: + h_select = numpy.where(numpy.bitwise_and(self.dataOut.height[0, :] >= 0., self.dataOut.height[0, :] < 20, numpy.isfinite(self.dataOut.height[0, :]))) + + ht = h_select[0] + + self.o_height = self.dataOut.height[self.im, ht] + self.o_zon = self.z_zon[ht, self.im] + self.o_mer = self.z_mer[ht, self.im] + self.o_ver = self.z_ver[ht, self.im] + o_snr = self.dataOut.data_SNR[ :, :, self.im] + + o_snr = o_snr[ht, :] + + ndiv = numpy.nansum((numpy.isfinite(o_snr)), 1) + ndiv = ndiv.astype(float) + + sel_div = numpy.where(ndiv == 0.) + ndiv[sel_div] = numpy.nan + + if self.nchannels > 1: + msnr = numpy.nansum(o_snr, axis=1) + else: + msnr = o_snr + + try: + self.msnr = 10 * numpy.log10(msnr / ndiv) + except ZeroDivisionError: + self.msnr = 10 * numpy.log10(msnr /1) + print 'Number of division (ndiv) egal to 1 by default. Check SNR' + + time_t = time.gmtime(self.dataOut.time1) + year = time_t.tm_year + month = time_t.tm_mon + day = time_t.tm_mday + hour = time_t.tm_hour + minute = time_t.tm_min + second = time_t.tm_sec + timedate_0 = datetime.datetime(year, month, day, hour, minute, second) + + # 1d parameters + GDLATR = self.lat + GDLONR = self.lon + GDLAT2 = self.lat + GLON2 = self.lon + + # 2d parameters + GDALT = self.o_height + + SNL = self.msnr + VN1P2 = self.o_zon + VN2P2 = self.o_mer + EL2 = self.o_ver + NROW = len(self.o_height) + + startTime = timedate_0 + endTime = startTime + self.dataRec = madrigal.cedar.MadrigalDataRecord(self.kinst, + self.kindat, + startTime.year, + startTime.month, + startTime.day, + startTime.hour, + startTime.minute, + startTime.second, + 0, + endTime.year, + endTime.month, + endTime.day, + endTime.hour, + endTime.minute, + endTime.second, + 0, + ('gdlatr', 'gdlonr', 'gdlat2', 'glon2'), + ('gdalt', 'snl', 'vn1p2', 'vn2p2', 'el2'), + NROW, ind2DList=['gdalt']) + + # Setting 1d values + self.dataRec.set1D('gdlatr', GDLATR) + self.dataRec.set1D('gdlonr', GDLONR) + self.dataRec.set1D('gdlat2', GDLAT2) + self.dataRec.set1D('glon2', GLON2) + + # Setting 2d values + for n in range(self.o_height.shape[0]): + self.dataRec.set2D('gdalt', n, GDALT[n]) + self.dataRec.set2D('snl', n, SNL[n]) + self.dataRec.set2D('vn1p2', n, VN1P2[n]) + self.dataRec.set2D('vn2p2', n, VN2P2[n]) + self.dataRec.set2D('el2', n, EL2[n]) + + # Appending new data record + ''' + [MADRIGAL3]There are two ways to write to a MadrigalCedarFile. Either this method (write) is called after all the + records have been appended to the MadrigalCedarFile, or dump is called after a certain number of records are appended, + and then at the end dump is called a final time if there were any records not yet dumped, followed by addArray. + ''' + + self.cedarObj.append(self.dataRec) + print ' [Writing] records {} (mode {}).'.format(self.dataOut.counter_records,self.im+1) + self.cedarObj.dump() + + + + + def setHeader(self): + ''' + - Creating self.catHeadObj + - Adding information catalog + - Writing file header + + ''' + self.catHeadObj = madrigal.cedar.CatalogHeaderCreator(self.fullname) + kindatDesc, comments, analyst, history, principleInvestigator = self._info_BLTR() + + self.catHeadObj.createCatalog(principleInvestigator="Jarjar", + expPurpose='characterize the atmospheric dynamics in this region where frequently it happens the El Nino', + sciRemarks="http://madrigal3.haystack.mit.edu/static/CEDARMadrigalHdf5Format.pdf") + + self.catHeadObj.createHeader(kindatDesc, analyst, comments, history) + + self.catHeadObj.write() + + print '[File created] path: %s' % (self.fullname) + + def putData(self): + + if self.dataOut.flagNoData: + return 0 + + if self.dataOut.counter_records == 1: + self.setFile() + print '[Writing] Setting new hdf5 file for the mode {}'.format(self.im+1) + + if self.dataOut.counter_records <= self.dataOut.nrecords: + self.writeBlock() + + + if self.dataOut.counter_records == self.dataOut.nrecords: + self.cedarObj.addArray() + + self.setHeader() + self.flagIsNewFile = 1 + + def _info_BLTR(self): + + kindatDesc = '''--This header is for KINDAT = %d''' % self.kindat + history = None + analyst = '''Jarjar''' + principleInvestigator = ''' + Jarjar + Radio Observatorio de Jicamarca + Instituto Geofisico del Peru + + ''' + if self.type == 1: + comments = ''' + + --These data are provided by two Boundary Layer and Tropospheric Radar (BLTR) deployed at two different locations at Peru(GMT-5), one of them at Piura(5.17 S, 80.64W) and another located at Huancayo (12.04 S, 75.32 W). + + --The purpose of conducting these observations is to measure wind in the differents levels of height, this radar makes measurements the Zonal(U), Meridional(V) and Vertical(W) wind velocities component in northcoast from Peru. And the main purpose of these mensurations is to characterize the atmospheric dynamics in this region where frequently it happens the 'El Nino Phenomenon' + + --In Kindat = 1600, contains information of wind velocities component since 0 Km to 3 Km. + + --In Kindat = 1601, contains information of wind velocities component since 0 Km to 10 Km. + + --The Huancayo-BLTR is a VHF Profiler Radar System is a 3 channel coherent receiver pulsed radar utilising state-of-the-art software and computing techniques to acquire, decode, and translate signals obtained from partial reflection echoes in the troposphere, lower stratosphere and mesosphere. It uses an array of three horizontal spaced and vertically directed receiving antennas. The data is recorded thirty seconds, averaged to one minute mean values of Height, Zonal, Meridional and Vertical wind. + + --The Huancayo-BLTR was installed in January 2010. This instrument was designed and constructed by Genesis Soft Pty. Ltd. Is constituted by three groups of spaced antennas (distributed) forming an isosceles triangle. + + + Station _______ Geographic Coord ______ Geomagnetic Coord + + _______________ Latitude _ Longitude __ Latitude _ Longitude + + Huancayo (HUA) __12.04 S ___ 75.32 W _____ -12.05 ____ 352.85 + Piura (PIU) _____ 5.17 S ___ 80.64 W ______ 5.18 ____ 350.93 + + WIND OBSERVATIONS + + --To obtain wind the BLTR uses Spaced Antenna technique (e.g., Briggs 1984). The scatter and reflection it still provided by variations in the refractive index as in the Doppler method(Gage and Basley,1978; Balsley and Gage 1982; Larsen and Rottger 1982), but instead of using the Doppler shift to derive the velocity components, the cross-correlation between signals in an array of three horizontally spaced and vertically directed receiving antennas is used. + + ...................................................................... + For more information, consult the following references: + - Balsley, B. B., and K. S. Gage., On the use of radars for operational wind profiling, Bull. Amer. Meteor.Soc.,63, 1009-1018, 1982. + + - Briggs, B. H., The analysis of spaced sensor data by correations techniques, Handbook for MAP, Vol. 13, SCOTEP Secretariat, University of Illinois, Urbana, 166-186, 1984. + + - Gage, K. S., and B.B. Balsley., Doppler radar probing of the clear atmosphere, Bull. Amer. Meteor.Soc., 59, 1074-1093, 1978. + + - Larsen, M. F., The Spaced Antenna Technique for Radar Wind Profiling, Journal of Atm. and Ocean. Technology. , Vol.6, 920-937, 1989. + + - Larsen, M. F., A method for single radar voracity measurements?, Handbook for MAP,SCOSTEP Secretariat, University of the Illinois, Urban, in press, 1989. + ...................................................................... + + ACKNOWLEDGEMENTS: + + --The Piura and Huancayo BLTR are part of the network of instruments operated by the Jicamarca Radio Observatory. + + --The Jicamarca Radio Observatory is a facility of the Instituto Geofisico del Peru operated with support from the NSF Cooperative Agreement ATM-0432565 through Cornell University + + ...................................................................... + + Further questions and comments should be addressed to: + Radio Observatorio de Jicamarca + Instituto Geofisico del Peru + Lima, Peru + Web URL: http://jro.igp.gob.pe + ...................................................................... + ''' + + return kindatDesc, comments, analyst, history, principleInvestigator + diff --git a/schainpy/model/io/.svn/text-base/io_bltr_block.pyc.svn-base b/schainpy/model/io/.svn/text-base/io_bltr_block.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..ce803599b800c4324a04160f9a3e410aa6c5a24e GIT binary patch literal 30940 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 literal 0 Hc$@=self.startDate and thisDate <= self.endDate): + return amisr_dirname_format + except: + return None + + def __findDataForDates(self,online=False): + + + + if not(self.status): + return None + + pat = '\d+.\d+' + dirnameList = [re.search(pat,x) for x in os.listdir(self.path)] + dirnameList = filter(lambda x:x!=None,dirnameList) + dirnameList = [x.string for x in dirnameList] + if not(online): + dirnameList = [self.__selDates(x) for x in dirnameList] + dirnameList = filter(lambda x:x!=None,dirnameList) + if len(dirnameList)>0: + self.status = 1 + self.dirnameList = dirnameList + self.dirnameList.sort() + else: + self.status = 0 + return None + + def __getTimeFromData(self): + startDateTime_Reader = datetime.datetime.combine(self.startDate,self.startTime) + endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime) + + print 'Filtering Files from %s to %s'%(startDateTime_Reader, endDateTime_Reader) + print '........................................' + filter_filenameList = [] + self.filenameList.sort() + for i in range(len(self.filenameList)-1): + filename = self.filenameList[i] + fp = h5py.File(filename,'r') + time_str = fp.get('Time/RadacTimeString') + + startDateTimeStr_File = time_str[0][0].split('.')[0] + junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S') + startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec) + + endDateTimeStr_File = time_str[-1][-1].split('.')[0] + junk = time.strptime(endDateTimeStr_File, '%Y-%m-%d %H:%M:%S') + endDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec) + + fp.close() + + if self.timezone == 'lt': + startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300) + endDateTime_File = endDateTime_File - datetime.timedelta(minutes = 300) + + if (endDateTime_File>=startDateTime_Reader and endDateTime_File0: + self.status = 1 + self.filenameList.sort() + else: + self.status = 0 + return None + + else: + #get the last file - 1 + self.filenameList = [self.filenameList[-2]] + + new_dirnameList = [] + for dirname in self.dirnameList: + junk = numpy.array([dirname in x for x in self.filenameList]) + junk_sum = junk.sum() + if junk_sum > 0: + new_dirnameList.append(dirname) + self.dirnameList = new_dirnameList + return 1 + + def __searchFilesOnline(self, + path, + walk=True): + + startDate = datetime.datetime.utcnow().date() + endDate = datetime.datetime.utcnow().date() + + self.__setParameters(path=path, startDate=startDate, endDate=endDate, walk=walk) + + self.__checkPath() + + self.__findDataForDates(online=True) + + self.dirnameList = [self.dirnameList[-1]] + + self.__selectDataForTimes(online=True) + + return + + + def __searchFilesOffline(self, + path, + startDate, + endDate, + startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59), + walk=True): + + self.__setParameters(path, startDate, endDate, startTime, endTime, walk) + + self.__checkPath() + + self.__findDataForDates() + + self.__selectDataForTimes() + + for i in range(len(self.filenameList)): + print "%s" %(self.filenameList[i]) + + return + + def __setNextFileOffline(self): + idFile = self.fileIndex + + while (True): + idFile += 1 + if not(idFile < len(self.filenameList)): + self.flagNoMoreFiles = 1 + print "No more Files" + return 0 + + filename = self.filenameList[idFile] + + amisrFilePointer = h5py.File(filename,'r') + + break + + self.flagIsNewFile = 1 + self.fileIndex = idFile + self.filename = filename + + self.amisrFilePointer = amisrFilePointer + + print "Setting the file: %s"%self.filename + + return 1 + + + def __setNextFileOnline(self): + filename = self.filenameList[0] + if self.__filename_online != None: + self.__selectDataForTimes(online=True) + filename = self.filenameList[0] + while self.__filename_online == filename: + print 'waiting %d seconds to get a new file...'%(self.__waitForNewFile) + sleep(self.__waitForNewFile) + self.__selectDataForTimes(online=True) + filename = self.filenameList[0] + + self.__filename_online = filename + + self.amisrFilePointer = h5py.File(filename,'r') + self.flagIsNewFile = 1 + self.filename = filename + print "Setting the file: %s"%self.filename + return 1 + + + def __readHeader(self): + self.radacHeaderObj = RadacHeader(self.amisrFilePointer) + + #update values from experiment cfg file + if self.radacHeaderObj.nrecords == self.recordsperfile_fromfile: + self.radacHeaderObj.nrecords = self.recordsperfile_fromfile + self.radacHeaderObj.nbeams = self.nbeamcodes_fromfile + self.radacHeaderObj.npulses = self.npulsesint_fromfile + self.radacHeaderObj.nsamples = self.ngates_fromfile + + #looking index list for data + start_index = self.radacHeaderObj.pulseCount[0,:][0] + end_index = self.radacHeaderObj.npulses + range4data = range(start_index, end_index) + self.index4_schain_datablock = numpy.array(range4data) + + buffer_start_index = 0 + buffer_end_index = self.radacHeaderObj.pulseCount[0,:][0] + range4buffer = range(buffer_start_index, buffer_end_index) + self.index4_buffer = numpy.array(range4buffer) + + self.linear_pulseCount = numpy.array(range4data + range4buffer) + self.npulseByFrame = max(self.radacHeaderObj.pulseCount[0,:]+1) + + #get tuning frequency + frequency_h5file_dataset = self.amisrFilePointer.get('Rx'+'/TuningFrequency') + self.frequency_h5file = frequency_h5file_dataset[0,0] + + self.flagIsNewFile = 1 + + def __getBeamCode(self): + self.beamCodeDict = {} + self.beamRangeDict = {} + + beamCodeMap = self.amisrFilePointer.get('Setup/BeamcodeMap') + + for i in range(len(self.radacHeaderObj.beamCode[0,:])): + self.beamCodeDict.setdefault(i) + self.beamRangeDict.setdefault(i) + beamcodeValue = self.radacHeaderObj.beamCode[0,i] + beamcodeIndex = numpy.where(beamCodeMap[:,0] == beamcodeValue)[0][0] + x = beamCodeMap[beamcodeIndex][1] + y = beamCodeMap[beamcodeIndex][2] + z = beamCodeMap[beamcodeIndex][3] + self.beamCodeDict[i] = [beamcodeValue, x, y, z] + + just4record0 = self.radacHeaderObj.beamCodeByPulse[0,:] + + for i in range(len(self.beamCodeDict.values())): + xx = numpy.where(just4record0==self.beamCodeDict.values()[i][0]) + indexPulseByBeam = self.linear_pulseCount[xx[0]] + self.beamRangeDict[i] = indexPulseByBeam + + def __getExpParameters(self): + if not(self.status): + return None + + experimentCfgPath = os.path.join(self.path, self.dirnameList[0], 'Setup') + + expFinder = glob.glob1(experimentCfgPath,'*.exp') + if len(expFinder)== 0: + self.status = 0 + return None + + experimentFilename = os.path.join(experimentCfgPath,expFinder[0]) + + f = open(experimentFilename) + lines = f.readlines() + f.close() + + parmsList = ['npulsesint*','recordsperfile*','nbeamcodes*','ngates*'] + filterList = [fnmatch.filter(lines, x) for x in parmsList] + + + values = [re.sub(r'\D',"",x[0]) for x in filterList] + + self.npulsesint_fromfile = int(values[0]) + self.recordsperfile_fromfile = int(values[1]) + self.nbeamcodes_fromfile = int(values[2]) + self.ngates_fromfile = int(values[3]) + + tufileFinder = fnmatch.filter(lines, 'tufile=*') + tufile = tufileFinder[0].split('=')[1].split('\n')[0] + tufile = tufile.split('\r')[0] + tufilename = os.path.join(experimentCfgPath,tufile) + + f = open(tufilename) + lines = f.readlines() + f.close() + self.ippSeconds_fromfile = float(lines[1].split()[2])/1E6 + + + self.status = 1 + + def __setIdsAndArrays(self): + self.dataByFrame = self.__setDataByFrame() + self.beamCodeByFrame = self.amisrFilePointer.get('Raw11/Data/RadacHeader/BeamCode').value[0, :] + self.readRanges() + self.index_amisr_sample, self.index_amisr_buffer = self.radacHeaderObj.getIndexRangeToPulse(0) + self.radacTimeByFrame = numpy.zeros(self.radacHeaderObj.npulses) + if len(self.index_amisr_buffer) > 0: + self.buffer_radactime = numpy.zeros_like(self.radacTimeByFrame) + + + def __setNextFile(self,online=False): + + if not(online): + newFile = self.__setNextFileOffline() + else: + newFile = self.__setNextFileOnline() + + if not(newFile): + return 0 + + self.__readHeader() + + if self.__firstFile: + self.__setIdsAndArrays() + self.__firstFile = False + + self.__getBeamCode() + self.readDataBlock() + + + def setup(self,path=None, + startDate=None, + endDate=None, + startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59), + walk=True, + timezone='ut', + all=0, + online=False): + + self.timezone = timezone + self.all = all + self.online = online + if not(online): + #Busqueda de archivos offline + self.__searchFilesOffline(path, startDate, endDate, startTime, endTime, walk) + else: + self.__searchFilesOnline(path, walk) + + if not(self.filenameList): + print "There is no files into the folder: %s"%(path) + + sys.exit(-1) + + self.__getExpParameters() + + self.fileIndex = -1 + + self.__setNextFile(online) + +# first_beamcode = self.radacHeaderObj.beamCodeByPulse[0,0] +# index = numpy.where(self.radacHeaderObj.beamCodeByPulse[0,:]!=first_beamcode)[0][0] + self.profileIndex_offset = self.radacHeaderObj.pulseCount[0,:][0] + self.profileIndex = self.profileIndex_offset + + def readRanges(self): + dataset = self.amisrFilePointer.get('Raw11/Data/Samples/Range') + + self.rangeFromFile = numpy.reshape(dataset.value,(-1)) + return self.rangeFromFile + + + def readRadacTime(self,idrecord, range1, range2): + self.radacTimeFromFile = self.radacHeaderObj.radacTime.value + + radacTimeByFrame = numpy.zeros((self.radacHeaderObj.npulses)) + #radacTimeByFrame = dataset[idrecord - 1,range1] + #radacTimeByFrame = dataset[idrecord,range2] + + return radacTimeByFrame + + def readBeamCode(self, idrecord, range1, range2): + dataset = self.amisrFilePointer.get('Raw11/Data/RadacHeader/BeamCode') + beamcodeByFrame = numpy.zeros((self.radacHeaderObj.npulses)) + self.beamCodesFromFile = dataset.value + + #beamcodeByFrame[range1] = dataset[idrecord - 1, range1] + #beamcodeByFrame[range2] = dataset[idrecord, range2] + beamcodeByFrame[range1] = dataset[idrecord, range1] + beamcodeByFrame[range2] = dataset[idrecord, range2] + + return beamcodeByFrame + + + def __setDataByFrame(self): + ndata = 2 # porque es complejo + dataByFrame = numpy.zeros((self.radacHeaderObj.npulses, self.radacHeaderObj.nsamples, ndata)) + return dataByFrame + + def __readDataSet(self): + dataset = self.amisrFilePointer.get('Raw11/Data/Samples/Data') + return dataset + + def __setDataBlock(self,): + real = self.dataByFrame[:,:,0] #asumo que 0 es real + imag = self.dataByFrame[:,:,1] #asumo que 1 es imaginario + datablock = real + imag*1j #armo el complejo + return datablock + + def readSamples_version1(self,idrecord): + #estas tres primeras lineas solo se deben ejecutar una vez + if self.flagIsNewFile: + #reading dataset + self.dataset = self.__readDataSet() + self.flagIsNewFile = 0 + + if idrecord == 0: + self.dataByFrame[self.index4_schain_datablock, : ,:] = self.dataset[0, self.index_amisr_sample,:,:] + self.radacTimeByFrame[self.index4_schain_datablock] = self.radacHeaderObj.radacTime[0, self.index_amisr_sample] + datablock = self.__setDataBlock() + if len(self.index_amisr_buffer) > 0: + self.buffer = self.dataset[0, self.index_amisr_buffer,:,:] + self.buffer_radactime = self.radacHeaderObj.radacTime[0, self.index_amisr_buffer] + + return datablock + if len(self.index_amisr_buffer) > 0: + self.dataByFrame[self.index4_buffer,:,:] = self.buffer.copy() + self.radacTimeByFrame[self.index4_buffer] = self.buffer_radactime.copy() + self.dataByFrame[self.index4_schain_datablock,:,:] = self.dataset[idrecord, self.index_amisr_sample,:,:] + self.radacTimeByFrame[self.index4_schain_datablock] = self.radacHeaderObj.radacTime[idrecord, self.index_amisr_sample] + datablock = self.__setDataBlock() + if len(self.index_amisr_buffer) > 0: + self.buffer = self.dataset[idrecord, self.index_amisr_buffer, :, :] + self.buffer_radactime = self.radacHeaderObj.radacTime[idrecord, self.index_amisr_buffer] + + return datablock + + + def readSamples(self,idrecord): + if self.flagIsNewFile: + self.dataByFrame = self.__setDataByFrame() + self.beamCodeByFrame = self.amisrFilePointer.get('Raw11/Data/RadacHeader/BeamCode').value[idrecord, :] + + #reading ranges + self.readRanges() + #reading dataset + self.dataset = self.__readDataSet() + + self.flagIsNewFile = 0 + self.radacTimeByFrame = self.radacHeaderObj.radacTime.value[idrecord, :] + self.dataByFrame = self.dataset[idrecord, :, :, :] + datablock = self.__setDataBlock() + return datablock + + + def readDataBlock(self): + + self.datablock = self.readSamples_version1(self.idrecord_count) + #self.datablock = self.readSamples(self.idrecord_count) + #print 'record:', self.idrecord_count + + self.idrecord_count += 1 + self.profileIndex = 0 + + if self.idrecord_count >= self.radacHeaderObj.nrecords: + self.idrecord_count = 0 + self.flagIsNewFile = 1 + + def readNextBlock(self): + + self.readDataBlock() + + if self.flagIsNewFile: + self.__setNextFile(self.online) + pass + + def __hasNotDataInBuffer(self): + #self.radacHeaderObj.npulses debe ser otra variable para considerar el numero de pulsos a tomar en el primer y ultimo record + if self.profileIndex >= self.radacHeaderObj.npulses: + return 1 + return 0 + + def printUTC(self): + print self.dataOut.utctime + print '' + + def setObjProperties(self): + + self.dataOut.heightList = self.rangeFromFile/1000.0 #km + self.dataOut.nProfiles = self.radacHeaderObj.npulses + self.dataOut.nRecords = self.radacHeaderObj.nrecords + self.dataOut.nBeams = self.radacHeaderObj.nbeams + self.dataOut.ippSeconds = self.ippSeconds_fromfile +# self.dataOut.timeInterval = self.dataOut.ippSeconds * self.dataOut.nCohInt + self.dataOut.frequency = self.frequency_h5file + self.dataOut.npulseByFrame = self.npulseByFrame + self.dataOut.nBaud = None + self.dataOut.nCode = None + self.dataOut.code = None + + self.dataOut.beamCodeDict = self.beamCodeDict + self.dataOut.beamRangeDict = self.beamRangeDict + + if self.timezone == 'lt': + self.dataOut.timeZone = time.timezone / 60. #get the timezone in minutes + else: + self.dataOut.timeZone = 0 #by default time is UTC + + def getData(self): + + if self.flagNoMoreFiles: + self.dataOut.flagNoData = True + print 'Process finished' + return 0 + + if self.__hasNotDataInBuffer(): + self.readNextBlock() + + + if self.datablock is None: # setear esta condicion cuando no hayan datos por leers + self.dataOut.flagNoData = True + return 0 + + self.dataOut.data = numpy.reshape(self.datablock[self.profileIndex,:],(1,-1)) + + self.dataOut.utctime = self.radacTimeByFrame[self.profileIndex] + self.dataOut.profileIndex = self.profileIndex + self.dataOut.flagNoData = False + + self.profileIndex += 1 + + return self.dataOut.data + + + def run(self, **kwargs): + if not(self.isConfig): + self.setup(**kwargs) + self.setObjProperties() + self.isConfig = True + + self.getData() diff --git a/schainpy/model/io/.svn/text-base/jroIO_base.py.svn-base b/schainpy/model/io/.svn/text-base/jroIO_base.py.svn-base new file mode 100644 index 0000000..c4c7769 --- /dev/null +++ b/schainpy/model/io/.svn/text-base/jroIO_base.py.svn-base @@ -0,0 +1,1723 @@ +''' +Created on Jul 2, 2014 + +@author: roj-idl71 +''' +import os +import sys +import glob +import time +import numpy +import fnmatch +import time, datetime +#import h5py +import traceback + +try: + from gevent import sleep +except: + from time import sleep + +from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader +from schainpy.model.data.jroheaderIO import get_dtype_index, get_numpy_dtype, get_procflag_dtype, get_dtype_width + +LOCALTIME = True + +def isNumber(cad): + """ + Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero. + + Excepciones: + Si un determinado string no puede ser convertido a numero + Input: + str, string al cual se le analiza para determinar si convertible a un numero o no + + Return: + True : si el string es uno numerico + False : no es un string numerico + """ + try: + float( cad ) + return True + except: + return False + +def isFileInEpoch(filename, startUTSeconds, endUTSeconds): + """ + Esta funcion determina si un archivo de datos se encuentra o no dentro del rango de fecha especificado. + + Inputs: + filename : nombre completo del archivo de datos en formato Jicamarca (.r) + + startUTSeconds : fecha inicial del rango seleccionado. La fecha esta dada en + segundos contados desde 01/01/1970. + endUTSeconds : fecha final del rango seleccionado. La fecha esta dada en + segundos contados desde 01/01/1970. + + Return: + Boolean : Retorna True si el archivo de datos contiene datos en el rango de + fecha especificado, de lo contrario retorna False. + + Excepciones: + Si el archivo no existe o no puede ser abierto + Si la cabecera no puede ser leida. + + """ + basicHeaderObj = BasicHeader(LOCALTIME) + + try: + fp = open(filename,'rb') + except IOError: + print "The file %s can't be opened" %(filename) + return 0 + + sts = basicHeaderObj.read(fp) + fp.close() + + if not(sts): + print "Skipping the file %s because it has not a valid header" %(filename) + return 0 + + if not ((startUTSeconds <= basicHeaderObj.utc) and (endUTSeconds > basicHeaderObj.utc)): + return 0 + + return 1 + +def isTimeInRange(thisTime, startTime, endTime): + + if endTime >= startTime: + if (thisTime < startTime) or (thisTime > endTime): + return 0 + + return 1 + else: + if (thisTime < startTime) and (thisTime > endTime): + return 0 + + return 1 + +def isFileInTimeRange(filename, startDate, endDate, startTime, endTime): + """ + Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado. + + Inputs: + filename : nombre completo del archivo de datos en formato Jicamarca (.r) + + startDate : fecha inicial del rango seleccionado en formato datetime.date + + endDate : fecha final del rango seleccionado en formato datetime.date + + startTime : tiempo inicial del rango seleccionado en formato datetime.time + + endTime : tiempo final del rango seleccionado en formato datetime.time + + Return: + Boolean : Retorna True si el archivo de datos contiene datos en el rango de + fecha especificado, de lo contrario retorna False. + + Excepciones: + Si el archivo no existe o no puede ser abierto + Si la cabecera no puede ser leida. + + """ + + + try: + fp = open(filename,'rb') + except IOError: + print "The file %s can't be opened" %(filename) + return None + + firstBasicHeaderObj = BasicHeader(LOCALTIME) + systemHeaderObj = SystemHeader() + radarControllerHeaderObj = RadarControllerHeader() + processingHeaderObj = ProcessingHeader() + + lastBasicHeaderObj = BasicHeader(LOCALTIME) + + sts = firstBasicHeaderObj.read(fp) + + if not(sts): + print "[Reading] Skipping the file %s because it has not a valid header" %(filename) + return None + + if not systemHeaderObj.read(fp): + return None + + if not radarControllerHeaderObj.read(fp): + return None + + if not processingHeaderObj.read(fp): + return None + + filesize = os.path.getsize(filename) + + offset = processingHeaderObj.blockSize + 24 #header size + + if filesize <= offset: + print "[Reading] %s: This file has not enough data" %filename + return None + + fp.seek(-offset, 2) + + sts = lastBasicHeaderObj.read(fp) + + fp.close() + + thisDatetime = lastBasicHeaderObj.datatime + thisTime_last_block = thisDatetime.time() + + thisDatetime = firstBasicHeaderObj.datatime + thisDate = thisDatetime.date() + thisTime_first_block = thisDatetime.time() + + #General case + # o>>>>>>>>>>>>>><<<<<<<<<<<<<= startTime: + if (thisTime_last_block < startTime) or (thisTime_first_block > endTime): + return None + + return thisDatetime + + #If endTime < startTime then endTime belongs to the next day + + + #<<<<<<<<<<>>>>>>>>>> + #-----------o----------------------------o----------- + # endTime startTime + + if (thisDate == startDate) and (thisTime_last_block < startTime): + return None + + if (thisDate == endDate) and (thisTime_first_block > endTime): + return None + + if (thisTime_last_block < startTime) and (thisTime_first_block > endTime): + return None + + return thisDatetime + +def isFolderInDateRange(folder, startDate=None, endDate=None): + """ + Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado. + + Inputs: + folder : nombre completo del directorio. + Su formato deberia ser "/path_root/?YYYYDDD" + + siendo: + YYYY : Anio (ejemplo 2015) + DDD : Dia del anio (ejemplo 305) + + startDate : fecha inicial del rango seleccionado en formato datetime.date + + endDate : fecha final del rango seleccionado en formato datetime.date + + Return: + Boolean : Retorna True si el archivo de datos contiene datos en el rango de + fecha especificado, de lo contrario retorna False. + Excepciones: + Si el directorio no tiene el formato adecuado + """ + + basename = os.path.basename(folder) + + if not isRadarFolder(basename): + print "The folder %s has not the rigth format" %folder + return 0 + + if startDate and endDate: + thisDate = getDateFromRadarFolder(basename) + + if thisDate < startDate: + return 0 + + if thisDate > endDate: + return 0 + + return 1 + +def isFileInDateRange(filename, startDate=None, endDate=None): + """ + Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado. + + Inputs: + filename : nombre completo del archivo de datos en formato Jicamarca (.r) + + Su formato deberia ser "?YYYYDDDsss" + + siendo: + YYYY : Anio (ejemplo 2015) + DDD : Dia del anio (ejemplo 305) + sss : set + + startDate : fecha inicial del rango seleccionado en formato datetime.date + + endDate : fecha final del rango seleccionado en formato datetime.date + + Return: + Boolean : Retorna True si el archivo de datos contiene datos en el rango de + fecha especificado, de lo contrario retorna False. + Excepciones: + Si el archivo no tiene el formato adecuado + """ + + basename = os.path.basename(filename) + + if not isRadarFile(basename): + print "The filename %s has not the rigth format" %filename + return 0 + + if startDate and endDate: + thisDate = getDateFromRadarFile(basename) + + if thisDate < startDate: + return 0 + + if thisDate > endDate: + return 0 + + return 1 + +def getFileFromSet(path, ext, set): + validFilelist = [] + fileList = os.listdir(path) + + # 0 1234 567 89A BCDE + # H YYYY DDD SSS .ext + + for thisFile in fileList: + try: + year = int(thisFile[1:5]) + doy = int(thisFile[5:8]) + except: + continue + + if (os.path.splitext(thisFile)[-1].lower() != ext.lower()): + continue + + validFilelist.append(thisFile) + + myfile = fnmatch.filter(validFilelist,'*%4.4d%3.3d%3.3d*'%(year,doy,set)) + + if len(myfile)!= 0: + return myfile[0] + else: + filename = '*%4.4d%3.3d%3.3d%s'%(year,doy,set,ext.lower()) + print 'the filename %s does not exist'%filename + print '...going to the last file: ' + + if validFilelist: + validFilelist = sorted( validFilelist, key=str.lower ) + return validFilelist[-1] + + return None + +def getlastFileFromPath(path, ext): + """ + Depura el fileList dejando solo los que cumplan el formato de "PYYYYDDDSSS.ext" + al final de la depuracion devuelve el ultimo file de la lista que quedo. + + Input: + fileList : lista conteniendo todos los files (sin path) que componen una determinada carpeta + ext : extension de los files contenidos en una carpeta + + Return: + El ultimo file de una determinada carpeta, no se considera el path. + """ + validFilelist = [] + fileList = os.listdir(path) + + # 0 1234 567 89A BCDE + # H YYYY DDD SSS .ext + + for thisFile in fileList: + + year = thisFile[1:5] + if not isNumber(year): + continue + + doy = thisFile[5:8] + if not isNumber(doy): + continue + + year = int(year) + doy = int(doy) + + if (os.path.splitext(thisFile)[-1].lower() != ext.lower()): + continue + + validFilelist.append(thisFile) + + if validFilelist: + validFilelist = sorted( validFilelist, key=str.lower ) + return validFilelist[-1] + + return None + +def checkForRealPath(path, foldercounter, year, doy, set, ext): + """ + Por ser Linux Case Sensitive entonces checkForRealPath encuentra el nombre correcto de un path, + Prueba por varias combinaciones de nombres entre mayusculas y minusculas para determinar + el path exacto de un determinado file. + + Example : + nombre correcto del file es .../.../D2009307/P2009307367.ext + + Entonces la funcion prueba con las siguientes combinaciones + .../.../y2009307367.ext + .../.../Y2009307367.ext + .../.../x2009307/y2009307367.ext + .../.../x2009307/Y2009307367.ext + .../.../X2009307/y2009307367.ext + .../.../X2009307/Y2009307367.ext + siendo para este caso, la ultima combinacion de letras, identica al file buscado + + Return: + Si encuentra la cobinacion adecuada devuelve el path completo y el nombre del file + caso contrario devuelve None como path y el la ultima combinacion de nombre en mayusculas + para el filename + """ + fullfilename = None + find_flag = False + filename = None + + prefixDirList = [None,'d','D'] + if ext.lower() == ".r": #voltage + prefixFileList = ['d','D'] + elif ext.lower() == ".pdata": #spectra + prefixFileList = ['p','P'] + else: + return None, filename + + #barrido por las combinaciones posibles + for prefixDir in prefixDirList: + thispath = path + if prefixDir != None: + #formo el nombre del directorio xYYYYDDD (x=d o x=D) + if foldercounter == 0: + thispath = os.path.join(path, "%s%04d%03d" % ( prefixDir, year, doy )) + else: + thispath = os.path.join(path, "%s%04d%03d_%02d" % ( prefixDir, year, doy , foldercounter)) + for prefixFile in prefixFileList: #barrido por las dos combinaciones posibles de "D" + filename = "%s%04d%03d%03d%s" % ( prefixFile, year, doy, set, ext ) #formo el nombre del file xYYYYDDDSSS.ext + fullfilename = os.path.join( thispath, filename ) #formo el path completo + + if os.path.exists( fullfilename ): #verifico que exista + find_flag = True + break + if find_flag: + break + + if not(find_flag): + return None, filename + + return fullfilename, filename + +def isRadarFolder(folder): + try: + year = int(folder[1:5]) + doy = int(folder[5:8]) + except: + return 0 + + return 1 + +def isRadarFile(file): + try: + year = int(file[1:5]) + doy = int(file[5:8]) + set = int(file[8:11]) + except: + return 0 + + return 1 + +def getDateFromRadarFile(file): + try: + year = int(file[1:5]) + doy = int(file[5:8]) + set = int(file[8:11]) + except: + return None + + thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy-1) + return thisDate + +def getDateFromRadarFolder(folder): + try: + year = int(folder[1:5]) + doy = int(folder[5:8]) + except: + return None + + thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy-1) + return thisDate + +class JRODataIO: + + c = 3E8 + + isConfig = False + + basicHeaderObj = None + + systemHeaderObj = None + + radarControllerHeaderObj = None + + processingHeaderObj = None + + dtype = None + + pathList = [] + + filenameList = [] + + filename = None + + ext = None + + flagIsNewFile = 1 + + flagDiscontinuousBlock = 0 + + flagIsNewBlock = 0 + + fp = None + + firstHeaderSize = 0 + + basicHeaderSize = 24 + + versionFile = 1103 + + fileSize = None + +# ippSeconds = None + + fileSizeByHeader = None + + fileIndex = None + + profileIndex = None + + blockIndex = None + + nTotalBlocks = None + + maxTimeStep = 30 + + lastUTTime = None + + datablock = None + + dataOut = None + + blocksize = None + + getByBlock = False + + def __init__(self): + + raise NotImplementedError + + def run(self): + + raise NotImplementedError + + def getDtypeWidth(self): + + dtype_index = get_dtype_index(self.dtype) + dtype_width = get_dtype_width(dtype_index) + + return dtype_width + +class JRODataReader(JRODataIO): + + + online = 0 + + realtime = 0 + + nReadBlocks = 0 + + delay = 10 #number of seconds waiting a new file + + nTries = 3 #quantity tries + + nFiles = 3 #number of files for searching + + path = None + + foldercounter = 0 + + flagNoMoreFiles = 0 + + datetimeList = [] + + __isFirstTimeOnline = 1 + + __printInfo = True + + profileIndex = None + + nTxs = 1 + + txIndex = None + + #Added-------------------- + + selBlocksize = None + + selBlocktime = None + + + def __init__(self): + + """ + This class is used to find data files + + Example: + reader = JRODataReader() + fileList = reader.findDataFiles() + + """ + pass + + + def createObjByDefault(self): + """ + + """ + raise NotImplementedError + + def getBlockDimension(self): + + raise NotImplementedError + + def __searchFilesOffLine(self, + path, + startDate=None, + endDate=None, + startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59), + set=None, + expLabel='', + ext='.r', + walk=True): + + self.filenameList = [] + self.datetimeList = [] + + pathList = [] + + dateList, pathList = self.findDatafiles(path, startDate, endDate, expLabel, ext, walk, include_path=True) + + if dateList == []: +# print "[Reading] Date range selected invalid [%s - %s]: No *%s files in %s)" %(startDate, endDate, ext, path) + return None, None + + if len(dateList) > 1: + print "[Reading] Data found for date range [%s - %s]: total days = %d" %(startDate, endDate, len(dateList)) + else: + print "[Reading] Data found for date range [%s - %s]: date = %s" %(startDate, endDate, dateList[0]) + + filenameList = [] + datetimeList = [] + + for thisPath in pathList: +# thisPath = pathList[pathDict[file]] + + fileList = glob.glob1(thisPath, "*%s" %ext) + fileList.sort() + + for file in fileList: + + filename = os.path.join(thisPath,file) + + if not isFileInDateRange(filename, startDate, endDate): + continue + + thisDatetime = isFileInTimeRange(filename, startDate, endDate, startTime, endTime) + + if not(thisDatetime): + continue + + filenameList.append(filename) + datetimeList.append(thisDatetime) + + if not(filenameList): + print "[Reading] Time range selected invalid [%s - %s]: No *%s files in %s)" %(startTime, endTime, ext, path) + return None, None + + print "[Reading] %d file(s) was(were) found in time range: %s - %s" %(len(filenameList), startTime, endTime) + print + + for i in range(len(filenameList)): + print "[Reading] %s -> [%s]" %(filenameList[i], datetimeList[i].ctime()) + + self.filenameList = filenameList + self.datetimeList = datetimeList + + return pathList, filenameList + + def __searchFilesOnLine(self, path, expLabel = "", ext = None, walk=True, set=None): + + """ + Busca el ultimo archivo de la ultima carpeta (determinada o no por startDateTime) y + devuelve el archivo encontrado ademas de otros datos. + + Input: + path : carpeta donde estan contenidos los files que contiene data + + expLabel : Nombre del subexperimento (subfolder) + + ext : extension de los files + + walk : Si es habilitado no realiza busquedas dentro de los ubdirectorios (doypath) + + Return: + directory : eL directorio donde esta el file encontrado + filename : el ultimo file de una determinada carpeta + year : el anho + doy : el numero de dia del anho + set : el set del archivo + + + """ + if not os.path.isdir(path): + return None, None, None, None, None, None + + dirList = [] + + if not walk: + fullpath = path + foldercounter = 0 + else: + #Filtra solo los directorios + for thisPath in os.listdir(path): + if not os.path.isdir(os.path.join(path,thisPath)): + continue + if not isRadarFolder(thisPath): + continue + + dirList.append(thisPath) + + if not(dirList): + return None, None, None, None, None, None + + dirList = sorted( dirList, key=str.lower ) + + doypath = dirList[-1] + foldercounter = int(doypath.split('_')[1]) if len(doypath.split('_'))>1 else 0 + fullpath = os.path.join(path, doypath, expLabel) + + + print "[Reading] %s folder was found: " %(fullpath ) + + if set == None: + filename = getlastFileFromPath(fullpath, ext) + else: + filename = getFileFromSet(fullpath, ext, set) + + if not(filename): + return None, None, None, None, None, None + + print "[Reading] %s file was found" %(filename) + + if not(self.__verifyFile(os.path.join(fullpath, filename))): + return None, None, None, None, None, None + + year = int( filename[1:5] ) + doy = int( filename[5:8] ) + set = int( filename[8:11] ) + + return fullpath, foldercounter, filename, year, doy, set + + def __setNextFileOffline(self): + + idFile = self.fileIndex + + while (True): + idFile += 1 + if not(idFile < len(self.filenameList)): + self.flagNoMoreFiles = 1 +# print "[Reading] No more Files" + return 0 + + filename = self.filenameList[idFile] + + if not(self.__verifyFile(filename)): + continue + + fileSize = os.path.getsize(filename) + fp = open(filename,'rb') + break + + self.flagIsNewFile = 1 + self.fileIndex = idFile + self.filename = filename + self.fileSize = fileSize + self.fp = fp + +# print "[Reading] Setting the file: %s"%self.filename + + return 1 + + def __setNextFileOnline(self): + """ + Busca el siguiente file que tenga suficiente data para ser leida, dentro de un folder especifico, si + no encuentra un file valido espera un tiempo determinado y luego busca en los posibles n files + siguientes. + + Affected: + self.flagIsNewFile + self.filename + self.fileSize + self.fp + self.set + self.flagNoMoreFiles + + Return: + 0 : si luego de una busqueda del siguiente file valido este no pudo ser encontrado + 1 : si el file fue abierto con exito y esta listo a ser leido + + Excepciones: + Si un determinado file no puede ser abierto + """ + nFiles = 0 + fileOk_flag = False + firstTime_flag = True + + self.set += 1 + + if self.set > 999: + self.set = 0 + self.foldercounter += 1 + + #busca el 1er file disponible + fullfilename, filename = checkForRealPath( self.path, self.foldercounter, self.year, self.doy, self.set, self.ext ) + if fullfilename: + if self.__verifyFile(fullfilename, False): + fileOk_flag = True + + #si no encuentra un file entonces espera y vuelve a buscar + if not(fileOk_flag): + for nFiles in range(self.nFiles+1): #busco en los siguientes self.nFiles+1 files posibles + + if firstTime_flag: #si es la 1era vez entonces hace el for self.nTries veces + tries = self.nTries + else: + tries = 1 #si no es la 1era vez entonces solo lo hace una vez + + for nTries in range( tries ): + if firstTime_flag: + print "\t[Reading] Waiting %0.2f sec for the next file: \"%s\" , try %03d ..." % ( self.delay, filename, nTries+1 ) + sleep( self.delay ) + else: + print "\t[Reading] Searching the next \"%s%04d%03d%03d%s\" file ..." % (self.optchar, self.year, self.doy, self.set, self.ext) + + fullfilename, filename = checkForRealPath( self.path, self.foldercounter, self.year, self.doy, self.set, self.ext ) + if fullfilename: + if self.__verifyFile(fullfilename): + fileOk_flag = True + break + + if fileOk_flag: + break + + firstTime_flag = False + + print "\t[Reading] Skipping the file \"%s\" due to this file doesn't exist" % filename + self.set += 1 + + if nFiles == (self.nFiles-1): #si no encuentro el file buscado cambio de carpeta y busco en la siguiente carpeta + self.set = 0 + self.doy += 1 + self.foldercounter = 0 + + if fileOk_flag: + self.fileSize = os.path.getsize( fullfilename ) + self.filename = fullfilename + self.flagIsNewFile = 1 + if self.fp != None: self.fp.close() + self.fp = open(fullfilename, 'rb') + self.flagNoMoreFiles = 0 +# print '[Reading] Setting the file: %s' % fullfilename + else: + self.fileSize = 0 + self.filename = None + self.flagIsNewFile = 0 + self.fp = None + self.flagNoMoreFiles = 1 +# print '[Reading] No more files to read' + + return fileOk_flag + + def setNextFile(self): + if self.fp != None: + self.fp.close() + + if self.online: + newFile = self.__setNextFileOnline() + else: + newFile = self.__setNextFileOffline() + + if not(newFile): + print '[Reading] No more files to read' + return 0 + + print '[Reading] Setting the file: %s' % self.filename + + self.__readFirstHeader() + self.nReadBlocks = 0 + return 1 + + def __waitNewBlock(self): + """ + Return 1 si se encontro un nuevo bloque de datos, 0 de otra forma. + + Si el modo de lectura es OffLine siempre retorn 0 + """ + if not self.online: + return 0 + + if (self.nReadBlocks >= self.processingHeaderObj.dataBlocksPerFile): + return 0 + + currentPointer = self.fp.tell() + + neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize + + for nTries in range( self.nTries ): + + self.fp.close() + self.fp = open( self.filename, 'rb' ) + self.fp.seek( currentPointer ) + + self.fileSize = os.path.getsize( self.filename ) + currentSize = self.fileSize - currentPointer + + if ( currentSize >= neededSize ): + self.basicHeaderObj.read(self.fp) + return 1 + + if self.fileSize == self.fileSizeByHeader: +# self.flagEoF = True + return 0 + + print "[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries+1) + sleep( self.delay ) + + + return 0 + + def waitDataBlock(self,pointer_location): + + currentPointer = pointer_location + + neededSize = self.processingHeaderObj.blockSize #+ self.basicHeaderSize + + for nTries in range( self.nTries ): + self.fp.close() + self.fp = open( self.filename, 'rb' ) + self.fp.seek( currentPointer ) + + self.fileSize = os.path.getsize( self.filename ) + currentSize = self.fileSize - currentPointer + + if ( currentSize >= neededSize ): + return 1 + + print "[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries+1) + sleep( self.delay ) + + return 0 + + def __jumpToLastBlock(self): + + if not(self.__isFirstTimeOnline): + return + + csize = self.fileSize - self.fp.tell() + blocksize = self.processingHeaderObj.blockSize + + #salta el primer bloque de datos + if csize > self.processingHeaderObj.blockSize: + self.fp.seek(self.fp.tell() + blocksize) + else: + return + + csize = self.fileSize - self.fp.tell() + neededsize = self.processingHeaderObj.blockSize + self.basicHeaderSize + while True: + + if self.fp.tell() 0: +# self.fp.seek(self.fp.tell() + factor*neededsize) + + self.flagIsNewFile = 0 + self.__isFirstTimeOnline = 0 + + def __setNewBlock(self): + + if self.fp == None: + return 0 + +# if self.online: +# self.__jumpToLastBlock() + + if self.flagIsNewFile: + self.lastUTTime = self.basicHeaderObj.utc + return 1 + + if self.realtime: + self.flagDiscontinuousBlock = 1 + if not(self.setNextFile()): + return 0 + else: + return 1 + + currentSize = self.fileSize - self.fp.tell() + neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize + + if (currentSize >= neededSize): + self.basicHeaderObj.read(self.fp) + self.lastUTTime = self.basicHeaderObj.utc + return 1 + + if self.__waitNewBlock(): + self.lastUTTime = self.basicHeaderObj.utc + return 1 + + if not(self.setNextFile()): + return 0 + + deltaTime = self.basicHeaderObj.utc - self.lastUTTime # + self.lastUTTime = self.basicHeaderObj.utc + + self.flagDiscontinuousBlock = 0 + + if deltaTime > self.maxTimeStep: + self.flagDiscontinuousBlock = 1 + + return 1 + + def readNextBlock(self): + + #Skip block out of startTime and endTime + while True: + if not(self.__setNewBlock()): + return 0 + + if not(self.readBlock()): + return 0 + + self.getBasicHeader() + + if not isTimeInRange(self.dataOut.datatime.time(), self.startTime, self.endTime): + + print "[Reading] Block No. %d/%d -> %s [Skipping]" %(self.nReadBlocks, + self.processingHeaderObj.dataBlocksPerFile, + self.dataOut.datatime.ctime()) + continue + + break + + print "[Reading] Block No. %d/%d -> %s" %(self.nReadBlocks, + self.processingHeaderObj.dataBlocksPerFile, + self.dataOut.datatime.ctime()) + return 1 + + def __readFirstHeader(self): + + self.basicHeaderObj.read(self.fp) + self.systemHeaderObj.read(self.fp) + self.radarControllerHeaderObj.read(self.fp) + self.processingHeaderObj.read(self.fp) + + self.firstHeaderSize = self.basicHeaderObj.size + + datatype = int(numpy.log2((self.processingHeaderObj.processFlags & PROCFLAG.DATATYPE_MASK))-numpy.log2(PROCFLAG.DATATYPE_CHAR)) + if datatype == 0: + datatype_str = numpy.dtype([('real',' %s" %(self.nReadBlocks, + self.processingHeaderObj.dataBlocksPerFile, + self.dataOut.datatime.ctime()) + + def printInfo(self): + + if self.__printInfo == False: + return + + self.basicHeaderObj.printInfo() + self.systemHeaderObj.printInfo() + self.radarControllerHeaderObj.printInfo() + self.processingHeaderObj.printInfo() + + self.__printInfo = False + + + def run(self, **kwargs): + + if not(self.isConfig): + +# self.dataOut = dataOut + self.setup(**kwargs) + self.isConfig = True + + self.getData() + +class JRODataWriter(JRODataIO): + + """ + Esta clase permite escribir datos a archivos procesados (.r o ,pdata). La escritura + de los datos siempre se realiza por bloques. + """ + + blockIndex = 0 + + path = None + + setFile = None + + profilesPerBlock = None + + blocksPerFile = None + + nWriteBlocks = 0 + + fileDate = None + + def __init__(self, dataOut=None): + raise NotImplementedError + + + def hasAllDataInBuffer(self): + raise NotImplementedError + + + def setBlockDimension(self): + raise NotImplementedError + + + def writeBlock(self): + raise NotImplementedError + + + def putData(self): + raise NotImplementedError + + + def getProcessFlags(self): + + processFlags = 0 + + dtype_index = get_dtype_index(self.dtype) + procflag_dtype = get_procflag_dtype(dtype_index) + + processFlags += procflag_dtype + + if self.dataOut.flagDecodeData: + processFlags += PROCFLAG.DECODE_DATA + + if self.dataOut.flagDeflipData: + processFlags += PROCFLAG.DEFLIP_DATA + + if self.dataOut.code is not None: + processFlags += PROCFLAG.DEFINE_PROCESS_CODE + + if self.dataOut.nCohInt > 1: + processFlags += PROCFLAG.COHERENT_INTEGRATION + + if self.dataOut.type == "Spectra": + if self.dataOut.nIncohInt > 1: + processFlags += PROCFLAG.INCOHERENT_INTEGRATION + + if self.dataOut.data_dc is not None: + processFlags += PROCFLAG.SAVE_CHANNELS_DC + + if self.dataOut.flagShiftFFT: + processFlags += PROCFLAG.SHIFT_FFT_DATA + + return processFlags + + def setBasicHeader(self): + + self.basicHeaderObj.size = self.basicHeaderSize #bytes + self.basicHeaderObj.version = self.versionFile + self.basicHeaderObj.dataBlock = self.nTotalBlocks + + utc = numpy.floor(self.dataOut.utctime) + milisecond = (self.dataOut.utctime - utc)* 1000.0 + + self.basicHeaderObj.utc = utc + self.basicHeaderObj.miliSecond = milisecond + self.basicHeaderObj.timeZone = self.dataOut.timeZone + self.basicHeaderObj.dstFlag = self.dataOut.dstFlag + self.basicHeaderObj.errorCount = self.dataOut.errorCount + + def setFirstHeader(self): + """ + Obtiene una copia del First Header + + Affected: + + self.basicHeaderObj + self.systemHeaderObj + self.radarControllerHeaderObj + self.processingHeaderObj self. + + Return: + None + """ + + raise NotImplementedError + + def __writeFirstHeader(self): + """ + Escribe el primer header del file es decir el Basic header y el Long header (SystemHeader, RadarControllerHeader, ProcessingHeader) + + Affected: + __dataType + + Return: + None + """ + +# CALCULAR PARAMETROS + + sizeLongHeader = self.systemHeaderObj.size + self.radarControllerHeaderObj.size + self.processingHeaderObj.size + self.basicHeaderObj.size = self.basicHeaderSize + sizeLongHeader + + self.basicHeaderObj.write(self.fp) + self.systemHeaderObj.write(self.fp) + self.radarControllerHeaderObj.write(self.fp) + self.processingHeaderObj.write(self.fp) + + def __setNewBlock(self): + """ + Si es un nuevo file escribe el First Header caso contrario escribe solo el Basic Header + + Return: + 0 : si no pudo escribir nada + 1 : Si escribio el Basic el First Header + """ + if self.fp == None: + self.setNextFile() + + if self.flagIsNewFile: + return 1 + + if self.blockIndex < self.processingHeaderObj.dataBlocksPerFile: + self.basicHeaderObj.write(self.fp) + return 1 + + if not( self.setNextFile() ): + return 0 + + return 1 + + + def writeNextBlock(self): + """ + Selecciona el bloque siguiente de datos y los escribe en un file + + Return: + 0 : Si no hizo pudo escribir el bloque de datos + 1 : Si no pudo escribir el bloque de datos + """ + if not( self.__setNewBlock() ): + return 0 + + self.writeBlock() + + print "[Writing] Block No. %d/%d" %(self.blockIndex, + self.processingHeaderObj.dataBlocksPerFile) + + return 1 + + def setNextFile(self): + """ + Determina el siguiente file que sera escrito + + Affected: + self.filename + self.subfolder + self.fp + self.setFile + self.flagIsNewFile + + Return: + 0 : Si el archivo no puede ser escrito + 1 : Si el archivo esta listo para ser escrito + """ + ext = self.ext + path = self.path + + if self.fp != None: + self.fp.close() + + timeTuple = time.localtime( self.dataOut.utctime) + subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday) + + fullpath = os.path.join( path, subfolder ) + setFile = self.setFile + + if not( os.path.exists(fullpath) ): + os.mkdir(fullpath) + setFile = -1 #inicializo mi contador de seteo + else: + filesList = os.listdir( fullpath ) + if len( filesList ) > 0: + filesList = sorted( filesList, key=str.lower ) + filen = filesList[-1] + # el filename debera tener el siguiente formato + # 0 1234 567 89A BCDE (hex) + # x YYYY DDD SSS .ext + if isNumber( filen[8:11] ): + setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file + else: + setFile = -1 + else: + setFile = -1 #inicializo mi contador de seteo + + setFile += 1 + + #If this is a new day it resets some values + if self.dataOut.datatime.date() > self.fileDate: + setFile = 0 + self.nTotalBlocks = 0 + + filen = '%s%4.4d%3.3d%3.3d%s' % (self.optchar, timeTuple.tm_year, timeTuple.tm_yday, setFile, ext ) + + filename = os.path.join( path, subfolder, filen ) + + fp = open( filename,'wb' ) + + self.blockIndex = 0 + + #guardando atributos + self.filename = filename + self.subfolder = subfolder + self.fp = fp + self.setFile = setFile + self.flagIsNewFile = 1 + self.fileDate = self.dataOut.datatime.date() + + self.setFirstHeader() + + print '[Writing] Opening file: %s'%self.filename + + self.__writeFirstHeader() + + return 1 + + def setup(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4): + """ + Setea el tipo de formato en la cual sera guardada la data y escribe el First Header + + Inputs: + path : directory where data will be saved + profilesPerBlock : number of profiles per block + set : initial file set + datatype : An integer number that defines data type: + 0 : int8 (1 byte) + 1 : int16 (2 bytes) + 2 : int32 (4 bytes) + 3 : int64 (8 bytes) + 4 : float32 (4 bytes) + 5 : double64 (8 bytes) + + Return: + 0 : Si no realizo un buen seteo + 1 : Si realizo un buen seteo + """ + + if ext == None: + ext = self.ext + + self.ext = ext.lower() + + self.path = path + + if set is None: + self.setFile = -1 + else: + self.setFile = set - 1 + + self.blocksPerFile = blocksPerFile + + self.profilesPerBlock = profilesPerBlock + + self.dataOut = dataOut + self.fileDate = self.dataOut.datatime.date() + #By default + self.dtype = self.dataOut.dtype + + if datatype is not None: + self.dtype = get_numpy_dtype(datatype) + + if not(self.setNextFile()): + print "[Writing] There isn't a next file" + return 0 + + self.setBlockDimension() + + return 1 + + def run(self, dataOut, **kwargs): + + if not(self.isConfig): + + self.setup(dataOut, **kwargs) + self.isConfig = True + + self.putData() + diff --git a/schainpy/model/io/.svn/text-base/jroIO_base.pyc.svn-base b/schainpy/model/io/.svn/text-base/jroIO_base.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..54df976594dae899f8829455c77b82a9e735202c GIT binary patch literal 42921 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 V@6P3N`P@J*KYnH6PZa*${(tt{;OYPX literal 0 Hc$@ vertical) + ('AntennaCoord0',' endFp: + sys.stderr.write("Warning %s: Size value read from System Header is lower than it has to be\n" %fp) + return 0 + + if OffRHeader < endFp: + sys.stderr.write("Warning %s: Size value read from System Header size is greater than it has to be\n" %fp) + return 0 + + return 1 + + +class BLTRReader (ProcessingUnit,FileHeaderBLTR,RecordHeaderBLTR): + + path = None + startDate = None + endDate = None + startTime = None + endTime = None + walk = None + isConfig = False + + + fileList= None + + #metadata + TimeZone= None + Interval= None + heightList= None + + #data + data= None + utctime= None + + + + def __init__(self): + + #Eliminar de la base la herencia + ProcessingUnit.__init__(self) + +# self.isConfig = False + + self.pts2read_SelfSpectra = 0 + self.pts2read_CrossSpectra = 0 + self.pts2read_DCchannels = 0 + self.datablock = None + self.utc = None + self.ext = ".fdt" + self.optchar = "P" + self.fpFile=None + self.fp = None + self.BlockCounter=0 + self.dtype = None + self.fileSizeByHeader = None + self.filenameList = [] + self.fileSelector = 0 + self.Off2StartNxtRec=0 + self.RecCounter=0 + self.flagNoMoreFiles = 0 + self.data_spc=None + self.data_cspc=None + self.data_output=None + self.path = None + self.OffsetStartHeader=0 + self.Off2StartData=0 + self.ipp = 0 + self.nFDTdataRecors=0 + self.blocksize = 0 + self.dataOut = Spectra() + self.profileIndex = 1 #Always + self.dataOut.flagNoData=False + self.dataOut.nRdPairs = 0 + self.dataOut.pairsList = [] + self.dataOut.data_spc=None + self.dataOut.noise=[] + self.dataOut.velocityX=[] + self.dataOut.velocityY=[] + self.dataOut.velocityV=[] + + + + def Files2Read(self, fp): + ''' + Function that indicates the number of .fdt files that exist in the folder to be read. + It also creates an organized list with the names of the files to read. + ''' + #self.__checkPath() + + ListaData=os.listdir(fp) #Gets the list of files within the fp address + ListaData=sorted(ListaData) #Sort the list of files from least to largest by names + nFiles=0 #File Counter + FileList=[] #A list is created that will contain the .fdt files + for IndexFile in ListaData : + if '.fdt' in IndexFile: + FileList.append(IndexFile) + nFiles+=1 + + #print 'Files2Read' + #print 'Existen '+str(nFiles)+' archivos .fdt' + + self.filenameList=FileList #List of files from least to largest by names + + + def run(self, **kwargs): + ''' + This method will be the one that will initiate the data entry, will be called constantly. + You should first verify that your Setup () is set up and then continue to acquire + the data to be processed with getData (). + ''' + if not self.isConfig: + self.setup(**kwargs) + self.isConfig = True + + self.getData() + #print 'running' + + + def setup(self, path=None, + startDate=None, + endDate=None, + startTime=None, + endTime=None, + walk=True, + timezone='utc', + code = None, + online=False, + ReadMode=None): + + self.isConfig = True + + self.path=path + self.startDate=startDate + self.endDate=endDate + self.startTime=startTime + self.endTime=endTime + self.walk=walk + self.ReadMode=int(ReadMode) + + pass + + + def getData(self): + ''' + Before starting this function, you should check that there is still an unread file, + If there are still blocks to read or if the data block is empty. + + You should call the file "read". + + ''' + + if self.flagNoMoreFiles: + self.dataOut.flagNoData = True + print 'NoData se vuelve true' + return 0 + + self.fp=self.path + self.Files2Read(self.fp) + self.readFile(self.fp) + self.dataOut.data_spc = self.data_spc + self.dataOut.data_cspc =self.data_cspc + self.dataOut.data_output=self.data_output + + print 'self.dataOut.data_output', shape(self.dataOut.data_output) + + #self.removeDC() + return self.dataOut.data_spc + + + def readFile(self,fp): + ''' + You must indicate if you are reading in Online or Offline mode and load the + The parameters for this file reading mode. + + Then you must do 2 actions: + + 1. Get the BLTR FileHeader. + 2. Start reading the first block. + ''' + + #The address of the folder is generated the name of the .fdt file that will be read + print "File: ",self.fileSelector+1 + + if self.fileSelector < len(self.filenameList): + + self.fpFile=str(fp)+'/'+str(self.filenameList[self.fileSelector]) + #print self.fpFile + fheader = FileHeaderBLTR() + fheader.FHread(self.fpFile) #Bltr FileHeader Reading + self.nFDTdataRecors=fheader.nFDTdataRecors + + self.readBlock() #Block reading + else: + print 'readFile FlagNoData becomes true' + self.flagNoMoreFiles=True + self.dataOut.flagNoData = True + return 0 + + def getVelRange(self, extrapoints=0): + Lambda= SPEED_OF_LIGHT/50000000 + PRF = self.dataOut.PRF#1./(self.dataOut.ippSeconds * self.dataOut.nCohInt) + Vmax=-Lambda/(4.*(1./PRF)*self.dataOut.nCohInt*2.) + deltafreq = PRF / (self.nProfiles) + deltavel = (Vmax*2) / (self.nProfiles) + freqrange = deltafreq*(numpy.arange(self.nProfiles)-self.nProfiles/2.) - deltafreq/2 + velrange = deltavel*(numpy.arange(self.nProfiles)-self.nProfiles/2.) + return velrange + + def readBlock(self): + ''' + It should be checked if the block has data, if it is not passed to the next file. + + Then the following is done: + + 1. Read the RecordHeader + 2. Fill the buffer with the current block number. + + ''' + + if self.BlockCounter < self.nFDTdataRecors-2: + print self.nFDTdataRecors, 'CONDICION!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + if self.ReadMode==1: + rheader = RecordHeaderBLTR(RecCounter=self.BlockCounter+1) + elif self.ReadMode==0: + rheader = RecordHeaderBLTR(RecCounter=self.BlockCounter) + + rheader.RHread(self.fpFile) #Bltr FileHeader Reading + + self.OffsetStartHeader=rheader.OffsetStartHeader + self.RecCounter=rheader.RecCounter + self.Off2StartNxtRec=rheader.Off2StartNxtRec + self.Off2StartData=rheader.Off2StartData + self.nProfiles=rheader.nProfiles + self.nChannels=rheader.nChannels + self.nHeights=rheader.nHeights + self.frequency=rheader.TransmitFrec + self.DualModeIndex=rheader.DualModeIndex + + self.pairsList =[(0,1),(0,2),(1,2)] + self.dataOut.pairsList = self.pairsList + + self.nRdPairs=len(self.dataOut.pairsList) + self.dataOut.nRdPairs = self.nRdPairs + + self.__firstHeigth=rheader.StartRangeSamp + self.__deltaHeigth=rheader.SampResolution + self.dataOut.heightList= self.__firstHeigth + numpy.array(range(self.nHeights))*self.__deltaHeigth + self.dataOut.channelList = range(self.nChannels) + self.dataOut.nProfiles=rheader.nProfiles + self.dataOut.nIncohInt=rheader.nIncohInt + self.dataOut.nCohInt=rheader.nCohInt + self.dataOut.ippSeconds= 1/float(rheader.PRFhz) + self.dataOut.PRF=rheader.PRFhz + self.dataOut.nFFTPoints=rheader.nProfiles + self.dataOut.utctime=rheader.nUtime + self.dataOut.timeZone=0 + self.dataOut.normFactor= self.dataOut.nProfiles*self.dataOut.nIncohInt*self.dataOut.nCohInt + self.dataOut.outputInterval= self.dataOut.ippSeconds * self.dataOut.nCohInt * self.dataOut.nIncohInt * self.nProfiles + + self.data_output=numpy.ones([3,rheader.nHeights])*numpy.NaN + print 'self.data_output', shape(self.data_output) + self.dataOut.velocityX=[] + self.dataOut.velocityY=[] + self.dataOut.velocityV=[] + + '''Block Reading, the Block Data is received and Reshape is used to give it + shape. + ''' + + #Procedure to take the pointer to where the date block starts + startDATA = open(self.fpFile,"rb") + OffDATA= self.OffsetStartHeader + self.RecCounter*self.Off2StartNxtRec+self.Off2StartData + startDATA.seek(OffDATA, os.SEEK_SET) + + def moving_average(x, N=2): + return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):] + + def gaus(xSamples,a,x0,sigma): + return a*exp(-(xSamples-x0)**2/(2*sigma**2)) + + def Find(x,value): + for index in range(len(x)): + if x[index]==value: + return index + + def pol2cart(rho, phi): + x = rho * numpy.cos(phi) + y = rho * numpy.sin(phi) + return(x, y) + + + + + if self.DualModeIndex==self.ReadMode: + + self.data_fft = numpy.fromfile( startDATA, [('complex',' 0.0001) : + + try: + popt,pcov = curve_fit(gaus,xSamples,yMean,p0=[1,meanGauss,sigma]) + + if numpy.amax(popt)>numpy.amax(yMean)*0.3: + FitGauss=gaus(xSamples,*popt) + + else: + FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean) + print 'Verificador: Dentro', Height + except RuntimeError: + + try: + for j in range(len(ySamples[1])): + yMean2=numpy.append(yMean2,numpy.average([ySamples[1,j],ySamples[2,j]])) + popt,pcov = curve_fit(gaus,xSamples,yMean2,p0=[1,meanGauss,sigma]) + FitGauss=gaus(xSamples,*popt) + print 'Verificador: Exepcion1', Height + except RuntimeError: + + try: + popt,pcov = curve_fit(gaus,xSamples,ySamples[1],p0=[1,meanGauss,sigma]) + FitGauss=gaus(xSamples,*popt) + print 'Verificador: Exepcion2', Height + except RuntimeError: + FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean) + print 'Verificador: Exepcion3', Height + else: + FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean) + #print 'Verificador: Fuera', Height + + + + Maximun=numpy.amax(yMean) + eMinus1=Maximun*numpy.exp(-1) + + HWpos=Find(FitGauss,min(FitGauss, key=lambda value:abs(value-eMinus1))) + HalfWidth= xFrec[HWpos] + GCpos=Find(FitGauss, numpy.amax(FitGauss)) + Vpos=Find(FactNorm, numpy.amax(FactNorm)) + #Vpos=numpy.sum(FactNorm)/len(FactNorm) + #Vpos=Find(FactNorm, min(FactNorm, key=lambda value:abs(value- numpy.mean(FactNorm) ))) + #print 'GCpos',GCpos, numpy.amax(FitGauss), 'HWpos',HWpos + '''****** Getting Fij ******''' + + GaussCenter=xFrec[GCpos] + if (GaussCenter<0 and HalfWidth>0) or (GaussCenter>0 and HalfWidth<0): + Fij=abs(GaussCenter)+abs(HalfWidth)+0.0000001 + else: + Fij=abs(GaussCenter-HalfWidth)+0.0000001 + + '''****** Getting Frecuency range of significant data ******''' + + Rangpos=Find(FitGauss,min(FitGauss, key=lambda value:abs(value-Maximun*0.10))) + + if Rangpos5 and len(FrecRange) 0.: + self.dataOut.velocityX=numpy.append(self.dataOut.velocityX, Vzon) #Vmag + #print 'Vmag',Vmag + else: + self.dataOut.velocityX=numpy.append(self.dataOut.velocityX, NaN) + + if abs(Vx)<100 and abs(Vx) > 0.: + self.dataOut.velocityY=numpy.append(self.dataOut.velocityY, Vmer) #Vang + #print 'Vang',Vang + else: + self.dataOut.velocityY=numpy.append(self.dataOut.velocityY, NaN) + + if abs(GaussCenter)<2: + self.dataOut.velocityV=numpy.append(self.dataOut.velocityV, xFrec[Vpos]) + + else: + self.dataOut.velocityV=numpy.append(self.dataOut.velocityV, NaN) + + +# print '********************************************' +# print 'HalfWidth ', HalfWidth +# print 'Maximun ', Maximun +# print 'eMinus1 ', eMinus1 +# print 'Rangpos ', Rangpos +# print 'GaussCenter ',GaussCenter +# print 'E01 ',E01 +# print 'N01 ',N01 +# print 'E02 ',E02 +# print 'N02 ',N02 +# print 'E12 ',E12 +# print 'N12 ',N12 + #print 'self.dataOut.velocityX ', self.dataOut.velocityX +# print 'Fij ', Fij +# print 'cC ', cC +# print 'cF ', cF +# print 'cG ', cG +# print 'cA ', cA +# print 'cB ', cB +# print 'cH ', cH +# print 'Vx ', Vx +# print 'Vy ', Vy +# print 'Vmag ', Vmag +# print 'Vang ', Vang*180/numpy.pi +# print 'PhaseSlope ',PhaseSlope[0] +# print 'PhaseSlope ',PhaseSlope[1] +# print 'PhaseSlope ',PhaseSlope[2] +# print '********************************************' + #print 'data_output',shape(self.dataOut.velocityX), shape(self.dataOut.velocityY) + + #print 'self.dataOut.velocityX', len(self.dataOut.velocityX) + #print 'self.dataOut.velocityY', len(self.dataOut.velocityY) + #print 'self.dataOut.velocityV', self.dataOut.velocityV + + self.data_output[0]=numpy.array(self.dataOut.velocityX) + self.data_output[1]=numpy.array(self.dataOut.velocityY) + self.data_output[2]=numpy.array(self.dataOut.velocityV) + + prin= self.data_output[0][~numpy.isnan(self.data_output[0])] + print ' ' + print 'VmagAverage',numpy.mean(prin) + print ' ' +# plt.figure(5) +# plt.subplot(211) +# plt.plot(self.dataOut.velocityX,'yo:') +# plt.subplot(212) +# plt.plot(self.dataOut.velocityY,'yo:') + +# plt.figure(1) +# # plt.subplot(121) +# # plt.plot(xFrec,ySamples[0],'k',label='Ch0') +# # plt.plot(xFrec,ySamples[1],'g',label='Ch1') +# # plt.plot(xFrec,ySamples[2],'r',label='Ch2') +# # plt.plot(xFrec,FitGauss,'yo:',label='fit') +# # plt.legend() +# plt.title('DATOS A ALTURA DE 2850 METROS') +# +# plt.xlabel('Frecuencia (KHz)') +# plt.ylabel('Magnitud') +# # plt.subplot(122) +# # plt.title('Fit for Time Constant') +# #plt.plot(xFrec,zline) +# #plt.plot(xFrec,SmoothSPC,'g') +# plt.plot(xFrec,FactNorm) +# plt.axis([-4, 4, 0, 0.15]) +# # plt.xlabel('SelfSpectra KHz') +# +# plt.figure(10) +# # plt.subplot(121) +# plt.plot(xFrec,ySamples[0],'b',label='Ch0') +# plt.plot(xFrec,ySamples[1],'y',label='Ch1') +# plt.plot(xFrec,ySamples[2],'r',label='Ch2') +# # plt.plot(xFrec,FitGauss,'yo:',label='fit') +# plt.legend() +# plt.title('SELFSPECTRA EN CANALES') +# +# plt.xlabel('Frecuencia (KHz)') +# plt.ylabel('Magnitud') +# # plt.subplot(122) +# # plt.title('Fit for Time Constant') +# #plt.plot(xFrec,zline) +# #plt.plot(xFrec,SmoothSPC,'g') +# # plt.plot(xFrec,FactNorm) +# # plt.axis([-4, 4, 0, 0.15]) +# # plt.xlabel('SelfSpectra KHz') +# +# plt.figure(9) +# +# +# plt.title('DATOS SUAVIZADOS') +# plt.xlabel('Frecuencia (KHz)') +# plt.ylabel('Magnitud') +# plt.plot(xFrec,SmoothSPC,'g') +# +# #plt.plot(xFrec,FactNorm) +# plt.axis([-4, 4, 0, 0.15]) +# # plt.xlabel('SelfSpectra KHz') +# # +# plt.figure(2) +# # #plt.subplot(121) +# plt.plot(xFrec,yMean,'r',label='Mean SelfSpectra') +# plt.plot(xFrec,FitGauss,'yo:',label='Ajuste Gaussiano') +# # plt.plot(xFrec[Rangpos],FitGauss[Find(FitGauss,min(FitGauss, key=lambda value:abs(value-Maximun*0.1)))],'bo') +# # #plt.plot(xFrec,phase) +# # plt.xlabel('Suavizado, promediado KHz') +# plt.title('SELFSPECTRA PROMEDIADO') +# # #plt.subplot(122) +# # #plt.plot(xSamples,zline) +# plt.xlabel('Frecuencia (KHz)') +# plt.ylabel('Magnitud') +# plt.legend() +# # +# # plt.figure(3) +# # plt.subplot(311) +# # #plt.plot(xFrec,phase[0]) +# # plt.plot(xFrec,phase[0],'g') +# # plt.subplot(312) +# # plt.plot(xFrec,phase[1],'g') +# # plt.subplot(313) +# # plt.plot(xFrec,phase[2],'g') +# # #plt.plot(xFrec,phase[2]) +# # +# # plt.figure(4) +# # +# # plt.plot(xSamples,coherence[0],'b') +# # plt.plot(xSamples,coherence[1],'r') +# # plt.plot(xSamples,coherence[2],'g') +# plt.show() +# # +# # plt.clf() +# # plt.cla() +# # plt.close() + + print ' ' + + + + self.BlockCounter+=2 + + else: + self.fileSelector+=1 + self.BlockCounter=0 + print "Next File" + + + +class BLTRWriter(ProcessingUnit): + ''' + classdocs + ''' + + def __init__(self): + ''' + Constructor + ''' + self.dataOut = None + + self.isConfig = False + + def setup(self, dataIn, path, blocksPerFile, set=0, ext=None): + ''' + In this method we should set all initial parameters. + + Input: + dataIn : Input data will also be outputa data + + ''' + self.dataOut = dataIn + + self.isConfig = True + + return + + def run(self, dataIn, **kwargs): + ''' + This method will be called many times so here you should put all your code + + Inputs: + + dataIn : object with the data + + ''' + + if not self.isConfig: + self.setup(dataIn, **kwargs) + diff --git a/schainpy/model/io/.svn/text-base/jroIO_bltr.pyc.svn-base b/schainpy/model/io/.svn/text-base/jroIO_bltr.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..9c3ac4188aab6d0b80df0c1fb84f63ba0c394a68 GIT binary patch literal 26045 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 literal 0 Hc$@ 0: + filesList = sorted( filesList, key=str.lower ) + filen = filesList[-1] + + if isNumber( filen[8:11] ): + self.setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file + else: + self.setFile = -1 + else: + self.setFile = -1 #inicializo mi contador de seteo + + setFile = self.setFile + setFile += 1 + + thisFile = '%s%4.4d%3.3d%3.3d%s' % (self.optchar, + timeTuple.tm_year, + timeTuple.tm_yday, + setFile, + ext ) + + filename = os.path.join( path, subfolder, thisFile ) + + self.blockIndex = 0 + self.filename = filename + self.setFile = setFile + self.flagIsNewFile = 1 + + print 'Writing the file: %s'%self.filename + + self.setFitsHeader(self.dataOut, self.metadatafile) + + return 1 + + def writeBlock(self): + self.addData(self.dataOut.data_spc) + self.flagIsNewFile = 0 + + + def __setNewBlock(self): + + if self.flagIsNewFile: + return 1 + + if self.blockIndex < self.dataBlocksPerFile: + return 1 + + if not( self.setNextFile() ): + return 0 + + return 1 + + def writeNextBlock(self): + if not( self.__setNewBlock() ): + return 0 + self.writeBlock() + return 1 + + def putData(self): + if self.flagIsNewFile: + self.setNextFile() + self.writeNextBlock() + + def run(self, dataOut, **kwargs): + if not(self.isConfig): + self.setup(dataOut, **kwargs) + self.isConfig = True + self.putData() + + +class FitsReader(ProcessingUnit): + +# __TIMEZONE = time.timezone + + expName = None + datetimestr = None + utc = None + nChannels = None + nSamples = None + dataBlocksPerFile = None + comments = None + lastUTTime = None + header_dict = None + data = None + data_header_dict = None + + def __init__(self): + self.isConfig = False + self.ext = '.fits' + self.setFile = 0 + self.flagNoMoreFiles = 0 + self.flagIsNewFile = 1 + self.flagDiscontinuousBlock = None + self.fileIndex = None + self.filename = None + self.fileSize = None + self.fitsObj = None + self.timeZone = None + self.nReadBlocks = 0 + self.nTotalBlocks = 0 + self.dataOut = self.createObjByDefault() + self.maxTimeStep = 10# deberia ser definido por el usuario usando el metodo setup() + self.blockIndex = 1 + + def createObjByDefault(self): + + dataObj = Fits() + + return dataObj + + def isFileinThisTime(self, filename, startTime, endTime, useLocalTime=False): + try: + fitsObj = pyfits.open(filename,'readonly') + except: + print "File %s can't be opened" %(filename) + return None + + header = fitsObj[0].header + struct_time = time.strptime(header['DATETIME'], "%b %d %Y %H:%M:%S") + utc = time.mktime(struct_time) - time.timezone #TIMEZONE debe ser un parametro del header FITS + + ltc = utc + if useLocalTime: + ltc -= time.timezone + thisDatetime = datetime.datetime.utcfromtimestamp(ltc) + thisTime = thisDatetime.time() + + if not ((startTime <= thisTime) and (endTime > thisTime)): + return None + + return thisDatetime + + def __setNextFileOnline(self): + raise NotImplementedError + + def __setNextFileOffline(self): + idFile = self.fileIndex + + while (True): + idFile += 1 + if not(idFile < len(self.filenameList)): + self.flagNoMoreFiles = 1 + print "No more Files" + return 0 + + filename = self.filenameList[idFile] + +# if not(self.__verifyFile(filename)): +# continue + + fileSize = os.path.getsize(filename) + fitsObj = pyfits.open(filename,'readonly') + break + + self.flagIsNewFile = 1 + self.fileIndex = idFile + self.filename = filename + self.fileSize = fileSize + self.fitsObj = fitsObj + self.blockIndex = 0 + print "Setting the file: %s"%self.filename + + return 1 + + def __setValuesFromHeader(self): + + self.dataOut.header = self.header_dict + self.dataOut.expName = self.expName + + self.dataOut.timeZone = self.timeZone + self.dataOut.dataBlocksPerFile = self.dataBlocksPerFile + self.dataOut.comments = self.comments +# self.dataOut.timeInterval = self.timeInterval + self.dataOut.channelList = self.channelList + self.dataOut.heightList = self.heightList + + self.dataOut.nCohInt = self.nCohInt + self.dataOut.nIncohInt = self.nIncohInt + + self.dataOut.ippSeconds = self.ippSeconds + + def readHeader(self): + headerObj = self.fitsObj[0] + + self.header_dict = headerObj.header + if 'EXPNAME' in headerObj.header.keys(): + self.expName = headerObj.header['EXPNAME'] + + if 'DATATYPE' in headerObj.header.keys(): + self.dataType = headerObj.header['DATATYPE'] + + self.datetimestr = headerObj.header['DATETIME'] + channelList = headerObj.header['CHANNELLIST'] + channelList = channelList.split('[') + channelList = channelList[1].split(']') + channelList = channelList[0].split(',') + channelList = [int(ch) for ch in channelList] + self.channelList = channelList + self.nChannels = headerObj.header['NCHANNELS'] + self.nHeights = headerObj.header['NHEIGHTS'] + self.ippSeconds = headerObj.header['IPPSECONDS'] + self.nCohInt = headerObj.header['NCOHINT'] + self.nIncohInt = headerObj.header['NINCOHINT'] + self.dataBlocksPerFile = headerObj.header['NBLOCK'] + self.timeZone = headerObj.header['TIMEZONE'] + +# self.timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt + + if 'COMMENT' in headerObj.header.keys(): + self.comments = headerObj.header['COMMENT'] + + self.readHeightList() + + def readHeightList(self): + self.blockIndex = self.blockIndex + 1 + obj = self.fitsObj[self.blockIndex] + self.heightList = obj.data + self.blockIndex = self.blockIndex + 1 + + def readExtension(self): + obj = self.fitsObj[self.blockIndex] + self.heightList = obj.data + self.blockIndex = self.blockIndex + 1 + + def setNextFile(self): + + if self.online: + newFile = self.__setNextFileOnline() + else: + newFile = self.__setNextFileOffline() + + if not(newFile): + return 0 + + self.readHeader() + self.__setValuesFromHeader() + self.nReadBlocks = 0 +# self.blockIndex = 1 + return 1 + + def __searchFilesOffLine(self, + path, + startDate, + endDate, + startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59), + set=None, + expLabel='', + ext='.fits', + walk=True): + + pathList = [] + + if not walk: + pathList.append(path) + + else: + dirList = [] + for thisPath in os.listdir(path): + if not os.path.isdir(os.path.join(path,thisPath)): + continue + if not isRadarFolder(thisPath): + continue + + dirList.append(thisPath) + + if not(dirList): + return None, None + + thisDate = startDate + + while(thisDate <= endDate): + year = thisDate.timetuple().tm_year + doy = thisDate.timetuple().tm_yday + + matchlist = fnmatch.filter(dirList, '?' + '%4.4d%3.3d' % (year,doy) + '*') + if len(matchlist) == 0: + thisDate += datetime.timedelta(1) + continue + for match in matchlist: + pathList.append(os.path.join(path,match,expLabel)) + + thisDate += datetime.timedelta(1) + + if pathList == []: + print "Any folder was found for the date range: %s-%s" %(startDate, endDate) + return None, None + + print "%d folder(s) was(were) found for the date range: %s - %s" %(len(pathList), startDate, endDate) + + filenameList = [] + datetimeList = [] + + for i in range(len(pathList)): + + thisPath = pathList[i] + + fileList = glob.glob1(thisPath, "*%s" %ext) + fileList.sort() + + for thisFile in fileList: + + filename = os.path.join(thisPath,thisFile) + thisDatetime = self.isFileinThisTime(filename, startTime, endTime) + + if not(thisDatetime): + continue + + filenameList.append(filename) + datetimeList.append(thisDatetime) + + if not(filenameList): + print "Any file was found for the time range %s - %s" %(startTime, endTime) + return None, None + + print "%d file(s) was(were) found for the time range: %s - %s" %(len(filenameList), startTime, endTime) + print + + for i in range(len(filenameList)): + print "%s -> [%s]" %(filenameList[i], datetimeList[i].ctime()) + + self.filenameList = filenameList + self.datetimeList = datetimeList + + return pathList, filenameList + + def setup(self, path=None, + startDate=None, + endDate=None, + startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59), + set=0, + expLabel = "", + ext = None, + online = False, + delay = 60, + walk = True): + + if path == None: + raise ValueError, "The path is not valid" + + if ext == None: + ext = self.ext + + if not(online): + print "Searching files in offline mode ..." + pathList, filenameList = self.__searchFilesOffLine(path, startDate=startDate, endDate=endDate, + startTime=startTime, endTime=endTime, + set=set, expLabel=expLabel, ext=ext, + walk=walk) + + if not(pathList): + print "No *%s files into the folder %s \nfor the range: %s - %s"%(ext, path, + datetime.datetime.combine(startDate,startTime).ctime(), + datetime.datetime.combine(endDate,endTime).ctime()) + + sys.exit(-1) + + self.fileIndex = -1 + self.pathList = pathList + self.filenameList = filenameList + + self.online = online + self.delay = delay + ext = ext.lower() + self.ext = ext + + if not(self.setNextFile()): + if (startDate!=None) and (endDate!=None): + print "No files in range: %s - %s" %(datetime.datetime.combine(startDate,startTime).ctime(), datetime.datetime.combine(endDate,endTime).ctime()) + elif startDate != None: + print "No files in range: %s" %(datetime.datetime.combine(startDate,startTime).ctime()) + else: + print "No files" + + sys.exit(-1) + + + + def readBlock(self): + dataObj = self.fitsObj[self.blockIndex] + + self.data = dataObj.data + self.data_header_dict = dataObj.header + self.utc = self.data_header_dict['UTCTIME'] + + self.flagIsNewFile = 0 + self.blockIndex += 1 + self.nTotalBlocks += 1 + self.nReadBlocks += 1 + + return 1 + + def __jumpToLastBlock(self): + raise NotImplementedError + + def __waitNewBlock(self): + """ + Return 1 si se encontro un nuevo bloque de datos, 0 de otra forma. + + Si el modo de lectura es OffLine siempre retorn 0 + """ + if not self.online: + return 0 + + if (self.nReadBlocks >= self.dataBlocksPerFile): + return 0 + + currentPointer = self.fp.tell() + + neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize + + for nTries in range( self.nTries ): + + self.fp.close() + self.fp = open( self.filename, 'rb' ) + self.fp.seek( currentPointer ) + + self.fileSize = os.path.getsize( self.filename ) + currentSize = self.fileSize - currentPointer + + if ( currentSize >= neededSize ): + self.__rdBasicHeader() + return 1 + + print "\tWaiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries+1) + sleep( self.delay ) + + + return 0 + + def __setNewBlock(self): + + if self.online: + self.__jumpToLastBlock() + + if self.flagIsNewFile: + return 1 + + self.lastUTTime = self.utc + + if self.online: + if self.__waitNewBlock(): + return 1 + + if self.nReadBlocks < self.dataBlocksPerFile: + return 1 + + if not(self.setNextFile()): + return 0 + + deltaTime = self.utc - self.lastUTTime + + self.flagDiscontinuousBlock = 0 + + if deltaTime > self.maxTimeStep: + self.flagDiscontinuousBlock = 1 + + return 1 + + + def readNextBlock(self): + if not(self.__setNewBlock()): + return 0 + + if not(self.readBlock()): + return 0 + + return 1 + + def printInfo(self): + + pass + + def getData(self): + + if self.flagNoMoreFiles: + self.dataOut.flagNoData = True + print 'Process finished' + return 0 + + self.flagDiscontinuousBlock = 0 + self.flagIsNewBlock = 0 + + if not(self.readNextBlock()): + return 0 + + if self.data is None: + self.dataOut.flagNoData = True + return 0 + + self.dataOut.data = self.data + self.dataOut.data_header = self.data_header_dict + self.dataOut.utctime = self.utc + +# self.dataOut.header = self.header_dict +# self.dataOut.expName = self.expName +# self.dataOut.nChannels = self.nChannels +# self.dataOut.timeZone = self.timeZone +# self.dataOut.dataBlocksPerFile = self.dataBlocksPerFile +# self.dataOut.comments = self.comments +# # self.dataOut.timeInterval = self.timeInterval +# self.dataOut.channelList = self.channelList +# self.dataOut.heightList = self.heightList + self.dataOut.flagNoData = False + + return self.dataOut.data + + def run(self, **kwargs): + + if not(self.isConfig): + self.setup(**kwargs) + self.isConfig = True + + self.getData() + +class SpectraHeisWriter(Operation): +# set = None + setFile = None + idblock = None + doypath = None + subfolder = None + + def __init__(self): + self.wrObj = PyFits() +# self.dataOut = dataOut + self.nTotalBlocks=0 +# self.set = None + self.setFile = None + self.idblock = 0 + self.wrpath = None + self.doypath = None + self.subfolder = None + self.isConfig = False + + def isNumber(str): + """ + Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero. + + Excepciones: + Si un determinado string no puede ser convertido a numero + Input: + str, string al cual se le analiza para determinar si convertible a un numero o no + + Return: + True : si el string es uno numerico + False : no es un string numerico + """ + try: + float( str ) + return True + except: + return False + + def setup(self, dataOut, wrpath): + + if not(os.path.exists(wrpath)): + os.mkdir(wrpath) + + self.wrpath = wrpath +# self.setFile = 0 + self.dataOut = dataOut + + def putData(self): + name= time.localtime( self.dataOut.utctime) + ext=".fits" + + if self.doypath == None: + self.subfolder = 'F%4.4d%3.3d_%d' % (name.tm_year,name.tm_yday,time.mktime(datetime.datetime.now().timetuple())) + self.doypath = os.path.join( self.wrpath, self.subfolder ) + os.mkdir(self.doypath) + + if self.setFile == None: +# self.set = self.dataOut.set + self.setFile = 0 +# if self.set != self.dataOut.set: +## self.set = self.dataOut.set +# self.setFile = 0 + + #make the filename + thisFile = 'D%4.4d%3.3d_%3.3d%s' % (name.tm_year,name.tm_yday,self.setFile,ext) + + filename = os.path.join(self.wrpath,self.subfolder, thisFile) + + idblock = numpy.array([self.idblock],dtype="int64") + header=self.wrObj.cFImage(idblock=idblock, + year=time.gmtime(self.dataOut.utctime).tm_year, + month=time.gmtime(self.dataOut.utctime).tm_mon, + day=time.gmtime(self.dataOut.utctime).tm_mday, + hour=time.gmtime(self.dataOut.utctime).tm_hour, + minute=time.gmtime(self.dataOut.utctime).tm_min, + second=time.gmtime(self.dataOut.utctime).tm_sec) + + c=3E8 + deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0] + freq=numpy.arange(-1*self.dataOut.nHeights/2.,self.dataOut.nHeights/2.)*(c/(2*deltaHeight*1000)) + + colList = [] + + colFreq=self.wrObj.setColF(name="freq", format=str(self.dataOut.nFFTPoints)+'E', array=freq) + + colList.append(colFreq) + + nchannel=self.dataOut.nChannels + + for i in range(nchannel): + col = self.wrObj.writeData(name="PCh"+str(i+1), + format=str(self.dataOut.nFFTPoints)+'E', + data=10*numpy.log10(self.dataOut.data_spc[i,:])) + + colList.append(col) + + data=self.wrObj.Ctable(colList=colList) + + self.wrObj.CFile(header,data) + + self.wrObj.wFile(filename) + + #update the setFile + self.setFile += 1 + self.idblock += 1 + + return 1 + + def run(self, dataOut, **kwargs): + + if not(self.isConfig): + + self.setup(dataOut, **kwargs) + self.isConfig = True + + self.putData() \ No newline at end of file diff --git a/schainpy/model/io/.svn/text-base/jroIO_heispectra.pyc.svn-base b/schainpy/model/io/.svn/text-base/jroIO_heispectra.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..f540e703ea09fd96a3f5d5550ed1cb98f3d9a700 GIT binary patch literal 25493 zc$~$3du$}hd0%zUaE3FS;rqF(+nak(qRxBVyS=qmzMQ4oTXK(-cDaitPkYPrX*`^1 zl0(jPbGv(P$rXvfT1kcz8P3Cs6D9Eul=9lu^Js`aeN_o?+hlh3L3oXO|adY;1|( z7&ey+YQ3QD2h%F+7u9Z2ML(&W^#SEHvg*yHz)^3bU7u=|RJ*L!%XERtIn^3e?IE>3 zq}s!3eOPMqsx_k8qiTIr%KfS}rrP6beO$FC)cOR~7L-4!XsC^%`kYcvlzOl}r5Xcj zlZIWgRnw|bHVp@D?Tl&+DSw=6hi&Zz)fiF!1lNw*+KZ|&X4;P1+7DpFt8){W@5_`F zZ$^GC@f(#esC=T+s=RW!a`mN`uN8~0*E-2|7`=t!5He8nvWWsn>!aOe!0Gr4##&`O0z-C$(0qvUjkFHtn#{Y5CH{040kp zzwHOfTIBn4E-K5EG-I#Us71HJR>O~yey&;Rv^V@nZp`W@${htt?(X?fEop{9GDxL+ zQCRomxEXA{6*QA1hpGeIV7DB)c>^PONQtj_o8@^^<#{{hc_Za{3(4lmW6vNhV2jdh zt{1U=kQu;~B2&T!L#C`~>mW0TeS^#pHViVu%3Gbokm`x--C=8P;aoCA$&ECNkntZ=? zr5Rq?iNfW()os5S@A>s4s?F~m@HAJeO`5Q3^;tXuldIf%R#Rx+yyg}qhmJa==9FHo)q^mApuSrD&ya%$!ZJ#{>nU}+2>)7i#bKZ=@( zzd-ML{nYu!o8dQO=KC+>-FT8{)}J_fnq`7_c(Q4ZX&s)p%IT?fu_z~MGd$79YiauX zPS*CR!`#W*oI1>R)vnIvnQSn@5ByrhG;oJ_<932EEYuG8(h|)R@BTZ@ppytmt@`ya zXvm6SrII4E(`LIC9V{)p#rJPFI^1^KuYo;hWWNgWA>kd|Y;3f``Yu1{z`R4-zC%O5 z!?t;ccKQynyu(@3SpC*=ySC+j98VbLH6L{*yMF4}edd?feg4#SM@>erzOEE%%UVvJ zPG?@2&4RxfoBbd29t`|P)ugu3@_C|?4Vq+@Zt09t)7#BBIn#MzUdXTU2|OUDr)9#a zXEXs=BKSb}WYA{ca?>g45@MO2q0<(^7+BUMG{hDLl(FPrK{9W~cUFVM1mC>XZ29+; zk#eUj_DAgaAkBEaqi4-xbI}QuUT0#ax~gmBIm5w1S?awS?R``><4t-vXCuEIzUO;a z&HOMYO2V#{M}p=MdS^Z>k1#8%-77!rtjvv=_o!C!7S$>g|-@Yu4Z}6pu9hZEMYDpdGlO|5YqPny6)FRNQ9SV zW^>0+YS14~(%OY?TKiltxp_hzC-)+5+EPYG?h@kNESt^AA-%6a=yx}EAg_2v(yizH zz;a@GDdi1LMZ zFRP=BzI?=Xz)q1>S4ULL0ku5|3o(hY@ca-lMWxmz9<>wY@#xD6n>|?3(Hq z;Wb_8W+M7+&U8`nqAheisu#6Diq(*N(JfQ1?66emqDM=LXHSJo)Z?bvZV-Mf;Q^T3 zhe8rr8q63P{K6?TILKt^u&|RNi9DBq6ahnW1`Np?FoY2mWC}paG^kQApi0qzDgy>o zDH%|utU(o`cdYG6@p)UZ`evmjG8rRBv)bOR_L)mLZTMF6YH*BPd%u(QGL#2MvFpRgKM7 zZEHDR@mU)a)Pf#ByOZ|w zOt~cGVN)(kdBl_lr95iNLsX_I88hW!DpPKpdGmzjvy=Q{Q$TlN-Sa*K^H_-)fVr`7 z!>cUZSi8ZSVDasHP%SvWdT;UOnsFBv^76fVtBW`9 zt}LwbgH~?dU0PnzcP*O|?n3A5cUKmfXRo|*`|iz8atG2G9yQ070i#7vBY6hNlHv8K zM#$Dj(rgRK#Ywbj3!pYG6ik!OUQ5Iawd1kTh7SUt4QnyOZ%ReX9Ry2$b89<^`PG_x zdxDO{JhtFwxV;?cyOx8xl=}6P)?p64jd%R06+$qKYK_L?e&Po)plbBG%}-#%z865j z%irxJd{2pk7d&8?9sOHW$?p>T0&BhcuRWgO1l`&UTR?R|C&kxmy8}=pBdrn%2-as zpq<3gqdeq+LI^1LNN_g6vr~1nkMHQRA}0)o5F6+7cJvq}qkc;ZZ}H$gU_gR>K+}|E&2$3{VrX0|bZ)o>Sr)r;i{1v+;oT4*LG{F`ChLq*`Zn<;#2?IsvLD^A`H zX0F(?F5VZ+W)wF6*xcAj>follO2SSt=q|*NpZH^EO{jPk;@of%d=pO?)a&v=XN>sN zkTd04g0=S9^LBN1#OHz?%;dVmb7`ke&>TGCJwMtAW4#I2&Bokpb>eNN+qI}8@Nm6_ zX6Hk zboPaidZ#Ok><4jFe8e>ay69*PzNCU5;R|Jbf%HK#J>ex`cmHlyMgJWJAk`2VB*W0k z;Q7jNjjLuzZ%js^IubF^rhf)N?|)EatM*jMvmSm&rOz#-d5p58j)+cJ)x1u*h7iqo z&v@xFk>_R~jk<7r)Q3b)8Ff@NmdJ!UEOKU&Z{z1Q*fUz4f`%#z;^do4$V}^rMmi(P zBHX7Svy~W&)tJ3Df2}e5%KR%0_Tn>zvMRLeA2iuoVZz1Y#<0_8a+zO}VN+`{1+#4Zla{BptLzjq`9|%)yQZ{w+6kKh z3on14)S_5CN4t$?G^aJqZ z{fIK6e!y}SI})oouCeBbQry|tOyd$ZJFON2`?!SZh*_2F)1^ROS==4X7)IKegGa0& zl3KAs!U_-k2Pl4wi5Gg-gfmIMqojS6+#&Yu6p5&3NDnK}^&0rB5`<$(1mL9*t;WeleU4#j$Yy1!F7GxdsXU}ikP{*rP-WZQ~=-*LB zl+i+G-BJ22(eFu2`;zKXG~(f|d0-*t+OaCbK?F&K1y@Z`q@IU+Up>E(51JJRN$}GL z9IIW?kV%rC9CRwbqe+#HR{Q+iRDO5)IUkrM^?v^RM#m^=CxLP@;#k)m5Jjsp;`ft^ zcc&RtJe#86B!7OK2sbeXl^$c}_!xNue+tQGk^BUbUr;^z7*jUhVE0ii+KSI~;CO1( z2`1CEERZ%E0pPPpT%Z9HmWT)3!s3p**(W%vlrL}d4VC>3yj2G zU>NoSW3U$(fW5%z>jj2hFEH+UfkD>`jJPU;xH=kf^@rJ~>8SM)(g0>Cx-N7|3B833Y2|DN#6H_8Ce{EL9iK9^I7V7#FJeNR0U zxrYn<=EL02i2B@sT7OChORir+pd>O+>p;o%ifT-7<{8zP8uH4@S_aCD{@j?SA*zsVF#rf4z)CQ~x~luc%k>30b9i{h}s zv`5T?M!PWW6vIyWcN2ST4r-wHmL+=DiddfkgL zDT|%36EoYjS`vfZf{K{{ht=j|UrfM9N;_r(>~Mk083qg1!lc&H6~IC39J+dUW9N;7 z1%I>FX(hsdaC5u1zebANYU1y)ygf&7{6$A=N5{eO?w=t8^SIqorz{)hiI`GOj}zGg z|2-BI#3g;)eB7}XV8LZPuB5t*-M%RVJ^vqk5W~@8)>JXt*HW= zfkl{42s@>z9AFb`K}(bISeq%9;!swjTH#}Wy#$vDC4O-2>f5%CoQoKly@Bi0S z7vQqrhBGqS*K~JX7)N3tK%xb*Q{tOFzE2{=jImm%@eJS^h6ODQDE@x|CmI6DWYxWg zC3Ro-Q#=uJJYaD5l0o9jM&583yhILw2{?w}1a2tv0#w>0ODZf(guMP1t^smb^^=p3 z0|yfWP!>J(FDUI{F~M@|f?s@W{M zXka^C%xc(J7bRojNOV9+-W2m)h_PcL#|x$?nW8Bc^`_9pfo|F?8TMqHU5FHUY#A5x zxBWc?HL=FP_B3;+de{aT#~#jhc+jZ54wCnfAZ+fOD0{*z->2Yei*FI{7C+c$9KErX zJLC-ES5p418@G>j{rs4PR~sNziJ3-Rz-hp-8xk!9){rMTo`-IqRyk5t&{bPXVv0sJPZ7t>r(N~%*YzEu z-|8n7<;g`;9+2{YDVL;NGUc+A%ceXi1KY`HZ6*jYy*rV+xO^ zrZD^8g+YB`~lnH52bI;dUl~2uW=Aeitb)0L7&9kCcwr zg6^}FdZev4jCBj4L((?6Uk+`qZ=X3-C$EGjf6>t~_{u4}C1QGGE`EodG7-=i{XES8 zK-W(e*R7Im+28A`i=d_syF&uG*3g(S(~h_80yY`!${L9wD>q@-PM59@(H)+#p8n6M z$6rdpkYNTxPLBSiW6b}w(K>dt&grAILh`iHdjI0AS!-Eu3>!=FjTHGhebjgDsH5o= z&ZD6Rr4-PUnV>z^gXuaV44DHs#!f#C^yG+tBq6JC32@VDiqxE<5w zE2lI(E?2y-s}lxdAYo)@y77RU{cXntHj?%+m@O$x5e5Ui;tV{(W?NBs{2$Ce-Ywll_bSCCL+tFFB4IlPWqKGVT@Q!ZOPN)>u8IcHCvoAOA&A>2 z(B#YN;g|4o`!Av?hrNyH>F62X2wTb$5b-Dn|4flXE7P0Xd%(5E35>3oK4Wwsmhfvr0j!5+l}C$BJRb?qgqVa zPSBtkwTtz6bxaDRAe{8L_DWo+VKKWkZTtlU~u-)8HdZ0=-!cSia=6?esiZy<>Ex>^$dAk!m-4#gBN(?=9jhGThsnU!q z_(;WjwN|qcKc@gOVfz7O;vkMnGpK~3e&LH1er0}s-uurWhu=feOT6BHQN}y+UzLs- zSP3h{T5V@ZDBzWFcDhhBJhGQPa%c|w|EL4|CdXLl#QR-l#ot^JCn!5)z;jtwWL#6& z%PETIaRL-pDMydn8>sk?hOfj2a;DYaCsUI_xc`QPS<1gOe3EFscHsR*r9G>2gFU?Q zdznsj5mcg4tYmxWmsJ`=U6i=t0Uf>A;15=$7(j+&D#hv&YXaw6lsPEF z@ED2=qfN^(!9#hy-|hy@Xb+0}S&qBF01^(LjO$uf+}~o)g7~CksC>nW{?GH1P83vL zuEfns>{t8%UgapPbb?CI@!tz88?EqRhjd(4bHn&@?VXeye4VP0A;YmJAHXbisYX zcg{}vjauBSO9S?&|9hnoiC`^i`my(?lyQ2n$B=bf-``DLB;Ic+?cPW(9G4JL3}QH+kmxo!zsWZet0j`m0F(MvuVYean{DS^JQ^zd}8J0qYIL0?1UELmeTpOHST~ zJdy|@OQLj&07;_&PYHdDD_s5_0w8ckmX=A{ADXCPw`~_OiGQHV4VpK%1PfhmpByH##osnzd~|P*b!ieivzB9 z`&Cr!?ZsZ!RrxM=rrYbkbYUx{b@SV(Sv5Zts_Z9HD+fuJF_1f zs*@lqgmy9^F*mcvgJl~b{898bMnW9JV7rt!(cch!&(U1x7?--`b6o1zT@$v!ga=nO zhn0i%I+D`QK&jVP!x5{gw}NQ+(8L%0xcVc8t6p?^RM%fT<4NGi(SPiAo$f=}{mLAi z_gw+1ymIjFdH=*PU3S~aA=K3xB2!{vs&LhLqmK3s%EDvKCCK$x%o;OV<^3xp{~F1^ zK>|ktdx^Z?QHDRm#^azQnVartnl@q)%;F`}IWXxv{vidUzp2WhO zL!h#yS~Y1nAbaST=k_yCR^e}rTA8+JD$&eH=j!s_Fr zh!43i`WPM{@BOshYM(kcp2C~_+paR79*{FD_R|Aq2Cc;ni}qktN8qv@L*n{=(2tNr zVjrt-vyOy0iNEG_SsXXFeKII&FgVCaAWeR!0|boJ+I|$y7wvNv_v`*%y-7X9ulATG)VP7e+wEph zBMU`$9fYU$PMu57wuj|luamrLi*);C(?^ZQ)1f4W(Nn1fwN~?St%B3y=@TOi-1NVJ zX6f5kLVAsp=9JiI=_7Ge5r1Fh=kqk`7oeHz&_KAiWjFoGnKw(6B59?nZ{P$;iPpwNl;t}&QeHuAy zQ1qWLu}l(ll;<0nf7#D=kf!y72^l^+L8wXL+F@`4eOY|M%qFgm=*M(@v2WBo^B2>A zcvwu?p65$TS{Xp-h+R7EQHW;BAU2Y$bo>2|Ek~am#X(b1I4Ai#9(e}+`*~>7J#&JO z;ucP;pMgu@lzKkoa7z6}z~86Te*mFUr_?`1Q<^`@A#m!*sJT0rOx%<%WYi4euQA4_ z5kjS}RMdE5L`~Qd3YhymPF5WD)73FGJ~4h&F#dd*h-YxjqA`J^70I)vujkkmKBcA_ z(;ULBG6>r)s-5S>A!0vyIt#zZ{u7maP`m3F-tDlTL^}TvcRs^CmobbfYBKdckD^Ju z$fKGw*FMa5vElQ17p{mIYCDd%88mM*D1g<5dtX2D1=Zjvg(u268Zz(keemoY4%yGL zQq^Vi%`Ap#NAYsk-Rh{IwiCL@e^=+8QawjA_?+IY)OlQ;70ZE->MnHG%TZm=evXK& zsE=G@NzQITZx#vbpC3X32I1lBg$PMgKl^XLenZd#I3l*R=JR?J+^qS#M9lK7L1@;S zk^fM>^o#b3@_A&ip?f#CSuN!=BpyBvJ_ir8D4Bo8vM4r3Dvr@Ntn=3UJ4&mi+*=Sn z67TL$_cFmRS^oD^R$WQIG|a=jgsU$Y6=th#qwSM+6aIRao))@DS#e2<>cYxsdE0_9E^47~Qd0#=@vF}|DTMo{O z8T&s{FDwt}88h2;vG4$)NVJ~!oTKO3d@A-9EsvNF`V%+a|1?udS9yWXR6qbGD?&gl z;Q`Ks17Gbm=aMt#4!Nb=)9xkrB5C8(_UEFTqpPpFIrn9^?3Uayr{YXHm)#L}!X0ym zGYs(m|2fcjK4#*ZsW>gT!)zw<0gq#5qE*a=c$h5M_RH9Doa32A7-qj?JTf`gnq#HH z7#USR$ZU+aWVPA|>(#1I@OLaf_@<@Xe~09Ek>FM3b1m5A%cNmP341Pi@B18Az29!l z`$^>c^IiV~0r`#~C{bQ@qZa!TB*Mxfj_8?D&GV?{0g}v9WByP%rHuLRTjYw}6nkFgKs1zwS9c3O&`EW;lwq0Qw^ WQf|_ne0{7uIX3x~$v;rP_J09GFNZDw literal 0 Hc$@=self.startDate and thisDate <= self.endDate): + return hf_dirname_format + except: + return None + + def __findDataForDates(self,online=False): + if not(self.status): + return None + + pat = '\d+.\d+' + dirnameList = [re.search(pat,x) for x in os.listdir(self.path)] + dirnameList = filter(lambda x:x!=None,dirnameList) + dirnameList = [x.string for x in dirnameList] + if not(online): + + dirnameList = [self.__selDates(x) for x in dirnameList] + dirnameList = filter(lambda x:x!=None,dirnameList) + + if len(dirnameList)>0: + self.status = 1 + self.dirnameList = dirnameList + self.dirnameList.sort() + + else: + self.status = 0 + return None + + def __getTimeFromData(self): + startDateTime_Reader = datetime.datetime.combine(self.startDate,self.startTime) + endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime) + print 'Filtering Files from %s to %s'%(startDateTime_Reader, endDateTime_Reader) + print '........................................' + filter_filenameList=[] + self.filenameList.sort() + for i in range(len(self.filenameList)-1): + filename=self.filenameList[i] + dir_hf_filename= filename + fp= h5py.File(dir_hf_filename,'r') + hipoc=fp['t'].value + hipoc=hipoc+self.timezone + date_time=datetime.datetime.utcfromtimestamp(hipoc) + fp.close() + year =int(date_time[0:4]) + month=int(date_time[5:7]) + dom =int(date_time[8:10]) + hour =int(date_time[11:13]) + min =int(date_time[14:16]) + sec =int(date_time[17:19]) + this_time=datetime.datetime(year,month,dom,hour,min,sec) + if (this_time>=startDateTime_Reader and this_time <= endDateTime_Reader): + filter_filenameList.append(filename) + filter_filenameList.sort() + self.filenameList = filter_filenameList + return 1 + + def __getFilenameList(self): + #print "hola" + #print self.dirnameList + dirList = [os.path.join(self.path,x) for x in self.dirnameList] + self.filenameList= dirList + #print self.filenameList + #print "pase",len(self.filenameList) + + def __selectDataForTimes(self, online=False): + + if not(self.status): + return None + #---------------- + self.__getFilenameList() + #---------------- + if not(online): + if not(self.all): + self.__getTimeFromData() + if len(self.filenameList)>0: + self.status=1 + self.filenameList.sort() + else: + self.status=0 + return None + else: + if self.set != None: + + filename=getFileFromSet(self.path,self.ext,self.set) + + if self.flag_nextfile==True: + self.dirnameList=[filename] + fullfilename=self.path+"/"+filename + self.filenameList=[fullfilename] + self.filename_next_set=int(filename[6:16])+10 + + self.flag_nextfile=False + else: + print filename + print "PRIMERA CONDICION" + #if self.filename_next_set== int(filename[6:16]): + print "TODO BIEN" + + if filename == None: + raise ValueError, "corregir" + + self.dirnameList=[filename] + fullfilename=self.path+"/"+filename + self.filenameList=[fullfilename] + self.filename_next_set=int(filename[6:16])+10 + print "Setting next file",self.filename_next_set + self.set=int(filename[6:16]) + if True: + pass + else: + print "ESTOY AQUI PORQUE NO EXISTE EL SIGUIENTE ARCHIVO" + + else: + filename =getlastFileFromPath(self.path,self.ext) + + if self.flag_nextfile==True: + self.dirnameList=[filename] + fullfilename=self.path+"/"+filename + self.filenameList=[self.filenameList[-1]] + self.filename_next_set=int(filename[6:16])+10 + + self.flag_nextfile=False + else: + filename=getFileFromSet(self.path,self.ext,self.set) + print filename + print "PRIMERA CONDICION" + #if self.filename_next_set== int(filename[6:16]): + print "TODO BIEN" + + if filename == None: + raise ValueError, "corregir" + + self.dirnameList=[filename] + fullfilename=self.path+"/"+filename + self.filenameList=[fullfilename] + self.filename_next_set=int(filename[6:16])+10 + print "Setting next file",self.filename_next_set + self.set=int(filename[6:16]) + if True: + pass + else: + print "ESTOY AQUI PORQUE NO EXISTE EL SIGUIENTE ARCHIVO" + + + + def __searchFilesOffline(self, + path, + startDate, + endDate, + ext, + startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59), + walk=True): + + self.__setParameters(path, startDate, endDate, startTime, endTime, walk) + + self.__checkPath() + + self.__findDataForDates() + #print self.dirnameList + + self.__selectDataForTimes() + + for i in range(len(self.filenameList)): + print "%s"% (self.filenameList[i]) + + return + + def __searchFilesOnline(self, + path, + expLabel= "", + ext=None, + startDate=None, + endDate=None, + walk=True, + set=None): + + + startDate = datetime.datetime.utcnow().date() + endDate = datetime.datetime.utcnow().date() + + self.__setParameters(path=path,startDate=startDate,endDate=endDate,walk=walk) + + self.__checkPath() + + fullpath=path + print "%s folder was found: " %(fullpath ) + + if set == None: + self.set=None + filename =getlastFileFromPath(fullpath,ext) + startDate= datetime.datetime.utcnow().date + endDate= datetime.datetime.utcnow().date() +# + else: + filename= getFileFromSet(fullpath,ext,set) + startDate=None + endDate=None +# + if not (filename): + return None,None,None,None,None + #print "%s file was found" %(filename) + +# +# dir_hf_filename= self.path+"/"+filename +# fp= h5py.File(dir_hf_filename,'r') +# hipoc=fp['t'].value +# fp.close() +# date_time=datetime.datetime.utcfromtimestamp(hipoc) +# +# year =int(date_time[0:4]) +# month=int(date_time[5:7]) +# dom =int(date_time[8:10]) +# set= int(filename[4:10]) +# self.set=set-1 + #self.dirnameList=[filename] + filenameList= fullpath+"/"+filename + self.dirnameList=[filename] + self.filenameList=[filenameList] + self.flag_nextfile=True + + #self.__findDataForDates(online=True) + #self.dirnameList=[self.dirnameList[-1]] + #print self.dirnameList + #self.__selectDataForTimes(online=True) + #return fullpath,filename,year,month,dom,set + return + + def __setNextFile(self,online=False): + """ + """ + if not(online): + newFile = self.__setNextFileOffline() + else: + newFile = self.__setNextFileOnline() + + if not(newFile): + return 0 + return 1 + + def __setNextFileOffline(self): + """ + """ + idFile= self.fileIndex + while(True): + idFile += 1 + if not (idFile < len(self.filenameList)): + self.flagNoMoreFiles = 1 + print "No more Files" + return 0 + filename = self.filenameList[idFile] + hfFilePointer =h5py.File(filename,'r') + + epoc=hfFilePointer['t'].value + #this_time=datetime.datetime(year,month,dom,hour,min,sec) + break + + self.flagIsNewFile = 1 + self.fileIndex = idFile + self.filename = filename + + self.hfFilePointer = hfFilePointer + hfFilePointer.close() + self.__t0=epoc + print "Setting the file: %s"%self.filename + + return 1 + + def __setNextFileOnline(self): + """ + """ + print "SOY NONE",self.set + if self.set==None: + pass + else: + self.set +=10 + + filename = self.filenameList[0]#fullfilename + if self.filename_online != None: + self.__selectDataForTimes(online=True) + filename = self.filenameList[0] + while self.filename_online == filename: + print 'waiting %d seconds to get a new file...'%(self.__waitForNewFile) + time.sleep(self.__waitForNewFile) + #self.__findDataForDates(online=True) + self.set=self.filename_next_set + self.__selectDataForTimes(online=True) + filename = self.filenameList[0] + sizeoffile=os.path.getsize(filename) + + #print filename + sizeoffile=os.path.getsize(filename) + if sizeoffile<1670240: + print "%s is not the rigth size"%filename + delay=50 + print 'waiting %d seconds for delay...'%(delay) + time.sleep(delay) + sizeoffile=os.path.getsize(filename) + if sizeoffile<1670240: + delay=50 + print 'waiting %d more seconds for delay...'%(delay) + time.sleep(delay) + + sizeoffile=os.path.getsize(filename) + if sizeoffile<1670240: + delay=50 + print 'waiting %d more seconds for delay...'%(delay) + time.sleep(delay) + + try: + hfFilePointer=h5py.File(filename,'r') + + except: + print "Error reading file %s"%filename + + self.filename_online=filename + epoc=hfFilePointer['t'].value + + self.hfFilePointer=hfFilePointer + hfFilePointer.close() + self.__t0=epoc + + + self.flagIsNewFile = 1 + self.filename = filename + + print "Setting the file: %s"%self.filename + return 1 + + def __getExpParameters(self): + if not(self.status): + return None + + def setup(self, + path = None, + startDate = None, + endDate = None, + startTime = datetime.time(0,0,0), + endTime = datetime.time(23,59,59), + set = None, + expLabel = "", + ext = None, + all=0, + timezone=0, + online = False, + delay = 60, + walk = True): + ''' + In this method we should set all initial parameters. + + ''' + if path==None: + raise ValueError,"The path is not valid" + + if ext==None: + ext = self.ext + + self.timezone= timezone + self.online= online + self.all=all + #if set==None: + + #print set + if not(online): + print "Searching files in offline mode..." + + self.__searchFilesOffline(path, startDate, endDate, ext, startTime, endTime, walk) + else: + print "Searching files in online mode..." + self.__searchFilesOnline(path, walk,ext,set=set) + if set==None: + pass + else: + self.set=set-10 + +# for nTries in range(self.nTries): +# +# fullpath,file,year,month,day,set = self.__searchFilesOnline(path=path,expLabel=expLabel,ext=ext, walk=walk,set=set) +# +# if fullpath: +# break +# print '\tWaiting %0.2f sec for an valid file in %s: try %02d ...' % (self.delay, path, nTries+1) +# time.sleep(self.delay) +# if not(fullpath): +# print "There ins't valid files in %s" % path +# return None + + + if not(self.filenameList): + print "There is no files into the folder: %s"%(path) + sys.exit(-1) + + self.__getExpParameters() + + + self.fileIndex = -1 + + self.__setNextFile(online) + + self.__readMetadata() + + self.__setLocalVariables() + + self.__setHeaderDO() + #self.profileIndex_offset= 0 + + #self.profileIndex = self.profileIndex_offset + + self.isConfig = True + + def __readMetadata(self): + self.__readHeader() + + + def __setLocalVariables(self): + + self.datablock = numpy.zeros((self.nChannels, self.nHeights,self.nProfiles), dtype = numpy.complex) + # + + + + self.profileIndex = 9999 + + + def __setHeaderDO(self): + + + self.dataOut.radarControllerHeaderObj = RadarControllerHeader() + + self.dataOut.systemHeaderObj = SystemHeader() + + + #--------------------------------------------------------- + self.dataOut.systemHeaderObj.nProfiles=100 + self.dataOut.systemHeaderObj.nSamples=1000 + + + SAMPLING_STRUCTURE=[('h0', '= self.nProfiles: + return 1 + + return 0 + + def readNextBlock(self): + if not(self.__setNewBlock()): + return 0 + + if not(self.readBlock()): + return 0 + + return 1 + + def __setNewBlock(self): + + if self.hfFilePointer==None: + return 0 + + if self.flagIsNewFile: + return 1 + + if self.profileIndex < self.nProfiles: + return 1 + + self.__setNextFile(self.online) + + return 1 + + + + def readBlock(self): + fp=h5py.File(self.filename,'r') + #Puntero que apunta al archivo hdf5 + ch0=(fp['ch0']).value #Primer canal (100,1000)--(perfiles,alturas) + ch1=(fp['ch1']).value #Segundo canal (100,1000)--(perfiles,alturas) + fp.close() + ch0= ch0.swapaxes(0,1) #Primer canal (100,1000)--(alturas,perfiles) + ch1= ch1.swapaxes(0,1) #Segundo canal (100,1000)--(alturas,perfiles) + self.datablock = numpy.array([ch0,ch1]) + self.flagIsNewFile=0 + + self.profileIndex=0 + + return 1 + + def getData(self): + if self.flagNoMoreFiles: + self.dataOut.flagNoData = True + print 'Process finished' + return 0 + + if self.__hasNotDataInBuffer(): + if not(self.readNextBlock()): + self.dataOut.flagNodata=True + return 0 + + ############################## + ############################## + self.dataOut.data = self.datablock[:,:,self.profileIndex] + self.dataOut.utctime = self.__t0 + self.dataOut.ippSeconds*self.profileIndex + self.dataOut.profileIndex= self.profileIndex + self.dataOut.flagNoData=False + self.profileIndex +=1 + + return self.dataOut.data + + + def run(self, **kwargs): + ''' + This method will be called many times so here you should put all your code + ''' + + if not self.isConfig: + self.setup(**kwargs) + self.isConfig = True + self.getData() + + + + diff --git a/schainpy/model/io/.svn/text-base/jroIO_hf.pyc.svn-base b/schainpy/model/io/.svn/text-base/jroIO_hf.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..9a917a6791eba6ebf808ecd5ec73d3efec57ab60 GIT binary patch literal 20152 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 Code=%d, azimuth=%2.2f, zenith=%2.2f, gain=%2.2f'%(k,v[0],v[1],v[2],v[3]) for k,v in dataOut.beamCodeDict.items()] + for b in beamStrList: + print b + self.__isPrinted = True + + return + + +class BeamSelector(Operation): + profileIndex = None + nProfiles = None + + def __init__(self): + + self.profileIndex = 0 + self.__isConfig = False + + def incIndex(self): + self.profileIndex += 1 + + if self.profileIndex >= self.nProfiles: + self.profileIndex = 0 + + def isProfileInRange(self, minIndex, maxIndex): + + if self.profileIndex < minIndex: + return False + + if self.profileIndex > maxIndex: + return False + + return True + + def isProfileInList(self, profileList): + + if self.profileIndex not in profileList: + return False + + return True + + def run(self, dataOut, beam=None): + + dataOut.flagNoData = True + + if not(self.__isConfig): + + self.nProfiles = dataOut.nProfiles + self.profileIndex = dataOut.profileIndex + self.__isConfig = True + + if beam != None: + if self.isProfileInList(dataOut.beamRangeDict[beam]): + beamInfo = dataOut.beamCodeDict[beam] + dataOut.azimuth = beamInfo[1] + dataOut.zenith = beamInfo[2] + dataOut.gain = beamInfo[3] + dataOut.flagNoData = False + + self.incIndex() + return 1 + + else: + raise ValueError, "BeamSelector needs beam value" + + return 0 + +class ProfileToChannels(Operation): + + def __init__(self): + self.__isConfig = False + self.__counter_chan = 0 + self.buffer = None + + def isProfileInList(self, profileList): + + if self.profileIndex not in profileList: + return False + + return True + + def run(self, dataOut): + + dataOut.flagNoData = True + + if not(self.__isConfig): + nchannels = len(dataOut.beamRangeDict.keys()) + nsamples = dataOut.nHeights + self.buffer = numpy.zeros((nchannels, nsamples), dtype = 'complex128') + dataOut.beam.codeList = [dataOut.beamCodeDict[x][0] for x in range(nchannels)] + dataOut.beam.azimuthList = [dataOut.beamCodeDict[x][1] for x in range(nchannels)] + dataOut.beam.zenithList = [dataOut.beamCodeDict[x][2] for x in range(nchannels)] + self.__isConfig = True + + for i in range(self.buffer.shape[0]): + if dataOut.profileIndex in dataOut.beamRangeDict[i]: + self.buffer[i,:] = dataOut.data + break + + + self.__counter_chan += 1 + + if self.__counter_chan >= self.buffer.shape[0]: + self.__counter_chan = 0 + dataOut.data = self.buffer.copy() + dataOut.channelList = range(self.buffer.shape[0]) + self.__isConfig = False + dataOut.flagNoData = False + pass + \ No newline at end of file diff --git a/schainpy/model/proc/.svn/text-base/jroproc_amisr.pyc.svn-base b/schainpy/model/proc/.svn/text-base/jroproc_amisr.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..650e83923d0c5f742025c9c4bb4cbdadb6377767 GIT binary patch literal 5860 zc$~dhO>-N^5$)Ms00cmqGATi!%d(NAq#!Pdh!rPsRI7e?Q=F`e!csMEhJS>N_-6w6CP@(%7MiOZzTOJlgk2q1U5vi6&** zFLS#@+NA;amg#e%&xn4tU!i`5v?skQMehprtG2gR^j4`~x4o-HZw=e%wAQe@Z*Woj zAed!GadM}*6GWjNH#@T+(NAmP|M+jO8`xcJG>cRRj3lo}=#M!}$a5c?Vzn#2%RkWlM7l)2Chbq@=6WH);)Y{!S(Y=w(%H{@-1yIGAJ@xf5{vYoJ(`J!J1rxawt zC$r3`;z6Pw4_cTnMfx!p?W1_2+d2t*qxSFPWRy;Wo^GeTqaciuIL_K>JWGn6=}CJM z_w~3vWh=CYNsQlaFbUISdwSwS1`L&!#W-uKs-D;SCW&T4QJjr5awus@k3&N@e*|kp zWOT>OJ<+NK0a-a$Z8s97vXiOy%T~o+JUtPG{fgCdIm%|Z5XmfpBc-0`yP?bm&EZ7B zMCXUo?eapiF*n6TetltUOF9hfZ^dq|tg0pP;fF~WWxLTJ{+fJv&G;}}Rn5DqW3SJL z!8p~~6aNs1_#2ufI4gQe(kx58EcJ@iEA-KWLz0da8dh<$cYgZ=`i(=+_}>NUow5`ch_{8G zn)#`lpHE(qH4`+N@sXVy$f(J4)VaJvcZ!C=H1e59543WVy zWSxiXPN&TdOOEnb_P=qanvE)E5vb!xDPGdJpYotq)~1Vxfu~7`+%*IW-whe zg%0;lL|eJ*V;#w5KGNagQTB0|X3`9&(_A?LrbzV3R=IkR>jF@gs}N?IAHf$NB{SVB zThBM>g`JM1{4}fQ(>qxrg3x=g%nJg6S1kyTQ&p?-*^siNekNGH>IlC1P|k;uE)dNC zvzv2h=8B17?2aBY^TkO4XpRN6oijiy0mM*x7Tih}+{%a^P^ln-L1hIa`GSAWkxdoQ zSAHS%HAq4rbL}#fQ}-EVi37IaI3z zPQ6glwMxEifYBR@u0L|R7AH@IzegoXZoz>ME&!L|J80=&M*)Lf4E?>y3t}%Rc(APa<5Wx4 zavbYV8;`>KI6zOsLe0cwD`s(mLXFv~R2N!#u?B1mLIDd}p=91Jo)+^y=HxjJBOOD+&}J?JCx03AnNo0wDjfBo=Aq)VKP4KE2Q z%PMyzqv9E_S~lQyMrBG^DQ<7%Q@FP;an2tdD1P_h6Q%h7v4lyRKyMC{Hf8YUq7+0+ ze^-4&ImNTf@~($Xzwx4N;lUNk8ural-{~gNH`vf#06ydiik9vCS zj*_+j8gtSp@+CtY(!~7qD46Oq9>RMa|NB@CV`YJ!K?KZ@3v@njlH4sHlsi>q) z$5MvNrkE#`N0CA?>I!4U8|r)VS#_>4)x54&+;wM*`!^KIRb@c(TrzcWl!C~B ai6h)Kuif64sL3!VSpSmKs5csoJO2kuP~3k2 literal 0 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 Hm;U)bdo%t6 literal 0 Hc$@= limit_sec1) + t2 = numpy.where(self.dataOut.time[0, :] < limit_sec2) + time_select = [] + for val_sec in t1[0]: + if val_sec in t2[0]: + time_select.append(val_sec) + + time_select = numpy.array(time_select, dtype='int') + valid_data = valid_data + len(time_select) + + + if len(time_select) > 0: + self.f_timesec = self.dataOut.time[:, time_select] + snr = self.dataOut.data_SNR[time_select, :, :, :] + zon = self.dataOut.data_output[0][time_select, :, :] + mer = self.dataOut.data_output[1][time_select, :, :] + ver = self.dataOut.data_output[2][time_select, :, :] + + if valid_data > 0: + self.timesec1 = self.f_timesec[0, :] + self.f_height = self.dataOut.height + self.f_zon = zon + self.f_mer = mer + self.f_ver = ver + self.f_snr = snr + self.f_timedate = [] + self.f_time = [] + + for valuet in self.timesec1: + time_t = time.gmtime(valuet) + year = time_t.tm_year + month = time_t.tm_mon + day = time_t.tm_mday + hour = time_t.tm_hour + minute = time_t.tm_min + second = time_t.tm_sec + f_timedate_0 = datetime.datetime(year, month, day, hour, minute, second) + self.f_timedate.append(f_timedate_0) + + return self.f_timedate, self.f_timesec, self.f_height, self.f_zon, self.f_mer, self.f_ver, self.f_snr + + else: + self.f_timesec = None + self.f_timedate = None + self.f_height = None + self.f_zon = None + self.f_mer = None + self.f_ver = None + self.f_snr = None + print 'Invalid time' + + return self.f_timedate, self.f_height, self.f_zon, self.f_mer, self.f_ver, self.f_snr + + def SnrFilter(self, snr_val,modetofilter): + ''' + Inputs: snr_val - Threshold value + + ''' + if modetofilter!=2 and modetofilter!=1 : + raise ValueError,'Mode to filter should be "1" or "2". {} is not valid, check "Modetofilter" value.'.format(modetofilter) + m = modetofilter-1 + + print ' SNR filter [mode {}]: SNR <= {}: data_output = NA'.format(modetofilter,snr_val) + for k in range(self.dataOut.nchannels): + for r in range(self.dataOut.nranges): + if self.dataOut.data_SNR[r,k,m] <= snr_val: + self.dataOut.data_output[2][r,m] = numpy.nan + self.dataOut.data_output[1][r,m] = numpy.nan + self.dataOut.data_output[0][r,m] = numpy.nan + + + + def OutliersFilter(self,modetofilter,svalue,svalue2,method,factor,filter,npoints): + ''' + Inputs: + svalue - string to select array velocity + svalue2 - string to choose axis filtering + method - 0 for SMOOTH or 1 for MEDIAN + factor - number used to set threshold + filter - 1 for data filtering using the standard deviation criteria else 0 + npoints - number of points for mask filter + + ''' + if modetofilter!=2 and modetofilter!=1 : + raise ValueError,'Mode to filter should be "1" or "2". {} is not valid, check "Modetofilter" value.'.format(modetofilter) + + m = modetofilter-1 + + print ' Outliers Filter [mode {}]: {} {} / threshold = {}'.format(modetofilter,svalue,svalue,factor) + + npoints = 9 + novalid = 0.1 + if svalue == 'zonal': + value = self.dataOut.data_output[0] + + elif svalue == 'meridional': + value = self.dataOut.data_output[1] + + elif svalue == 'vertical': + value = self.dataOut.data_output[2] + + else: + print 'value is not defined' + return + + if svalue2 == 'inTime': + yaxis = self.dataOut.height + xaxis = numpy.array([[self.dataOut.time1],[self.dataOut.time1]]) + + elif svalue2 == 'inHeight': + yaxis = numpy.array([[self.dataOut.time1],[self.dataOut.time1]]) + xaxis = self.dataOut.height + + else: + print 'svalue2 is required, either inHeight or inTime' + return + + output_array = value + + value_temp = value[:,m] + error = numpy.zeros(len(self.dataOut.time[m,:])) + if svalue2 == 'inHeight': + value_temp = numpy.transpose(value_temp) + error = numpy.zeros(len(self.dataOut.height)) + + htemp = yaxis[m,:] + std = value_temp + for h in range(len(htemp)): + if filter: #standard deviation filtering + std[h] = numpy.std(value_temp[h],ddof = npoints) + value_temp[numpy.where(std[h] > 5),h] = numpy.nan + error[numpy.where(std[h] > 5)] = error[numpy.where(std[h] > 5)] + 1 + + + nvalues_valid = len(numpy.where(numpy.isfinite(value_temp[h]))[0]) + minvalid = novalid*len(xaxis[m,:]) + if minvalid <= npoints: + minvalid = npoints + + #only if valid values greater than the minimum required (10%) + if nvalues_valid > minvalid: + + if method == 0: + #SMOOTH + w = value_temp[h] - self.Smooth(input=value_temp[h], width=npoints, edge_truncate=1) + + + if method == 1: + #MEDIAN + w = value_temp[h] - self.Median(input=value_temp[h], width = npoints) + + dw = numpy.std(w[numpy.where(numpy.isfinite(w))],ddof = 1) + + threshold = dw*factor + value_temp[numpy.where(w > threshold),h] = numpy.nan + value_temp[numpy.where(w < -1*threshold),h] = numpy.nan + + + #At the end + if svalue2 == 'inHeight': + value_temp = numpy.transpose(value_temp) + output_array[:,m] = value_temp + + if svalue == 'zonal': + self.dataOut.data_output[0] = output_array + + elif svalue == 'meridional': + self.dataOut.data_output[1] = output_array + + elif svalue == 'vertical': + self.dataOut.data_output[2] = output_array + + return self.dataOut.data_output + + + def Median(self,input,width): + ''' + Inputs: + input - Velocity array + width - Number of points for mask filter + + ''' + + if numpy.mod(width,2) == 1: + pc = int((width - 1) / 2) + cont = 0 + output = [] + + for i in range(len(input)): + if i >= pc and i < len(input) - pc: + new2 = input[i-pc:i+pc+1] + temp = numpy.where(numpy.isfinite(new2)) + new = new2[temp] + value = numpy.median(new) + output.append(value) + + output = numpy.array(output) + output = numpy.hstack((input[0:pc],output)) + output = numpy.hstack((output,input[-pc:len(input)])) + + return output + + def Smooth(self,input,width,edge_truncate = None): + ''' + Inputs: + input - Velocity array + width - Number of points for mask filter + edge_truncate - 1 for truncate the convolution product else + + ''' + + if numpy.mod(width,2) == 0: + real_width = width + 1 + nzeros = width / 2 + else: + real_width = width + nzeros = (width - 1) / 2 + + half_width = int(real_width)/2 + length = len(input) + + gate = numpy.ones(real_width,dtype='float') + norm_of_gate = numpy.sum(gate) + + nan_process = 0 + nan_id = numpy.where(numpy.isnan(input)) + if len(nan_id[0]) > 0: + nan_process = 1 + pb = numpy.zeros(len(input)) + pb[nan_id] = 1. + input[nan_id] = 0. + + if edge_truncate == True: + output = numpy.convolve(input/norm_of_gate,gate,mode='same') + elif edge_truncate == False or edge_truncate == None: + output = numpy.convolve(input/norm_of_gate,gate,mode='valid') + output = numpy.hstack((input[0:half_width],output)) + output = numpy.hstack((output,input[len(input)-half_width:len(input)])) + + if nan_process: + pb = numpy.convolve(pb/norm_of_gate,gate,mode='valid') + pb = numpy.hstack((numpy.zeros(half_width),pb)) + pb = numpy.hstack((pb,numpy.zeros(half_width))) + output[numpy.where(pb > 0.9999)] = numpy.nan + input[nan_id] = numpy.nan + return output + + def Average(self,aver=0,nhaver=1): + ''' + Inputs: + aver - Indicates the time period over which is averaged or consensus data + nhaver - Indicates the decimation factor in heights + + ''' + nhpoints = 48 + + lat_piura = -5.17 + lat_huancayo = -12.04 + lat_porcuya = -5.8 + + if '%2.2f'%self.dataOut.lat == '%2.2f'%lat_piura: + hcm = 3. + if self.dataOut.year == 2003 : + if self.dataOut.doy >= 25 and self.dataOut.doy < 64: + nhpoints = 12 + + elif '%2.2f'%self.dataOut.lat == '%2.2f'%lat_huancayo: + hcm = 3. + if self.dataOut.year == 2003 : + if self.dataOut.doy >= 25 and self.dataOut.doy < 64: + nhpoints = 12 + + + elif '%2.2f'%self.dataOut.lat == '%2.2f'%lat_porcuya: + hcm = 5.#2 + + pdata = 0.2 + taver = [1,2,3,4,6,8,12,24] + t0 = 0 + tf = 24 + ntime =(tf-t0)/taver[aver] + ti = numpy.arange(ntime) + tf = numpy.arange(ntime) + taver[aver] + + + old_height = self.dataOut.heightList + + if nhaver > 1: + num_hei = len(self.dataOut.heightList)/nhaver/self.dataOut.nmodes + deltha = 0.05*nhaver + minhvalid = pdata*nhaver + for im in range(self.dataOut.nmodes): + new_height = numpy.arange(num_hei)*deltha + self.dataOut.height[im,0] + deltha/2. + + + data_fHeigths_List = [] + data_fZonal_List = [] + data_fMeridional_List = [] + data_fVertical_List = [] + startDTList = [] + + + for i in range(ntime): + height = old_height + + start = datetime.datetime(self.dataOut.year,self.dataOut.month,self.dataOut.day) + datetime.timedelta(hours = int(ti[i])) - datetime.timedelta(hours = 5) + stop = datetime.datetime(self.dataOut.year,self.dataOut.month,self.dataOut.day) + datetime.timedelta(hours = int(tf[i])) - datetime.timedelta(hours = 5) + + + limit_sec1 = time.mktime(start.timetuple()) + limit_sec2 = time.mktime(stop.timetuple()) + + t1 = numpy.where(self.f_timesec >= limit_sec1) + t2 = numpy.where(self.f_timesec < limit_sec2) + time_select = [] + for val_sec in t1[0]: + if val_sec in t2[0]: + time_select.append(val_sec) + + + time_select = numpy.array(time_select,dtype = 'int') + minvalid = numpy.ceil(pdata*nhpoints) + + zon_aver = numpy.zeros([self.dataOut.nranges,self.dataOut.nmodes],dtype='f4') + numpy.nan + mer_aver = numpy.zeros([self.dataOut.nranges,self.dataOut.nmodes],dtype='f4') + numpy.nan + ver_aver = numpy.zeros([self.dataOut.nranges,self.dataOut.nmodes],dtype='f4') + numpy.nan + + if nhaver > 1: + new_zon_aver = numpy.zeros([num_hei,self.dataOut.nmodes],dtype='f4') + numpy.nan + new_mer_aver = numpy.zeros([num_hei,self.dataOut.nmodes],dtype='f4') + numpy.nan + new_ver_aver = numpy.zeros([num_hei,self.dataOut.nmodes],dtype='f4') + numpy.nan + + if len(time_select) > minvalid: + time_average = self.f_timesec[time_select] + + for im in range(self.dataOut.nmodes): + + for ih in range(self.dataOut.nranges): + if numpy.sum(numpy.isfinite(self.f_zon[time_select,ih,im])) >= minvalid: + zon_aver[ih,im] = numpy.nansum(self.f_zon[time_select,ih,im]) / numpy.sum(numpy.isfinite(self.f_zon[time_select,ih,im])) + + if numpy.sum(numpy.isfinite(self.f_mer[time_select,ih,im])) >= minvalid: + mer_aver[ih,im] = numpy.nansum(self.f_mer[time_select,ih,im]) / numpy.sum(numpy.isfinite(self.f_mer[time_select,ih,im])) + + if numpy.sum(numpy.isfinite(self.f_ver[time_select,ih,im])) >= minvalid: + ver_aver[ih,im] = numpy.nansum(self.f_ver[time_select,ih,im]) / numpy.sum(numpy.isfinite(self.f_ver[time_select,ih,im])) + + if nhaver > 1: + for ih in range(num_hei): + hvalid = numpy.arange(nhaver) + nhaver*ih + + if numpy.sum(numpy.isfinite(zon_aver[hvalid,im])) >= minvalid: + new_zon_aver[ih,im] = numpy.nansum(zon_aver[hvalid,im]) / numpy.sum(numpy.isfinite(zon_aver[hvalid,im])) + + if numpy.sum(numpy.isfinite(mer_aver[hvalid,im])) >= minvalid: + new_mer_aver[ih,im] = numpy.nansum(mer_aver[hvalid,im]) / numpy.sum(numpy.isfinite(mer_aver[hvalid,im])) + + if numpy.sum(numpy.isfinite(ver_aver[hvalid,im])) >= minvalid: + new_ver_aver[ih,im] = numpy.nansum(ver_aver[hvalid,im]) / numpy.sum(numpy.isfinite(ver_aver[hvalid,im])) + if nhaver > 1: + zon_aver = new_zon_aver + mer_aver = new_mer_aver + ver_aver = new_ver_aver + height = new_height + + + tstart = time_average[0] + tend = time_average[-1] + startTime = time.gmtime(tstart) + + year = startTime.tm_year + month = startTime.tm_mon + day = startTime.tm_mday + hour = startTime.tm_hour + minute = startTime.tm_min + second = startTime.tm_sec + + startDTList.append(datetime.datetime(year,month,day,hour,minute,second)) + + + o_height = numpy.array([]) + o_zon_aver = numpy.array([]) + o_mer_aver = numpy.array([]) + o_ver_aver = numpy.array([]) + if self.dataOut.nmodes > 1: + for im in range(self.dataOut.nmodes): + + if im == 0: + h_select = numpy.where(numpy.bitwise_and(height[0,:] >=0,height[0,:] <= hcm,numpy.isfinite(height[0,:]))) + else: + h_select = numpy.where(numpy.bitwise_and(height[1,:] > hcm,height[1,:] < 20,numpy.isfinite(height[1,:]))) + + + ht = h_select[0] + + o_height = numpy.hstack((o_height,height[im,ht])) + o_zon_aver = numpy.hstack((o_zon_aver,zon_aver[ht,im])) + o_mer_aver = numpy.hstack((o_mer_aver,mer_aver[ht,im])) + o_ver_aver = numpy.hstack((o_ver_aver,ver_aver[ht,im])) + + data_fHeigths_List.append(o_height) + data_fZonal_List.append(o_zon_aver) + data_fMeridional_List.append(o_mer_aver) + data_fVertical_List.append(o_ver_aver) + + + else: + h_select = numpy.where(numpy.bitwise_and(height[0,:] <= hcm,numpy.isfinite(height[0,:]))) + ht = h_select[0] + o_height = numpy.hstack((o_height,height[im,ht])) + o_zon_aver = numpy.hstack((o_zon_aver,zon_aver[ht,im])) + o_mer_aver = numpy.hstack((o_mer_aver,mer_aver[ht,im])) + o_ver_aver = numpy.hstack((o_ver_aver,ver_aver[ht,im])) + + data_fHeigths_List.append(o_height) + data_fZonal_List.append(o_zon_aver) + data_fMeridional_List.append(o_mer_aver) + data_fVertical_List.append(o_ver_aver) + + + return startDTList, data_fHeigths_List, data_fZonal_List, data_fMeridional_List, data_fVertical_List + + + def prePlot(self,modeselect=None): + + ''' + Inputs: + + self.dataOut.data_output - Zonal, Meridional and Vertical velocity array + self.dataOut.height - height array + self.dataOut.time - Time array (seconds) + self.dataOut.data_SNR - SNR array + + ''' + + m = modeselect -1 + + print ' [Plotting mode {}]'.format(modeselect) + if not (m ==1 or m==0): + raise IndexError("'Mode' must be egual to : 1 or 2") +# + if self.flagfirstmode==0: + #copy of the data + self.data_output_copy = self.dataOut.data_output.copy() + self.data_height_copy = self.dataOut.height.copy() + self.data_time_copy = self.dataOut.time.copy() + self.data_SNR_copy = self.dataOut.data_SNR.copy() + self.flagfirstmode = 1 + + else: + self.dataOut.data_output = self.data_output_copy + self.dataOut.height = self.data_height_copy + self.dataOut.time = self.data_time_copy + self.dataOut.data_SNR = self.data_SNR_copy + self.flagfirstmode = 0 + + + #select data for mode m + #self.dataOut.data_output = self.dataOut.data_output[:,:,m] + self.dataOut.heightList = self.dataOut.height[0,:] + + data_SNR = self.dataOut.data_SNR[:,:,m] + self.dataOut.data_SNR= transpose(data_SNR) + + if m==1 and self.dataOut.counter_records%2==0: + print '*********' + print 'MODO 2' + #print 'Zonal', self.dataOut.data_output[0] + #print 'Meridional', self.dataOut.data_output[1] + #print 'Vertical', self.dataOut.data_output[2] + + print '*********' + + Vx=self.dataOut.data_output[0,:,m] + Vy=self.dataOut.data_output[1,:,m] + + Vmag=numpy.sqrt(Vx**2+Vy**2) + Vang=numpy.arctan2(Vy,Vx) + #print 'Vmag', Vmag + #print 'Vang', Vang + + self.dataOut.data_output[0,:,m]=Vmag + self.dataOut.data_output[1,:,m]=Vang + + prin= self.dataOut.data_output[0,:,m][~numpy.isnan(self.dataOut.data_output[0,:,m])] + print ' ' + print 'VmagAverage',numpy.mean(prin) + print ' ' + self.dataOut.data_output = self.dataOut.data_output[:,:,m] + + + \ No newline at end of file diff --git a/schainpy/model/proc/.svn/text-base/jroproc_bltr.pyc.svn-base b/schainpy/model/proc/.svn/text-base/jroproc_bltr.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..4b37eeb98d1f9e8b2292cffe9af384cbb3ccaffd GIT binary patch literal 15500 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 0: + if mode == 'time': + ccf0 = data_pre[ch0,:nProfiles-idx,:]*numpy.conj(data_pre[ch1,idx:,:]) #time + else: + ccf0 = data_pre[ch0,:,nHeights-idx]*numpy.conj(data_pre[ch1,:,idx:]) #heights + else: + if mode == 'time': + ccf0 = data_pre[ch0,-idx:,:]*numpy.conj(data_pre[ch1,:nProfiles+idx,:]) #time + else: + ccf0 = data_pre[ch0,:,-idx:]*numpy.conj(data_pre[ch1,:,:nHeights+idx]) #heights + + if fullBuffer: + tmp[l,i,:ccf0.shape[0],:] = ccf0 + else: + tmp[l,i,:] = numpy.sum(ccf0, axis=0) + + #----------------------------------------------------------------- + if fullBuffer: + tmp = numpy.sum(numpy.reshape(tmp,(tmp.shape[0],tmp.shape[1],tmp.shape[2]/nAvg,nAvg,tmp.shape[3])),axis=3) + self.dataOut.nAvg = nAvg + + self.dataOut.data_cf = tmp + self.dataOut.mode = mode + self.dataOut.nLags = len(lags) + self.dataOut.pairsList = pairsList + self.dataOut.nPairs = len(pairsList) + + #Se Calcula los factores de Normalizacion + if mode == 'time': + delta = self.dataIn.ippSeconds*self.dataIn.nCohInt + else: + delta = self.dataIn.heightList[1] - self.dataIn.heightList[0] + self.dataOut.lagRange = numpy.array(lags)*delta +# self.dataOut.nCohInt = self.dataIn.nCohInt*nAvg + self.dataOut.flagNoData = False + a = self.dataOut.normFactor + return \ No newline at end of file diff --git a/schainpy/model/proc/.svn/text-base/jroproc_correlation.pyc.svn-base b/schainpy/model/proc/.svn/text-base/jroproc_correlation.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..22f627834943e7ad1a67304dace5894d7319ba5e GIT binary patch literal 5439 zc$~dh&2Jn@6|buK{;(Z?+X*DgW(6a(YX>QSR5+_jHfD zd$Kl~K|)E+ToC^N2mS?Etbm^f4O>eZ|Fs@``^;a_w0 zj~@Q}*cI8o0)2i=pV*?IP5-6vg*ZuJC44CcN}MP$D2S7SkiZs%UlfCqI4OxiS)7y! zTNGM}juh>ZcqPP3A)cR9!0M<~Cbr&x>EA(15tz)=a2SQIj$<$A{w(m4q(-QxLmfGZ z7X~R+gNEHOinPzjWRd1Q&u{C~$O+nZtj~IcUARgGw)wrP^m&YXJ*Pp_jp%SyTmfSd zx1)p74d{>n%D60m3hqbuc_qb36~uHU8g)&y%NPMv#H)%psSE3pg6!)tRAr@4m@0j#lS!!!M$wTBfZ&nQm09H z+ShKf=ebEz#D*}?36y?1>U4CJ%n{h}qBv3}Z?0g!u^@YXiuE6%R{&bYI za1rJdYroTC>B9KOb}t<0Z5?^;+4dJ1c)2|Y+uGkI zY3_DE3h`~bQ-f^{FRc=>ZGt}rq2^RgrhmCsi$<%zmaLw>QEXocTN+HkU%7`%U-`xlC8V?%7h)5YHLRoWaZ+%)G%Y z7|epf+%lLHSTxfmL$GWx%LcPzFe?VLYA~w?vt}@B2D5H3>jtwlmBlUz$2wr|h_vI! zNFF<#hm7zBPM2LazP>!gf+ojqz|qQ?=Y1NmXTw2H$b+p$?v`<~?>k*~bsa@vv>T3s zB!Rb#V*Mm^9se1;8r&kM?a+FVM4|8N=o9U$y1j&_aL`~hpv{2V$>mU|xW~?@okF|h<(Uiu)(~-Y_nffFlxL$Mbc}v1>I= z$lhe!@-1z9G$i9`(&By;4n7b4#OZ3R#4KAaN&ZtCa)Y5eg>=3o7o>rfqznImBUDVJ zzoua<;enJLHz!J5oQs6QiGynIm#&x;us$wul@j8$ngX2y?I?;waZV^AuM?A(Qcg;k zj!R;LmI1w+!Or<@aXd!(D&#qs4eVTaaSH$&KJGc0Gf-9PYHQPw4YU(*tgtcIv-|Oo z(lph$DjPHPw*&_B*qP0`oeYNTk~v~;_vWox<&YhOFZAB-4Wv^MBmSrvYw{ET_#HOlu$9@Uy2!~EHbw*ATTC116M`np#^v-+_NmA z-!g{q4UUe62-34O;KGs|H2S-sv_%aK)vGZ}2f(oe_pZY=)8M1b3(5ttGHHt7&+NaY z^bV3X(3t^OnP?H48`Nm8)AvgyCK7_*DX5MB%cX$5&Fm}8@^>@ryM}!|V_*Lo>}#T< z412}wg}5lHWNAvw<>;SsGKcwij&fO*B7Q!fm1(vhF8(I7O)}r~Cpo#rCFmBB(7_h* z$~Y^D==W->p+iLm7|-)#p$3|b>y-|NUxt~+3(VuqT1e7XCQIV{<3i3WOC)vXc%931 zeeq2$!5?Pq_mAv!MA&$X;A>3N3#`B6c)@4l`tfqE?>r&6)(zJgX7JCm!kB<2%s?sz zI9W2 z&6f-j<@-(vJ_v!0%zeit6Y%RCa7{DafYvj3bH+nc%x!kJ6uvX{%?$I68H)`}GWe#6 z_`9UAWf9yp^Ly#3^9fyMg9vcP_l(qKv6AurmPp>enxiNq-4~M;el75e0h#|``pV3D zMC-OexZz;v(>oM-lXD?I3DW+X3!3%qysDw3v_3GU!GO2m?Jof2%rde@87!CFvHwmNG>XlMW^f3#yp65y)`Tk@6UBUVs3){wu z@zD2@-F@pPz(T#&6C;+7KaA3b0L?9o?DNd+J;=VlXMJdN;k7SP4Y{2M>642py~Del zo3G|LK{N_}4iP;FQcbm_mQ|6)rsTguSuWM;H2#q1x8+CXyRfO|<-FRIb*6oy_UZel z>NBeUAF2nm change this line + self.n = 9999 + self.__byTime = True + + if overlapping: + self.__withOverapping = True + self.__buffer = None + else: + self.__withOverapping = False + self.__buffer = 0 + + self.__profIndex = 0 + + def putData(self, data): + + """ + Add a profile to the __buffer and increase in one the __profileIndex + + """ + + if not self.__withOverapping: + self.__buffer += data.copy() + self.__profIndex += 1 + return + + #Overlapping data + nChannels, nHeis = data.shape + data = numpy.reshape(data, (1, nChannels, nHeis)) + + #If the buffer is empty then it takes the data value + if self.__buffer is None: + self.__buffer = data + self.__profIndex += 1 + return + + #If the buffer length is lower than n then stakcing the data value + if self.__profIndex < self.n: + self.__buffer = numpy.vstack((self.__buffer, data)) + self.__profIndex += 1 + return + + #If the buffer length is equal to n then replacing the last buffer value with the data value + self.__buffer = numpy.roll(self.__buffer, -1, axis=0) + self.__buffer[self.n-1] = data + self.__profIndex = self.n + return + + + def pushData(self): + """ + Return the sum of the last profiles and the profiles used in the sum. + + Affected: + + self.__profileIndex + + """ + + if not self.__withOverapping: + data = self.__buffer + n = self.__profIndex + + self.__buffer = 0 + self.__profIndex = 0 + + return data, n + + #Integration with Overlapping + data = numpy.sum(self.__buffer, axis=0) + n = self.__profIndex + + return data, n + + def byProfiles(self, data): + + self.__dataReady = False + avgdata = None +# n = None + + self.putData(data) + + if self.__profIndex == self.n: + + avgdata, n = self.pushData() + self.__dataReady = True + + return avgdata + + def byTime(self, data, datatime): + + self.__dataReady = False + avgdata = None + n = None + + self.putData(data) + + if (datatime - self.__initime) >= self.__integrationtime: + avgdata, n = self.pushData() + self.n = n + self.__dataReady = True + + return avgdata + + def integrate(self, data, datatime=None): + + if self.__initime == None: + self.__initime = datatime + + if self.__byTime: + avgdata = self.byTime(data, datatime) + else: + avgdata = self.byProfiles(data) + + + self.__lastdatatime = datatime + + if avgdata is None: + return None, None + + avgdatatime = self.__initime + + deltatime = datatime -self.__lastdatatime + + if not self.__withOverapping: + self.__initime = datatime + else: + self.__initime += deltatime + + return avgdata, avgdatatime + + def run(self, dataOut, **kwargs): + + if not self.isConfig: + self.setup(**kwargs) + self.isConfig = True + + avgdata, avgdatatime = self.integrate(dataOut.data_spc, dataOut.utctime) + +# dataOut.timeInterval *= n + dataOut.flagNoData = True + + if self.__dataReady: + dataOut.data_spc = avgdata + dataOut.nIncohInt *= self.n +# dataOut.nCohInt *= self.n + dataOut.utctime = avgdatatime +# dataOut.timeInterval = dataOut.ippSeconds * dataOut.nIncohInt +# dataOut.timeInterval = self.__timeInterval*self.n + dataOut.flagNoData = False \ No newline at end of file diff --git a/schainpy/model/proc/.svn/text-base/jroproc_heispectra.pyc.svn-base b/schainpy/model/proc/.svn/text-base/jroproc_heispectra.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..b0c1a94454089fff3903c7028a3e16ca44ac0e03 GIT binary patch literal 9229 zc$~djOLyDG6&?V52sCBdvZTmIiG$CY085bLUMi^vi^Tddon=ZJMjSb#brDv4fMte0tA64DkO zOSH@4b0Izx;K`5Z(;A-fU za2s^Wf^LFNrML<3t#D^T_-hMQ+N)(1y94ptIN>GWCd8H{cIlRuuyPxhr9sodp=*r& z>OzTHAGqbXezO_UHJeSJ34op3K^{CD9oTXuhu5%~MT7+j950XK4 zD@t11eAz+X0tMI-@id7Y?+|@PK%FS;GpMT0-Xz+wp^ERvEj7aAXJOn)%X~7neW(a4*JAaN%UP#livGDlm}gT7KifD_LRl{>^W8Hdg3$Bn%(hyz-FlUoZ9kQ*{g?+7pTQhsM*tLr>v51*aHufrb9%iBO zXTfusG3}Ja0%3hzFbBGwPOeyXQF};&WSe0p=f}ZD#+pXl*&1|-8j7p1Wd1AI&Cxv3 zYnx9=^m#3@_t+VwTzXgL%bol_j+tQYTp%U8Y#C*8G*AAfc(TicZz=*h-~h2@+ZO3t z3@O7ET6twS5A+?*wRvt(JTBD9;TU9mqQeva$j>Ku(_L1r!?q_)D0~vHo&D6_&s9j^ zFl;F-Oa^6nyeU1HX)oE>BGP!5GB3=$ILW=IK@_$ZVDSA*S|?fOU|ClaSXE{}AHbF# zTy5?P?+#G~_5;i0@}v(JlVAS+Wd+9UxDHNLJY?M752As*3)gpoDi0Y+2k|4E@FELQ zoz%K!)vXf!p5wNLv0buT;6iy+u->7jD+Hx-`Q2F!$bi07mnBWzA(wec(4#{h5=~vV|zp4oPh8P+@rtNlBq*Xk- zw~}*~K@XumPpbI)VCX8@^wQrSC~30AdGJTGh#V*(!u!uMkBm1hiSwV(UR^zr)q0Jy zifoY(t$D>~4cBT>))aVy*xQJbCj;rV=`YBW%##EPGU)|gD~N+gW?m+{G*3p}ey(_C zOVha@_Xqh6GsNe>D*D_&6VV``-Q!jmMFB9-CjzQ*Ouc@RdU9*g`|!=zfAadZkG-+o z&EV}$hnOYX~(s^W7?tWS&f1OsPKR^iYa=pIZu&We4tl@YImNk02! zT=V2SG#~d3wzt_^v`Ph~jT8PmH7bUp45`hyBe*IRHKAN}II<=nLbDb43ezXQN`xiP z5eq%X5ow4%7FP8R6C$23JP=}UM?b9X}y~8Puo})W;OjFTbcGVhl zE4i1G!RQAmDGVjHnU{1JLix4qszRODih?X#Ji>8gHx53)C)OSI8>@rfhD@2^IwwVl~wznZYh*a1K>F~wH#jx?JPF*<$hPBR- zg*Fe1fBX_OsYgBoG%u?L>4Smd4i ze?{j9IH~Sh{Lh)ApuSGMy3J#|qWdZmEfvuy+n5Pcl+AvOP6;-W<9kZ#uGy+IQ&NdO z4Y}C8w#!-mM>Zl?iaH4ymDa0RmCQwlaszr~6)7Py%n6Zxp)Jqho0|I1gxIFsxg?K(6C6+bR}lT+{)yaPH==t`rqJEU<%YiV_ooyox3*P@H;JMVq2+1_ml$=Js0yDD^JAA)AWUW($@xEx zv{qfpjT%G~@*B53UE5N{Lu=QRhRYo6Jm7u>Mr&x6s>OPQKembYfD=0@9|bn0LBBC116lla zQPh|AYY-$kc-mzbb|M5sOuMo3sF0|-RRr*Yh*xnY?V`x;6c*i(ueG0i9IEe?_7PDL zwIt>WLY76^94Dm1i%L2ooEV{~V<_q#MbTw64-7@$F=Q=|lT}yH*?WI@V$xY*;v%}3 zw@e|N2y0dBNqd$OJy#RAB1XdUZ;TNlnnL(Y@GO`xY*5ncLt3K}#4|akhcH(0+;0cE~h46DI2(}Z2)#%unh0}DPCx2*}s%C>jn;E;|xHf8= zF7Xb0Ym8Slaoy~Tq5HU~!vR}-CHP(Y7z3Gaicu(^+e2l@*;5oRpQK`-FJ;h z-Zf%+&sdKYb9cTr8|C+mm034J{E4C4b#YRKl{>WS*P@7ODmMMI_{(O5|2b}X>azQa zd){rhjrzQDK*qj{UryD@Ql7DAzx)sCQQRH? literal 0 Hc$@ 0.: + velocityX=numpy.append(velocityX, Vzon)#Vmag + + else: + velocityX=numpy.append(velocityX, numpy.NaN) + + if abs(Vmer)<100 and abs(Vmer) > 0.: + velocityY=numpy.append(velocityY, Vmer)#Vang + + else: + velocityY=numpy.append(velocityY, numpy.NaN) + + if abs(GaussCenter)<2: + velocityV=numpy.append(velocityV, Vver) + else: + velocityV=numpy.append(velocityV, numpy.NaN) + + + data_output[0]=numpy.array(velocityX) + data_output[1]=numpy.array(velocityY) + data_output[2]=FirstMoment + + dataOut.data_output=data_output + return + + + def moving_average(self,x, N=2): + return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):] + + def gaus(self,xSamples,a,x0,sigma): + return a*exp(-(xSamples-x0)**2/(2*sigma**2)) + + def Find(self,x,value): + for index in range(len(x)): + if x[index]==value: + return index + + def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, VelRange): + + ySamples=numpy.ones([spc.shape[0],spc.shape[1]]) + phase=numpy.ones([spc.shape[0],spc.shape[1]]) + CSPCSamples=numpy.ones([spc.shape[0],spc.shape[1]],dtype=numpy.complex_) + coherence=numpy.ones([spc.shape[0],spc.shape[1]]) + PhaseSlope=numpy.ones(spc.shape[0]) + PhaseInter=numpy.ones(spc.shape[0]) + xFrec=VelRange + + '''Getting Eij and Nij''' + + E01=ChanDist[0][0] + N01=ChanDist[0][1] + + E02=ChanDist[1][0] + N02=ChanDist[1][1] + + E12=ChanDist[2][0] + N12=ChanDist[2][1] + + z = spc.copy() + z = numpy.where(numpy.isfinite(z), z, numpy.NAN) + + for i in range(spc.shape[0]): + + '''****** Line of Data SPC ******''' + zline=z[i,:,Height] + + '''****** SPC is normalized ******''' + FactNorm= zline.copy() / numpy.sum(zline.copy()) + FactNorm= FactNorm/numpy.sum(FactNorm) + + SmoothSPC=self.moving_average(FactNorm,N=3) + + xSamples = ar(range(len(SmoothSPC))) + ySamples[i] = SmoothSPC-noise[i] + + for i in range(spc.shape[0]): + + '''****** Line of Data CSPC ******''' + cspcLine=cspc[i,:,Height].copy() + + '''****** CSPC is normalized ******''' + chan_index0 = pairsList[i][0] + chan_index1 = pairsList[i][1] + CSPCFactor= numpy.sum(ySamples[chan_index0]) * numpy.sum(ySamples[chan_index1]) + + CSPCNorm= cspcLine.copy() / numpy.sqrt(CSPCFactor) + + CSPCSamples[i] = CSPCNorm-noise[i] + coherence[i] = numpy.abs(CSPCSamples[i]) / numpy.sqrt(CSPCFactor) + + coherence[i]= self.moving_average(coherence[i],N=2) + + phase[i] = self.moving_average( numpy.arctan2(CSPCSamples[i].imag, CSPCSamples[i].real),N=1)#*180/numpy.pi + + '''****** Getting fij width ******''' + + yMean=[] + yMean2=[] + + for j in range(len(ySamples[1])): + yMean=numpy.append(yMean,numpy.mean([ySamples[0,j],ySamples[1,j],ySamples[2,j]])) + + '''******* Getting fitting Gaussian ******''' + meanGauss=sum(xSamples*yMean) / len(xSamples) + sigma=sum(yMean*(xSamples-meanGauss)**2) / len(xSamples) + + if (abs(meanGauss/sigma**2) > 0.0001) : + + try: + popt,pcov = curve_fit(self.gaus,xSamples,yMean,p0=[1,meanGauss,sigma]) + + if numpy.amax(popt)>numpy.amax(yMean)*0.3: + FitGauss=self.gaus(xSamples,*popt) + + else: + FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean) + print 'Verificador: Dentro', Height + except RuntimeError: + + try: + for j in range(len(ySamples[1])): + yMean2=numpy.append(yMean2,numpy.average([ySamples[1,j],ySamples[2,j]])) + popt,pcov = curve_fit(self.gaus,xSamples,yMean2,p0=[1,meanGauss,sigma]) + FitGauss=self.gaus(xSamples,*popt) + print 'Verificador: Exepcion1', Height + except RuntimeError: + + try: + popt,pcov = curve_fit(self.gaus,xSamples,ySamples[1],p0=[1,meanGauss,sigma]) + FitGauss=self.gaus(xSamples,*popt) + print 'Verificador: Exepcion2', Height + except RuntimeError: + FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean) + print 'Verificador: Exepcion3', Height + else: + FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean) + + Maximun=numpy.amax(yMean) + eMinus1=Maximun*numpy.exp(-1) + + HWpos=self.Find(FitGauss,min(FitGauss, key=lambda value:abs(value-eMinus1))) + HalfWidth= xFrec[HWpos] + GCpos=self.Find(FitGauss, numpy.amax(FitGauss)) + Vpos=self.Find(FactNorm, numpy.amax(FactNorm)) + + #Vpos=FirstMoment[] + + '''****** Getting Fij ******''' + + GaussCenter=xFrec[GCpos] + if (GaussCenter<0 and HalfWidth>0) or (GaussCenter>0 and HalfWidth<0): + Fij=abs(GaussCenter)+abs(HalfWidth)+0.0000001 + else: + Fij=abs(GaussCenter-HalfWidth)+0.0000001 + + '''****** Getting Frecuency range of significant data ******''' + + Rangpos=self.Find(FitGauss,min(FitGauss, key=lambda value:abs(value-Maximun*0.10))) + + if Rangpos5 and len(FrecRange) m): ss1 = m + + valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1 + power = ((spec2[valid] - n0)*fwindow[valid]).sum() + fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power + w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power) + snr = (spec2.mean()-n0)/n0 + + if (snr < 1.e-20) : + snr = 1.e-20 + + vec_power[ind] = power + vec_fd[ind] = fd + vec_w[ind] = w + vec_snr[ind] = snr + + moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w)) + return moments + + #------------------ Get SA Parameters -------------------------- + + def GetSAParameters(self): + #SA en frecuencia + pairslist = self.dataOut.groupList + num_pairs = len(pairslist) + + vel = self.dataOut.abscissaList + spectra = self.dataOut.data_pre + cspectra = self.dataIn.data_cspc + delta_v = vel[1] - vel[0] + + #Calculating the power spectrum + spc_pow = numpy.sum(spectra, 3)*delta_v + #Normalizing Spectra + norm_spectra = spectra/spc_pow + #Calculating the norm_spectra at peak + max_spectra = numpy.max(norm_spectra, 3) + + #Normalizing Cross Spectra + norm_cspectra = numpy.zeros(cspectra.shape) + + for i in range(num_chan): + norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:]) + + max_cspectra = numpy.max(norm_cspectra,2) + max_cspectra_index = numpy.argmax(norm_cspectra, 2) + + for i in range(num_pairs): + cspc_par[i,:,:] = __calculateMoments(norm_cspectra) + #------------------- Get Lags ---------------------------------- + +class SALags(Operation): + ''' + Function GetMoments() + + Input: + self.dataOut.data_pre + self.dataOut.abscissaList + self.dataOut.noise + self.dataOut.normFactor + self.dataOut.data_SNR + self.dataOut.groupList + self.dataOut.nChannels + + Affected: + self.dataOut.data_param + + ''' + def run(self, dataOut): + data_acf = dataOut.data_pre[0] + data_ccf = dataOut.data_pre[1] + normFactor_acf = dataOut.normFactor[0] + normFactor_ccf = dataOut.normFactor[1] + pairs_acf = dataOut.groupList[0] + pairs_ccf = dataOut.groupList[1] + + nHeights = dataOut.nHeights + absc = dataOut.abscissaList + noise = dataOut.noise + SNR = dataOut.data_SNR + nChannels = dataOut.nChannels +# pairsList = dataOut.groupList +# pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels) + + for l in range(len(pairs_acf)): + data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:] + + for l in range(len(pairs_ccf)): + data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:] + + dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights)) + dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc) + dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc) + return + +# def __getPairsAutoCorr(self, pairsList, nChannels): +# +# pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan +# +# for l in range(len(pairsList)): +# firstChannel = pairsList[l][0] +# secondChannel = pairsList[l][1] +# +# #Obteniendo pares de Autocorrelacion +# if firstChannel == secondChannel: +# pairsAutoCorr[firstChannel] = int(l) +# +# pairsAutoCorr = pairsAutoCorr.astype(int) +# +# pairsCrossCorr = range(len(pairsList)) +# pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr) +# +# return pairsAutoCorr, pairsCrossCorr + + def __calculateTaus(self, data_acf, data_ccf, lagRange): + + lag0 = data_acf.shape[1]/2 + #Funcion de Autocorrelacion + mean_acf = stats.nanmean(data_acf, axis = 0) + + #Obtencion Indice de TauCross + ind_ccf = data_ccf.argmax(axis = 1) + #Obtencion Indice de TauAuto + ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int') + ccf_lag0 = data_ccf[:,lag0,:] + + for i in range(ccf_lag0.shape[0]): + ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0) + + #Obtencion de TauCross y TauAuto + tau_ccf = lagRange[ind_ccf] + tau_acf = lagRange[ind_acf] + + Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0]) + + tau_ccf[Nan1,Nan2] = numpy.nan + tau_acf[Nan1,Nan2] = numpy.nan + tau = numpy.vstack((tau_ccf,tau_acf)) + + return tau + + def __calculateLag1Phase(self, data, lagTRange): + data1 = stats.nanmean(data, axis = 0) + lag1 = numpy.where(lagTRange == 0)[0][0] + 1 + + phase = numpy.angle(data1[lag1,:]) + + return phase + +class SpectralFitting(Operation): + ''' + Function GetMoments() + + Input: + Output: + Variables modified: + ''' + + def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None): + + + if path != None: + sys.path.append(path) + self.dataOut.library = importlib.import_module(file) + + #To be inserted as a parameter + groupArray = numpy.array(groupList) +# groupArray = numpy.array([[0,1],[2,3]]) + self.dataOut.groupList = groupArray + + nGroups = groupArray.shape[0] + nChannels = self.dataIn.nChannels + nHeights=self.dataIn.heightList.size + + #Parameters Array + self.dataOut.data_param = None + + #Set constants + constants = self.dataOut.library.setConstants(self.dataIn) + self.dataOut.constants = constants + M = self.dataIn.normFactor + N = self.dataIn.nFFTPoints + ippSeconds = self.dataIn.ippSeconds + K = self.dataIn.nIncohInt + pairsArray = numpy.array(self.dataIn.pairsList) + + #List of possible combinations + listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2) + indCross = numpy.zeros(len(list(listComb)), dtype = 'int') + + if getSNR: + listChannels = groupArray.reshape((groupArray.size)) + listChannels.sort() + noise = self.dataIn.getNoise() + self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels]) + + for i in range(nGroups): + coord = groupArray[i,:] + + #Input data array + data = self.dataIn.data_spc[coord,:,:]/(M*N) + data = data.reshape((data.shape[0]*data.shape[1],data.shape[2])) + + #Cross Spectra data array for Covariance Matrixes + ind = 0 + for pairs in listComb: + pairsSel = numpy.array([coord[x],coord[y]]) + indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0]) + ind += 1 + dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N) + dataCross = dataCross**2/K + + for h in range(nHeights): +# print self.dataOut.heightList[h] + + #Input + d = data[:,h] + + #Covariance Matrix + D = numpy.diag(d**2/K) + ind = 0 + for pairs in listComb: + #Coordinates in Covariance Matrix + x = pairs[0] + y = pairs[1] + #Channel Index + S12 = dataCross[ind,:,h] + D12 = numpy.diag(S12) + #Completing Covariance Matrix with Cross Spectras + D[x*N:(x+1)*N,y*N:(y+1)*N] = D12 + D[y*N:(y+1)*N,x*N:(x+1)*N] = D12 + ind += 1 + Dinv=numpy.linalg.inv(D) + L=numpy.linalg.cholesky(Dinv) + LT=L.T + + dp = numpy.dot(LT,d) + + #Initial values + data_spc = self.dataIn.data_spc[coord,:,h] + + if (h>0)and(error1[3]<5): + p0 = self.dataOut.data_param[i,:,h-1] + else: + p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i)) + + try: + #Least Squares + minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True) +# minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants)) + #Chi square error + error0 = numpy.sum(infodict['fvec']**2)/(2*N) + #Error with Jacobian + error1 = self.dataOut.library.errorFunction(minp,constants,LT) + except: + minp = p0*numpy.nan + error0 = numpy.nan + error1 = p0*numpy.nan + + #Save + if self.dataOut.data_param == None: + self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan + self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan + + self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1)) + self.dataOut.data_param[i,:,h] = minp + return + + def __residFunction(self, p, dp, LT, constants): + + fm = self.dataOut.library.modelFunction(p, constants) + fmp=numpy.dot(LT,fm) + + return dp-fmp + + def __getSNR(self, z, noise): + + avg = numpy.average(z, axis=1) + SNR = (avg.T-noise)/noise + SNR = SNR.T + return SNR + + def __chisq(p,chindex,hindex): + #similar to Resid but calculates CHI**2 + [LT,d,fm]=setupLTdfm(p,chindex,hindex) + dp=numpy.dot(LT,d) + fmp=numpy.dot(LT,fm) + chisq=numpy.dot((dp-fmp).T,(dp-fmp)) + return chisq + +class WindProfiler(Operation): + + __isConfig = False + + __initime = None + __lastdatatime = None + __integrationtime = None + + __buffer = None + + __dataReady = False + + __firstdata = None + + n = None + + def __init__(self): + Operation.__init__(self) + + def __calculateCosDir(self, elev, azim): + zen = (90 - elev)*numpy.pi/180 + azim = azim*numpy.pi/180 + cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2))) + cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2) + + signX = numpy.sign(numpy.cos(azim)) + signY = numpy.sign(numpy.sin(azim)) + + cosDirX = numpy.copysign(cosDirX, signX) + cosDirY = numpy.copysign(cosDirY, signY) + return cosDirX, cosDirY + + def __calculateAngles(self, theta_x, theta_y, azimuth): + + dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2) + zenith_arr = numpy.arccos(dir_cosw) + azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180 + + dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr) + dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr) + + return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw + + def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly): + +# + if horOnly: + A = numpy.c_[dir_cosu,dir_cosv] + else: + A = numpy.c_[dir_cosu,dir_cosv,dir_cosw] + A = numpy.asmatrix(A) + A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose() + + return A1 + + def __correctValues(self, heiRang, phi, velRadial, SNR): + listPhi = phi.tolist() + maxid = listPhi.index(max(listPhi)) + minid = listPhi.index(min(listPhi)) + + rango = range(len(phi)) + # rango = numpy.delete(rango,maxid) + + heiRang1 = heiRang*math.cos(phi[maxid]) + heiRangAux = heiRang*math.cos(phi[minid]) + indOut = (heiRang1 < heiRangAux[0]).nonzero() + heiRang1 = numpy.delete(heiRang1,indOut) + + velRadial1 = numpy.zeros([len(phi),len(heiRang1)]) + SNR1 = numpy.zeros([len(phi),len(heiRang1)]) + + for i in rango: + x = heiRang*math.cos(phi[i]) + y1 = velRadial[i,:] + f1 = interpolate.interp1d(x,y1,kind = 'cubic') + + x1 = heiRang1 + y11 = f1(x1) + + y2 = SNR[i,:] + f2 = interpolate.interp1d(x,y2,kind = 'cubic') + y21 = f2(x1) + + velRadial1[i,:] = y11 + SNR1[i,:] = y21 + + return heiRang1, velRadial1, SNR1 + + def __calculateVelUVW(self, A, velRadial): + + #Operacion Matricial +# velUVW = numpy.zeros((velRadial.shape[1],3)) +# for ind in range(velRadial.shape[1]): +# velUVW[ind,:] = numpy.dot(A,velRadial[:,ind]) +# velUVW = velUVW.transpose() + velUVW = numpy.zeros((A.shape[0],velRadial.shape[1])) + velUVW[:,:] = numpy.dot(A,velRadial) + + + return velUVW + +# def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0): + + def techniqueDBS(self, kwargs): + """ + Function that implements Doppler Beam Swinging (DBS) technique. + + Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth, + Direction correction (if necessary), Ranges and SNR + + Output: Winds estimation (Zonal, Meridional and Vertical) + + Parameters affected: Winds, height range, SNR + """ + velRadial0 = kwargs['velRadial'] + heiRang = kwargs['heightList'] + SNR0 = kwargs['SNR'] + + if kwargs.has_key('dirCosx') and kwargs.has_key('dirCosy'): + theta_x = numpy.array(kwargs['dirCosx']) + theta_y = numpy.array(kwargs['dirCosy']) + else: + elev = numpy.array(kwargs['elevation']) + azim = numpy.array(kwargs['azimuth']) + theta_x, theta_y = self.__calculateCosDir(elev, azim) + azimuth = kwargs['correctAzimuth'] + if kwargs.has_key('horizontalOnly'): + horizontalOnly = kwargs['horizontalOnly'] + else: horizontalOnly = False + if kwargs.has_key('correctFactor'): + correctFactor = kwargs['correctFactor'] + else: correctFactor = 1 + if kwargs.has_key('channelList'): + channelList = kwargs['channelList'] + if len(channelList) == 2: + horizontalOnly = True + arrayChannel = numpy.array(channelList) + param = param[arrayChannel,:,:] + theta_x = theta_x[arrayChannel] + theta_y = theta_y[arrayChannel] + + azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth) + heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0) + A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly) + + #Calculo de Componentes de la velocidad con DBS + winds = self.__calculateVelUVW(A,velRadial1) + + return winds, heiRang1, SNR1 + + def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None): + + nPairs = len(pairs_ccf) + posx = numpy.asarray(posx) + posy = numpy.asarray(posy) + + #Rotacion Inversa para alinear con el azimuth + if azimuth!= None: + azimuth = azimuth*math.pi/180 + posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth) + posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth) + else: + posx1 = posx + posy1 = posy + + #Calculo de Distancias + distx = numpy.zeros(nPairs) + disty = numpy.zeros(nPairs) + dist = numpy.zeros(nPairs) + ang = numpy.zeros(nPairs) + + for i in range(nPairs): + distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]] + disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]] + dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2) + ang[i] = numpy.arctan2(disty[i],distx[i]) + + return distx, disty, dist, ang + #Calculo de Matrices +# nPairs = len(pairs) +# ang1 = numpy.zeros((nPairs, 2, 1)) +# dist1 = numpy.zeros((nPairs, 2, 1)) +# +# for j in range(nPairs): +# dist1[j,0,0] = dist[pairs[j][0]] +# dist1[j,1,0] = dist[pairs[j][1]] +# ang1[j,0,0] = ang[pairs[j][0]] +# ang1[j,1,0] = ang[pairs[j][1]] +# +# return distx,disty, dist1,ang1 + + + def __calculateVelVer(self, phase, lagTRange, _lambda): + + Ts = lagTRange[1] - lagTRange[0] + velW = -_lambda*phase/(4*math.pi*Ts) + + return velW + + def __calculateVelHorDir(self, dist, tau1, tau2, ang): + nPairs = tau1.shape[0] + nHeights = tau1.shape[1] + vel = numpy.zeros((nPairs,3,nHeights)) + dist1 = numpy.reshape(dist, (dist.size,1)) + + angCos = numpy.cos(ang) + angSin = numpy.sin(ang) + + vel0 = dist1*tau1/(2*tau2**2) + vel[:,0,:] = (vel0*angCos).sum(axis = 1) + vel[:,1,:] = (vel0*angSin).sum(axis = 1) + + ind = numpy.where(numpy.isinf(vel)) + vel[ind] = numpy.nan + + return vel + +# def __getPairsAutoCorr(self, pairsList, nChannels): +# +# pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan +# +# for l in range(len(pairsList)): +# firstChannel = pairsList[l][0] +# secondChannel = pairsList[l][1] +# +# #Obteniendo pares de Autocorrelacion +# if firstChannel == secondChannel: +# pairsAutoCorr[firstChannel] = int(l) +# +# pairsAutoCorr = pairsAutoCorr.astype(int) +# +# pairsCrossCorr = range(len(pairsList)) +# pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr) +# +# return pairsAutoCorr, pairsCrossCorr + +# def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor): + def techniqueSA(self, kwargs): + + """ + Function that implements Spaced Antenna (SA) technique. + + Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth, + Direction correction (if necessary), Ranges and SNR + + Output: Winds estimation (Zonal, Meridional and Vertical) + + Parameters affected: Winds + """ + position_x = kwargs['positionX'] + position_y = kwargs['positionY'] + azimuth = kwargs['azimuth'] + + if kwargs.has_key('correctFactor'): + correctFactor = kwargs['correctFactor'] + else: + correctFactor = 1 + + groupList = kwargs['groupList'] + pairs_ccf = groupList[1] + tau = kwargs['tau'] + _lambda = kwargs['_lambda'] + + #Cross Correlation pairs obtained +# pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels) +# pairsArray = numpy.array(pairsList)[pairsCrossCorr] +# pairsSelArray = numpy.array(pairsSelected) +# pairs = [] +# +# #Wind estimation pairs obtained +# for i in range(pairsSelArray.shape[0]/2): +# ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0] +# ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0] +# pairs.append((ind1,ind2)) + + indtau = tau.shape[0]/2 + tau1 = tau[:indtau,:] + tau2 = tau[indtau:-1,:] +# tau1 = tau1[pairs,:] +# tau2 = tau2[pairs,:] + phase1 = tau[-1,:] + + #--------------------------------------------------------------------- + #Metodo Directo + distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth) + winds = self.__calculateVelHorDir(dist, tau1, tau2, ang) + winds = stats.nanmean(winds, axis=0) + #--------------------------------------------------------------------- + #Metodo General +# distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth) +# #Calculo Coeficientes de Funcion de Correlacion +# F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n) +# #Calculo de Velocidades +# winds = self.calculateVelUV(F,G,A,B,H) + + #--------------------------------------------------------------------- + winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda) + winds = correctFactor*winds + return winds + + def __checkTime(self, currentTime, paramInterval, outputInterval): + + dataTime = currentTime + paramInterval + deltaTime = dataTime - self.__initime + + if deltaTime >= outputInterval or deltaTime < 0: + self.__dataReady = True + return + + def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax): + ''' + Function that implements winds estimation technique with detected meteors. + + Input: Detected meteors, Minimum meteor quantity to wind estimation + + Output: Winds estimation (Zonal and Meridional) + + Parameters affected: Winds + ''' +# print arrayMeteor.shape + #Settings + nInt = (heightMax - heightMin)/2 +# print nInt + nInt = int(nInt) +# print nInt + winds = numpy.zeros((2,nInt))*numpy.nan + + #Filter errors + error = numpy.where(arrayMeteor[:,-1] == 0)[0] + finalMeteor = arrayMeteor[error,:] + + #Meteor Histogram + finalHeights = finalMeteor[:,2] + hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax)) + nMeteorsPerI = hist[0] + heightPerI = hist[1] + + #Sort of meteors + indSort = finalHeights.argsort() + finalMeteor2 = finalMeteor[indSort,:] + + # Calculating winds + ind1 = 0 + ind2 = 0 + + for i in range(nInt): + nMet = nMeteorsPerI[i] + ind1 = ind2 + ind2 = ind1 + nMet + + meteorAux = finalMeteor2[ind1:ind2,:] + + if meteorAux.shape[0] >= meteorThresh: + vel = meteorAux[:, 6] + zen = meteorAux[:, 4]*numpy.pi/180 + azim = meteorAux[:, 3]*numpy.pi/180 + + n = numpy.cos(zen) + # m = (1 - n**2)/(1 - numpy.tan(azim)**2) + # l = m*numpy.tan(azim) + l = numpy.sin(zen)*numpy.sin(azim) + m = numpy.sin(zen)*numpy.cos(azim) + + A = numpy.vstack((l, m)).transpose() + A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose()) + windsAux = numpy.dot(A1, vel) + + winds[0,i] = windsAux[0] + winds[1,i] = windsAux[1] + + return winds, heightPerI[:-1] + + def techniqueNSM_SA(self, **kwargs): + metArray = kwargs['metArray'] + heightList = kwargs['heightList'] + timeList = kwargs['timeList'] + + rx_location = kwargs['rx_location'] + groupList = kwargs['groupList'] + azimuth = kwargs['azimuth'] + dfactor = kwargs['dfactor'] + k = kwargs['k'] + + azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth) + d = dist*dfactor + #Phase calculation + metArray1 = self.__getPhaseSlope(metArray, heightList, timeList) + + metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities + + velEst = numpy.zeros((heightList.size,2))*numpy.nan + azimuth1 = azimuth1*numpy.pi/180 + + for i in range(heightList.size): + h = heightList[i] + indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0] + metHeight = metArray1[indH,:] + if metHeight.shape[0] >= 2: + velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities + iazim = metHeight[:,1].astype(int) + azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths + A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux))) + A = numpy.asmatrix(A) + A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose() + velHor = numpy.dot(A1,velAux) + + velEst[i,:] = numpy.squeeze(velHor) + return velEst + + def __getPhaseSlope(self, metArray, heightList, timeList): + meteorList = [] + #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2 + #Putting back together the meteor matrix + utctime = metArray[:,0] + uniqueTime = numpy.unique(utctime) + + phaseDerThresh = 0.5 + ippSeconds = timeList[1] - timeList[0] + sec = numpy.where(timeList>1)[0][0] + nPairs = metArray.shape[1] - 6 + nHeights = len(heightList) + + for t in uniqueTime: + metArray1 = metArray[utctime==t,:] +# phaseDerThresh = numpy.pi/4 #reducir Phase thresh + tmet = metArray1[:,1].astype(int) + hmet = metArray1[:,2].astype(int) + + metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1)) + metPhase[:,:] = numpy.nan + metPhase[:,hmet,tmet] = metArray1[:,6:].T + + #Delete short trails + metBool = ~numpy.isnan(metPhase[0,:,:]) + heightVect = numpy.sum(metBool, axis = 1) + metBool[heightVect phaseDerThresh)) + metPhase[phDerAux] = numpy.nan + + #--------------------------METEOR DETECTION ----------------------------------------- + indMet = numpy.where(numpy.any(metBool,axis=1))[0] + + for p in numpy.arange(nPairs): + phase = metPhase[p,:,:] + phDer = metDer[p,:,:] + + for h in indMet: + height = heightList[h] + phase1 = phase[h,:] #82 + phDer1 = phDer[h,:] + + phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap + + indValid = numpy.where(~numpy.isnan(phase1))[0] + initMet = indValid[0] + endMet = 0 + + for i in range(len(indValid)-1): + + #Time difference + inow = indValid[i] + inext = indValid[i+1] + idiff = inext - inow + #Phase difference + phDiff = numpy.abs(phase1[inext] - phase1[inow]) + + if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor + sizeTrail = inow - initMet + 1 + if sizeTrail>3*sec: #Too short meteors + x = numpy.arange(initMet,inow+1)*ippSeconds + y = phase1[initMet:inow+1] + ynnan = ~numpy.isnan(y) + x = x[ynnan] + y = y[ynnan] + slope, intercept, r_value, p_value, std_err = stats.linregress(x,y) + ylin = x*slope + intercept + rsq = r_value**2 + if rsq > 0.5: + vel = slope#*height*1000/(k*d) + estAux = numpy.array([utctime,p,height, vel, rsq]) + meteorList.append(estAux) + initMet = inext + metArray2 = numpy.array(meteorList) + + return metArray2 + + def __calculateAzimuth1(self, rx_location, pairslist, azimuth0): + + azimuth1 = numpy.zeros(len(pairslist)) + dist = numpy.zeros(len(pairslist)) + + for i in range(len(rx_location)): + ch0 = pairslist[i][0] + ch1 = pairslist[i][1] + + diffX = rx_location[ch0][0] - rx_location[ch1][0] + diffY = rx_location[ch0][1] - rx_location[ch1][1] + azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi + dist[i] = numpy.sqrt(diffX**2 + diffY**2) + + azimuth1 -= azimuth0 + return azimuth1, dist + + def techniqueNSM_DBS(self, **kwargs): + metArray = kwargs['metArray'] + heightList = kwargs['heightList'] + timeList = kwargs['timeList'] + zenithList = kwargs['zenithList'] + nChan = numpy.max(cmet) + 1 + nHeights = len(heightList) + + utctime = metArray[:,0] + cmet = metArray[:,1] + hmet = metArray1[:,3].astype(int) + h1met = heightList[hmet]*zenithList[cmet] + vmet = metArray1[:,5] + + for i in range(nHeights - 1): + hmin = heightList[i] + hmax = heightList[i + 1] + + vthisH = vmet[(h1met>=hmin) & (h1metSNRthresh)#|(~numpy.isnan(SNRdB)) +# +# #Erase small objects +# boolMet1 = self.__erase_small(boolMet, 2*sec, 5) +# +# auxEEJ = numpy.sum(boolMet1,axis=0) +# indOver = auxEEJ>nProfiles*0.8 #Use this later +# indEEJ = numpy.where(indOver)[0] +# indNEEJ = numpy.where(~indOver)[0] +# +# boolMetFin = boolMet1 +# +# if indEEJ.size > 0: +# boolMet1[:,indEEJ] = False #Erase heights with EEJ +# +# boolMet2 = coh > cohThresh +# boolMet2 = self.__erase_small(boolMet2, 2*sec,5) +# +# #Final Meteor mask +# boolMetFin = boolMet1|boolMet2 + + #Coherence mask + boolMet1 = coh > 0.75 + struc = numpy.ones((30,1)) + boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc) + + #Derivative mask + derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0) + boolMet2 = derPhase < 0.2 +# boolMet2 = ndimage.morphology.binary_opening(boolMet2) +# boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1))) + boolMet2 = ndimage.median_filter(boolMet2,size=5) + boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool))) +# #Final mask +# boolMetFin = boolMet2 + boolMetFin = boolMet1&boolMet2 +# boolMetFin = ndimage.morphology.binary_dilation(boolMetFin) + #Creating data_param + coordMet = numpy.where(boolMetFin) + + tmet = coordMet[0] + hmet = coordMet[1] + + data_param = numpy.zeros((tmet.size, 6 + nPairs)) + data_param[:,0] = utctime + data_param[:,1] = tmet + data_param[:,2] = hmet + data_param[:,3] = SNRm[tmet,hmet] + data_param[:,4] = velRad[tmet,hmet] + data_param[:,5] = coh[tmet,hmet] + data_param[:,6:] = phase[:,tmet,hmet].T + + elif mode == 'DBS': + self.dataOut.groupList = numpy.arange(nChannels) + + #Radial Velocities +# phase = numpy.angle(data_acf[:,1,:,:]) + phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1)) + velRad = phase*lamb/(4*numpy.pi*tSamp) + + #Spectral width + acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1)) + acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1)) + + spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2)) +# velRad = ndimage.median_filter(velRad, size = (1,5,1)) + if allData: + boolMetFin = ~numpy.isnan(SNRdB) + else: + #SNR + boolMet1 = (SNRdB>SNRthresh) #SNR mask + boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5)) + + #Radial velocity + boolMet2 = numpy.abs(velRad) < 30 + boolMet2 = ndimage.median_filter(boolMet2, (1,5,5)) + + #Spectral Width + boolMet3 = spcWidth < 30 + boolMet3 = ndimage.median_filter(boolMet3, (1,5,5)) +# boolMetFin = self.__erase_small(boolMet1, 10,5) + boolMetFin = boolMet1&boolMet2&boolMet3 + + #Creating data_param + coordMet = numpy.where(boolMetFin) + + cmet = coordMet[0] + tmet = coordMet[1] + hmet = coordMet[2] + + data_param = numpy.zeros((tmet.size, 7)) + data_param[:,0] = utctime + data_param[:,1] = cmet + data_param[:,2] = tmet + data_param[:,3] = hmet + data_param[:,4] = SNR[cmet,tmet,hmet].T + data_param[:,5] = velRad[cmet,tmet,hmet].T + data_param[:,6] = spcWidth[cmet,tmet,hmet].T + +# self.dataOut.data_param = data_int + if len(data_param) == 0: + self.dataOut.flagNoData = True + else: + self.dataOut.data_param = data_param + + def __erase_small(self, binArray, threshX, threshY): + labarray, numfeat = ndimage.measurements.label(binArray) + binArray1 = numpy.copy(binArray) + + for i in range(1,numfeat + 1): + auxBin = (labarray==i) + auxSize = auxBin.sum() + + x,y = numpy.where(auxBin) + widthX = x.max() - x.min() + widthY = y.max() - y.min() + + #width X: 3 seg -> 12.5*3 + #width Y: + + if (auxSize < 50) or (widthX < threshX) or (widthY < threshY): + binArray1[auxBin] = False + + return binArray1 + +#--------------- Specular Meteor ---------------- + +class SMDetection(Operation): + ''' + Function DetectMeteors() + Project developed with paper: + HOLDSWORTH ET AL. 2004 + + Input: + self.dataOut.data_pre + + centerReceiverIndex: From the channels, which is the center receiver + + hei_ref: Height reference for the Beacon signal extraction + tauindex: + predefinedPhaseShifts: Predefined phase offset for the voltge signals + + cohDetection: Whether to user Coherent detection or not + cohDet_timeStep: Coherent Detection calculation time step + cohDet_thresh: Coherent Detection phase threshold to correct phases + + noise_timeStep: Noise calculation time step + noise_multiple: Noise multiple to define signal threshold + + multDet_timeLimit: Multiple Detection Removal time limit in seconds + multDet_rangeLimit: Multiple Detection Removal range limit in km + + phaseThresh: Maximum phase difference between receiver to be consider a meteor + SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor + + hmin: Minimum Height of the meteor to use it in the further wind estimations + hmax: Maximum Height of the meteor to use it in the further wind estimations + azimuth: Azimuth angle correction + + Affected: + self.dataOut.data_param + + Rejection Criteria (Errors): + 0: No error; analysis OK + 1: SNR < SNR threshold + 2: angle of arrival (AOA) ambiguously determined + 3: AOA estimate not feasible + 4: Large difference in AOAs obtained from different antenna baselines + 5: echo at start or end of time series + 6: echo less than 5 examples long; too short for analysis + 7: echo rise exceeds 0.3s + 8: echo decay time less than twice rise time + 9: large power level before echo + 10: large power level after echo + 11: poor fit to amplitude for estimation of decay time + 12: poor fit to CCF phase variation for estimation of radial drift velocity + 13: height unresolvable echo: not valid height within 70 to 110 km + 14: height ambiguous echo: more then one possible height within 70 to 110 km + 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s + 16: oscilatory echo, indicating event most likely not an underdense echo + + 17: phase difference in meteor Reestimation + + Data Storage: + Meteors for Wind Estimation (8): + Utc Time | Range Height + Azimuth Zenith errorCosDir + VelRad errorVelRad + Phase0 Phase1 Phase2 Phase3 + TypeError + + ''' + + def run(self, dataOut, hei_ref = None, tauindex = 0, + phaseOffsets = None, + cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25, + noise_timeStep = 4, noise_multiple = 4, + multDet_timeLimit = 1, multDet_rangeLimit = 3, + phaseThresh = 20, SNRThresh = 5, + hmin = 50, hmax=150, azimuth = 0, + channelPositions = None) : + + + #Getting Pairslist + if channelPositions == None: +# channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T + channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella + meteorOps = SMOperations() + pairslist0, distances = meteorOps.getPhasePairs(channelPositions) + heiRang = dataOut.getHeiRange() + #Get Beacon signal - No Beacon signal anymore +# newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex]) +# +# if hei_ref != None: +# newheis = numpy.where(self.dataOut.heightList>hei_ref) +# + + + #****************REMOVING HARDWARE PHASE DIFFERENCES*************** + # see if the user put in pre defined phase shifts + voltsPShift = dataOut.data_pre.copy() + +# if predefinedPhaseShifts != None: +# hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180 +# +# # elif beaconPhaseShifts: +# # #get hardware phase shifts using beacon signal +# # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10) +# # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0) +# +# else: +# hardwarePhaseShifts = numpy.zeros(5) +# +# voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex') +# for i in range(self.dataOut.data_pre.shape[0]): +# voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i]) + + #******************END OF REMOVING HARDWARE PHASE DIFFERENCES********* + + #Remove DC + voltsDC = numpy.mean(voltsPShift,1) + voltsDC = numpy.mean(voltsDC,1) + for i in range(voltsDC.shape[0]): + voltsPShift[i] = voltsPShift[i] - voltsDC[i] + + #Don't considerate last heights, theyre used to calculate Hardware Phase Shift +# voltsPShift = voltsPShift[:,:,:newheis[0][0]] + + #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) ********** + #Coherent Detection + if cohDetection: + #use coherent detection to get the net power + cohDet_thresh = cohDet_thresh*numpy.pi/180 + voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh) + + #Non-coherent detection! + powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0) + #********** END OF COH/NON-COH POWER CALCULATION********************** + + #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS **************** + #Get noise + noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval) +# noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval) + #Get signal threshold + signalThresh = noise_multiple*noise + #Meteor echoes detection + listMeteors = self.__findMeteors(powerNet, signalThresh) + #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION ********** + + #************** REMOVE MULTIPLE DETECTIONS (3.5) *************************** + #Parameters + heiRange = dataOut.getHeiRange() + rangeInterval = heiRange[1] - heiRange[0] + rangeLimit = multDet_rangeLimit/rangeInterval + timeLimit = multDet_timeLimit/dataOut.timeInterval + #Multiple detection removals + listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit) + #************ END OF REMOVE MULTIPLE DETECTIONS ********************** + + #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ******************** + #Parameters + phaseThresh = phaseThresh*numpy.pi/180 + thresh = [phaseThresh, noise_multiple, SNRThresh] + #Meteor reestimation (Errors N 1, 6, 12, 17) + listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency) +# listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise) + #Estimation of decay times (Errors N 7, 8, 11) + listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency) + #******************* END OF METEOR REESTIMATION ******************* + + #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) ************************** + #Calculating Radial Velocity (Error N 15) + radialStdThresh = 10 + listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval) + + if len(listMeteors4) > 0: + #Setting New Array + date = dataOut.utctime + arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang) + + #Correcting phase offset + if phaseOffsets != None: + phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180 + arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets) + + #Second Pairslist + pairsList = [] + pairx = (0,1) + pairy = (2,3) + pairsList.append(pairx) + pairsList.append(pairy) + + jph = numpy.array([0,0,0,0]) + h = (hmin,hmax) + arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph) + +# #Calculate AOA (Error N 3, 4) +# #JONES ET AL. 1998 +# error = arrayParameters[:,-1] +# AOAthresh = numpy.pi/8 +# phases = -arrayParameters[:,9:13] +# arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth) +# +# #Calculate Heights (Error N 13 and 14) +# error = arrayParameters[:,-1] +# Ranges = arrayParameters[:,2] +# zenith = arrayParameters[:,5] +# arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax) +# error = arrayParameters[:,-1] + #********************* END OF PARAMETERS CALCULATION ************************** + + #***************************+ PASS DATA TO NEXT STEP ********************** +# arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1])) + dataOut.data_param = arrayParameters + + if arrayParameters == None: + dataOut.flagNoData = True + else: + dataOut.flagNoData = True + + return + + def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n): + + minIndex = min(newheis[0]) + maxIndex = max(newheis[0]) + + voltage = voltage0[:,:,minIndex:maxIndex+1] + nLength = voltage.shape[1]/n + nMin = 0 + nMax = 0 + phaseOffset = numpy.zeros((len(pairslist),n)) + + for i in range(n): + nMax += nLength + phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0])) + phaseCCF = numpy.mean(phaseCCF, axis = 2) + phaseOffset[:,i] = phaseCCF.transpose() + nMin = nMax +# phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist) + + #Remove Outliers + factor = 2 + wt = phaseOffset - signal.medfilt(phaseOffset,(1,5)) + dw = numpy.std(wt,axis = 1) + dw = dw.reshape((dw.size,1)) + ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor)) + phaseOffset[ind] = numpy.nan + phaseOffset = stats.nanmean(phaseOffset, axis=1) + + return phaseOffset + + def __shiftPhase(self, data, phaseShift): + #this will shift the phase of a complex number + dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j) + return dataShifted + + def __estimatePhaseDifference(self, array, pairslist): + nChannel = array.shape[0] + nHeights = array.shape[2] + numPairs = len(pairslist) +# phaseCCF = numpy.zeros((nChannel, 5, nHeights)) + phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2])) + + #Correct phases + derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:] + indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi) + + if indDer[0].shape[0] > 0: + for i in range(indDer[0].shape[0]): + signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]]) + phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi + +# for j in range(numSides): +# phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2]) +# phaseCCF[j,:,:] = numpy.angle(phaseCCFAux) +# + #Linear + phaseInt = numpy.zeros((numPairs,1)) + angAllCCF = phaseCCF[:,[0,1,3,4],0] + for j in range(numPairs): + fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:]) + phaseInt[j] = fit[1] + #Phase Differences + phaseDiff = phaseInt - phaseCCF[:,2,:] + phaseArrival = phaseInt.reshape(phaseInt.size) + + #Dealias + phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival)) +# indAlias = numpy.where(phaseArrival > numpy.pi) +# phaseArrival[indAlias] -= 2*numpy.pi +# indAlias = numpy.where(phaseArrival < -numpy.pi) +# phaseArrival[indAlias] += 2*numpy.pi + + return phaseDiff, phaseArrival + + def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh): + #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power + #find the phase shifts of each channel over 1 second intervals + #only look at ranges below the beacon signal + numProfPerBlock = numpy.ceil(timeSegment/timeInterval) + numBlocks = int(volts.shape[1]/numProfPerBlock) + numHeights = volts.shape[2] + nChannel = volts.shape[0] + voltsCohDet = volts.copy() + + pairsarray = numpy.array(pairslist) + indSides = pairsarray[:,1] +# indSides = numpy.array(range(nChannel)) +# indSides = numpy.delete(indSides, indCenter) +# +# listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0) + listBlocks = numpy.array_split(volts, numBlocks, 1) + + startInd = 0 + endInd = 0 + + for i in range(numBlocks): + startInd = endInd + endInd = endInd + listBlocks[i].shape[1] + + arrayBlock = listBlocks[i] +# arrayBlockCenter = listCenter[i] + + #Estimate the Phase Difference + phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist) + #Phase Difference RMS + arrayPhaseRMS = numpy.abs(phaseDiff) + phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0) + indPhase = numpy.where(phaseRMSaux==4) + #Shifting + if indPhase[0].shape[0] > 0: + for j in range(indSides.size): + arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose()) + voltsCohDet[:,startInd:endInd,:] = arrayBlock + + return voltsCohDet + + def __calculateCCF(self, volts, pairslist ,laglist): + + nHeights = volts.shape[2] + nPoints = volts.shape[1] + voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex') + + for i in range(len(pairslist)): + volts1 = volts[pairslist[i][0]] + volts2 = volts[pairslist[i][1]] + + for t in range(len(laglist)): + idxT = laglist[t] + if idxT >= 0: + vStacked = numpy.vstack((volts2[idxT:,:], + numpy.zeros((idxT, nHeights),dtype='complex'))) + else: + vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'), + volts2[:(nPoints + idxT),:])) + voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0) + + vStacked = None + return voltsCCF + + def __getNoise(self, power, timeSegment, timeInterval): + numProfPerBlock = numpy.ceil(timeSegment/timeInterval) + numBlocks = int(power.shape[0]/numProfPerBlock) + numHeights = power.shape[1] + + listPower = numpy.array_split(power, numBlocks, 0) + noise = numpy.zeros((power.shape[0], power.shape[1])) + noise1 = numpy.zeros((power.shape[0], power.shape[1])) + + startInd = 0 + endInd = 0 + + for i in range(numBlocks): #split por canal + startInd = endInd + endInd = endInd + listPower[i].shape[0] + + arrayBlock = listPower[i] + noiseAux = numpy.mean(arrayBlock, 0) +# noiseAux = numpy.median(noiseAux) +# noiseAux = numpy.mean(arrayBlock) + noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux + + noiseAux1 = numpy.mean(arrayBlock) + noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1 + + return noise, noise1 + + def __findMeteors(self, power, thresh): + nProf = power.shape[0] + nHeights = power.shape[1] + listMeteors = [] + + for i in range(nHeights): + powerAux = power[:,i] + threshAux = thresh[:,i] + + indUPthresh = numpy.where(powerAux > threshAux)[0] + indDNthresh = numpy.where(powerAux <= threshAux)[0] + + j = 0 + + while (j < indUPthresh.size - 2): + if (indUPthresh[j + 2] == indUPthresh[j] + 2): + indDNAux = numpy.where(indDNthresh > indUPthresh[j]) + indDNthresh = indDNthresh[indDNAux] + + if (indDNthresh.size > 0): + indEnd = indDNthresh[0] - 1 + indInit = indUPthresh[j] + + meteor = powerAux[indInit:indEnd + 1] + indPeak = meteor.argmax() + indInit + FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0))) + + listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!! + j = numpy.where(indUPthresh == indEnd)[0] + 1 + else: j+=1 + else: j+=1 + + return listMeteors + + def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit): + + arrayMeteors = numpy.asarray(listMeteors) + listMeteors1 = [] + + while arrayMeteors.shape[0] > 0: + FLAs = arrayMeteors[:,4] + maxFLA = FLAs.argmax() + listMeteors1.append(arrayMeteors[maxFLA,:]) + + MeteorInitTime = arrayMeteors[maxFLA,1] + MeteorEndTime = arrayMeteors[maxFLA,3] + MeteorHeight = arrayMeteors[maxFLA,0] + + #Check neighborhood + maxHeightIndex = MeteorHeight + rangeLimit + minHeightIndex = MeteorHeight - rangeLimit + minTimeIndex = MeteorInitTime - timeLimit + maxTimeIndex = MeteorEndTime + timeLimit + + #Check Heights + indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex) + indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex) + indBoth = numpy.where(numpy.logical_and(indTime,indHeight)) + + arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0) + + return listMeteors1 + + def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency): + numHeights = volts.shape[2] + nChannel = volts.shape[0] + + thresholdPhase = thresh[0] + thresholdNoise = thresh[1] + thresholdDB = float(thresh[2]) + + thresholdDB1 = 10**(thresholdDB/10) + pairsarray = numpy.array(pairslist) + indSides = pairsarray[:,1] + + pairslist1 = list(pairslist) + pairslist1.append((0,1)) + pairslist1.append((3,4)) + + listMeteors1 = [] + listPowerSeries = [] + listVoltageSeries = [] + #volts has the war data + + if frequency == 30e6: + timeLag = 45*10**-3 + else: + timeLag = 15*10**-3 + lag = numpy.ceil(timeLag/timeInterval) + + for i in range(len(listMeteors)): + + ###################### 3.6 - 3.7 PARAMETERS REESTIMATION ######################### + meteorAux = numpy.zeros(16) + + #Loading meteor Data (mHeight, mStart, mPeak, mEnd) + mHeight = listMeteors[i][0] + mStart = listMeteors[i][1] + mPeak = listMeteors[i][2] + mEnd = listMeteors[i][3] + + #get the volt data between the start and end times of the meteor + meteorVolts = volts[:,mStart:mEnd+1,mHeight] + meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1) + + #3.6. Phase Difference estimation + phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist) + + #3.7. Phase difference removal & meteor start, peak and end times reestimated + #meteorVolts0.- all Channels, all Profiles + meteorVolts0 = volts[:,:,mHeight] + meteorThresh = noise[:,mHeight]*thresholdNoise + meteorNoise = noise[:,mHeight] + meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting + powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power + + #Times reestimation + mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0] + if mStart1.size > 0: + mStart1 = mStart1[-1] + 1 + + else: + mStart1 = mPeak + + mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1 + mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0] + if mEndDecayTime1.size == 0: + mEndDecayTime1 = powerNet0.size + else: + mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1 +# mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax() + + #meteorVolts1.- all Channels, from start to end + meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1] + meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1] + if meteorVolts2.shape[1] == 0: + meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1] + meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1) + meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1) + ##################### END PARAMETERS REESTIMATION ######################### + + ##################### 3.8 PHASE DIFFERENCE REESTIMATION ######################## +# if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis + if meteorVolts2.shape[1] > 0: + #Phase Difference re-estimation + phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation +# phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist) + meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1]) + phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1)) + meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting + + #Phase Difference RMS + phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1))) + powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0) + #Data from Meteor + mPeak1 = powerNet1.argmax() + mStart1 + mPeakPower1 = powerNet1.max() + noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight]) + mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux + Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]) + Meteor1 = numpy.hstack((Meteor1,phaseDiffint)) + PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1] + #Vectorize + meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1] + meteorAux[7:11] = phaseDiffint[0:4] + + #Rejection Criterions + if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation + meteorAux[-1] = 17 + elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB + meteorAux[-1] = 1 + + + else: + meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd] + meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis + PowerSeries = 0 + + listMeteors1.append(meteorAux) + listPowerSeries.append(PowerSeries) + listVoltageSeries.append(meteorVolts1) + + return listMeteors1, listPowerSeries, listVoltageSeries + + def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency): + + threshError = 10 + #Depending if it is 30 or 50 MHz + if frequency == 30e6: + timeLag = 45*10**-3 + else: + timeLag = 15*10**-3 + lag = numpy.ceil(timeLag/timeInterval) + + listMeteors1 = [] + + for i in range(len(listMeteors)): + meteorPower = listPower[i] + meteorAux = listMeteors[i] + + if meteorAux[-1] == 0: + + try: + indmax = meteorPower.argmax() + indlag = indmax + lag + + y = meteorPower[indlag:] + x = numpy.arange(0, y.size)*timeLag + + #first guess + a = y[0] + tau = timeLag + #exponential fit + popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau]) + y1 = self.__exponential_function(x, *popt) + #error estimation + error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size)) + + decayTime = popt[1] + riseTime = indmax*timeInterval + meteorAux[11:13] = [decayTime, error] + + #Table items 7, 8 and 11 + if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s + meteorAux[-1] = 7 + elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time + meteorAux[-1] = 8 + if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time + meteorAux[-1] = 11 + + + except: + meteorAux[-1] = 11 + + + listMeteors1.append(meteorAux) + + return listMeteors1 + + #Exponential Function + + def __exponential_function(self, x, a, tau): + y = a*numpy.exp(-x/tau) + return y + + def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval): + + pairslist1 = list(pairslist) + pairslist1.append((0,1)) + pairslist1.append((3,4)) + numPairs = len(pairslist1) + #Time Lag + timeLag = 45*10**-3 + c = 3e8 + lag = numpy.ceil(timeLag/timeInterval) + freq = 30e6 + + listMeteors1 = [] + + for i in range(len(listMeteors)): + meteorAux = listMeteors[i] + if meteorAux[-1] == 0: + mStart = listMeteors[i][1] + mPeak = listMeteors[i][2] + mLag = mPeak - mStart + lag + + #get the volt data between the start and end times of the meteor + meteorVolts = listVolts[i] + meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1) + + #Get CCF + allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2]) + + #Method 2 + slopes = numpy.zeros(numPairs) + time = numpy.array([-2,-1,1,2])*timeInterval + angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0]) + + #Correct phases + derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1] + indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi) + + if indDer[0].shape[0] > 0: + for i in range(indDer[0].shape[0]): + signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]]) + angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi + +# fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]])) + for j in range(numPairs): + fit = stats.linregress(time, angAllCCF[j,:]) + slopes[j] = fit[0] + + #Remove Outlier +# indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes))) +# slopes = numpy.delete(slopes,indOut) +# indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes))) +# slopes = numpy.delete(slopes,indOut) + + radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq) + radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq) + meteorAux[-2] = radialError + meteorAux[-3] = radialVelocity + + #Setting Error + #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s + if numpy.abs(radialVelocity) > 200: + meteorAux[-1] = 15 + #Number 12: Poor fit to CCF variation for estimation of radial drift velocity + elif radialError > radialStdThresh: + meteorAux[-1] = 12 + + listMeteors1.append(meteorAux) + return listMeteors1 + + def __setNewArrays(self, listMeteors, date, heiRang): + + #New arrays + arrayMeteors = numpy.array(listMeteors) + arrayParameters = numpy.zeros((len(listMeteors), 13)) + + #Date inclusion +# date = re.findall(r'\((.*?)\)', date) +# date = date[0].split(',') +# date = map(int, date) +# +# if len(date)<6: +# date.append(0) +# +# date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]] +# arrayDate = numpy.tile(date, (len(listMeteors), 1)) + arrayDate = numpy.tile(date, (len(listMeteors))) + + #Meteor array +# arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)] +# arrayMeteors = numpy.hstack((arrayDate, arrayMeteors)) + + #Parameters Array + arrayParameters[:,0] = arrayDate #Date + arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range + arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error + arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases + arrayParameters[:,-1] = arrayMeteors[:,-1] #Error + + + return arrayParameters + +class CorrectSMPhases(Operation): + + def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None): + + arrayParameters = dataOut.data_param + pairsList = [] + pairx = (0,1) + pairy = (2,3) + pairsList.append(pairx) + pairsList.append(pairy) + jph = numpy.zeros(4) + + phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180 + # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets) + arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets))) + + meteorOps = SMOperations() + if channelPositions == None: + # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T + channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella + + pairslist0, distances = meteorOps.getPhasePairs(channelPositions) + h = (hmin,hmax) + + arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph) + + dataOut.data_param = arrayParameters + return + +class SMPhaseCalibration(Operation): + + __buffer = None + + __initime = None + + __dataReady = False + + __isConfig = False + + def __checkTime(self, currentTime, initTime, paramInterval, outputInterval): + + dataTime = currentTime + paramInterval + deltaTime = dataTime - initTime + + if deltaTime >= outputInterval or deltaTime < 0: + return True + + return False + + def __getGammas(self, pairs, d, phases): + gammas = numpy.zeros(2) + + for i in range(len(pairs)): + + pairi = pairs[i] + + phip3 = phases[:,pairi[1]] + d3 = d[pairi[1]] + phip2 = phases[:,pairi[0]] + d2 = d[pairi[0]] + #Calculating gamma +# jdcos = alp1/(k*d1) +# jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0))) + jgamma = -phip2*d3/d2 - phip3 + jgamma = numpy.angle(numpy.exp(1j*jgamma)) +# jgamma[jgamma>numpy.pi] -= 2*numpy.pi +# jgamma[jgamma<-numpy.pi] += 2*numpy.pi + + #Revised distribution + jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi)) + + #Histogram + nBins = 64.0 + rmin = -0.5*numpy.pi + rmax = 0.5*numpy.pi + phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax)) + + meteorsY = phaseHisto[0] + phasesX = phaseHisto[1][:-1] + width = phasesX[1] - phasesX[0] + phasesX += width/2 + + #Gaussian aproximation + bpeak = meteorsY.argmax() + peak = meteorsY.max() + jmin = bpeak - 5 + jmax = bpeak + 5 + 1 + + if jmin<0: + jmin = 0 + jmax = 6 + elif jmax > meteorsY.size: + jmin = meteorsY.size - 6 + jmax = meteorsY.size + + x0 = numpy.array([peak,bpeak,50]) + coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax])) + + #Gammas + gammas[i] = coeff[0][1] + + return gammas + + def __residualFunction(self, coeffs, y, t): + + return y - self.__gauss_function(t, coeffs) + + def __gauss_function(self, t, coeffs): + + return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2) + + def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray): + meteorOps = SMOperations() + nchan = 4 + pairx = pairsList[0] + pairy = pairsList[1] + center_xangle = 0 + center_yangle = 0 + range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4]) + ntimes = len(range_angle) + + nstepsx = 20.0 + nstepsy = 20.0 + + for iz in range(ntimes): + min_xangle = -range_angle[iz]/2 + center_xangle + max_xangle = range_angle[iz]/2 + center_xangle + min_yangle = -range_angle[iz]/2 + center_yangle + max_yangle = range_angle[iz]/2 + center_yangle + + inc_x = (max_xangle-min_xangle)/nstepsx + inc_y = (max_yangle-min_yangle)/nstepsy + + alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle + alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle + penalty = numpy.zeros((nstepsx,nstepsy)) + jph_array = numpy.zeros((nchan,nstepsx,nstepsy)) + jph = numpy.zeros(nchan) + + # Iterations looking for the offset + for iy in range(int(nstepsy)): + for ix in range(int(nstepsx)): + jph[pairy[1]] = alpha_y[iy] + jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]] + + jph[pairx[1]] = alpha_x[ix] + jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]] + + jph_array[:,ix,iy] = jph + + meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph) + error = meteorsArray1[:,-1] + ind1 = numpy.where(error==0)[0] + penalty[ix,iy] = ind1.size + + i,j = numpy.unravel_index(penalty.argmax(), penalty.shape) + phOffset = jph_array[:,i,j] + + center_xangle = phOffset[pairx[1]] + center_yangle = phOffset[pairy[1]] + + phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j])) + phOffset = phOffset*180/numpy.pi + return phOffset + + + def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1): + + dataOut.flagNoData = True + self.__dataReady = False + dataOut.outputInterval = nHours*3600 + + if self.__isConfig == False: +# self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03) + #Get Initial LTC time + self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime) + self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds() + + self.__isConfig = True + + if self.__buffer == None: + self.__buffer = dataOut.data_param.copy() + + else: + self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param)) + + self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready + + if self.__dataReady: + dataOut.utctimeInit = self.__initime + self.__initime += dataOut.outputInterval #to erase time offset + + freq = dataOut.frequency + c = dataOut.C #m/s + lamb = c/freq + k = 2*numpy.pi/lamb + azimuth = 0 + h = (hmin, hmax) + pairs = ((0,1),(2,3)) + + if channelPositions == None: +# channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T + channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella + meteorOps = SMOperations() + pairslist0, distances = meteorOps.getPhasePairs(channelPositions) + +# distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb] + + meteorsArray = self.__buffer + error = meteorsArray[:,-1] + boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14) + ind1 = numpy.where(boolError)[0] + meteorsArray = meteorsArray[ind1,:] + meteorsArray[:,-1] = 0 + phases = meteorsArray[:,8:12] + + #Calculate Gammas + gammas = self.__getGammas(pairs, distances, phases) +# gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180 + #Calculate Phases + phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray) + phasesOff = phasesOff.reshape((1,phasesOff.size)) + dataOut.data_output = -phasesOff + dataOut.flagNoData = False + self.__buffer = None + + + return + +class SMOperations(): + + def __init__(self): + + return + + def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph): + + arrayParameters = arrayParameters0.copy() + hmin = h[0] + hmax = h[1] + + #Calculate AOA (Error N 3, 4) + #JONES ET AL. 1998 + AOAthresh = numpy.pi/8 + error = arrayParameters[:,-1] + phases = -arrayParameters[:,8:12] + jph +# phases = numpy.unwrap(phases) + arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth) + + #Calculate Heights (Error N 13 and 14) + error = arrayParameters[:,-1] + Ranges = arrayParameters[:,1] + zenith = arrayParameters[:,4] + arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax) + + #----------------------- Get Final data ------------------------------------ +# error = arrayParameters[:,-1] +# ind1 = numpy.where(error==0)[0] +# arrayParameters = arrayParameters[ind1,:] + + return arrayParameters + + def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth): + + arrayAOA = numpy.zeros((phases.shape[0],3)) + cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions) + + arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth) + cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1) + arrayAOA[:,2] = cosDirError + + azimuthAngle = arrayAOA[:,0] + zenithAngle = arrayAOA[:,1] + + #Setting Error + indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0] + error[indError] = 0 + #Number 3: AOA not fesible + indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0] + error[indInvalid] = 3 + #Number 4: Large difference in AOAs obtained from different antenna baselines + indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0] + error[indInvalid] = 4 + return arrayAOA, error + + def __getDirectionCosines(self, arrayPhase, pairsList, distances): + + #Initializing some variables + ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi + ang_aux = ang_aux.reshape(1,ang_aux.size) + + cosdir = numpy.zeros((arrayPhase.shape[0],2)) + cosdir0 = numpy.zeros((arrayPhase.shape[0],2)) + + + for i in range(2): + ph0 = arrayPhase[:,pairsList[i][0]] + ph1 = arrayPhase[:,pairsList[i][1]] + d0 = distances[pairsList[i][0]] + d1 = distances[pairsList[i][1]] + + ph0_aux = ph0 + ph1 + ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux)) +# ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi +# ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi + #First Estimation + cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1)) + + #Most-Accurate Second Estimation + phi1_aux = ph0 - ph1 + phi1_aux = phi1_aux.reshape(phi1_aux.size,1) + #Direction Cosine 1 + cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1)) + + #Searching the correct Direction Cosine + cosdir0_aux = cosdir0[:,i] + cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1) + #Minimum Distance + cosDiff = (cosdir1 - cosdir0_aux)**2 + indcos = cosDiff.argmin(axis = 1) + #Saving Value obtained + cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos] + + return cosdir0, cosdir + + def __calculateAOA(self, cosdir, azimuth): + cosdirX = cosdir[:,0] + cosdirY = cosdir[:,1] + + zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi + azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east + angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose() + + return angles + + def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight): + + Ramb = 375 #Ramb = c/(2*PRF) + Re = 6371 #Earth Radius + heights = numpy.zeros(Ranges.shape) + + R_aux = numpy.array([0,1,2])*Ramb + R_aux = R_aux.reshape(1,R_aux.size) + + Ranges = Ranges.reshape(Ranges.size,1) + + Ri = Ranges + R_aux + hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re + + #Check if there is a height between 70 and 110 km + h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1) + ind_h = numpy.where(h_bool == 1)[0] + + hCorr = hi[ind_h, :] + ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight)) + + hCorr = hi[ind_hCorr] + heights[ind_h] = hCorr + + #Setting Error + #Number 13: Height unresolvable echo: not valid height within 70 to 110 km + #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km + indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0] + error[indError] = 0 + indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0] + error[indInvalid2] = 14 + indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0] + error[indInvalid1] = 13 + + return heights, error + + def getPhasePairs(self, channelPositions): + chanPos = numpy.array(channelPositions) + listOper = list(itertools.combinations(range(5),2)) + + distances = numpy.zeros(4) + axisX = [] + axisY = [] + distX = numpy.zeros(3) + distY = numpy.zeros(3) + ix = 0 + iy = 0 + + pairX = numpy.zeros((2,2)) + pairY = numpy.zeros((2,2)) + + for i in range(len(listOper)): + pairi = listOper[i] + + posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:]) + + if posDif[0] == 0: + axisY.append(pairi) + distY[iy] = posDif[1] + iy += 1 + elif posDif[1] == 0: + axisX.append(pairi) + distX[ix] = posDif[0] + ix += 1 + + for i in range(2): + if i==0: + dist0 = distX + axis0 = axisX + else: + dist0 = distY + axis0 = axisY + + side = numpy.argsort(dist0)[:-1] + axis0 = numpy.array(axis0)[side,:] + chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0]) + axis1 = numpy.unique(numpy.reshape(axis0,4)) + side = axis1[axis1 != chanC] + diff1 = chanPos[chanC,i] - chanPos[side[0],i] + diff2 = chanPos[chanC,i] - chanPos[side[1],i] + if diff1<0: + chan2 = side[0] + d2 = numpy.abs(diff1) + chan1 = side[1] + d1 = numpy.abs(diff2) + else: + chan2 = side[1] + d2 = numpy.abs(diff2) + chan1 = side[0] + d1 = numpy.abs(diff1) + + if i==0: + chanCX = chanC + chan1X = chan1 + chan2X = chan2 + distances[0:2] = numpy.array([d1,d2]) + else: + chanCY = chanC + chan1Y = chan1 + chan2Y = chan2 + distances[2:4] = numpy.array([d1,d2]) +# axisXsides = numpy.reshape(axisX[ix,:],4) +# +# channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0]) +# channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0]) +# +# ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0] +# ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0] +# channel25X = int(pairX[0,ind25X]) +# channel20X = int(pairX[1,ind20X]) +# ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0] +# ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0] +# channel25Y = int(pairY[0,ind25Y]) +# channel20Y = int(pairY[1,ind20Y]) + +# pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)] + pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)] + + return pairslist, distances +# def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth): +# +# arrayAOA = numpy.zeros((phases.shape[0],3)) +# cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList) +# +# arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth) +# cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1) +# arrayAOA[:,2] = cosDirError +# +# azimuthAngle = arrayAOA[:,0] +# zenithAngle = arrayAOA[:,1] +# +# #Setting Error +# #Number 3: AOA not fesible +# indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0] +# error[indInvalid] = 3 +# #Number 4: Large difference in AOAs obtained from different antenna baselines +# indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0] +# error[indInvalid] = 4 +# return arrayAOA, error +# +# def __getDirectionCosines(self, arrayPhase, pairsList): +# +# #Initializing some variables +# ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi +# ang_aux = ang_aux.reshape(1,ang_aux.size) +# +# cosdir = numpy.zeros((arrayPhase.shape[0],2)) +# cosdir0 = numpy.zeros((arrayPhase.shape[0],2)) +# +# +# for i in range(2): +# #First Estimation +# phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]] +# #Dealias +# indcsi = numpy.where(phi0_aux > numpy.pi) +# phi0_aux[indcsi] -= 2*numpy.pi +# indcsi = numpy.where(phi0_aux < -numpy.pi) +# phi0_aux[indcsi] += 2*numpy.pi +# #Direction Cosine 0 +# cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5) +# +# #Most-Accurate Second Estimation +# phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]] +# phi1_aux = phi1_aux.reshape(phi1_aux.size,1) +# #Direction Cosine 1 +# cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5) +# +# #Searching the correct Direction Cosine +# cosdir0_aux = cosdir0[:,i] +# cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1) +# #Minimum Distance +# cosDiff = (cosdir1 - cosdir0_aux)**2 +# indcos = cosDiff.argmin(axis = 1) +# #Saving Value obtained +# cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos] +# +# return cosdir0, cosdir +# +# def __calculateAOA(self, cosdir, azimuth): +# cosdirX = cosdir[:,0] +# cosdirY = cosdir[:,1] +# +# zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi +# azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east +# angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose() +# +# return angles +# +# def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight): +# +# Ramb = 375 #Ramb = c/(2*PRF) +# Re = 6371 #Earth Radius +# heights = numpy.zeros(Ranges.shape) +# +# R_aux = numpy.array([0,1,2])*Ramb +# R_aux = R_aux.reshape(1,R_aux.size) +# +# Ranges = Ranges.reshape(Ranges.size,1) +# +# Ri = Ranges + R_aux +# hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re +# +# #Check if there is a height between 70 and 110 km +# h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1) +# ind_h = numpy.where(h_bool == 1)[0] +# +# hCorr = hi[ind_h, :] +# ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight)) +# +# hCorr = hi[ind_hCorr] +# heights[ind_h] = hCorr +# +# #Setting Error +# #Number 13: Height unresolvable echo: not valid height within 70 to 110 km +# #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km +# +# indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0] +# error[indInvalid2] = 14 +# indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0] +# error[indInvalid1] = 13 +# +# return heights, error + \ No newline at end of file diff --git a/schainpy/model/proc/.svn/text-base/jroproc_parameters.pyc.svn-base b/schainpy/model/proc/.svn/text-base/jroproc_parameters.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..34fc2f31a1699465e46a01246d59e5e2906cd065 GIT binary patch literal 71884 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 K-4v4*I{^Tu2Msy^ literal 0 Hc$@ maxHei): + raise ValueError, "Error selecting heights: Height range (%d,%d) is not valid" % (minHei, maxHei) + + if (minHei < self.dataOut.heightList[0]): + minHei = self.dataOut.heightList[0] + + if (maxHei > self.dataOut.heightList[-1]): + maxHei = self.dataOut.heightList[-1] + + minIndex = 0 + maxIndex = 0 + heights = self.dataOut.heightList + + inda = numpy.where(heights >= minHei) + indb = numpy.where(heights <= maxHei) + + try: + minIndex = inda[0][0] + except: + minIndex = 0 + + try: + maxIndex = indb[0][-1] + except: + maxIndex = len(heights) + + self.selectHeightsByIndex(minIndex, maxIndex) + + return 1 + + def getBeaconSignal(self, tauindex = 0, channelindex = 0, hei_ref=None): + newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex]) + + if hei_ref != None: + newheis = numpy.where(self.dataOut.heightList>hei_ref) + + minIndex = min(newheis[0]) + maxIndex = max(newheis[0]) + data_spc = self.dataOut.data_spc[:,:,minIndex:maxIndex+1] + heightList = self.dataOut.heightList[minIndex:maxIndex+1] + + # determina indices + nheis = int(self.dataOut.radarControllerHeaderObj.txB/(self.dataOut.heightList[1]-self.dataOut.heightList[0])) + avg_dB = 10*numpy.log10(numpy.sum(data_spc[channelindex,:,:],axis=0)) + beacon_dB = numpy.sort(avg_dB)[-nheis:] + beacon_heiIndexList = [] + for val in avg_dB.tolist(): + if val >= beacon_dB[0]: + beacon_heiIndexList.append(avg_dB.tolist().index(val)) + + #data_spc = data_spc[:,:,beacon_heiIndexList] + data_cspc = None + if self.dataOut.data_cspc is not None: + data_cspc = self.dataOut.data_cspc[:,:,minIndex:maxIndex+1] + #data_cspc = data_cspc[:,:,beacon_heiIndexList] + + data_dc = None + if self.dataOut.data_dc is not None: + data_dc = self.dataOut.data_dc[:,minIndex:maxIndex+1] + #data_dc = data_dc[:,beacon_heiIndexList] + + self.dataOut.data_spc = data_spc + self.dataOut.data_cspc = data_cspc + self.dataOut.data_dc = data_dc + self.dataOut.heightList = heightList + self.dataOut.beacon_heiIndexList = beacon_heiIndexList + + return 1 + + + def selectHeightsByIndex(self, minIndex, maxIndex): + """ + Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango + minIndex <= index <= maxIndex + + Input: + minIndex : valor de indice minimo de altura a considerar + maxIndex : valor de indice maximo de altura a considerar + + Affected: + self.dataOut.data_spc + self.dataOut.data_cspc + self.dataOut.data_dc + self.dataOut.heightList + + Return: + 1 si el metodo se ejecuto con exito caso contrario devuelve 0 + """ + + if (minIndex < 0) or (minIndex > maxIndex): + raise ValueError, "Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex) + + if (maxIndex >= self.dataOut.nHeights): + maxIndex = self.dataOut.nHeights-1 + + #Spectra + data_spc = self.dataOut.data_spc[:,:,minIndex:maxIndex+1] + + data_cspc = None + if self.dataOut.data_cspc is not None: + data_cspc = self.dataOut.data_cspc[:,:,minIndex:maxIndex+1] + + data_dc = None + if self.dataOut.data_dc is not None: + data_dc = self.dataOut.data_dc[:,minIndex:maxIndex+1] + + self.dataOut.data_spc = data_spc + self.dataOut.data_cspc = data_cspc + self.dataOut.data_dc = data_dc + + self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex+1] + + return 1 + + def removeDC(self, mode = 2): + jspectra = self.dataOut.data_spc + jcspectra = self.dataOut.data_cspc + + + num_chan = jspectra.shape[0] + num_hei = jspectra.shape[2] + + if jcspectra is not None: + jcspectraExist = True + num_pairs = jcspectra.shape[0] + else: jcspectraExist = False + + freq_dc = jspectra.shape[1]/2 + ind_vel = numpy.array([-2,-1,1,2]) + freq_dc + + if ind_vel[0]<0: + ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof + + if mode == 1: + jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION + + if jcspectraExist: + jcspectra[:,freq_dc,:] = (jcspectra[:,ind_vel[1],:] + jcspectra[:,ind_vel[2],:])/2 + + if mode == 2: + + vel = numpy.array([-2,-1,1,2]) + xx = numpy.zeros([4,4]) + + for fil in range(4): + xx[fil,:] = vel[fil]**numpy.asarray(range(4)) + + xx_inv = numpy.linalg.inv(xx) + xx_aux = xx_inv[0,:] + + for ich in range(num_chan): + yy = jspectra[ich,ind_vel,:] + jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy) + + junkid = jspectra[ich,freq_dc,:]<=0 + cjunkid = sum(junkid) + + if cjunkid.any(): + jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2 + + if jcspectraExist: + for ip in range(num_pairs): + yy = jcspectra[ip,ind_vel,:] + jcspectra[ip,freq_dc,:] = numpy.dot(xx_aux,yy) + + + self.dataOut.data_spc = jspectra + self.dataOut.data_cspc = jcspectra + + return 1 + + def removeInterference(self, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None): + + jspectra = self.dataOut.data_spc + jcspectra = self.dataOut.data_cspc + jnoise = self.dataOut.getNoise() + num_incoh = self.dataOut.nIncohInt + + num_channel = jspectra.shape[0] + num_prof = jspectra.shape[1] + num_hei = jspectra.shape[2] + + #hei_interf + if hei_interf is None: + count_hei = num_hei/2 #Como es entero no importa + hei_interf = numpy.asmatrix(range(count_hei)) + num_hei - count_hei + hei_interf = numpy.asarray(hei_interf)[0] + #nhei_interf + if (nhei_interf == None): + nhei_interf = 5 + if (nhei_interf < 1): + nhei_interf = 1 + if (nhei_interf > count_hei): + nhei_interf = count_hei + if (offhei_interf == None): + offhei_interf = 0 + + ind_hei = range(num_hei) +# mask_prof = numpy.asarray(range(num_prof - 2)) + 1 +# mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1 + mask_prof = numpy.asarray(range(num_prof)) + num_mask_prof = mask_prof.size + comp_mask_prof = [0, num_prof/2] + + + #noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal + if (jnoise.size < num_channel or numpy.isnan(jnoise).any()): + jnoise = numpy.nan + noise_exist = jnoise[0] < numpy.Inf + + #Subrutina de Remocion de la Interferencia + for ich in range(num_channel): + #Se ordena los espectros segun su potencia (menor a mayor) + power = jspectra[ich,mask_prof,:] + power = power[:,hei_interf] + power = power.sum(axis = 0) + psort = power.ravel().argsort() + + #Se estima la interferencia promedio en los Espectros de Potencia empleando + junkspc_interf = jspectra[ich,:,hei_interf[psort[range(offhei_interf, nhei_interf + offhei_interf)]]] + + if noise_exist: + # tmp_noise = jnoise[ich] / num_prof + tmp_noise = jnoise[ich] + junkspc_interf = junkspc_interf - tmp_noise + #junkspc_interf[:,comp_mask_prof] = 0 + + jspc_interf = junkspc_interf.sum(axis = 0) / nhei_interf + jspc_interf = jspc_interf.transpose() + #Calculando el espectro de interferencia promedio + noiseid = numpy.where(jspc_interf <= tmp_noise/ numpy.sqrt(num_incoh)) + noiseid = noiseid[0] + cnoiseid = noiseid.size + interfid = numpy.where(jspc_interf > tmp_noise/ numpy.sqrt(num_incoh)) + interfid = interfid[0] + cinterfid = interfid.size + + if (cnoiseid > 0): jspc_interf[noiseid] = 0 + + #Expandiendo los perfiles a limpiar + if (cinterfid > 0): + new_interfid = (numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof)%num_prof + new_interfid = numpy.asarray(new_interfid) + new_interfid = {x for x in new_interfid} + new_interfid = numpy.array(list(new_interfid)) + new_cinterfid = new_interfid.size + else: new_cinterfid = 0 + + for ip in range(new_cinterfid): + ind = junkspc_interf[:,new_interfid[ip]].ravel().argsort() + jspc_interf[new_interfid[ip]] = junkspc_interf[ind[nhei_interf/2],new_interfid[ip]] + + + jspectra[ich,:,ind_hei] = jspectra[ich,:,ind_hei] - jspc_interf #Corregir indices + + #Removiendo la interferencia del punto de mayor interferencia + ListAux = jspc_interf[mask_prof].tolist() + maxid = ListAux.index(max(ListAux)) + + + if cinterfid > 0: + for ip in range(cinterfid*(interf == 2) - 1): + ind = (jspectra[ich,interfid[ip],:] < tmp_noise*(1 + 1/numpy.sqrt(num_incoh))).nonzero() + cind = len(ind) + + if (cind > 0): + jspectra[ich,interfid[ip],ind] = tmp_noise*(1 + (numpy.random.uniform(cind) - 0.5)/numpy.sqrt(num_incoh)) + + ind = numpy.array([-2,-1,1,2]) + xx = numpy.zeros([4,4]) + + for id1 in range(4): + xx[:,id1] = ind[id1]**numpy.asarray(range(4)) + + xx_inv = numpy.linalg.inv(xx) + xx = xx_inv[:,0] + ind = (ind + maxid + num_mask_prof)%num_mask_prof + yy = jspectra[ich,mask_prof[ind],:] + jspectra[ich,mask_prof[maxid],:] = numpy.dot(yy.transpose(),xx) + + + indAux = (jspectra[ich,:,:] < tmp_noise*(1-1/numpy.sqrt(num_incoh))).nonzero() + jspectra[ich,indAux[0],indAux[1]] = tmp_noise * (1 - 1/numpy.sqrt(num_incoh)) + + #Remocion de Interferencia en el Cross Spectra + if jcspectra is None: return jspectra, jcspectra + num_pairs = jcspectra.size/(num_prof*num_hei) + jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei) + + for ip in range(num_pairs): + + #------------------------------------------- + + cspower = numpy.abs(jcspectra[ip,mask_prof,:]) + cspower = cspower[:,hei_interf] + cspower = cspower.sum(axis = 0) + + cspsort = cspower.ravel().argsort() + junkcspc_interf = jcspectra[ip,:,hei_interf[cspsort[range(offhei_interf, nhei_interf + offhei_interf)]]] + junkcspc_interf = junkcspc_interf.transpose() + jcspc_interf = junkcspc_interf.sum(axis = 1)/nhei_interf + + ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort() + + median_real = numpy.median(numpy.real(junkcspc_interf[mask_prof[ind[range(3*num_prof/4)]],:])) + median_imag = numpy.median(numpy.imag(junkcspc_interf[mask_prof[ind[range(3*num_prof/4)]],:])) + junkcspc_interf[comp_mask_prof,:] = numpy.complex(median_real, median_imag) + + for iprof in range(num_prof): + ind = numpy.abs(junkcspc_interf[iprof,:]).ravel().argsort() + jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf/2]] + + #Removiendo la Interferencia + jcspectra[ip,:,ind_hei] = jcspectra[ip,:,ind_hei] - jcspc_interf + + ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist() + maxid = ListAux.index(max(ListAux)) + + ind = numpy.array([-2,-1,1,2]) + xx = numpy.zeros([4,4]) + + for id1 in range(4): + xx[:,id1] = ind[id1]**numpy.asarray(range(4)) + + xx_inv = numpy.linalg.inv(xx) + xx = xx_inv[:,0] + + ind = (ind + maxid + num_mask_prof)%num_mask_prof + yy = jcspectra[ip,mask_prof[ind],:] + jcspectra[ip,mask_prof[maxid],:] = numpy.dot(yy.transpose(),xx) + + #Guardar Resultados + self.dataOut.data_spc = jspectra + self.dataOut.data_cspc = jcspectra + + return 1 + + def setRadarFrequency(self, frequency=None): + + if frequency != None: + self.dataOut.frequency = frequency + + return 1 + + def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None): + #validacion de rango + if minHei == None: + minHei = self.dataOut.heightList[0] + + if maxHei == None: + maxHei = self.dataOut.heightList[-1] + + if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei): + print 'minHei: %.2f is out of the heights range'%(minHei) + print 'minHei is setting to %.2f'%(self.dataOut.heightList[0]) + minHei = self.dataOut.heightList[0] + + if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei): + print 'maxHei: %.2f is out of the heights range'%(maxHei) + print 'maxHei is setting to %.2f'%(self.dataOut.heightList[-1]) + maxHei = self.dataOut.heightList[-1] + + # validacion de velocidades + velrange = self.dataOut.getVelRange(1) + + if minVel == None: + minVel = velrange[0] + + if maxVel == None: + maxVel = velrange[-1] + + if (minVel < velrange[0]) or (minVel > maxVel): + print 'minVel: %.2f is out of the velocity range'%(minVel) + print 'minVel is setting to %.2f'%(velrange[0]) + minVel = velrange[0] + + if (maxVel > velrange[-1]) or (maxVel < minVel): + print 'maxVel: %.2f is out of the velocity range'%(maxVel) + print 'maxVel is setting to %.2f'%(velrange[-1]) + maxVel = velrange[-1] + + # seleccion de indices para rango + minIndex = 0 + maxIndex = 0 + heights = self.dataOut.heightList + + inda = numpy.where(heights >= minHei) + indb = numpy.where(heights <= maxHei) + + try: + minIndex = inda[0][0] + except: + minIndex = 0 + + try: + maxIndex = indb[0][-1] + except: + maxIndex = len(heights) + + if (minIndex < 0) or (minIndex > maxIndex): + raise ValueError, "some value in (%d,%d) is not valid" % (minIndex, maxIndex) + + if (maxIndex >= self.dataOut.nHeights): + maxIndex = self.dataOut.nHeights-1 + + # seleccion de indices para velocidades + indminvel = numpy.where(velrange >= minVel) + indmaxvel = numpy.where(velrange <= maxVel) + try: + minIndexVel = indminvel[0][0] + except: + minIndexVel = 0 + + try: + maxIndexVel = indmaxvel[0][-1] + except: + maxIndexVel = len(velrange) + + #seleccion del espectro + data_spc = self.dataOut.data_spc[:,minIndexVel:maxIndexVel+1,minIndex:maxIndex+1] + #estimacion de ruido + noise = numpy.zeros(self.dataOut.nChannels) + + for channel in range(self.dataOut.nChannels): + daux = data_spc[channel,:,:] + noise[channel] = hildebrand_sekhon(daux, self.dataOut.nIncohInt) + + self.dataOut.noise_estimation = noise.copy() + + return 1 + +class IncohInt(Operation): + + + __profIndex = 0 + __withOverapping = False + + __byTime = False + __initime = None + __lastdatatime = None + __integrationtime = None + + __buffer_spc = None + __buffer_cspc = None + __buffer_dc = None + + __dataReady = False + + __timeInterval = None + + n = None + + + + def __init__(self): + + Operation.__init__(self) +# self.isConfig = False + + def setup(self, n=None, timeInterval=None, overlapping=False): + """ + Set the parameters of the integration class. + + Inputs: + + n : Number of coherent integrations + timeInterval : Time of integration. If the parameter "n" is selected this one does not work + overlapping : + + """ + + self.__initime = None + self.__lastdatatime = 0 + + self.__buffer_spc = 0 + self.__buffer_cspc = 0 + self.__buffer_dc = 0 + + self.__profIndex = 0 + self.__dataReady = False + self.__byTime = False + + if n is None and timeInterval is None: + raise ValueError, "n or timeInterval should be specified ..." + + if n is not None: + self.n = int(n) + else: + self.__integrationtime = int(timeInterval) #if (type(timeInterval)!=integer) -> change this line + self.n = None + self.__byTime = True + + def putData(self, data_spc, data_cspc, data_dc): + + """ + Add a profile to the __buffer_spc and increase in one the __profileIndex + + """ + + self.__buffer_spc += data_spc + + if data_cspc is None: + self.__buffer_cspc = None + else: + self.__buffer_cspc += data_cspc + + if data_dc is None: + self.__buffer_dc = None + else: + self.__buffer_dc += data_dc + + self.__profIndex += 1 + + return + + def pushData(self): + """ + Return the sum of the last profiles and the profiles used in the sum. + + Affected: + + self.__profileIndex + + """ + + data_spc = self.__buffer_spc + data_cspc = self.__buffer_cspc + data_dc = self.__buffer_dc + n = self.__profIndex + + self.__buffer_spc = 0 + self.__buffer_cspc = 0 + self.__buffer_dc = 0 + self.__profIndex = 0 + + return data_spc, data_cspc, data_dc, n + + def byProfiles(self, *args): + + self.__dataReady = False + avgdata_spc = None + avgdata_cspc = None + avgdata_dc = None + + self.putData(*args) + + if self.__profIndex == self.n: + + avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData() + self.n = n + self.__dataReady = True + + return avgdata_spc, avgdata_cspc, avgdata_dc + + def byTime(self, datatime, *args): + + self.__dataReady = False + avgdata_spc = None + avgdata_cspc = None + avgdata_dc = None + + self.putData(*args) + + if (datatime - self.__initime) >= self.__integrationtime: + avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData() + self.n = n + self.__dataReady = True + + return avgdata_spc, avgdata_cspc, avgdata_dc + + def integrate(self, datatime, *args): + + if self.__profIndex == 0: + self.__initime = datatime + + if self.__byTime: + avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(datatime, *args) + else: + avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args) + + if not self.__dataReady: + return None, None, None, None + + return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc + + def run(self, dataOut, n=None, timeInterval=None, overlapping=False): + + if n==1: + return + + dataOut.flagNoData = True + + if not self.isConfig: + self.setup(n, timeInterval, overlapping) + self.isConfig = True + + avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime, + dataOut.data_spc, + dataOut.data_cspc, + dataOut.data_dc) + + if self.__dataReady: + + dataOut.data_spc = avgdata_spc + dataOut.data_cspc = avgdata_cspc + dataOut.data_dc = avgdata_dc + + dataOut.nIncohInt *= self.n + dataOut.utctime = avgdatatime + dataOut.flagNoData = False diff --git a/schainpy/model/proc/.svn/text-base/jroproc_spectra.pyc.svn-base b/schainpy/model/proc/.svn/text-base/jroproc_spectra.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..b5a66658bc7fd0347293afab1f73241b515d3beb GIT binary patch literal 23707 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 Hia-A!^wv(o literal 0 Hc$@ maxHei): + raise ValueError, "Error selecting heights: Height range (%d,%d) is not valid" % (minHei, maxHei) + + if (minHei < self.dataOut.heightList[0]): + minHei = self.dataOut.heightList[0] + + if (maxHei > self.dataOut.heightList[-1]): + maxHei = self.dataOut.heightList[-1] + + minIndex = 0 + maxIndex = 0 + heights = self.dataOut.heightList + + inda = numpy.where(heights >= minHei) + indb = numpy.where(heights <= maxHei) + + try: + minIndex = inda[0][0] + except: + minIndex = 0 + + try: + maxIndex = indb[0][-1] + except: + maxIndex = len(heights) + + self.selectHeightsByIndex(minIndex, maxIndex) + + return 1 + + def getBeaconSignal(self, tauindex = 0, channelindex = 0, hei_ref=None): + newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex]) + + if hei_ref != None: + newheis = numpy.where(self.dataOut.heightList>hei_ref) + + minIndex = min(newheis[0]) + maxIndex = max(newheis[0]) + data_spc = self.dataOut.data_spc[:,:,minIndex:maxIndex+1] + heightList = self.dataOut.heightList[minIndex:maxIndex+1] + + # determina indices + nheis = int(self.dataOut.radarControllerHeaderObj.txB/(self.dataOut.heightList[1]-self.dataOut.heightList[0])) + avg_dB = 10*numpy.log10(numpy.sum(data_spc[channelindex,:,:],axis=0)) + beacon_dB = numpy.sort(avg_dB)[-nheis:] + beacon_heiIndexList = [] + for val in avg_dB.tolist(): + if val >= beacon_dB[0]: + beacon_heiIndexList.append(avg_dB.tolist().index(val)) + + #data_spc = data_spc[:,:,beacon_heiIndexList] + data_cspc = None + if self.dataOut.data_cspc is not None: + data_cspc = self.dataOut.data_cspc[:,:,minIndex:maxIndex+1] + #data_cspc = data_cspc[:,:,beacon_heiIndexList] + + data_dc = None + if self.dataOut.data_dc is not None: + data_dc = self.dataOut.data_dc[:,minIndex:maxIndex+1] + #data_dc = data_dc[:,beacon_heiIndexList] + + self.dataOut.data_spc = data_spc + self.dataOut.data_cspc = data_cspc + self.dataOut.data_dc = data_dc + self.dataOut.heightList = heightList + self.dataOut.beacon_heiIndexList = beacon_heiIndexList + + return 1 + + + def selectHeightsByIndex(self, minIndex, maxIndex): + """ + Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango + minIndex <= index <= maxIndex + + Input: + minIndex : valor de indice minimo de altura a considerar + maxIndex : valor de indice maximo de altura a considerar + + Affected: + self.dataOut.data_spc + self.dataOut.data_cspc + self.dataOut.data_dc + self.dataOut.heightList + + Return: + 1 si el metodo se ejecuto con exito caso contrario devuelve 0 + """ + + if (minIndex < 0) or (minIndex > maxIndex): + raise ValueError, "Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex) + + if (maxIndex >= self.dataOut.nHeights): + maxIndex = self.dataOut.nHeights-1 + + #Spectra + data_spc = self.dataOut.data_spc[:,:,minIndex:maxIndex+1] + + data_cspc = None + if self.dataOut.data_cspc is not None: + data_cspc = self.dataOut.data_cspc[:,:,minIndex:maxIndex+1] + + data_dc = None + if self.dataOut.data_dc is not None: + data_dc = self.dataOut.data_dc[:,minIndex:maxIndex+1] + + self.dataOut.data_spc = data_spc + self.dataOut.data_cspc = data_cspc + self.dataOut.data_dc = data_dc + + self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex+1] + + return 1 + + def removeDC(self, mode = 2): + jspectra = self.dataOut.data_spc + jcspectra = self.dataOut.data_cspc + + + num_chan = jspectra.shape[0] + num_hei = jspectra.shape[2] + + if jcspectra is not None: + jcspectraExist = True + num_pairs = jcspectra.shape[0] + else: jcspectraExist = False + + freq_dc = jspectra.shape[1]/2 + ind_vel = numpy.array([-2,-1,1,2]) + freq_dc + + if ind_vel[0]<0: + ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof + + if mode == 1: + jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION + + if jcspectraExist: + jcspectra[:,freq_dc,:] = (jcspectra[:,ind_vel[1],:] + jcspectra[:,ind_vel[2],:])/2 + + if mode == 2: + + vel = numpy.array([-2,-1,1,2]) + xx = numpy.zeros([4,4]) + + for fil in range(4): + xx[fil,:] = vel[fil]**numpy.asarray(range(4)) + + xx_inv = numpy.linalg.inv(xx) + xx_aux = xx_inv[0,:] + + for ich in range(num_chan): + yy = jspectra[ich,ind_vel,:] + jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy) + + junkid = jspectra[ich,freq_dc,:]<=0 + cjunkid = sum(junkid) + + if cjunkid.any(): + jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2 + + if jcspectraExist: + for ip in range(num_pairs): + yy = jcspectra[ip,ind_vel,:] + jcspectra[ip,freq_dc,:] = numpy.dot(xx_aux,yy) + + + self.dataOut.data_spc = jspectra + self.dataOut.data_cspc = jcspectra + + return 1 + + def removeInterference(self, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None): + + jspectra = self.dataOut.data_spc + jcspectra = self.dataOut.data_cspc + jnoise = self.dataOut.getNoise() + num_incoh = self.dataOut.nIncohInt + + num_channel = jspectra.shape[0] + num_prof = jspectra.shape[1] + num_hei = jspectra.shape[2] + + #hei_interf + if hei_interf is None: + count_hei = num_hei/2 #Como es entero no importa + hei_interf = numpy.asmatrix(range(count_hei)) + num_hei - count_hei + hei_interf = numpy.asarray(hei_interf)[0] + #nhei_interf + if (nhei_interf == None): + nhei_interf = 5 + if (nhei_interf < 1): + nhei_interf = 1 + if (nhei_interf > count_hei): + nhei_interf = count_hei + if (offhei_interf == None): + offhei_interf = 0 + + ind_hei = range(num_hei) +# mask_prof = numpy.asarray(range(num_prof - 2)) + 1 +# mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1 + mask_prof = numpy.asarray(range(num_prof)) + num_mask_prof = mask_prof.size + comp_mask_prof = [0, num_prof/2] + + + #noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal + if (jnoise.size < num_channel or numpy.isnan(jnoise).any()): + jnoise = numpy.nan + noise_exist = jnoise[0] < numpy.Inf + + #Subrutina de Remocion de la Interferencia + for ich in range(num_channel): + #Se ordena los espectros segun su potencia (menor a mayor) + power = jspectra[ich,mask_prof,:] + power = power[:,hei_interf] + power = power.sum(axis = 0) + psort = power.ravel().argsort() + + #Se estima la interferencia promedio en los Espectros de Potencia empleando + junkspc_interf = jspectra[ich,:,hei_interf[psort[range(offhei_interf, nhei_interf + offhei_interf)]]] + + if noise_exist: + # tmp_noise = jnoise[ich] / num_prof + tmp_noise = jnoise[ich] + junkspc_interf = junkspc_interf - tmp_noise + #junkspc_interf[:,comp_mask_prof] = 0 + + jspc_interf = junkspc_interf.sum(axis = 0) / nhei_interf + jspc_interf = jspc_interf.transpose() + #Calculando el espectro de interferencia promedio + noiseid = numpy.where(jspc_interf <= tmp_noise/ numpy.sqrt(num_incoh)) + noiseid = noiseid[0] + cnoiseid = noiseid.size + interfid = numpy.where(jspc_interf > tmp_noise/ numpy.sqrt(num_incoh)) + interfid = interfid[0] + cinterfid = interfid.size + + if (cnoiseid > 0): jspc_interf[noiseid] = 0 + + #Expandiendo los perfiles a limpiar + if (cinterfid > 0): + new_interfid = (numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof)%num_prof + new_interfid = numpy.asarray(new_interfid) + new_interfid = {x for x in new_interfid} + new_interfid = numpy.array(list(new_interfid)) + new_cinterfid = new_interfid.size + else: new_cinterfid = 0 + + for ip in range(new_cinterfid): + ind = junkspc_interf[:,new_interfid[ip]].ravel().argsort() + jspc_interf[new_interfid[ip]] = junkspc_interf[ind[nhei_interf/2],new_interfid[ip]] + + + jspectra[ich,:,ind_hei] = jspectra[ich,:,ind_hei] - jspc_interf #Corregir indices + + #Removiendo la interferencia del punto de mayor interferencia + ListAux = jspc_interf[mask_prof].tolist() + maxid = ListAux.index(max(ListAux)) + + + if cinterfid > 0: + for ip in range(cinterfid*(interf == 2) - 1): + ind = (jspectra[ich,interfid[ip],:] < tmp_noise*(1 + 1/numpy.sqrt(num_incoh))).nonzero() + cind = len(ind) + + if (cind > 0): + jspectra[ich,interfid[ip],ind] = tmp_noise*(1 + (numpy.random.uniform(cind) - 0.5)/numpy.sqrt(num_incoh)) + + ind = numpy.array([-2,-1,1,2]) + xx = numpy.zeros([4,4]) + + for id1 in range(4): + xx[:,id1] = ind[id1]**numpy.asarray(range(4)) + + xx_inv = numpy.linalg.inv(xx) + xx = xx_inv[:,0] + ind = (ind + maxid + num_mask_prof)%num_mask_prof + yy = jspectra[ich,mask_prof[ind],:] + jspectra[ich,mask_prof[maxid],:] = numpy.dot(yy.transpose(),xx) + + + indAux = (jspectra[ich,:,:] < tmp_noise*(1-1/numpy.sqrt(num_incoh))).nonzero() + jspectra[ich,indAux[0],indAux[1]] = tmp_noise * (1 - 1/numpy.sqrt(num_incoh)) + + #Remocion de Interferencia en el Cross Spectra + if jcspectra is None: return jspectra, jcspectra + num_pairs = jcspectra.size/(num_prof*num_hei) + jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei) + + for ip in range(num_pairs): + + #------------------------------------------- + + cspower = numpy.abs(jcspectra[ip,mask_prof,:]) + cspower = cspower[:,hei_interf] + cspower = cspower.sum(axis = 0) + + cspsort = cspower.ravel().argsort() + junkcspc_interf = jcspectra[ip,:,hei_interf[cspsort[range(offhei_interf, nhei_interf + offhei_interf)]]] + junkcspc_interf = junkcspc_interf.transpose() + jcspc_interf = junkcspc_interf.sum(axis = 1)/nhei_interf + + ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort() + + median_real = numpy.median(numpy.real(junkcspc_interf[mask_prof[ind[range(3*num_prof/4)]],:])) + median_imag = numpy.median(numpy.imag(junkcspc_interf[mask_prof[ind[range(3*num_prof/4)]],:])) + junkcspc_interf[comp_mask_prof,:] = numpy.complex(median_real, median_imag) + + for iprof in range(num_prof): + ind = numpy.abs(junkcspc_interf[iprof,:]).ravel().argsort() + jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf/2]] + + #Removiendo la Interferencia + jcspectra[ip,:,ind_hei] = jcspectra[ip,:,ind_hei] - jcspc_interf + + ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist() + maxid = ListAux.index(max(ListAux)) + + ind = numpy.array([-2,-1,1,2]) + xx = numpy.zeros([4,4]) + + for id1 in range(4): + xx[:,id1] = ind[id1]**numpy.asarray(range(4)) + + xx_inv = numpy.linalg.inv(xx) + xx = xx_inv[:,0] + + ind = (ind + maxid + num_mask_prof)%num_mask_prof + yy = jcspectra[ip,mask_prof[ind],:] + jcspectra[ip,mask_prof[maxid],:] = numpy.dot(yy.transpose(),xx) + + #Guardar Resultados + self.dataOut.data_spc = jspectra + self.dataOut.data_cspc = jcspectra + + return 1 + + def setRadarFrequency(self, frequency=None): + + if frequency != None: + self.dataOut.frequency = frequency + + return 1 + + def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None): + #validacion de rango + if minHei == None: + minHei = self.dataOut.heightList[0] + + if maxHei == None: + maxHei = self.dataOut.heightList[-1] + + if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei): + print 'minHei: %.2f is out of the heights range'%(minHei) + print 'minHei is setting to %.2f'%(self.dataOut.heightList[0]) + minHei = self.dataOut.heightList[0] + + if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei): + print 'maxHei: %.2f is out of the heights range'%(maxHei) + print 'maxHei is setting to %.2f'%(self.dataOut.heightList[-1]) + maxHei = self.dataOut.heightList[-1] + + # validacion de velocidades + velrange = self.dataOut.getVelRange(1) + + if minVel == None: + minVel = velrange[0] + + if maxVel == None: + maxVel = velrange[-1] + + if (minVel < velrange[0]) or (minVel > maxVel): + print 'minVel: %.2f is out of the velocity range'%(minVel) + print 'minVel is setting to %.2f'%(velrange[0]) + minVel = velrange[0] + + if (maxVel > velrange[-1]) or (maxVel < minVel): + print 'maxVel: %.2f is out of the velocity range'%(maxVel) + print 'maxVel is setting to %.2f'%(velrange[-1]) + maxVel = velrange[-1] + + # seleccion de indices para rango + minIndex = 0 + maxIndex = 0 + heights = self.dataOut.heightList + + inda = numpy.where(heights >= minHei) + indb = numpy.where(heights <= maxHei) + + try: + minIndex = inda[0][0] + except: + minIndex = 0 + + try: + maxIndex = indb[0][-1] + except: + maxIndex = len(heights) + + if (minIndex < 0) or (minIndex > maxIndex): + raise ValueError, "some value in (%d,%d) is not valid" % (minIndex, maxIndex) + + if (maxIndex >= self.dataOut.nHeights): + maxIndex = self.dataOut.nHeights-1 + + # seleccion de indices para velocidades + indminvel = numpy.where(velrange >= minVel) + indmaxvel = numpy.where(velrange <= maxVel) + try: + minIndexVel = indminvel[0][0] + except: + minIndexVel = 0 + + try: + maxIndexVel = indmaxvel[0][-1] + except: + maxIndexVel = len(velrange) + + #seleccion del espectro + data_spc = self.dataOut.data_spc[:,minIndexVel:maxIndexVel+1,minIndex:maxIndex+1] + #estimacion de ruido + noise = numpy.zeros(self.dataOut.nChannels) + + for channel in range(self.dataOut.nChannels): + daux = data_spc[channel,:,:] + noise[channel] = hildebrand_sekhon(daux, self.dataOut.nIncohInt) + + self.dataOut.noise_estimation = noise.copy() + + return 1 \ No newline at end of file diff --git a/schainpy/model/proc/.svn/text-base/jroproc_spectra_acf.pyc.svn-base b/schainpy/model/proc/.svn/text-base/jroproc_spectra_acf.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..208f5d95dacf24e29f990360d6361a8a98128cb4 GIT binary patch literal 19807 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 UeqQqV0*f;cD&{mH)G_ma0S!+fbN~PV literal 0 Hc$@ maxHei): + raise ValueError, "Error selecting heights: Height range (%d,%d) is not valid" % (minHei, maxHei) + + if (minHei < self.dataOut.heightList[0]): + minHei = self.dataOut.heightList[0] + + if (maxHei > self.dataOut.heightList[-1]): + maxHei = self.dataOut.heightList[-1] + + minIndex = 0 + maxIndex = 0 + heights = self.dataOut.heightList + + inda = numpy.where(heights >= minHei) + indb = numpy.where(heights <= maxHei) + + try: + minIndex = inda[0][0] + except: + minIndex = 0 + + try: + maxIndex = indb[0][-1] + except: + maxIndex = len(heights) + + self.selectHeightsByIndex(minIndex, maxIndex) + + return 1 + + def getBeaconSignal(self, tauindex = 0, channelindex = 0, hei_ref=None): + newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex]) + + if hei_ref != None: + newheis = numpy.where(self.dataOut.heightList>hei_ref) + + minIndex = min(newheis[0]) + maxIndex = max(newheis[0]) + data_spc = self.dataOut.data_spc[:,:,minIndex:maxIndex+1] + heightList = self.dataOut.heightList[minIndex:maxIndex+1] + + # determina indices + nheis = int(self.dataOut.radarControllerHeaderObj.txB/(self.dataOut.heightList[1]-self.dataOut.heightList[0])) + avg_dB = 10*numpy.log10(numpy.sum(data_spc[channelindex,:,:],axis=0)) + beacon_dB = numpy.sort(avg_dB)[-nheis:] + beacon_heiIndexList = [] + for val in avg_dB.tolist(): + if val >= beacon_dB[0]: + beacon_heiIndexList.append(avg_dB.tolist().index(val)) + + #data_spc = data_spc[:,:,beacon_heiIndexList] + data_cspc = None + if self.dataOut.data_cspc is not None: + data_cspc = self.dataOut.data_cspc[:,:,minIndex:maxIndex+1] + #data_cspc = data_cspc[:,:,beacon_heiIndexList] + + data_dc = None + if self.dataOut.data_dc is not None: + data_dc = self.dataOut.data_dc[:,minIndex:maxIndex+1] + #data_dc = data_dc[:,beacon_heiIndexList] + + self.dataOut.data_spc = data_spc + self.dataOut.data_cspc = data_cspc + self.dataOut.data_dc = data_dc + self.dataOut.heightList = heightList + self.dataOut.beacon_heiIndexList = beacon_heiIndexList + + return 1 + + + def selectHeightsByIndex(self, minIndex, maxIndex): + """ + Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango + minIndex <= index <= maxIndex + + Input: + minIndex : valor de indice minimo de altura a considerar + maxIndex : valor de indice maximo de altura a considerar + + Affected: + self.dataOut.data_spc + self.dataOut.data_cspc + self.dataOut.data_dc + self.dataOut.heightList + + Return: + 1 si el metodo se ejecuto con exito caso contrario devuelve 0 + """ + + if (minIndex < 0) or (minIndex > maxIndex): + raise ValueError, "Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex) + + if (maxIndex >= self.dataOut.nHeights): + maxIndex = self.dataOut.nHeights-1 + + #Spectra + data_spc = self.dataOut.data_spc[:,:,minIndex:maxIndex+1] + + data_cspc = None + if self.dataOut.data_cspc is not None: + data_cspc = self.dataOut.data_cspc[:,:,minIndex:maxIndex+1] + + data_dc = None + if self.dataOut.data_dc is not None: + data_dc = self.dataOut.data_dc[:,minIndex:maxIndex+1] + + self.dataOut.data_spc = data_spc + self.dataOut.data_cspc = data_cspc + self.dataOut.data_dc = data_dc + + self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex+1] + + return 1 + + def removeDC(self, mode = 2): + jspectra = self.dataOut.data_spc + jcspectra = self.dataOut.data_cspc + + + num_chan = jspectra.shape[0] + num_hei = jspectra.shape[2] + + if jcspectra is not None: + jcspectraExist = True + num_pairs = jcspectra.shape[0] + else: jcspectraExist = False + + freq_dc = jspectra.shape[1]/2 + ind_vel = numpy.array([-2,-1,1,2]) + freq_dc + + if ind_vel[0]<0: + ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof + + if mode == 1: + jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION + + if jcspectraExist: + jcspectra[:,freq_dc,:] = (jcspectra[:,ind_vel[1],:] + jcspectra[:,ind_vel[2],:])/2 + + if mode == 2: + + vel = numpy.array([-2,-1,1,2]) + xx = numpy.zeros([4,4]) + + for fil in range(4): + xx[fil,:] = vel[fil]**numpy.asarray(range(4)) + + xx_inv = numpy.linalg.inv(xx) + xx_aux = xx_inv[0,:] + + for ich in range(num_chan): + yy = jspectra[ich,ind_vel,:] + jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy) + + junkid = jspectra[ich,freq_dc,:]<=0 + cjunkid = sum(junkid) + + if cjunkid.any(): + jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2 + + if jcspectraExist: + for ip in range(num_pairs): + yy = jcspectra[ip,ind_vel,:] + jcspectra[ip,freq_dc,:] = numpy.dot(xx_aux,yy) + + + self.dataOut.data_spc = jspectra + self.dataOut.data_cspc = jcspectra + + return 1 + + def removeInterference(self, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None): + + jspectra = self.dataOut.data_spc + jcspectra = self.dataOut.data_cspc + jnoise = self.dataOut.getNoise() + num_incoh = self.dataOut.nIncohInt + + num_channel = jspectra.shape[0] + num_prof = jspectra.shape[1] + num_hei = jspectra.shape[2] + + #hei_interf + if hei_interf is None: + count_hei = num_hei/2 #Como es entero no importa + hei_interf = numpy.asmatrix(range(count_hei)) + num_hei - count_hei + hei_interf = numpy.asarray(hei_interf)[0] + #nhei_interf + if (nhei_interf == None): + nhei_interf = 5 + if (nhei_interf < 1): + nhei_interf = 1 + if (nhei_interf > count_hei): + nhei_interf = count_hei + if (offhei_interf == None): + offhei_interf = 0 + + ind_hei = range(num_hei) +# mask_prof = numpy.asarray(range(num_prof - 2)) + 1 +# mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1 + mask_prof = numpy.asarray(range(num_prof)) + num_mask_prof = mask_prof.size + comp_mask_prof = [0, num_prof/2] + + + #noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal + if (jnoise.size < num_channel or numpy.isnan(jnoise).any()): + jnoise = numpy.nan + noise_exist = jnoise[0] < numpy.Inf + + #Subrutina de Remocion de la Interferencia + for ich in range(num_channel): + #Se ordena los espectros segun su potencia (menor a mayor) + power = jspectra[ich,mask_prof,:] + power = power[:,hei_interf] + power = power.sum(axis = 0) + psort = power.ravel().argsort() + + #Se estima la interferencia promedio en los Espectros de Potencia empleando + junkspc_interf = jspectra[ich,:,hei_interf[psort[range(offhei_interf, nhei_interf + offhei_interf)]]] + + if noise_exist: + # tmp_noise = jnoise[ich] / num_prof + tmp_noise = jnoise[ich] + junkspc_interf = junkspc_interf - tmp_noise + #junkspc_interf[:,comp_mask_prof] = 0 + + jspc_interf = junkspc_interf.sum(axis = 0) / nhei_interf + jspc_interf = jspc_interf.transpose() + #Calculando el espectro de interferencia promedio + noiseid = numpy.where(jspc_interf <= tmp_noise/ numpy.sqrt(num_incoh)) + noiseid = noiseid[0] + cnoiseid = noiseid.size + interfid = numpy.where(jspc_interf > tmp_noise/ numpy.sqrt(num_incoh)) + interfid = interfid[0] + cinterfid = interfid.size + + if (cnoiseid > 0): jspc_interf[noiseid] = 0 + + #Expandiendo los perfiles a limpiar + if (cinterfid > 0): + new_interfid = (numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof)%num_prof + new_interfid = numpy.asarray(new_interfid) + new_interfid = {x for x in new_interfid} + new_interfid = numpy.array(list(new_interfid)) + new_cinterfid = new_interfid.size + else: new_cinterfid = 0 + + for ip in range(new_cinterfid): + ind = junkspc_interf[:,new_interfid[ip]].ravel().argsort() + jspc_interf[new_interfid[ip]] = junkspc_interf[ind[nhei_interf/2],new_interfid[ip]] + + + jspectra[ich,:,ind_hei] = jspectra[ich,:,ind_hei] - jspc_interf #Corregir indices + + #Removiendo la interferencia del punto de mayor interferencia + ListAux = jspc_interf[mask_prof].tolist() + maxid = ListAux.index(max(ListAux)) + + + if cinterfid > 0: + for ip in range(cinterfid*(interf == 2) - 1): + ind = (jspectra[ich,interfid[ip],:] < tmp_noise*(1 + 1/numpy.sqrt(num_incoh))).nonzero() + cind = len(ind) + + if (cind > 0): + jspectra[ich,interfid[ip],ind] = tmp_noise*(1 + (numpy.random.uniform(cind) - 0.5)/numpy.sqrt(num_incoh)) + + ind = numpy.array([-2,-1,1,2]) + xx = numpy.zeros([4,4]) + + for id1 in range(4): + xx[:,id1] = ind[id1]**numpy.asarray(range(4)) + + xx_inv = numpy.linalg.inv(xx) + xx = xx_inv[:,0] + ind = (ind + maxid + num_mask_prof)%num_mask_prof + yy = jspectra[ich,mask_prof[ind],:] + jspectra[ich,mask_prof[maxid],:] = numpy.dot(yy.transpose(),xx) + + + indAux = (jspectra[ich,:,:] < tmp_noise*(1-1/numpy.sqrt(num_incoh))).nonzero() + jspectra[ich,indAux[0],indAux[1]] = tmp_noise * (1 - 1/numpy.sqrt(num_incoh)) + + #Remocion de Interferencia en el Cross Spectra + if jcspectra is None: return jspectra, jcspectra + num_pairs = jcspectra.size/(num_prof*num_hei) + jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei) + + for ip in range(num_pairs): + + #------------------------------------------- + + cspower = numpy.abs(jcspectra[ip,mask_prof,:]) + cspower = cspower[:,hei_interf] + cspower = cspower.sum(axis = 0) + + cspsort = cspower.ravel().argsort() + junkcspc_interf = jcspectra[ip,:,hei_interf[cspsort[range(offhei_interf, nhei_interf + offhei_interf)]]] + junkcspc_interf = junkcspc_interf.transpose() + jcspc_interf = junkcspc_interf.sum(axis = 1)/nhei_interf + + ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort() + + median_real = numpy.median(numpy.real(junkcspc_interf[mask_prof[ind[range(3*num_prof/4)]],:])) + median_imag = numpy.median(numpy.imag(junkcspc_interf[mask_prof[ind[range(3*num_prof/4)]],:])) + junkcspc_interf[comp_mask_prof,:] = numpy.complex(median_real, median_imag) + + for iprof in range(num_prof): + ind = numpy.abs(junkcspc_interf[iprof,:]).ravel().argsort() + jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf/2]] + + #Removiendo la Interferencia + jcspectra[ip,:,ind_hei] = jcspectra[ip,:,ind_hei] - jcspc_interf + + ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist() + maxid = ListAux.index(max(ListAux)) + + ind = numpy.array([-2,-1,1,2]) + xx = numpy.zeros([4,4]) + + for id1 in range(4): + xx[:,id1] = ind[id1]**numpy.asarray(range(4)) + + xx_inv = numpy.linalg.inv(xx) + xx = xx_inv[:,0] + + ind = (ind + maxid + num_mask_prof)%num_mask_prof + yy = jcspectra[ip,mask_prof[ind],:] + jcspectra[ip,mask_prof[maxid],:] = numpy.dot(yy.transpose(),xx) + + #Guardar Resultados + self.dataOut.data_spc = jspectra + self.dataOut.data_cspc = jcspectra + + return 1 + + def setRadarFrequency(self, frequency=None): + + if frequency != None: + self.dataOut.frequency = frequency + + return 1 + + def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None): + #validacion de rango + if minHei == None: + minHei = self.dataOut.heightList[0] + + if maxHei == None: + maxHei = self.dataOut.heightList[-1] + + if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei): + print 'minHei: %.2f is out of the heights range'%(minHei) + print 'minHei is setting to %.2f'%(self.dataOut.heightList[0]) + minHei = self.dataOut.heightList[0] + + if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei): + print 'maxHei: %.2f is out of the heights range'%(maxHei) + print 'maxHei is setting to %.2f'%(self.dataOut.heightList[-1]) + maxHei = self.dataOut.heightList[-1] + + # validacion de velocidades + velrange = self.dataOut.getVelRange(1) + + if minVel == None: + minVel = velrange[0] + + if maxVel == None: + maxVel = velrange[-1] + + if (minVel < velrange[0]) or (minVel > maxVel): + print 'minVel: %.2f is out of the velocity range'%(minVel) + print 'minVel is setting to %.2f'%(velrange[0]) + minVel = velrange[0] + + if (maxVel > velrange[-1]) or (maxVel < minVel): + print 'maxVel: %.2f is out of the velocity range'%(maxVel) + print 'maxVel is setting to %.2f'%(velrange[-1]) + maxVel = velrange[-1] + + # seleccion de indices para rango + minIndex = 0 + maxIndex = 0 + heights = self.dataOut.heightList + + inda = numpy.where(heights >= minHei) + indb = numpy.where(heights <= maxHei) + + try: + minIndex = inda[0][0] + except: + minIndex = 0 + + try: + maxIndex = indb[0][-1] + except: + maxIndex = len(heights) + + if (minIndex < 0) or (minIndex > maxIndex): + raise ValueError, "some value in (%d,%d) is not valid" % (minIndex, maxIndex) + + if (maxIndex >= self.dataOut.nHeights): + maxIndex = self.dataOut.nHeights-1 + + # seleccion de indices para velocidades + indminvel = numpy.where(velrange >= minVel) + indmaxvel = numpy.where(velrange <= maxVel) + try: + minIndexVel = indminvel[0][0] + except: + minIndexVel = 0 + + try: + maxIndexVel = indmaxvel[0][-1] + except: + maxIndexVel = len(velrange) + + #seleccion del espectro + data_spc = self.dataOut.data_spc[:,minIndexVel:maxIndexVel+1,minIndex:maxIndex+1] + #estimacion de ruido + noise = numpy.zeros(self.dataOut.nChannels) + + for channel in range(self.dataOut.nChannels): + daux = data_spc[channel,:,:] + noise[channel] = hildebrand_sekhon(daux, self.dataOut.nIncohInt) + + self.dataOut.noise_estimation = noise.copy() + + return 1 \ No newline at end of file diff --git a/schainpy/model/proc/.svn/text-base/jroproc_spectra_lags.pyc.svn-base b/schainpy/model/proc/.svn/text-base/jroproc_spectra_lags.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..f7f25dbc1c26fbfb707f125d3581f52cf66d3291 GIT binary patch literal 20376 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 WROa-u self.dataOut.heightList[-1]): + maxHei = self.dataOut.heightList[-1] + + minIndex = 0 + maxIndex = 0 + heights = self.dataOut.heightList + + inda = numpy.where(heights >= minHei) + indb = numpy.where(heights <= maxHei) + + try: + minIndex = inda[0][0] + except: + minIndex = 0 + + try: + maxIndex = indb[0][-1] + except: + maxIndex = len(heights) + + self.selectHeightsByIndex(minIndex, maxIndex) + + return 1 + + + def selectHeightsByIndex(self, minIndex, maxIndex): + """ + Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango + minIndex <= index <= maxIndex + + Input: + minIndex : valor de indice minimo de altura a considerar + maxIndex : valor de indice maximo de altura a considerar + + Affected: + self.dataOut.data + self.dataOut.heightList + + Return: + 1 si el metodo se ejecuto con exito caso contrario devuelve 0 + """ + + if (minIndex < 0) or (minIndex > maxIndex): + raise ValueError, "Height index range (%d,%d) is not valid" % (minIndex, maxIndex) + + if (maxIndex >= self.dataOut.nHeights): + maxIndex = self.dataOut.nHeights + + #voltage + if self.dataOut.flagDataAsBlock: + """ + Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis] + """ + data = self.dataOut.data[:,:, minIndex:maxIndex] + else: + data = self.dataOut.data[:, minIndex:maxIndex] + +# firstHeight = self.dataOut.heightList[minIndex] + + self.dataOut.data = data + self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex] + + if self.dataOut.nHeights <= 1: + raise ValueError, "selectHeights: Too few heights. Current number of heights is %d" %(self.dataOut.nHeights) + + return 1 + + + def filterByHeights(self, window): + + deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0] + + if window == None: + window = (self.dataOut.radarControllerHeaderObj.txA/self.dataOut.radarControllerHeaderObj.nBaud) / deltaHeight + + newdelta = deltaHeight * window + r = self.dataOut.nHeights % window + newheights = (self.dataOut.nHeights-r)/window + + if newheights <= 1: + raise ValueError, "filterByHeights: Too few heights. Current number of heights is %d and window is %d" %(self.dataOut.nHeights, window) + + if self.dataOut.flagDataAsBlock: + """ + Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis] + """ + buffer = self.dataOut.data[:, :, 0:self.dataOut.nHeights-r] + buffer = buffer.reshape(self.dataOut.nChannels,self.dataOut.nProfiles,self.dataOut.nHeights/window,window) + buffer = numpy.sum(buffer,3) + + else: + buffer = self.dataOut.data[:,0:self.dataOut.nHeights-r] + buffer = buffer.reshape(self.dataOut.nChannels,self.dataOut.nHeights/window,window) + buffer = numpy.sum(buffer,2) + + self.dataOut.data = buffer + self.dataOut.heightList = self.dataOut.heightList[0] + numpy.arange( newheights )*newdelta + self.dataOut.windowOfFilter = window + + def setH0(self, h0, deltaHeight = None): + + if not deltaHeight: + deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0] + + nHeights = self.dataOut.nHeights + + newHeiRange = h0 + numpy.arange(nHeights)*deltaHeight + + self.dataOut.heightList = newHeiRange + + def deFlip(self, channelList = []): + + data = self.dataOut.data.copy() + + if self.dataOut.flagDataAsBlock: + flip = self.flip + profileList = range(self.dataOut.nProfiles) + + if not channelList: + for thisProfile in profileList: + data[:,thisProfile,:] = data[:,thisProfile,:]*flip + flip *= -1.0 + else: + for thisChannel in channelList: + if thisChannel not in self.dataOut.channelList: + continue + + for thisProfile in profileList: + data[thisChannel,thisProfile,:] = data[thisChannel,thisProfile,:]*flip + flip *= -1.0 + + self.flip = flip + + else: + if not channelList: + data[:,:] = data[:,:]*self.flip + else: + for thisChannel in channelList: + if thisChannel not in self.dataOut.channelList: + continue + + data[thisChannel,:] = data[thisChannel,:]*self.flip + + self.flip *= -1. + + self.dataOut.data = data + + def setRadarFrequency(self, frequency=None): + + if frequency != None: + self.dataOut.frequency = frequency + + return 1 + + def interpolateHeights(self, topLim, botLim): + #69 al 72 para julia + #82-84 para meteoros + if len(numpy.shape(self.dataOut.data))==2: + sampInterp = (self.dataOut.data[:,botLim-1] + self.dataOut.data[:,topLim+1])/2 + sampInterp = numpy.transpose(numpy.tile(sampInterp,(topLim-botLim + 1,1))) + #self.dataOut.data[:,botLim:limSup+1] = sampInterp + self.dataOut.data[:,botLim:topLim+1] = sampInterp + else: + nHeights = self.dataOut.data.shape[2] + x = numpy.hstack((numpy.arange(botLim),numpy.arange(topLim+1,nHeights))) + y = self.dataOut.data[:,:,range(botLim)+range(topLim+1,nHeights)] + f = interpolate.interp1d(x, y, axis = 2) + xnew = numpy.arange(botLim,topLim+1) + ynew = f(xnew) + + self.dataOut.data[:,:,botLim:topLim+1] = ynew + +# import collections + +class CohInt(Operation): + + isConfig = False + + __profIndex = 0 + __withOverapping = False + + __byTime = False + __initime = None + __lastdatatime = None + __integrationtime = None + + __buffer = None + + __dataReady = False + + n = None + + + def __init__(self): + + Operation.__init__(self) + +# self.isConfig = False + + def setup(self, n=None, timeInterval=None, overlapping=False, byblock=False): + """ + Set the parameters of the integration class. + + Inputs: + + n : Number of coherent integrations + timeInterval : Time of integration. If the parameter "n" is selected this one does not work + overlapping : + + """ + + self.__initime = None + self.__lastdatatime = 0 + self.__buffer = None + self.__dataReady = False + self.byblock = byblock + + if n == None and timeInterval == None: + raise ValueError, "n or timeInterval should be specified ..." + + if n != None: + self.n = n + self.__byTime = False + else: + self.__integrationtime = timeInterval #* 60. #if (type(timeInterval)!=integer) -> change this line + self.n = 9999 + self.__byTime = True + + if overlapping: + self.__withOverapping = True + self.__buffer = None + else: + self.__withOverapping = False + self.__buffer = 0 + + self.__profIndex = 0 + + def putData(self, data): + + """ + Add a profile to the __buffer and increase in one the __profileIndex + + """ + + if not self.__withOverapping: + self.__buffer += data.copy() + self.__profIndex += 1 + return + + #Overlapping data + nChannels, nHeis = data.shape + data = numpy.reshape(data, (1, nChannels, nHeis)) + + #If the buffer is empty then it takes the data value + if self.__buffer is None: + self.__buffer = data + self.__profIndex += 1 + return + + #If the buffer length is lower than n then stakcing the data value + if self.__profIndex < self.n: + self.__buffer = numpy.vstack((self.__buffer, data)) + self.__profIndex += 1 + return + + #If the buffer length is equal to n then replacing the last buffer value with the data value + self.__buffer = numpy.roll(self.__buffer, -1, axis=0) + self.__buffer[self.n-1] = data + self.__profIndex = self.n + return + + + def pushData(self): + """ + Return the sum of the last profiles and the profiles used in the sum. + + Affected: + + self.__profileIndex + + """ + + if not self.__withOverapping: + data = self.__buffer + n = self.__profIndex + + self.__buffer = 0 + self.__profIndex = 0 + + return data, n + + #Integration with Overlapping + data = numpy.sum(self.__buffer, axis=0) + n = self.__profIndex + + return data, n + + def byProfiles(self, data): + + self.__dataReady = False + avgdata = None +# n = None + + self.putData(data) + + if self.__profIndex == self.n: + + avgdata, n = self.pushData() + self.__dataReady = True + + return avgdata + + def byTime(self, data, datatime): + + self.__dataReady = False + avgdata = None + n = None + + self.putData(data) + + if (datatime - self.__initime) >= self.__integrationtime: + avgdata, n = self.pushData() + self.n = n + self.__dataReady = True + + return avgdata + + def integrate(self, data, datatime=None): + + if self.__initime == None: + self.__initime = datatime + + if self.__byTime: + avgdata = self.byTime(data, datatime) + else: + avgdata = self.byProfiles(data) + + + self.__lastdatatime = datatime + + if avgdata is None: + return None, None + + avgdatatime = self.__initime + + deltatime = datatime -self.__lastdatatime + + if not self.__withOverapping: + self.__initime = datatime + else: + self.__initime += deltatime + + return avgdata, avgdatatime + + def integrateByBlock(self, dataOut): + + times = int(dataOut.data.shape[1]/self.n) + avgdata = numpy.zeros((dataOut.nChannels, times, dataOut.nHeights), dtype=numpy.complex) + + id_min = 0 + id_max = self.n + + for i in range(times): + junk = dataOut.data[:,id_min:id_max,:] + avgdata[:,i,:] = junk.sum(axis=1) + id_min += self.n + id_max += self.n + + timeInterval = dataOut.ippSeconds*self.n + avgdatatime = (times - 1) * timeInterval + dataOut.utctime + self.__dataReady = True + return avgdata, avgdatatime + + def run(self, dataOut, **kwargs): + + if not self.isConfig: + self.setup(**kwargs) + self.isConfig = True + + if dataOut.flagDataAsBlock: + """ + Si la data es leida por bloques, dimension = [nChannels, nProfiles, nHeis] + """ + avgdata, avgdatatime = self.integrateByBlock(dataOut) + dataOut.nProfiles /= self.n + else: + avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime) + +# dataOut.timeInterval *= n + dataOut.flagNoData = True + + if self.__dataReady: + dataOut.data = avgdata + dataOut.nCohInt *= self.n + dataOut.utctime = avgdatatime +# dataOut.timeInterval = dataOut.ippSeconds * dataOut.nCohInt + dataOut.flagNoData = False + +class Decoder(Operation): + + isConfig = False + __profIndex = 0 + + code = None + + nCode = None + nBaud = None + + + def __init__(self): + + Operation.__init__(self) + + self.times = None + self.osamp = None +# self.__setValues = False + self.isConfig = False + + def setup(self, code, osamp, dataOut): + + self.__profIndex = 0 + + self.code = code + + self.nCode = len(code) + self.nBaud = len(code[0]) + + if (osamp != None) and (osamp >1): + self.osamp = osamp + self.code = numpy.repeat(code, repeats=self.osamp, axis=1) + self.nBaud = self.nBaud*self.osamp + + self.__nChannels = dataOut.nChannels + self.__nProfiles = dataOut.nProfiles + self.__nHeis = dataOut.nHeights + + if self.__nHeis < self.nBaud: + raise ValueError, 'Number of heights (%d) should be greater than number of bauds (%d)' %(self.__nHeis, self.nBaud) + + #Frequency + __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=numpy.complex) + + __codeBuffer[:,0:self.nBaud] = self.code + + self.fft_code = numpy.conj(numpy.fft.fft(__codeBuffer, axis=1)) + + if dataOut.flagDataAsBlock: + + self.ndatadec = self.__nHeis #- self.nBaud + 1 + + self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=numpy.complex) + + else: + + #Time + self.ndatadec = self.__nHeis #- self.nBaud + 1 + + self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=numpy.complex) + + def __convolutionInFreq(self, data): + + fft_code = self.fft_code[self.__profIndex].reshape(1,-1) + + fft_data = numpy.fft.fft(data, axis=1) + + conv = fft_data*fft_code + + data = numpy.fft.ifft(conv,axis=1) + + return data + + def __convolutionInFreqOpt(self, data): + + raise NotImplementedError + + def __convolutionInTime(self, data): + + code = self.code[self.__profIndex] + + for i in range(self.__nChannels): + self.datadecTime[i,:] = numpy.correlate(data[i,:], code, mode='full')[self.nBaud-1:] + + return self.datadecTime + + def __convolutionByBlockInTime(self, data): + + repetitions = self.__nProfiles / self.nCode + + junk = numpy.lib.stride_tricks.as_strided(self.code, (repetitions, self.code.size), (0, self.code.itemsize)) + junk = junk.flatten() + code_block = numpy.reshape(junk, (self.nCode*repetitions, self.nBaud)) + + for i in range(self.__nChannels): + for j in range(self.__nProfiles): + self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:] + + return self.datadecTime + + def __convolutionByBlockInFreq(self, data): + + raise NotImplementedError, "Decoder by frequency fro Blocks not implemented" + + + fft_code = self.fft_code[self.__profIndex].reshape(1,-1) + + fft_data = numpy.fft.fft(data, axis=2) + + conv = fft_data*fft_code + + data = numpy.fft.ifft(conv,axis=2) + + return data + + def run(self, dataOut, code=None, nCode=None, nBaud=None, mode = 0, osamp=None, times=None): + + if dataOut.flagDecodeData: + print "This data is already decoded, recoding again ..." + + if not self.isConfig: + + if code is None: + if dataOut.code is None: + raise ValueError, "Code could not be read from %s instance. Enter a value in Code parameter" %dataOut.type + + code = dataOut.code + else: + code = numpy.array(code).reshape(nCode,nBaud) + + self.setup(code, osamp, dataOut) + + self.isConfig = True + + if mode == 3: + sys.stderr.write("Decoder Warning: mode=%d is not valid, using mode=0\n" %mode) + + if times != None: + sys.stderr.write("Decoder Warning: Argument 'times' in not used anymore\n") + + if self.code is None: + print "Fail decoding: Code is not defined." + return + + datadec = None + if mode == 3: + mode = 0 + + if dataOut.flagDataAsBlock: + """ + Decoding when data have been read as block, + """ + + if mode == 0: + datadec = self.__convolutionByBlockInTime(dataOut.data) + if mode == 1: + datadec = self.__convolutionByBlockInFreq(dataOut.data) + else: + """ + Decoding when data have been read profile by profile + """ + if mode == 0: + datadec = self.__convolutionInTime(dataOut.data) + + if mode == 1: + datadec = self.__convolutionInFreq(dataOut.data) + + if mode == 2: + datadec = self.__convolutionInFreqOpt(dataOut.data) + + if datadec is None: + raise ValueError, "Codification mode selected is not valid: mode=%d. Try selecting 0 or 1" %mode + + dataOut.code = self.code + dataOut.nCode = self.nCode + dataOut.nBaud = self.nBaud + + dataOut.data = datadec + + dataOut.heightList = dataOut.heightList[0:datadec.shape[-1]] + + dataOut.flagDecodeData = True #asumo q la data esta decodificada + + if self.__profIndex == self.nCode-1: + self.__profIndex = 0 + return 1 + + self.__profIndex += 1 + + return 1 +# dataOut.flagDeflipData = True #asumo q la data no esta sin flip + + +class ProfileConcat(Operation): + + isConfig = False + buffer = None + + def __init__(self): + + Operation.__init__(self) + self.profileIndex = 0 + + def reset(self): + self.buffer = numpy.zeros_like(self.buffer) + self.start_index = 0 + self.times = 1 + + def setup(self, data, m, n=1): + self.buffer = numpy.zeros((data.shape[0],data.shape[1]*m),dtype=type(data[0,0])) + self.nHeights = data.shape[1]#.nHeights + self.start_index = 0 + self.times = 1 + + def concat(self, data): + + self.buffer[:,self.start_index:self.nHeights*self.times] = data.copy() + self.start_index = self.start_index + self.nHeights + + def run(self, dataOut, m): + + dataOut.flagNoData = True + + if not self.isConfig: + self.setup(dataOut.data, m, 1) + self.isConfig = True + + if dataOut.flagDataAsBlock: + raise ValueError, "ProfileConcat can only be used when voltage have been read profile by profile, getBlock = False" + + else: + self.concat(dataOut.data) + self.times += 1 + if self.times > m: + dataOut.data = self.buffer + self.reset() + dataOut.flagNoData = False + # se deben actualizar mas propiedades del header y del objeto dataOut, por ejemplo, las alturas + deltaHeight = dataOut.heightList[1] - dataOut.heightList[0] + xf = dataOut.heightList[0] + dataOut.nHeights * deltaHeight * m + dataOut.heightList = numpy.arange(dataOut.heightList[0], xf, deltaHeight) + dataOut.ippSeconds *= m + +class ProfileSelector(Operation): + + profileIndex = None + # Tamanho total de los perfiles + nProfiles = None + + def __init__(self): + + Operation.__init__(self) + self.profileIndex = 0 + + def incProfileIndex(self): + + self.profileIndex += 1 + + if self.profileIndex >= self.nProfiles: + self.profileIndex = 0 + + def isThisProfileInRange(self, profileIndex, minIndex, maxIndex): + + if profileIndex < minIndex: + return False + + if profileIndex > maxIndex: + return False + + return True + + def isThisProfileInList(self, profileIndex, profileList): + + if profileIndex not in profileList: + return False + + return True + + def run(self, dataOut, profileList=None, profileRangeList=None, beam=None, byblock=False, rangeList = None, nProfiles=None): + + """ + ProfileSelector: + + Inputs: + profileList : Index of profiles selected. Example: profileList = (0,1,2,7,8) + + profileRangeList : Minimum and maximum profile indexes. Example: profileRangeList = (4, 30) + + rangeList : List of profile ranges. Example: rangeList = ((4, 30), (32, 64), (128, 256)) + + """ + + if rangeList is not None: + if type(rangeList[0]) not in (tuple, list): + rangeList = [rangeList] + + dataOut.flagNoData = True + + if dataOut.flagDataAsBlock: + """ + data dimension = [nChannels, nProfiles, nHeis] + """ + if profileList != None: + dataOut.data = dataOut.data[:,profileList,:] + + if profileRangeList != None: + minIndex = profileRangeList[0] + maxIndex = profileRangeList[1] + profileList = range(minIndex, maxIndex+1) + + dataOut.data = dataOut.data[:,minIndex:maxIndex+1,:] + + if rangeList != None: + + profileList = [] + + for thisRange in rangeList: + minIndex = thisRange[0] + maxIndex = thisRange[1] + + profileList.extend(range(minIndex, maxIndex+1)) + + dataOut.data = dataOut.data[:,profileList,:] + + dataOut.nProfiles = len(profileList) + dataOut.profileIndex = dataOut.nProfiles - 1 + dataOut.flagNoData = False + + return True + + """ + data dimension = [nChannels, nHeis] + """ + + if profileList != None: + + if self.isThisProfileInList(dataOut.profileIndex, profileList): + + self.nProfiles = len(profileList) + dataOut.nProfiles = self.nProfiles + dataOut.profileIndex = self.profileIndex + dataOut.flagNoData = False + + self.incProfileIndex() + return True + + if profileRangeList != None: + + minIndex = profileRangeList[0] + maxIndex = profileRangeList[1] + + if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex): + + self.nProfiles = maxIndex - minIndex + 1 + dataOut.nProfiles = self.nProfiles + dataOut.profileIndex = self.profileIndex + dataOut.flagNoData = False + + self.incProfileIndex() + return True + + if rangeList != None: + + nProfiles = 0 + + for thisRange in rangeList: + minIndex = thisRange[0] + maxIndex = thisRange[1] + + nProfiles += maxIndex - minIndex + 1 + + for thisRange in rangeList: + + minIndex = thisRange[0] + maxIndex = thisRange[1] + + if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex): + + self.nProfiles = nProfiles + dataOut.nProfiles = self.nProfiles + dataOut.profileIndex = self.profileIndex + dataOut.flagNoData = False + + self.incProfileIndex() + + break + + return True + + + if beam != None: #beam is only for AMISR data + if self.isThisProfileInList(dataOut.profileIndex, dataOut.beamRangeDict[beam]): + dataOut.flagNoData = False + dataOut.profileIndex = self.profileIndex + + self.incProfileIndex() + + return True + + raise ValueError, "ProfileSelector needs profileList, profileRangeList or rangeList parameter" + + return False + +class Reshaper(Operation): + + def __init__(self): + + Operation.__init__(self) + + self.__buffer = None + self.__nitems = 0 + + def __appendProfile(self, dataOut, nTxs): + + if self.__buffer is None: + shape = (dataOut.nChannels, int(dataOut.nHeights/nTxs) ) + self.__buffer = numpy.empty(shape, dtype = dataOut.data.dtype) + + ini = dataOut.nHeights * self.__nitems + end = ini + dataOut.nHeights + + self.__buffer[:, ini:end] = dataOut.data + + self.__nitems += 1 + + return int(self.__nitems*nTxs) + + def __getBuffer(self): + + if self.__nitems == int(1./self.__nTxs): + + self.__nitems = 0 + + return self.__buffer.copy() + + return None + + def __checkInputs(self, dataOut, shape, nTxs): + + if shape is None and nTxs is None: + raise ValueError, "Reshaper: shape of factor should be defined" + + if nTxs: + if nTxs < 0: + raise ValueError, "nTxs should be greater than 0" + + if nTxs < 1 and dataOut.nProfiles % (1./nTxs) != 0: + raise ValueError, "nProfiles= %d is not divisibled by (1./nTxs) = %f" %(dataOut.nProfiles, (1./nTxs)) + + shape = [dataOut.nChannels, dataOut.nProfiles*nTxs, dataOut.nHeights/nTxs] + + return shape, nTxs + + if len(shape) != 2 and len(shape) != 3: + raise ValueError, "shape dimension should be equal to 2 or 3. shape = (nProfiles, nHeis) or (nChannels, nProfiles, nHeis). Actually shape = (%d, %d, %d)" %(dataOut.nChannels, dataOut.nProfiles, dataOut.nHeights) + + if len(shape) == 2: + shape_tuple = [dataOut.nChannels] + shape_tuple.extend(shape) + else: + shape_tuple = list(shape) + + nTxs = 1.0*shape_tuple[1]/dataOut.nProfiles + + return shape_tuple, nTxs + + def run(self, dataOut, shape=None, nTxs=None): + + shape_tuple, self.__nTxs = self.__checkInputs(dataOut, shape, nTxs) + + dataOut.flagNoData = True + profileIndex = None + + if dataOut.flagDataAsBlock: + + dataOut.data = numpy.reshape(dataOut.data, shape_tuple) + dataOut.flagNoData = False + + profileIndex = int(dataOut.nProfiles*self.__nTxs) - 1 + + else: + + if self.__nTxs < 1: + + self.__appendProfile(dataOut, self.__nTxs) + new_data = self.__getBuffer() + + if new_data is not None: + dataOut.data = new_data + dataOut.flagNoData = False + + profileIndex = dataOut.profileIndex*nTxs + + else: + raise ValueError, "nTxs should be greater than 0 and lower than 1, or use VoltageReader(..., getblock=True)" + + deltaHeight = dataOut.heightList[1] - dataOut.heightList[0] + + dataOut.heightList = numpy.arange(dataOut.nHeights/self.__nTxs) * deltaHeight + dataOut.heightList[0] + + dataOut.nProfiles = int(dataOut.nProfiles*self.__nTxs) + + dataOut.profileIndex = profileIndex + + dataOut.ippSeconds /= self.__nTxs + +class SplitProfiles(Operation): + + def __init__(self): + + Operation.__init__(self) + + def run(self, dataOut, n): + + dataOut.flagNoData = True + profileIndex = None + + if dataOut.flagDataAsBlock: + + #nchannels, nprofiles, nsamples + shape = dataOut.data.shape + + if shape[2] % n != 0: + raise ValueError, "Could not split the data, n=%d has to be multiple of %d" %(n, shape[2]) + + new_shape = shape[0], shape[1]*n, shape[2]/n + + dataOut.data = numpy.reshape(dataOut.data, new_shape) + dataOut.flagNoData = False + + profileIndex = int(dataOut.nProfiles/n) - 1 + + else: + + raise ValueError, "Could not split the data when is read Profile by Profile. Use VoltageReader(..., getblock=True)" + + deltaHeight = dataOut.heightList[1] - dataOut.heightList[0] + + dataOut.heightList = numpy.arange(dataOut.nHeights/n) * deltaHeight + dataOut.heightList[0] + + dataOut.nProfiles = int(dataOut.nProfiles*n) + + dataOut.profileIndex = profileIndex + + dataOut.ippSeconds /= n + +class CombineProfiles(Operation): + + def __init__(self): + + Operation.__init__(self) + + self.__remData = None + self.__profileIndex = 0 + + def run(self, dataOut, n): + + dataOut.flagNoData = True + profileIndex = None + + if dataOut.flagDataAsBlock: + + #nchannels, nprofiles, nsamples + shape = dataOut.data.shape + new_shape = shape[0], shape[1]/n, shape[2]*n + + if shape[1] % n != 0: + raise ValueError, "Could not split the data, n=%d has to be multiple of %d" %(n, shape[1]) + + dataOut.data = numpy.reshape(dataOut.data, new_shape) + dataOut.flagNoData = False + + profileIndex = int(dataOut.nProfiles*n) - 1 + + else: + + #nchannels, nsamples + if self.__remData is None: + newData = dataOut.data + else: + newData = numpy.concatenate((self.__remData, dataOut.data), axis=1) + + self.__profileIndex += 1 + + if self.__profileIndex < n: + self.__remData = newData + #continue + return + + self.__profileIndex = 0 + self.__remData = None + + dataOut.data = newData + dataOut.flagNoData = False + + profileIndex = dataOut.profileIndex/n + + + deltaHeight = dataOut.heightList[1] - dataOut.heightList[0] + + dataOut.heightList = numpy.arange(dataOut.nHeights*n) * deltaHeight + dataOut.heightList[0] + + dataOut.nProfiles = int(dataOut.nProfiles/n) + + dataOut.profileIndex = profileIndex + + dataOut.ippSeconds *= n + +# import collections +# from scipy.stats import mode +# +# class Synchronize(Operation): +# +# isConfig = False +# __profIndex = 0 +# +# def __init__(self): +# +# Operation.__init__(self) +# # self.isConfig = False +# self.__powBuffer = None +# self.__startIndex = 0 +# self.__pulseFound = False +# +# def __findTxPulse(self, dataOut, channel=0, pulse_with = None): +# +# #Read data +# +# powerdB = dataOut.getPower(channel = channel) +# noisedB = dataOut.getNoise(channel = channel)[0] +# +# self.__powBuffer.extend(powerdB.flatten()) +# +# dataArray = numpy.array(self.__powBuffer) +# +# filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same") +# +# maxValue = numpy.nanmax(filteredPower) +# +# if maxValue < noisedB + 10: +# #No se encuentra ningun pulso de transmision +# return None +# +# maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0] +# +# if len(maxValuesIndex) < 2: +# #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX +# return None +# +# phasedMaxValuesIndex = maxValuesIndex - self.__nSamples +# +# #Seleccionar solo valores con un espaciamiento de nSamples +# pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex) +# +# if len(pulseIndex) < 2: +# #Solo se encontro un pulso de transmision con ancho mayor a 1 +# return None +# +# spacing = pulseIndex[1:] - pulseIndex[:-1] +# +# #remover senales que se distancien menos de 10 unidades o muestras +# #(No deberian existir IPP menor a 10 unidades) +# +# realIndex = numpy.where(spacing > 10 )[0] +# +# if len(realIndex) < 2: +# #Solo se encontro un pulso de transmision con ancho mayor a 1 +# return None +# +# #Eliminar pulsos anchos (deja solo la diferencia entre IPPs) +# realPulseIndex = pulseIndex[realIndex] +# +# period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0] +# +# print "IPP = %d samples" %period +# +# self.__newNSamples = dataOut.nHeights #int(period) +# self.__startIndex = int(realPulseIndex[0]) +# +# return 1 +# +# +# def setup(self, nSamples, nChannels, buffer_size = 4): +# +# self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float), +# maxlen = buffer_size*nSamples) +# +# bufferList = [] +# +# for i in range(nChannels): +# bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN, +# maxlen = buffer_size*nSamples) +# +# bufferList.append(bufferByChannel) +# +# self.__nSamples = nSamples +# self.__nChannels = nChannels +# self.__bufferList = bufferList +# +# def run(self, dataOut, channel = 0): +# +# if not self.isConfig: +# nSamples = dataOut.nHeights +# nChannels = dataOut.nChannels +# self.setup(nSamples, nChannels) +# self.isConfig = True +# +# #Append new data to internal buffer +# for thisChannel in range(self.__nChannels): +# bufferByChannel = self.__bufferList[thisChannel] +# bufferByChannel.extend(dataOut.data[thisChannel]) +# +# if self.__pulseFound: +# self.__startIndex -= self.__nSamples +# +# #Finding Tx Pulse +# if not self.__pulseFound: +# indexFound = self.__findTxPulse(dataOut, channel) +# +# if indexFound == None: +# dataOut.flagNoData = True +# return +# +# self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex) +# self.__pulseFound = True +# self.__startIndex = indexFound +# +# #If pulse was found ... +# for thisChannel in range(self.__nChannels): +# bufferByChannel = self.__bufferList[thisChannel] +# #print self.__startIndex +# x = numpy.array(bufferByChannel) +# self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples] +# +# deltaHeight = dataOut.heightList[1] - dataOut.heightList[0] +# dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight +# # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6 +# +# dataOut.data = self.__arrayBuffer +# +# self.__startIndex += self.__newNSamples +# +# return \ No newline at end of file diff --git a/schainpy/model/proc/.svn/text-base/jroproc_voltage.pyc.svn-base b/schainpy/model/proc/.svn/text-base/jroproc_voltage.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..9cd7697f6eb97170a3461a5706f0ba7b32e2ed9f GIT binary patch literal 30440 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 T;>_>N{L0MPnXk>P&Mf?2RBP#J literal 0 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 literal 0 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 JO?TyA{{!(O{S^QJ literal 0 Hc$@= limit_sec1) + t2 = numpy.where(self.dataOut.time[0, :] < limit_sec2) + time_select = [] + for val_sec in t1[0]: + if val_sec in t2[0]: + time_select.append(val_sec) + + time_select = numpy.array(time_select, dtype='int') + valid_data = valid_data + len(time_select) + + + if len(time_select) > 0: + self.f_timesec = self.dataOut.time[:, time_select] + snr = self.dataOut.data_SNR[time_select, :, :, :] + zon = self.dataOut.data_output[0][time_select, :, :] + mer = self.dataOut.data_output[1][time_select, :, :] + ver = self.dataOut.data_output[2][time_select, :, :] + + if valid_data > 0: + self.timesec1 = self.f_timesec[0, :] + self.f_height = self.dataOut.height + self.f_zon = zon + self.f_mer = mer + self.f_ver = ver + self.f_snr = snr + self.f_timedate = [] + self.f_time = [] + + for valuet in self.timesec1: + time_t = time.gmtime(valuet) + year = time_t.tm_year + month = time_t.tm_mon + day = time_t.tm_mday + hour = time_t.tm_hour + minute = time_t.tm_min + second = time_t.tm_sec + f_timedate_0 = datetime.datetime(year, month, day, hour, minute, second) + self.f_timedate.append(f_timedate_0) + + return self.f_timedate, self.f_timesec, self.f_height, self.f_zon, self.f_mer, self.f_ver, self.f_snr + + else: + self.f_timesec = None + self.f_timedate = None + self.f_height = None + self.f_zon = None + self.f_mer = None + self.f_ver = None + self.f_snr = None + print 'Invalid time' + + return self.f_timedate, self.f_height, self.f_zon, self.f_mer, self.f_ver, self.f_snr + + def SnrFilter(self, snr_val,modetofilter): + ''' + Inputs: snr_val - Threshold value + + ''' + if modetofilter!=2 and modetofilter!=1 : + raise ValueError,'Mode to filter should be "1" or "2". {} is not valid, check "Modetofilter" value.'.format(modetofilter) + m = modetofilter-1 + + print ' SNR filter [mode {}]: SNR <= {}: data_output = NA'.format(modetofilter,snr_val) + for k in range(self.dataOut.nchannels): + for r in range(self.dataOut.nranges): + if self.dataOut.data_SNR[r,k,m] <= snr_val: + self.dataOut.data_output[2][r,m] = numpy.nan + self.dataOut.data_output[1][r,m] = numpy.nan + self.dataOut.data_output[0][r,m] = numpy.nan + + + + def OutliersFilter(self,modetofilter,svalue,svalue2,method,factor,filter,npoints): + ''' + Inputs: + svalue - string to select array velocity + svalue2 - string to choose axis filtering + method - 0 for SMOOTH or 1 for MEDIAN + factor - number used to set threshold + filter - 1 for data filtering using the standard deviation criteria else 0 + npoints - number of points for mask filter + + ''' + if modetofilter!=2 and modetofilter!=1 : + raise ValueError,'Mode to filter should be "1" or "2". {} is not valid, check "Modetofilter" value.'.format(modetofilter) + + m = modetofilter-1 + + print ' Outliers Filter [mode {}]: {} {} / threshold = {}'.format(modetofilter,svalue,svalue,factor) + + npoints = 9 + novalid = 0.1 + if svalue == 'zonal': + value = self.dataOut.data_output[0] + + elif svalue == 'meridional': + value = self.dataOut.data_output[1] + + elif svalue == 'vertical': + value = self.dataOut.data_output[2] + + else: + print 'value is not defined' + return + + if svalue2 == 'inTime': + yaxis = self.dataOut.height + xaxis = numpy.array([[self.dataOut.time1],[self.dataOut.time1]]) + + elif svalue2 == 'inHeight': + yaxis = numpy.array([[self.dataOut.time1],[self.dataOut.time1]]) + xaxis = self.dataOut.height + + else: + print 'svalue2 is required, either inHeight or inTime' + return + + output_array = value + + value_temp = value[:,m] + error = numpy.zeros(len(self.dataOut.time[m,:])) + if svalue2 == 'inHeight': + value_temp = numpy.transpose(value_temp) + error = numpy.zeros(len(self.dataOut.height)) + + htemp = yaxis[m,:] + std = value_temp + for h in range(len(htemp)): + if filter: #standard deviation filtering + std[h] = numpy.std(value_temp[h],ddof = npoints) + value_temp[numpy.where(std[h] > 5),h] = numpy.nan + error[numpy.where(std[h] > 5)] = error[numpy.where(std[h] > 5)] + 1 + + + nvalues_valid = len(numpy.where(numpy.isfinite(value_temp[h]))[0]) + minvalid = novalid*len(xaxis[m,:]) + if minvalid <= npoints: + minvalid = npoints + + #only if valid values greater than the minimum required (10%) + if nvalues_valid > minvalid: + + if method == 0: + #SMOOTH + w = value_temp[h] - self.Smooth(input=value_temp[h], width=npoints, edge_truncate=1) + + + if method == 1: + #MEDIAN + w = value_temp[h] - self.Median(input=value_temp[h], width = npoints) + + dw = numpy.std(w[numpy.where(numpy.isfinite(w))],ddof = 1) + + threshold = dw*factor + value_temp[numpy.where(w > threshold),h] = numpy.nan + value_temp[numpy.where(w < -1*threshold),h] = numpy.nan + + + #At the end + if svalue2 == 'inHeight': + value_temp = numpy.transpose(value_temp) + output_array[:,m] = value_temp + + if svalue == 'zonal': + self.dataOut.data_output[0] = output_array + + elif svalue == 'meridional': + self.dataOut.data_output[1] = output_array + + elif svalue == 'vertical': + self.dataOut.data_output[2] = output_array + + return self.dataOut.data_output + + + def Median(self,input,width): + ''' + Inputs: + input - Velocity array + width - Number of points for mask filter + + ''' + + if numpy.mod(width,2) == 1: + pc = int((width - 1) / 2) + cont = 0 + output = [] + + for i in range(len(input)): + if i >= pc and i < len(input) - pc: + new2 = input[i-pc:i+pc+1] + temp = numpy.where(numpy.isfinite(new2)) + new = new2[temp] + value = numpy.median(new) + output.append(value) + + output = numpy.array(output) + output = numpy.hstack((input[0:pc],output)) + output = numpy.hstack((output,input[-pc:len(input)])) + + return output + + def Smooth(self,input,width,edge_truncate = None): + ''' + Inputs: + input - Velocity array + width - Number of points for mask filter + edge_truncate - 1 for truncate the convolution product else + + ''' + + if numpy.mod(width,2) == 0: + real_width = width + 1 + nzeros = width / 2 + else: + real_width = width + nzeros = (width - 1) / 2 + + half_width = int(real_width)/2 + length = len(input) + + gate = numpy.ones(real_width,dtype='float') + norm_of_gate = numpy.sum(gate) + + nan_process = 0 + nan_id = numpy.where(numpy.isnan(input)) + if len(nan_id[0]) > 0: + nan_process = 1 + pb = numpy.zeros(len(input)) + pb[nan_id] = 1. + input[nan_id] = 0. + + if edge_truncate == True: + output = numpy.convolve(input/norm_of_gate,gate,mode='same') + elif edge_truncate == False or edge_truncate == None: + output = numpy.convolve(input/norm_of_gate,gate,mode='valid') + output = numpy.hstack((input[0:half_width],output)) + output = numpy.hstack((output,input[len(input)-half_width:len(input)])) + + if nan_process: + pb = numpy.convolve(pb/norm_of_gate,gate,mode='valid') + pb = numpy.hstack((numpy.zeros(half_width),pb)) + pb = numpy.hstack((pb,numpy.zeros(half_width))) + output[numpy.where(pb > 0.9999)] = numpy.nan + input[nan_id] = numpy.nan + return output + + def Average(self,aver=0,nhaver=1): + ''' + Inputs: + aver - Indicates the time period over which is averaged or consensus data + nhaver - Indicates the decimation factor in heights + + ''' + nhpoints = 48 + + lat_piura = -5.17 + lat_huancayo = -12.04 + lat_porcuya = -5.8 + + if '%2.2f'%self.dataOut.lat == '%2.2f'%lat_piura: + hcm = 3. + if self.dataOut.year == 2003 : + if self.dataOut.doy >= 25 and self.dataOut.doy < 64: + nhpoints = 12 + + elif '%2.2f'%self.dataOut.lat == '%2.2f'%lat_huancayo: + hcm = 3. + if self.dataOut.year == 2003 : + if self.dataOut.doy >= 25 and self.dataOut.doy < 64: + nhpoints = 12 + + + elif '%2.2f'%self.dataOut.lat == '%2.2f'%lat_porcuya: + hcm = 5.#2 + + pdata = 0.2 + taver = [1,2,3,4,6,8,12,24] + t0 = 0 + tf = 24 + ntime =(tf-t0)/taver[aver] + ti = numpy.arange(ntime) + tf = numpy.arange(ntime) + taver[aver] + + + old_height = self.dataOut.heightList + + if nhaver > 1: + num_hei = len(self.dataOut.heightList)/nhaver/self.dataOut.nmodes + deltha = 0.05*nhaver + minhvalid = pdata*nhaver + for im in range(self.dataOut.nmodes): + new_height = numpy.arange(num_hei)*deltha + self.dataOut.height[im,0] + deltha/2. + + + data_fHeigths_List = [] + data_fZonal_List = [] + data_fMeridional_List = [] + data_fVertical_List = [] + startDTList = [] + + + for i in range(ntime): + height = old_height + + start = datetime.datetime(self.dataOut.year,self.dataOut.month,self.dataOut.day) + datetime.timedelta(hours = int(ti[i])) - datetime.timedelta(hours = 5) + stop = datetime.datetime(self.dataOut.year,self.dataOut.month,self.dataOut.day) + datetime.timedelta(hours = int(tf[i])) - datetime.timedelta(hours = 5) + + + limit_sec1 = time.mktime(start.timetuple()) + limit_sec2 = time.mktime(stop.timetuple()) + + t1 = numpy.where(self.f_timesec >= limit_sec1) + t2 = numpy.where(self.f_timesec < limit_sec2) + time_select = [] + for val_sec in t1[0]: + if val_sec in t2[0]: + time_select.append(val_sec) + + + time_select = numpy.array(time_select,dtype = 'int') + minvalid = numpy.ceil(pdata*nhpoints) + + zon_aver = numpy.zeros([self.dataOut.nranges,self.dataOut.nmodes],dtype='f4') + numpy.nan + mer_aver = numpy.zeros([self.dataOut.nranges,self.dataOut.nmodes],dtype='f4') + numpy.nan + ver_aver = numpy.zeros([self.dataOut.nranges,self.dataOut.nmodes],dtype='f4') + numpy.nan + + if nhaver > 1: + new_zon_aver = numpy.zeros([num_hei,self.dataOut.nmodes],dtype='f4') + numpy.nan + new_mer_aver = numpy.zeros([num_hei,self.dataOut.nmodes],dtype='f4') + numpy.nan + new_ver_aver = numpy.zeros([num_hei,self.dataOut.nmodes],dtype='f4') + numpy.nan + + if len(time_select) > minvalid: + time_average = self.f_timesec[time_select] + + for im in range(self.dataOut.nmodes): + + for ih in range(self.dataOut.nranges): + if numpy.sum(numpy.isfinite(self.f_zon[time_select,ih,im])) >= minvalid: + zon_aver[ih,im] = numpy.nansum(self.f_zon[time_select,ih,im]) / numpy.sum(numpy.isfinite(self.f_zon[time_select,ih,im])) + + if numpy.sum(numpy.isfinite(self.f_mer[time_select,ih,im])) >= minvalid: + mer_aver[ih,im] = numpy.nansum(self.f_mer[time_select,ih,im]) / numpy.sum(numpy.isfinite(self.f_mer[time_select,ih,im])) + + if numpy.sum(numpy.isfinite(self.f_ver[time_select,ih,im])) >= minvalid: + ver_aver[ih,im] = numpy.nansum(self.f_ver[time_select,ih,im]) / numpy.sum(numpy.isfinite(self.f_ver[time_select,ih,im])) + + if nhaver > 1: + for ih in range(num_hei): + hvalid = numpy.arange(nhaver) + nhaver*ih + + if numpy.sum(numpy.isfinite(zon_aver[hvalid,im])) >= minvalid: + new_zon_aver[ih,im] = numpy.nansum(zon_aver[hvalid,im]) / numpy.sum(numpy.isfinite(zon_aver[hvalid,im])) + + if numpy.sum(numpy.isfinite(mer_aver[hvalid,im])) >= minvalid: + new_mer_aver[ih,im] = numpy.nansum(mer_aver[hvalid,im]) / numpy.sum(numpy.isfinite(mer_aver[hvalid,im])) + + if numpy.sum(numpy.isfinite(ver_aver[hvalid,im])) >= minvalid: + new_ver_aver[ih,im] = numpy.nansum(ver_aver[hvalid,im]) / numpy.sum(numpy.isfinite(ver_aver[hvalid,im])) + if nhaver > 1: + zon_aver = new_zon_aver + mer_aver = new_mer_aver + ver_aver = new_ver_aver + height = new_height + + + tstart = time_average[0] + tend = time_average[-1] + startTime = time.gmtime(tstart) + + year = startTime.tm_year + month = startTime.tm_mon + day = startTime.tm_mday + hour = startTime.tm_hour + minute = startTime.tm_min + second = startTime.tm_sec + + startDTList.append(datetime.datetime(year,month,day,hour,minute,second)) + + + o_height = numpy.array([]) + o_zon_aver = numpy.array([]) + o_mer_aver = numpy.array([]) + o_ver_aver = numpy.array([]) + if self.dataOut.nmodes > 1: + for im in range(self.dataOut.nmodes): + + if im == 0: + h_select = numpy.where(numpy.bitwise_and(height[0,:] >=0,height[0,:] <= hcm,numpy.isfinite(height[0,:]))) + else: + h_select = numpy.where(numpy.bitwise_and(height[1,:] > hcm,height[1,:] < 20,numpy.isfinite(height[1,:]))) + + + ht = h_select[0] + + o_height = numpy.hstack((o_height,height[im,ht])) + o_zon_aver = numpy.hstack((o_zon_aver,zon_aver[ht,im])) + o_mer_aver = numpy.hstack((o_mer_aver,mer_aver[ht,im])) + o_ver_aver = numpy.hstack((o_ver_aver,ver_aver[ht,im])) + + data_fHeigths_List.append(o_height) + data_fZonal_List.append(o_zon_aver) + data_fMeridional_List.append(o_mer_aver) + data_fVertical_List.append(o_ver_aver) + + + else: + h_select = numpy.where(numpy.bitwise_and(height[0,:] <= hcm,numpy.isfinite(height[0,:]))) + ht = h_select[0] + o_height = numpy.hstack((o_height,height[im,ht])) + o_zon_aver = numpy.hstack((o_zon_aver,zon_aver[ht,im])) + o_mer_aver = numpy.hstack((o_mer_aver,mer_aver[ht,im])) + o_ver_aver = numpy.hstack((o_ver_aver,ver_aver[ht,im])) + + data_fHeigths_List.append(o_height) + data_fZonal_List.append(o_zon_aver) + data_fMeridional_List.append(o_mer_aver) + data_fVertical_List.append(o_ver_aver) + + + return startDTList, data_fHeigths_List, data_fZonal_List, data_fMeridional_List, data_fVertical_List + + + def prePlot(self,modeselect=None): + + ''' + Inputs: + + self.dataOut.data_output - Zonal, Meridional and Vertical velocity array + self.dataOut.height - height array + self.dataOut.time - Time array (seconds) + self.dataOut.data_SNR - SNR array + + ''' + + m = modeselect -1 + + print ' [Plotting mode {}]'.format(modeselect) + if not (m ==1 or m==0): + raise IndexError("'Mode' must be egual to : 1 or 2") +# + if self.flagfirstmode==0: + #copy of the data + self.data_output_copy = self.dataOut.data_output.copy() + self.data_height_copy = self.dataOut.height.copy() + self.data_time_copy = self.dataOut.time.copy() + self.data_SNR_copy = self.dataOut.data_SNR.copy() + self.flagfirstmode = 1 + + else: + self.dataOut.data_output = self.data_output_copy + self.dataOut.height = self.data_height_copy + self.dataOut.time = self.data_time_copy + self.dataOut.data_SNR = self.data_SNR_copy + self.flagfirstmode = 0 + + + #select data for mode m + #self.dataOut.data_output = self.dataOut.data_output[:,:,m] + self.dataOut.heightList = self.dataOut.height[0,:] + + data_SNR = self.dataOut.data_SNR[:,:,m] + self.dataOut.data_SNR= transpose(data_SNR) + + if m==1 and self.dataOut.counter_records%2==0: + print '*********' + print 'MODO 2' + #print 'Zonal', self.dataOut.data_output[0] + #print 'Meridional', self.dataOut.data_output[1] + #print 'Vertical', self.dataOut.data_output[2] + + print '*********' + + Vx=self.dataOut.data_output[0,:,m] + Vy=self.dataOut.data_output[1,:,m] + + Vmag=numpy.sqrt(Vx**2+Vy**2) + Vang=numpy.arctan2(Vy,Vx) + #print 'Vmag', Vmag + #print 'Vang', Vang + + self.dataOut.data_output[0,:,m]=Vmag + self.dataOut.data_output[1,:,m]=Vang + + prin= self.dataOut.data_output[0,:,m][~numpy.isnan(self.dataOut.data_output[0,:,m])] + print ' ' + print 'VmagAverage',numpy.mean(prin) + print ' ' + self.dataOut.data_output = self.dataOut.data_output[:,:,m] + + + \ No newline at end of file diff --git a/schainpy/model/proc/jroproc_bltr.pyc b/schainpy/model/proc/jroproc_bltr.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b37eeb98d1f9e8b2292cffe9af384cbb3ccaffd GIT binary patch literal 15500 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 wApF literal 0 Hc$@yEGhbwpGWy|P#@)3_w0 zEjpHHm&NBod?v)N)+?f25z=93)j+G*dTn8XjtT!wpVbAMy7_5p9;Qi4W?2|_e;J2) z?h@!hU#3AGCh>xWS*NI3>&sT21}iem^2YcW8<-nm!A;!gE;W+wV&N`?2Hk>CK*zz= z&?(_I=#&NB1f5E86X09n&V=yS7OJ#Y%PMvU;tW;A3*LuNH(77|zVpVLq0G-OVR4}@ctB_fqUltEc4VO4 z809i$efBF_jgL{6`Hs!zpigX-MBn8!>AjakdC-+-aVQ^cPg(rWp0nooci!Q#GlgGU zee3o?GxsO)|FQx`+p8K<9qRvotNBLNM=b3mC=R~(^JpL`J}BT%Y10b9XK_KNne|&N zE@8jFMtqOknSTM(Uqn;WYaXQo>0|2?`k0FrP%2d47C*Nm~qai`HqZ# zGK?dBkrQmgR$69bD-Pl`s_L7Y)B8_(`^TN!FliYg}L}7aY2H(G=b&_=smUT6ORb}?` z0c`2P)#kqN?hsXAKd?+LPx^2%`Q`6kR$$DI>)=$yL&ojBAR5R!aD6AJ@{o~q5I@8T z&$AHKNv&&E-73-VIc{qh+auqYfLXcWM`vDa8_Qwli&lwtSQvO|*ki8NV z7lymU0`quMyuYjLwrwP+u&3oQE6Nln7bl-_3=#DEGH&NHf&*5%#x3R1vzt5jFiEYh znAK;5ar*q6U43;3^sk=;l}{f)w+l#(30|=$tr_d=ki5p0enri*D~hnMiJ|dh+HO}x zTE(-wD>-Kw^bqRvxQf5`hpv)MFa7Jdd6kYmqp5O0PLgS5-W_m?wD<71reFh5JI_ zMT&3#r_(kNxvqu3mWNZzm-!%#$7!`n(Y*m=uNCI{32dBqsqKaFK~|0$?^WfshqmA+ zXx`Kgn3a1(*YT8dh0#rUX3inNu_v}SXxGQs9tKC8o22-tY)zM*x9ip`_JS)+9v%lh z*=(}GZ#HS$K}18&i~S#?c>~Q=G}qAl49$%(8+Dx5fMo|kGgz#O?Yi#E?pe3$KIhi* zX#(lYvJ}uf444gq(g+p(kdobxZEB4h^M!XUx z`Rtc*&6D%ceB9UA-ezynDixGAPWZ3Xs2GYeq&DM@;Hp&AgmTs4$eMr%%~s$mOrQKJ z5tckhEc6^lq#^oPSk*gBhH3`$cs z);dQP+B{6dRrL@BiQFd?*YJ{=J9(b~1 zk$3L@8J+Lpq`GVIKWC1D`a1RMHjnL!?yE?&R79g}VdHv1tuCD=%g?QE@$~4*@#>z>Lg@TTCZYNG8Y}n4d{_oq=d*YCq(*%wmgS#YU)1|Vw-Z8 zzwy3qu?4N{=$h=|>oL2g59I0txsK0lt5~3MQ3ue%xf{E>QdI1)zz(u0My%Ca?KXv( z5Q8wHoHSwW*P`wPG2)$8DiH}&-~+u^6N(iqI|q#whd`_R=E8qjdo7jKzJq234bo75 zRTPO*wi)!LDsv#oNu>hZF%k*fpHQUS+EyjrB#K6ama8FLV$@-xDttoBk6l)QFqv&6 z=YKcST6HNmYFH(wVa?Om<^Gg4&%YO}X-ZTN)}ZiSsgTyI1wZ$6F>24&zGuW)?y^L7 zARdk`CaSc_DvDEP@o*{^fw)k)FA!$tW`mygSg?#*I5L(7b`Baa$Rx+Z#i~Qx*}-gN z7+E87|4u;yC0T@2$UKxD2+pu7MyC%eTPzGLG$&Hd>JPF_u>KpNi;Xp9mhi2Su^KT; zCSZFgbYZK>Z`}5DZA%potzAV2X&E;Pf-44~ zU}NhTo;d_B8SuMpb%3g_Delbel?&cvUydBuP`;4PEyEWwV~AmF$84b!oYhr+{iis> z4EhC{PtbgX=B_p$>;y;b#K&mB6Ap0-;pb2gY$pn<(XlfNr|CdXe%~@x%?5`yGj_vq zZPYeh;vM+b7_VyLy4e>)_i<5&1Ge}|@VoXg1~T6iqfkD#hsuz%rzl=NRYm$K6Wrn# zR2DHpy>W8IH5-`|1Btyzo_JL(M&B@<($XJhx01LMcKvs?j`)GlB@ur6^t#cn7mY4m z8P_E)hNHLrG)TLd(xm1IXcAX6?tmxLg$_*;2QD~lhsD0v1>*ap?5_!mH%4@*CO(HHscD3MMi?lc#AZhy$@F{*rne-sjIS} V-cXgTp8`pKIaMc1dB&do@;{)Z+iL&- literal 0 Hc$@ 0. , ETA, numpy.NaN) + + Ze = numpy.ones([Num_Chn,Num_Hei] ) + + for r in range(Num_Hei): + + Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2) + Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2) + + + dBZe = 10*numpy.log10(Ze) + dataOut.data_output = Ze + dataOut.data_param = dBZe + + print 'dBZe',dBZe[0,:] + + + + +class FullSpectralAnalysis(Operation): + + """ + Function that implements Full Spectral Analisys technique. + + Input: + self.dataOut.data_pre : SelfSpectra and CrossSPectra data + self.dataOut.groupList : Pairlist of channels + self.dataOut.ChanDist : Physical distance between receivers + + + Output: + + self.dataOut.data_output : Zonal wind, Meridional wind and Vertical wind + + + Parameters affected: Winds, height range, SNR + + """ + def run(self, dataOut): + + spc = dataOut.data_pre[0].copy() + cspc = dataOut.data_pre[1].copy() + + nChannel = spc.shape[0] + nProfiles = spc.shape[1] + nHeights = spc.shape[2] + + pairsList = dataOut.groupList + ChanDist = dataOut.ChanDist + VelRange= dataOut.VelRange + + ySamples=numpy.ones([nChannel,nProfiles]) + phase=numpy.ones([nChannel,nProfiles]) + CSPCSamples=numpy.ones([nChannel,nProfiles],dtype=numpy.complex_) + coherence=numpy.ones([nChannel,nProfiles]) + PhaseSlope=numpy.ones(nChannel) + PhaseInter=numpy.ones(nChannel) + + data = dataOut.data_pre + noise = dataOut.noise + SNRdB = 10*numpy.log10(dataOut.data_SNR) + + FirstMoment = [] + SNRdBMean = [] + + for j in range(nHeights): + FirstMoment = numpy.append(FirstMoment,numpy.mean([dataOut.data_param[0,1,j],dataOut.data_param[1,1,j],dataOut.data_param[2,1,j]])) + SNRdBMean = numpy.append(SNRdBMean,numpy.mean([SNRdB[0,j],SNRdB[1,j],SNRdB[2,j]])) + + data_output=numpy.ones([3,spc.shape[2]])*numpy.NaN + + velocityX=[] + velocityY=[] + velocityV=[] + + for Height in range(nHeights): + + + + [Vzon,Vmer,Vver, GaussCenter]= self.WindEstimation(spc, cspc, pairsList, ChanDist, Height, noise, VelRange) + + if abs(Vzon)<100 and abs(Vzon)> 0.: + velocityX=numpy.append(velocityX, Vzon)#Vmag + + else: + velocityX=numpy.append(velocityX, numpy.NaN) + + if abs(Vmer)<100 and abs(Vmer) > 0.: + velocityY=numpy.append(velocityY, Vmer)#Vang + + else: + velocityY=numpy.append(velocityY, numpy.NaN) + + if abs(GaussCenter)<10: + velocityV=numpy.append(velocityV, Vver) + else: + velocityV=numpy.append(velocityV, numpy.NaN) + #FirstMoment[Height]= numpy.NaN + if SNRdBMean[Height] <12: + FirstMoment[Height] = numpy.NaN + velocityX[Height] = numpy.NaN + velocityY[Height] = numpy.NaN + + + data_output[0]=numpy.array(velocityX) + data_output[1]=numpy.array(velocityY) + data_output[2]=-FirstMoment + + print ' ' + #print 'FirstMoment' + #print FirstMoment + print ' ' + #print 'velocityY' + #print numpy.array(velocityY) + print ' ' + #print 'SNR' + #print 10*numpy.log10(dataOut.data_SNR) + #print numpy.shape(10*numpy.log10(dataOut.data_SNR)) + print ' ' + + + dataOut.data_output=data_output + return + + + def moving_average(self,x, N=2): + return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):] + + def gaus(self,xSamples,a,x0,sigma): + return a*exp(-(xSamples-x0)**2/(2*sigma**2)) + + def Find(self,x,value): + for index in range(len(x)): + if x[index]==value: + return index + + def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, VelRange): + + ySamples=numpy.ones([spc.shape[0],spc.shape[1]]) + phase=numpy.ones([spc.shape[0],spc.shape[1]]) + CSPCSamples=numpy.ones([spc.shape[0],spc.shape[1]],dtype=numpy.complex_) + coherence=numpy.ones([spc.shape[0],spc.shape[1]]) + PhaseSlope=numpy.ones(spc.shape[0]) + PhaseInter=numpy.ones(spc.shape[0]) + xFrec=VelRange + + '''Getting Eij and Nij''' + + E01=ChanDist[0][0] + N01=ChanDist[0][1] + + E02=ChanDist[1][0] + N02=ChanDist[1][1] + + E12=ChanDist[2][0] + N12=ChanDist[2][1] + + z = spc.copy() + z = numpy.where(numpy.isfinite(z), z, numpy.NAN) + + for i in range(spc.shape[0]): + + '''****** Line of Data SPC ******''' + zline=z[i,:,Height] + + '''****** SPC is normalized ******''' + FactNorm= zline.copy() / numpy.sum(zline.copy()) + FactNorm= FactNorm/numpy.sum(FactNorm) + + SmoothSPC=self.moving_average(FactNorm,N=3) + + xSamples = ar(range(len(SmoothSPC))) + ySamples[i] = SmoothSPC-noise[i] + + for i in range(spc.shape[0]): + + '''****** Line of Data CSPC ******''' + cspcLine=cspc[i,:,Height].copy() + + '''****** CSPC is normalized ******''' + chan_index0 = pairsList[i][0] + chan_index1 = pairsList[i][1] + CSPCFactor= numpy.sum(ySamples[chan_index0]) * numpy.sum(ySamples[chan_index1]) + + CSPCNorm= cspcLine.copy() / numpy.sqrt(CSPCFactor) + + CSPCSamples[i] = CSPCNorm-noise[i] + coherence[i] = numpy.abs(CSPCSamples[i]) / numpy.sqrt(CSPCFactor) + + coherence[i]= self.moving_average(coherence[i],N=2) + + phase[i] = self.moving_average( numpy.arctan2(CSPCSamples[i].imag, CSPCSamples[i].real),N=1)#*180/numpy.pi + + '''****** Getting fij width ******''' + + yMean=[] + yMean2=[] + + for j in range(len(ySamples[1])): + yMean=numpy.append(yMean,numpy.mean([ySamples[0,j],ySamples[1,j],ySamples[2,j]])) + + '''******* Getting fitting Gaussian ******''' + meanGauss=sum(xSamples*yMean) / len(xSamples) + sigma=sum(yMean*(xSamples-meanGauss)**2) / len(xSamples) + + if (abs(meanGauss/sigma**2) > 0.00001) : + + try: + popt,pcov = curve_fit(self.gaus,xSamples,yMean,p0=[1,meanGauss,sigma]) + + if numpy.amax(popt)>numpy.amax(yMean)*0.3: + FitGauss=self.gaus(xSamples,*popt) + + else: + FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean) + print 'Verificador: Dentro', Height + except RuntimeError: + FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean) + +# + else: + FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean) + + Maximun=numpy.amax(yMean) + eMinus1=Maximun*numpy.exp(-1)*0.8 + + HWpos=self.Find(FitGauss,min(FitGauss, key=lambda value:abs(value-eMinus1))) + HalfWidth= xFrec[HWpos] + GCpos=self.Find(FitGauss, numpy.amax(FitGauss)) + Vpos=self.Find(FactNorm, numpy.amax(FactNorm)) + + #Vpos=FirstMoment[] + + '''****** Getting Fij ******''' + + GaussCenter=xFrec[GCpos] + if (GaussCenter<0 and HalfWidth>0) or (GaussCenter>0 and HalfWidth<0): + Fij=abs(GaussCenter)+abs(HalfWidth)+0.0000001 + else: + Fij=abs(GaussCenter-HalfWidth)+0.0000001 + + '''****** Getting Frecuency range of significant data ******''' + + Rangpos=self.Find(FitGauss,min(FitGauss, key=lambda value:abs(value-Maximun*0.10))) + + if Rangpos5 and len(FrecRange) m): ss1 = m - - valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1 + + valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1 power = ((spec2[valid] - n0)*fwindow[valid]).sum() fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power) - snr = (spec2.mean()-n0)/n0 - - if (snr < 1.e-20) : + snr = (spec2.mean()-n0)/n0 + + if (snr < 1.e-20) : snr = 1.e-20 - + vec_power[ind] = power vec_fd[ind] = fd vec_w[ind] = w vec_snr[ind] = snr - + moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w)) return moments - + #------------------ Get SA Parameters -------------------------- - + def GetSAParameters(self): #SA en frecuencia pairslist = self.dataOut.groupList num_pairs = len(pairslist) - + vel = self.dataOut.abscissaList - spectra = self.dataOut.data_pre[0] - cspectra = self.dataOut.data_pre[1] - delta_v = vel[1] - vel[0] - + spectra = self.dataOut.data_pre + cspectra = self.dataIn.data_cspc + delta_v = vel[1] - vel[0] + #Calculating the power spectrum spc_pow = numpy.sum(spectra, 3)*delta_v #Normalizing Spectra norm_spectra = spectra/spc_pow #Calculating the norm_spectra at peak - max_spectra = numpy.max(norm_spectra, 3) - + max_spectra = numpy.max(norm_spectra, 3) + #Normalizing Cross Spectra norm_cspectra = numpy.zeros(cspectra.shape) - + for i in range(num_chan): norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:]) - + max_cspectra = numpy.max(norm_cspectra,2) max_cspectra_index = numpy.argmax(norm_cspectra, 2) - + for i in range(num_pairs): cspc_par[i,:,:] = __calculateMoments(norm_cspectra) #------------------- Get Lags ---------------------------------- - + class SALags(Operation): ''' Function GetMoments() @@ -283,19 +644,19 @@ class SALags(Operation): self.dataOut.data_SNR self.dataOut.groupList self.dataOut.nChannels - + Affected: self.dataOut.data_param - + ''' - def run(self, dataOut): + def run(self, dataOut): data_acf = dataOut.data_pre[0] data_ccf = dataOut.data_pre[1] normFactor_acf = dataOut.normFactor[0] normFactor_ccf = dataOut.normFactor[1] pairs_acf = dataOut.groupList[0] pairs_ccf = dataOut.groupList[1] - + nHeights = dataOut.nHeights absc = dataOut.abscissaList noise = dataOut.noise @@ -306,97 +667,97 @@ class SALags(Operation): for l in range(len(pairs_acf)): data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:] - + for l in range(len(pairs_ccf)): data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:] - + dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights)) dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc) dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc) return - + # def __getPairsAutoCorr(self, pairsList, nChannels): -# +# # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan -# -# for l in range(len(pairsList)): +# +# for l in range(len(pairsList)): # firstChannel = pairsList[l][0] # secondChannel = pairsList[l][1] -# -# #Obteniendo pares de Autocorrelacion +# +# #Obteniendo pares de Autocorrelacion # if firstChannel == secondChannel: # pairsAutoCorr[firstChannel] = int(l) -# +# # pairsAutoCorr = pairsAutoCorr.astype(int) -# +# # pairsCrossCorr = range(len(pairsList)) # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr) -# +# # return pairsAutoCorr, pairsCrossCorr - + def __calculateTaus(self, data_acf, data_ccf, lagRange): - + lag0 = data_acf.shape[1]/2 #Funcion de Autocorrelacion mean_acf = stats.nanmean(data_acf, axis = 0) - + #Obtencion Indice de TauCross ind_ccf = data_ccf.argmax(axis = 1) #Obtencion Indice de TauAuto ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int') ccf_lag0 = data_ccf[:,lag0,:] - + for i in range(ccf_lag0.shape[0]): ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0) - + #Obtencion de TauCross y TauAuto tau_ccf = lagRange[ind_ccf] tau_acf = lagRange[ind_acf] - + Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0]) - + tau_ccf[Nan1,Nan2] = numpy.nan tau_acf[Nan1,Nan2] = numpy.nan tau = numpy.vstack((tau_ccf,tau_acf)) - + return tau - + def __calculateLag1Phase(self, data, lagTRange): data1 = stats.nanmean(data, axis = 0) lag1 = numpy.where(lagTRange == 0)[0][0] + 1 phase = numpy.angle(data1[lag1,:]) - + return phase - + class SpectralFitting(Operation): ''' Function GetMoments() - + Input: Output: Variables modified: ''' - - def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None): - - + + def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None): + + if path != None: sys.path.append(path) self.dataOut.library = importlib.import_module(file) - + #To be inserted as a parameter groupArray = numpy.array(groupList) -# groupArray = numpy.array([[0,1],[2,3]]) +# groupArray = numpy.array([[0,1],[2,3]]) self.dataOut.groupList = groupArray - + nGroups = groupArray.shape[0] nChannels = self.dataIn.nChannels nHeights=self.dataIn.heightList.size - + #Parameters Array self.dataOut.data_param = None - + #Set constants constants = self.dataOut.library.setConstants(self.dataIn) self.dataOut.constants = constants @@ -405,24 +766,24 @@ class SpectralFitting(Operation): ippSeconds = self.dataIn.ippSeconds K = self.dataIn.nIncohInt pairsArray = numpy.array(self.dataIn.pairsList) - + #List of possible combinations listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2) indCross = numpy.zeros(len(list(listComb)), dtype = 'int') - + if getSNR: listChannels = groupArray.reshape((groupArray.size)) listChannels.sort() noise = self.dataIn.getNoise() self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels]) - - for i in range(nGroups): + + for i in range(nGroups): coord = groupArray[i,:] - + #Input data array data = self.dataIn.data_spc[coord,:,:]/(M*N) data = data.reshape((data.shape[0]*data.shape[1],data.shape[2])) - + #Cross Spectra data array for Covariance Matrixes ind = 0 for pairs in listComb: @@ -431,10 +792,10 @@ class SpectralFitting(Operation): ind += 1 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N) dataCross = dataCross**2/K - + for h in range(nHeights): # print self.dataOut.heightList[h] - + #Input d = data[:,h] @@ -443,7 +804,7 @@ class SpectralFitting(Operation): ind = 0 for pairs in listComb: #Coordinates in Covariance Matrix - x = pairs[0] + x = pairs[0] y = pairs[1] #Channel Index S12 = dataCross[ind,:,h] @@ -457,15 +818,15 @@ class SpectralFitting(Operation): LT=L.T dp = numpy.dot(LT,d) - + #Initial values data_spc = self.dataIn.data_spc[coord,:,h] - + if (h>0)and(error1[3]<5): p0 = self.dataOut.data_param[i,:,h-1] else: p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i)) - + try: #Least Squares minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True) @@ -478,30 +839,30 @@ class SpectralFitting(Operation): minp = p0*numpy.nan error0 = numpy.nan error1 = p0*numpy.nan - + #Save - if self.dataOut.data_param is None: + if self.dataOut.data_param == None: self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan - + self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1)) self.dataOut.data_param[i,:,h] = minp return - + def __residFunction(self, p, dp, LT, constants): fm = self.dataOut.library.modelFunction(p, constants) fmp=numpy.dot(LT,fm) - + return dp-fmp def __getSNR(self, z, noise): - + avg = numpy.average(z, axis=1) SNR = (avg.T-noise)/noise SNR = SNR.T return SNR - + def __chisq(p,chindex,hindex): #similar to Resid but calculates CHI**2 [LT,d,fm]=setupLTdfm(p,chindex,hindex) @@ -509,50 +870,53 @@ class SpectralFitting(Operation): fmp=numpy.dot(LT,fm) chisq=numpy.dot((dp-fmp).T,(dp-fmp)) return chisq - + class WindProfiler(Operation): - + __isConfig = False - + __initime = None __lastdatatime = None __integrationtime = None - + __buffer = None - + __dataReady = False - + __firstdata = None - + n = None - + + def __init__(self): + Operation.__init__(self) + def __calculateCosDir(self, elev, azim): zen = (90 - elev)*numpy.pi/180 azim = azim*numpy.pi/180 - cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2))) + cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2))) cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2) - + signX = numpy.sign(numpy.cos(azim)) signY = numpy.sign(numpy.sin(azim)) - + cosDirX = numpy.copysign(cosDirX, signX) cosDirY = numpy.copysign(cosDirY, signY) return cosDirX, cosDirY - + def __calculateAngles(self, theta_x, theta_y, azimuth): - + dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2) zenith_arr = numpy.arccos(dir_cosw) azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180 - + dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr) dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr) - + return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly): - -# + +# if horOnly: A = numpy.c_[dir_cosu,dir_cosv] else: @@ -566,37 +930,37 @@ class WindProfiler(Operation): listPhi = phi.tolist() maxid = listPhi.index(max(listPhi)) minid = listPhi.index(min(listPhi)) - - rango = range(len(phi)) + + rango = range(len(phi)) # rango = numpy.delete(rango,maxid) - + heiRang1 = heiRang*math.cos(phi[maxid]) heiRangAux = heiRang*math.cos(phi[minid]) indOut = (heiRang1 < heiRangAux[0]).nonzero() heiRang1 = numpy.delete(heiRang1,indOut) - + velRadial1 = numpy.zeros([len(phi),len(heiRang1)]) SNR1 = numpy.zeros([len(phi),len(heiRang1)]) - + for i in rango: x = heiRang*math.cos(phi[i]) y1 = velRadial[i,:] f1 = interpolate.interp1d(x,y1,kind = 'cubic') - + x1 = heiRang1 y11 = f1(x1) - + y2 = SNR[i,:] f2 = interpolate.interp1d(x,y2,kind = 'cubic') y21 = f2(x1) - + velRadial1[i,:] = y11 SNR1[i,:] = y21 - + return heiRang1, velRadial1, SNR1 def __calculateVelUVW(self, A, velRadial): - + #Operacion Matricial # velUVW = numpy.zeros((velRadial.shape[1],3)) # for ind in range(velRadial.shape[1]): @@ -604,27 +968,27 @@ class WindProfiler(Operation): # velUVW = velUVW.transpose() velUVW = numpy.zeros((A.shape[0],velRadial.shape[1])) velUVW[:,:] = numpy.dot(A,velRadial) - - + + return velUVW - + # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0): - + def techniqueDBS(self, kwargs): """ Function that implements Doppler Beam Swinging (DBS) technique. - + Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth, Direction correction (if necessary), Ranges and SNR - + Output: Winds estimation (Zonal, Meridional and Vertical) - + Parameters affected: Winds, height range, SNR """ velRadial0 = kwargs['velRadial'] heiRang = kwargs['heightList'] SNR0 = kwargs['SNR'] - + if kwargs.has_key('dirCosx') and kwargs.has_key('dirCosy'): theta_x = numpy.array(kwargs['dirCosx']) theta_y = numpy.array(kwargs['dirCosy']) @@ -632,7 +996,7 @@ class WindProfiler(Operation): elev = numpy.array(kwargs['elevation']) azim = numpy.array(kwargs['azimuth']) theta_x, theta_y = self.__calculateCosDir(elev, azim) - azimuth = kwargs['correctAzimuth'] + azimuth = kwargs['correctAzimuth'] if kwargs.has_key('horizontalOnly'): horizontalOnly = kwargs['horizontalOnly'] else: horizontalOnly = False @@ -647,22 +1011,22 @@ class WindProfiler(Operation): param = param[arrayChannel,:,:] theta_x = theta_x[arrayChannel] theta_y = theta_y[arrayChannel] - - azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth) - heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0) + + azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth) + heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0) A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly) - + #Calculo de Componentes de la velocidad con DBS winds = self.__calculateVelUVW(A,velRadial1) - + return winds, heiRang1, SNR1 - + def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None): - + nPairs = len(pairs_ccf) posx = numpy.asarray(posx) posy = numpy.asarray(posy) - + #Rotacion Inversa para alinear con el azimuth if azimuth!= None: azimuth = azimuth*math.pi/180 @@ -671,126 +1035,126 @@ class WindProfiler(Operation): else: posx1 = posx posy1 = posy - + #Calculo de Distancias distx = numpy.zeros(nPairs) disty = numpy.zeros(nPairs) dist = numpy.zeros(nPairs) ang = numpy.zeros(nPairs) - + for i in range(nPairs): distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]] - disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]] + disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]] dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2) ang[i] = numpy.arctan2(disty[i],distx[i]) - + return distx, disty, dist, ang - #Calculo de Matrices + #Calculo de Matrices # nPairs = len(pairs) # ang1 = numpy.zeros((nPairs, 2, 1)) # dist1 = numpy.zeros((nPairs, 2, 1)) -# +# # for j in range(nPairs): # dist1[j,0,0] = dist[pairs[j][0]] # dist1[j,1,0] = dist[pairs[j][1]] # ang1[j,0,0] = ang[pairs[j][0]] # ang1[j,1,0] = ang[pairs[j][1]] -# +# # return distx,disty, dist1,ang1 - + def __calculateVelVer(self, phase, lagTRange, _lambda): Ts = lagTRange[1] - lagTRange[0] velW = -_lambda*phase/(4*math.pi*Ts) - + return velW - + def __calculateVelHorDir(self, dist, tau1, tau2, ang): nPairs = tau1.shape[0] nHeights = tau1.shape[1] - vel = numpy.zeros((nPairs,3,nHeights)) + vel = numpy.zeros((nPairs,3,nHeights)) dist1 = numpy.reshape(dist, (dist.size,1)) - + angCos = numpy.cos(ang) angSin = numpy.sin(ang) - - vel0 = dist1*tau1/(2*tau2**2) + + vel0 = dist1*tau1/(2*tau2**2) vel[:,0,:] = (vel0*angCos).sum(axis = 1) vel[:,1,:] = (vel0*angSin).sum(axis = 1) - + ind = numpy.where(numpy.isinf(vel)) vel[ind] = numpy.nan - + return vel - + # def __getPairsAutoCorr(self, pairsList, nChannels): -# +# # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan -# -# for l in range(len(pairsList)): +# +# for l in range(len(pairsList)): # firstChannel = pairsList[l][0] # secondChannel = pairsList[l][1] -# -# #Obteniendo pares de Autocorrelacion +# +# #Obteniendo pares de Autocorrelacion # if firstChannel == secondChannel: # pairsAutoCorr[firstChannel] = int(l) -# +# # pairsAutoCorr = pairsAutoCorr.astype(int) -# +# # pairsCrossCorr = range(len(pairsList)) # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr) -# +# # return pairsAutoCorr, pairsCrossCorr - + # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor): def techniqueSA(self, kwargs): - - """ + + """ Function that implements Spaced Antenna (SA) technique. - + Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth, Direction correction (if necessary), Ranges and SNR - + Output: Winds estimation (Zonal, Meridional and Vertical) - + Parameters affected: Winds """ position_x = kwargs['positionX'] position_y = kwargs['positionY'] azimuth = kwargs['azimuth'] - + if kwargs.has_key('correctFactor'): correctFactor = kwargs['correctFactor'] else: correctFactor = 1 - + groupList = kwargs['groupList'] pairs_ccf = groupList[1] tau = kwargs['tau'] _lambda = kwargs['_lambda'] - + #Cross Correlation pairs obtained # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels) # pairsArray = numpy.array(pairsList)[pairsCrossCorr] # pairsSelArray = numpy.array(pairsSelected) # pairs = [] -# +# # #Wind estimation pairs obtained # for i in range(pairsSelArray.shape[0]/2): # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0] # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0] # pairs.append((ind1,ind2)) - + indtau = tau.shape[0]/2 tau1 = tau[:indtau,:] tau2 = tau[indtau:-1,:] # tau1 = tau1[pairs,:] # tau2 = tau2[pairs,:] phase1 = tau[-1,:] - + #--------------------------------------------------------------------- - #Metodo Directo + #Metodo Directo distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth) winds = self.__calculateVelHorDir(dist, tau1, tau2, ang) winds = stats.nanmean(winds, axis=0) @@ -806,100 +1170,100 @@ class WindProfiler(Operation): winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda) winds = correctFactor*winds return winds - + def __checkTime(self, currentTime, paramInterval, outputInterval): - + dataTime = currentTime + paramInterval deltaTime = dataTime - self.__initime - + if deltaTime >= outputInterval or deltaTime < 0: self.__dataReady = True - return - - def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax, binkm=2): + return + + def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax): ''' Function that implements winds estimation technique with detected meteors. - + Input: Detected meteors, Minimum meteor quantity to wind estimation - + Output: Winds estimation (Zonal and Meridional) - + Parameters affected: Winds - ''' -# print arrayMeteor.shape + ''' +# print arrayMeteor.shape #Settings - nInt = (heightMax - heightMin)/binkm + nInt = (heightMax - heightMin)/2 # print nInt nInt = int(nInt) # print nInt - winds = numpy.zeros((2,nInt))*numpy.nan - + winds = numpy.zeros((2,nInt))*numpy.nan + #Filter errors error = numpy.where(arrayMeteor[:,-1] == 0)[0] finalMeteor = arrayMeteor[error,:] - + #Meteor Histogram finalHeights = finalMeteor[:,2] hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax)) nMeteorsPerI = hist[0] heightPerI = hist[1] - + #Sort of meteors indSort = finalHeights.argsort() finalMeteor2 = finalMeteor[indSort,:] - + # Calculating winds ind1 = 0 - ind2 = 0 - + ind2 = 0 + for i in range(nInt): nMet = nMeteorsPerI[i] ind1 = ind2 ind2 = ind1 + nMet - + meteorAux = finalMeteor2[ind1:ind2,:] - + if meteorAux.shape[0] >= meteorThresh: vel = meteorAux[:, 6] zen = meteorAux[:, 4]*numpy.pi/180 azim = meteorAux[:, 3]*numpy.pi/180 - + n = numpy.cos(zen) # m = (1 - n**2)/(1 - numpy.tan(azim)**2) # l = m*numpy.tan(azim) l = numpy.sin(zen)*numpy.sin(azim) m = numpy.sin(zen)*numpy.cos(azim) - + A = numpy.vstack((l, m)).transpose() A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose()) windsAux = numpy.dot(A1, vel) - + winds[0,i] = windsAux[0] winds[1,i] = windsAux[1] - + return winds, heightPerI[:-1] - + def techniqueNSM_SA(self, **kwargs): metArray = kwargs['metArray'] heightList = kwargs['heightList'] timeList = kwargs['timeList'] - + rx_location = kwargs['rx_location'] groupList = kwargs['groupList'] azimuth = kwargs['azimuth'] dfactor = kwargs['dfactor'] k = kwargs['k'] - + azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth) d = dist*dfactor #Phase calculation metArray1 = self.__getPhaseSlope(metArray, heightList, timeList) - + metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities - + velEst = numpy.zeros((heightList.size,2))*numpy.nan azimuth1 = azimuth1*numpy.pi/180 - + for i in range(heightList.size): h = heightList[i] indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0] @@ -912,71 +1276,71 @@ class WindProfiler(Operation): A = numpy.asmatrix(A) A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose() velHor = numpy.dot(A1,velAux) - + velEst[i,:] = numpy.squeeze(velHor) return velEst - + def __getPhaseSlope(self, metArray, heightList, timeList): meteorList = [] #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2 #Putting back together the meteor matrix utctime = metArray[:,0] uniqueTime = numpy.unique(utctime) - + phaseDerThresh = 0.5 ippSeconds = timeList[1] - timeList[0] sec = numpy.where(timeList>1)[0][0] nPairs = metArray.shape[1] - 6 nHeights = len(heightList) - + for t in uniqueTime: metArray1 = metArray[utctime==t,:] # phaseDerThresh = numpy.pi/4 #reducir Phase thresh tmet = metArray1[:,1].astype(int) hmet = metArray1[:,2].astype(int) - + metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1)) metPhase[:,:] = numpy.nan metPhase[:,hmet,tmet] = metArray1[:,6:].T - + #Delete short trails metBool = ~numpy.isnan(metPhase[0,:,:]) heightVect = numpy.sum(metBool, axis = 1) metBool[heightVect phaseDerThresh)) metPhase[phDerAux] = numpy.nan - + #--------------------------METEOR DETECTION ----------------------------------------- indMet = numpy.where(numpy.any(metBool,axis=1))[0] - + for p in numpy.arange(nPairs): phase = metPhase[p,:,:] phDer = metDer[p,:,:] - + for h in indMet: height = heightList[h] phase1 = phase[h,:] #82 phDer1 = phDer[h,:] - + phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap - + indValid = numpy.where(~numpy.isnan(phase1))[0] initMet = indValid[0] endMet = 0 - + for i in range(len(indValid)-1): - + #Time difference inow = indValid[i] inext = indValid[i+1] idiff = inext - inow #Phase difference - phDiff = numpy.abs(phase1[inext] - phase1[inow]) - + phDiff = numpy.abs(phase1[inext] - phase1[inow]) + if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor sizeTrail = inow - initMet + 1 if sizeTrail>3*sec: #Too short meteors @@ -992,28 +1356,28 @@ class WindProfiler(Operation): vel = slope#*height*1000/(k*d) estAux = numpy.array([utctime,p,height, vel, rsq]) meteorList.append(estAux) - initMet = inext + initMet = inext metArray2 = numpy.array(meteorList) - + return metArray2 - + def __calculateAzimuth1(self, rx_location, pairslist, azimuth0): - + azimuth1 = numpy.zeros(len(pairslist)) dist = numpy.zeros(len(pairslist)) - + for i in range(len(rx_location)): ch0 = pairslist[i][0] ch1 = pairslist[i][1] - + diffX = rx_location[ch0][0] - rx_location[ch1][0] diffY = rx_location[ch0][1] - rx_location[ch1][1] azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi dist[i] = numpy.sqrt(diffX**2 + diffY**2) - + azimuth1 -= azimuth0 return azimuth1, dist - + def techniqueNSM_DBS(self, **kwargs): metArray = kwargs['metArray'] heightList = kwargs['heightList'] @@ -1021,64 +1385,64 @@ class WindProfiler(Operation): zenithList = kwargs['zenithList'] nChan = numpy.max(cmet) + 1 nHeights = len(heightList) - + utctime = metArray[:,0] cmet = metArray[:,1] hmet = metArray1[:,3].astype(int) h1met = heightList[hmet]*zenithList[cmet] vmet = metArray1[:,5] - + for i in range(nHeights - 1): hmin = heightList[i] hmax = heightList[i + 1] - + vthisH = vmet[(h1met>=hmin) & (h1metSNRthresh)#|(~numpy.isnan(SNRdB)) -# +# # #Erase small objects -# boolMet1 = self.__erase_small(boolMet, 2*sec, 5) -# +# boolMet1 = self.__erase_small(boolMet, 2*sec, 5) +# # auxEEJ = numpy.sum(boolMet1,axis=0) # indOver = auxEEJ>nProfiles*0.8 #Use this later # indEEJ = numpy.where(indOver)[0] # indNEEJ = numpy.where(~indOver)[0] -# +# # boolMetFin = boolMet1 -# +# # if indEEJ.size > 0: -# boolMet1[:,indEEJ] = False #Erase heights with EEJ -# +# boolMet1[:,indEEJ] = False #Erase heights with EEJ +# # boolMet2 = coh > cohThresh # boolMet2 = self.__erase_small(boolMet2, 2*sec,5) -# +# # #Final Meteor mask # boolMetFin = boolMet1|boolMet2 - + #Coherence mask boolMet1 = coh > 0.75 struc = numpy.ones((30,1)) boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc) - + #Derivative mask derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0) boolMet2 = derPhase < 0.2 @@ -1377,7 +1738,7 @@ class NonSpecularMeteorDetection(Operation): tmet = coordMet[0] hmet = coordMet[1] - + data_param = numpy.zeros((tmet.size, 6 + nPairs)) data_param[:,0] = utctime data_param[:,1] = tmet @@ -1386,19 +1747,19 @@ class NonSpecularMeteorDetection(Operation): data_param[:,4] = velRad[tmet,hmet] data_param[:,5] = coh[tmet,hmet] data_param[:,6:] = phase[:,tmet,hmet].T - + elif mode == 'DBS': self.dataOut.groupList = numpy.arange(nChannels) - + #Radial Velocities # phase = numpy.angle(data_acf[:,1,:,:]) phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1)) velRad = phase*lamb/(4*numpy.pi*tSamp) - + #Spectral width acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1)) acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1)) - + spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2)) # velRad = ndimage.median_filter(velRad, size = (1,5,1)) if allData: @@ -1407,24 +1768,24 @@ class NonSpecularMeteorDetection(Operation): #SNR boolMet1 = (SNRdB>SNRthresh) #SNR mask boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5)) - + #Radial velocity boolMet2 = numpy.abs(velRad) < 30 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5)) - + #Spectral Width boolMet3 = spcWidth < 30 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5)) # boolMetFin = self.__erase_small(boolMet1, 10,5) boolMetFin = boolMet1&boolMet2&boolMet3 - + #Creating data_param coordMet = numpy.where(boolMetFin) cmet = coordMet[0] tmet = coordMet[1] hmet = coordMet[2] - + data_param = numpy.zeros((tmet.size, 7)) data_param[:,0] = utctime data_param[:,1] = cmet @@ -1433,7 +1794,7 @@ class NonSpecularMeteorDetection(Operation): data_param[:,4] = SNR[cmet,tmet,hmet].T data_param[:,5] = velRad[cmet,tmet,hmet].T data_param[:,6] = spcWidth[cmet,tmet,hmet].T - + # self.dataOut.data_param = data_int if len(data_param) == 0: self.dataOut.flagNoData = True @@ -1443,21 +1804,21 @@ class NonSpecularMeteorDetection(Operation): def __erase_small(self, binArray, threshX, threshY): labarray, numfeat = ndimage.measurements.label(binArray) binArray1 = numpy.copy(binArray) - + for i in range(1,numfeat + 1): auxBin = (labarray==i) auxSize = auxBin.sum() - + x,y = numpy.where(auxBin) widthX = x.max() - x.min() widthY = y.max() - y.min() - + #width X: 3 seg -> 12.5*3 - #width Y: - + #width Y: + if (auxSize < 50) or (widthX < threshX) or (widthY < threshY): binArray1[auxBin] = False - + return binArray1 #--------------- Specular Meteor ---------------- @@ -1467,36 +1828,36 @@ class SMDetection(Operation): Function DetectMeteors() Project developed with paper: HOLDSWORTH ET AL. 2004 - + Input: self.dataOut.data_pre - + centerReceiverIndex: From the channels, which is the center receiver - + hei_ref: Height reference for the Beacon signal extraction tauindex: predefinedPhaseShifts: Predefined phase offset for the voltge signals - + cohDetection: Whether to user Coherent detection or not cohDet_timeStep: Coherent Detection calculation time step cohDet_thresh: Coherent Detection phase threshold to correct phases - + noise_timeStep: Noise calculation time step noise_multiple: Noise multiple to define signal threshold - + multDet_timeLimit: Multiple Detection Removal time limit in seconds multDet_rangeLimit: Multiple Detection Removal range limit in km - + phaseThresh: Maximum phase difference between receiver to be consider a meteor - SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor - + SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor + hmin: Minimum Height of the meteor to use it in the further wind estimations hmax: Maximum Height of the meteor to use it in the further wind estimations azimuth: Azimuth angle correction - + Affected: self.dataOut.data_param - + Rejection Criteria (Errors): 0: No error; analysis OK 1: SNR < SNR threshold @@ -1515,9 +1876,9 @@ class SMDetection(Operation): 14: height ambiguous echo: more then one possible height within 70 to 110 km 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s 16: oscilatory echo, indicating event most likely not an underdense echo - + 17: phase difference in meteor Reestimation - + Data Storage: Meteors for Wind Estimation (8): Utc Time | Range Height @@ -1525,21 +1886,21 @@ class SMDetection(Operation): VelRad errorVelRad Phase0 Phase1 Phase2 Phase3 TypeError - - ''' - + + ''' + def run(self, dataOut, hei_ref = None, tauindex = 0, phaseOffsets = None, - cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25, + cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25, noise_timeStep = 4, noise_multiple = 4, multDet_timeLimit = 1, multDet_rangeLimit = 3, phaseThresh = 20, SNRThresh = 5, hmin = 50, hmax=150, azimuth = 0, channelPositions = None) : - - + + #Getting Pairslist - if channelPositions is None: + if channelPositions == None: # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella meteorOps = SMOperations() @@ -1547,53 +1908,53 @@ class SMDetection(Operation): heiRang = dataOut.getHeiRange() #Get Beacon signal - No Beacon signal anymore # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex]) -# +# # if hei_ref != None: # newheis = numpy.where(self.dataOut.heightList>hei_ref) -# - - +# + + #****************REMOVING HARDWARE PHASE DIFFERENCES*************** # see if the user put in pre defined phase shifts voltsPShift = dataOut.data_pre.copy() - + # if predefinedPhaseShifts != None: # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180 -# +# # # elif beaconPhaseShifts: # # #get hardware phase shifts using beacon signal # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10) # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0) -# +# # else: -# hardwarePhaseShifts = numpy.zeros(5) -# +# hardwarePhaseShifts = numpy.zeros(5) +# # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex') # for i in range(self.dataOut.data_pre.shape[0]): # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i]) #******************END OF REMOVING HARDWARE PHASE DIFFERENCES********* - + #Remove DC voltsDC = numpy.mean(voltsPShift,1) voltsDC = numpy.mean(voltsDC,1) for i in range(voltsDC.shape[0]): voltsPShift[i] = voltsPShift[i] - voltsDC[i] - - #Don't considerate last heights, theyre used to calculate Hardware Phase Shift + + #Don't considerate last heights, theyre used to calculate Hardware Phase Shift # voltsPShift = voltsPShift[:,:,:newheis[0][0]] - + #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) ********** #Coherent Detection if cohDetection: #use coherent detection to get the net power cohDet_thresh = cohDet_thresh*numpy.pi/180 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh) - + #Non-coherent detection! powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0) #********** END OF COH/NON-COH POWER CALCULATION********************** - + #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS **************** #Get noise noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval) @@ -1603,7 +1964,7 @@ class SMDetection(Operation): #Meteor echoes detection listMeteors = self.__findMeteors(powerNet, signalThresh) #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION ********** - + #************** REMOVE MULTIPLE DETECTIONS (3.5) *************************** #Parameters heiRange = dataOut.getHeiRange() @@ -1613,7 +1974,7 @@ class SMDetection(Operation): #Multiple detection removals listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit) #************ END OF REMOVE MULTIPLE DETECTIONS ********************** - + #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ******************** #Parameters phaseThresh = phaseThresh*numpy.pi/180 @@ -1624,40 +1985,40 @@ class SMDetection(Operation): #Estimation of decay times (Errors N 7, 8, 11) listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency) #******************* END OF METEOR REESTIMATION ******************* - + #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) ************************** #Calculating Radial Velocity (Error N 15) radialStdThresh = 10 - listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval) + listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval) if len(listMeteors4) > 0: #Setting New Array date = dataOut.utctime arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang) - + #Correcting phase offset if phaseOffsets != None: phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets) - + #Second Pairslist pairsList = [] pairx = (0,1) pairy = (2,3) pairsList.append(pairx) pairsList.append(pairy) - + jph = numpy.array([0,0,0,0]) h = (hmin,hmax) arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph) - + # #Calculate AOA (Error N 3, 4) # #JONES ET AL. 1998 # error = arrayParameters[:,-1] # AOAthresh = numpy.pi/8 # phases = -arrayParameters[:,9:13] # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth) -# +# # #Calculate Heights (Error N 13 and 14) # error = arrayParameters[:,-1] # Ranges = arrayParameters[:,2] @@ -1665,73 +2026,73 @@ class SMDetection(Operation): # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax) # error = arrayParameters[:,-1] #********************* END OF PARAMETERS CALCULATION ************************** - - #***************************+ PASS DATA TO NEXT STEP ********************** + + #***************************+ PASS DATA TO NEXT STEP ********************** # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1])) dataOut.data_param = arrayParameters - - if arrayParameters is None: + + if arrayParameters == None: dataOut.flagNoData = True else: dataOut.flagNoData = True - + return - + def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n): - + minIndex = min(newheis[0]) maxIndex = max(newheis[0]) - + voltage = voltage0[:,:,minIndex:maxIndex+1] nLength = voltage.shape[1]/n nMin = 0 nMax = 0 phaseOffset = numpy.zeros((len(pairslist),n)) - + for i in range(n): nMax += nLength phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0])) phaseCCF = numpy.mean(phaseCCF, axis = 2) - phaseOffset[:,i] = phaseCCF.transpose() + phaseOffset[:,i] = phaseCCF.transpose() nMin = nMax # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist) - + #Remove Outliers factor = 2 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5)) dw = numpy.std(wt,axis = 1) dw = dw.reshape((dw.size,1)) - ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor)) + ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor)) phaseOffset[ind] = numpy.nan - phaseOffset = stats.nanmean(phaseOffset, axis=1) - + phaseOffset = stats.nanmean(phaseOffset, axis=1) + return phaseOffset - + def __shiftPhase(self, data, phaseShift): #this will shift the phase of a complex number - dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j) + dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j) return dataShifted - + def __estimatePhaseDifference(self, array, pairslist): nChannel = array.shape[0] nHeights = array.shape[2] numPairs = len(pairslist) # phaseCCF = numpy.zeros((nChannel, 5, nHeights)) phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2])) - + #Correct phases derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:] indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi) - - if indDer[0].shape[0] > 0: + + if indDer[0].shape[0] > 0: for i in range(indDer[0].shape[0]): signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]]) phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi - + # for j in range(numSides): # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2]) # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux) -# +# #Linear phaseInt = numpy.zeros((numPairs,1)) angAllCCF = phaseCCF[:,[0,1,3,4],0] @@ -1741,16 +2102,16 @@ class SMDetection(Operation): #Phase Differences phaseDiff = phaseInt - phaseCCF[:,2,:] phaseArrival = phaseInt.reshape(phaseInt.size) - + #Dealias phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival)) # indAlias = numpy.where(phaseArrival > numpy.pi) # phaseArrival[indAlias] -= 2*numpy.pi # indAlias = numpy.where(phaseArrival < -numpy.pi) # phaseArrival[indAlias] += 2*numpy.pi - + return phaseDiff, phaseArrival - + def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh): #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power #find the phase shifts of each channel over 1 second intervals @@ -1760,25 +2121,25 @@ class SMDetection(Operation): numHeights = volts.shape[2] nChannel = volts.shape[0] voltsCohDet = volts.copy() - + pairsarray = numpy.array(pairslist) indSides = pairsarray[:,1] # indSides = numpy.array(range(nChannel)) # indSides = numpy.delete(indSides, indCenter) -# +# # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0) listBlocks = numpy.array_split(volts, numBlocks, 1) - + startInd = 0 endInd = 0 - + for i in range(numBlocks): startInd = endInd - endInd = endInd + listBlocks[i].shape[1] - + endInd = endInd + listBlocks[i].shape[1] + arrayBlock = listBlocks[i] # arrayBlockCenter = listCenter[i] - + #Estimate the Phase Difference phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist) #Phase Difference RMS @@ -1790,21 +2151,21 @@ class SMDetection(Operation): for j in range(indSides.size): arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose()) voltsCohDet[:,startInd:endInd,:] = arrayBlock - + return voltsCohDet - + def __calculateCCF(self, volts, pairslist ,laglist): - + nHeights = volts.shape[2] - nPoints = volts.shape[1] + nPoints = volts.shape[1] voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex') - + for i in range(len(pairslist)): volts1 = volts[pairslist[i][0]] - volts2 = volts[pairslist[i][1]] - + volts2 = volts[pairslist[i][1]] + for t in range(len(laglist)): - idxT = laglist[t] + idxT = laglist[t] if idxT >= 0: vStacked = numpy.vstack((volts2[idxT:,:], numpy.zeros((idxT, nHeights),dtype='complex'))) @@ -1812,10 +2173,10 @@ class SMDetection(Operation): vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'), volts2[:(nPoints + idxT),:])) voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0) - + vStacked = None return voltsCCF - + def __getNoise(self, power, timeSegment, timeInterval): numProfPerBlock = numpy.ceil(timeSegment/timeInterval) numBlocks = int(power.shape[0]/numProfPerBlock) @@ -1824,133 +2185,133 @@ class SMDetection(Operation): listPower = numpy.array_split(power, numBlocks, 0) noise = numpy.zeros((power.shape[0], power.shape[1])) noise1 = numpy.zeros((power.shape[0], power.shape[1])) - + startInd = 0 endInd = 0 - + for i in range(numBlocks): #split por canal startInd = endInd - endInd = endInd + listPower[i].shape[0] - + endInd = endInd + listPower[i].shape[0] + arrayBlock = listPower[i] noiseAux = numpy.mean(arrayBlock, 0) # noiseAux = numpy.median(noiseAux) # noiseAux = numpy.mean(arrayBlock) - noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux - + noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux + noiseAux1 = numpy.mean(arrayBlock) - noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1 - + noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1 + return noise, noise1 - + def __findMeteors(self, power, thresh): nProf = power.shape[0] nHeights = power.shape[1] listMeteors = [] - + for i in range(nHeights): powerAux = power[:,i] threshAux = thresh[:,i] - + indUPthresh = numpy.where(powerAux > threshAux)[0] indDNthresh = numpy.where(powerAux <= threshAux)[0] - + j = 0 - + while (j < indUPthresh.size - 2): if (indUPthresh[j + 2] == indUPthresh[j] + 2): indDNAux = numpy.where(indDNthresh > indUPthresh[j]) indDNthresh = indDNthresh[indDNAux] - + if (indDNthresh.size > 0): indEnd = indDNthresh[0] - 1 - indInit = indUPthresh[j] if isinstance(indUPthresh[j], (int, float)) else indUPthresh[j][0] ##CHECK!!!! - + indInit = indUPthresh[j] + meteor = powerAux[indInit:indEnd + 1] indPeak = meteor.argmax() + indInit FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0))) - + listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!! j = numpy.where(indUPthresh == indEnd)[0] + 1 else: j+=1 else: j+=1 - + return listMeteors - + def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit): - - arrayMeteors = numpy.asarray(listMeteors) + + arrayMeteors = numpy.asarray(listMeteors) listMeteors1 = [] - + while arrayMeteors.shape[0] > 0: FLAs = arrayMeteors[:,4] maxFLA = FLAs.argmax() listMeteors1.append(arrayMeteors[maxFLA,:]) - + MeteorInitTime = arrayMeteors[maxFLA,1] MeteorEndTime = arrayMeteors[maxFLA,3] MeteorHeight = arrayMeteors[maxFLA,0] - + #Check neighborhood maxHeightIndex = MeteorHeight + rangeLimit minHeightIndex = MeteorHeight - rangeLimit minTimeIndex = MeteorInitTime - timeLimit maxTimeIndex = MeteorEndTime + timeLimit - + #Check Heights indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex) indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex) indBoth = numpy.where(numpy.logical_and(indTime,indHeight)) - + arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0) - + return listMeteors1 - + def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency): numHeights = volts.shape[2] nChannel = volts.shape[0] - + thresholdPhase = thresh[0] thresholdNoise = thresh[1] thresholdDB = float(thresh[2]) - + thresholdDB1 = 10**(thresholdDB/10) pairsarray = numpy.array(pairslist) indSides = pairsarray[:,1] - + pairslist1 = list(pairslist) - pairslist1.append((0,4)) - pairslist1.append((1,3)) + pairslist1.append((0,1)) + pairslist1.append((3,4)) listMeteors1 = [] listPowerSeries = [] listVoltageSeries = [] #volts has the war data - - if frequency == 30.175e6: + + if frequency == 30e6: timeLag = 45*10**-3 else: timeLag = 15*10**-3 - lag = int(numpy.ceil(timeLag/timeInterval)) - + lag = numpy.ceil(timeLag/timeInterval) + for i in range(len(listMeteors)): - + ###################### 3.6 - 3.7 PARAMETERS REESTIMATION ######################### meteorAux = numpy.zeros(16) - + #Loading meteor Data (mHeight, mStart, mPeak, mEnd) - mHeight = int(listMeteors[i][0]) - mStart = int(listMeteors[i][1]) - mPeak = int(listMeteors[i][2]) - mEnd = int(listMeteors[i][3]) - + mHeight = listMeteors[i][0] + mStart = listMeteors[i][1] + mPeak = listMeteors[i][2] + mEnd = listMeteors[i][3] + #get the volt data between the start and end times of the meteor meteorVolts = volts[:,mStart:mEnd+1,mHeight] meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1) - + #3.6. Phase Difference estimation phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist) - + #3.7. Phase difference removal & meteor start, peak and end times reestimated #meteorVolts0.- all Channels, all Profiles meteorVolts0 = volts[:,:,mHeight] @@ -1958,15 +2319,15 @@ class SMDetection(Operation): meteorNoise = noise[:,mHeight] meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power - + #Times reestimation mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0] if mStart1.size > 0: mStart1 = mStart1[-1] + 1 - - else: + + else: mStart1 = mPeak - + mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0] if mEndDecayTime1.size == 0: @@ -1974,7 +2335,7 @@ class SMDetection(Operation): else: mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax() - + #meteorVolts1.- all Channels, from start to end meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1] meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1] @@ -1983,17 +2344,17 @@ class SMDetection(Operation): meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1) meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1) ##################### END PARAMETERS REESTIMATION ######################### - + ##################### 3.8 PHASE DIFFERENCE REESTIMATION ######################## # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis - if meteorVolts2.shape[1] > 0: + if meteorVolts2.shape[1] > 0: #Phase Difference re-estimation phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist) meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1]) phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1)) meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting - + #Phase Difference RMS phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1))) powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0) @@ -2008,50 +2369,50 @@ class SMDetection(Operation): #Vectorize meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1] meteorAux[7:11] = phaseDiffint[0:4] - + #Rejection Criterions if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation meteorAux[-1] = 17 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB meteorAux[-1] = 1 - - - else: + + + else: meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd] meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis PowerSeries = 0 - + listMeteors1.append(meteorAux) listPowerSeries.append(PowerSeries) listVoltageSeries.append(meteorVolts1) - - return listMeteors1, listPowerSeries, listVoltageSeries - + + return listMeteors1, listPowerSeries, listVoltageSeries + def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency): - + threshError = 10 #Depending if it is 30 or 50 MHz - if frequency == 30.175e6: + if frequency == 30e6: timeLag = 45*10**-3 else: timeLag = 15*10**-3 - lag = int(numpy.ceil(timeLag/timeInterval)) - + lag = numpy.ceil(timeLag/timeInterval) + listMeteors1 = [] - + for i in range(len(listMeteors)): meteorPower = listPower[i] meteorAux = listMeteors[i] - + if meteorAux[-1] == 0: - try: + try: indmax = meteorPower.argmax() indlag = indmax + lag - + y = meteorPower[indlag:] x = numpy.arange(0, y.size)*timeLag - + #first guess a = y[0] tau = timeLag @@ -2060,26 +2421,26 @@ class SMDetection(Operation): y1 = self.__exponential_function(x, *popt) #error estimation error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size)) - + decayTime = popt[1] riseTime = indmax*timeInterval meteorAux[11:13] = [decayTime, error] - + #Table items 7, 8 and 11 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s - meteorAux[-1] = 7 + meteorAux[-1] = 7 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time meteorAux[-1] = 8 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time - meteorAux[-1] = 11 - - + meteorAux[-1] = 11 + + except: - meteorAux[-1] = 11 - - + meteorAux[-1] = 11 + + listMeteors1.append(meteorAux) - + return listMeteors1 #Exponential Function @@ -2087,45 +2448,45 @@ class SMDetection(Operation): def __exponential_function(self, x, a, tau): y = a*numpy.exp(-x/tau) return y - + def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval): - + pairslist1 = list(pairslist) - pairslist1.append((0,4)) - pairslist1.append((1,3)) + pairslist1.append((0,1)) + pairslist1.append((3,4)) numPairs = len(pairslist1) #Time Lag timeLag = 45*10**-3 c = 3e8 lag = numpy.ceil(timeLag/timeInterval) - freq = 30.175e6 - + freq = 30e6 + listMeteors1 = [] - + for i in range(len(listMeteors)): meteorAux = listMeteors[i] if meteorAux[-1] == 0: mStart = listMeteors[i][1] - mPeak = listMeteors[i][2] + mPeak = listMeteors[i][2] mLag = mPeak - mStart + lag - + #get the volt data between the start and end times of the meteor meteorVolts = listVolts[i] meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1) #Get CCF allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2]) - + #Method 2 slopes = numpy.zeros(numPairs) time = numpy.array([-2,-1,1,2])*timeInterval - angAllCCF = numpy.angle(allCCFs[:,[0,4,2,3],0]) - + angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0]) + #Correct phases derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1] indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi) - - if indDer[0].shape[0] > 0: + + if indDer[0].shape[0] > 0: for i in range(indDer[0].shape[0]): signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]]) angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi @@ -2134,51 +2495,51 @@ class SMDetection(Operation): for j in range(numPairs): fit = stats.linregress(time, angAllCCF[j,:]) slopes[j] = fit[0] - + #Remove Outlier # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes))) # slopes = numpy.delete(slopes,indOut) # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes))) # slopes = numpy.delete(slopes,indOut) - + radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq) radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq) meteorAux[-2] = radialError meteorAux[-3] = radialVelocity - + #Setting Error #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s - if numpy.abs(radialVelocity) > 200: + if numpy.abs(radialVelocity) > 200: meteorAux[-1] = 15 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity elif radialError > radialStdThresh: meteorAux[-1] = 12 - + listMeteors1.append(meteorAux) return listMeteors1 - + def __setNewArrays(self, listMeteors, date, heiRang): - + #New arrays arrayMeteors = numpy.array(listMeteors) arrayParameters = numpy.zeros((len(listMeteors), 13)) - + #Date inclusion # date = re.findall(r'\((.*?)\)', date) # date = date[0].split(',') # date = map(int, date) -# +# # if len(date)<6: # date.append(0) -# +# # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]] # arrayDate = numpy.tile(date, (len(listMeteors), 1)) arrayDate = numpy.tile(date, (len(listMeteors))) - + #Meteor array # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)] # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors)) - + #Parameters Array arrayParameters[:,0] = arrayDate #Date arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range @@ -2186,13 +2547,13 @@ class SMDetection(Operation): arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases arrayParameters[:,-1] = arrayMeteors[:,-1] #Error - + return arrayParameters - + class CorrectSMPhases(Operation): - + def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None): - + arrayParameters = dataOut.data_param pairsList = [] pairx = (0,1) @@ -2200,51 +2561,51 @@ class CorrectSMPhases(Operation): pairsList.append(pairx) pairsList.append(pairy) jph = numpy.zeros(4) - + phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets) arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets))) - + meteorOps = SMOperations() - if channelPositions is None: + if channelPositions == None: # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella - + pairslist0, distances = meteorOps.getPhasePairs(channelPositions) h = (hmin,hmax) - + arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph) - + dataOut.data_param = arrayParameters return class SMPhaseCalibration(Operation): - + __buffer = None __initime = None __dataReady = False - + __isConfig = False - + def __checkTime(self, currentTime, initTime, paramInterval, outputInterval): - + dataTime = currentTime + paramInterval deltaTime = dataTime - initTime - + if deltaTime >= outputInterval or deltaTime < 0: return True - + return False - + def __getGammas(self, pairs, d, phases): gammas = numpy.zeros(2) - + for i in range(len(pairs)): - + pairi = pairs[i] - + phip3 = phases[:,pairi[1]] d3 = d[pairi[1]] phip2 = phases[:,pairi[0]] @@ -2256,7 +2617,7 @@ class SMPhaseCalibration(Operation): jgamma = numpy.angle(numpy.exp(1j*jgamma)) # jgamma[jgamma>numpy.pi] -= 2*numpy.pi # jgamma[jgamma<-numpy.pi] += 2*numpy.pi - + #Revised distribution jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi)) @@ -2265,39 +2626,39 @@ class SMPhaseCalibration(Operation): rmin = -0.5*numpy.pi rmax = 0.5*numpy.pi phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax)) - + meteorsY = phaseHisto[0] phasesX = phaseHisto[1][:-1] width = phasesX[1] - phasesX[0] phasesX += width/2 - + #Gaussian aproximation bpeak = meteorsY.argmax() peak = meteorsY.max() jmin = bpeak - 5 jmax = bpeak + 5 + 1 - + if jmin<0: jmin = 0 jmax = 6 elif jmax > meteorsY.size: jmin = meteorsY.size - 6 jmax = meteorsY.size - + x0 = numpy.array([peak,bpeak,50]) coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax])) - + #Gammas gammas[i] = coeff[0][1] - + return gammas - + def __residualFunction(self, coeffs, y, t): - + return y - self.__gauss_function(t, coeffs) def __gauss_function(self, t, coeffs): - + return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2) def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray): @@ -2309,58 +2670,58 @@ class SMPhaseCalibration(Operation): center_yangle = 0 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4]) ntimes = len(range_angle) - + nstepsx = 20.0 nstepsy = 20.0 - + for iz in range(ntimes): min_xangle = -range_angle[iz]/2 + center_xangle max_xangle = range_angle[iz]/2 + center_xangle min_yangle = -range_angle[iz]/2 + center_yangle max_yangle = range_angle[iz]/2 + center_yangle - + inc_x = (max_xangle-min_xangle)/nstepsx inc_y = (max_yangle-min_yangle)/nstepsy - + alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle penalty = numpy.zeros((nstepsx,nstepsy)) jph_array = numpy.zeros((nchan,nstepsx,nstepsy)) jph = numpy.zeros(nchan) - + # Iterations looking for the offset for iy in range(int(nstepsy)): for ix in range(int(nstepsx)): jph[pairy[1]] = alpha_y[iy] - jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]] - + jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]] + jph[pairx[1]] = alpha_x[ix] jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]] - + jph_array[:,ix,iy] = jph - + meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph) error = meteorsArray1[:,-1] ind1 = numpy.where(error==0)[0] penalty[ix,iy] = ind1.size - + i,j = numpy.unravel_index(penalty.argmax(), penalty.shape) phOffset = jph_array[:,i,j] - + center_xangle = phOffset[pairx[1]] center_yangle = phOffset[pairy[1]] - + phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j])) - phOffset = phOffset*180/numpy.pi + phOffset = phOffset*180/numpy.pi return phOffset - - + + def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1): - + dataOut.flagNoData = True - self.__dataReady = False + self.__dataReady = False dataOut.outputInterval = nHours*3600 - + if self.__isConfig == False: # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03) #Get Initial LTC time @@ -2368,19 +2729,19 @@ class SMPhaseCalibration(Operation): self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds() self.__isConfig = True - - if self.__buffer is None: + + if self.__buffer == None: self.__buffer = dataOut.data_param.copy() else: self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param)) - + self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready - + if self.__dataReady: dataOut.utctimeInit = self.__initime self.__initime += dataOut.outputInterval #to erase time offset - + freq = dataOut.frequency c = dataOut.C #m/s lamb = c/freq @@ -2388,15 +2749,15 @@ class SMPhaseCalibration(Operation): azimuth = 0 h = (hmin, hmax) pairs = ((0,1),(2,3)) - - if channelPositions is None: + + if channelPositions == None: # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella meteorOps = SMOperations() pairslist0, distances = meteorOps.getPhasePairs(channelPositions) - + # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb] - + meteorsArray = self.__buffer error = meteorsArray[:,-1] boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14) @@ -2404,7 +2765,7 @@ class SMPhaseCalibration(Operation): meteorsArray = meteorsArray[ind1,:] meteorsArray[:,-1] = 0 phases = meteorsArray[:,8:12] - + #Calculate Gammas gammas = self.__getGammas(pairs, distances, phases) # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180 @@ -2413,24 +2774,23 @@ class SMPhaseCalibration(Operation): phasesOff = phasesOff.reshape((1,phasesOff.size)) dataOut.data_output = -phasesOff dataOut.flagNoData = False - dataOut.channelList = pairslist0 self.__buffer = None - - + + return - + class SMOperations(): - + def __init__(self): - + return - + def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph): - + arrayParameters = arrayParameters0.copy() hmin = h[0] hmax = h[1] - + #Calculate AOA (Error N 3, 4) #JONES ET AL. 1998 AOAthresh = numpy.pi/8 @@ -2438,72 +2798,72 @@ class SMOperations(): phases = -arrayParameters[:,8:12] + jph # phases = numpy.unwrap(phases) arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth) - + #Calculate Heights (Error N 13 and 14) error = arrayParameters[:,-1] Ranges = arrayParameters[:,1] zenith = arrayParameters[:,4] arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax) - + #----------------------- Get Final data ------------------------------------ # error = arrayParameters[:,-1] # ind1 = numpy.where(error==0)[0] # arrayParameters = arrayParameters[ind1,:] - + return arrayParameters - + def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth): - + arrayAOA = numpy.zeros((phases.shape[0],3)) cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions) - + arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth) cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1) arrayAOA[:,2] = cosDirError - + azimuthAngle = arrayAOA[:,0] zenithAngle = arrayAOA[:,1] - + #Setting Error indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0] error[indError] = 0 #Number 3: AOA not fesible indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0] - error[indInvalid] = 3 + error[indInvalid] = 3 #Number 4: Large difference in AOAs obtained from different antenna baselines indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0] - error[indInvalid] = 4 + error[indInvalid] = 4 return arrayAOA, error - + def __getDirectionCosines(self, arrayPhase, pairsList, distances): - + #Initializing some variables ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi ang_aux = ang_aux.reshape(1,ang_aux.size) - + cosdir = numpy.zeros((arrayPhase.shape[0],2)) cosdir0 = numpy.zeros((arrayPhase.shape[0],2)) - - + + for i in range(2): ph0 = arrayPhase[:,pairsList[i][0]] ph1 = arrayPhase[:,pairsList[i][1]] d0 = distances[pairsList[i][0]] d1 = distances[pairsList[i][1]] - - ph0_aux = ph0 + ph1 + + ph0_aux = ph0 + ph1 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux)) # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi -# ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi +# ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi #First Estimation cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1)) - + #Most-Accurate Second Estimation phi1_aux = ph0 - ph1 phi1_aux = phi1_aux.reshape(phi1_aux.size,1) #Direction Cosine 1 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1)) - + #Searching the correct Direction Cosine cosdir0_aux = cosdir0[:,i] cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1) @@ -2512,59 +2872,59 @@ class SMOperations(): indcos = cosDiff.argmin(axis = 1) #Saving Value obtained cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos] - + return cosdir0, cosdir - + def __calculateAOA(self, cosdir, azimuth): cosdirX = cosdir[:,0] cosdirY = cosdir[:,1] - + zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose() - + return angles - + def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight): - + Ramb = 375 #Ramb = c/(2*PRF) Re = 6371 #Earth Radius heights = numpy.zeros(Ranges.shape) - + R_aux = numpy.array([0,1,2])*Ramb R_aux = R_aux.reshape(1,R_aux.size) Ranges = Ranges.reshape(Ranges.size,1) - + Ri = Ranges + R_aux hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re - + #Check if there is a height between 70 and 110 km h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1) ind_h = numpy.where(h_bool == 1)[0] - + hCorr = hi[ind_h, :] ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight)) - - hCorr = hi[ind_hCorr] + + hCorr = hi[ind_hCorr] heights[ind_h] = hCorr - + #Setting Error #Number 13: Height unresolvable echo: not valid height within 70 to 110 km - #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km + #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0] error[indError] = 0 - indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0] + indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0] error[indInvalid2] = 14 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0] - error[indInvalid1] = 13 - + error[indInvalid1] = 13 + return heights, error - + def getPhasePairs(self, channelPositions): chanPos = numpy.array(channelPositions) listOper = list(itertools.combinations(range(5),2)) - + distances = numpy.zeros(4) axisX = [] axisY = [] @@ -2572,15 +2932,15 @@ class SMOperations(): distY = numpy.zeros(3) ix = 0 iy = 0 - + pairX = numpy.zeros((2,2)) pairY = numpy.zeros((2,2)) - + for i in range(len(listOper)): pairi = listOper[i] - + posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:]) - + if posDif[0] == 0: axisY.append(pairi) distY[iy] = posDif[1] @@ -2589,7 +2949,7 @@ class SMOperations(): axisX.append(pairi) distX[ix] = posDif[0] ix += 1 - + for i in range(2): if i==0: dist0 = distX @@ -2597,7 +2957,7 @@ class SMOperations(): else: dist0 = distY axis0 = axisY - + side = numpy.argsort(dist0)[:-1] axis0 = numpy.array(axis0)[side,:] chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0]) @@ -2605,7 +2965,7 @@ class SMOperations(): side = axis1[axis1 != chanC] diff1 = chanPos[chanC,i] - chanPos[side[0],i] diff2 = chanPos[chanC,i] - chanPos[side[1],i] - if diff1<0: + if diff1<0: chan2 = side[0] d2 = numpy.abs(diff1) chan1 = side[1] @@ -2615,7 +2975,7 @@ class SMOperations(): d2 = numpy.abs(diff2) chan1 = side[0] d1 = numpy.abs(diff1) - + if i==0: chanCX = chanC chan1X = chan1 @@ -2627,10 +2987,10 @@ class SMOperations(): chan2Y = chan2 distances[2:4] = numpy.array([d1,d2]) # axisXsides = numpy.reshape(axisX[ix,:],4) -# +# # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0]) # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0]) -# +# # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0] # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0] # channel25X = int(pairX[0,ind25X]) @@ -2639,59 +2999,59 @@ class SMOperations(): # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0] # channel25Y = int(pairY[0,ind25Y]) # channel20Y = int(pairY[1,ind20Y]) - + # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)] - pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)] - + pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)] + return pairslist, distances # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth): -# +# # arrayAOA = numpy.zeros((phases.shape[0],3)) # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList) -# +# # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth) # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1) # arrayAOA[:,2] = cosDirError -# +# # azimuthAngle = arrayAOA[:,0] # zenithAngle = arrayAOA[:,1] -# +# # #Setting Error # #Number 3: AOA not fesible # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0] -# error[indInvalid] = 3 +# error[indInvalid] = 3 # #Number 4: Large difference in AOAs obtained from different antenna baselines # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0] -# error[indInvalid] = 4 +# error[indInvalid] = 4 # return arrayAOA, error -# +# # def __getDirectionCosines(self, arrayPhase, pairsList): -# +# # #Initializing some variables # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi # ang_aux = ang_aux.reshape(1,ang_aux.size) -# +# # cosdir = numpy.zeros((arrayPhase.shape[0],2)) # cosdir0 = numpy.zeros((arrayPhase.shape[0],2)) -# -# +# +# # for i in range(2): # #First Estimation # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]] # #Dealias # indcsi = numpy.where(phi0_aux > numpy.pi) -# phi0_aux[indcsi] -= 2*numpy.pi +# phi0_aux[indcsi] -= 2*numpy.pi # indcsi = numpy.where(phi0_aux < -numpy.pi) -# phi0_aux[indcsi] += 2*numpy.pi +# phi0_aux[indcsi] += 2*numpy.pi # #Direction Cosine 0 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5) -# +# # #Most-Accurate Second Estimation # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]] # phi1_aux = phi1_aux.reshape(phi1_aux.size,1) # #Direction Cosine 1 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5) -# +# # #Searching the correct Direction Cosine # cosdir0_aux = cosdir0[:,i] # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1) @@ -2700,50 +3060,51 @@ class SMOperations(): # indcos = cosDiff.argmin(axis = 1) # #Saving Value obtained # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos] -# +# # return cosdir0, cosdir -# +# # def __calculateAOA(self, cosdir, azimuth): # cosdirX = cosdir[:,0] # cosdirY = cosdir[:,1] -# +# # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose() -# +# # return angles -# +# # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight): -# +# # Ramb = 375 #Ramb = c/(2*PRF) # Re = 6371 #Earth Radius # heights = numpy.zeros(Ranges.shape) -# +# # R_aux = numpy.array([0,1,2])*Ramb # R_aux = R_aux.reshape(1,R_aux.size) -# +# # Ranges = Ranges.reshape(Ranges.size,1) -# +# # Ri = Ranges + R_aux # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re -# +# # #Check if there is a height between 70 and 110 km # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1) # ind_h = numpy.where(h_bool == 1)[0] -# +# # hCorr = hi[ind_h, :] # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight)) -# -# hCorr = hi[ind_hCorr] +# +# hCorr = hi[ind_hCorr] # heights[ind_h] = hCorr -# +# # #Setting Error # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km -# #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km -# -# indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0] +# #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km +# +# indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0] # error[indInvalid2] = 14 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0] -# error[indInvalid1] = 13 -# -# return heights, error +# error[indInvalid1] = 13 +# +# return heights, error + \ No newline at end of file diff --git a/schainpy/model/proc/jroproc_parameters.pyc b/schainpy/model/proc/jroproc_parameters.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c530ce9cfccf22090e55b673b19d7b124db7dcc3 GIT binary patch literal 81409 zc%1CL33OaXdLCN$-tGn(XzblUg8<3q4pQ7eNh6JfkwlTAq#23gG&F>UmW*k3H-H8k z-9UGP1muR7aJ)?7ICjSCc#fAdGjVLcycZ{4(;IM_x~^Nj|ckJ`kr}jQJH_9{(VOOHb3nsRnq?* zRaNSSpLWy@hiO+;UA5+^8=hK=sT(o17FRdoYAvB|B-C1uy3wN?)23J5=(X*W>PFJ0 z`_zp-o90(8nn4Xe(ru%8n(G3e(nKP8nwA&e(ph4O55CwpPN&qahp5g=N?j} ztj(SDa}TT1KASt`=N?g|X`8#>&poP22W;*^Klhj_< zuFk}Dvem0E_4QU|t@38M)sMnjtK3+xR|~CjD}hy0S*{hTEmUr{3aw_VN2h9~%35K$ zJmaE^L4CQ_s29u4W~H|Lo?4~VO6sgv*2|4Tt5UB?tv=K$Gzx2F-G8$+qHk9!)l&Ip zqfjd?Hp{nGY)w3%&@40>h3yvBZh32c#z6skEp9e$mlu~Rt;##Mesx5i?e~gN_{$zm zp2et7q7TJI&b6%CXETzqnY@v$eR`!b7jtYck_EH-kYl?r;^EBX!b{_BnU(u=iHc`M&z=L+SoY_?>M&{MNqU7F$JaB03xjXg7t>${6SU%S*t`sV@#q!O1u}~{7Hwq?aef!*6y;QEA(@!g&TW!?wcX8dH z=d!^v2+v$yJE+DuN&=EQ7H+~&k>PQvCSY)+5O z>9IMzYBgzQ9r?XBzb~5KXY>1QPQT4b*_@QpQ@=V0K%}A0vWw4ciUw`vA)7N~bB1ls zu+15XuCv9^wHYa0q#%<2H&6%({6E-JnbFwyPGBghC z?6WyjHfKr}FIMDLE~`elP;FvE&MiH{48Q;`?q+9kkc&Eg?le|t!YtVrYwV=8y2^-e!v+1p5Q4{sy)MmwB^wrCL}fASpK*^~R<8X06pq>D$d_`6a!CtFL00WHFXP zsi4bitwz0CEjL~$7fR*ED>qm9#A1DYyETLXZZ})ywV)8-Pp|)4tz3Pn(rocbE9J`a zN{hGHwzbVQ-59A71}=He7B)+gx}KZdMuUNW_`2yY_(pz#TVLa z6}hbkZM8C5UB+$?vX-iqb!PQQ|0{ahIIzn4`n+yX)6al4bW+ZJ+2ecrNNSoAvq~ZVy*eAiWT|WCa>=Q!}V#y7j>jMdmlMH}~M*u@G$PP#l z-vtTcyC6Xv`#$_?tw~csL$$klc+WZ!01yWNsHsr3IIC4`wJBR|Dq1bUYF}xqP1|bI z(P}-c_I%*sa zef7gO=Sa83der6|Rgnqm;{-kCN$ILZuOM9_>*AO!-N+`{y#bEf99ir${X`1bfYn%zi!}#odVh951{F&9T>6}*Bb)AuV}m_qXNjiS_inz z0~m5721>tZ$=aHJ)>5TfZss3Cm#0w=v=HH)4}txMG}nu4#+xGU3~=_R1JJv0vstV( zn}wI`Wa<2?0MYsL%FxcWdSmTMq1dW7h#l&iE&YD}^GF&NG_}YcaJSs3Z?5wW^S7c2 z>Q<|fe*|NG6qmQ*@)$0pZP90Qy;^Bq*{l^Y?M8sES3pHMJkknt4nJ9*1@Y;4vp z;tALBoY<(_r}0usW1r(rOy3>QcNxJ;P6~Lb<2Rcabq=}DJ5M{!Eq>8oq`E)VP$3B^rawJ&G?=@p2+a;=p@E2l}jW-hPE zAPrh7w=1pf+!8lIZsx|x(>cvL=E_aIKlQ$E<}~Q3EfuQOTwdP>{RJt)geRhT`XBhE zvxbX0Ye54FSan{P8psxD)we703isp_-3z-vNVc&&sLNZPj=ocuZv8|6408p|KNef% z5_?_Hd#rgnCv>dtPH*7TIlW=ou!!j&HnbG!s6Pj{<`5e@YEokojTbaZMHUe&5=5_h zpMzK9*X)izHP%BP8PwSe$D)o#mKkBQG|EQ*2_kM6e4eI`CU<)5jjp-VYj1SdJ4p^h zXK9qxV|cZlK4vB(naJr=>79NMKszbkYpRZ{zot1%8_gE=f%Lf*Lqgiz^}6@CGoZG< z9H3w4=-bP0e7@QlWP44`4GL`#3*BJ6>2^Ysje{VYGWyNN((Qqu#vIzZ;kNEuwzW0p zHXd~rG?j&6>Ol-(MCqL&r1XS>OC4fj7&O-N`li%D#ytN5@j9TdNGgcLD_9=OKmPyD zy#9}V><^w^wi{a#U-mDbsQ^|9j(zqB4(;uU!FZrj2hZagrKsGu_tDREeaC+&py|S zq2aw^@gecj)y=g<%{lq$XDc;7eQBk}_Rqa~F~5Qan4ov9@z0HN3v<@Uf9`_-$N>Ex zLieYLoW>x0i7mvFu>l7^8E0Ap=~3r^n{mh7Ip-OVHC&3f@;7k#9Q(qHizQG`4-lKY zp?m#+G7^HsP{JjDcxAI%HGsByu~w*VH#OgE*PLsS$y0kF6Tlcxz2Bi^FJ>isaUE@MqWS5wy8-dv z7ReB)UDDg3Ie$$uPod+`GA@(fy%ZThS9=)NfnTxrJJ> zoV!_W-6@xAIgRPdmD~Co-UAK&EpgzDx}M_P9gVY2=U&!Ju2k_eI4{@BjTQ&ToWE;y z==VUp2-!rR#f#tS?THtuIk8zD(UU9aDQ0hgxZ?H(C@oraXT2j9Ww8;Gt5L%?Tlatp-vxj`USC!0tM`h z@tRg!-=Q=UqtO%5;D^;thAlMe8DnCQO$F!Z8OsRbmn?U8mKVxerf>uZdd&8jwtbEg zb!G%xj@m}%#ywrFN#(&VIFXK(#b`KZV8`Mc>jWqTvQPy`VObBd<5X zd>13A`SUnoMko1bJ00rnN8BJsdixRETbB7Q-X!QP8|p2~-VU&BoW1>(Z9A#j`&nl) z)OIq|b`l>$zx5=fF}h{Kl`{R=b?%(GnF!xxd9#sl^?!bfF;sy3YaCy5&SYh67O0{z z)sLj7=1P4^(<#x5E&^eb4#_1t=$AZX1*B9UBUF`=Pr=}hvQyN}&19nF%lmM7CoTcg z3_>PZ~|BM|{?F9n1X8y&n*s5f7&uZM0ab;v)7&d*y?PJ__Wv+VB*826X!z@O}o zB`@pO=QOVh-GqYMQZ8bR;MZ5KQA|aNpWX#63i32eT5`C7T$Q=& z8Wt^k(CQ)a6=poUn$1G4-L6+}m$|g1Y|QS9EnctQcYzCb#9IA!rMA3S&|kE$Tz*(T zxQQ_nz^4#czGr5oEN_Fy(C^P*FXM z;bwkgOf3*5%I9-^z=STV<(hB;gf3rcH}UO4byFCt3RKJwN4*_yp5U8LI>Szp zT5|oHGBeQpp=4;88|uoWT#LXp1@)FylJ~BnkxYw9BG6BLZ{1!0t}4h)bUCfk?`FAKw8xj)aXNJ#?^O^t+beA*|ZhI)o$f&K4 zVcACpclnL4RGRS76@h83TtHKepusf7p>eeI-xBSBz12-KnuGvFAq81KOOa&Ef~tU$ zNYCdaqUEj&uC_%O6u_ zmd8>5E;WH^boXd1=;)aGa=orjsM%rUs%}qcr4bMP`CP2 z<7;D%#d-x@58k;puW_hVb`Gg z5^OdHUt|U%zxIq?%_l<*r2iB4vz@X&G*xZlSoXIhSbE)8C6RwDb(57yR@A{c9%C&e52ve8=Y0{vltPc z(UWM2w)rfV<0+NasjLCF=TuF0@Km@^|N7;4wQ~Zi&v7#x+BvVb8s2U|@`k4Y2|n3* zuA&jX?e8S~oB-CBM)e9)C^S2n+c5eVBSj5>-K=U&Q_p=~wP!K!uWQc!g4%gl?L4A( z9#uPUQ|$|?of07MFa@x zqMfHhSux3aMz!Z4k50GWq1u|`p1?cl(PUbp5P!-*Q5hKu07>+3cIP6Sj!4td-A$j~ zyXmuRIwnoiyPH0X8T6FfZjPol0OrVEXEXulyQf%UD+62X8hriy^27Z1 z^G{QQcwJMTOO;}wRBup{m%ChseHV>cmp}9k`1gBHle)cC-uBH9agRqg2Zd8=6Z!%~ zS<0BB+4dQPZ?GxK#>+2PYMag3`$+_Y*qy5u)^3&xPklWIVLWU3h5zH@ANr$TeDkS@ zJtbdcH2flZ>!syo$mp1P_<^VI{Z=m*wkm6zwfo5+f3xoO+wI#_z)~2Q%dbC88{|Ng zB7&ApW#ukq%a>J}OE8ZWdxNVNuabSqgW=BqV`X$Ng+~7Cl{I_aXtemsVrtMRwhFZi zc}jJlUdZ3ZEV_+*RU+PT5qh0 z#AdBtZ>`KvZ@tQYIIWt^23>#(mE7S`(`vwERWU0SG=S}V+d{?fWpCSKQx z{8!kIc%`z+r2#7z)QFq37)WA90|O-ry7IoFu}KM-Sg7hHUM#PRT}@+AcxI&6L+NI# zv{-I5xHO8F*zo1b>T{LVt9lH5a+fbRH><7l(c9VRtt_tM75Vc#Ut__1=>_wJ7xb4! zqlIXf3(+q9+m6aIfeZfN_@ImO=UMslg3RUC^=*D`B*LS+z9oOQ^Zx)7`sMcPU0*AR zHPCfEjro75tYVQs|66eRCUxK7&zA1>DZrl}!ZY0?&JpLd{vFppiP)es=-S_ubI9H2 zO?n5NF*oC8opF74(9NbpX)iN+`~@BJ4|8S$=G3c z$eD0YIDO8PGnMFb&O7_vbnJxgJEvP`V*A{4&KdWRE+26FoIY>FJLK%sKN)9=g1#~L zNk{*Sm-Lcx+ErV9sR)4s9WE9Rb-2%~y>z&-d;WLT`}?TX^#Xql?oOT2MVZ?%j+v9Y z)r6M{)#7HA)t)Vzf*3U&H)~s&OrrQDl|&DQu%g;g8GwGM9yE$L%-TuDd)sP zW_RDOZm*Y7M~vM?&D&u|6pW)@TdFK?io;AudHF4}tL57=!rT*)g2J1co@lMG|%dw(=d>fLQo zjwBrvq3^nV1&%Ofx-kS8V6{g?zC8J5V_VbnUJ(TG* zs}B{j2O4tb^wjB>S}!;33wAdqyJ(fwZ}o~;BB6(b^xbs z+^=VELoz73do+*fQA)Q*#kq~w)q*Y$3gcb7b7*57uIGrHOcx|Wo-xAFfCs72-31dQ zDi#uuR3|>CEOqxjWhvi+vhsM`E_Q&b#l@lpOeRNkhfpsHItbK)Pg;D7$`rVtLw3P?6nAE=q-7)7CcgC4?ir~M%^Z6Q_zk)?Y3{wfEMFtbB7YdBn z<2LgY){$N?$V}MGrtklW&HPzr_A@hOGk=?zDP|7X%)emf05d(Sa36AXLhqFt z67utl7HDG&;>l|8zH0CV5lYwFY z>H`HO0Yqt3E38ruhOQ_0bwv5}D~@gkbAu_cNvr)ZsuZ&g*j$KkENg5KU>lI-C%^+I zsR!V?4!6h+=MwLQ#Ogd&A7hM)k9dNwk4~($nH$3+7a77 zGNCw_Vr~6RKH}m-(bq-y7xeOjE>`KZstwZ@W1qixrlC;K{X&ZP>#k1hhzE=dDTy9< zYuK1}Oz3)9zJOJL=!}V-{j`nPPdJt}>WDPt{|fda;j%#~i`Ho$pn{?`YRo4(dor!s z2lcai)L5t$zF&@?A&S7-H2C2!imu!_YI#6OM^GT7W2F)qjUH=g71FIQ6X`{Wvk)opXus+lYDKp6$9>Jgx$J5o`<97bVC^82ob1|Hpwaz}vA-cNj% zQc1`D4ymLo=}9M?Z+=ncCdg=xgPC;4HQSfc%p%ICym8Ia^=SqV*C8jZSS^M_vd~V~L)q)vwpK*MIa=ynX zTTRY@+Il-RL9UGXA?o$1goUPSTvPOL}jh19z?~{Wh3<=OK`7|L# zo1gOGSpdpt*|oX02)dl0My$&k%X$;${~r~S(P3fF4Ek`#cMGdpw=i@gzEvK#c~!(! zLVntAb4s22m)YC8#oC`^e&CW=M-b;USmkhPPDyWAG6Jk1 z_-Fx_*OakE4mJ{9Z9B4xI?G2TtPtGkGI^mt@L!1jRHq$dKw5nu!iRqV2!5QPZXoy( zb6omHO*+?H{2q7CI>($MAlp!QM?MwVk$UZ9;N-|1*5-N=yDj6!;V}m;9}Wm75oje$ zF|nz#(YkUyu4S7Q$er(PqH2(|*$y{o-;M9Kk$6sTL*Lao}-13EcDJUZ2C2kMosj4wNRV2 z2~ou9(g#AkbnN^ez|x;4@iO9OJj72q=`GKH%0DW9}pQGbqC15GUO>#Y5-v(%D5py)NbVd{T!4e6zvjB`lOwG6)-b$A9Z zeD;A6h7ai{y=h067*06Jv&pH5a_&l{)vDB%eF_nC+ttCcOi88ruc^gYBx0JO7JIDA zWiQA^if3T&v0En>Asu&VKRU=r<4ow^UoSK&g_~6>>q?cSiY3B|c;Gn|a@WIBZ!`-87iuwrN#n#OzBq-S2>9y%Wu$4PW z6A%tvLkQqrUU}%P|O?6O4#wmZ?zWD4n6jiy z*|-O(ao7%izf9Qy4(}vnwYD*af6%_}$K`duTZtf^E1Cj!D>tVkJJK!am7MLCR?H$G zh7fp?qZLW|1d?d8Pcrv~Gf7fQn{LHjJ7Sw){tkEx7{n>H`VjgNVY10N4XHA6j=+L^ z^^Ah?xh^^jYjT+6)0DjHYO=3*94TY@d^-k%WlcB1r&94=HuG>~k)naCvTQ!1YDYuc zQ#SrN)jrPso(8*t@y)31JF0bFtIM1QlDx)tVis^Z1^PXxpy8? zJEzso8TS7OEGZ$z{cy4L$f#*ka?sN9p)+LM_xzDaUd2)6mD;R9g2eDYOf6 zPpF!sUi079=&rskE)WFd<_slhNhK;<)6NHa9rgG%yVre;Iuf1rI8DG$SYAyY{aEKj zgV$@HRC|2~vVy;-~QUXO?x$^3@dIfo>?Wk%m)`|=rNSi|$s3sL! z^?Fsp2NvsVH!HP*1bz})8x)sN;bcVr$PT_ymarX^4e7VbUqK0?E-rS^7K@9TW}Cm7 z&x5WATw`VSeJZ|Ctx^UmaYQPG<@|TrqDoDy{)#Jgjr4DAlb?K*MWuSHm0^`it5T?5 zhvi+GWyic3VutZEvm1(@E;7U|*`Mce-<0o8ZaQz-=a*?8EuRwi?_zuM-qN0- zxhhS)FxGC0-E6JI@Dcp5EU{t*a_3}h;{4|IMoHXw|Ip^KUvUV;!=!g+&X=oxAT#M6 z6;^l^-OXhQ3})<2FYCW}@5}gzD1M20o|j$~rPVqY1!s!0Ih+5mT?3lOTQ@;8Z?Bs- zTGI4hv1L4|o6E8~i~@`8&p!|;!*7G6{xUqoOM$KOhTN1p;G~=(FXd&Ol>Y3Goc+$*oI&S|Gw6=R#=QwAAy$Fzq%-6`;yj|u5G*X|j(P{( zY3I0m)b-rA>-0g#qglm>H|oqd=iIZ-32}_Y3i2IAFQ|}ONQ4({QFO$ysSM-B@QxB? zNmE@}YYQK@OE`bcG5dh?;_m}OtoJ#Qz;0-|p8tF--5tj+UF!7K_??#4)*ldC9NEwF zo^>kK4DqNiz<9ryovDY_9t^OaAn~KlwnYr2C(xKN!IOd3)Pg-ae5q-7F3!vOMJMcN zoc|tWq+XO;R(DGmEn29Z} zP(37Imq}S}cX0VKT(|^3;8^gsQfY47_X(B&N_4aKn( z4M4SUfd+3FBVSqxfalyhfrY;bv;do@5U(3BpyF*q4pnVVQnKS*bzU zr8;SpVuDf12u3L&7=?5IrAemyc%^O?f`gP*MGaWt!k`r{3|ZmAu#M+5V&gfDq7zM} zBka={{6~?QHo^aIWI#wGF>V6?-VnRu1^BuT+)WYRry=f%5HDi0UEP+{?nx2+O z8SC4~42&>Y4~EggK)hKIr1xf7qQ>bSFIO6`h0^b}p(Sds`KkBbcQ`eoA|lL797@|W z{$!9}jyR7xGl;#-Xr)w;B*SawL;gyam7^EPSXQLO@;&W$H^HR*4=b32SVClOX}vNs z6XrV`t3aEMi_5hCt-F-bE>}Kzo8~G@zQ8%8ef#d{cMe%i6!mw=e+-#_=C1%a-sQi> zM>@XIR%@lK>HV!xT0p)rc$b*8mBym(@(!_?{_d65%3`4*F=DN;(@d%CT`8OLaR~PB7>NJ!!ew!MwYeadc9c=Xwp1f z5A)xF%RjO7!%DsJO06n9r1&>ooPE&hnwJZ$i(l=}yXFSQ-Elql$7SAu{(bZ4A9QFB zyvpNSM60qYMqcp%P?}6Hl*u5Vt#}A-(j>sdc_U>efi9BK>>iUX4(<$NItjblUOu0y zb>sZrZ;ii_RJq$nAwkik5tpXks=|QU`Wfut%WwQRRfyry44Tmlk+vM{5DE`N8UjT= z4NE2P<6W0R>?B3jbd1L{7%62}`*f&%I@F$)&Zgx!z3Nk)jpyL|Kd>uz<9E~o=0>!n zo)3?d#Spg;>Y8Nf=FLiR#=P)Th~^^Gjy%6WlS_RH*Qjp2-W!< z)8VW=ApJ{*b`4KoLr&T39SrFU|c*L|)ZzR5?P zuc#2OX~PNmu_28@!s~)DyQm1T2tCV(hP10OAK3-wgJjiXK3M$cSV%aK$5{SW-*bK8 zL1UlmeCm(-+LL zE?Egxdn%MGkTKw48LMW}fKd4|BsomD1UX-VK^G^Dxs?Lvf#?4;3zD?IsL?>g*kLKK zB&hKT*65>MhOVLc6JwyIz@nhWs)HIST_Z)<$z08~KpKC{(O*y;QOsad2Bx+d|5@`i z`ahP9O%O2;DzUAiDOo~N343sa(9sEF7zNG45EO?Rs%nsG^nJaA$HTM;aa9_mUW_7w zG(t=5$T1{I1AqZQ`%qzL!Ulwzp!0}pR8R0Q85eNL^LW0>`AlN+Uaqg}bR+j{xv-X- zzoU6%{XaKz`PuoCpJ8BLfl4_OWUx|hp3YsS3nU&_q)%isH?u`Y&+U`e&lAr(ox7-E zY^_$XE{~@pPIC5NxVMH)&Qz9iwK9%LD>SxGp3c#xp=rHI?-@#$QEP3ad-laZxse#T z;qbU!RO_F0KwQELQAYTv!uX$t(%Zx;zJqA~V~(*bGZS#p5X^%@iB%BBu}~#JHW1Vj zdou|Tl2eA1zsj(l_85!BTjh}Aq=k?Xi(%2kE+!}c4j-B3->QXB#;xftRl-Q2YlSe4 zch83i0GyfhaWr7wtvl2`MbPH?{P$b!f&L)p^B=*7_$V$P!sQ!r!93@G4ws*I%%sVQ zBG3&O!M~C0>+hfcr>OL8&Mpc$|HHWa7%o5V7(^ja*ReeAJBnZwR=aieM*dk~2OM#s z`so7U9&pAqtqfD9EG6m#PQt(9D2=54dyxM1N1bC%)*BUydLWF0Kj?^X(^DPj;I8;j zI7aGgTqt7JdgOyhTh7%Hfv}t?kTAS%8e)@J5J)*aA(){*l4&X>f=WHAmO?!d#2duZ zYuTpW=xs83+ZVm75&G$Bb4T&Ki(Ych1Jk%0u;OKD=FCt9ngqZY~9IXtaT zNs~#&14{ZyIJ1e_AglE&Q)X&|lA%q*+{W)}GP&1q7_c9V`C^(tLZj@)7em3o43@0< zpidQlhff-ldk+i-!RwR3pBeD?7&Wy3SthZazhJiy_h0QAog(6<+N@1&OA4{jxBS$$ z(N&t$ixA%8d({Jw=8r`wsmmrn`=>o?`|73;a@I>ZBhFE027zY1A%{PD?;O`ZC!E7B zMLT$BUuOipMB67y#T|%xqW-o+X^oKy>V=!mL@fM5Ukvvm^7Ow>$eNGQY%W_~d{N>Z zk-mRb)aV-O{f{6;HO4#{^A$y-Al@zD@JZ2LpA|O_?B>QL^=@@M zcWFXnn0sqJV;&2k)(E(vfd4-^2IjPKYHzaJV$0T{dsOoGYG9`RR7H@3y!V zz1{59tRfHrbsb`Q*7ydE<# z=v7MSbWM}H3FEfhH#p)?n@P>pQ0NcGDhDD{E{pAqEy=ypk0%1Hm2Qs(Ft1 zRl?9d$q4BBleiFElsXRBruJ@p_ZOp`*jiaw!0hgF9uiqDl(qw!MPl1+>itz~;bh_b zMU=dtRB(pmtM*uK`pM$%fqVhj1eA-n@Vu{y`9=reeqe({0%pGo`8IvPr4Gl0$dHbNgLuOX7G;w|HTxQGt_O&`i8_TLTUE|wU*3LZM~s}5I3V?|7ybTs8iZaa;YD>h+_ggmaV36>=&~ zY?_Hy=-*Xg+|pVZ6H~=-QW^U}`c1f%G_2G+%KH4WN#3U@U7IwYb9KPPMnTaauS2k( zm0JWjVFiRU5&K)4bC*F-OtmSRFuTf_rDH}CN+Q}4(N6PAA+N{gZTzLu{}FBpfpI*Q zqgtMZtS3GrQQw_TyyU|kUDR61mGrg%rpaM{)b$3r7goO9QCVX*4Hecl*GxukW3y0e z;qb*)UCx&Z9{ky0Ph!jffqvFFGlcX4ebUWJP25C<3MaxqzVOk2f^r<+pGHY>kk~?Y z18S{klvvl`XU#-RU8X(nl25{SaMgnQvNkd(~F@k4YCnfHPk8Z&0#lehWj6iE}XTA3t}o8GkuyMrKo#xbBlaO{=-%dN3C)#k0VR+gI0i+|1QVi3a(?_ z>b_%#;V^zS6Y)(kBEyDpL9#zW3 z{c8KBh#rwb*gaeTa3rfwf`(|&oAx!eL1~Jm8V|O}zfYz!yZf6nY={R;B>mlWjNmUV zhkwd(q-o8jfPvcDaUhaoeIlZ&V>H@BqQw^P+TEknxagK^4=LUKUUzvWfF_2Xxyw-d zJS}7(;!(6@P7N8Q&-xH~I-svJ4tgDkdTaT;YB;|$7A@Mj7S~@j7e~ zQ;cqJO#3cZrtx^_R)SWI+Xz(SVi;oY(?EqWMv|HU4mGEi#e!1}1bs)<@n;8g!K3EC&h-@-z7Zu2lmaL@MW6-i55pA>1Bz&Ab}sbynDu zJJwRiet=o4etxdm5{rP_R@S3u;ssmR9Q$SJ!oYyCBHGwlBP@X80M?qSnuU8HwgNt+ zy*mH$;{3&50ieZ+vP$?L%LnPyl>W`QMfadH!hldOX&^i19Ci-szb9Y;q=D>l;f`RI zp0bqtbew_H4Jhr1MQIGHoWNgIf*rOQoxq;IoHYj{xhDUX4S6_ej!>4!A!wmtbyf~L zZrcNnwmuNkkofW&UliM+s-jIr^ewjo(sY1d;SpAObfgIo5H5~)6c1TzzdnjqsbrQA z2U#Od9kwU+4DV$T5$-=08X5p>s1XSLK@oW>Lf7HF53tq`9zrxlx(v2yb6oO_@ToOm zmE1i1Ffx|iL+w(}^G^@z_DUr$>=4?uh63_5HL_ysB!@EKI&2gyC0gX^!D{r{!f`?l zl=3`*$AIK?FtZw-&&f(L#|DL7*(@2HAJuft@iu*e)NZ=a`wvHaQ6uxXL%_XvaaL_j zxf)Mgeq+pqCn|kG>4`eQ2#t}IHf30wXs%c%rop9{@5<9Phv zG-v6K8dqaDfrkg;$e476o%4L$B;m$59e>ZG&ayzPS-RHj;~6=QayC90gDuKo#Jt@2 z8c+XU*!X>SVdIDOo3Dm4=+vr;Q>wIo%l zEG^j%kp!KA@S?9a3Y99Y67x;_S+{HWtp6T){{feu#pOTZ@^khP+trGA2Q-=+qKD!@ znk~F*nBKYYfGigyl%uQPqS+udlF;nl5WNxiJ0lJ}7N<2Oa?l0+aY3_#83dj5-mO`^ z0q?M;Pf#|XsT2gTe8}Ao*3jMW^*Mu}WZZN5@36B^_cToE<`D9olx81cr2#KS(lOYX zz8(vK>dY}|Zpbt_)-5y66Q#W%pe5n$*9Pv2lQsy4xpOTK2_t56P@@KZlS2I@{Sr4Q zp^CfDIV3l{Ezv&ANC8PNac1XrG3DOlGf+*ka`P!{k?W87gx@kzt(DDY3VgTb^o1A zI_wiHlQWN%2$?(_4>RthgL5}<{>35Zh^CP#SQs&@g@T3t&qV8K1Pg`&CLyVD5R7VC zt~K)MjfCLR#Eg+ZM{x8Uf#n>nUqgInTAb#xIwQ~e{Q|gg!R%r z3$5^Y5b=&Sm=en_4q9P|l8Al~rMDO-RTHRS>>(c5_!-78ou^OA)ox&4yiEZ1JEM%;@1Ox9Lh|!jN+N@Bn z&NB%cDK3c4D3)R~LFC4q30p5w851@tV~>r>*c$}cYW!FvkXFfylE-2MVyv|Eu;<$3 zkMv@mGa7KN_1C#Q7Wsfhj%!iEMG`VD3Y$k8e8UumZ-sSMU8J`jUnHvdYFPksWBp!*{m_bom!)BswkIA zIDC(zZj%t#W5lRmazP3UHO#lXE6T@7bGD@>UQ20J(%p~qI)Uq5hjmY)+xnX2sS z6y;lN+@h_+;<&ZFp0;6D+OC;@UCLNZI7HI1Pd%V&2UJT=?qe&d?1xR!O-xiK`$goF zBRsPw0i4qMgD1?nobthxiphVBT9jLr@y5w@ZRV+A$-4Qm{v>{ZTSKpEp1HGYF-Im%LNRATLn1kpk9HvO@ZW^+!f z(iuEm0*aa~o`R7|=`eWk(h()vK+R1U)4|YVat_;_+;G$` z#@(w=Oy^gR;(P=Iq&kRzR0y6lz&KC(59Fudp0j3kBF@s^&Fb72|DR)ZPV=1S5evb7 zE{@C-SSN7I>ZJsGKc&JvrJ!_-(g*UwB|46lPC&SDSM|z*uAOIZ0*+k{V5Vz*&(v2Y zmM-F9F{k@xF!l*&l~v$LXq0E?#loe-vL5u|{KXEt7dfy|G&y3a`a*qECkK?}`k?80 zR!#q8fbyxLBpD81iaZQixQDB`pU(6tt9cgE5$}#?koSI$IzPQ zu|iDNUar)dm9$ThLhM^1Q+mkK2EfFma>^UxvrD64M!(@~GZfLUJBIQx;k>(AzQd*WKmrA|L0%0e8sDI`7au3^BaW0e4#WoN`Cq z6L5YATALO_PB=Y4L-35QgJT8zoDtX5_K>&Vd7`slXO!1x_3u&L9#6PB!{b?lSSDQl z4cBfjF5s!%i>q3YCCHD{#g-0EtIKlm9WAu(xOP`<;WC8_je>sxtK$E}c zB>R)8q$m!HN3$2;8jjqx-3A;%J*je9y~+zQ;dg?_^6CerYg%~5roJ%vIfW_|#m9c$eG zxTH`<*OScKcWmfiIMR7$<@!=o<3Zem{byuzo&>IUeKXMBs8}TMGw6sw4)!s{XY_LW z!D(s0-cw(h&f+dUW4aeO52+ z8f~{6d$g#iR~4xQq0pi|h5~6Tm_d3-I1Q0IQvyhlGggMs%fmha=AR@Pia!dHPfnuT zjb%EVU&Xw{511oXfgN--31!gHA*rGt8B>Ioq=F@R$@gK99U5%Ts8^~97rHKoij~Fr z?#|*J^S7Lza17DD`9Q4UNkLpmSQB_nB^@SJ1^Vg~Lpnl%@|yFSn{f^Or+29Y1q{e2 z(l&P=EJ5=3^y6{~@};i!ukDWlW3) zQRqk_F1TB67%rhrw8>8U?TvvYa^v}~N<`?`_O>r<)ugf4^ZU%0?JD>E)`zKM6eg7t zKP0&sput8G`?na7Vsp7aVYU{O*!AQ z6z2#sA+vNb`-FVuQ*jO5>}S|#hq{L^WAs(!Wu`uhHq&Zr)WHPolL?49u=S8nG0wv= zjnzjq4~yd+S{fx zh|3;VjZb>WJZNk;hjxyt+9zn8(g&-Nonvg1qnuKIw&R?TLzG7!gL0sKoDY#|Y5T@g zorByJQ-3Nt^nqP9vXPfK0mB!uvE7+59|d9BdpNJU!VDjMgmKf8kj9o=gTPzIpnzx{ z2c2y2`3!@*&!}e*l0M0!1CFxbB#dad@J=y><@S(W-KQvo9LAEJFddyHseL-K>`7{$ zisl*u{Gn*BC%IX4t;@LC!{x@2t_wrsT4^6eHsHYc#(s1435KB<|1t>jA zql6AW*(*R%Ae8}yiOaETA%mP1m?^?sMs5L3dp@?ZAmiF)TwvO2qeVU;^PTSivLcUKcwfn>Z z+OP36`DIXvFhQewpO$QfqWayZE0h7#qN&x`EVecqWojG@rS;QKi}f2#uxMVk1pNR6 zry@I#tB7R%fPd@xqly1*^WuM#yt9^RkmK_x|D`A%>~8)cTqv%8A1-an&Pb%X`ev;p z%+9-g#st=Oq79%9gF*rd6KEyD1F0~XB5nRCE|_1VXDL+*HFGF*{t~MCR(?3Stgywi zpG9!~Fs0hc8s^m->nrtYeOYX@aL7Vqd$Clhik|_Qr$^C(YK6B^IH}B67R&vArmVn& zN(Zct84%3ERY5?`uReb@-xABdCv8@-zGA$tXf0o@UWO(hI3lfWEjC*7&_HlDPh0!9 z8V(Z7KjTj>Cw$H~3OVi1YX*Z1&i(VvJ@kOq@^_K-o4&1IOhz>;=6|n|>2a;`QgO+| z;9W6RgN0_*nMkjupNI3G`=Im)D`3+8IUeE+JHs?jf%zVOz)Mc*-<-}l z=sn~NIit>)b42r?8D~s$ngi}5`e)2Z>z`ZBWA5W_CiaXo=_Z`9DTIm1dhc^mUdB1& z^?5_&R;SIW)j9q=s{3FI?-}PAcMk15Xb3XSs0aPPptREMvi7uVhL}0&jam~x2=RO| z?awPKT=t_bz3$q;@}6-s7GW(y8O4o9vcAHY`SKfIsrBD9>MsXlY!I^ncH|$>HiB1SSw)|3B0f^ z#c+?HL!2KAO%00a&dMcPE!@;=nUa?SJ_sr)yYB-*C)6vUqnvvMdIV>N$Zmfvlzy+A z1yZ*Rdp&2q>JmdD3q?Y|Zz@4pQp;O*jK zxuN&&VslLct^OWsJ?Lch!rF(0?`E*v;zykkw^N)#trX8T#3&c{mS{vC@?gX+IHYt5 zI~vO);buNU)%*O*yQM4;n^DU0an*5NGY{<2*K*8=<4X*wUUJRJqr#$Sf<~$#0RAvT z@%P&k`%?DAz5#P$p9z4Uv;pw@YykXz8vs8A>iqo@oPW#)=TF<<{23dZf7}M=pD@As z^Yio~Yo1MY^Y)h4Hbw@a;{fRz-KekX!d$70C@Smak~n;?7uL&-Cn7apc;%(b^9!%! zUwt9>+^e~ZFP+U@IDh_;NR_?L7sS7NA5|TxS}Y^JZoXVBS8kUZFX9M_C(J7~>T8VQ zQZz^HoX*`@sT5aom8N8~Wv*eGb{`!6t&}T^jq=hHxn2KWFaa9NOXWtnRxIb1>J1w< zrl=-g6yZ1TvA=)3DTEtQulwQ@Vq zjZFQA-mX_$%VqP>=HBn4k-5LPqc63vQq~fBY7dFtrvn#?M@ZQ5iV>_)cRn{skzyFtQx4|^z%WL)9 z=ojOxqIRyLm!H_EbnTWwMI-&*qgz%E`n|Qb_pmwZukQYKy8pr!13SnkgYmoBG&jqw zJLPiC--(#6n|l81wPr<=jJbk|1rd3UrewQ5CFci_&^1B}!^CqkQ6=nW=>DMGJz&9F zrPc)ygdS^PLiBmEp>i^P$Y0uQaHn;Iv}krbtgyAm!^~X%9X`zXFm!pIaT&<*FyK&d ztM0RO(FVzmE$HUVH`4X`)T z_~9pVx~iSiGC*Ta({|0u&1yMP@sTHTFBKZgk#(=Xj&9t{)o->6gz7Lp^DDIUuq5i( zO}$^L2u~L2@zE!8<>E>`S7>R#RA{sSnaed<=!8~!?mC*h%`~Z&n?QkuTJBMen+gc+ z(#%!swdE)E+NtOC95n>1*lCUQ@|fwR0T5T-DwfNoX72pihoiL~H?>OTVqx3BCI7Ll zI~D!@>;NT^hHrl&SLIBt*YD^xTLrD5cc~sunLS3o@A+=E3rj%kyDRI}u&x=++>+iJ zdXwPAE3M6vpzTno7(Io-u%lgEh<0)5(iH>GZsQnaw%*-YLqgA$pu@ER=(eN%>V;&Y zJ#W_ZDy>&<<4k3~!xLOpx8Y!C>wxUitLL%v7{l!B`A&#D`-tD2zlcp=YnVq34fMcj zn6)O?>Sx@sUUgmH2CHvf$V0u5gJ9A@1-nu-A(&e`7hNo~dS%v|MF?Q(jctzfwB8=2 z3L-z$mUH^6>iw`*Z?-fNx>eTu5mTZU(x#@L8l`fr*=21+pP*OmF2tkX)PT%<`Ceg# zAfn05>!B5v%TXX?=wyC#SkUDH4ZSX%dAtK=y{A>o!K70s+qh>mKqLf?N9tOrtN-1g zMjk1GI|-p3seGNH7{7+xMrn7v{CW8^D}OG?pNAv$Ufo_V6W(?qw?jfua1eplE-jEn zObB+n^0g4@KukER08$M50m2fB!ydJe-AyW(>ISBV-nEBIM00IOFl;SerqzDkk zXvI(O9aP8|YkfJa27yb&0E=o*NW&*=&P0&2H4C;~=d30v_om`;ng;xgT`~#(_AJz@ zyq(+l8npnC{vSZbf$sWLS~GPSqwr<`uy(>4fY6WsZXAQDky~FK;B~OOr+q}(bytpW zGKYhUP5ltH2EC?x6L@DI4egWAL8W)Ze1DkrrrC0TXo?O{{RvGc&z+vkLUGy;r6=^7 z?LO0SW=GBpA2BZT?L&;;bC~uup?6ME43mTa2EHCg*l3ixMKL%#LT_?w46{0>?)K1* z=qQvPaAuc)07t2&2v>{YFl5asL%*S@q&{JM;M-&N?dk8{8i&S0oc`g_UW4`j>ID4Y z(J;#cmQOLljR(*8AY}M|aq%kFS3Ue%G2ZQ?$9%}wP_yh-{T@?vFx{gZdIbaoISpog z=L|iZ&O(s@bsB%WB2Y!h5M(3%RNJIN`H^CQs zh&D$1&8V=Y?s%;O%si+z?s&DN@^7igfc)aB(M^m#Q;FK{i)j*Mxiku?r0m|F@qGvU zR-%oFq^795(!NNYYd^+@zmH3n{BVXl|~FK4E-ULp=cUcdf}?MN8sIPrs1kyGk2i zr^=Sk@(Y?0l_*kG@KP8pQP0xlH7xCU859cx3+%3=M=arQuN!PEx(h}n*te^;ezU9P zI}}Sc#S-mt2;_O3_K;q(Glv~Pf+FFajMRf4mniuaiZSe& z*MV$;59<&vn1d-o5(36ii1PBGEX#s3%J?ppnkL-4IbuoxLyWA|<(Mc9fp-LhQNd=; zh?uUKShCGfT)J1*o5AVOIL_(31Sd6-Z<}(S1fB@_P4gNBKAbh)U%n)gVQODM<6hO@ z^1Q!L@shK03^`d^GhlRwXW6wFIv`4%SopFpLI9=-OO7w}`g9uc=O`8JOX5VCx$h{u zz{v<@T*HVvGq2;lI-5SsuPwCYe5>?o*Zv=o82|9uL2ZiEgLsW{j=DWDd&^I4Q-!s< zzQSM@4@5;&gnayS@sR$Mn{|>-#!2-LrE!SkK4)J~!X0rAc~8X;czy0@JjD~K2i#12 z#2IqWdk5kP=YR`mkBpbn^`G_Vng9ipJLROD17k2+9CDKq79VTar?Fs2E$3-K(SO&* zk`3J_qEV}Ss}P#~Y64`!niThdmNAE6X#@ykz7j*@m*k`is)u~@__iOss9$Y;EuHOS zV%7C!bmnE`^2bcO9(!(4$XHD5_IKF`(cWO$0XEmY_3!uwz5_BjDLM@aS*<4rA8)TJQrxFh>%^H(m+SHdkd+PKsFt0>|(v+AvEI~u!cCIx>BB(#~BnDEPXB>)&d6 z^-R=KpYm~Cw;&eKjdua_!I3I2r8Ii{q zHKtv>5Oo6%bCdSR@J#c#}nK{qNr z#~j>&NLikBVhY=r#k<-$c32F@cH22hfRt5vbi$nWfpm`v4QS$a>w%l`!+c4zKO4^0 zHsqqWX$e802M?%&gzP`<(t?GFZc9kigHiviamda)043mFr0LVE@mN(P{tV449* z86KJdn^F?2&E30g*azOhsY*0w`aR$9h}$p-DEf82LsbxyEP&3~l_3`o67Yb#`Oj0v zZisNPwz(!8)StM9{XDQp&Ka#%fkeJU8MC1!Lqx7y z7#9%x7e&N=-+=>pGoLx~fvrgXrh4t+Ok%a;p7CCA4!IM~0q0TYT|F7+m^0>_bw=GI z&Zsw?pg#m$wEf`yKkxY9mhM#ozVMh695Wod-obPD^nTo*XBWi1zr^BQu z)WImP+rua&erJmQ3;`84E>Luop(n>B1k|7jg}-P0xs4a~h999Xs9(Za*kyA65vBhx z=!(`=%Qy239ila4_omp(l`B<=)x?c^z;3i4*7{--$_4J%)-kmg)84TzWupg%N7&C2 z8z9P{`zVhj+f3GOc5YL$jdCam_~G(0?3~2=i(ueaT*Jo$0yOGNh*VLn7jJRL>O9^E z&#LcCIClb%fJ?nZ4m{v%#kk4D0-Udu%F-UJo9T{rd(cy9!p_D9)JcIZeRkGZIUmCv-*DUe2~*qAe6;L4CQ9?!TE z%RQk9x4u|b=Vf&YKA^8Ur^O}@uj#XJU*JUOlvtQfu?K^|XWBKcizet(42wBni4tn- z5rh@@YjUUM9CIv)xJ&~-+Aw{tACC`!Y3q-bY3%upe=QVn%>bx4WI&2_XiK-mGn%IzC4DH+jraODH`%0EgX>i9{DIt-Qi{Yq?EcO*a; zkz9ao{Tz_85?gzKV-s?<*TnVeT-+LKP3%=T=l64$A-nxUJa=_6q&wN8aBkx}?FpbH zWjoI>4RH~0Va`95XXc1ry3Vku)LltUQrW}G9=kuZGM^y1qzgnvR< z^oVHgr<{B7pUVuBvGuJ^%kd>=A9OmTb!`(YvnLWP)8_VC#+9%y2q|yaK)=B83;b1l z+>xU!aVDmxvM{awVaI@TgwK{FNVo|on*N1jI)#Nz!HWNZVy?mxR-J|R~;ql7V51ZhRb5p>H0;&4*OvW?|zDwZY-|7@+`H!8w~t{+0=0tB`mMgl4jLe#N?i)Ig?*$Hy}%!1EwXr5Ub^^z%+5nPwQuS*2jdFg zmf*QK;~JGrx(RpOnRX_5+#Nz9BM|aw_n4E@^+tut!u0ylHMX6oz%1B;Z#am5?uMl- zEhiET)V0BB;h-*xcAjgt8Z*8SQE3F!zmo0wXRyhA%#VE=GYlQ?`^=#W6XGw?cEv}6 zAx7=yLB#pNfM@Jv6>%O!_kw-`0M{Py&`~L7&*~oZl>cQ*A?bB2A^g?~TRKhpMJizjP@g*BXX*XHoRptqjzbxg4&+Wm*UYNa!dWTF zLKmTo!d8%xlwD?eHG7VaH0fvSt(E(}@2D%-Q(OHb*n~$(&kZ>Vaes35Lw4;9dnRtL z_muOLGv!XZMSMyGB=p6whZ2#4n|s3tH*+JD%od1=kfdJ;Mzs2?6wkNgH8TcEN}#!j zV+SLljqHBo5lC%&XbH4AarjPfW6I4KZvX&B2nI%Zr8SQUXZd6F;7F_VPFmIaXuFi* zjgi=cntO~E{AP| zk^dw;?L9I@?W{;o89e|faN16-Nr@N+#PGB=Uz+C3h{R_8V>*r?lB{k3H}g<82c?^XK{uSXeQE*(5nQPwl@E1PmeW7X zGxc)$q^oNp3dk{48>ORnxVK{rJK@jO5m-c-Psmw29xdMo!P-Pe9Y#a2-&7vj_Bxw& zHbIQk<6IfX{grXNV`cDs5mY(hS2@v9rSsW(l7A%Lwnv!gJ!RI@44uyR>(_cKw{#y?#znf}c=_u#9$zOU^_)q8HN{-e*VxoTY7AJo-7!J`m$Bl+*XTeNJWdZw4Ox0=}|rc7~>LXKC&A zkXn`~DYL9ILI3uXR*5ppm3V|Ji$};@*s~8kH$yi zh-)!{oiexadvUZMpp)hA#q}eCg4#)Q+7A}k6jd-2rr(E3Beo(=y}AJW59(k-VC^Vx zF38OoZ;tb3#eNLezT3~~?+kGwH8 zGkqxN$K?lHtI!EpgO4i1K1&4Pjm<)%ECdfV`xFR+R|uUqLjuPa8#GI`^oOStGQYWGN+59Lv9P_N^*BUg<3N?kf_c{7`dLPj03VGK> zhi`J}9Si%S!ZLY@YGGNp{e3oW>{{rUxwUzSjXCjaWIynY)}FI5l1YZqq$ngePDM-3 zGpuc>zPzxUbS^ek=jFM4miVpX5wk+ZJqJygF|V8L?0i?og+MV5(f(|p{K9Re7P2p6 z`D~yo%fCE78yS{}_4wYiGJYgE#k2Vno>`D<^H=k;p`g@KHS{6wJIRUh;zit#tu6BG=X`+IqV(Mtwy|r zd&WU3<&MU3&QW^T>!0|Tn{{)}LFetd-lLirg%5sOmuH+2_pp=36Lj8iY?24(fO{Mf z^C@g?Uq*w_wIvZI#w;p7NFnqvkKP957l#9G+K3o=%88Xs_K<4qRa;*P8AHnp(|>J8 z!YD$GzC*ifruvN$(xf3Xf5O>5>xks!F2&N&ZuMwPBZqqqsDnP&SEAr#l?F_D5R5iD zD2KNWBLjR`4`n5y!W*)2*oP?&(Rjpjd^KNCXH8DzfpPjJF zU>ZRPBpd-YwM4}KF{FMR7Y1M*vY}2&zC|)73Ep0~c|iKPU1rhO^^lry-&bzJweTiE zHAJ5~?0OnH;Be4M5AflXGwPlrv>GGi7$)=>@jU%IBGM$l4&VF=F@oA|AW-TzAR#R$ zP(|W3b5+ntBkq5>ju~w}06SGavQmnR=nrlxREIViBmPg{0 zII)dmUTMfI%ef7`Aonv)O$>{(G#n}bhDs4s3<`#7X$+OpU?Q!eY6YJs5j@prkyZ38 z4_%U25uLH~cdmcJoFdkN3}YvcioF{p4+a2d{^2oM?(SRRkd z&wKV56wPep-{TqnqCkT+5&Sk0%A_eLYvQZ}5A8mU9u!gzF3_0dW1eB98WCR_Ij5Xi zM6nMD!R_+t`5>V7H6pl_F+b6$OcTfngXV?}Vcn+*>!aR~CYH~7Z!>0Zr<`X!oP9mo zi(pk6@x?M4MQVcC9TB~Jj|wSICU+}OjKQ&`d40v4ISnvoqK_MB?i#!i78%+If}ZN4 zZ1K;fo{Tgx;RT}_42@|lgbdeB*t3~CTQD+Dw-!ACOpUgP@2(q{T5^{P- zWB(cJ5hSemMBzwOIk6-N6}6in?q)qNLKTWvzTdU5 z=wIRTgSdPgmw%1R4>715>isZMKN5)+cR&4szDGalP>(qhAn^FsnIh8z|+@IV|zC9UBK1Yd)iNiksGT*qlJLLC%wJYRzDHeqMwvoPlzieU> z_$SfS#f6@o#jQ1BwYqjIrZ3px?0lybo#2exCDS{(1N1}11r8z zfBip8nsap$F8x!@*1uG!R&F+;M+|uu2)rHufgT3>??IIRavZVcaOFOFzXXCD14k#d9Wh4W89y{t5X>Hf34w-r*r5*f z2t0OvUXyLc@hDiP;yujZiUDHt{=eR?B{r_B4ByB2amTON^G=+XDXmLs8#{#{a8c5< zO^ZrXO@Sm*tEuC0>~Rvu$vD(OlLa^kfdpkiS%5?(0z&G7MZ2hIK~PapDNw`)i3MU& zAt8ap0tvOe%K5(kKj+*#jw3d`iFTe7NT4-yVgi7l+-b${kE~48v@+3JIoex)|3n9BTlW+J-on4B@JRB2)ZQn_&)g%_gu6*mMFL%qwvl#Y$$cdM4J` zF5oi^VRGo1tHY_wG@hiNzWIIzbR{0nU_FdP3#WT~R0|)~jC{3Ev~a42V+vAHP*;$7 zlchsa5lK)%f&Ve8nVv8@7Qv*dP?FiIFo>(7i3gZ-*F&U5l*z>^!SW<^*HMsrsAazl zrESh~5boeQ`6&mfY8Js*7GhPKSBK~>6l{(v7!Dj)EWNNF4=pWvFGHxoHR~j;NhR`` zixVtQ{x~xVQZdF{4I5a8FU}#2#}3;gKd$#hs)~tRNj6X6l1Ri4hn8l0Qt!=>p42l2 zjpV-{<9V;s-yCzm{pzPfpUKcokPs}=ZZ$8@p0hZTlRMoyzJw8;M|lAd|c9hjB_)9ky%&Q!gmDHyDbmb&l*69`Na&nC&JM0obrk}NsKX+mN%$Y5hv+<272_NIzyB(zI zFz#pgSuM&(JB^BG{&R(Jyyvc1INg3jwuZwoqxu1#7$vj^DSD1jNvwu<$7LaC_MZd| zCV-Bu=F$-&X2`p>Wn#Pfp3UaN!tCXC+Zhyn;wXPSzNxm@lJDIHB2G5CagH|fwt$^P z>*C*qp5H0o9>%0qTjj>(g4U{92CHN?1*X*6+#w9-mS`$Aw9E7xyXAowQ2%DU4R2wG zOr6XxGnaY?SOi$$uIkT+#Lz48jZH~Hja{TxY)gW{)z2tdO~Bx*S!LXOQ9fh~tesUG zSYJ}en<2(#4QcciILrvQJA$>RVF4Bk+5JzpB5(~x^411067oR68sv~WQpjF3Xbu%K z7vV^Ws6t~w)i5WPe6A$%9oBt-L&}`0fbz>>1|b_VUqo#nlzR>}Hd!)3 z*IDM-WuWMB;U2p(nJFlL^WhLi?tZ-)zv!(fg0r^Uo)~c_k`TdJRo1}iun0KbKTHnz z9I$6{_Drp)ZHN%1s&8uh}p;Yk_YmX_*`vJ)qWsRK{eZH$49op7sC@5SHcskf*-XL zR#?R2>}1Za1RhNgoGSfzjFw>t+bs-`(XR&w>@Dt%Ar0sY0Y@I;Gwq-#bHj105XIq) zsH0Q8BnKX!%#$2YDa7(hMX;olxO)zhcW=}fp+`y*FI6#b6?)#Wa5D1~E)|$*8LzsO zVWtkk26cJ)((I?_&ov0TBkcXDAT0q*zSq$rDsj-uM1KR*u75tx#8b4%XsOEyw*~Z# z*YpIRhser}HR5Wfk6e)>VlZ7^m~Y5Fk!+;uGP9ikwA)@wwXcx%w>~4)8w~x^p}9M| zmf1CDuVl~aF6E=;xyG7nT~S-G;ryAl+lJ5?cJcNri-JzEeNuv0jTZ9OG)%)2{F=~$4;t<-xhnbfMiB>d zOE%s6P}GoSNzr(g%GS=*D=<6#d=#*resh4NN=k2bXz;#D4EW|4+k+P3&U~-0gv|ni zl$#~szBenhf#s;qRLRB#D92*pJ;B5?7{K_IRY7yqc|fT1D5Lme+yIRPjr-6Vbgd!R z8fMGzWqg61nm0~4p+FyO%IB%Ia1mR$;jS~8L$v7G9(TiwfI#@$af3}Qh!~dL(XAwpU3VCeH%=H z-f~C9j68tu09cc}F>w2Bfct_Vh15oai&X!S*R?%wRWR{Q9MWL3vA|5+=Qi7hoX_V8s5t?_9$Y1 zn=4|Upd71VK&Tp`_-MJru$Oy6CUk}4vAN!`pgjB|@uO04rOPP$GJ|PjoyPT-=mEm! z6>NTp%{n&Uz~)EswwiH2Yi?J{s}7y2DW6Y1nB>ggAx=JL#>MKV8TVN5e^iQBb8U|` z*D|^Nnp6+zRU>a*QrPE09X+(18MLVB3&`_Dgm#i{`FjBo{9~8K2{V`z96sQ@P?}U1 zyDTB6c&dsCQ9GaY5NSHyK=x>yatIF?4qLf8s7$&;-YJ*@l4obQ#S>Asd&X_N;choL zwBZ4K73{1#i${ko&eV`Pog@)^y=TLNBsX~kt8O@EB3y>-$050jaWLn&K~I*T5+=1I zB+f&wlDHi?e#C;EcAZgp5P?Ubfd^KGE?~w3-HOF;olodb87~rP7H%easw0-5Q9~ej zWxIZDJFNcDqu#FPmZPa0~@=E$Lhj?M8uOw{v9FMZe(ng7#RMFHxLTvJ#Z0z=X^S07MoD%w=}=7Y%WBSjvwlD2(^V(roy{#<7ypIiFuqwk28MmZyx-d;L^K?nz;;q}PL(^X~VK`|f zuIa|-dV{qqfZ=LtW$&{JyW`DBinf!e8?XO{XY=047pJ?_6ouxiFBXl`yEal$wsgwQ>QHSxeqXsHAMg?w~F0G2-W#qSZpr_&>JK;kLi z1{-__n}1^SFKqse4TG{gQlICZT~Qt0wdP{}H<;`sbKS@NduyH72^^vEz^vkg`=HAT zfN3vk)(rrUP|)s6)muHSK+ zHyl6lKlRB}`&9kcxZ+n<;G)@d>wn}f#3;iN?!~VQ{uL13<6yYo@C8~K@jaZh^&d^v zVw8lUJ6XwV-GMp9o->FOpSec)>YNtkqatx_HZmh`^Qs7rc9!uOf~~kN5vT&^HfRG920g+e z&1wWI?FK;A9I?ThjlC{_Q3D{qnoZH^caofRWt~;SNzck`Pg25H?2LD`-_2z1Cl8s^ zC6et#6Cyf|ZtN7>J9T#&qaP-QJ#j{GP)OcI>4BS~^;R|GXmRUAq&{bT6H`J~>Jw7! zsWg|;vo0*+`xduHL^vnWNenADui*p~6K|Gr&>ymAu|XI&P@g@2n&h}XZ_6VA<3;i|6A5$VxG>;A1wu1ajuNQaK{nn1$=AE>k5mN>IYop zK2Wt8I6~1c2^0r)?H_PG6KcbJmp?1Gz7F-(&~$^GCbgOfO60RmMaQEn+fXh9cInSW zxed`>86q``d8%Y>RI#&DZ)TK|d{>GOo*eI{p!5mbVRcaG?_MMrOA)??vqC%Yk{K6Z z-}sokfg#P7D&6pk-qaNg5onThUV1sw{sD_h%N|&hiZz3n6OdduzLmg%{1`cLs#%|ol%!8iI4b?7m7C$Re(Zw4X(HJOdb~*0 z_#(4wEsX+0>l9n4)^gIdPSsxo!GFP~-y?ACq-&j0r>_;GRwy^S&IjDk2gnRidQ{@a z%u^k8C#SRn@B?gX+FdtY|B}5qcBksUvv=btCtY*OH>Z8`=qZ1JZ%&_LuGN+s*WhzG z3x=>v5pN{i10X5$HxlyG?2RB{Df&o+yxU>Tza0)oqe95YHT7EW4QIk#=G=t&gNbg$ z{6qZ5=Llom@V8em2Eu(i-WLg4tM?>OU1QM1Pw0^C~tkMcd^tfIHw1u!BH6 z>5Ya^QaQeZS0vxKmFXxqon zJ_72B)+uwaq7RH(_KEM}6SGk3UFLGS0;zCNo8U{l9;ot40lq!gGQBRWthUahVEuqS z{`g}LJaB*G_=Al{9zOQaC+bW>coLg7Hh;n94m{jL*nAC}&*9Ngl%0t)jEJW{h3{xv zeht!v8FSU;bMqg?OK!tkiqOePc&zMSBzE8(fF69he7O8>Fkb$8`E>cqruA;{gYtvr NSJ?V}d3X8s{{hZZeGC8q literal 0 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 Yy&EcXdRg-J0_!jkislUA(lPUY0RpJH+W-In literal 0 Hc$@BCG(n5>kD_hT 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 W`IdNb>bIwUY3lsc*QVB{=Ke2YALJzf literal 0 Hc$@?|#LT>+{QMIA;{4JgxJW^zer|qBYL0#}P)A};W>spDetdjpUS>&r Yyk0?N2?x+b8=#8PoK!oIy~QAV0NghyMF0Q* literal 0 Hc$@sF1I~yFLApDG4P`Yw>aSg!1+4O2ehUZ8h1BSL7}2XdeL|~P8yqEeb(6eV)K#f zJ_*Lfd76FGcov_HRnmB#g{d3=g;!JHi^Usg_9hp>Fb+E^i-RQoS!KG5%%{Z?+As<7 z9Ai|k7m`<$ob1y4HHrn8GAB0@mnG5DE*8=DdQlt}y`CO$0nK@k2SriNP(d@CeEYKB zB$nCahiF>o=}@(BIpLsnnP!806ojgkhvz|jk)>(T%F}T+^Nc2~VH&BVmCpdQqM!&i zMiX8{oZ}2CESN1?8_0j7_#=wGXotWqplKT1<+yD#~AluSj8{yJ8?IvNt zM>La>Vq^zFlB%CWWMietsFFF4^Y4NLUGpNuV?y>& zm4h@J2E{T>;W8n`gAs|R@ai#*Q8+NQiSPW18aM{VY?pltW#66m#Z=B{CxLxZ z(RU4rn52}iyBh_`~UPQ%2XxS*a za$2(6z^fFnIunp`uAN>eZm6Gv#II9d&B%f~is}a|N3~^(st2*)ziISm_1h>qi|MbB z@r>HTNn2gcvEuk7*_SlzyEM2>8>%j=a;?;^&UQs_GQud0dLNeR31(0deJG-? zX>y)k@xi2XG#-xfrahy;WtPmk__4F^AMP9_YD(sg{R$II8Ocp9z9Z3I-5uYX>oa-o9131a*pgoh3c?jGm9ktQtPXBV4P}Oc51)=nb)O5Cl@}E>Rc_ zmUq)pnKyG~-q05bJ=JGv;|LE+MNN3J-F#@O9ezKhA)a09Go)`(7aiJr`v*JEk578{ z_V#-;V!4V9Ud0Aa-Op0`ud6JxQk&(}s!1%(;m2e?d5wg5eU@!w?>JG9iE=*Z98t$( S&c(ZGS6%O&>YBHRzv|y)hH2pd literal 0 Hc$@x zU*m&+n9oMfIbGL@7-MvsP4C&=xj%ZobIy0~QNNV5*~PEhHgq2q+cLKJGYSWwj#7cT z0-Z8Ag8IG+brl?yl-t2L2q6Liue0$S)N|nEPK-Na;EusAPRYXufMb9+^*lJ^;O1F7 z(bJBDQ%JR1Pdfq5WU4Lpv^Y@%rvwcJqE8U8v9-z>0x*k0Ta8>xx{e+O`qQ?r&oAB5 z7v|;{HEr2y%l$CAuSem*tmpVk^P2Y!pG`TA>+Bbv-SA!RH{-pQWjCaT{hAwjmhZiD zqn^VAwny~6t0-J_m>{>IeFz^NLLHT?qD~HsT7^7pi|$GV+bXRtCGI`~FnNPog@!jP zG(qO58wM`h5ch20DLfdv{%(b=VG%z^QQZ%lZWZU+jp|_-HDUzeR%3hL@`5M~Wi<}l zQBTwARGXpW`qgarzV7W-M^50Lrs)NqG|kKO5wZ*vTj?eZwP&P14-De~Ujaw>D)3SK zfX5({Ddg0E2%;Rt4(2Dlr!J;xKz*qhi8b7q0J~Rfo%qXPx4-N!n z#Y_)`sIV)Ocm-C|HBHVN)5LAsKK?bxy$qd~X4VbPM6&D>ZBC!gD}`JkC(mU>8!WHn zFL-4@8a`HX&<5-Wf`20m)$j8Sp&rwbMiVzZl3CJm2uF}_^x2!IfKXBpXHS4QK7}z! z>WzjhvnR-6Op+*)7(O*9L$CKyLoKLGjqbfO8fwT=W`P;tDcu=9PZr?kbNP=_j1Of( zurnf(-2GdUZ~@W|MumYWaPNQO3Ke#9(0`32TzTBVi_Wu8;fj)SfL)%4!Bbla-enTV`#| zSYO##udf-BqP5;^g^^r~qA=pqCOLn}mr17adh%#eAPj-puTlblk{3m6C8a2)CW>N{ zozj%DgWcgb8Vo`htwqywb literal 0 Hc$@z9aR1}I3Vj&yWjWC&f56BX8-o*AKwH}UIyMz@y>oi z69RP63J4{{0tOPg5=2;ouE|~l;tHIECUh+bD{zb93lLh|ScG$YbpdV#bgK|9veO2I zZ&um4#BH0~4!4)MU4sbt(Sci>@DbpAo#rE2Qwxo~n<_t7VIvtfo{i(i=4T%@wm#nc z)V81coQ6E*~kx6D+@0CXy~c4B=CpoJoQV@Xwn)ap^97C3_vUN zbAMwr;YCCl&Y*&v*`l?9{5OivXDDt2H6m{G4M^9CiB2x5uV=swKz{+!t-@;}TpFj{ zBrN!dW-?NY?7)vRl@mR?$2*-)d*}JSceMX42ldq?&PUW7PI z$R4V4kfZ}YU#2N+CS_HaavAS{I3fV1Cg&G4Qvum3bAW$>Xt)+IWTLJMZY0q&mBhmK z)pt6yLZN%#KZ8>V*9KghFg0i}BJmVnKA|yk3#KOVon27_$H18FvTvd6yYqfMl{4B& zV3$;MZA~I3Ddnr@l_^*xu3Oa^7v*Y@xfVTAKyudGB0g9_x1tjj6*`WxJhwPUDS+Li z(2<(Bj@D-mBDu6F*J;>Q7RD0G(vo$#E*)XvZ41j-DRS5RS_mlNs>k7GA=2pskubb3A??D;Z5E=UMVhi;EC+cE5M_jx>bi0-qM{=T z*(kX(TC&~1s}!(06OeMQoeUK>)DM2_)~T6A+C}UBO zP!pt5=RCdQf==gfJQ!t7b4G#9Ea`ReV`twz+&Mn%?z<%iMX8@#ky+B>6!RR@3>K%d zBOm{d(Bs4pOX%;Ap*`cit(llByu!_eZBHcJwU+CdDUw`Y_tL7n1WXGxDaqvt&`tD2AT2-m6#ricnY^afZs2m&c~ zmne(|%e(HV%$vC~Z|IAJp6au-v4n%Aq9z>KZa&u44!@t00MD-V8PeCNiw^C*{ezts z$0y#sz5N!ASgvA&SFyoU_tJ#^7gd&7sm*d~RVP-#;rnDhctFCuKFhYTcO0uHL^&UH WmZ;+~XX9NptG4q-bAK literal 0 Hc$@^^v{7o% z)?iQvPf$P5p{;|blk#ae3qpucz_Vh!1nm-dr5)qm49FRHiBrn(4qzMLdAkhWEXXoz z=Z4x@@G8017;5Lho6oh?p%y0^;MJg`LHq$iHn!E+LjV?07`I~SDCwC|Xx{Ay=F;Ue z=J|6=7Y$?C>8s5szG}wN)}rqPmzNCx8$N4l7T38CeYX=x?st=op5u0uf&G?@eJAi= z%XsK8f$b)J?>GvH4in@yv=8BPDet8Uq!uWeM^<`xAV%0H@aOkpDt^aQl+H!6+{~^ zuhcJiWkDW3R&vnB><5B>stDEZ^9`YH(~(9K*L;#i(s2l_6@9x4CE$7O?f-5Oq1hK?Q zPgagj-k2PAN{(bdC|>baqv{gFl$<1qLs)W(RE1Qd`g0kSMpY>hO3!9vnM^}3s7xCj zV!Clzms~)(8YapK0@E?E(%QsgwSa8~en*o%s$yZT zD%RL3BRQt$i8hJ!A|F1=^S!KPHB^^&vm5g{A8p%') + + # List of files contained in the directory at the given URL, ignoring + # any "?" / GET query-string locations given: + files = [x[9:-2] for x in pattern.findall(page) if not x[9:-2].startswith('?')] + #print files + + yamlFiles = [] + dirs = [] + for fn in files: + if not fn.startswith('/'): # Ignore absolute paths... + path = os.path.join(object_uri, fn) + #print path + + # Keep list of YAML files found... + if fn.endswith('.yml'): + yamlFiles.append(path) + + # Keep list of directories found... + elif recursive and fn.endswith('/'): + dirs.append(path) + + if recursive: + #print dirs + for path in dirs: + yamlFiles += self.__parseLink(path,recursive) + + return yamlFiles + + def __getYamlFiles(self, local_dir, recursive): + """ Returns a listing of all YAML files located in the given + directory, recursing if requested. """ + yamlFiles = [] + dirs = [] + for fn in os.listdir(local_dir): + path = os.path.join(local_dir, fn) + + # List of YAML files found... + if fn.endswith('.yml'): + yamlFiles.append(path) + + # List of directories found... + elif recursive and os.path.isdir(path): + dirs.append(path) + + # Recurse if desired: + if recursive: + for path in dirs: + yamlFiles += self.__getYamlFiles(path,recursive) + + return yamlFiles + + def equals(self, obj, compare_time_created=True): + """ Returns True iff self has identical attributes + (numerically) to obj (no extras) """ + + if not isinstance(obj, Object): return False + + self_keys = self.__dict__.keys() + obj_keys = obj.__dict__.keys() + if not self_keys == obj_keys: + return False + for key in self_keys: + obj_keys.remove(key) + + self_value, obj_value = self.__dict__[key], obj.__dict__[key] + if isinstance(self_value, Object): + if not self_value.equals(obj_value, compare_time_created): + return False + elif isinstance(self_value, np.ndarray): + m1 = map(repr,self_value.flat) + m2 = map(repr,obj_value.flat) + ret = m1 == m2 + if not ret: + return False + else: + if not self_value == obj_value: + # Return False iff the different times are important + return key == '__time_created' and not compare_time_created + + return obj_keys == [] # no more keys --> the objects are identical + + def sizeof(self): + """ Recursively computes the size in bytes of the given Dynamic Object """ + sz = 0 + values = self.__dict__.values() + for val in values: + if isinstance(val, Object): sz += val.sizeof() + elif isinstance(val, np.ndarray): sz += val.nbytes + elif hasattr(val, 'dtype') and hasattr(val.dtype, 'itemsize'): sz += val.dtype.itemsize + else: sz += sys.getsizeof(val) + return sz + + # Automatic methods for accessing meta-data + getters = ['__object_name', '__revision_number', '__revision_id', '__revision_source', '__revision_tag', '__time_created'] + def getObjectName(self): return self.__class__.meta_attributes['__object_name'] + def getRevisionNumber(self): return self.__class__.meta_attributes['__revision_number'] + def getRevisionId(self): return self.__class__.meta_attributes['__revision_id'] + def getRevisionSource(self): return self.__class__.meta_attributes['__revision_source'] + def getRevisionTag(self): return self.__class__.meta_attributes['__revision_tag'] + def getTimeCreated(self): return getattr(self, "__time_created") + + """ + __getters = [('ObjectName', getObjectName), ('RevisionNumber', getRevisionNumber), + ('RevisionId', getRevisionId), ('RevisionSource', getRevisionSource), + ('RevisionTag', getRevisionTag)] + def __repr__(self): + meta_atts = repr([(x[0], x[1](self)) for x in Object.__getters]) + atts = repr(self.__dict__) + return "Object(%s, %s)"%(atts, meta_atts) + """ + + +class SignatureException(Exception): + """ Exception thrown when a data or method signature is unknown or invalid + for a particular Object. """ + def __init__(self, value): self.value = value + def __str__(self): return repr(self.value) + +class _IDLTag(object): + """ IDLTag (aka Interface Definition Language Tag) is an abstract helper class + used by the Factory to define built-in tags used + specifically for our IDL """ + def __init__(self, yamlString): + self.yamlString = yamlString + def __repr__(self): + return self.yamlString + +class _Reference(_IDLTag): + """ Helper class for Factory: Objects can be composed + of other objects, requiring a Reference to the other object. """ + def __repr__(self): + return "Ref(%s)"%(self.yamlString,) + +class _Method(_IDLTag): + """ Helper class for Factory: Objects have methods + associated with them - this tag tells the Factory that a method + signature follows (in dict format) """ + def __repr__(self): + return "Method(%r)"%(self.yamlString,) + +class Binary(Object): + def __init__(self, binary_type, value=None): + self.binary_type = binary_type + self.value = value + +import Lookup + +class BuiltinDtype(_IDLTag): + """ Helper class for Factory: Object parameters each + have a certain data type (either dtype.xxxx for numpy compatible data + types, or one of the generic python data types (i.e. int, bool, str...) + + __addYamlConstructor in Factory registers all of the tags + listed as keys in the dtypes dictionary.""" + + def __init__(self, yamlString, tag=None): + self.tag = tag[1:] + super(BuiltinDtype, self).__init__(yamlString) + #print self.tag + try: self.dtype = Lookup.numpy_dtypes[self.tag] + except KeyError: self.dtype = Lookup.builtin_objects[self.tag] + + def __repr__(self): + return "_BuiltinType(%s,%s)"%(self.yamlString, self.tag) + +# Register hexadecimal representation of numpy dtypes in YAML + +class _Parameter: + """ Helper class for Factory: Contains the name, default + value, and length (if an array) of an object initialization parameter. """ + + def __init__(self, name, hasDefault=False, default=None, length=None, classType=None): + self.name = name + self.hasDefault = hasDefault + self.default = default + self.length = length + if isinstance(classType, None.__class__) and not isinstance(default, None.__class__): + self.classType = default.__class__ + else: + self.classType = classType + +class _UnresolvedType: + """ Used to indicate a data type which has not yet been parsed (i.e. for + recursive data-types. """ + + def __init__(self, yamlObject): + # Either the name of the class we couldn't resolve, or a dictionary + # containing the name and a default value + self.yamlObject = yamlObject + +class UnresolvedTypeException(Exception): + """ Raised when a !ref tag is used, but the reference cannot be resolved """ + pass + +def get_class(kls): + """ Returns a pointer to the class instance with the name kls + Function acquired from http://stackoverflow.com/questions/452969/ """ + parts = kls.split('.') + module = ".".join(parts[:-1]) + m = __import__( module ) + for comp in parts[1:]: + m = getattr(m, comp) + return m + +# Aliased constructor & representer adders for easily swapping between Ordered and non-Ordered: +def add_constructor(tag, constructor): + #yaml.add_constructor(tag, constructor) + OrderedYAML.Loader.add_constructor(tag, constructor) +def add_representer(cls, representer): + #yaml.add_representer(cls, representer) + OrderedYAML.Dumper.add_representer(cls, representer) + +# Implicit constructor for _Reference objects using the !ref tag: +def __ref_constructor(loader, node): + if isinstance(node, yaml.nodes.MappingNode): + return _Reference(loader.construct_mapping(node)) + else: + return _Reference(loader.construct_scalar(node)) +add_constructor(u'!ref', __ref_constructor) + +# Method constructor using !method tag: +def __method_constructor(loader, node): + if isinstance(node, yaml.nodes.MappingNode): + return _Method(loader.construct_mapping(node)) + else: + return _Method(loader.construct_scalar(node)) +add_constructor(u'!method', __method_constructor) + +# Generic constructor for any _BuiltinDtype +def __dtype_constructor(loader, node): + if isinstance(node, yaml.nodes.SequenceNode): + ret = BuiltinDtype(loader.construct_sequence(node), tag=node.tag) + elif isinstance(node, yaml.nodes.MappingNode): + ret = BuiltinDtype(loader.construct_mapping(node), tag=node.tag) + else: + ret = BuiltinDtype(loader.construct_scalar(node), tag=node.tag) + return ret + +# Register YAML constructors for each builtin type: +for dtype in Lookup.numpy_dtypes.keys() + Lookup.builtin_objects.keys(): + add_constructor(u'!%s'%(dtype,), __dtype_constructor) + +class FactoryLoader(OrderedYAML.Loader): + """ A YAML Loader specifically designed to load YAML object definitions + (as opposed to actual instances of the objects) """ + + def construct_yaml_timestamp(self, node): + """ Make empty timestamps (None/null) acceptable, otherwise parse the timestamp """ + if node.value == u'': + name = 'YAML_DEFN_LOADED_INCORRECTLY' # in case we forget to fix the name... + return _Parameter(name, hasDefault=False, classType=datetime.datetime) + else: + return yaml.constructor.SafeConstructor.construct_yaml_timestamp(self, node) + +# Override default timestamp constructor: +FactoryLoader.add_constructor( + u'tag:yaml.org,2002:timestamp', + FactoryLoader.construct_yaml_timestamp +) + +import DynamicYAML +class Factory: + """ Load a YAML defined python class and create a class with initialization + provided by this factory. This is intended as an abstract class to be sub-classed + to enable complex initialization on object instantiation. + + Factory subclasses should override __buildClass().""" + + def __init__(self, dynamic_object=None, yaml=None, typeCheck='strong', parse=True, revision_dict=None): + if revision_dict != None: self.revision_dict = revision_dict # Remember for when we build each individual class + else: + self.revision_dict = {\ + "__revision_number": 0, + "__revision_id": 'unknown', + "__revision_source": 'unknown', + "__revision_tag": 'unknown'} + if parse: + if dynamic_object: + self.parse(dynamic_object, typeCheck=typeCheck) + else: + dyno = Object() + dyno.yaml = yaml + self.parse(dyno, typeCheck=typeCheck) + + def parse(self, dynamic_object, typeCheck='strong'): + """ + Initializer for a Factory, converting the given dynamic_object + containing a (text) YAML object definition into the corresponding class-type + with initializer. + + typeCheck parameter can be one of 'strong' or 'cast': + 'strong': Class initializer should raise a TypeError when given + anything but the correct type + 'cast': Class initializer should attempt to cast any input to the correct type + """ + + # Remember what kind of type-checking to do: + if typeCheck not in ['strong', 'cast']: + raise Exception('Incorrect input for typeCheck: %s\nExpected "strong" or "cast"'%(typeCheck)) + self.typeCheck = typeCheck + + # Get a list of the objects to build: + if isinstance(dynamic_object.yaml, list): + objects = dynamic_object.yaml + else: + objects = [dynamic_object] + + # Generate a dictionary of classes from the DynamicObjects given: + self.classes = dict() + for obj in objects: + + # This loader breaks nothing anymore #everything currently + loader = FactoryLoader(obj.yaml) + #loader = yaml.Loader(obj.yaml) + + # Dictionary with method and data signatures for the current object: + objDefn = [] + while loader.check_data(): + objDefn.append(loader.get_data()) + loader.dispose() + + # Parse the dictionary into a class definition: + objClass = self.__buildClass(objDefn) + self.classes.update(objClass) + + def parseMethodSignature(self, sigName, methDict): + """ Returns the python method corresponding to the given signature + (given signature should be in the loaded YAML dict format. + + Override this method for recognizing complex method signatures. """ + + raise SignatureException("Object abstract base class doesn't support any method signatures.") + + def parseDataSignature(self, sigName, sig): + """ Returns the Parameter object corresponding to the given signature. + + This method should be overridden for recognizing complex data signatures + (don't forget to call super(sig) for built-in data types though!) """ + + # Is the object an array with explicit default elements?: + if isinstance(sig.yamlString, list): + #length = len(sig.yamlString) + if 'dtype' in sig.tag: + default = np.array(sig.yamlString, dtype=sig.dtype) + elif 'binary' == sig.tag: + default = Binary(sig.yamlString["type"]) + else: + default = sig.yamlString + return _Parameter(sigName, True, default, length=None) + + # Is the object an array with length and default value given?: + if isinstance(sig.yamlString, dict) and "len" in sig.yamlString.keys(): + length = sig.yamlString["len"] + + # Shape is given as something like [[],[]], not [2,2] - convert + if isinstance(length, list): + + def get_shape(lst): + """ Gets the shape of a list recursively filled with empty lists """ + if lst == []: return [0] + return [len(lst)] + get_shape(lst[0]) + + if len(length) > 0: + if isinstance(length[0], list): + length = get_shape(length) + else: + pass + else: + length = [0] # convert [] to [0] (numpy interprets [] as [1] for shapes) + + + if 'complex' in sig.tag: + imag = sig.yamlString["default"]["imag"] + real = sig.yamlString["default"]["real"] + default = sig.dtype(real) + sig.dtype(imag*1j) + elif 'binary' == sig.tag: + default = Binary(sig.yamlString["type"]) + else: + default = sig.dtype(sig.yamlString["default"]) + + return _Parameter(sigName, True, default, length) + + # The object is singular, with a given value: + if 'complex' in sig.tag: + imag = sig.yamlString["imag"] + real = sig.yamlString["real"] + default = sig.dtype(real) + sig.dtype(imag*1j) + return _Parameter(sigName, True, default) + elif 'binary' == sig.tag: + default = Binary(sig.yamlString["type"]) + return _Parameter(sigName, False, default, classType=Binary) + elif 'timestamp' in sig.tag: + if isinstance(sig.yamlString, dict): + if sig.tag in ['timestamp_picosecond', 'timestamp_ps']: + try: s = sig.yamlString['second'] + except KeyError: s = sig.yamlString['s'] + try: ps = sig.yamlString['picosecond'] + except KeyError: ps = sig.yamlString['ps'] + return _Parameter(sigName, True, PrecisionTime.psTime(s, ps)) + elif sig.tag in ['timestamp_nanosecond', 'timestamp_ns']: + try: s = sig.yamlString['second'] + except KeyError: s = sig.yamlString['s'] + try: ns = sig.yamlString['nanosecond'] + except KeyError: ns = sig.yamlString['ns'] + return _Parameter(sigName, True, PrecisionTime.nsTime(s, ns)) + else: + if sig.tag in ['timestamp_picosecond', 'timestamp_ps']: + return _Parameter(sigName, False, classType=PrecisionTime.psTime) + elif sig.tag in ['timestamp_nanosecond', 'timestamp_ns']: + return _Parameter(sigName, False, classType=PrecisionTime.nsTime) + else: + default = sig.dtype(sig.yamlString) + return _Parameter(sigName, True, default) # not binary + + + + def __parsePythonType(self, sigName, sig): + """ Returns a _Parameter object, similar to parseDataSignature, but + for a basic python type. """ + + if isinstance(sig, collections.OrderedDict): + default = dict(sig) # Type-check user-defined !!maps as dicts, not OrderedDicts. + else: + default = sig # The signature sig is the default value itself + return _Parameter(sigName, True, default) + + def __parseReferenceSignature(self, sigName, ref_object, objClasses): + """ Takes a reference object ref_object to be named sigName, and + produces a _Parameter object with default value of None. """ + + # List of names of classes we've created so far: + #print [x for x in objClasses] + names = objClasses.keys() + + if ref_object.yamlString in names: + defaultType = objClasses[ref_object.yamlString] + return _Parameter(sigName, classType=defaultType) + else: + try: + # Try to find the class type in globals: + className = objClasses[str(ref_object.yamlString)] + defaultType = get_class(className) + except (ValueError, KeyError): + defaultType = _UnresolvedType(ref_object.yamlString) + #raise NameError("Invalid reference to module %s"%(className,)) + + return _Parameter(sigName, classType=defaultType) + + def __buildInitializer(self, className, classData): + """ Constructs the initializer for an object which expects parameters + listed in classData as input upon initialization. """ + + # Type of type-checking to use: + strong = (self.typeCheck == 'strong') + #cast = (self.typeCheck == 'cast') + + def typeCheck(param, arg): + """ + Checks to see if the type of arg matches that of the corresponding param, + casting arg to the correct type if desired. + """ + if isinstance(arg, param.classType): return arg + if isinstance(arg, np.ndarray) and arg.dtype.type == param.classType: + if not param.hasDefault: return arg + if param.default.shape == (): return arg + if param.default.shape[-1] == 0: return arg + if arg.shape == param.default.shape: return arg + if isinstance(arg, None.__class__): return arg + if strong: + raise TypeError("Incorrect input type on strong type-checking."+\ + " Expected %s - got %s"%(param.classType,arg.__class__)) + else: + # If the parameter corresponding to the given argument has a non-NoneType default + # value, then attempt to cast the argument into the correct parameter type + if param.hasDefault and param.default != None: + if isinstance(param.default, np.ndarray): + return np.array(arg, dtype=param.default.dtype) + else: + return param.default.__class__(arg) + else: + return param.classType(arg) + + """ + attributes = {"__object_name": className, + "__revision_number": self.svn_revision_number, + "__revision_id": 'unknown', + "__revision_source": 'unknown', + "__revision_tag": 'unknown'} + """ + attributes = {} # Create new attributes dict for this particular class object + attributes.update(self.revision_dict) # Revision info now passed into the factory + attributes['__object_name'] = className + + def init(_self, *args, **kwargs): + """ Dynamically generated initializer. """ + + # meta-data goes in the class, not the objects (commented the following out): + """ + # Initialize automatic class data + for attr,value in attributes.items(): + try: + value = kwargs[attr] # Are we given a value to over-ride with? + del kwargs[attr] # Ignore the meta attribute later + except KeyError: + pass + setattr(_self, attr, value) + """ + + # Set default values first (assume no parameters): + for param in classData: + if param.length: + if isinstance(param.length, int): param.length = [param.length] + default = np.empty(param.length, dtype=param.classType) + if param.hasDefault: + # Initialize array with default array value given: + flatIter = default.flat + for i in range(len(flatIter)): + flatIter[i] = copy.deepcopy(param.default) + else: + # Initialize to None if no default given: + default.fill(None) + else: + default = param.default + setattr(_self, param.name, copy.deepcopy(default)) + + # Set attributes given by standard args: + for i in range(len(args)): + arg = typeCheck(classData[i], args[i]) + setattr(_self, classData[i].name, arg) + + # Set named attributes (given by dictionary kwargs): + for key,value in kwargs.items(): + + try: keyIndex = [param.name for param in classData].index(key) + except ValueError: + raise TypeError("'%s' is an invalid keyword argument"%(key,)) + arg = typeCheck(classData[keyIndex],value) + #setattr(_self, key, value) + setattr(_self, key, arg) + + + # Object instantiation / creation time (if not already present): + if not kwargs.has_key('__time_created'): + setattr(_self, "__time_created", np.float64(time.time())) + + return init, attributes + + def __findClass(self, className, localClasses): + """ Looks for the given className first in the given dictionary of localClasses + then in the global definitions, returning the corresponding class object. Raises + a KeyError if the class cannot be found. """ + + # If class definition was in the YAML file, extend that one: + if className in localClasses.keys(): + return localClasses[className] + + # Else try finding the class definition in our global scope: + try: classObj = get_class(className) + except KeyError: + raise KeyError("Class '%s' not found in given YAML scope or global scope."%(className,)) + return classObj + + def __buildClass(self, objDefn): + """ Takes an object definition list / dictionary objDefn (loaded from a YAML + object definition file) and creates a class, dynamically binding + method and data signatures to the new class. + + This method only performs a basic binding of method and data signatures to + the new class. Object(s) having more complex initialization requirements + should be given their own Factory subclass, overriding this + and other methods.""" + + # objDefn is a list of dictionaries found in the YAML file - build each one... + objClasses = dict() + objClassesRev = dict() + + # A list of all _Parameter objects created, used to resolve recursive + # or "tangled" data structures + allClassData = [] + + for document in objDefn: + # Each document can contain multiple objects - build each one. + # (NOTE: objects can cross reference each other in the same document + # need to resolve Reference objects as last step) + for objClassName in document.keys(): + + # The dictionary containing method & data signatures: + objDict = document[objClassName] + + # Extract data / attribute definitions (signatures) from the YAML dictionary + # as well as method signatures and which classes this class extends: + classData = [] + classMethods = dict() + classBases = [Object] + + # List structured documents result in a list of dicts each with one key: + if isinstance(objDict, list): keys = [param.keys()[0] for param in objDict] + # Otherwise the parameter names are just the keys of the dict + else: keys = objDict.keys() # if key not found, raises AttributeError + + for sigName in keys: + #print sigName + sig = objDict[sigName] + #for f in _BuiltinDtype.python_dtypes: print f.__class__ + if sigName == '__extends': + if isinstance(sig, str): + sig = [sig] + if isinstance(sig, list): + for className in sig: + newBase = self.__findClass(className, objClasses) + + # Remove Object extension if newBase extends it already: + if Object in classBases and Object in inspect.getmro(newBase): + classBases.remove(Object) + classBases += [newBase] + else: + raise TypeError("Incorrect format for extending classes - %s"%(sig,)) + elif isinstance(sig, BuiltinDtype): + classData.append(self.parseDataSignature(sigName, sig)) + elif isinstance(sig, Lookup.python_dtypes): + classData.append(self.__parsePythonType(sigName, sig)) + elif isinstance(sig, _Reference): + classData.append(self.__parseReferenceSignature(sigName, sig, objClasses)) + elif isinstance(sig, _Method): + classMethods[sigName] = self.parseMethodSignature(sigName, sig.yamlString) + elif isinstance(sig, (PrecisionTime.nsTime, PrecisionTime.psTime)): + classData.append(_Parameter(sigName, True, sig)) + elif isinstance(sig, _Parameter): # sig is already a parameter (we skipped a step) + sig.name = sigName # we didn't know the name during load time - fill that in now + classData.append(sig) + else: + msg = "Factory abstract base class doesn't " +\ + "support the following signature: %r \"%s\""%(sig.__class__,str(sig)) + print sig.__class__ + raise SignatureException(msg) + + # Built-in attribute for all Dynamic Objects: + classData.append(_Parameter('__time_created', classType=np.float64)) + + # Turn the object data / attributes into a usable __init__ method: + classMethods["__init__"], meta_attributes = self.__buildInitializer(objClassName, classData) + + # Keep a record of the _Parameters created for later type resolution + allClassData.extend(classData) + + """ + __automaticMethods = { + "getObjectName": lambda _self: getattr(_self, '__object_name'), + "getRevisionNumber": lambda _self: getattr(_self, '__revision_number'), + "getRevisionId": lambda _self: getattr(_self, '__revision_id'), + "getRevisionSource": lambda _self: getattr(_self, '__revision_source'), + "getRevisionTag": lambda _self: getattr(_self, '__revision_tag') + } + classMethods.update(__automaticMethods) + """ + + # Put the method signatures into a namespace for the new class, + # then dynamically build the class from this namespace. + classNamespace = classMethods + classNamespace["meta_attributes"] = meta_attributes + cls = type(str(objClassName), tuple(classBases), classNamespace) + objClasses[objClassName] = cls + objClassesRev['%s.%s'%(objClassName,cls.meta_attributes["__revision_number"])] = cls + + # Create and register a constructor (loading) and representer (dumping) for the new class cls + def construct_dynamic_object(loader, node): + kwargs = loader.construct_mapping(node) + # Remove revision control from loaded objects (info is in the class object!) + for arg in kwargs.keys(): + if arg in getattr(Object, 'getters') and arg != '__time_created': + del kwargs[arg] + return cls(**kwargs) + revision = cls.meta_attributes["__revision_number"] + DynamicYAML.Loader.add_constructor(u'!%s.%s'%(str(objClassName),revision), construct_dynamic_object) + + represent_dynamic_object = DynamicYAML.Dumper.represent_dynamic_object + DynamicYAML.Dumper.add_representer(cls, represent_dynamic_object) + + def findClass(className): + """ Search for the most recently added class object with given className """ + try: + return objClasses[className] # Look for reference to object in same YAML defn file: + except KeyError: + # Now look for reference to class object loaded from any YAML defn file, loading the + # most recent version / revision (number) of the definition + for dynClass in Object.dynamicClasses.keys()[::-1]: + if dynClass.startswith(className): + return Object.dynamicClasses[dynClass] + + # Still unresolved - raise exception: + allDynamicClasses = repr(objClasses.keys() + Object.dynamicClasses.keys()) + raise UnresolvedTypeException("Cannot resolve type '%s': Name not found in %s"%(className,allDynamicClasses)) + + + def resolve(param): + + # Reference is just a string - that's the class name: + if isinstance(param.classType.yamlObject, (str, unicode)): + className = str(param.classType.yamlObject) + param.classType = findClass(className) + return + + # Reference is a dict containing class name and / or default values: + if not isinstance(param.classType.yamlObject, dict): + raise UnresolvedTypeException("Cannot resolve reference of type '%s'"%(param.classType.yamlObject.__class__,)) + + # Definitely a dict: + refDict = param.classType.yamlObject + + # Determine the name of the class being referenced + try: + className = refDict["type"] + except KeyError: + raise KeyError("No 'type' key in reference dictionary for parameter '%s'"%(param.name,)) + + # Determine the class object corresponding to the class name + param.classType = findClass(className) + + try: + defaultParams = refDict["default"] + except KeyError: + defaultParams = None + + if defaultParams != None: + for sub_param in defaultParams: + if isinstance(sub_param.classType, _UnresolvedType): + resolve(sub_param) + param.default = param.classType( **defaultParams ) # Create the default object + param.hasDefault = True + else: + param.hasDefault = False # for good measure + + # Is it an object array?: + if "len" in refDict.keys(): + param.length = refDict["len"] + + # Resolve any unresolved data-types: + for param in allClassData: + if isinstance(param.classType, _UnresolvedType): + resolve(param) + + Object.dynamicClasses.update(objClassesRev) + return objClasses + +def load_defn(yaml): + """ Shortcut for producing a single DynamicObject class object from + the provided yaml definition in string format """ + return Factory(yaml=yaml).classes.values()[0] + + + diff --git a/schainpy/model/serializer/test/.svn/text-base/DynamicSerializer.py.svn-base b/schainpy/model/serializer/test/.svn/text-base/DynamicSerializer.py.svn-base new file mode 100644 index 0000000..34b0444 --- /dev/null +++ b/schainpy/model/serializer/test/.svn/text-base/DynamicSerializer.py.svn-base @@ -0,0 +1,69 @@ +# +# rps 6/9/2014 +# mit haystack obs +# +# wrapper for Karl's code + +import DynamicObject # used for serial/deserial of complex python objects +import Serializer # used for serial/deserial of complex python + +# +class DynamicSerializer: + # + #------------------------------------------------------ + # + def __init__(self,which='yaml'): + # + # choices are: yaml, msgpack, hdf5, json + # + self.err_f = False + self.whichList = ['yaml', 'msgpack', 'hdf5', 'json'] # from Serialzer.py + self.err_f,self.serializer = self.initSerializer(which) + # + #------------------------------------------------------ + # + def initSerializer(self,which): + # + # calls REU student code that works but hasn't been walked-through + # it's a dynamic serializer not strictly a yaml serializer + # + err_f = False + match_f = False + serializer = None + ii = 0 + while ii < len(self.whichList): + if (self.whichList[ii] == which): + match_f = True + break + ii = ii + 1 + # end while + if not match_f: + err_f = True + else: + serializer = which + serializer = Serializer.serializers[serializer]() + + return err_f,serializer + # end initSerializer + # + # -------------------------------------------------- + # + def loads(self,element): # borrows name from json module (json - to - python) + retval = self.serializer.fromSerial(element) # de-serialize + return retval + # end loads + # + # -------------------------------------------------- + # + def dumps(self,element): # borrows name from json module (python - to - json) + retval = self.serializer.toSerial(element) # serialize + return retval + # end dumps + # + # -------------------------------------------------- + # +# end class DynamicSerializer + +if __name__ == "__main__": + DynamicSerializer() + print "DynamicSerializer ran" \ No newline at end of file diff --git a/schainpy/model/serializer/test/.svn/text-base/DynamicYAML.py.svn-base b/schainpy/model/serializer/test/.svn/text-base/DynamicYAML.py.svn-base new file mode 100644 index 0000000..f74cf98 --- /dev/null +++ b/schainpy/model/serializer/test/.svn/text-base/DynamicYAML.py.svn-base @@ -0,0 +1,221 @@ +''' +Module containing YAML Loader and Dumper for DynamicObjects +as well as built-in data types (numpy, PrecisionTime, datetime, Binary, ...) + +$Id$ +''' + +import yaml +import OrderedYAML +import DynamicObject +import binascii +import numpy as np +import PrecisionTime +import Lookup +import pysvn + +def load_defn(source, rev='head', repo=""): + """ Import YAML definition(s) from given 'source' SVN location + with specific revision number 'rev'. Returns a dict of the object + names -> class object instances. + + NOTE: Object defns with same name & revision number will conflict / + cause issues (regardless of svn location). """ + client = pysvn.Client() + + if rev == 'head': + #yaml = client.cat(source) + rev = client.info(repo).revision.number + + if source.startswith('http'): + yaml = client.cat("%s?p=%d"%(source, rev)) + else: + pysvn_rev = pysvn.Revision(pysvn.opt_revision_kind.number, rev) + yaml = client.cat(source, pysvn_rev) + + revision_dict = {\ + "__revision_number": rev, + "__revision_id": 'unknown', + "__revision_source": source, + "__revision_tag": 'unknown'} + + return DynamicObject.Factory(yaml=yaml, revision_dict=revision_dict).classes + +class Loader(OrderedYAML.Loader): + + def __init__(self, stream): + OrderedYAML.Loader.__init__(self, stream) + + def construct_object(self, node, deep=False): + """ Unresolved tags on mapping nodes come from un-imported YAML definitions - import it """ + resolved = node.tag in self.yaml_constructors + resolved = resolved or any([node.tag.startswith(x) for x in self.yaml_multi_constructors]) + if isinstance(node, yaml.nodes.MappingNode) and not resolved: + data = self.construct_mapping(self, node) + self.constructed_objects[node] = data + del self.recursive_objects[node] + if data.has_key('__revision_source'): + # TODO: Handle password authentication + client = pysvn.Client() + source = data['__revision_source'] + if source.startswith('http'): + rev = data['__revision_number'] + defn = client.cat("%s?p=%d"%(source, rev)) + else: + rev = pysvn.Revision(pysvn.opt_revision_kind.number, data['__revision_number']) + defn = client.cat(source, revision=rev) + DynamicObject.Factory(yaml=defn) # Register the object + + constructor = self.yaml_constructors["%s.%s"%(data['__revision_name'], data['__revision_number'])] + return constructor(node) + else: + raise Exception("Cannot load object with tag '%s' - cannot find YAML object definition (no __revision_source included)") + else: + return yaml.Loader.construct_object(self, node, deep=deep) + +class Dumper(OrderedYAML.Dumper): + + def __init__(self, stream, *args, **kwargs): + OrderedYAML.Dumper.__init__(self, stream, *args, **kwargs) + + def represent_dynamic_object(self, obj): + """ + Override the !!python/object:__main__.xxx syntax with + !ObjectName.zzz where zzz is the revision number of the Object obj + """ + + state = {} + state.update(obj.__dict__.items()) + state.update(obj.__class__.meta_attributes.items()) + name = obj.getObjectName() # obj.__class__.__name__ + revision = obj.getRevisionNumber() + return self.represent_mapping(u'!%s.%s' % (name, revision), state) + +# Dtypes to be stored as hex in YAML streams / strings +hex_dtypes = ['float', 'complex', 'half', 'single', 'double'] + +# Register hex constructors for the numpy / built-in dtypes: +dtypes = Lookup.numpy_dtypes + +# Inverse lookup for accessing tags given a class instance: +cls_dtypes = dict([(v,k) for (k,v) in dtypes.items()]) + +# Representer for numpy arrays: +def ndarray_representer(dumper, obj): + #if isinstance(obj, np.ndarray): + tag = 'dtype.'+obj.dtype.type.__name__ + hexlify = any([x in tag for x in hex_dtypes]) + np_ary = obj + #hex_ary = np.empty(np_ary.shape, dtype=yaml.nodes.ScalarNode) + np_flat, hex_flat = np_ary.flat, [] #hex_ary.flat + hex_flat.append(dumper.represent_sequence(u'tag:yaml.org,2002:seq', list(np_ary.shape), flow_style=True)) + if hexlify: + lst = [] + for i in range(len(np_flat)): + value = u'%s'%(np_flat[i],) + node = dumper.represent_scalar(u'tag:yaml.org,2002:str', value, style='') + lst.append(node) + hex_flat.append(yaml.nodes.SequenceNode(u'tag:yaml.org,2002:seq', lst, flow_style=True)) + lst = [] + for i in range(len(np_flat)): + if hexlify: value = u'%s'%(binascii.hexlify(np_flat[i]),) + else: value = u'%s'%(np_flat[i],) + node = dumper.represent_scalar(u'tag:yaml.org,2002:str', value, style='') + if hexlify: lst.append(node) + else: hex_flat.append(node) + if hexlify: hex_flat.append(yaml.nodes.SequenceNode(u'tag:yaml.org,2002:seq', lst, flow_style=True)) + return yaml.nodes.SequenceNode(u'!%s'%(tag,), hex_flat, flow_style=True) +Dumper.add_representer(np.ndarray, ndarray_representer) + +# Constructor for ndarrays with arbitrary (specified) dtype: +def ndarray_constructor(loader, node, dtype, hexlify=False): + shape = loader.construct_sequence(node.value.pop(0)) + np_ary = np.empty(shape, dtype=dtype) + np_flat = np_ary.flat # Flat iterator + if hexlify: + node.value[1].tag = node.tag + node = node.value[1] # only look at hexlified values + for i in range(len(node.value)): + # Over-ride the 'tag:yaml.org,2002:str' tag with correct data type + node.value[i].tag = node.tag + value = loader.construct_object(node.value[i]) + #if hexlify: + # value = binascii.unhexlify(value) + # value = np.frombuffer(value, dtype=dtype) + np_flat[i] = value + return np_ary + +class __dtype_con: + + def __init__(self, tag): + # Whether or not to convert to hex: + hexlify = any([x in tag for x in hex_dtypes]) + dtype = dtypes[tag] + + # Mutable list containing constructor & representer info + self.fncn_attributes = [tag, hexlify, dtype] + + def dtype_constructor(loader, node): + tag, hexlify, dtype = self.fncn_attributes + if isinstance(node, yaml.nodes.SequenceNode): + return ndarray_constructor(loader, node, dtype, hexlify=hexlify) + else: # isinstance(node, yaml.nodes.ScalarNode): + value = loader.construct_scalar(node) + dtype = dtypes[node.tag[1:]] + if hexlify: + value = binascii.unhexlify(value) + value = np.frombuffer(value, dtype=dtype)[0] + else: + value = dtype(value) + return value + + def dtype_representer(dumper, obj): + tag, hexlify, dtype = self.fncn_attributes + if isinstance(obj, float): obj = np.float64(obj) + if hexlify: value = u'%s'%(binascii.hexlify(obj),) + else: value = u'%s'%(obj,) + try: tag = u'!%s'%(cls_dtypes[obj.__class__]) # 'dtype.'+obj.__class__.__name__ # bullshit... + except KeyError: tag = '' + node = dumper.represent_scalar(tag, value, style='') + return node + + self.dtype_constructor = dtype_constructor + self.dtype_representer = dtype_representer + +keys = [x for x in dtypes.keys() if x != 'dtype.int' and x != 'dtype.bool'] +print keys + +n = len(keys) +print n +i=0 + +for tag in keys: + dtype = __dtype_con(tag) + dtype_constructor = dtype.dtype_constructor + dtype_representer = dtype.dtype_representer + Loader.add_constructor(u'!%s'%(tag,), dtype_constructor) + Dumper.add_representer(dtypes[tag], dtype_representer) + +# Precision time constructors & representers: +def ns_rep(dumper, obj): + state = {'second': obj.__dict__['second'], 'nanosecond': obj.__dict__['nanosecond']} + return dumper.represent_mapping(u'!timestamp_ns', state) +def ps_rep(dumper, obj): + state = {'second': obj.__dict__['second'], 'picosecond': obj.__dict__['picosecond']} + return dumper.represent_mapping(u'!timestamp_ps', state) +def ns_con(loader, node): return PrecisionTime.nsTime(**loader.construct_mapping(node)) +def ps_con(loader, node): return PrecisionTime.psTime(**loader.construct_mapping(node)) + +Dumper.add_representer(PrecisionTime.nsTime, ns_rep) +Dumper.add_representer(PrecisionTime.psTime, ps_rep) +Loader.add_constructor(u'!timestamp_ns', ns_con) +Loader.add_constructor(u'!timestamp_nanosecond', ns_con) +Loader.add_constructor(u'!timestamp_ps', ps_con) +Loader.add_constructor(u'!timestamp_picosecond', ps_con) + +# Binary object constructor & representer: +def bin_rep(dumper, obj): return dumper.represent_mapping(u'!binary', obj.__dict__) +def bin_con(loader, node): return DynamicObject.Binary(**loader.construct_mapping(node)) +Dumper.add_representer(DynamicObject.Binary, bin_rep) +Loader.add_constructor(u'!binary', bin_con) + diff --git a/schainpy/model/serializer/test/.svn/text-base/Lookup.py.svn-base b/schainpy/model/serializer/test/.svn/text-base/Lookup.py.svn-base new file mode 100644 index 0000000..53ab278 --- /dev/null +++ b/schainpy/model/serializer/test/.svn/text-base/Lookup.py.svn-base @@ -0,0 +1,62 @@ +''' +Helper module for DynamicObject module - contains dictionaries +of data types built-in to our YAML IDL, converting backing and forth between +strings / YAML tags and python class instances. + +$Id$ +''' + +import datetime +import numpy as np +import PrecisionTime +import DynamicObject +Binary = DynamicObject.Binary +import platform +import collections + +# Implicit Types: +python_dtypes = tuple([bool,int,long,float,str,datetime.datetime,list, + set,dict,tuple,unicode]) + +# Numpy Data-types: +numpy_dtypes = {'dtype.bool': bool, 'dtype.int': np.int, 'dtype.int8': np.int8, + 'dtype.int16': np.int16, 'dtype.int32': np.int32, 'dtype.int64': np.int64, + 'dtype.uint8': np.uint8, 'dtype.uint16': np.uint16, 'dtype.uint32': np.uint32, + 'dtype.uint64': np.uint64, 'dtype.float': np.float, 'dtype.float16': np.float16, + 'dtype.float32': np.float32, 'dtype.float64': np.float64, 'dtype.complex': np.complex, + 'dtype.complex64': np.complex64, 'dtype.complex128': np.complex128, + 'dtype.byte': np.byte, 'dtype.short': np.short, 'dtype.intc': np.intc, + 'dtype.longlong': np.longlong, 'dtype.intp': np.intp, 'dtype.ubyte': np.ubyte, + 'dtype.ushort': np.ushort, 'dtype.uintc': np.uintc, 'dtype.uint': np.uint, + 'dtype.uintc': np.uintc, 'dtype.uint': np.uint, 'dtype.ulonglong': np.ulonglong, + 'dtype.uintp': np.uintp, 'dtype.half': np.half, 'dtype.single': np.single, + 'dtype.double': np.double, 'dtype.longfloat': np.longfloat, + 'dtype.csingle': np.csingle, 'dtype.clongfloat': np.clongfloat, 'dtype.long': np.long} + +if platform.architecture()[0] != '32bit': # 64bit - certain numpy types exist + numpy_dtypes.update({'dtype.float128': np.float128, 'dtype.complex256': np.complex256}) + bit32 = False +else: + bit32 = True +#else: # 32 bit - fix 32 bit integer issue. +# np.int32 = np.int +# bit32 = True + +# Built-in objects: +builtin_objects = {'binary': Binary, 'nsTime': PrecisionTime.nsTime, 'psTime': PrecisionTime.psTime, + 'timestamp_ns': PrecisionTime.nsTime, 'timestamp_ps': PrecisionTime.psTime, + 'timestamp_nanosecond': PrecisionTime.nsTime, 'timestamp_picosecond': PrecisionTime.psTime, + 'datetime': datetime.datetime, 'Binary': Binary} + +builtin_objects_simple = {'nsTime': PrecisionTime.nsTime, 'psTime': PrecisionTime.psTime, + 'binary': Binary, 'datetime': datetime.datetime, + 'Binary': Binary} + +# Inverse lookup for accessing tags given a class instance: +cls_dtypes = dict([(v,k) for (k,v) in numpy_dtypes.items()]) +obj_dtypes = dict([(v,k) for (k,v) in builtin_objects_simple.items()]) + +# Pointer to the list of all Object classes created, as located in the Object module / class: +dynamicClasses = DynamicObject.Object.dynamicClasses + + diff --git a/schainpy/model/serializer/test/.svn/text-base/OrderedYAML.py.svn-base b/schainpy/model/serializer/test/.svn/text-base/OrderedYAML.py.svn-base new file mode 100644 index 0000000..711fd4f --- /dev/null +++ b/schainpy/model/serializer/test/.svn/text-base/OrderedYAML.py.svn-base @@ -0,0 +1,89 @@ +''' +A YAML Loader and Dumper which provide ordered dictionaries in place +of dictionaries (to keep the order of attributes as +found in the original YAML object file). + +This module is modified from a submission on pyyaml.org: +http://pyyaml.org/attachment/ticket/161/use_ordered_dict.py + +$Id$ +''' + +import yaml +import collections + +class Loader(yaml.loader.Loader): + """ YAML Loader producing OrderedDicts in place of dicts """ + + def __init__(self, stream): + yaml.loader.Loader.__init__(self, stream) + + def construct_ordered_mapping(self, node, deep=False): + """ Replacement mapping constructor producing an OrderedDict """ + if not isinstance(node, yaml.MappingNode): + raise yaml.constructor.ConstructorError(None, None, + "expected a mapping node, but found %s" % node.id, + node.start_mark) + mapping = collections.OrderedDict() + for key_node, value_node in node.value: + key = self.construct_object(key_node, deep=deep) + if not isinstance(key, collections.Hashable): + raise yaml.constructor.ConstructorError("while constructing a mapping", node.start_mark, + "found unhashable key", key_node.start_mark) + value = self.construct_object(value_node, deep=deep) + mapping[key] = value + return mapping + # yaml.constructor.BaseConstructor.construct_mapping = construct_ordered_mapping + + def construct_mapping(self, node, deep=False): + return self.construct_ordered_mapping(node, deep=deep) + + def construct_yaml_map_with_ordered_dict(self, node): + data = collections.OrderedDict() + yield data + value = self.construct_mapping(node) + data.update(value) + +class Dumper(yaml.dumper.Dumper): + """ YAML Dumper producing documents from OrderedDicts """ + + def __init__(self, stream, *args, **kwargs): + yaml.dumper.Dumper.__init__(self, stream, *args, **kwargs) + + def represent_ordered_mapping(self, tag, mapping, flow_style=None): + """ Replacement mapping representer for OrderedDicts """ + value = [] + node = yaml.MappingNode(tag, value, flow_style=flow_style) + if self.alias_key is not None: + self.represented_objects[self.alias_key] = node + best_style = True + if hasattr(mapping, 'items'): + mapping = list(mapping.items()) + for item_key, item_value in mapping: + node_key = self.represent_data(item_key) + node_value = self.represent_data(item_value) + if not (isinstance(node_key, yaml.ScalarNode) and not node_key.style): + best_style = False + if not (isinstance(node_value, yaml.ScalarNode) and not node_value.style): + best_style = False + value.append((node_key, node_value)) + if flow_style is None: + if self.default_flow_style is not None: + node.flow_style = self.default_flow_style + else: + node.flow_style = best_style + return node + # yaml.representer.BaseRepresenter.represent_mapping = represent_ordered_mapping + + def represent_mapping(self, tag, mapping, flow_style=None): + return self.represent_ordered_mapping(tag, mapping, flow_style=flow_style) + +# Loader.add_constructor( +# u'tag:yaml.org,2002:map', +# Loader.construct_yaml_map_with_ordered_dict +# ) +# +# Dumper.add_representer( +# collections.OrderedDict, +# yaml.representer.SafeRepresenter.represent_dict +# ) diff --git a/schainpy/model/serializer/test/.svn/text-base/PrecisionTime.py.svn-base b/schainpy/model/serializer/test/.svn/text-base/PrecisionTime.py.svn-base new file mode 100644 index 0000000..205cf5b --- /dev/null +++ b/schainpy/model/serializer/test/.svn/text-base/PrecisionTime.py.svn-base @@ -0,0 +1,211 @@ +#!/usr/local/midas/bin/python + +"""PrecisionTime.py is a collection of python classes to manipulate times with high +precision using integer logic. + +Written by "Bill Rideout":mailto:wrideout@haystack.mit.edu May 24, 2007 + +$Id$ +""" +import types + +class nsTime: + """nsTime is a class to handle times given as UT second (integer) and nanosecond (integer) + + If nanosecond > 1E9, seconds will be added to second + """ + + def __init__(self, second, nanosecond): + self.second = int(second) + if self.second < 0: + raise ValueError, 'seconds must be greater than 0, not %i' % (self.second) + nanosecond = long(nanosecond) + if nanosecond < 0: + raise ValueError, 'nanoseconds must be greater 0, not %i' % (nanosecond) + addSec = nanosecond / 1000000000 + if addSec > 0: + self.second += addSec + self.nanosecond = nanosecond % 1000000000 + self.totalNS = long(self.nanosecond) + long(self.second) * 1000000000 + + + def __add__(self, other): + """__add__ another nsTime to this one and return a new one as result + """ + nsResult = self.nanosecond + other.nanosecond + addSec = int(nsResult / 1000000000) + newSec = self.second + other.second + addSec + newNS = nsResult % 1000000000 + return(nsTime(newSec, newNS)) + + + def increase(self, other): + """increase adds other to self, changing self (rather than creating a new object) + """ + nsResult = self.nanosecond + other.nanosecond + addSec = int(nsResult / 1000000000) + self.second = self.second + other.second + addSec + self.nanosecond = nsResult % 1000000000 + self.totalNS = long(self.nanosecond) + long(self.second) * 1000000000 + + + def __sub__(self, other): + """__sub__ another nsTime from this one and return a new one as result + """ + nsResult = self.nanosecond - other.nanosecond + if nsResult < 0: + addSec = 1 + nsResult += 1000000000 + else: + addSec = 0 + newSec = (self.second - other.second) - addSec + return(nsTime(newSec, nsResult)) + + + def multiply(self, factor): + """multiply this nsTime times an integer + """ + if type(factor) not in (types.IntType, types.LongType): + raise ValueError, 'Illegal type %s passed into nsTime.multiply' % (str(type(factor))) + newTotalNS = self.totalNS * factor + newSeconds = int(newTotalNS / 1000000000) + newNanoseconds = int(newTotalNS - (newSeconds * 1000000000)) + return(nsTime(newSeconds, newNanoseconds)) + + + def integerDivision(self, other): + """integerDivision returns the total number of other nsTimes that fit in self + """ + return(int(self.totalNS / other.totalNS)) + + def getUnixTime(self): + """ getUnixTime() returns a Unix style time as a float. """ + return(float(self.second) + float(self.nanosecond)/1.0e9) + + def __mod__(self, other): + """__mod__ implements self % other. + """ + if type(other) in (types.IntType, types.LongType): + return self.totalNS % other + else: + return self.totalNS % other.totalNS + + def __eq__(self, other): + """ equality of two nsTime objects """ + if not (hasattr(other, 'second') and hasattr(other, 'nanosecond')): return False + return self.__cmp__(other) == 0 + + def __cmp__(self, other): + """compare two nsTime objects + """ + result = cmp(self.second, other.second) + if result != 0: + return(result) + + return(cmp(self.nanosecond, other.nanosecond)) + + + def __str__(self): + return '%d.%09d' % (self.second, self.nanosecond) + + +class psTime: + """psTime is a class to handle times given as UT second (integer) and picosecond (integer) + + If picosecond > 1E12, seconds will be added to second + """ + + def __init__(self, second, picosecond): + self.second = int(second) + if self.second < 0: + raise ValueError, 'seconds must be greater than 0, not %i' % (self.second) + picosecond = long(picosecond) + if picosecond < 0: + raise ValueError, 'picoseconds must be greater 0, not %i' % (picosecond) + addSec = picosecond / 1000000000000 + if addSec > 0: + self.second += addSec + self.picosecond = picosecond % 1000000000000 + self.totalPS = long(self.picosecond) + long(self.second) * 1000000000000 + + + def __add__(self, other): + """__add__ another psTime to this one and return a new one as result + """ + psResult = self.picosecond + other.picosecond + addSec = int(psResult / 1000000000000) + newSec = self.second + other.second + addSec + newPS = psResult % 1000000000000 + return(psTime(newSec, newPS)) + + + def increase(self, other): + """increase adds other to self, changing self (rather than creating a new object) + """ + psResult = self.picosecond + other.picosecond + addSec = int(psResult / 1000000000000) + self.second = self.second + other.second + addSec + self.picosecond = psResult % 1000000000000 + self.totalPS = long(self.picosecond) + long(self.second) * 1000000000000 + + + def __sub__(self, other): + """__sub__ another psTime from this one and return a new one as result + """ + psResult = self.picosecond - other.picosecond + if psResult < 0: + addSec = 1 + psResult += 1000000000000 + else: + addSec = 0 + newSec = (self.second - other.second) - addSec + return(psTime(newSec, psResult)) + + + def multiply(self, factor): + """multiply this psTime times an integer + """ + if type(factor) not in (types.IntType, types.LongType): + raise ValueError, 'Illegal type %s passed into psTime.multiply' % (str(type(factor))) + newTotalPS = self.totalPS * factor + newSeconds = int(newTotalPS / 1000000000000) + newPicoseconds = int(newTotalPS - (newSeconds * 1000000000000)) + return(psTime(newSeconds, newPicoseconds)) + + + def integerDivision(self, other): + """integerDivision returns the total number of other psTimes that fit in self + """ + return(int(self.totalPS / other.totalPS)) + + def getUnixTime(self): + """ getUnixTime() returns a Unix style time as a float. """ + return(float(self.second) + float(self.picosecond)/1.0e12) + + def __mod__(self, other): + """__mod__ implements self % other. + """ + if type(other) in (types.IntType, types.LongType): + return self.totalPS % other + else: + return self.totalPS % other.totalPS + + def __eq__(self, other): + """ equality of two psTime objects """ + if not (hasattr(other, 'second') and hasattr(other, 'picosecond')): return False + return self.__cmp__(other) == 0 + + def __cmp__(self, other): + """compare two psTime objects + """ + result = cmp(self.second, other.second) + if result != 0: + return(result) + + return(cmp(self.picosecond, other.picosecond)) + + + def __str__(self): + return '%d.%12d' % (self.second, self.picosecond) + + diff --git a/schainpy/model/serializer/test/.svn/text-base/Serializer.py.svn-base b/schainpy/model/serializer/test/.svn/text-base/Serializer.py.svn-base new file mode 100644 index 0000000..9201f6c --- /dev/null +++ b/schainpy/model/serializer/test/.svn/text-base/Serializer.py.svn-base @@ -0,0 +1,373 @@ +''' +Module containing classes with serialization and de-serialization services. + +$Id$ +''' + +import Lookup +import numpy as np +import zlib +import binascii +import yaml +import DynamicObject +import DynamicYAML +import PrecisionTime +import datetime +import re +import os +#import json +import jsonpickle +import jpickle +import h5py +import msgpack + +class CompressionException(Exception): pass + +class Serializer: + """ Base class for pickle-like serialization + of DynamicObjects (with compression available) """ + + def __init__(self): + pass + + def dump(self, obj, file_name, compression=None): + """ Dumps obj to file_name, serializing the obj with toSerial() """ + string = self.dumps(obj, compression) + open(file_name, 'w').write(string) + + def dumps(self, obj, compression=None): + """ Returns serialized string representing obj, using toSerial() to serialize """ + if compression == 'gzip': + return zlib.compress(self.toSerial(obj)) + elif compression in [None, '']: + return self.toSerial(obj) + else: + raise CompressionException("Invalid decompression type '%r'"%(compression,)) + + def load(self, file_name, compression=None): + """ Returns the Object located in file_name, using fromSerial() to deserialize """ + string = open(file_name, 'r').read() + return self.loads(string, compression) + + def loads(self, string, compression=None): + """ Returns the Object serialized as the given string """ + if compression == 'gzip': + return self.fromSerial(zlib.decompress(string)) + elif compression in [None, '']: + return self.fromSerial(string) + else: + raise CompressionException("Invalid compression type '%r'"%(compression,)) + + def fromSerial(self, string): + """ Deserializes the given string """ + return string + + def toSerial(self, obj): + """ Serializes the given object """ + return repr(obj) + +class YAMLSerializer(Serializer): + """ Serializes a Object to/from YAML format """ + + def __init__(self): + Serializer.__init__(self) + + def fromSerial(self, string): + loader = DynamicYAML.Loader + return yaml.load(string, Loader=loader) + + def toSerial(self, obj): + dumper = DynamicYAML.Dumper + return yaml.dump(obj, Dumper=dumper) + +# Regular expression taken from yaml.constructor.py +timestamp_regexp_str = str(\ + ur'^(?P[0-9][0-9][0-9][0-9])' + ur'-(?P[0-9][0-9]?)' + ur'-(?P[0-9][0-9]?)' + ur'(?:(?:[Tt]|[ \t]+)' + ur'(?P[0-9][0-9]?)' + ur':(?P[0-9][0-9])' + ur':(?P[0-9][0-9])' + ur'(?:\.(?P[0-9]*))?' + ur'(?:[ \t]*(?PZ|(?P[-+])(?P[0-9][0-9]?)' + ur'(?::(?P[0-9][0-9]))?))?)?$') +timestamp_regexp = re.compile(timestamp_regexp_str, re.X) + +def construct_timestamp(value): + """ Taken & modified from yaml.constructor.py """ + + match = timestamp_regexp.match(value) + #print "&%s&"%(value,) + #print timestamp_regexp_str + values = match.groupdict() + year = int(values['year']) + month = int(values['month']) + day = int(values['day']) + if not values['hour']: + return datetime.date(year, month, day) + hour = int(values['hour']) + minute = int(values['minute']) + second = int(values['second']) + fraction = 0 + if values['fraction']: + fraction = values['fraction'][:6] + while len(fraction) < 6: + fraction += '0' + fraction = int(fraction) + delta = None + if values['tz_sign']: + tz_hour = int(values['tz_hour']) + tz_minute = int(values['tz_minute'] or 0) + delta = datetime.timedelta(hours=tz_hour, minutes=tz_minute) + if values['tz_sign'] == '-': + delta = -delta + data = datetime.datetime(year, month, day, hour, minute, second, fraction) + if delta: + data -= delta + return data + +class MessagePackSerializer(Serializer): + """ Serializes a Object to/from MessagePack format """ + + def __fromSerial(self, msg_dict): + if not isinstance(msg_dict, (dict, list, tuple)): + return msg_dict # msg_dict is a value - return it + if isinstance(msg_dict, dict) and msg_dict.has_key('__meta_attributes'): + meta_attr = msg_dict['__meta_attributes'] + msg_dict.pop('__meta_attributes') + if meta_attr.has_key('type'): + if meta_attr['type'] == 'datetime': + return construct_timestamp(str(msg_dict['ts'])) + elif meta_attr['type'] == 'nsTime': + msg_dict.pop('totalNS') + elif meta_attr['type'] == 'psTime': + msg_dict.pop('totalPS') + try: dtype = Lookup.cls_dtypes[meta_attr['type']] + except KeyError: dtype = Lookup.builtin_objects[meta_attr['type']] + return dtype(**msg_dict) + else: + for key in msg_dict.keys(): + msg_dict[key] = self.__fromSerial(msg_dict[key]) + cls = Lookup.dynamicClasses['%s.%s'%(meta_attr['__object_name'],meta_attr['__revision_number'])] + return cls(**msg_dict) + elif msg_dict == (): + return [] + elif isinstance(msg_dict[0], str) and msg_dict[1] in Lookup.numpy_dtypes and\ + isinstance(msg_dict, tuple) and len(msg_dict) == 2: + value = binascii.unhexlify(msg_dict[0]) + return np.frombuffer(value, dtype=Lookup.numpy_dtypes[msg_dict[1]])[0] + + tup = isinstance(msg_dict, tuple) + if tup and len(msg_dict) > 1 and msg_dict[0] in Lookup.numpy_dtypes.keys(): + msg_flat = list(msg_dict) + dtypeName = msg_flat.pop(0) + dtype = Lookup.numpy_dtypes[dtypeName] + shape = msg_flat.pop(0) + obj = np.empty(shape, dtype=dtype) + np_flat = obj.flat + for i in range(len(np_flat)): + if isinstance(msg_flat[i], float): + value = msg_flat[i] + else: + value = self.__fromSerial((msg_flat[i], dtypeName)) + np_flat[i] = value + return obj + else: + return msg_dict + + def fromSerial(self, string): + msg_dict = msgpack.unpackb(string) + return self.__fromSerial(msg_dict) + + def __toSerial(self, obj): + + if isinstance(obj, (PrecisionTime.nsTime, PrecisionTime.psTime, DynamicObject.Binary, datetime.datetime)): + msg_dict = {} + if isinstance(obj, datetime.datetime): + msg_dict['ts'] = obj.isoformat(' ') + else: + msg_dict.update(obj.__dict__) + msg_dict['__meta_attributes'] = {'type': obj.__class__.__name__} + return msg_dict + elif isinstance(obj, DynamicObject.Object): + msg_dict = {} + for key, value in obj.__dict__.items(): + msg_dict[key] = self.__toSerial(value) + + msg_dict['__meta_attributes'] = obj.__class__.meta_attributes + return msg_dict + elif isinstance(obj, np.ndarray): + np_flat = obj.flat + msg_flat = [] + msg_flat.append(Lookup.cls_dtypes[obj.dtype.type]) # dtype is first element + msg_flat.append(obj.shape) # shape of array is second element + for i in range(len(np_flat)): + toSer = self.__toSerial(np_flat[i]) + if isinstance(toSer, tuple): + msg_flat.append(toSer[0]) + else: + msg_flat.append(toSer) + return list(msg_flat) + + is_builtin = obj.__class__ in Lookup.numpy_dtypes.values() + #is_python = isinstance(obj, Lookup.python_dtypes) + if is_builtin: # and not is_python: + try: + #print obj.__class__ + msg_dict = (binascii.hexlify(obj), Lookup.cls_dtypes[obj.__class__]) + return msg_dict + except TypeError: # numpy dtype is a built-in python type... force the hexlify: + if not Lookup.bit32: + if obj.__class__ == int: return (binascii.hexlify(np.int64(obj)), 'dtype.int64') + elif obj.__class__ == float: return (binascii.hexlify(np.float64(obj)), 'dtype.float64') + else: + #print np.int32(obj).__class__, obj.__class__ + if obj.__class__ == int: return (binascii.hexlify(np.int32(obj)), 'dtype.int32') + elif obj.__class__ == float: return (binascii.hexlify(np.float32(obj)), 'dtype.float32') + raise + else: + return obj + + def toSerial(self, obj): + #if Lookup.bit32 and np.int32 != np.int: np.int32 = np.int + toSer = self.__toSerial(obj) + #print toSer + value = msgpack.packb(toSer) + return value + +class HDF5Serializer(Serializer): + """ Serializes a Object to/from HDF5 format """ + + tmp_num = 0 + + def __fromSerial(self, grp): + + if isinstance(grp, h5py.Dataset): + return grp.value + + elif isinstance(grp, h5py.Group) and '__type' in grp.keys(): + typ = grp['__type'].value + if typ == 'datetime': + return construct_timestamp(str(grp['ts'].value)) + elif typ == '_null': + return None + elif typ == 'tuple': + return tuple(grp['tuple']) + elif typ == 'empty_list': + return [] + try: cls = Lookup.builtin_objects_simple[typ] + except KeyError: cls = Lookup.dynamicClasses[typ] + args = [] + for key in grp.keys(): + fromSer = self.__fromSerial(grp[key]) + args.append((key, fromSer)) + kwargs = dict(args) + kwargs.pop('__type') + return cls(**kwargs) + #else: + # return grp.value + + + def fromSerial(self, string): + HDF5Serializer.tmp_num += 1 + fn = 'tmp%d.hdf5'%(HDF5Serializer.tmp_num-1,) + fp = open(fn, 'wb') + fp.write(string) + fp.flush(), fp.close() + + root = h5py.File(fn, driver='core') + try: + fromSer = self.__fromSerial(root['dataset']) + except: + root.flush(), root.close() + os.remove(fn) + raise + + root.flush(), root.close() + os.remove(fn) + + return fromSer + + def __toSerial(self, obj, grp, name): + + if isinstance(obj, datetime.datetime): + sub_grp = grp.create_group(name) + sub_grp['__type'] = 'datetime' + sub_grp['ts'] = obj.isoformat(' ') + + elif isinstance(obj, tuple(Lookup.builtin_objects_simple.values())): + sub_grp = grp.create_group(name) + sub_grp['__type'] = Lookup.obj_dtypes[obj.__class__] + for key, value in obj.__dict__.items(): + if value != None and key not in ['totalNS', 'totalPS']: + sub_grp[key] = value + + elif obj == None: + sub_grp = grp.create_group(name) + sub_grp['__type'] = '_null' + + elif isinstance(obj, DynamicObject.Object): + # Create the new group and assign unique identifier for this type of DynamicObject + sub_grp = grp.create_group(name) + tag = '%s.%s'%(obj.getObjectName(), obj.getRevisionNumber()) + sub_grp['__type'] = tag + # Put all of the DynamicObject's attributes into the new h5py group + for key, value in obj.__dict__.items(): + self.__toSerial(value, sub_grp, key) + + elif isinstance(obj, tuple): + sub_grp = grp.create_group(name) + sub_grp['__type'] = 'tuple' + sub_grp['tuple'] = obj + + elif isinstance(obj, list) and len(obj) == 0: + sub_grp = grp.create_group(name) + sub_grp['__type'] = 'empty_list' + + else: + grp[name] = obj + + def toSerial(self, obj): + HDF5Serializer.tmp_num += 1 + fn = 'tmp%d.hdf5'%(HDF5Serializer.tmp_num,) + root = h5py.File(fn, driver='core') + try: + self.__toSerial(obj, root, 'dataset') + except: + root.flush(), root.close() + os.remove(fn) + raise + root.flush(), root.close() + + fp = open(fn, 'rb') + msg = fp.read() + fp.close() + os.remove(fn) + + return msg + +# Alias for the standard json serializer: +class jsonSerializer(Serializer): + def fromSerial(self, string): + #return json.loads(string) + return jsonpickle.decode(string) + def toSerial(self, string): + #return json.dumps(string) + return jsonpickle.encode(string, max_depth=500) + +# Dict mapping from serializer type to corresponding class object: +serializers = {'yaml': YAMLSerializer, + 'msgpack': MessagePackSerializer, + 'hdf5': HDF5Serializer, + 'json': jsonSerializer} + +instances = {'yaml': YAMLSerializer(), + 'msgpack': MessagePackSerializer(), + 'hdf5': HDF5Serializer(), + 'json': jsonSerializer()} + +serial_types = dict([(v,u) for u,v in serializers.items()]) + +compression_types = ['gzip', ''] + diff --git a/schainpy/model/serializer/test/.svn/text-base/__init__.py.svn-base b/schainpy/model/serializer/test/.svn/text-base/__init__.py.svn-base new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/schainpy/model/serializer/test/.svn/text-base/__init__.py.svn-base diff --git a/schainpy/model/serializer/test/.svn/text-base/serialtest.py.svn-base b/schainpy/model/serializer/test/.svn/text-base/serialtest.py.svn-base new file mode 100644 index 0000000..0b8ded6 --- /dev/null +++ b/schainpy/model/serializer/test/.svn/text-base/serialtest.py.svn-base @@ -0,0 +1,187 @@ + +# +# when Serializer is imported alone, fault indicates this package is +# dependent on lookup, but don't import Lookup, instead: +# +import DynamicObject # dependent on pysvn +import Serializer # dependent on Dynamic Object + +import msgpack +import redis + +import numpy as np + +class NamedObject(): + + #--------------------------------------------- + @staticmethod + def indexListMatch(list_of_lists, name, value, name2=None, value2=None, unique_f=False): + # + # for each list's attribute compare with value + # if match, return True plus list + # else return False plus empty list + # + # search needs to be named part of class for object else . is unrecognized + # + # unique_f finds non-uniqueness + + + index = [] # return empty indices + list_data = [] # return empty list + ii = 0 + for theList in list_of_lists: + + cmd0 = "theList.%s == value" % (name) + cmd1 = "isInlist(theList.%s,value)" % name + # if name is valid then + # match name against value + # match name (as list) against value + if (eval(cmd0) or eval(cmd1)): + if (name2 != None): + cmd2 = "theList.%s == value2" % name2 + cmd3 = "isInlist(theList.%s,value2)" % name2 + if (eval(cmd2) or eval(cmd3)): + if (unique_f): + index = index + [ii] + list_data = list_data + [theList] # save list of lists if non-unique + # don't exit on match, may be non-unique + else: + list_data = theList # save the list + index = [ii] + break + else: + if (unique_f): + index = index + [ii] + list_data = list_data + [theList] # list of lists if non-unique + else: + list_data = theList + index = [ii] + break # exit on match + #endif + ii = ii + 1 + #end for + + return index, list_data # return indices of matches and list (or list of lists) + + #end indexListMatch + + #--------------------------------------------- + @staticmethod + def namedListMatch(list_of_lists, name, value, name2=None, value2=None, unique_f=None): + # + # for each list's attribute compare with value + # if match, return True plus list + # else return False plus empty list + # + # search needs to be named part of class for object else . is unrecognized + # + # unique_f finds non-uniqueness ('None' is same as False) + + match_f = False + list_data = [] # initialize + + for theList in list_of_lists: + + cmd0 = "theList.%s == value" % (name) + cmd1 = "isInlist(theList.%s,value)" % name + # if name is valid then + # match name against value + # match name (as list) against value + if (eval(cmd0) or eval(cmd1)): + if (name2 != None): + cmd2 = "theList.%s == value2" % name2 + cmd3 = "isInlist(theList.%s,value2)" % name2 + if (eval(cmd2) or eval(cmd3)): + match_f = True + if (unique_f): + list_data = list_data + [theList] # save list of lists if non-unique + # don't exit on match, may be non-unique + else: + list_data = theList # save the list + break + else: + match_f = True + if (unique_f): + list_data = list_data + [theList] # list of lists if non-unique + else: + list_data = theList + break # exit on match + #endif + #end for + + return match_f, list_data # return match, and list (or list of lists) + + #end namedListMatch + + #--------------------------------------------- + @staticmethod + def combineLists(object): + # + # used for dumping elements in list of lists for debugging + # + ret_list =[] + ii = 0 + while ii < len(object): + ret_list = ret_list + [object[ii].list] # not a real list, so can't use built-in list iterator + ii = ii + 1 + return ret_list + + # end combineLists + + + +class StateListObject(NamedObject): + def __init__(self, concurrent=None, hierarchical=None, history=None, state=None): + self.concurrent = concurrent + self.hierarchical = hierarchical + self.history = history + self.state = state + self.list = [self.concurrent, self.hierarchical, self.history, self.state ] +#end class StateListObject + +source_object = "my test string" + +serializer = "yaml" +# +# python versioning issue (ver 2.7 -> else path) +# +if isinstance(serializer,Serializer.Serializer): + serial_type = Serializer.serial_types[serializer] +else: + serial_type = serializer + serializer = Serializer.serializers[serializer]() + + + +datastr = serializer.toSerial(source_object) + +dest_object = serializer.fromSerial(datastr) + +print "dest_object=",dest_object + +myObject = StateListObject(hierarchical="yes",state=np.array([1,2,3.0])) + +datastr = serializer.toSerial(myObject) + +packed = msgpack.packb(datastr) + +try: + r= redis.StrictRedis(host='localhost',port=6379,db=0) +except Exception as eobj: + print "is the redis server running?",eobj +else: + + r.set('baz',packed) # converts to string + x = r.get('baz') + +unpacked = msgpack.unpackb(x) + +dest_object = serializer.fromSerial(unpacked) + +print "val1=",dest_object.hierarchical +val2 = dest_object.state +print "val2=",val2 +# can numpy array be used as array? +print val2.shape + + diff --git a/schainpy/model/serializer/test/.svn/text-base/test _serializer_speed.py.svn-base b/schainpy/model/serializer/test/.svn/text-base/test _serializer_speed.py.svn-base new file mode 100644 index 0000000..5b891d3 --- /dev/null +++ b/schainpy/model/serializer/test/.svn/text-base/test _serializer_speed.py.svn-base @@ -0,0 +1,175 @@ +''' +Created on Jul 16, 2014 + +@author: roj-idl71 +''' +""" +Dependencies: + + pip install tabulate simplejson python-cjson ujson yajl msgpack-python + +""" + +from timeit import timeit +from tabulate import tabulate + +setup = '''d = { + 'words': """ + Lorem ipsum dolor sit amet, consectetur adipiscing + elit. Mauris adipiscing adipiscing placerat. + Vestibulum augue augue, + pellentesque quis sollicitudin id, adipiscing. + """, + 'boolean' : False, + 'list': range(10), + 'dict': dict((str(i),'a') for i in xrange(10)), + 'int': 100, + 'float': 100.123456, +}''' + +setup = '''import numpy; +import datetime; +d = { + 'words': """ + Lorem ipsum dolor sit amet, consectetur adipiscing + elit. Mauris adipiscing adipiscing placerat. + Vestibulum augue augue, + pellentesque quis sollicitudin id, adipiscing. + """, + 'boolean' : False, + 'list': range(10), + 'dict': dict((str(i),'a') for i in xrange(10)), + 'int': 100, + 'float': 100.123456, + 'datetime' : datetime.datetime(2001,1,1,10,10,10) +}''' + + +setup_pickle = '%s ; import pickle ; src = pickle.dumps(d)' % setup +setup_pickle2 = '%s ; import pickle ; src = pickle.dumps(d, 2)' % setup +setup_cpickle = '%s ; import cPickle ; src = cPickle.dumps(d)' % setup +setup_cpickle2 = '%s ; import cPickle ; src = cPickle.dumps(d, 2)' % setup +setup_json = '%s ; import json; src = json.dumps(d)' % setup +setup_ujson = '%s ; import ujson; src = ujson.encode(d)' % setup +setup_cjson = '%s ; import cjson; src = cjson.encode(d)' % setup +setup_simplejson = '%s ; import simplejson; src = simplejson.dump(d)' % setup +setup_jsonpickle = '%s ; import jsonpickle; src = jsonpickle.encode(d)' % setup +setup_yaml = '%s ; import yaml; src = yaml.dump(d)' % setup +setup_msgpack = '%s ; import msgpack; src = msgpack.dumps(d)' % setup +setup_msgpack_np = '%s; import msgpack_numpy as msgpack; src = msgpack.dumps(d)' % setup + +tests = [ + # (title, setup, enc_test, dec_test, result) + ('cPickle (binary)', 'import cPickle; %s' % setup_cpickle2, 'cPickle.dumps(d, 2)', 'r = cPickle.loads(src)', 'print r'), + ('cPickle (ascii)', 'import cPickle; %s' % setup_cpickle, 'cPickle.dumps(d, 0)', 'r = cPickle.loads(src)', 'print r'), + ('pickle (binary)', 'import pickle; %s' % setup_pickle2, 'pickle.dumps(d, 2)', 'r = pickle.loads(src)', 'print r'), + ('pickle (ascii)', 'import pickle; %s' % setup_pickle, 'pickle.dumps(d, 0)', 'r = pickle.loads(src)', 'print r'), + ('jsonpickle', 'import jsonpickle; %s' % setup_jsonpickle, 'jsonpickle.encode(d)', 'r = jsonpickle.decode(src)', 'print r'), +# ('msgpack-numpy-python', '%s' % setup_msgpack_np, 'msgpack.dumps(d)', 'r = msgpack.loads(src)', 'print r'), + ('ujson', 'import ujson; %s' % setup_ujson, 'ujson.encode(d)', 'r = ujson.decode(src)', 'print r'), +# ('msgpack-python', 'import msgpack; %s' % setup_msgpack, 'msgpack.dumps(d)', 'r = msgpack.loads(src)', 'print r'), +# ('json', 'import json; %s' % setup_json, 'json.dumps(d)', 'r = json.loads(src)', 'print r'), +# ('python-cjson-1.0.5', 'import cjson; %s' % setup_cjson, 'cjson.encode(d)', 'r = cjson.decode(src)', 'print r'), +# ('simplejson-3.3.1', 'import simplejson; %s' % setup_json, 'simplejson.dumps(d)', 'r = simplejson.loads(src)', 'print r'), + ('yaml', 'import yaml; %s' % setup_yaml, 'yaml.dump(d)', 'r = yaml.load(src)', 'print r'), +] + +loops = 1 +enc_table = [] +dec_table = [] + +print "Running tests (%d loops each)" % loops + +for title, mod, enc, dec, msg in tests: + print title + + ### Getting the package size + exec mod + size = len("".join(src)) + + print " [Encode]", enc + result = timeit(enc, mod, number=loops) + enc_table.append([title, result, size]) + + print " [Decode]", dec + result = timeit(dec, mod, number=loops) + dec_table.append([title, result]) + + print " Result" + result = timeit(msg, mod+';'+dec, number=1) + +enc_table.sort(key=lambda x: x[1]) +enc_table.insert(0, ['Package', 'Seconds', 'Size']) + +dec_table.sort(key=lambda x: x[1]) +dec_table.insert(0, ['Package', 'Seconds']) + +print "\nEncoding Test (%d loops)" % loops +print tabulate(enc_table, headers="firstrow") + +print "\nDecoding Test (%d loops)" % loops +print tabulate(dec_table, headers="firstrow") + +""" +OUTPUT: + +Running tests (15000 loops each) +pickle (ascii) + [Encode] pickle.dumps(d, 0) + [Decode] pickle.loads(src) +pickle (binary) + [Encode] pickle.dumps(d, 2) + [Decode] pickle.loads(src) +cPickle (ascii) + [Encode] cPickle.dumps(d, 0) + [Decode] cPickle.loads(src) +cPickle (binary) + [Encode] cPickle.dumps(d, 2) + [Decode] cPickle.loads(src) +json + [Encode] json.dumps(d) + [Decode] json.loads(src) +simplejson-3.3.1 + [Encode] simplejson.dumps(d) + [Decode] simplejson.loads(src) +python-cjson-1.0.5 + [Encode] cjson.encode(d) + [Decode] cjson.decode(src) +ujson-1.33 + [Encode] ujson.dumps(d) + [Decode] ujson.loads(src) +yajl 0.3.5 + [Encode] yajl.dumps(d) + [Decode] yajl.loads(src) +msgpack-python-0.3.0 + [Encode] msgpack.dumps(d) + [Decode] msgpack.loads(src) + +Encoding Test (15000 loops) +Package Seconds +-------------------- --------- +ujson-1.33 0.232215 +msgpack-python-0.3.0 0.241945 +cPickle (binary) 0.305273 +yajl 0.3.5 0.634148 +python-cjson-1.0.5 0.680604 +json 0.780438 +simplejson-3.3.1 1.04763 +cPickle (ascii) 1.62062 +pickle (ascii) 14.0497 +pickle (binary) 15.4712 + +Decoding Test (15000 loops) +Package Seconds +-------------------- --------- +msgpack-python-0.3.0 0.240885 +cPickle (binary) 0.393152 +ujson-1.33 0.396875 +python-cjson-1.0.5 0.694321 +yajl 0.3.5 0.748369 +simplejson-3.3.1 0.780531 +cPickle (ascii) 1.38561 +json 1.65921 +pickle (binary) 5.20554 +pickle (ascii) 17.8767 +""" \ No newline at end of file diff --git a/schainpy/model/utils/.svn/all-wcprops b/schainpy/model/utils/.svn/all-wcprops new file mode 100644 index 0000000..9cf186c --- /dev/null +++ b/schainpy/model/utils/.svn/all-wcprops @@ -0,0 +1,47 @@ +K 25 +svn:wc:ra_dav:version-url +V 82 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/model/utils +END +jroutils_publish.pyc +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/model/utils/jroutils_publish.pyc +END +__init__.py +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/model/utils/__init__.py +END +scp.py +K 25 +svn:wc:ra_dav:version-url +V 89 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/model/utils/scp.py +END +jroutils_ftp.pyc +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/model/utils/jroutils_ftp.pyc +END +jroutils_ftp.py +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/model/utils/jroutils_ftp.py +END +__init__.pyc +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/model/utils/__init__.pyc +END +jroutils_publish.py +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/model/utils/jroutils_publish.py +END diff --git a/schainpy/model/utils/.svn/entries b/schainpy/model/utils/.svn/entries new file mode 100644 index 0000000..3a7caf8 --- /dev/null +++ b/schainpy/model/utils/.svn/entries @@ -0,0 +1,266 @@ +10 + +dir +1608 +http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainpy/model/utils +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 + +__init__.py +file + + + + +2017-04-17T17:05:33.000000Z +42a9a28f83e3851367128843ecaafb97 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +143 + +__init__.pyc +file + + + + +2017-04-17T17:05:33.000000Z +a4c081d87ac0b6a5c59f50fe87333920 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +360 + +jroutils_ftp.py +file + + + + +2017-04-17T17:05:33.000000Z +6473177700740337e030fa2776ceb121 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +29145 + +jroutils_ftp.pyc +file + + + + +2017-04-17T17:05:33.000000Z +e800fadc1302287516d5734eff0e818f +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +28498 + +jroutils_publish.py +file + + + + +2017-04-17T17:05:33.000000Z +9522155f87526cbcfaddbf453aaadf9a +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +2955 + +jroutils_publish.pyc +file + + + + +2017-04-17T17:05:33.000000Z +dc1e4056da4d98668f288a787d25d7f7 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +4379 + +scp.py +file + + + + +2017-04-17T17:05:33.000000Z +06e62b8d882ea9e0d7185dac9f373c02 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +16233 + diff --git a/schainpy/model/utils/.svn/prop-base/__init__.pyc.svn-base b/schainpy/model/utils/.svn/prop-base/__init__.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/model/utils/.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/model/utils/.svn/prop-base/jroutils_ftp.pyc.svn-base b/schainpy/model/utils/.svn/prop-base/jroutils_ftp.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/model/utils/.svn/prop-base/jroutils_ftp.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/model/utils/.svn/prop-base/jroutils_publish.pyc.svn-base b/schainpy/model/utils/.svn/prop-base/jroutils_publish.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/model/utils/.svn/prop-base/jroutils_publish.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/model/utils/.svn/text-base/__init__.py.svn-base b/schainpy/model/utils/.svn/text-base/__init__.py.svn-base new file mode 100644 index 0000000..f8ea804 --- /dev/null +++ b/schainpy/model/utils/.svn/text-base/__init__.py.svn-base @@ -0,0 +1,8 @@ +''' + +$Author: murco $ +$Id: Processor.py 1 2012-11-12 18:56:07Z murco $ +''' + +from jroutils_ftp import * +from jroutils_publish import PublishData \ No newline at end of file diff --git a/schainpy/model/utils/.svn/text-base/__init__.pyc.svn-base b/schainpy/model/utils/.svn/text-base/__init__.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..ff484fdff825cef32d3e10d9855278b8630bfdde GIT binary patch literal 360 zc$`&`-AcqT5QWor{h=!O2)XD*5!P%9{!l~|_CjxDQ7@!7p(c^WZFfqND*IACmM`D~ z=ww$#2j=5&k~vJ0eC(w!?{5#1d{>Npf$cJcBBVk_M8%|y$bC==X=BnQq)JGnM&vHv z2)Cz*G|est-+(P?H&_WYOS5ZL(wPORodbK=FDa+RgcoDZ$Go8Yv^+X4CnweKfceDA zBTVxF2Wz>5m<^Auam}>$^-Vqs?iNA_1yTsVi~8BZ;7#kqlkffhU!z~o-iEN8{DZqf zum(EKv^8?hUct^?UrWuLY-+Qx0G>I({eGN&$vRNFWvg%|gjpCb1isF1W7ruU4y`_4 L{YzMMGftx~3{hEQ literal 0 Hc$@ 2*self.period: +# return 0 + + self.fileList = fileList + self.mutex.release() + return 1 + + def run(self): + + if not self.status: + print "Finishing FTP service" + return + + if not self.cd(self.remotefolder): + raise ValueError, "Could not access to the new remote directory: %s" %self.remotefolder + + while True: + + for i in range(self.period): + if self.stopFlag: + break + sleep(1) + + if self.stopFlag: + break + +# self.bussy = True + self.mutex.acquire() + + print "[Remote Server] Opening %s" %self.__server + if not self.open(self.__server, self.__username, self.__password, self.__remotefolder): + self.mutex.release() + continue + + for thisFile in self.fileList: + self.upload(thisFile, self.remotefolder) + + print "[Remote Server] Closing %s" %self.__server + self.close() + + self.mutex.release() +# self.bussy = False + + print "[Remote Server] Thread stopped successfully" + +class FTPClient(Remote): + + __ftpClientObj = None + + def __init__(self, server, username, password, remotefolder, period=60): + """ + """ + Remote.__init__(self, server, username, password, remotefolder, period) + + def open(self, server, username, password, remotefolder): + + """ + This method is used to set FTP parameters and establish a connection to remote server + + Inputs: + server - remote server IP Address + + username - remote server Username + + password - remote server password + + remotefolder - remote server current working directory + + Return: + Boolean - Returns 1 if a connection has been established, 0 otherwise + + Affects: + self.status - in case of error or fail connection this parameter is set to 0 else 1 + + """ + + if server == None: + raise ValueError, "FTP server should be defined" + + if username == None: + raise ValueError, "FTP username should be defined" + + if password == None: + raise ValueError, "FTP password should be defined" + + if remotefolder == None: + raise ValueError, "FTP remote folder should be defined" + + try: + ftpClientObj = ftplib.FTP(server) + except ftplib.all_errors, e: + print "[FTP Server]: FTP server connection fail: %s" %server + print "[FTP Server]:", e + self.status = 0 + return 0 + + try: + ftpClientObj.login(username, password) + except ftplib.all_errors: + print "[FTP Server]: FTP username or password are incorrect" + self.status = 0 + return 0 + + if remotefolder == None: + remotefolder = ftpClientObj.pwd() + else: + try: + ftpClientObj.cwd(remotefolder) + except ftplib.all_errors: + print "[FTP Server]: FTP remote folder is invalid: %s" %remotefolder + remotefolder = ftpClientObj.pwd() + + self.server = server + self.username = username + self.password = password + self.remotefolder = remotefolder + self.__ftpClientObj = ftpClientObj + self.status = 1 + + return 1 + + def close(self): + """ + Close connection to remote server + """ + if not self.status: + return 0 + + self.__ftpClientObj.close() + + def mkdir(self, remotefolder): + """ + mkdir is used to make a new directory in remote server + + Input: + remotefolder - directory name + + Return: + 0 in error case else 1 + """ + if not self.status: + return 0 + + try: + self.__ftpClientObj.mkd(dirname) + except ftplib.all_errors: + print "[FTP Server]: Error creating remote folder: %s" %remotefolder + return 0 + + return 1 + + def cd(self, remotefolder): + """ + cd is used to change remote working directory on server + + Input: + remotefolder - current working directory + + Affects: + self.remotefolder + + Return: + 0 in case of error else 1 + """ + if not self.status: + return 0 + + if remotefolder == self.remotefolder: + return 1 + + try: + self.__ftpClientObj.cwd(remotefolder) + except ftplib.all_errors: + print '[FTP Server]: Error changing to %s' %remotefolder + print '[FTP Server]: Trying to create remote folder' + + if not self.mkdir(remotefolder): + print '[FTP Server]: Remote folder could not be created' + return 0 + + try: + self.__ftpClientObj.cwd(remotefolder) + except ftplib.all_errors: + return 0 + + self.remotefolder = remotefolder + + return 1 + + def sendFile(self, fullfilename): + + if not self.status: + return 0 + + fp = open(fullfilename, 'rb') + + filename = os.path.basename(fullfilename) + + command = "STOR %s" %filename + + try: + self.__ftpClientObj.storbinary(command, fp) + except ftplib.all_errors, e: + print "[FTP Server]:", e + return 0 + + try: + self.__ftpClientObj.sendcmd('SITE CHMOD 755 ' + filename) + except ftplib.all_errors, e: + print "[FTP Server]:", e + + fp.close() + + return 1 + +class SSHClient(Remote): + + __sshClientObj = None + __scpClientObj = None + + def __init__(self, server, username, password, remotefolder, period=60): + """ + """ + Remote.__init__(self, server, username, password, remotefolder, period) + + def open(self, server, username, password, remotefolder, port=22): + + """ + This method is used to set SSH parameters and establish a connection to a remote server + + Inputs: + server - remote server IP Address + + username - remote server Username + + password - remote server password + + remotefolder - remote server current working directory + + Return: void + + Affects: + self.status - in case of error or fail connection this parameter is set to 0 else 1 + + """ + import socket + + if server == None: + raise ValueError, "SSH server should be defined" + + if username == None: + raise ValueError, "SSH username should be defined" + + if password == None: + raise ValueError, "SSH password should be defined" + + if remotefolder == None: + raise ValueError, "SSH remote folder should be defined" + + sshClientObj = paramiko.SSHClient() + + sshClientObj.load_system_host_keys() + sshClientObj.set_missing_host_key_policy(paramiko.WarningPolicy()) + + self.status = 0 + try: + sshClientObj.connect(server, username=username, password=password, port=port) + except paramiko.AuthenticationException, e: +# print "SSH username or password are incorrect: %s" + print "[SSH Server]:", e + return 0 + except SSHException, e: + print "[SSH Server]:", e + return 0 + except socket.error: + self.status = 0 + print "[SSH Server]:", e + return 0 + + self.status = 1 + scpClientObj = scp.SCPClient(sshClientObj.get_transport(), socket_timeout=30) + + if remotefolder == None: + remotefolder = self.pwd() + + self.server = server + self.username = username + self.password = password + self.__sshClientObj = sshClientObj + self.__scpClientObj = scpClientObj + self.status = 1 + + if not self.cd(remotefolder): + raise ValueError, "[SSH Server]: Could not access to remote folder: %s" %remotefolder + return 0 + + self.remotefolder = remotefolder + + return 1 + + def close(self): + """ + Close connection to remote server + """ + if not self.status: + return 0 + + self.__scpClientObj.close() + self.__sshClientObj.close() + + def __execute(self, command): + """ + __execute a command on remote server + + Input: + command - Exmaple 'ls -l' + + Return: + 0 in error case else 1 + """ + if not self.status: + return 0 + + stdin, stdout, stderr = self.__sshClientObj.exec_command(command) + + result = stderr.readlines() + if len(result) > 1: + return 0 + + result = stdout.readlines() + if len(result) > 1: + return result[0][:-1] + + return 1 + + def mkdir(self, remotefolder): + """ + mkdir is used to make a new directory in remote server + + Input: + remotefolder - directory name + + Return: + 0 in error case else 1 + """ + + command = 'mkdir %s' %remotefolder + + return self.__execute(command) + + def pwd(self): + + command = 'pwd' + + return self.__execute(command) + + def cd(self, remotefolder): + """ + cd is used to change remote working directory on server + + Input: + remotefolder - current working directory + + Affects: + self.remotefolder + + Return: + 0 in case of error else 1 + """ + if not self.status: + return 0 + + if remotefolder == self.remotefolder: + return 1 + + chk_command = "cd %s; pwd" %remotefolder + mkdir_command = "mkdir %s" %remotefolder + + if not self.__execute(chk_command): + if not self.__execute(mkdir_command): + self.remotefolder = None + return 0 + + self.remotefolder = remotefolder + + return 1 + + def sendFile(self, fullfilename): + + if not self.status: + return 0 + + try: + self.__scpClientObj.put(fullfilename, remote_path=self.remotefolder) + except scp.ScpError, e: + print "[SSH Server]", str(e) + return 0 + + remotefile = os.path.join(self.remotefolder, os.path.split(fullfilename)[-1]) + command = 'chmod 775 %s' %remotefile + + return self.__execute(command) + +class SendToServer(ProcessingUnit): + + def __init__(self): + + ProcessingUnit.__init__(self) + + self.isConfig = False + self.clientObj = None + + def setup(self, server, username, password, remotefolder, localfolder, ext='.png', period=60, protocol='ftp', **kwargs): + + self.clientObj = None + self.localfolder = localfolder + self.ext = ext + self.period = period + + if str.lower(protocol) == 'ftp': + self.clientObj = FTPClient(server, username, password, remotefolder, period) + + if str.lower(protocol) == 'ssh': + self.clientObj = SSHClient(server, username, password, remotefolder, period) + + if not self.clientObj: + raise ValueError, "%s has been chosen as remote access protocol but it is not valid" %protocol + + self.clientObj.start() + + def findFiles(self): + + if not type(self.localfolder) == list: + folderList = [self.localfolder] + else: + folderList = self.localfolder + + #Remove duplicate items + folderList = list(set(folderList)) + + fullfilenameList = [] + + for thisFolder in folderList: + + print "[Remote Server]: Searching files on %s" %thisFolder + + filenameList = glob.glob1(thisFolder, '*%s' %self.ext) + + if len(filenameList) < 1: + continue + + for thisFile in filenameList: + fullfilename = os.path.join(thisFolder, thisFile) + + if fullfilename in fullfilenameList: + continue + + #Only files modified in the last 30 minutes are considered + if os.path.getmtime(fullfilename) < time.time() - 30*60: + continue + + fullfilenameList.append(fullfilename) + + return fullfilenameList + + def run(self, **kwargs): + + if not self.isConfig: + self.init = time.time() + self.setup(**kwargs) + self.isConfig = True + + if time.time() - self.init >= self.period: + fullfilenameList = self.findFiles() + + if self.clientObj.updateFileList(fullfilenameList): + print "[Remote Server]: Sending the next files ", str(fullfilenameList) + + self.init = time.time() + + def close(self): + print "[Remote Server] Stopping thread" + self.clientObj.stop() + + +class FTP(object): + """ + Ftp is a public class used to define custom File Transfer Protocol from "ftplib" python module + + Non-standard Python modules used: None + + Written by "Daniel Suarez":mailto:daniel.suarez@jro.igp.gob.pe Oct. 26, 2010 + """ + + def __init__(self,server = None, username=None, password=None, remotefolder=None): + """ + This method is used to setting parameters for FTP and establishing connection to remote server + + Inputs: + server - remote server IP Address + + username - remote server Username + + password - remote server password + + remotefolder - remote server current working directory + + Return: void + + Affects: + self.status - in Error Case or Connection Failed this parameter is set to 1 else 0 + + self.folderList - sub-folder list of remote folder + + self.fileList - file list of remote folder + + + """ + + if ((server == None) and (username==None) and (password==None) and (remotefolder==None)): + server, username, password, remotefolder = self.parmsByDefault() + + self.server = server + self.username = username + self.password = password + self.remotefolder = remotefolder + self.file = None + self.ftp = None + self.status = 0 + + try: + self.ftp = ftplib.FTP(self.server) + self.ftp.login(self.username,self.password) + self.ftp.cwd(self.remotefolder) +# print 'Connect to FTP Server: Successfully' + + except ftplib.all_errors: + print 'Error FTP Service' + self.status = 1 + return + + + + self.dirList = [] + + try: + self.dirList = self.ftp.nlst() + + except ftplib.error_perm, resp: + if str(resp) == "550 No files found": + print "no files in this directory" + self.status = 1 + return + + except ftplib.all_errors: + print 'Error Displaying Dir-Files' + self.status = 1 + return + + self.fileList = [] + self.folderList = [] + #only for test + for f in self.dirList: + name, ext = os.path.splitext(f) + if ext != '': + self.fileList.append(f) +# print 'filename: %s - size: %d'%(f,self.ftp.size(f)) + + def parmsByDefault(self): + server = 'jro-app.igp.gob.pe' + username = 'wmaster' + password = 'mst2010vhf' + remotefolder = '/home/wmaster/graficos' + + return server, username, password, remotefolder + + + def mkd(self,dirname): + """ + mkd is used to make directory in remote server + + Input: + dirname - directory name + + Return: + 1 in error case else 0 + """ + try: + self.ftp.mkd(dirname) + except: + print 'Error creating remote folder:%s'%dirname + return 1 + + return 0 + + + def delete(self,filename): + """ + delete is used to delete file in current working directory of remote server + + Input: + filename - filename to delete in remote folder + + Return: + 1 in error case else 0 + """ + + try: + self.ftp.delete(filename) + except: + print 'Error deleting remote file:%s'%filename + return 1 + + return 0 + + def download(self,filename,localfolder): + """ + download is used to downloading file from remote folder into local folder + + Inputs: + filename - filename to donwload + + localfolder - directory local to store filename + + Returns: + self.status - 1 in error case else 0 + """ + + self.status = 0 + + + if not(filename in self.fileList): + print 'filename:%s not exists'%filename + self.status = 1 + return self.status + + newfilename = os.path.join(localfolder,filename) + + self.file = open(newfilename, 'wb') + + try: + print 'Download: ' + filename + self.ftp.retrbinary('RETR ' + filename, self.__handleDownload) + print 'Download Complete' + except ftplib.all_errors: + print 'Error Downloading ' + filename + self.status = 1 + return self.status + + self.file.close() + + return self.status + + + def __handleDownload(self,block): + """ + __handleDownload is used to handle writing file + """ + self.file.write(block) + + + def upload(self,filename,remotefolder=None): + """ + upload is used to uploading local file to remote directory + + Inputs: + filename - full path name of local file to store in remote directory + + remotefolder - remote directory + + Returns: + self.status - 1 in error case else 0 + """ + + if remotefolder == None: + remotefolder = self.remotefolder + + self.status = 0 + + try: + self.ftp.cwd(remotefolder) + + self.file = open(filename, 'rb') + + (head, tail) = os.path.split(filename) + + command = "STOR " + tail + + print 'Uploading: ' + tail + self.ftp.storbinary(command, self.file) + print 'Upload Completed' + + except ftplib.all_errors: + print 'Error Uploading ' + tail + self.status = 1 + return self.status + + self.file.close() + + #back to initial directory in __init__() + self.ftp.cwd(self.remotefolder) + + return self.status + + + def dir(self,remotefolder): + """ + dir is used to change working directory of remote server and get folder and file list + + Input: + remotefolder - current working directory + + Affects: + self.fileList - file list of working directory + + Return: + infoList - list with filenames and size of file in bytes + + self.folderList - folder list + """ + + self.remotefolder = remotefolder + print 'Change to ' + self.remotefolder + try: + self.ftp.cwd(remotefolder) + except ftplib.all_errors: + print 'Error Change to ' + self.remotefolder + infoList = None + self.folderList = None + return infoList,self.folderList + + self.dirList = [] + + try: + self.dirList = self.ftp.nlst() + + except ftplib.error_perm, resp: + if str(resp) == "550 No files found": + print "no files in this directory" + infoList = None + self.folderList = None + return infoList,self.folderList + except ftplib.all_errors: + print 'Error Displaying Dir-Files' + infoList = None + self.folderList = None + return infoList,self.folderList + + infoList = [] + self.fileList = [] + self.folderList = [] + for f in self.dirList: + name,ext = os.path.splitext(f) + if ext != '': + self.fileList.append(f) + value = (f,self.ftp.size(f)) + infoList.append(value) + + if ext == '': + self.folderList.append(f) + + return infoList,self.folderList + + + def close(self): + """ + close is used to close and end FTP connection + + Inputs: None + + Return: void + + """ + self.ftp.close() + +class SendByFTP(Operation): + + def __init__(self): + + self.status = 1 + self.counter = 0 + + def error_print(self, ValueError): + + print ValueError, 'Error FTP' + print "don't worry the program is running..." + + def worker_ftp(self, server, username, password, remotefolder, filenameList): + + self.ftpClientObj = FTP(server, username, password, remotefolder) + for filename in filenameList: + self.ftpClientObj.upload(filename) + self.ftpClientObj.close() + + def ftp_thread(self, server, username, password, remotefolder): + if not(self.status): + return + + import multiprocessing + + p = multiprocessing.Process(target=self.worker_ftp, args=(server, username, password, remotefolder, self.filenameList,)) + p.start() + + p.join(3) + + if p.is_alive(): + p.terminate() + p.join() + print 'killing ftp process...' + self.status = 0 + return + + self.status = 1 + return + + def filterByExt(self, ext, localfolder): + fnameList = glob.glob1(localfolder,ext) + self.filenameList = [os.path.join(localfolder,x) for x in fnameList] + + if len(self.filenameList) == 0: + self.status = 0 + + def run(self, dataOut, ext, localfolder, remotefolder, server, username, password, period=1): + + self.counter += 1 + if self.counter >= period: + self.filterByExt(ext, localfolder) + + self.ftp_thread(server, username, password, remotefolder) + + self.counter = 0 + + self.status = 1 + diff --git a/schainpy/model/utils/.svn/text-base/jroutils_ftp.pyc.svn-base b/schainpy/model/utils/.svn/text-base/jroutils_ftp.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..aea5a3029488f73baa6d120d70c8120c4adb50a6 GIT binary patch literal 28498 zc%1EBYj7OdRleQx(u`&-SzgO_ypN6_S!J`9?cHpacz46@TK0M$(Yi)n zo%`sX8Og8RQ34ft)#|?8ef!>X&pnUtoO?I(y-MlSd%r*55b7sGzt7Tdbixv%DZ~OD zEzz_^%MuHgKDWh!tt z5DNw27R2g^SQz2LEFNeV#X?b7xXy`INwi1B!l-DM#RApX%nNr!EYZD!cvFa*LVReU zBAO$@t#E14l>I#HwJw7kWz9(r!%l)NQplipab`>_)TPB(I$xw%VDCk*1C5wy6h(+cWM zXUS{P3v?Z?xK8ATH{5WF22jK~w65j4ohcia`{-~v3>t0}dH(Wiz8A+uDtfi!hV|GB z{5VfnRkt0)u3-th_&lol8Xa80Y#^8c_VHNn!zkmJ=VJi_NW-`+FnVqYVO$#GO zj6f8`SY`QSA4V4^G$MIE8CPSvupbrDkmAJ&HKZUrk0=W7QzN=?5Tl8cNi~`aheUO5 zY7EVOk_b_9=tuU;@gk=Vvb#jpMyno0AZ!!FYr0FG?=lS+-Ie+cFX)C&u;g64a+!w* z#OF7rohvIYjRr1=?o=0lK-Z%NB?z5nuE&Q?y5l;|OI?53IrI3V&SPiJK4Gfi6YpsvU;{jXU+~g-Q1q|BNyk&-sfsp$1r8BcwDUR#~JFK02j|qWvMT- z9{4;uMu(qPOftuF=$b<_!>5^|=F~aoWE7p<;jxpEdV(fvV4^K`TdmEh z1E3kGcx5GY>&U#2axpiowY>`O#WUek$Id zE+bwE{d(K&E$tAqt_NW=KA0|*Y`7G(np6uuLet+1WShXKuXs_+lH+2%Ma{z5VmFF5 z`GF`7Iu~2@Wo{;V%J&J9gF)L5x|ei#Jt>4;{sDd}vU zrWxk8PIqIk6`iK}z$dk(xHH|^tfI9T2ZE zC&xSF`g`XhI;UETk1QsI{JuEG8I4P1K)QWtfJH;fUs;38_*1?I}Lf8w2KnAQ;?@597&wM z8!ySxRqsxlYNHeMkr&&YmfMD?j#o%<6LYKtP@Ya>#Um}s70yakhZ!~-#O4jRc_9pg za8Jltg%wam&7hpf-Z3E`?I9#4QJP+cqW4Oa>VxR=o=^bfznY?et$Keu3Ov$70nIdW zt{a8<*7|Sj{#TC4ooV^KtbaxXH0nREu1{c@gB&9gq5r)w&`b6ID49jc&+R@*OarIeF3VbmJ(oTJZx5 zNRv>Po#Ilm!{Zf)%gN5}Z2@Vg&`o{Ow4$eOb5V8UZs_-Y`3&B7p$41=nd**9_Kb7( zZJIJ{nxy+SYIyY>Vh5vk6({--}lId>{{VXqJ6|>S3*Ns$gukM&aL99Tc7H zk-*gxd!e4tD%togp#U9GIZQTjmTdj9Jw|`WEL`PmBZ4hG=dyCnN$Wm(EUm9VpBrwE zw%S>O&dS~;3i+LT&||vm#_ktxrC!d_!3Yybiv!$MDKSWzz_C`Iz7{sC87@t9(Y;ZG zIg*)%z4R);tLh}!1(K%TxZb4+!{;G&gP1=>ynRC^-aclRCK;<2mBaj-_zpCJ$bnfZ zBSots9V(E(U?(Rnp=cRRfRH3Rg{Gzy&ycZC0!&f3hb<;Q&VqU4Uola_qt?bWfISI+ z(9<*59uV7>0z$%uxa_mp(v)z_^~+*j-TEls!bMT6mgE>Q5VJa}wL@85;#d(0+A;=g zCHfov@;JYI{Tw&z1eflob{v5U!Nr8ae9#@69{dL}-^}%X>44;%zWU}#B}tO7I+=|C zTwG*n0?`A{5nSStP&osVGM4HGu~TO`qb(QTT_2FD0B@L^*hSwB=pnhb(`~qB>h^nf zxGg~)XoF6tANjdYOF1drAjo3)|36i4bzPRN3<9w45JJN-!oipTJW9#()pz3nd_}sN zsGtgKv<1gR6dPQkPyw$jF_+v*hPC1 zLe$y^!J4Tsj8d`k_PBM3&P(?G%HJ+fp-?lY){)<>v6U(VZk zi~q^LcKQBdu9%nq%K2is?9kbL47kypIN$QfejP;YUl0bdFCa|QWHklkJj;N*VCY@~ z@_7x&7c?M0q5=6Luyl+_FCJXbG7aQ2crbK<%}8$+=;`@FKM0+0FY6**@eZ>g8~EA@!nHP=rD$8A1J-b_I1 zJ6!i7ckq+XEiKW@(K)AYJX%ZBGD@P0POc z)kSofV^)>^7o@lM-W}^PeFzesLX4BB+6Y2$1nc#|7kisc1oiwI^_JH(me=eQYh+g1 z=mYy8Bz{}oBAX3V2`l@0t5xH1i==x95!?!vJ)fWItT*{@W4*bPqKHveGg`3*`7Tdi zU0h|Wa#tNA5uMcIY&s3oT4GD&yQujh>Ys$Knf}dK2doJhd$MwLb)Pj(#uU!W))-yy zr|Y6MuH#c2qcXt<@PmfpEa3S7pFqi?5a#h8Cu6SeDW zaB<;>+%E>F+uI5~b!z23sJqiu@5;>1AUF3a_?;M9di%$A<7yBHEoTID2c3E)+*G$!EW3yO z8Gq<~q1vPW8U~vn%`IzaO7$~hd>R&%K-iKA!fd;Tv&4bk#Vi5LDk?<=I@2>{jJ*E_Ej932b>Xz zd2pSao*aW!FKp@Ab9M8uezS-;cvSv-h7+Gpy0Powv)m;`w5+ zc(C{`MpWkJF71Y>EDD3Dlo(MdF_vO*l^nPph>CR^L`9`ImN>sraFV3VZ!80B0Vn;x z2U`#-RA7rYsrw3+8PR?HYs;h`3$dM7LIvvh1m-}3rr5gtX)e#E&=*;Lh0Aj(^hK7p zxIC}QW0q3DEDB<)0NKJAbpgT&_ZZLMRIY-`U)(&-4;Hy;BixW8f40QqVP!}jEs{LS zK;l3i{Ts=n5vpL6=eiv@U~=VByTEB0Vy(NRxTx|UP1{1X9#E4qRl9F+co4w)z)0PILgLFTx)y03c%c{ zb%K`H*o@Jc`Feu0-4mZmBmHZ1hZ(2ti<|9!on5dYdG#M4N@9JeN5h*_MTz&1O~u%dO8A)+)e zG-g%EVA}~GLY!-NfCv|vw;L_ukUksB$QqS);JnyN$mkzIU$j6%Mit9=HW^Kqja}&? zU76Q2@NdYWAvH?cP9{E(zY$AwOqwfM5xyi}&g}j~j7xgx2pKib921#graw#*xmI&G z+(uWWRkO(tKmP7PCH*o>?h703dZ*<&54R%cRO{il4^Uzu$bx(-XGVKoPbGAvrW(Q$ z0U`7jiP?zdM9cM4HYy^Saxqif^nA54qDf<_PpK(1@~2*1Ra zFy|&XWoUxtDDzWKhAa9alk+B3ri4(LcFJb|e}yXYGnS+kLsOqNZzJQxsK zgFvQ2D7V>J;&Z>+2t=~>aW=#pUrh6ikuBdGzyl2xL=FhU9%B+Q8vNcb!LT)Fvx zNNZD-?FM$U$Z3988V9eEV{8jvLmcN7hbk0MB7Lhx^|HDwsp(40edH!9Xo(O4aa0Lz zSvj4-xC;Cm6?&yv4R{?V^QEnH)?{4TSRn#APd@nsoLIA?}#wE-yMC_)Fe04*?q}4dbNji8+nt%-A{tixra=E2!y?zsxu$ z^F2M>U{F#>GaJ5E^hZMIzFIl~h-i>kWKi%^7E=Tvf)Sq9QkBhPy7xe!1#wfWDPQ!y zB9X68fnc|IMM|XTw?IYc$Pt}^D)j)TS{Ke>5`g<};a$6eYTGOApUiqz^ zd$WRnu^T&H3`GgopOYnI6oKcGkHazj0e2&oS&g0+7_DI44H?a5CYMNnG?MFKd>d~U z^;WM7h4o4RK{bmF>9zHGxEu|8v0Ow7wevDKXHtn7>8c*I9^_x-Ht?(|D4yY2V_ABQ z?JA4;mmch*E?E}v+%~?B!kKGdV-;bsig@9YR6JWI13ND! zp+vIGZmc(mHP%QPe@0w?g;StcQ9g5Rkv+Q+m0t}8%W()S&-_e{%!}|Z#P!b$nW2rx zMsW*WCS1F=FV=`)UY(30 zaM2?wXwN_tPfc%xD&oW(#%|F1u-@sAtW6SeSg}ciix-{)Cr&TM;X*va$;)!lI_K%6?pIF>r7MT+`7L>J z4OVo`)-h9J)G@o5nIK~vOT~}a6Qp7))1Wa{I7st@^Pct0{!+ zKW6jN3n^@Xh?VX8>371K*Z~)VP~t@za;PN1QVaQ`hXx7d%wZLPBorVG=^S#$k$b*( z_}1r)n`q@MIo}dvjSYw!W?VoS8EFwSEw8cjjxmjH6bEgGSJ++w zioHaB>1D0td5P08ndW%R>7@5~Nw#je?LIKO?*HN(>)CI}?D^8<(&>mx2X=jVwGmG{ zkG+p~eL2H5a>6@AoC&}Fol1Dmvg!0PM>oxRCUu@oo$FchdKPNdprZ+5VCx`bMh6+Q zIs-f>REteszKSFgb)&4(L}YRZa^Q>5sPHTQ zTP66BFPYI{)hs!cYBQRBVslbgKc+?HJ~8jVE-M-5N-kTRVG{4xfNqXS5m|C6Q@Y~b zuZJq0yUW)n^qx2e#KtAH6l><%Gq5J&`^4%&j=i#3@VbqF_4WwNRbuJ24Cw<)F2holx0s+;z*na27Orl2^=^-(4>V?bJ!xr zdwxrq#*8}FI&RozyGky6`&p4T%jFINfSBM&eiUsj8tZGfhS8Mka1Q*E{2nsbt`FHj zfExOutux|}oUx9kgP7zSW~_tO5$jM!Wx{7sG6@5YuM4)$kjJy*)?uqGm*JvbvrEF1 z(CB`XQxr)8Z?i_*&i23qOAwbi!!y*@Q{=y-G%1hCdb=Lc9O9v9M=@0Djg=*~9wlki z1E-h6`jXcOlv|y<75#@v;!jeA|E_H?Vd73{NDl<9R2O^ak z|4q>w#2N@;y~W^_N-CF<;$GrbXLpKQCGw7~`dg;HYbTn=i0ylxy&o`_JgPrA%x_)!v>bwj_Z7YZIoh{)ub|#QllVaMI**G=|u}=nCR#A zOj4n)SmnjX2;5*nU#+%6UPsH-6{i+WFm#bbNip{%hzW1rch~n|izePcU^1gtoQO&> zGsXr>!9HkD*qEB{z*0Rf8?h_);8rW>XTO9_(z%}#J()ngq)2nWyyL8gUaTiTe;PPQ z%_uG&O6{8>_xdDeTpK2i3WT@61J7hc&&F^)3rxNvWRCZUT6w>f+ODdpQH9NxLIBL} zRaTr!)}csgm4u5e?Kv|%(PV4y(6&S%vRasN+V+;&YsKb;_gavR>cs3nVL_Hx@2L!J zz5j_3WR-L-T{a0`sNHjwY`e6>{#gSXXJJ@xy>r$*39}#dy{_&_%vGNSS;0!Yq9=kt zFdJZzJR3LHMus)HPzteRudIO;%x3#4ss7LP3bI7PVfVi3j1ZzQ!*+?hs7dytl-SA~kb-L@JwLy08FWuiNa{4r zh4dO*V{*Pu&KK-g3hM44WPT#G2Q8`W?5F z*fDinKaT(Adm7DI3DF<)*i*eJhmGC#A?>&684z4{V{KpI(x5m$?5wU^fJ=9Q$o16g z`Ab1kCD*p@k?hnmRW4eIyf;{qY9DEFGfwSb*z=X7v3V)OOl7=rmW!fz z^)o2`EDpaUR1yOlE;q2F*08s>A}Vz<8l4(1T4hTvjV)Vwl92oCG#Zs>gKu1&?X&YN zMI|PMMze$5Oxa<^DWibB?Cm9|6%)x_<2L(FW@n&p*zH)L!)iyKq9*k&*F&+*Q%m z`v`I;crmPr2Jo(^s)dvpQW`p8upHLgm`-8W$Lgo)>FNGWIUgNvH`!fPV1DTN z@t^nfSg!*%cGpWn=0T+Z>zi3MfEy3OahbU`$+m?t!c;KuA-O4JvR7x4WXN7LM<1Rx zQ-x>AEw|38eq0P6^I~8CmAD~FzLn7ncI6267;I32T6DX`bozzT^KFbfnk{%o z-m-nlD%sdfvPA!KTt>4cBl%WZ6|#Bv0A~#N8U<-5O2`AiN}e-( zS#BveP^P*mvSxNxL@c9z9f#k;;dc!YO-NJ5O6zg`)oz>+RPt;e9}j!41LRhH*8ugr zNMhWcB(|0O(U+6;8#sK~^oskpCp(aSi7NbtZf4#t=ICFcc(7QIJJ>#MIG7olEq%0s z*En$IUzMNZp+O5{2hCJpp5`x4Ln2Mnhw-?-*OJ#2CN3qiw~E~Ouui2mE_=1vb$%>wLAF=R*g-)6M1leV z2pG!ZhCFF~%pp~Ij=V`;BUL%)0h0b20Hs5G)QZAzX1X!c)ARM$&C-9`&C7rNl{;}Q+HRpc5JC>p4uZ_vOf`Xw5aihh~K6&hD*P?4Du1vQ$~X;3HSmdR_- z8P8Ve4be5xt3i|8Dh7iUa%<$(MOpaFB<<)-*9HGx#}#Zk@y(bE2K&1I!+!Wp4L-ADtaw(aZo$rCyLvp-EqG(;r0>ukR(kbKd_x zO3u^RcD#P-jBGzlqDc4CXqqf%;#q$Zxn9tpYClN(<0O)f6;DqCKOObrnT9o%m3VPt zS*zH^kb@oI4s&5>Pdv-gO&Rcd(}0I&sj%ygEi~bdc41jnEgf1e96Exj1cz!x*9IlK zqzw$O6&>e-k_eul!@hqbljAZV@|3l1DON~V>C6yymvjwIz)}n%{>m>*Y$)Y6q13>G=eaIRQ@Wt{<8Y36rq(tD_(axU%V9XmM% z-X9OW(7TG0PqvrdCJ7w5dO!8URNJBBv5$zvTyqIk*LSqc``VkNGQ~@0Q+gT)p2oo@ zc5GIc5XVe(I=*ZCU_-=bx+=(CQ%!#M)V6A?EU+`xr?$42fn6>F`}lTXgRdxODg-&R zQ3dq!MxZvRf~=T&@L#4kB~TU<73hhj4bT(bYJwWzR{zES<%jn(IFD5hVU>Z|67--` zxeX(n&ZL`Q^+R8Cu)^=p>>%}I+D{Lo@XQ~|y&OfMr}3H-_+F@G9n*LVfxO9!{sgOI zb28dSLph~9kd~)^ha_g$!{;SRw&339pNEtk8Jb7FSh&m0*MO_%XwU7se(FSF$OGo< zUUm{_oA(OWOj9p$`Hm&H66daY6_Fi<){R|1$5v%Ic}w|!sQM<&&H? zSBl9RmPMzImCeI6g<|G=6~2mf&Me zmDC6Pw3(!~Rf9ib9nfo~vE#rqn>ls_H-?cVH16(8N6AH&>905RK@^HRaMh9x7ZqTE zhnxqu7geB3OW`%If_AnRH5u11b_HxD;j%}BW|KJ3qU}`zT%t>c9+PKSk?Z-<0L+bv!o3=Y!%3gljzJ3 zycCE$9Ci0o0UhI*BQ3}V9Ijq+$!TT#CU5%Tu#5M*I_myqA@Oz*r3VsaP%|GC_I#C0 zJqccpRa@&s%8D>bCeLg~Gn-)Ja5~9@B8Y~+d?@PnCD-A@tn5ffcDyV=_#NzE-OAvW z^~Gl=M_+$&@}rVhlJxUq{Sh@vRcJ}d6>K-v4%{Sl17EF}`xQ_8Eigg5zUlRS}lXP7*M03R@j)7ThGOz?ol8v$dCTuV=Ameh9rjNu5jd zT73Q5eInoXzynB^>&E$Pw+JU_N**DKct9^%2G>Tkv52BqS%*>Z)UeR0nWwybK!T_nPt438-jYe&)ve9lm5H1odS(Y0) z{Cn{kOnZvvV~9Eevr*JTitlBmsQLc#S`b2o9X+w5$Nc2<*bIDIr*`T|*=vf!~ fZ@i_$OJqLIehq&DAg3L1LQCPZVRTA6 + +""" +Utilities for sending files over ssh using the scp1 protocol. +""" + +__version__ = '0.10.0' + +import locale +import os +import re +from socket import timeout as SocketTimeout + + +# this is quote from the shlex module, added in py3.3 +_find_unsafe = re.compile(br'[^\w@%+=:,./~-]').search + + +def _sh_quote(s): + """Return a shell-escaped version of the string `s`.""" + if not s: + return b"" + if _find_unsafe(s) is None: + return s + + # use single quotes, and put single quotes into double quotes + # the string $'b is then quoted as '$'"'"'b' + return b"'" + s.replace(b"'", b"'\"'\"'") + b"'" + + +# Unicode conversion functions; assume UTF-8 + +def asbytes(s): + """Turns unicode into bytes, if needed. + Assumes UTF-8. + """ + if isinstance(s, bytes): + return s + else: + return s.encode('utf-8') + + +def asunicode(s): + """Turns bytes into unicode, if needed. + Uses UTF-8. + """ + if isinstance(s, bytes): + return s.decode('utf-8', 'replace') + else: + return s + + +# os.path.sep is unicode on Python 3, no matter the platform +bytes_sep = asbytes(os.path.sep) + + +# Unicode conversion function for Windows +# Used to convert local paths if the local machine is Windows + +def asunicode_win(s): + """Turns bytes into unicode, if needed. + """ + if isinstance(s, bytes): + return s.decode(locale.getpreferredencoding()) + else: + return s + + +class SCPClient(object): + """ + An scp1 implementation, compatible with openssh scp. + Raises SCPException for all transport related errors. Local filesystem + and OS errors pass through. + Main public methods are .put and .get + The get method is controlled by the remote scp instance, and behaves + accordingly. This means that symlinks are resolved, and the transfer is + halted after too many levels of symlinks are detected. + The put method uses os.walk for recursion, and sends files accordingly. + Since scp doesn't support symlinks, we send file symlinks as the file + (matching scp behaviour), but we make no attempt at symlinked directories. + """ + def __init__(self, transport, buff_size=16384, socket_timeout=5.0, + progress=None, sanitize=_sh_quote): + """ + Create an scp1 client. + @param transport: an existing paramiko L{Transport} + @type transport: L{Transport} + @param buff_size: size of the scp send buffer. + @type buff_size: int + @param socket_timeout: channel socket timeout in seconds + @type socket_timeout: float + @param progress: callback - called with (filename, size, sent) during + transfers + @param sanitize: function - called with filename, should return + safe or escaped string. Uses _sh_quote by default. + @type progress: function(string, int, int) + """ + self.transport = transport + self.buff_size = buff_size + self.socket_timeout = socket_timeout + self.channel = None + self.preserve_times = False + self._progress = progress + self._recv_dir = b'' + self._rename = False + self._utime = None + self.sanitize = sanitize + self._dirtimes = {} + + def __enter__(self): + self.channel = self._open() + return self + + def __exit__(self, type, value, traceback): + self.close() + + def put(self, files, remote_path=b'.', + recursive=False, preserve_times=False): + """ + Transfer files to remote host. + @param files: A single path, or a list of paths to be transfered. + recursive must be True to transfer directories. + @type files: string OR list of strings + @param remote_path: path in which to receive the files on the remote + host. defaults to '.' + @type remote_path: str + @param recursive: transfer files and directories recursively + @type recursive: bool + @param preserve_times: preserve mtime and atime of transfered files + and directories. + @type preserve_times: bool + """ + self.preserve_times = preserve_times + self.channel = self._open() + self._pushed = 0 + self.channel.settimeout(self.socket_timeout) + scp_command = (b'scp -t ', b'scp -r -t ')[recursive] + self.channel.exec_command(scp_command + + self.sanitize(asbytes(remote_path))) + self._recv_confirm() + + if not isinstance(files, (list, tuple)): + files = [files] + + if recursive: + self._send_recursive(files) + else: + self._send_files(files) + + self.close() + + def get(self, remote_path, local_path='', + recursive=False, preserve_times=False): + """ + Transfer files from remote host to localhost + @param remote_path: path to retreive from remote host. since this is + evaluated by scp on the remote host, shell wildcards and + environment variables may be used. + @type remote_path: str + @param local_path: path in which to receive files locally + @type local_path: str + @param recursive: transfer files and directories recursively + @type recursive: bool + @param preserve_times: preserve mtime and atime of transfered files + and directories. + @type preserve_times: bool + """ + if not isinstance(remote_path, (list, tuple)): + remote_path = [remote_path] + remote_path = [self.sanitize(asbytes(r)) for r in remote_path] + self._recv_dir = local_path or os.getcwd() + self._rename = (len(remote_path) == 1 and + not os.path.isdir(os.path.abspath(local_path))) + if len(remote_path) > 1: + if not os.path.exists(self._recv_dir): + raise SCPException("Local path '%s' does not exist" % + asunicode(self._recv_dir)) + elif not os.path.isdir(self._recv_dir): + raise SCPException("Local path '%s' is not a directory" % + asunicode(self._recv_dir)) + rcsv = (b'', b' -r')[recursive] + prsv = (b'', b' -p')[preserve_times] + self.channel = self._open() + self._pushed = 0 + self.channel.settimeout(self.socket_timeout) + self.channel.exec_command(b"scp" + + rcsv + + prsv + + b" -f " + + b' '.join(remote_path)) + self._recv_all() + self.close() + + def _open(self): + """open a scp channel""" + if self.channel is None: + self.channel = self.transport.open_session() + + return self.channel + + def close(self): + """close scp channel""" + if self.channel is not None: + self.channel.close() + self.channel = None + + def _read_stats(self, name): + """return just the file stats needed for scp""" + if os.name == 'nt': + name = asunicode(name) + stats = os.stat(name) + mode = oct(stats.st_mode)[-4:] + size = stats.st_size + atime = int(stats.st_atime) + mtime = int(stats.st_mtime) + return (mode, size, mtime, atime) + + def _send_files(self, files): + for name in files: + basename = asbytes(os.path.basename(name)) + (mode, size, mtime, atime) = self._read_stats(name) + if self.preserve_times: + self._send_time(mtime, atime) + file_hdl = open(name, 'rb') + + # The protocol can't handle \n in the filename. + # Quote them as the control sequence \^J for now, + # which is how openssh handles it. + self.channel.sendall(("C%s %d " % (mode, size)).encode('ascii') + + basename.replace(b'\n', b'\\^J') + b"\n") + self._recv_confirm() + file_pos = 0 + if self._progress: + if size == 0: + # avoid divide-by-zero + self._progress(basename, 1, 1) + else: + self._progress(basename, size, 0) + buff_size = self.buff_size + chan = self.channel + while file_pos < size: + chan.sendall(file_hdl.read(buff_size)) + file_pos = file_hdl.tell() + if self._progress: + self._progress(basename, size, file_pos) + chan.sendall('\x00') + file_hdl.close() + self._recv_confirm() + + def _chdir(self, from_dir, to_dir): + # Pop until we're one level up from our next push. + # Push *once* into to_dir. + # This is dependent on the depth-first traversal from os.walk + + # add path.sep to each when checking the prefix, so we can use + # path.dirname after + common = os.path.commonprefix([from_dir + bytes_sep, + to_dir + bytes_sep]) + # now take the dirname, since commonprefix is character based, + # and we either have a seperator, or a partial name + common = os.path.dirname(common) + cur_dir = from_dir.rstrip(bytes_sep) + while cur_dir != common: + cur_dir = os.path.split(cur_dir)[0] + self._send_popd() + # now we're in our common base directory, so on + self._send_pushd(to_dir) + + def _send_recursive(self, files): + for base in files: + if not os.path.isdir(base): + # filename mixed into the bunch + self._send_files([base]) + continue + last_dir = asbytes(base) + for root, dirs, fls in os.walk(base): + self._chdir(last_dir, asbytes(root)) + self._send_files([os.path.join(root, f) for f in fls]) + last_dir = asbytes(root) + # back out of the directory + while self._pushed > 0: + self._send_popd() + + def _send_pushd(self, directory): + (mode, size, mtime, atime) = self._read_stats(directory) + basename = asbytes(os.path.basename(directory)) + if self.preserve_times: + self._send_time(mtime, atime) + self.channel.sendall(('D%s 0 ' % mode).encode('ascii') + + basename.replace(b'\n', b'\\^J') + b'\n') + self._recv_confirm() + self._pushed += 1 + + def _send_popd(self): + self.channel.sendall('E\n') + self._recv_confirm() + self._pushed -= 1 + + def _send_time(self, mtime, atime): + self.channel.sendall(('T%d 0 %d 0\n' % (mtime, atime)).encode('ascii')) + self._recv_confirm() + + def _recv_confirm(self): + # read scp response + msg = b'' + try: + msg = self.channel.recv(512) + except SocketTimeout: + raise SCPException('Timout waiting for scp response') + # slice off the first byte, so this compare will work in py2 and py3 + if msg and msg[0:1] == b'\x00': + return + elif msg and msg[0:1] == b'\x01': + raise SCPException(asunicode(msg[1:])) + elif self.channel.recv_stderr_ready(): + msg = self.channel.recv_stderr(512) + raise SCPException(asunicode(msg)) + elif not msg: + raise SCPException('No response from server') + else: + raise SCPException('Invalid response from server', msg) + + def _recv_all(self): + # loop over scp commands, and receive as necessary + command = {b'C': self._recv_file, + b'T': self._set_time, + b'D': self._recv_pushd, + b'E': self._recv_popd} + while not self.channel.closed: + # wait for command as long as we're open + self.channel.sendall('\x00') + msg = self.channel.recv(1024) + if not msg: # chan closed while recving + break + assert msg[-1:] == b'\n' + msg = msg[:-1] + code = msg[0:1] + try: + command[code](msg[1:]) + except KeyError: + raise SCPException(asunicode(msg[1:])) + # directory times can't be set until we're done writing files + self._set_dirtimes() + + def _set_time(self, cmd): + try: + times = cmd.split(b' ') + mtime = int(times[0]) + atime = int(times[2]) or mtime + except: + self.channel.send(b'\x01') + raise SCPException('Bad time format') + # save for later + self._utime = (atime, mtime) + + def _recv_file(self, cmd): + chan = self.channel + parts = cmd.strip().split(b' ', 2) + + try: + mode = int(parts[0], 8) + size = int(parts[1]) + if self._rename: + path = self._recv_dir + self._rename = False + elif os.name == 'nt': + path = os.path.join(asunicode_win(self._recv_dir), + parts[2].decode('utf-8')) + else: + path = os.path.join(asbytes(self._recv_dir), + parts[2]) + except: + chan.send('\x01') + chan.close() + raise SCPException('Bad file format') + + try: + file_hdl = open(path, 'wb') + except IOError as e: + chan.send(b'\x01' + str(e).encode('utf-8')) + chan.close() + raise + + if self._progress: + if size == 0: + # avoid divide-by-zero + self._progress(path, 1, 1) + else: + self._progress(path, size, 0) + buff_size = self.buff_size + pos = 0 + chan.send(b'\x00') + try: + while pos < size: + # we have to make sure we don't read the final byte + if size - pos <= buff_size: + buff_size = size - pos + file_hdl.write(chan.recv(buff_size)) + pos = file_hdl.tell() + if self._progress: + self._progress(path, size, pos) + + msg = chan.recv(512) + if msg and msg[0:1] != b'\x00': + raise SCPException(asunicode(msg[1:])) + except SocketTimeout: + chan.close() + raise SCPException('Error receiving, socket.timeout') + + file_hdl.truncate() + try: + os.utime(path, self._utime) + self._utime = None + os.chmod(path, mode) + # should we notify the other end? + finally: + file_hdl.close() + # '\x00' confirmation sent in _recv_all + + def _recv_pushd(self, cmd): + parts = cmd.split(b' ', 2) + try: + mode = int(parts[0], 8) + if self._rename: + path = self._recv_dir + self._rename = False + elif os.name == 'nt': + path = os.path.join(asunicode_win(self._recv_dir), + parts[2].decode('utf-8')) + else: + path = os.path.join(asbytes(self._recv_dir), + parts[2]) + except: + self.channel.send(b'\x01') + raise SCPException('Bad directory format') + try: + if not os.path.exists(path): + os.mkdir(path, mode) + elif os.path.isdir(path): + os.chmod(path, mode) + else: + raise SCPException('%s: Not a directory' % path) + self._dirtimes[path] = (self._utime) + self._utime = None + self._recv_dir = path + except (OSError, SCPException) as e: + self.channel.send(b'\x01' + asbytes(str(e))) + raise + + def _recv_popd(self, *cmd): + self._recv_dir = os.path.split(self._recv_dir)[0] + + def _set_dirtimes(self): + try: + for d in self._dirtimes: + os.utime(d, self._dirtimes[d]) + finally: + self._dirtimes = {} + + +class SCPException(Exception): + """SCP exception class""" + pass \ No newline at end of file diff --git a/schainpy/model/utils/__init__.pyc b/schainpy/model/utils/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e4b30b15a5bbad11348b741f6b4819616cb70e8 GIT binary patch literal 360 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 literal 0 Hc$@|D>ST9uOc%g8r5jLM7%zle3>nji|zGLK#)+L-CHQRJG%L81BtE3a{*Ne)M1j79db ztmLU&&*JA0x=SSPm=SFs?_>5TEpxlq{rTBG7R?O6RH{e$6q@t}HwS}gtPgY&c;^S- zM#*^^yPiHsy@4Bqjy{b%H`M*a&1d52!8r2u=wM=kQF<^;BI!8snf?X^**gozs7l!UwJC13{fY+OhcxaajyYARR8}4WomQ~flq2S?iW!g-n&sEK&E#)Zhdx#USFZ{KCYBQf@91G6LO zL8o#XMmU{KH^CZ&f#G0<-=DdoRLgXb9!B9=(3g8Tib8Ghnl}n`Xk;DRdJBQP!HfO~ zt7CJrT2@_or96-pr+qBf+mXkMC@W&eazak+<1Tg#_;=eDh z{yMvAi>4n5RarC?*v%wI!a+Q20$Yr#YbvXkVVjgve8bs$p`w#n1*sHptb@QHs8T-3 zX>+-ltYKMnmasB9bx6@^WRAyajs!h}h@%>vI7*D9$#bn^cNARe;4z>Et}sn*PJ_^Q zT;ET0ni@fh=}zTdgA=}<{pEsI#uvtj@}XcgyUiM~n>p3qEQqA9 zjorb8zmEo)-o9VRJVtr7K>00M0ShEJ8N_ay^6mSw<@vX6(ogRiCpbPw=_G!D&ZgjF zRh867{Ir;)wp5)zVja-yq_OA0GaET}1UHtIB{c5tNk_>=mg%oI^g$GgJ8;#K4d)eL zfrp$2x8_x#%ShohtAchm=QSDEF!lv-*GkQoZs{#$dUcxBz<4{uCCPpbnlFnA3mRfh zgSM`vl)E=?781eNaQQ~kqCSZ^O?vuGljbW}^UoGt{DbDJKP3AX&D(T!x{$qujLn&? z(2g&xF>BIyLY?Th(C1{lGi*tStwQnftbSWxbP9#GC|p$3%OLaB3Ml=NS;f1syqXQ# zGN{p`TXwc-zJ}{)DOa%F#CUL%)D3*KV(ynb@!S0HqJPF_bN%z~ zBE{g%JgkL>~u9^#zbd|4wmU<(+@m z+=rc$N%%`_@KBhquG*?;ty(R$!OXW|ZIpJ^u61ACx7zBV+T(eAeyrM+HMMv1Qvi=t z5ARVygvn0c$&#rmN{Fm#vKIFS4BjN^w^j_vU3sG@)u=i1x}dI(B=y-C+R(6(Qte-( z0Z1fRIetyxF^UF}Z|_31U4)ta63r`mOTWz4c~KZ3m37sss;X75tyb1s%?H9of+ffC zBaeSCK7(mb(fk6Uw!mx<`?C3H-d0jRG-_EIba;u($Jwvpj{)SgEly}EeAcaYX}esne-AZwu+0Df literal 0 Hc$@ \ No newline at end of file diff --git a/schainpy/schain.xml b/schainpy/schain.xml new file mode 100644 index 0000000..a671bc5 --- /dev/null +++ b/schainpy/schain.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/schainpy/scripts/.svn/all-wcprops b/schainpy/scripts/.svn/all-wcprops new file mode 100644 index 0000000..85227d5 --- /dev/null +++ b/schainpy/scripts/.svn/all-wcprops @@ -0,0 +1,695 @@ +K 25 +svn:wc:ra_dav:version-url +V 78 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts +END +JASMET30_PreProc.py +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/JASMET30_PreProc.py +END +amisr_windEstimation.py +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_windEstimation.py +END +amisr_windEstimation.pyc +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_windEstimation.pyc +END +hf_write_pdata.pyc +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/hf_write_pdata.pyc +END +amisr_winds_proc_offline.py +K 25 +svn:wc:ra_dav:version-url +V 106 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_winds_proc_offline.py +END +NSM_Preproc2.py +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM_Preproc2.py +END +plot_mst.py +K 25 +svn:wc:ra_dav:version-url +V 90 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/plot_mst.py +END +test1.xml +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/test1.xml +END +150km_january_3.py +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/150km_january_3.py +END +testRawData.pyc +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/testRawData.pyc +END +test_isr_blocks.py +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/test_isr_blocks.py +END +NSM1.py +K 25 +svn:wc:ra_dav:version-url +V 86 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM1.py +END +mst_isr_eej_blocks.pyc +K 25 +svn:wc:ra_dav:version-url +V 101 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/mst_isr_eej_blocks.pyc +END +150km_January_shortPulse.pyc +K 25 +svn:wc:ra_dav:version-url +V 107 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/150km_January_shortPulse.pyc +END +amisr_eej_proc_online.pyc +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_eej_proc_online.pyc +END +amisr_EEJ.py +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_EEJ.py +END +amisr_reader_exp_ex2.pyc +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_reader_exp_ex2.pyc +END +amisr_reader.pyc +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_reader.pyc +END +test_mst_blocks.py +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/test_mst_blocks.py +END +NSM_HDF5.py +K 25 +svn:wc:ra_dav:version-url +V 90 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM_HDF5.py +END +NSM1.pyc +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM1.pyc +END +NSM2.pyc +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM2.pyc +END +150km_january_1.pyc +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/150km_january_1.pyc +END +150km_jicamarca.xml +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/150km_jicamarca.xml +END +bltrSpectra.py +K 25 +svn:wc:ra_dav:version-url +V 93 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/bltrSpectra.py +END +sousy.py +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/sousy.py +END +150km_january_3.pyc +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/150km_january_3.pyc +END +NSM_PreProc1.pyc +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM_PreProc1.pyc +END +mst_isr_eej_processing.pyc +K 25 +svn:wc:ra_dav:version-url +V 105 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/mst_isr_eej_processing.pyc +END +amisr_winds_proc_offline.pyc +K 25 +svn:wc:ra_dav:version-url +V 107 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_winds_proc_offline.pyc +END +hf_write_pdata.py +K 25 +svn:wc:ra_dav:version-url +V 96 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/hf_write_pdata.py +END +150km_January_longPulse.py +K 25 +svn:wc:ra_dav:version-url +V 105 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/150km_January_longPulse.py +END +hf_test.py +K 25 +svn:wc:ra_dav:version-url +V 89 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/hf_test.py +END +JASMET30_MetDet.pyc +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/JASMET30_MetDet.pyc +END +amisr_eej_proc_offline.py +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_eej_proc_offline.py +END +BLTR_reader.pyc +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/BLTR_reader.pyc +END +eej_plots.xml +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/eej_plots.xml +END +mst_isr_eej_processing.py +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/mst_isr_eej_processing.py +END +hf_plot_pdata.pyc +K 25 +svn:wc:ra_dav:version-url +V 96 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/hf_plot_pdata.pyc +END +jasmet50_16april.pyc +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/jasmet50_16april.pyc +END +WindProfiler_SA01.pyc +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/WindProfiler_SA01.pyc +END +bltrSpectra.pyc +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/bltrSpectra.pyc +END +schain +K 25 +svn:wc:ra_dav:version-url +V 85 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/schain +END +amisr_reader.xml +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_reader.xml +END +test_mst_blocks.pyc +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/test_mst_blocks.pyc +END +amisr_winds_proc_online.py +K 25 +svn:wc:ra_dav:version-url +V 105 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_winds_proc_online.py +END +amisr_eej_proc_online.py +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_eej_proc_online.py +END +amisr_reader_exp_ex2.py +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_reader_exp_ex2.py +END +JASMET30_Winds.pyc +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/JASMET30_Winds.pyc +END +plot_isr.pyc +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/plot_isr.pyc +END +testRawData.py +K 25 +svn:wc:ra_dav:version-url +V 93 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/testRawData.py +END +plot_mst.pyc +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/plot_mst.pyc +END +NSM_Preproc2.pyc +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM_Preproc2.pyc +END +amisr_proc.py +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_proc.py +END +amisr_esf_proc_online.pyc +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_esf_proc_online.pyc +END +hf_test.pyc +K 25 +svn:wc:ra_dav:version-url +V 90 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/hf_test.pyc +END +jacktotalrunner.pyc +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/jacktotalrunner.pyc +END +JASMET30_PhaseCal.py +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/JASMET30_PhaseCal.py +END +bltr_reader.xml +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/bltr_reader.xml +END +150km_January_longPulse.pyc +K 25 +svn:wc:ra_dav:version-url +V 106 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/150km_January_longPulse.pyc +END +amisr_esf_proc_online.py +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_esf_proc_online.py +END +EWDrifts_estimation02.py +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/EWDrifts_estimation02.py +END +JASMET30_Online_spc.pyc +K 25 +svn:wc:ra_dav:version-url +V 102 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/JASMET30_Online_spc.pyc +END +NSM_PreProc1.py +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM_PreProc1.py +END +sousy.pyc +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/sousy.pyc +END +plot_eej.py +K 25 +svn:wc:ra_dav:version-url +V 90 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/plot_eej.py +END +beacon_phase.pyc +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/beacon_phase.pyc +END +150km_january_1.py +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/150km_january_1.py +END +plot_isr.py +K 25 +svn:wc:ra_dav:version-url +V 90 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/plot_isr.py +END +test_eej_blocks.py +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/test_eej_blocks.py +END +testBLTR_block.py +K 25 +svn:wc:ra_dav:version-url +V 96 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/testBLTR_block.py +END +amisr_EEJ.pyc +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_EEJ.pyc +END +amisr_esf_proc_offline.py +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_esf_proc_offline.py +END +amisr_reader_exp.py +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_reader_exp.py +END +WindProfiler_DBS01.pyc +K 25 +svn:wc:ra_dav:version-url +V 101 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/WindProfiler_DBS01.pyc +END +NSM11.pyc +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM11.pyc +END +150km_January_shortPulse.py +K 25 +svn:wc:ra_dav:version-url +V 106 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/150km_January_shortPulse.py +END +mst_isr_eej_blocks.py +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/mst_isr_eej_blocks.py +END +schain.xml +K 25 +svn:wc:ra_dav:version-url +V 89 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/schain.xml +END +amisr_spreadF.pyc +K 25 +svn:wc:ra_dav:version-url +V 96 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_spreadF.pyc +END +BLTR_reader.py +K 25 +svn:wc:ra_dav:version-url +V 93 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/BLTR_reader.py +END +amisr_eej_proc_offline.pyc +K 25 +svn:wc:ra_dav:version-url +V 105 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_eej_proc_offline.pyc +END +JASMET30_PhaseCal.pyc +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/JASMET30_PhaseCal.pyc +END +jacktotalrunner.py +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/jacktotalrunner.py +END +JASMET30_PreProc.pyc +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/JASMET30_PreProc.pyc +END +amisr_proc.pyc +K 25 +svn:wc:ra_dav:version-url +V 93 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_proc.pyc +END +amisr_spreadF.py +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_spreadF.py +END +testProcBLTR.py +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/jro_soft/schain/!svn/ver/1609/branches/schain_ebocanegra/schainpy/scripts/testProcBLTR.py +END +ProcBLTR.xml +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/ProcBLTR.xml +END +__init__.py +K 25 +svn:wc:ra_dav:version-url +V 90 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/__init__.py +END +EWDrifts_estimation01.py +K 25 +svn:wc:ra_dav:version-url +V 103 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/EWDrifts_estimation01.py +END +testProcMIRA35c.py +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1639/branches/schain_ebocanegra/schainpy/scripts/testProcMIRA35c.py +END +NSM2.py +K 25 +svn:wc:ra_dav:version-url +V 86 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM2.py +END +NSM_HDF5.pyc +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM_HDF5.pyc +END +JASMET30_Winds.py +K 25 +svn:wc:ra_dav:version-url +V 96 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/JASMET30_Winds.py +END +NSM11.py +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM11.py +END +WindProfiler_DBS01.py +K 25 +svn:wc:ra_dav:version-url +V 100 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/WindProfiler_DBS01.py +END +NSM21.py +K 25 +svn:wc:ra_dav:version-url +V 87 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM21.py +END +amisr_esf_proc_offline.pyc +K 25 +svn:wc:ra_dav:version-url +V 105 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_esf_proc_offline.pyc +END +amisr_reader_exp.pyc +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_reader_exp.pyc +END +amisr_reader.py +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_reader.py +END +amisr_winds_proc_online.pyc +K 25 +svn:wc:ra_dav:version-url +V 106 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/amisr_winds_proc_online.pyc +END +NSM21.pyc +K 25 +svn:wc:ra_dav:version-url +V 88 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/NSM21.pyc +END +testBLTR_block.pyc +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/testBLTR_block.pyc +END +test_eej_blocks.pyc +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/test_eej_blocks.pyc +END +test_isr_blocks.pyc +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/test_isr_blocks.pyc +END +beacon_phase.py +K 25 +svn:wc:ra_dav:version-url +V 94 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/beacon_phase.py +END +plot_eej.pyc +K 25 +svn:wc:ra_dav:version-url +V 91 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/plot_eej.pyc +END +jasmet50_16april.py +K 25 +svn:wc:ra_dav:version-url +V 98 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/jasmet50_16april.py +END +hf_plot_pdata.py +K 25 +svn:wc:ra_dav:version-url +V 95 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/hf_plot_pdata.py +END +WindProfiler_SA01.py +K 25 +svn:wc:ra_dav:version-url +V 99 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/WindProfiler_SA01.py +END +JASMET30_Online_spc.py +K 25 +svn:wc:ra_dav:version-url +V 101 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/JASMET30_Online_spc.py +END +EWDrifts_estimation01.pyc +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/EWDrifts_estimation01.pyc +END +EWDrifts_estimation02.pyc +K 25 +svn:wc:ra_dav:version-url +V 104 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/EWDrifts_estimation02.pyc +END +JASMET30_MetDet.py +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/scripts/JASMET30_MetDet.py +END diff --git a/schainpy/scripts/.svn/entries b/schainpy/scripts/.svn/entries new file mode 100644 index 0000000..201fbc9 --- /dev/null +++ b/schainpy/scripts/.svn/entries @@ -0,0 +1,3938 @@ +10 + +dir +1608 +http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainpy/scripts +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_January_longPulse.py +file + + + + +2017-04-17T17:05:33.000000Z +395fc9ce3defafddacdf509f2f4556c6 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +7868 + +150km_January_longPulse.pyc +file + + + + +2017-04-17T17:05:33.000000Z +5d3a93af03bc2cf8c8874d3b3160daef +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +4391 + +150km_January_shortPulse.py +file + + + + +2017-04-17T17:05:33.000000Z +440444c0146e4298556f3d56f3568b1d +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +7474 + +150km_January_shortPulse.pyc +file + + + + +2017-04-17T17:05:33.000000Z +300e3086223e681ea9e8136e057495a0 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3833 + +150km_january_1.py +file + + + + +2017-04-17T17:05:33.000000Z +86a9fcd86f96d0db78e6141088d9fc7b +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4945 + +150km_january_1.pyc +file + + + + +2017-04-17T17:05:33.000000Z +5c2338ce8357128c9dbd98b76586baf3 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2852 + +150km_january_3.py +file + + + + +2017-04-17T17:05:33.000000Z +92f48cdeb6ce34d984c5eb68691d4f67 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +5960 + +150km_january_3.pyc +file + + + + +2017-04-17T17:05:33.000000Z +482fa3346a5a18cc941bfe98d0a020ed +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3147 + +150km_jicamarca.xml +file + + + + +2017-04-17T17:05:33.000000Z +92f2164728c8f8a6958e634a6447d6f2 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3795 + +BLTR_reader.py +file + + + + +2017-04-17T17:05:33.000000Z +78fff77e6aaf4e96976c31e126b7240b +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +1295 + +BLTR_reader.pyc +file + + + + +2017-04-17T17:05:33.000000Z +e10181436e9e1f61e3304fdd511b9afa +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +1398 + +EWDrifts_estimation01.py +file + + + + +2017-04-17T17:05:33.000000Z +a010bf08aa81509ec10268c73dfdf4cb +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +6835 + +EWDrifts_estimation01.pyc +file + + + + +2017-04-17T17:05:33.000000Z +369673c523d833277b92ebf71f606a9d +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3982 + +EWDrifts_estimation02.py +file + + + + +2017-04-17T17:05:33.000000Z +d1d854d0706a550d5fb51ff0edf5760c +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +2788 + +EWDrifts_estimation02.pyc +file + + + + +2017-04-17T17:05:33.000000Z +d1712e0830a989b53f2ea2b36dd0e46d +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2239 + +JASMET30_MetDet.py +file + + + + +2017-04-17T17:05:33.000000Z +b852abbce4cdfc567c6f326da2f8145d +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4898 + +JASMET30_MetDet.pyc +file + + + + +2017-04-17T17:05:33.000000Z +5475207b1fc58cee70b1b0a626dbd17f +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2792 + +JASMET30_Online_spc.py +file + + + + +2017-04-17T17:05:33.000000Z +0ca2d2ec22041c43c7cfc847244ac59f +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +6620 + +JASMET30_Online_spc.pyc +file + + + + +2017-04-17T17:05:33.000000Z +79096e3f07fc2d2f7d6fef35902458e0 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3304 + +JASMET30_PhaseCal.py +file + + + + +2017-04-17T17:05:33.000000Z +7dc675cfe29575aaa3ca590ec490cced +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4325 + +JASMET30_PhaseCal.pyc +file + + + + +2017-04-17T17:05:33.000000Z +004b9fac0cf574118efef05670a2ec85 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2499 + +JASMET30_PreProc.py +file + + + + +2017-04-17T17:05:33.000000Z +47e3f468d1456c64f8d57ee48d6c6d14 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +1852 + +JASMET30_PreProc.pyc +file + + + + +2017-04-17T17:05:33.000000Z +cc51a8225084f6ebc35537e8ada0e8df +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +1826 + +JASMET30_Winds.py +file + + + + +2017-04-17T17:05:33.000000Z +bdb16606b0d5b05db4481887d73af553 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +5199 + +JASMET30_Winds.pyc +file + + + + +2017-04-17T17:05:33.000000Z +353e8e4596d9cd0893bc9ede8e9669fa +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3162 + +NSM1.py +file + + + + +2017-04-17T17:05:33.000000Z +a2b764e5e86fb8cc463d64e654815922 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +6674 + +NSM1.pyc +file + + + + +2017-04-17T17:05:33.000000Z +42895bdc515c8a98fc715088c3421ee2 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2923 + +NSM11.py +file + + + + +2017-04-17T17:05:33.000000Z +e182e5f0b3d16d7f5b69b1f04c03e0b6 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3836 + +NSM11.pyc +file + + + + +2017-04-17T17:05:33.000000Z +36a3f2a50e7b12d37d9336f0ded59621 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2271 + +NSM2.py +file + + + + +2017-04-17T17:05:33.000000Z +31341debc428819005ee60eac4455021 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +9254 + +NSM2.pyc +file + + + + +2017-04-17T17:05:33.000000Z +4fe8fd134000327e696154a25d053994 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2771 + +NSM21.py +file + + + + +2017-04-17T17:05:33.000000Z +d0e1a093683929ede36bcfa671bb9d1c +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3795 + +NSM21.pyc +file + + + + +2017-04-17T17:05:33.000000Z +151e2785901f20d4fa5c22b82e15c4bb +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2244 + +NSM_HDF5.py +file + + + + +2017-04-17T17:05:33.000000Z +5197314550c747ac176cd98dafce7fb5 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3033 + +NSM_HDF5.pyc +file + + + + +2017-04-17T17:05:33.000000Z +f892116fb07bd8db97d36426d9d9f32e +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +1974 + +NSM_PreProc1.py +file + + + + +2017-04-17T17:05:33.000000Z +03566be5bde8e4765406e3674be0d1e7 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +2908 + +NSM_PreProc1.pyc +file + + + + +2017-04-17T17:05:33.000000Z +77a6b892e7006f2661c4a823ad014435 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2158 + +NSM_Preproc2.py +file + + + + +2017-04-17T17:05:33.000000Z +14c0c8098d0768026740ed90de5f7a35 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3131 + +NSM_Preproc2.pyc +file + + + + +2017-04-17T17:05:33.000000Z +7c64540624b1c89584e23c3f89d0dfbe +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2369 + +ProcBLTR.xml +file + + + + +2017-04-17T17:05:33.000000Z +88c5fec9242c6f8fb0d0fde499251664 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +1230 + +WindProfiler_DBS01.py +file + + + + +2017-04-17T17:05:33.000000Z +38373e38a0654f1077feaef0e4ae736d +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +7946 + +WindProfiler_DBS01.pyc +file + + + + +2017-04-17T17:05:33.000000Z +793e093265b2b4475b5fe5b6a0b9de18 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3908 + +WindProfiler_SA01.py +file + + + + +2017-04-17T17:05:33.000000Z +06eb96028e42c7bb2739118ff70a5e1e +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +5884 + +WindProfiler_SA01.pyc +file + + + + +2017-04-17T17:05:33.000000Z +448aac7dd03bac77cf797c3791f2ff09 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2523 + +__init__.py +file + + + + +2017-04-17T17:05:33.000000Z +2c125383ea262e4c2d0f2adc87c6292c +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +51 + +amisr_EEJ.py +file + + + + +2017-04-17T17:05:33.000000Z +7a79d0041d085bfb94795b50139bf357 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +5116 + +amisr_EEJ.pyc +file + + + + +2017-04-17T17:05:33.000000Z +bb7045897bd67562a34da4f61cc04035 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3170 + +amisr_eej_proc_offline.py +file + + + + +2017-04-17T17:05:33.000000Z +3b434f6180a550b107f12b66b38ae1f0 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +8590 + +amisr_eej_proc_offline.pyc +file + + + + +2017-04-17T17:05:33.000000Z +cd64aa447b8ca6b81e7eb9f0769dd840 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3794 + +amisr_eej_proc_online.py +file + + + + +2017-04-17T17:05:33.000000Z +07770d4cb153daf0bea9d8911e18a15d +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +9424 + +amisr_eej_proc_online.pyc +file + + + + +2017-04-17T17:05:33.000000Z +3df7014f4029a5d865b54ca64888a1f1 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +4089 + +amisr_esf_proc_offline.py +file + + + + +2017-04-17T17:05:33.000000Z +111d5469de0a9d87bf15cc6eae803259 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +8612 + +amisr_esf_proc_offline.pyc +file + + + + +2017-04-17T17:05:33.000000Z +10a876e06a264c686e29f15fde51a483 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +4154 + +amisr_esf_proc_online.py +file + + + + +2017-04-17T17:05:33.000000Z +0da07e8a9f0e523ca06bbcc4c841f4de +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +10091 + +amisr_esf_proc_online.pyc +file + + + + +2017-04-17T17:05:33.000000Z +1509c031039e09ef8a90f69e30633d0a +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +4240 + +amisr_proc.py +file + + + + +2017-04-17T17:05:33.000000Z +ff8508355cfff72608373443eb72881b +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3702 + +amisr_proc.pyc +file + + + + +2017-04-17T17:05:33.000000Z +09a8acec2acd38c9ba076cd70a2f7c8b +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2250 + +amisr_reader.py +file + + + + +2017-04-17T17:05:33.000000Z +96933f3e344677f28c5c66d4c3f2f0b9 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +1233 + +amisr_reader.pyc +file + + + + +2017-04-17T17:05:33.000000Z +34cdbd558677014aafab8e67622397e5 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +1333 + +amisr_reader.xml +file + + + + +2017-04-17T17:05:33.000000Z +8c53701bf02cae1ba4251b05f3bef47b +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4832 + +amisr_reader_exp.py +file + + + + +2017-04-17T17:05:33.000000Z +a9a02749d1055155f7c53294cc7f0e53 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +1681 + +amisr_reader_exp.pyc +file + + + + +2017-04-17T17:05:33.000000Z +d784cf072caa0d30846042a9ad72cceb +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +1692 + +amisr_reader_exp_ex2.py +file + + + + +2017-04-17T17:05:33.000000Z +12ec9bf6c53bba757b3ca43abff78539 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +19325 + +amisr_reader_exp_ex2.pyc +file + + + + +2017-04-17T17:05:33.000000Z +14290c7ce4fa3a91401663e5757f26e8 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +6231 + +amisr_spreadF.py +file + + + + +2017-04-17T17:05:33.000000Z +8a042f6495c86427a1afca4769f9df55 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4913 + +amisr_spreadF.pyc +file + + + + +2017-04-17T17:05:33.000000Z +9d71f4328fed3b6b215882defbe8853a +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3188 + +amisr_windEstimation.py +file + + + + +2017-04-17T17:05:33.000000Z +8f1ef0baad13373c0b2d3afa16c6daf8 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +6743 + +amisr_windEstimation.pyc +file + + + + +2017-04-17T17:05:33.000000Z +2837efc3fabb633cbcc29b9b38a235f2 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +4397 + +amisr_winds_proc_offline.py +file + + + + +2017-04-17T17:05:33.000000Z +cd64883a993633f3e52863f810757c49 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +10189 + +amisr_winds_proc_offline.pyc +file + + + + +2017-04-17T17:05:33.000000Z +dadfac61e0f5c8ef767b4c4acba22217 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +5536 + +amisr_winds_proc_online.py +file + + + + +2017-04-17T17:05:33.000000Z +aa4423eea5e0bc1d91bbf7a1803a90d6 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +7426 + +amisr_winds_proc_online.pyc +file + + + + +2017-04-17T17:05:33.000000Z +c0c3105b794bfd288a99bf67e061f6ec +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3559 + +beacon_phase.py +file + + + + +2017-04-17T17:05:33.000000Z +758f737670e5975c3af7695a766e1adc +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +2349 + +beacon_phase.pyc +file + + + + +2017-04-17T17:05:33.000000Z +3bd43026ec312c9593f42d92c697b212 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2123 + +bltrSpectra.py +file + + + + +2017-04-17T17:05:33.000000Z +322d80094e06cdc50bef6432a77496a1 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +1647 + +bltrSpectra.pyc +file + + + + +2017-04-17T17:05:33.000000Z +e9c99e2d79fd71eaa826a7502da32e2e +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +1497 + +bltr_reader.xml +file + + + + +2017-04-17T17:05:33.000000Z +b73684acdc87b83c42f035005e9e61b2 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +953 + +eej_plots.xml +file + + + + +2017-04-17T17:05:33.000000Z +5c26ca10ff7a7b7976a173af2a60fba8 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3562 + +hf_plot_pdata.py +file + + + + +2017-04-17T17:05:33.000000Z +a9a74ea6bf5a6edc602a86c803a5827d +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +9827 + +hf_plot_pdata.pyc +file + + + + +2017-04-17T17:05:33.000000Z +d4dda92ac6c2b4f4ab89988984e7c1b9 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3479 + +hf_test.py +file + + + + +2017-04-17T17:05:33.000000Z +e40d6032f318641f42d056a3f5f49cbd +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +11441 + +hf_test.pyc +file + + + + +2017-04-17T17:05:33.000000Z +0480641b137293e7b92945d3c19252c4 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +4108 + +hf_write_pdata.py +file + + + + +2017-04-17T17:05:33.000000Z +6421fbfd59187bf6620934274fd05f32 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +11800 + +hf_write_pdata.pyc +file + + + + +2017-04-17T17:05:33.000000Z +179dd562117c49fc21fd13e4163d15ea +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2257 + +jacktotalrunner.py +file + + + + +2017-04-17T17:05:33.000000Z +9cb28bd216659a6b11e75162a92c1807 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +5811 + +jacktotalrunner.pyc +file + + + + +2017-04-17T17:05:33.000000Z +5613e55b5cd8a2ac6077959e68003c40 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3482 + +jasmet50_16april.py +file + + + + +2017-04-17T17:05:33.000000Z +b4359fd270df5b5a8ecfc6edeb5f21ba +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3147 + +jasmet50_16april.pyc +file + + + + +2017-04-17T17:05:33.000000Z +b718b7e5be995e0df053fe5864a1ead1 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2619 + +mst_isr_eej_blocks.py +file + + + + +2017-04-17T17:05:33.000000Z +bf10d1c0f3e57165ec123d482d0229b8 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +12481 + +mst_isr_eej_blocks.pyc +file + + + + +2017-04-17T17:05:33.000000Z +23ff1ffab88450102a86acb9f65d2094 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +5095 + +mst_isr_eej_processing.py +file + + + + +2017-04-17T17:05:33.000000Z +fab23ab6d30a635967d6e32e8bd33526 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +14027 + +mst_isr_eej_processing.pyc +file + + + + +2017-04-17T17:05:33.000000Z +8442b2d2ff338293b75a09d785dd395c +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3490 + +plot_eej.py +file + + + + +2017-04-17T17:05:33.000000Z +bf39e579fd3778f2aa0fbdbaf2648565 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4280 + +plot_eej.pyc +file + + + + +2017-04-17T17:05:33.000000Z +e9b70a0a9b5dff67dafb3279cc84ee17 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2843 + +plot_isr.py +file + + + + +2017-04-17T17:05:33.000000Z +d35a515fe173584a65741f208f23036d +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3646 + +plot_isr.pyc +file + + + + +2017-04-17T17:05:33.000000Z +dad5d9b6415657509523ff7bdac6a4a8 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2836 + +plot_mst.py +file + + + + +2017-04-17T17:05:33.000000Z +ee07ba76ff153273cb252e4422f6c8c2 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4043 + +plot_mst.pyc +file + + + + +2017-04-17T17:05:33.000000Z +9d017fb10c7a79f202069ed600736648 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3077 + +schain +file + + + + +2017-04-17T17:05:33.000000Z +4324e94d97bce7d7bd3bf5ae829adcf1 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +1081 + +schain.xml +file + + + + +2017-04-17T17:05:33.000000Z +a27996b56f90e55c3c9e4ea8246291fe +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4751 + +sousy.py +file + + + + +2017-04-17T17:05:33.000000Z +75b46b343f42d33bc257b33bd32e40ea +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4510 + +sousy.pyc +file + + + + +2017-04-17T17:05:33.000000Z +1c2b35275f3139d132c6f9bf575eb293 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2520 + +test1.xml +file + + + + +2017-04-17T17:05:33.000000Z +4c1f5b8e3724687396b528759512c97f +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +775 + +testBLTR_block.py +file + + + + +2017-04-17T17:05:33.000000Z +fa1347c14d0bc3cf555565d017441dea +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +8370 + +testBLTR_block.pyc +file + + + + +2017-04-17T17:05:33.000000Z +f680b5dd6d183ccba3a5c213518ed453 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3026 + +testProcBLTR.py +file +1609 + + + +2017-04-17T17:09:43.000000Z +a8cadde398ca23851aabd0ffb5750783 +2017-04-17T17:13:10.698767Z +1609 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +6841 + +testProcMIRA35c.py +file +1639 + + + +2017-05-25T15:03:42.000000Z +b9bffa3ae4c0fa6ce8c551cb03501d2f +2017-05-25T18:37:17.681755Z +1639 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4094 + +testRawData.py +file + + + + +2017-04-17T17:05:33.000000Z +61f240f9a7c844f4d837dc0dafe2786e +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +4933 + +testRawData.pyc +file + + + + +2017-04-17T17:05:33.000000Z +92bb7187105e1011939528f8a6ab0232 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +2659 + +test_eej_blocks.py +file + + + + +2017-04-17T17:05:33.000000Z +a926751dea8ab6a7987899965547b0e5 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +5558 + +test_eej_blocks.pyc +file + + + + +2017-04-17T17:05:33.000000Z +22d82c537f5583ab6de0a6b2182b9d7d +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3562 + +test_isr_blocks.py +file + + + + +2017-04-17T17:05:33.000000Z +63d5a292d84efc3025c6b7a210cfed30 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +5837 + +test_isr_blocks.pyc +file + + + + +2017-04-17T17:05:33.000000Z +4a13f49c9aa03087e492fcf6acb18483 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3834 + +test_mst_blocks.py +file + + + + +2017-04-17T17:05:33.000000Z +9e74ddcde2d7f70239de7035a0063cc7 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +6065 + +test_mst_blocks.pyc +file + + + + +2017-04-17T17:05:33.000000Z +dd189cb3618f9a812e6b4d18e13e987c +2017-04-12T22:42:28.822577Z +1606 +ebocanegra +has-props + + + + + + + + + + + + + + + + + + + + +3625 + diff --git a/schainpy/scripts/.svn/prop-base/150km_January_longPulse.pyc.svn-base b/schainpy/scripts/.svn/prop-base/150km_January_longPulse.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/150km_January_longPulse.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/150km_January_shortPulse.pyc.svn-base b/schainpy/scripts/.svn/prop-base/150km_January_shortPulse.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/150km_January_shortPulse.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/150km_january_1.pyc.svn-base b/schainpy/scripts/.svn/prop-base/150km_january_1.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/150km_january_1.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/150km_january_3.pyc.svn-base b/schainpy/scripts/.svn/prop-base/150km_january_3.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/150km_january_3.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/BLTR_reader.pyc.svn-base b/schainpy/scripts/.svn/prop-base/BLTR_reader.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/BLTR_reader.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/EWDrifts_estimation01.pyc.svn-base b/schainpy/scripts/.svn/prop-base/EWDrifts_estimation01.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/EWDrifts_estimation01.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/EWDrifts_estimation02.pyc.svn-base b/schainpy/scripts/.svn/prop-base/EWDrifts_estimation02.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/EWDrifts_estimation02.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/JASMET30_MetDet.pyc.svn-base b/schainpy/scripts/.svn/prop-base/JASMET30_MetDet.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/JASMET30_MetDet.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/JASMET30_Online_spc.pyc.svn-base b/schainpy/scripts/.svn/prop-base/JASMET30_Online_spc.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/JASMET30_Online_spc.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/JASMET30_PhaseCal.pyc.svn-base b/schainpy/scripts/.svn/prop-base/JASMET30_PhaseCal.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/JASMET30_PhaseCal.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/JASMET30_PreProc.pyc.svn-base b/schainpy/scripts/.svn/prop-base/JASMET30_PreProc.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/JASMET30_PreProc.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/JASMET30_Winds.pyc.svn-base b/schainpy/scripts/.svn/prop-base/JASMET30_Winds.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/JASMET30_Winds.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/NSM1.pyc.svn-base b/schainpy/scripts/.svn/prop-base/NSM1.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/NSM1.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/NSM11.pyc.svn-base b/schainpy/scripts/.svn/prop-base/NSM11.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/NSM11.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/NSM2.pyc.svn-base b/schainpy/scripts/.svn/prop-base/NSM2.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/NSM2.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/NSM21.pyc.svn-base b/schainpy/scripts/.svn/prop-base/NSM21.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/NSM21.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/NSM_HDF5.pyc.svn-base b/schainpy/scripts/.svn/prop-base/NSM_HDF5.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/NSM_HDF5.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/NSM_PreProc1.pyc.svn-base b/schainpy/scripts/.svn/prop-base/NSM_PreProc1.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/NSM_PreProc1.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/NSM_Preproc2.pyc.svn-base b/schainpy/scripts/.svn/prop-base/NSM_Preproc2.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/NSM_Preproc2.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/WindProfiler_DBS01.pyc.svn-base b/schainpy/scripts/.svn/prop-base/WindProfiler_DBS01.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/WindProfiler_DBS01.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/WindProfiler_SA01.pyc.svn-base b/schainpy/scripts/.svn/prop-base/WindProfiler_SA01.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/WindProfiler_SA01.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_EEJ.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_EEJ.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_EEJ.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_eej_proc_offline.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_eej_proc_offline.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_eej_proc_offline.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_eej_proc_online.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_eej_proc_online.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_eej_proc_online.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_esf_proc_offline.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_esf_proc_offline.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_esf_proc_offline.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_esf_proc_online.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_esf_proc_online.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_esf_proc_online.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_proc.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_proc.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_proc.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_reader.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_reader.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_reader.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_reader_exp.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_reader_exp.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_reader_exp.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_reader_exp_ex2.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_reader_exp_ex2.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_reader_exp_ex2.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_spreadF.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_spreadF.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_spreadF.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_windEstimation.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_windEstimation.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_windEstimation.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_winds_proc_offline.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_winds_proc_offline.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_winds_proc_offline.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/amisr_winds_proc_online.pyc.svn-base b/schainpy/scripts/.svn/prop-base/amisr_winds_proc_online.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/amisr_winds_proc_online.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/beacon_phase.pyc.svn-base b/schainpy/scripts/.svn/prop-base/beacon_phase.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/beacon_phase.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/bltrSpectra.pyc.svn-base b/schainpy/scripts/.svn/prop-base/bltrSpectra.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/bltrSpectra.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/hf_plot_pdata.pyc.svn-base b/schainpy/scripts/.svn/prop-base/hf_plot_pdata.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/hf_plot_pdata.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/hf_test.pyc.svn-base b/schainpy/scripts/.svn/prop-base/hf_test.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/hf_test.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/hf_write_pdata.pyc.svn-base b/schainpy/scripts/.svn/prop-base/hf_write_pdata.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/hf_write_pdata.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/jacktotalrunner.pyc.svn-base b/schainpy/scripts/.svn/prop-base/jacktotalrunner.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/jacktotalrunner.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/jasmet50_16april.pyc.svn-base b/schainpy/scripts/.svn/prop-base/jasmet50_16april.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/jasmet50_16april.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/mst_isr_eej_blocks.pyc.svn-base b/schainpy/scripts/.svn/prop-base/mst_isr_eej_blocks.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/mst_isr_eej_blocks.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/mst_isr_eej_processing.pyc.svn-base b/schainpy/scripts/.svn/prop-base/mst_isr_eej_processing.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/mst_isr_eej_processing.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/plot_eej.pyc.svn-base b/schainpy/scripts/.svn/prop-base/plot_eej.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/plot_eej.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/plot_isr.pyc.svn-base b/schainpy/scripts/.svn/prop-base/plot_isr.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/plot_isr.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/plot_mst.pyc.svn-base b/schainpy/scripts/.svn/prop-base/plot_mst.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/plot_mst.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/sousy.pyc.svn-base b/schainpy/scripts/.svn/prop-base/sousy.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/sousy.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/testBLTR_block.pyc.svn-base b/schainpy/scripts/.svn/prop-base/testBLTR_block.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/testBLTR_block.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/testRawData.pyc.svn-base b/schainpy/scripts/.svn/prop-base/testRawData.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/testRawData.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/test_eej_blocks.pyc.svn-base b/schainpy/scripts/.svn/prop-base/test_eej_blocks.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/test_eej_blocks.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/test_isr_blocks.pyc.svn-base b/schainpy/scripts/.svn/prop-base/test_isr_blocks.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/test_isr_blocks.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/prop-base/test_mst_blocks.pyc.svn-base b/schainpy/scripts/.svn/prop-base/test_mst_blocks.pyc.svn-base new file mode 100644 index 0000000..5e9587e --- /dev/null +++ b/schainpy/scripts/.svn/prop-base/test_mst_blocks.pyc.svn-base @@ -0,0 +1,5 @@ +K 13 +svn:mime-type +V 24 +application/octet-stream +END diff --git a/schainpy/scripts/.svn/text-base/150km_January_longPulse.py.svn-base b/schainpy/scripts/.svn/text-base/150km_January_longPulse.py.svn-base new file mode 100644 index 0000000..9a27226 --- /dev/null +++ b/schainpy/scripts/.svn/text-base/150km_January_longPulse.py.svn-base @@ -0,0 +1,185 @@ +import os, sys +import numpy +path = os.path.split(os.getcwd())[0] +path = os.path.split(path)[0] + +sys.path.append(path) + +from schainpy.controller import Project + +desc = "150 km Jicamarca January 2015" +filename = "150km_jicamarca.xml" + +controllerObj = Project() + +controllerObj.setup(id = '191', name='test01', description=desc) + +#path = '/home/operaciones/150km_jicamarca_january/RAW_EXP/2015_ISR' +path = '/media/DATOS/2015_ISR' +#path = '/media/New Volume2/DATA/RAW_EXP/2015_ISR' + +figpath = '/home/operaciones/Pictures/150km_jicamarca_january' + +remotefolder = "/home/wmaster/graficos" + +readUnitConfObj = controllerObj.addReadUnit(datatype='VoltageReader', + path=path, + startDate='2015/01/13', + endDate='2015/01/30', + startTime='07:55:00', + endTime='23:59:59', + online=0, + delay=10, + walk=1) + +opObj11 = readUnitConfObj.addOperation(name='printNumberOfBlock') + +procUnitConfObj0 = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId()) +a=[] +for i in range(85): + if i>20: + a.append(i) +for i in range(170): + if i>105: + a.append(i) +for i in range(255): + if i>190: + a.append(i) +for i in range(340): + if 339>i>275: + a.append(i) + if i==339: + a.append(i) + +b= str(a) +profileIndex = b[1:][:-1] + +opObj11 = procUnitConfObj0.addOperation(name='ProfileSelector', optype='other') +#profileIndex = '0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19' +opObj11.addParameter(name='profileList', value=profileIndex, format='intlist') + + +# opObj11 = procUnitConfObj0.addOperation(name='ProfileSelector', optype='other') +# opObj11.addParameter(name='profileRangeList', value='21,84', format='intlist') + + +binary28="1,1,-1,1,1,-1,1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,1,1,1,-1,-1,-1" + + +CODEB=numpy.array([1,1,-1,1,1,-1,1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,-1,-1,-1,1,1,1,1,-1,-1,-1]) +x= numpy.array([ CODEB,CODEB,-CODEB,-CODEB]) +code= ",".join(map(str,x.flatten())) + +opObj11 = procUnitConfObj0.addOperation(name='Decoder', optype='other') +opObj11.addParameter(name='code', value=code, format='intlist') +opObj11.addParameter(name='nCode', value='4', format='int') +opObj11.addParameter(name='nBaud', value='28', format='int') + +opObj11 = procUnitConfObj0.addOperation(name='deFlip') +opObj11.addParameter(name='channelList', value='1,3,5,7', format='intlist') + +# opObj10 = procUnitConfObj0.addOperation(name='selectHeights') +# opObj10.addParameter(name='minHei', value='50', format='float') +# opObj10.addParameter(name='maxHei', value='150', format='float') + +# opObj11 = procUnitConfObj0.addOperation(name='CohInt', optype='other') +# opObj11.addParameter(name='n', value='4', format='float') + + +# opObj11 = procUnitConfObj0.addOperation(name='Scope', optype='other') +# opObj11.addParameter(name='id', value='10', format='int') +# opObj11.addParameter(name='wintitle', value='Voltage', format='str') +# opObj11.addParameter(name='zmin', value='40', format='int') +# opObj11.addParameter(name='zmax', value='90', format='int') + +#opObj11 = procUnitConfObj0.addOperation(name='Decoder', optype='other') + +procUnitConfObj1 = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObj0.getId()) +procUnitConfObj1.addParameter(name='nFFTPoints', value='64', format='int') +procUnitConfObj1.addParameter(name='nProfiles', value='64', format='int') + +#procUnitConfObj1.addParameter(name='pairsList', value='(3,7),(2,6)', format='pairsList') +procUnitConfObj1.addParameter(name='pairsList', value='(1,0),(3,2),(5,4),(7,6)', format='pairsList') + +opObj11 = procUnitConfObj1.addOperation(name='IncohInt', optype='other') +opObj11.addParameter(name='timeInterval', value='60', format='float') + +# opObj11 = procUnitConfObj1.addOperation(name='SpectraPlot', optype='other') +# opObj11.addParameter(name='id', value='2001', format='int') +# opObj11.addParameter(name='wintitle', value='150km_Jicamarca', format='str') +# #opObj11.addParameter(name='channelList', value='0,1,2,3,45', format='intlist') +# # opObj11.addParameter(name='zmin', value='0', format='int') +# # opObj11.addParameter(name='zmax', value='60', format='int') +# opObj11.addParameter(name='figpath', value=figpath, format='str') +# opObj11.addParameter(name='exp_code', value='13', format='int') + +opObj11 = procUnitConfObj1.addOperation(name='CrossSpectraPlot', optype='other') +opObj11.addParameter(name='id', value='2005', format='int') +opObj11.addParameter(name='wintitle', value='CrossSpectraPlot_LongPulse', format='str') +opObj11.addParameter(name='phase_cmap', value='jet', format='str') +opObj11.addParameter(name='zmin', value='20', format='int') +opObj11.addParameter(name='zmax', value='80', format='int') +opObj11.addParameter(name='figpath', value=figpath, format='str') +opObj11.addParameter(name='exp_code', value='13', format='int') +opObj11.addParameter(name='wr_period', value='2', format='int') +opObj11.addParameter(name='save', value='1', format='int') +opObj11.addParameter(name='figpath', value=figpath) +opObj11.addParameter(name='ftp', value='1', format='int') + + + + + +opObj11 = procUnitConfObj1.addOperation(name='CoherenceMap', optype='other') +opObj11.addParameter(name='id', value='101', format='int') +opObj11.addParameter(name='wintitle', value='Coherence', format='str') +opObj11.addParameter(name='phase_cmap', value='jet', format='str') + +opObj11.addParameter(name='xmin', value='0', format='int') +opObj11.addParameter(name='xmax', value='24', format='int') +opObj11.addParameter(name='exp_code', value='13', format='int') +opObj11.addParameter(name='wr_period', value='2', format='int') +opObj11.addParameter(name='save', value='1', format='int') +opObj11.addParameter(name='figpath', value=figpath) +opObj11.addParameter(name='ftp', value='1', format='int') + + + + + + + +# opObj11 = procUnitConfObj1.addOperation(name='RTIPlot', optype='other') +# opObj11.addParameter(name='id', value='3002', format='int') +# opObj11.addParameter(name='wintitle', value='150km_Jicamarca_LongPulse', format='str') +# # opObj11.addParameter(name='xmin', value='20.5', format='float') +# # opObj11.addParameter(name='xmax', value='24', format='float') +# opObj11.addParameter(name='zmin', value='20', format='int') +# opObj11.addParameter(name='zmax', value='80', format='int') +# #opObj11.addParameter(name='channelList', value='0,1,2,3', format='intlist') +# #opObj11.addParameter(name='channelList', value='0,1,2,3,4,5,6,7', format='intlist') +# opObj11.addParameter(name='showprofile', value='0', format='int') +# opObj11.addParameter(name='figpath', value=figpath, format='str') +# opObj11.addParameter(name='exp_code', value='13', format='int') + +procUnitConfObj2 = controllerObj.addProcUnit(name='SendToServer') +procUnitConfObj2.addParameter(name='server', value='jro-app.igp.gob.pe', format='str') +procUnitConfObj2.addParameter(name='username', value='wmaster', format='str') +procUnitConfObj2.addParameter(name='password', value='mst2010vhf', format='str') +procUnitConfObj2.addParameter(name='localfolder', value=figpath, format='str') +procUnitConfObj2.addParameter(name='remotefolder', value=remotefolder, format='str') +procUnitConfObj2.addParameter(name='ext', value='.png', format='str') +procUnitConfObj2.addParameter(name='period', value=60, format='int') +procUnitConfObj2.addParameter(name='protocol', value='ftp', format='str') + +print "Escribiendo el archivo XML" +controllerObj.writeXml(filename) +print "Leyendo el archivo XML" +controllerObj.readXml(filename) + +controllerObj.createObjects() +controllerObj.connectObjects() + +#timeit.timeit('controllerObj.run()', number=2) + +controllerObj.run() \ No newline at end of file diff --git a/schainpy/scripts/.svn/text-base/150km_January_longPulse.pyc.svn-base b/schainpy/scripts/.svn/text-base/150km_January_longPulse.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..181e3674063fa2737b642a27067924b12612a877 GIT binary patch literal 4391 zc$~#n+gck(60RA6INJma!H&R+V>>tz=m7Y%UTmxw#h^;lFmR1jr4ykd55fh z8*D2avCp~if!!~{i4EbeJ??*{=RjQrT*igUHBi@x#p_trY~?dhGi@Hf0{Jz_9P@>2 zPC-4x>q{V)K_UBjkcGIOMX1b!vZ1~}uIPdD0-P5vmgl={`Ke_%)$2(Jbv=2;=vy0L zFblE-_0K`w0NPv@>R)iNZANc)?Q7*D` F-R#=edu)v`d6%(!J=lH59&}@!SP$F1 z*wOw2Yd`9a(&^Jba-Yt0_3158x7wDE+44`_aXQ#H7hq2qd&=084i@LP{t+%V*yb7A zJnyl2@e!Le+kD%XqfN$MGWO>lY>Tm1eX(uEcKZ6m}w%hM(_nNWq z`eFx+y}2+Ra?-W>{f8DE7AqIB_}2?q{NXpV_#+AE7vA_4lepjaAQ-PS^Gjto& z?Y8z2YdhV0?O>8I)fcNWR_lu$f7me{%w_CSU#!kPPx@jWV~y@zbugc?@4M`zh8N$` zw!Z{58oy|RWM#3vLX$gmIk5CqNBWv2e8-m;-{Ow}_kZ}e?b7dqMGFTrgu`yA>&h_^ z{bDGt6|yId>`T`X4G}sb`%?H#5w^0WLUApcjx|mihxN9?@>#<(Ho2B2Meu{78NmO( zXeg7W5Gpc-q8UR`s>li5z_{9vW^kTwDCvs)#*_V>a-ISlZkG3=5+TRBq4GLVp>R-J zMfqLVG0hN#p7@9LIKgPPV|LmQkx^m37K*Ct=*SFHY+;0H1JoM9~WO9ncsqsY1CBK}`sqju*F3=Pu7rMULZZ?ioxKn-VY3GFLOm>0gb2yIc z2Tijn-Pa^vq2Zr2xLkJ{{zbz+x^>GmOygiK#|=<*Jylj7wt)`g+yZ8ca?|D*SsLR+ zSaHjZ3?uJ^*Nm%N)nP-JBn{)CLiB>VAy>>T(UAOGI`{tqv17xJAu4k0eM33AT{Mz7 z4}YB`Qd;FE#1!K7r=lsjJ4^RDO{t!H*nqSb=UDi@@@Oy75U0A5Tg%;JtQ;T_pU1Lir-%+oU9Ex~FjC2EReMT9Pbs?E136)ma zOPNlVE+cm;ZrX^&h|Wws)Jq}=mNDn$nm$^_UZ%X8sKQqhZ78`Y7zjiZo$63BL5;}Z z@h-eOu5vrzi4$H`d(?LnH&hL6RI-p_HcUhbE(d;%6N!0nA5npaFk?VTYQOasa79oF-N{=^LU|gF*`Yg~-T+(y9UxRJwjI!cV+VtA{+p6dK#(ja zt_s`|f|Wwy*Ww0q_llGXiANkPxvVyQiRDS6?~0IimDK#m_3_PtR|9zxVJKQGt?z6+ zd&-W^n3X!6e4?BV3?Bp!kEZhXG8C{+g2jG|rTDmpu2FCBl{u79L^6|%6QfX%-o)lo zOuLVh_7Wu!HvL5^*83qUL;JOdE$5u%v4>BhKsYKNS31<%1ZB!1FX+8(hpsdOrBr|rvD`rK#4p0XG4 z|1?@$=@~QDBuVzTb;+KyGehZ=W6fI&_8cPkv8Sxe)B;JV46ThN>*qeRRwmunKeswF R)vId{S`!w2?NMuV;Qv}Kp(_9Y literal 0 Hc$@rqg}^xB(08iP2#@x zU-WPGxu=~ONyaA?oYSYq_GWgzx$U>Rv!y?0r&b$(eebdCZvlRv!%uIO858ieSio3o zC|j&$<+9CMHj|9?O00K|gfaFzW50ue&91acBUouvYmv5`X)TOaV!=2ICs=C&=I2;z zl8G_anqqPSBetfQoMyclCdy2VGcmyg7yvp6Xvq@O48n>T)|zEvmbK24^#vx*GXdiq zCK4B!m}lY=6K^rGz{DaGmzh{%;tG}}t}=0ri3$_fnYh8kO^7?y0>?SlyGZ$#L1VS% zDe@(X{5BKskilEDXlAz-m|V#1-(})GCf+AKc+IokBI$22@c|PnOx$MT!?gO3SnKkL zXZ1CntLP~&ljjD>^XvGU7D_&x9 zDfhffp7%!c46%>jfZZqT6T5%%~D z_9bCo6=FMYz@8BHbz#1zggq<7o)flPi0u*fO(C{V=VKPvJ)&*?+hfSo!5f+S_6}R?sSD3t#TmM4V?a{Rkv0n+}h1elsULhv3 zx{5GK*!e=NLotsEu`Xf$=&FWTkFe&5pEzb;euc}v%H&kqoP$hrE!W_rf(?MA>qF@V zN$@T-S3-C|{J-JvxsPwkiUorihhZ;KJ?R;J9b|XISw0SzpZFdRdE)WqCp_x&WUyR! z+zovxwKxvjz1(2!Gz^T5p@k_SeAhMS;D5wJY08*FYU8+O8bl$rm-w;qRiyDrtA$ed zy!P;mgWYBg6SQ}l`?`)uSB0{sVwrFctfj8)`JU+~Ae_nH?xh9l#i83t$hDD4?I__L z-&5L5U~X=>8N|}e!sI&@7=9%8B^NTGa$|0~W)h!R!xQt6L)B9-!=h@ATXP%4l#Il` zpmpb!-+>=WjoF;7dkyEF)%U^6|+>PKOZPZcPyyI54Hc@h&x?6Q!$GJ^$ zJ1Pmep=e=0Fg`}pkMLwv@v}eKk9)%r&&MhtgB|#-T*XI)UOQ$V-p5QI8BZ z=vV?}sr~`)3({{?yF&bPw*N=OM~C*EEZ{pJn~o zuoDz~)1g(+TFo3t+lkUTuP9K4IH^0%CIvfzs(cejbFIL%-R#0q*y{&c5=Gi1<~%V9 zr$I)ZYIvDLpVGXsLFwgb+@}2@n+Dlv{xaQ{bSpdl z5nVmZ(lIfudOI)RS(YA77_m46DAFlr$4E{#&63v}WPFmep?&x&-R(L>ZsJu`P2f|e zmq3%K@mlo~waVjo4GLO2Qip4BH*gJoFri+C)n=WAfS7B2q7p&GgxWwqa9(yhbVT4% z@}Q#vJfxU6k)bj&Q-sO%@{4Crsp~zJg92#fCdNWSpaatW4s?12`e8iS$0Rh>ao`)O;Yb?qM34wXKuClA zUc zOr@=3>yRhMFfDL$i@q=5@l3A5eMtJz3KIBg z&<8AkyWkjj$2B-t$2#VotflNHN|~Bg{bZ<#2etGq%^$?$DX$;b2mt; kpl&+TTa{Aw-&(XPrJ>du(az1E)!Jj$tOY-N%9=X&4{6vz8UO$Q literal 0 Hc$@r>lC5MRm0U<2h5@*pw9d6uStWdnK8G);IUB~1fkXp`|5=FlBjM%HPhbBI6Z zPwwYVyStJdhnUR7md<cP^x#Ieeev8}DQRBt91S0QDYiLEY-o zHq>oU0L=_EvrG)ZCxA~VV8d)Z1Il772P#8ci}W(!55s}XLVX0}5Y+Ra3ZzvZ1vLuI zF_1Zs!ypmOgDij=K{R8@Q9y%o4C>=7_XEgrkho5eaXATc3gk4%OCV=JUIuvu!`S^=l^dZD+sY_c2e3RMYxw>O#$? z&nUeoSq3rjpP+dIR1wr1sO!+2=cH^#Z}#Q&;DWq15$ilYr}N|jogC||56tWr#-1|v z>pAQhS8IGA_8aRx9~k?KZ^p6l-EnL(wlz@i`(l*a@alIux?7;~$t8Z7a&C7yw7Ek^ z$<*B*b&n~W6#EOWaHM$u;peSKQ)a=!#nAE~rioKob4sVJ(reEZEfKk*^jZXM5p_yc zr?M7bN+eEOht00Q^2e5MY%(fMhTta^g98f!(NZQy##L;biWx;xs@RRZ(0DqC*KuEN z=$0z$P({K;o{G!oj2|`=@8#NycZb{W_sSH-;m&?7t`1b+^IX%8F1BMvC<4eIR z^}tasqGR7~ES zN9${A>yFda>H*c2^|dGXaFKN2dx7%!Fow8NzUX*loMSo@{;8R!;36+DZ`-XS7405x z_}V??!lqg5McQRQUJ$m;jx-ZUBlFnv)xPqTYjl*j3%LN~Nt*^HKFPLOuqJ{N^~Q@0 z!ykm-Rxwf4%Hrcy);`uzOPJJ=@liCUuBt3n7MEyAf0n-Z{RY|7;fI@Xk*#kjS9gzv zD2^!DB#MMqx#2K`gufx$k~^{bn2WL>V#1N&qEID+moE?YG>XS8^>CF>D@f}Tb8qYf zu5Rq0#W5;99u?9m!XmIr#bHm!zQ*+XUHIB?kW~jeo$Q>U8_)QPPatW=-j(90V-s+V4b*oOB5BLHq!0MIP^Wk4RE52dnTC_VTe|_zOD{T zqS zj3qL=Gy!O+um>F?RH<|g(DAc@p(Jp;6=}1(eWskQtvwM@sF(wVe&hu>HL#z!!P>2` z!<2|3kx-kvTiY9a1|K=;CiNGUu_eOVGUdUC>|?*EpjITt0PktfM4nOaaheXNsS?d~ z!i`ZVhlPvH4@u<$+;mywFlq-2JkWbf{6}v_s>pLs%V#<|jYHw8a_lyQ7erc{a;)1? zj}vyv$%O7r&}42NR+htLcs^}u+4j{lN;$^=qj1e0vy0ZGU9fXj&d%FKJBQy1EBD1W sZ%^Cv_BE@R$z@$@&SILrQ}eWDahGti_>M9)%y@Rl8n^JZ3sxcfKg6_ZtpET3 literal 0 Hc$@)C9t`grfEn>NJyYSj=BfWqFu0zu1C8LxF7l@ zKeIohpZl~kBgs(L0a?rJymRmDDEHTJVZQSBTZg58*WrB#ulloxF#$h=d5qQCw83gd zMw_f=GRasY#~M9E^s*0(eE;Y=YW+;~vf2QX1=Oky zGC9Z^LrmnE=wkxV0VWDe_5+$T#2^EMVu;m-N$wLShM9nM1dWSPCdQZ;r}Y{W6HHuZ zVv>m|CZ?IV!Ng4_ZV^4h#BH!xsDa`LYmAboJHRn&V`O=pEPu*Gkp!+$O3bWHFgcOQ zf5yb;OngCn&>CZn>%{+(iLaQr%f#1A%qDTqvD)M%&3hlw{024UBx#mN^8%YEs|$pc zJ1~nd`!d${wU}kqmR=(13Q1QJ>2}7;l<~x+jHj5K$~0F;HHnw&Jwocf$gsr!+ zB)~RP7gs{!7dQS;^))m_#?0Hw4F9_T2 zs`rwxS6#6k>Ve^|Hg`$y$Br5&HQBqeCi_>^%zXj#i->`aEg!V7LRPxv=gHl( zs+4b3=Sm(rK97jqkcrdZQO%?)obEvn_mwJ@@Yp?}TZM7S^XQNcj^vjp*NqUGPzH{C znHq+^qT00qGJ6hg6vC?u)s(@{iLsV46n~$H9)+Q&2LD@cbrbeaa8Mk%a4*B6^olTO z>hAln`0nMlngn=Twz@#GIKU|2P$l(hsce);JgB|?>>jJgb2YWsiPX-SAd*KBSfvU& zVW8vC^U@Z^!9|v^Uud%RC3m&~XGH_*LSg5qk+_h$8SOnlkC-7B0;kvO0Q};GkJHUY z7#yR@P$IJv$(ZASBoAQ(kZorMu%XF7ZxT4nj!_yn2|G1qWwv&CjG;mfNlIenh{va} z?V@BS-59%CzJr0@mqv&*r3V`=K@Rd&`jaH#05%y5%N;j^S^B257xedh!8Y0QCnf z)8>#lV~m;wGjHV00dvO8!!u&!JDve^+`MB>8#B2)uK1Ya@ZL%29Poxx{^ck4Ki=(L NW7vS#EEt8Je*u$8p9BB^ literal 0 Hc$@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/schainpy/scripts/.svn/text-base/BLTR_reader.py.svn-base b/schainpy/scripts/.svn/text-base/BLTR_reader.py.svn-base new file mode 100644 index 0000000..8bf03e1 --- /dev/null +++ b/schainpy/scripts/.svn/text-base/BLTR_reader.py.svn-base @@ -0,0 +1,37 @@ +import os, sys + +path = os.path.split(os.getcwd())[0] +path = os.path.split(path)[0] + +sys.path.insert(0, path) + +filename = "bltr_reader.xml" +path = os.path.join(os.environ['HOME'],'Documents/Data/') +pathfile = os.path.join(os.environ['HOME'],'Documents/BLTR') #'/home/signalchain/Documents/amisr' +desc = "BLTR Experiment" + +from schainpy.controller import Project +controllerObj = Project() +controllerObj.setup(id = '196', name='test01', description='Reader/Writer experiment') + +readUnitConfObj = controllerObj.addReadUnit(datatype='BLTRReader', + path=path, + startDate='2016/10/19', + endDate='2016/10/19', + startTime='00:00:00', + endTime='23:59:59', + walk=1) + +procUnitBLTR = controllerObj.addProcUnit(datatype='BLTRProc', inputId=readUnitConfObj.getId()) + +opObj11 = procUnitBLTR.addOperation(name='PrintInfo', optype='other') + + +print "Escribiendo el archivo XML" +controllerObj.writeXml(filename) +print "Leyendo el archivo XML" +controllerObj.readXml(filename) + +controllerObj.createObjects() +controllerObj.connectObjects() +controllerObj.run() diff --git a/schainpy/scripts/.svn/text-base/BLTR_reader.pyc.svn-base b/schainpy/scripts/.svn/text-base/BLTR_reader.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..c540ca2deba5a7ce2ff000da3cb93c2fd09623d8 GIT binary patch literal 1398 zc${rhZBG+H5T3o#7D`*dDi%boe&Q3?`j$Y9F)C3L6oVMaeKE()Vy|3pFS}c@pZVf1 z@{jogbY}X3CieEWvop`mJo9p;Uya(&R`Vo*>2HPJ=k&TC3IJ&-$N-|btRPaL0R{mK zN+K-4CBUTu3}7P){;~ysYn5ord}c!c3QG`GX7H*Ai+~HTfn~N|x%$Ue5!(`A6{4Du zT7+yFhINSQpmd$dL=Dgl7&HM1N1$cEI$#5^N!F5L+X^79Rlqf-gVz9CfY)We0k{r$ z6R-`q0k}zbs?n-=T$5Y30JlJ|!r+=@4nfoc-Gae&iF6zA4&YtUldBHAe#2MSL07mQ z3hzxdH)k3?wAqzN8*^z>Br5vH?fcY`^f&$9r`#mRT{_LY{bF^D+U|TGW`2QmZw}w> zi}967Mnj!@7ru&p9J=N|x)%q>M*?G^v;V!&Hf75;^&EVawhz_}bmD!$fzg-fuebX| zV&w5q`w9cK^WC0bCK0tuY+Cr#)qvrwqB7=#M9~au!rVJ)%abCo} z@0U15A6rk{wPVzSZtqFh>xR8uVW)Fs(-rWTygT;Y?e58%!RCes5BDDL(vm0_adw_c zu8UI&ly4$;(!3b?w!rn#dE3Ei_a)6xUZWMGKm zB-d}LHMtQ{hx5l^FZ_hZn}4yCP0>IH`v<#)r;~ z>|9ff!^tpDzLVJ}R*Z$<)1kpprk`=;+#}lB!IoMNT0uo^(NhUl)sor@R#avFECqLh OcB!lyir%26YU&SyU_S%^ literal 0 Hc$@IIMvWBnitBz0(A5rP5O6Max01kn%mA&|qgsy+g81P-r& z7yyCL5Qt$AC>%tz=!h$Tgkluxqaen3e3i%JP#+_E^{XHzpgztl6CkdEm;^CJrp0v- z?|_)*_q!lUAZ~!T3E~zl6f+=Z(Z*2y8pvyKILWr>P~z05nC&{V-3Bqw3h!``P^eFX zoKE%M191n$`z*&*Q*ih$%Rd0|A&8Gad<|$oyJj zzov73l|YtK#xgUydBzN@T!K{@t1(v1u*8%57yMpk?FX#=S)!d`D~vtNV;R$<3rwH0 z_80klW!hi9CC6X!ny-6W_=YXq$mQ!>&Q~dyubUumruvUr{}#wwDf<+&uQK~u!k%I4 zjBWJ9p5!w4G{G_}&)yQrz{UN~uU^|4#(Y(FP z|J|JbGazTq~~)Gs;9j_81s5!2aNgo*fLBoCVOIyOZ;py*6L|baST^` zavm}^p2NfuJb6k-X%6I2($a&jnK*z zdRj&0<47Nw*z;xiiS`=Gk8lMqG&eGR6UC9Xvb^S5FGZIwpl@YDdmVY;nYqgd%TL!f zmQ{(O9HRITv8S=LV>o#c1=efI9q9?FIVG`YTXvYPaE!ttjWi=TqfpE4!?OFp4&qdX zf}k_SJxshIde?o#zf>&)s15Nk_{ev!I9$aoFwyFg?6*kK9G8=@i>V5 zBi@v*pW8a}nOKE!$37Ew9LFeZs6g(@K>8MgXa1N&?5Ck^VQ3S~&5Ao-*p$zeu?)ZV zf{rvaau+Mr&vZ#m7{oxm!dO4~Q0{AmdExy$pi(#6 zQd4+*64v*VHnVOp(;l@W-p4;>sBFtnJ>RP>t+-WpWwEwYaUU!vMZ`PKB|DL6uSQy9 zkkrxmh%QxDYIvY|8&fkJ8aaR846}GXku&L^SX}ie#EqtS?o}|}MC_fgI4NV4j&_w_ zU|85O15;!_Q@}e(0q(}Nq)2x+cV1OEI2@r4yRpovJ3+4Qz&kNF$ua8A2MRk&G%tgB zY{@P4I+}m^!*er@@N;?E16p{W3YJVp-O@QVJCq8xZ{k2DhomX3e=K*!p8ON;9-kQ9ovcP-gE&VMoh`ialF}IDriW0ak`mByV}kx9GHjRKF6if|+>|Rj zr@gc)IRmv`3e_`(s+&{J%abN@Ohx~)oty}Yi^iNaoLGs9m`1~`1M?W-Bo)!d=}x!+ z)DN?l`7!Grc>ViFx!z&0nW<1mk;TT+(U~MZEhl%pDW~QCN@mB*tt`c-?CKZTP&$G9 zicj<3_$n1Rkl@LR+OXY`Ca1G)doy9k7OG3^gCk?K7|oy#Q7glOn|ch literal 0 Hc$@r>lC5MRk)uz8tBh@lR3-!u)jY-0*EP0|FCbS6zG(1y{MjL@CojI7h>&S3bO zKe^M7opx_!3zvFoOQ*g4?c;XucbEBNCcm-y*LxrOzj=J0;j8|%0T@0O1ORR-Ti{y2 z0opdSGbD_`M}UtOFdJ4}8@NT-IB?r&E#sGgAPdKA4BQD|$d-%owb>Of;Ah6RaKN~H%RA;XW>pCkRn-}rkg%!ydHaL{IWs1|YD zdwx{j??pTo9UkiPF;`kmC3=l=rPm3xZ9*`e!B1_crpNFbdL6E_CKMVuHEmoNSAHxa zEo7+Ha9%x^9bQ#3lCkF1Jx_a87K@fv)z^D3o2v33lPeitsL1nq^;PV(gfG>=A&R^F z)DuOMaMGm0VEQ`ZI*$_*?T~wn$F#J_)8{&84!!nbjcK_uR&}RVuR1$bXG>4ul!wef zw}!{q0A*r3&MrLzvlOT|cAGo+& zH7Ye{tGP{*=AT9RyMnRW@nw zMX0ItD-?tdxXO`jIWZ;^rIS5S-X$l`ge|912GoF-I7_$ZrXxaEhF+kI$wsZ|^wnOE z)Cu2EJKZ<_9lIfXw9ioW1HkJI0NM-Gn`(~U9)74%OHe`^T1}Hy)5BPO!Rx72Q-mSz zsld&aWge8h*gqGSvV8K(8?}t^8-6_kS~nc0l(Jv^wK^nfnEWaVgr@vwT>DpyL@$ak z5Rul${f=c2^hs;Z4mGzW0#1j^vFG;x){QyENTvZl z+`!49IcIb}J;uy2`3;Gn=WrhPCog2!GBNu$hOJ~Xo-7{uY6ukd)qU%v`)K|S?~a7N z6GUIcYPA8Fo`GAi-bhFk3(ZeD2`$V@j7)XnL~}I6!WA7PtUScYKxJATcf)nM&C)^r znqDV(m-!b%mx=PvJrTxIYP@N>ajJ=~tI36>ssqM<;OS{}>Xqo4mio9OSvTNMh}b7M x6z!5#u=94-%Gx=*G=^W4%sXdghyFQxEmO2gR>`LE?%y`=xHV(pYv--J^$&YL^W^{l literal 0 Hc$@23X=g^ZtOGfXC3!C2emgrCIRk%Bjo)AU=c5PRzpHpZ$6Nn303h(PAONVRvITVu zBtX-K<^T(W@D<>z1;U2Kx}EXaS*yj?A=1fVgGGb`5DY_W1nMJT$q^!|kAfV9<`{@U z5C|UzF#=)~#29)9EHMuKJ;qs>05JiJVvH9^^bU zFLUHK(PGuFF#iJc-vV))0arO|VAqj0*Tdgo{36IjXkKH>T@d#``~YGF#E+bTKKds{ zUk7=;hyIz-MMmHM2EFBs8i)rV);aooCi;gN`wfscdR&i~ zYa`2*=HoHvBbUj?63C?<<1ZP;Wsu7~#wX19YxbO}?f2%8OZL6`#<$D9y$gM>zsr+&1Fv=|SvNuK(==J)pli9+ zvygI|lE>1WRJzL&j_muDw>Z!Kzxemorx9PV@L@*q@h(0x$L>gVqUDgiKUlg__r+u~Ml%ez1WTA6vM_HJwPBDO7$}fpJe|O}awH9BJg5 zh8d&u7&kWCu92Kj848wD&j-JidRQJtS%rZgN;AX>4cv~uLG#D z(}=4@dnnWB8n;wq4_8w{Lw;5`3GdvPx?9GYb3{pae~>mWQ@elqtu~gJc3XSEwQ004 z64KY5uI_%}0LvAJIhgii>?1LE4OdLRlkrPGki4YqIF6Y_0e5$)!zk(c9vvHlFE%(2 zWGhC*wMQw!auliTbrmKgocUghGQnI|IpS5tw()2IgIky&eGP>j8r)+a+fWr`P;g_f z;eS?zPY3&YG96^6vihYJ=mj+F%gzPZ6^@mXpfsOdcXW;F&574h;3u`h&h^d(i+-pv zA7-9kB@Gvwv9s!7mSYtJGOp1JiL=$W9UeCmI%(PwpQ5S!uscPc{kU5q8o?9)lv9z& zfvnMt*QgjZI#rE`xi+p4G`+ut7~nMOaaY+=;R)?GnP3hh8M|o{s0dx~r;m-n2)oRq?AfI3_wgdT;x<}*xl#sLY)`C56&)8#Der$LkkDp;{*v5Nk r+8X}uGiJ{XF4=QdzIWp@XXmUuT63h4ZY?AdT8FGD3vYYe8n^xfa*=TA literal 0 Hc$@)nlYADtC*Y9pK?V2(a5w8U;2E zr7?^`tGW-(A22R;tf3CivP zN{rGZVcsFk46uh}Fh!jKvxKmBTlSC09z#q+b%rF5fjt5C6|k>?eM42Yt>?&k7Wiz- z`dhO8j;z1GWDGzKB*b-$wnaFzy7g_P)f7`?a6w zR~mTwYQL^bJAFgH(l^u=>k8y|kepkr`epAf6S{#y=`Ca!k62guavJ&fYlnNAN11}}xjxU-gzqX5 zy8fxWgUW2pSJ|o^%52`stsGmc*^QkwX_1CA*UnajbZlSP*^RZMwc`jY+kCZL_6zIV zn{wg*Ibj?sV!N=nDIe-WT}RbJE}Mpn7MY^uX=n!(*O77%t+XtQ!u;}8c17w&iGQc=ir+pBY_%d+M(x%o_fKC?KVS)$C!BCOe}iK;y9 za+^?9(PnnI74l!}+;RUh)(J_RoG==M;vV-2bX+Euas`@a%K7=+kNe|xN z+B!NA7)MgTTz-{m@X?^`dR)@bcYKG?q@Kl+wP0O=@0 zkB3ElhtW}M%L*se2#%|IK*dz`{G!8j?uH_wb<45yMLp!A9#>HpQq)*9J)1FoZa?5P zrbdwuo6NfK%R0nRWK#%uXzM$WKt+J6T&@M6cM$>fL`C6Y8>90XiJMSX+tspKxCeHq zZ(Xdtt;}`u&bJNnxdgqKp!2jTE<#uFPqk>%>2fqpy+cNEG{pTX={mq}`pC3IdQ@TE zpQC?_c##Et6IVoyXL;y4XW0u8p2@&=cs3eUD1^#NQ4eED(8xxA8tvQnIQqjlmVvVn zM7#H8O|ZJhU+Ik^|G;J1Oc_(=ggIso7^&V~1HWd<)GI#SqekzQ?|?bpoi@jfRO>NP g-P6W2u4zr1)6w(gwr>lC5MRk)^L_+EcsStnNn60OO$ecB9wj8S1BEf^B;)B!M(7SKBl|SEGvF`% zl0UhhJMHdD77D`zJ-oNSz1!X2?rO;WGd{Au`R{uVlD|oOUgD$w&H)I#EeHS_scb>R z0twKvp_OA{06qbHvOw6d(6BR@oz+^b9i%k@Hdu6E4uU+i3(zQlB@1*=V+iCBw1z

PQRKw|>LBs3;LOhID` z#56RfIgWcE@SXuNOJR%qAm%_k05K0@0VG;3f}94i1fq!X6&f?VYnFFC1hEWq23q%- zA+Q^BAm^a`vicV1(Ektr{_truS1o**0=|wT)smhuHW>(m zlM0TrX$J7O*X(5g%p7vK@(DxQB!q3 zTh<&s#Odwu&5LSn=kZg#IZxpl*YrZkc^d3A^SuVeX-Pa>!I?na-nH zg&g@HiKdA$ld`j~x{+q(r5kjmAtx1v&Q#QP4MS&vLWu%tw*3xw!j_Y)-D_@%O4Z>U z*!6Ls3~Mn#{>4qq-xUhJ38b0on`WcTF$Xc3+P#cZKUFGV;hJ1icuulJ&lE{D?!_L$ znuPVrwv%Z3v7v%UI`hxDMrrZhM?SJ>#>q{fybFCSqc?sKJFYm6W5!TGs$DAlfv=4& zQW22HHPtmlc?SL+YZLMoO+MyRwzenS8>SMiCNd_f1 z@|ymoDt$OS&|~TNIGY>S?Lg0=;z0K9uwA7AVM3ISne6F0RfH?3!@xIO)^lmRE5RZX zhS{4L9^j^nJ=ELqunv(50vXlmGr-*3=#EZX@p000Lr%4&uqtu8Uiy)WWnvl0W(s0C zkacSKI#FMztmz z{*b0GeTc7eQ?+GTM!t7ZzEaVJ4qZ={WBMbdOj+YVrkb!c literal 0 Hc$@r>lC5MRk)jKKi|A%@UYebYyfP1+90bUICe7Fu2dw8`j;=g=OtjHFZV&Jcgj zpWM%#c5nT_owl-d+TGvY@Ah@2KWf#dU;gzI*1&|BSUF0)1$l^tHW?LGuy~7U6oGbXz3dog_{}aG>0Ry(zC+zS2 z(_V+}L$<#U_yORDfFA*V%$eNp`Q(50)ZHFgb9V3Ey2(tRPBM+L&lvlB0>dxh#{-wt zD#)tqjfYQ%mPaFtQyMNwme$77I!iPF7n@sdMt-KHdLaXpS2DPj`Z|e)4u0>+K&AmE zCRPLmD6BGpA!8o*WNx(xGL>6_iY(64B*w~2RFl8xIZ50YZhExX8CuS?>dM%fRg#aT zl}ZQuZwjfCjHrT3X{=cyC}U{5*?QL8X>D)4$x=%L3<=s2eOk|3c8b2aAivt!y=`fG zvt{SVg3`n~DQu#0(;z*}avOGqHX)II-EQuLC#Smy`ymJNZ*cGMWoXtJl9-6ls6uHg z!#!a|_|waaMqaNwOtZxSxEt6!m$+@AEZE2&SfzfVerYx)o_pvcAm@*Ggx?a!2SiZp5$z zuXJLG#aXW0;pR;0ACgoKx<|n;a*XPlYz`YlSmFXTx$gU}eOC!(uG~xs9e0vj6}&z^ z;*K53{(nH5k4IzHZlj9ZZ5|qBnA!Brxho*2Vv01eoCNhNzC#w1+)&VV+2L_VP_g=3 zF^#rXX)5)(8)PoEn=S6X3x7O=_nxO$-N7N!_6nBVGz{iaAf8KszvOiM0_l3F?5h0Q z?VBI?oYIvLZg@ExRS?t~6VM%snP7SlKQ(k%&v=5WIpR7K+QmqzxtQ-MD=3*OkppT-*V#)XeoOQf5Th#m;FV*?3MjlZ^L~_ hTJXvfzgd6Df8sa%2H_2F)!U%&v{&=!^{Zah`x~A`qj3NL literal 0 Hc$@53cNJ5GEmEaAu|-HHU@GGn&Tiw zK%jXVL1AhuU=z(@>iRF$1+3 z5I3N91H?_J-Q;X$LEv`|#4So*%!5Sx+aS??0VLWlf<*f}Ansz8nc5tC-D0mSh$WD7 z(41$Uz^tL;ZD=m=*_J`v1Ce7r23dsW9oF9m@c`sa5D!5-icTK;e3kII3-WH?XM}vj z*X;963BT0=Y>o4n9O{?9V!r}o)=;c?gu-}WJ`@LjrXDIe6!T>|g-#Mo7Vt#XTHCHU=w{W$U-z+i*!q&F#29h~AutU35m9~%}A2hIaLyr?v+79(g zTTA9vwgt;E^4@L52+QPrW_u?t*W-FWG_n#Ztc=6PZae7cH$u}d-U~krv0R6h13s@# zqs|XFu~8Cr15=u$lnCFi*OkR2`mlD|T?;`C3yx zMeYW-t(kx`6kP2|m5D5KXvzjkM!a(3u6+*3dIsj{ag z)cR23C?uI5sGmfATJEFz(JdOgc`Ps7Fm z=;j@~R6^fF)~j@bF*g^w{o`g7PU=p;M{WAZa5QVDZsBNY$0gSKeRDR8o;o(c;UC}v}wUDbyolmW30x4UPnJipriH3N8D86fuzBVrUDymJ` zX|M1PMEp{3@l|N}Em@GE>zowM{P08twj&EsZ9?DI1%+c4Yl3be`i;1_rjKZDR6gi( zj!#>@=y>uc8Y}e|z81`^F>lVAGv>IFO=nZ|NgHVspH$kMHq!BDJhf~r7+Dja!Ow+m U7|PoDNJ@5O`Y<0=SuMfop*T zXxq@vv2YE(0DQ4P*s$Q*1DHLiwOE^{F#$GMWH1L|0Xie#j^OwjxYt4C!5sxTLPp&& zkYmsu2T=eq0s_%d5U9M4XwDMjfR@DsxDy~I!JPzg1Kb-Rrof%zl{Z1)eG9}iITbS? zZiBc3Viv?4hTip&+E8qpvA099cZ}@}#fI>e zaq@nElO>Q#{Wa4Z|0LGwe|8Me#V9%K7oVF!#I4#n24urL0AcRN%b_dt$P zPg>%rr&;c6XmFp(g{5L9JzxnNzrIq(Qz7^lfBOL)6e||K%m}^?Ros@o(K9I5HtWUh z^F*qkBO_D%AhprssotQxdfo|*O@@TY;a}xx#o##uk=K!?Kn8JAxngLEklI&4VuCo* z4{+?X;*NCMvG%px3X?It+Z%RZ=_qaa2#F-wi$GY;D)x z961=0(^Ov43VglxzgKqHtsxRN`2ECOr=T$^bCF0hiG#o5(0EOGBt0P&?=$gC%Z$?T zYCL6X9&UFGN7ZuWiBrbA%7n^DT!kKAuKR%GYVuaCJS&&+?yt&#@ zY3N-9w~1&9=gbRF0?s2XYD#k)#{LOAN+q-xoD)7x!K)xL``ym5R0oYs#>X#riB;fp z96^+H&3j>{P~M7_LYI_7#>r{uH8lrw>V;jYNh+5rr7FkTh*ifkJv$~0v@yg&qZ@{s z-9|&EjHg9&9HVEho;RmWuByjXt}0wQTL)@ z_u4y^?5+_sxm3tnegCKvM4F;`R4HdF?>yadnOB}>Q`Y;6-UJ*IgFCgi>mOBsWN>M6 zdi9}HZ-Y?syp6J(XKfMItha`F<9aLnP3s=LMjZMS=w)TShN?bK30K>!%(Ut z=(h-+LL7VpiQ;35=)0VGaNJIvNYhO?ca%8HA9qnIhcYeLbIM67U>Q*FctX(W@MnYp zQopF)U@MLqWO*W;bASgbHxWCC6ND<2z5%LjHjqzuh^=>%yERq!OqGWzD}4u9rwp4_ zz4Tfw56G1PxmVp(V4v`aAL;FdWabM8M&d;JPH=A`gAoq;DoUE_Ml1Yf$zJ+(b}r)= z#XoV*Vs)Yu&zDY`G!@6j(Q#L0n&iSsKO1;(*Y_%`$puID96P%k%9qrMTH$NnUb1HG z8T+PPunP95y_7Gogin6TDqOinbJO|d^<`^`E_>OU=KuM0Jb0mQwlC-M)})1xJ!Xwr F{{hw5nc4sV literal 0 Hc$@~e;DZCwg=OCzz}!Kp!_qwQ1i0Xk!yH5fXpMqDiu?%pV<7Y37eS4ZQ@;eN z1kG`f1(2g45iNp5;TWPhM~(w}mJ{GlfSd$>666&4Qy{0op9VPt{tU=j@Mqb}Cm`{e z136Ct$OVv#An$-&0=WzdtyVyx)m@5Eu7bP=at-8tT&d{Kv4?r~PzL!as5xjZaNgkh zi=Y;vd57cs4CLn^zhLr*pCC4dlmHkwn;rEz(hAMQRTO7N*1ws*k)1J~b}Aisk>ItsA?y*oK}W z(^O*}M`5gNo@*S5PB>46r$w(sbP;l2r>L(YrM9TlV21;C6UIr~{vz!J((f=`1kS<; zLuS7TCqsU5+y-bB9x7uVy>XK$tSxOx6Ep<&t+N^E*rqzd za@3*MaoS{DJ1P_JLaN=3=9|-IwurLrgsVlR!isToGdfZ=_GKygj1brL2T0T(5=Wa^ zNJ+!}YmA{zBcFDe7dk$pHM%-9XsnaZ(!o)q-X~pgSG&gZhw5+epb>OHaAZ0mtl9(n z<2wLuWpk2-R=sa!-KR*1=Dd-y3Ki)%<2`_th>_`usQ76+Ugra_|1tahvjPvk;KIAo z>4ix|puDX3sn*srx}EkVNyp1hH#|&Ej;htoq{E>-!MSfo>M4z>`3*ly?y9rs&bc#g s!6~>!cQs#d@y;PfcYfL_{O2y_*4!m$)mhEHx9^3#GwI;#mYkCFFT*GMXaE2J literal 0 Hc$@^Kj{y3goA`dfSO1j*5cpUS0eA!3 z0?z^o(6XVGV`Buq0(`YV*l^3UhcJ8CYq2*^eFAK-h%g6H0otSBjbeWUyelB`;1xlR z5~()^atvDIAPOKxK_FTLfzB(4<}5J|$Sfwnn*cEh-Xw^t;9UhV1>O{hY4D~&Tm$bK zv&?|NXBNbD3P9WdF$dx%xAP!z)-8}YYk?vZw?ULZ+ySu&;x4yk5chD^ac>snEVQn3 zH22YCc{iAUj`<&e_>KqMk)I!4{R$JoTFJ7ism-R+gWBWII|MS zQpWX?xn42X>y&GN{lwUt;dKVsTgKiE$2VBzJ%|q=)_Ce9Je$ zHW}L*j`6}g_tJSk6DB7vo%fOFZC@J8C&qrc6#JF2ogpQNUHG_78?XqnNN33sdwtK{ z%tM_rZ3tWU2G)JH@W9rV_VF}_|KevaqyxTWVPi(IIY?AX21d`Ky}4d1Z=H2y61HV* z%Ach+dOY`rWsq4#L266RDj&71ug4=th3xY;0|=9Xho&Csw8{ zMd-&)Bk?=UFwk%RKSi4Z(N~b6T6tZeC+$3az4{6t&b#XJ&(o?Qh;lH!jx>|l`CUcE zZ^%RG3z=|LI=*R|B3+`!Pt2x|#TjFE_qkKSr^@A*u^{Mt;AgCThOkYARdE!?(&V|Y zk>3liQ?+T8Q$IQmc{3@bhBQZ!3XYjBwU8n_BYcKpO2XLeb=yZW*{`oNK7JlNN+IB- z!?@EmpM<%JcA%03^|39(M$>2x;lz)+Qd3+{+?Ov_RyoAFO4`0*ydEjErqJ4;$&pVg zVDci@B~0{Ah|;=7LaZ#i50|m6V(VhdSw((BYobDQx!RA(L^#P%4eQ+~TJP5DSZPW< zRpF7sELe_fCk@^w_c_ZHXL2S7enLW(iRM@q&^08AREe9|1{5wcwUv;}R9j;vZ4yqQ zws&ZnD5@qezsm9XQM5^dAWy~25qa$br+W}7lkR7Sg+m!C)9j~F(N>r@$c9u_RyF0mMF;dKM473wjLLoz zG{X~B{<6EHDf%7Ry98Q#KvE)FrPGr1^dW5t=b}4Nm?nrq3{C}`xGW}U=zh^b(?@Of zRst+=qM}G9hma|mZVXPm9!8R{lu4FfHgf-{l`bMpx5G7{0$?5bsv zZoI_*1%pO^7+j$E9}pZnrz$zt9Y2sxx^;pvOgak~Hj literal 0 Hc$@~XI zTz?VNA~f%Ce4l~*9OM@)UjnrR&1IH<3GyqD4?wPie8|z?*nB-;gF&qHYzl1i4cmO1 z+4Qju#x@82^)ZjJ3S-qG1P90?Y4)mx5L<@q1boqbB3|Ux3FEtW`|;X?DPAf z*b~N{4q);b{QQ#Ia2HgOCd-k}yOPzOgqVBO7N*wv)P1IKd{5SCw!^>i_d29;Uw80j zNAY!>>ZS^;p$%~G<4O7OI#FrZQn4++RmPg}Om30hylzF-B}dZc@KfEb+7bN5qNQws z9HLUCYRN<@6Qp5cLmiu^$a@XlQeIP=K*U;j$6;XGsWRSc9iJpBXh$OTUK}3m*S(W{ zFV?oDWGG?}9V?xhXaC>Bc`A}d7?|z<nZBBNU2pSHQ4ol-Gp({w!cU_f%H2} z7lE@d!jRc-!pV?dZ5t>oa+8Bb9RAkM`P;;VeAo;*#+9Ru~&1Hmci|u0&jC z!IfkZv%st^?Mf3g1h%QO8R*!iI>K_) zq1RyAXIwif6K_PS-Hqm((`L4avh9ScMWw=uaW6AEQZ@EvDfx^L*YyWT)E^Q@`&mdy zv;1p}p-v;8c9|DCKBG0dIy6_Tlh4w@$)esTU2#{t#^Z+SZ}6-UbVhJwIw7pu1N+lD z0B&V-l7?2jZ)M%5NQmaVk+BLD=|tm^$4bP=^h8wrv>mVW8Q6cB{r=&AXJ2sPUFr0~ zBqC5=R{T_J>lxin`;w&NWd|Id9w$e&>Sog6(4MrkY)9%Djj6%E53uB}I*aa{JL49d pf?IS~^92{L9CCE!r=7yTu3~P@U2<0G`S@DMJChDRZpkS*{{TN5`%nM? literal 0 Hc$@r>lC5MK#wuz98s0)!AZNn82=$qvxMbUK}ur0Gl`8AzuYed!$9Gsws~jqVKi zbN=Lh?zFor+aU}eYU{DLzkS^Pc28q}&(t@!|M@e9!Eb@?pXs)39{}m{AO(motUy!)J;6bv zI_NrdrU0ve6M%%)07*GX=$MC7K#_48qG@@~0M0-(3pfkW9N-*8^MLaZ-IFMv0p0_o z=K^m47Xj}BE&)COTn0^EE1=11m3N2_0oMQ@0j^V~TC^Y$7A3-Czy|0A=-ijO!H2yJRE9xvBp%1^k^il zi$o)JvawI|mi$YcUb(VhNLEdC&chZi(a@MIVxtA+yxDGD9w9 zaR%egsUnsxRoc^1eM^kmrsygsT}v`2gj|u3xK!KeGJeAj5{Q*`B{f!EmT}5fpBj_O z=Gw`bu*Shpj*h!YX4!4C8A|?kYA79h#6u|D+7ZQNS6!Fm6NUo?S&Wy?p}d%H?}OHZ;!cGvLTzNNy*olcJUR8NO_4b z$D?oKb47&rw_=mI!lbD#j$zm;9%kXJoupc(eTFL=S-v^#lu5Mf>BK) z`X?St%Y9n**SsZv!Jqf5Ue&MpYZZEvBu}qene(cj{A-izt5aa E4;8bx(*OVf literal 0 Hc$@;-@a>?#Gje;%KBgD9&~@R_`bzg|6v0Nd@Kk6oIY)VV}S%{ z*w9EYF$A9gK3O1an0M>}ojoYESehiB6gF4{n1EmynkjHn$Pa-t0wM{{D999nI%$w; zXpDgv29W}R+EEZF96@cu5@UeKVjP@t5E*bXASS?>05J*9BzsPQz-JmnmNpeR5Hld2 z@R|oP3t|q$JctE~N<0No0PzgOa}Zy!WD&#*+-c02200ClEJyGqN-QVG_%n?E62w<* z@PsP?wvz{$@7aIdv(G_emL=bS_!h(xi0?pr&zU?}|L~dhGFz{(^=ikuuPd^yG^pz% zl|fWMtZ_WKfq2&cE$?Gh8Eb>FUOmG4@qc`>9dQuuDMp|t0Q$}R40pKW)RlkM}%y^C7$@bv5waiog%Wx2YxQm$6@OY*F% zrhIU$`JQRTQWuX@cp6Es6}Yi}@wuIFja%HWT^=$dp>yb!bwjC_%m@XEHl`g(lR@S; z6&UwMo=8{7nDdHUQ#Ye@*o_;TT^G|!6GW-JQ7qxJ#s!q2Ak~B68CFjde5tg>PtUBc zsH|;OH}T=3sW9+EX_8#Dz-{|8R7u+Z&JAvTZWKA)NOKh^@0K@WO8dV{AEr>BrD$V6 zG)JxGm5h(C-?8P`Lt5BokK^#esAWC~GeP0X09(IPcf(Kyn$5iqbKq;kA$@d%mek}} zUal;!Ew6LT*D7whri*6+GS2kz_N9MQH<}Hbeuykrext;I*MUM$*17kj<4LM?inJ>| zMb+oJMBEzkQKsG%?x^~Q&~OVwUMuX6K@9frJoXJbWcr1w$@sk=NHfKCQrAe6tW%`~ z_q3!J@ViG-d*x%Z)S?U)-Po)9AJyW;;epPh`arh-L$&mbdPF%Y&1kxWMcPE(iLyZ9%I&>OKj!kK=dMY%r3IZ9QKyL)-7;*P0WIkt<)Pv>mRim?sG_A;_ zyF>flzriEIe#DY5qupc4y98E@+U*KK1OID?Ax~V%8xt zJrNZ;ZiP#Ho%I*J-@gj*8uM<8cPhTsk?YA~r_ixdrl?gb?n|O}v2$19opO43S&R9w zlvkrRNBFv_L@SVQXxcRXqlY=WVCC(cJ!KDD!}h3MNa7bMe3O&b@Z&$U$R?lLS*yTr Z!Jf0{@H=Pat%6lZB(02vubsBi)<07C>f`_b literal 0 Hc$@=PP@CZji*VlblTfz_qn~@y&H0Wmx?Rv{~QO<`@4tlYkW;H2O#lrAOi3QvID*Y z3ZUgeE62hJd;<97fOO%$?+#(^u-0L1p5_F&;1FRBq5`x>!5_u>2>7=^=D{BWHAjX=ye|ydM!|d@&U*)$cG>wfqcxGMUYQ$)p36s)HJkaIGS%z zr{vkxZFS?=2m{+mmGR!|_%KmHClaZ7^0}Q9 zR(N}j(|xA&@MCVFRi*NRAD-0KUeurCV<{UI-db(l5<=d#n_^feiRV)d*F+9S&_7RpTX*!O=SlK)$EfU>uhB8U3 zT#4v19?CAj#XsXJjf>RLSs3kk0R)&mixaIetJ?i zuv5H^wp`pQH!Mb*>9<5ja=EK(ywJ98zD0~IV;*b6g+ES1i;I`~c{dG}z6m3h9fDfL zPICJ7IqC?@lAq&-sF(%(?$Tj63$g5aQALX)4VvLcy?C- zo9UVZYBS!0Nun@IBQ{2GC0Pt(gMnH)%LXfnweGG4I<~2fB9$IMzq9Cca#K;re0)os z*}mn6vsSiZf7c#-1fgoRPe47)1o>>&*u}lf2SZeqK37Aev@=WyMSMj?Ji!ZW zw6{9Rylb3Tg^qL!^0B}?#5n1zDD`P4UgCRmFqpl;orCvfaOqv?^wK0EP+pe$RBP)Q z-AM \ No newline at end of file diff --git a/schainpy/scripts/.svn/text-base/WindProfiler_DBS01.py.svn-base b/schainpy/scripts/.svn/text-base/WindProfiler_DBS01.py.svn-base new file mode 100644 index 0000000..59466e1 --- /dev/null +++ b/schainpy/scripts/.svn/text-base/WindProfiler_DBS01.py.svn-base @@ -0,0 +1,168 @@ +# DIAS 19 Y 20 FEB 2014 +# Comprobacion de Resultados DBS con SA + +import os, sys + +path = os.path.split(os.getcwd())[0] +path = os.path.split(path)[0] + +sys.path.insert(0, path) + +from schainpy.controller import Project + +desc = "DBS Experiment Test" +filename = "DBStest.xml" + +controllerObj = Project() + +controllerObj.setup(id = '191', name='test01', description=desc) + +#Experimentos + +#2014050 19 Feb 2014 +# path = '/home/soporte/Documents/MST_Data/DBS/d2014050' +# pathFigure = '/home/soporte/workspace/Graficos/DBS/d2014050p/' +# xmin = '15.5' +# xmax = '23.99999999' +# startTime = '17:25:00' +# filehdf5 = "DBS_2014050.hdf5" + +#2014051 20 Feb 2014 +path = '/media/joscanoa/84A65E64A65E5730/soporte/Data/MST/DBS/d2014051' +# path = '/media/joscanoa/disco4/Data/2014/DBS_SA JAN 2014/DBS_SA/250/d2014050' +pathfile1 = os.path.join(os.environ['HOME'],'Pictures/testHDF5/moments') +xmax = '1' +xmin = '0' +startTime = '00:00:00' +filehdf5 = "DBS_2014051.hdf5" + + + +#------------------------------------------------------------------------------------------------ +readUnitConfObj = controllerObj.addReadUnit(datatype='VoltageReader', + path=path, + startDate='2014/01/31', + endDate='2014/03/31', + startTime=startTime, + endTime='23:59:59', + online=0, + delay=5, + walk=0) + +opObj11 = readUnitConfObj.addOperation(name='printNumberOfBlock') + + +#------------------------------ Voltage Processing Unit ------------------------------------- + +procUnitConfObj0 = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId()) + +opObj11 = procUnitConfObj0.addOperation(name='Decoder', optype='other') + +opObj11 = procUnitConfObj0.addOperation(name='CohInt', optype='other') +opObj11.addParameter(name='n', value='256', format='int') +# opObj11.addParameter(name='n', value='16', format='int') + +opObj11 = procUnitConfObj0.addOperation(name='selectHeightsByIndex') +opObj11.addParameter(name='minIndex', value='10', format='float') +opObj11.addParameter(name='maxIndex', value='60', format='float') + +# opObj12 = procUnitConfObj0.addOperation(name='selectChannels') +# opObj12.addParameter(name='channelList', value='0,1', format='intlist') + +#------------------------------ Spectra Processing Unit ------------------------------------- + +procUnitConfObj1 = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObj0.getId()) +procUnitConfObj1.addParameter(name='nFFTPoints', value='64', format='int') +# procUnitConfObj1.addParameter(name='ippFactor', value='2', format='int') + +opObj11 = procUnitConfObj1.addOperation(name='IncohInt', optype='other') +opObj11.addParameter(name='n', value='5', format='int') + +opObj14 = procUnitConfObj1.addOperation(name='SpectraPlot', optype='other') +opObj14.addParameter(name='id', value='1', format='int') +opObj14.addParameter(name='wintitle', value='Con interf', format='str') +opObj14.addParameter(name='save', value='0', format='bool') +opObj14.addParameter(name='figpath', value=pathFigure, format='str') +opObj14.addParameter(name='zmin', value='5', format='int') +opObj14.addParameter(name='zmax', value='90', format='int') + +opObj12 = procUnitConfObj1.addOperation(name='removeInterference') +opObj13 = procUnitConfObj1.addOperation(name='removeDC') +opObj13.addParameter(name='mode', value='1', format='int') + +opObj12 = procUnitConfObj1.addOperation(name='RTIPlot', optype='other') +opObj12.addParameter(name='id', value='2', format='int') +opObj12.addParameter(name='wintitle', value='RTI Plot', format='str') +opObj12.addParameter(name='save', value='1', format='bool') +opObj12.addParameter(name='figpath', value = pathFigure, format='str') +opObj12.addParameter(name='xmin', value=xmin, format='float') +opObj12.addParameter(name='xmax', value=xmax, format='float') +opObj12.addParameter(name='zmin', value='5', format='int') +opObj12.addParameter(name='zmax', value='90', format='int') + + +#------------------------------ Parameters Processing Unit ------------------------------------- + +procUnitConfObj2 = controllerObj.addProcUnit(datatype='ParametersProc', inputId=procUnitConfObj1.getId()) + +opObj11 = procUnitConfObj2.addOperation(name='SpectralMoments', optype='other') + +# opObj12 = procUnitConfObj2.addOperation(name='HDF5Writer', optype='other') +# opObj12.addParameter(name='path', value=pathfile1) +# opObj12.addParameter(name='blocksPerFile', value='10', format='int') +# opObj12.addParameter(name='metadataList',value='type,inputUnit,heightList,paramInterval,timeZone',format='list') +# opObj12.addParameter(name='dataList',value='data_param,data_SNR,noise,utctime',format='list') +# opObj12.addParameter(name='mode',value='1',format='int') + +# opObj21 = procUnitConfObj2.addOperation(name='MomentsPlot', optype='other') +# opObj21.addParameter(name='id', value='3', format='int') +# opObj21.addParameter(name='wintitle', value='Moments Plot', format='str') +# opObj21.addParameter(name='save', value='0', format='bool') +# # opObj21.addParameter(name='figpath', value=pathFigure, format='str') +# opObj21.addParameter(name='zmin', value='5', format='int') +# opObj21.addParameter(name='zmax', value='90', format='int') +# +# opObj21 = procUnitConfObj2.addOperation(name='ParametersPlot', optype='other') +# opObj21.addParameter(name='id', value='5', format='int') +# opObj21.addParameter(name='wintitle', value='Radial Velocity Plot', format='str') +# opObj21.addParameter(name='save', value='0', format='bool') +# opObj21.addParameter(name='figpath', value=pathFigure, format='str') +# opObj21.addParameter(name='SNRmin', value='-10', format='int') +# opObj21.addParameter(name='SNRmax', value='60', format='int') +# opObj21.addParameter(name='channelList', value='0,2', format='intlist') +# opObj21.addParameter(name='SNR', value='1', format='bool') +# opObj21.addParameter(name='SNRthresh', value='0', format='float') +# opObj21.addParameter(name='xmin', value=xmin, format='float') +# opObj21.addParameter(name='xmax', value=xmax, format='float') + +opObj22 = procUnitConfObj2.addOperation(name='WindProfiler', optype='other') +opObj22.addParameter(name='technique', value='DBS', format='str') +opObj22.addParameter(name='correctAzimuth', value='51.06', format='float') +opObj22.addParameter(name='correctFactor', value='-1', format='float') +opObj22.addParameter(name='dirCosx', value='0.041016, 0, -0.054688', format='floatlist') +opObj22.addParameter(name='dirCosy', value='-0.041016, 0.025391, -0.023438', format='floatlist') + +opObj23 = procUnitConfObj2.addOperation(name='WindProfilerPlot', optype='other') +opObj23.addParameter(name='id', value='4', format='int') +opObj23.addParameter(name='wintitle', value='Wind Profiler', format='str') +opObj23.addParameter(name='save', value='0', format='bool') +# opObj23.addParameter(name='figpath', value = pathFigure, format='str') +opObj23.addParameter(name='zmin', value='-10', format='int') +opObj23.addParameter(name='zmax', value='10', format='int') +opObj23.addParameter(name='zmin_ver', value='-80', format='float') +opObj23.addParameter(name='zmax_ver', value='80', format='float') +opObj23.addParameter(name='SNRmin', value='-10', format='int') +opObj23.addParameter(name='SNRmax', value='60', format='int') +opObj23.addParameter(name='SNRthresh', value='0', format='float') +opObj23.addParameter(name='xmin', value=xmin, format='float') +opObj23.addParameter(name='xmax', value=xmax, format='float') + +#-------------------------------------------------------------------------------------------------- +print "Escribiendo el archivo XML" +controllerObj.writeXml(filename) +print "Leyendo el archivo XML" +controllerObj.readXml(filename) + +controllerObj.createObjects() +controllerObj.connectObjects() +controllerObj.run() \ No newline at end of file diff --git a/schainpy/scripts/.svn/text-base/WindProfiler_DBS01.pyc.svn-base b/schainpy/scripts/.svn/text-base/WindProfiler_DBS01.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..20b5d0319229d2d734b06751a3690340543c356f GIT binary patch literal 3908 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 Q5;8w-O5F3o=4Cc>n+a literal 0 Hc$@Hq0H?3U%yqM^%=wG1wQ6UFM!0`0Uw}} z$PQE-Pylro>M0g_;0)l*0qMd-#RcUs)(grdtwVMx@YAp>d!W(>vKK1-pa#gQk^z;0 z`X!KQkO=jI8~};RK15SaE6gB=83K6;CgdQTxqxBh5RKhdT;>&*K@LM@7~}|4MmWk9 zka&-Ryh_yMHIQQY@5W>WXnQaeTL05w$O>o4xYzO-s zs9f7}ku8@xEfefXS1iup=@&Bik!_xJIIKJF0?UbiiPeK)W4HZ~ciiT&R{YVL^qK799-@4>P+7x~j zpA>Bmeg~qVY?_=YV+%!l2}P+)HS$91>44X)Z*8vH-nK(?AEkUlNl)aBcNhr2S`%K7 zUtgKse!n-DXDa(|_BKi{_cymzR?R4`-}b7u87Y%z7kQ=XOn#9m6&Gwjg%wuV(@-%7 z_EKi*%pnxEW(VkZ#EQtS2&9|A*<7JGpDz~jg+<$kQx!;p&KK@tH4Hf~EIut1@NO?l zfZ{?6peV<}|Hxb{!k=`Yn4fRCWWx8kQabRxAdbN-wR%Ff$|L}{!aT=94dB7tBkT`Aw{$nso$F_sGhR>gJecN zkA&Zhz0c1tsK*@gKt~N>S$W`VVa;nw_Q7oXZeJaWuZf8beQ~xcs;b-FAt~lXp?uH8 zfrDkzQ=^MqK`cqEe9oTiys+Zvgm4d3S zmC)Z{t6M0m2n)e(9~F2}q#F82tt|88P}#TIGx2V3c)_~z;x_?%&nj`!R?RIHF3|F| zWf#ZD$g@acFnQ%(DbbiNu$8fKF+QR5n8i|SE>3vudO}fRL7bQyD6G<3`@zG_t*4bgEuw18JJQqdH#f|6gg4Y_ z7ii`V)sNU|6K8R1%3M=wlnH&$a&@qJ)nmz`2t#zleX8OK5ozCVZ38+uxKPBEPnN!T zpVzUDcIbk^)`xl=LfK}>)^%!l{CXaFkq*k#`tm9bYea}@A*7^3VJ|>h!`$I`vaEvx z^4MBK8;RHS#? no code + +opObj11 = procUnitConfObjBeam0.addOperation(name='Decoder', optype='other') +opObj11.addParameter(name='code', value=code, format='floatlist') +opObj11.addParameter(name='nCode', value=nCode, format='int') +opObj11.addParameter(name='nBaud', value=nBaud, format='int') + +# opObj12 = procUnitConfObjBeam0.addOperation(name='selectHeights') +# opObj12.addParameter(name='minHei', value='50', format='float') +# opObj12.addParameter(name='maxHei', value='150', format='float') +#Coherent Integration +# opObj11 = procUnitConfObjBeam0.addOperation(name='CohInt', optype='other') +# opObj11.addParameter(name='n', value='2', format='int') + +# opObj11 = procUnitConfObjBeam0.addOperation(name='Scope', optype='other') +# opObj11.addParameter(name='id', value='121', format='int') + +#Spectra Unit Processing, getting spectras with nProfiles and nFFTPoints +procUnitConfObjSpectraBeam0 = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObjBeam0.getId()) +procUnitConfObjSpectraBeam0.addParameter(name='nFFTPoints', value=16, format='int') +# +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='IncohInt', optype='other') +opObj11.addParameter(name='n', value='150', format='int') +#opObj11.addParameter(name='timeInterval', value='30', format='float') + +# #procUnitConfObjSpectraBeam0.addParameter(name='pairsList', value='(0,0),(1,1),(2,2),(3,3),(4,4)', \ +# # format='pairsList') +# +# # procUnitConfObjSpectraBeam0.addParameter(name='pairsList', value='(0,0)', \ +# # format='pairsList') +# # +# # #RemoveDc +# # opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='removeDC') +# +#Noise Estimation +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='getNoise') +opObj11.addParameter(name='minHei', value='100', format='float') +opObj11.addParameter(name='maxHei', value='280', format='float') +#opObj11.addParameter(name='minHei', value='15', format='float') +#opObj11.addParameter(name='maxHei', value='20', format='float') +# # +# #SpectraPlot +# opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='SpectraPlot', optype='other') +# opObj11.addParameter(name='id', value='1', format='int') +# opObj11.addParameter(name='wintitle', value='AMISR Beam 0', format='str') +# #opObj11.addParameter(name='zmin', value='38', format='int') +# opObj11.addParameter(name='zmin', value=dbmin, format='int') +# opObj11.addParameter(name='zmax', value=dbmax, format='int') +# opObj11.addParameter(name='save', value='1', format='bool') +# opObj11.addParameter(name='figpath', value = figpath, format='str') +# # +# #RTIPlot +# #title0 = 'RTI AMISR Beam 0' +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='RTIPlot', optype='other') +opObj11.addParameter(name='id', value='2', format='int') +# opObj11.addParameter(name='wintitle', value=title0, format='str') +opObj11.addParameter(name='showprofile', value='0', format='int') +opObj11.addParameter(name='xmin', value=xmin, format='float') +opObj11.addParameter(name='xmax', value=xmax, format='float') +opObj11.addParameter(name='zmin', value=dbmin, format='int') +opObj11.addParameter(name='zmax', value=dbmax, format='int') +opObj11.addParameter(name='save', value='1', format='bool') +opObj11.addParameter(name='figpath', value = figpath+'/plots', format='str') +opObj11.addParameter(name='show', value = show, format='bool') + +# # # +# # # +# #Noise +#title0 = 'RTI AMISR Beam 0' +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='Noise', optype='other') +opObj11.addParameter(name='id', value='3', format='int') +# opObj11.addParameter(name='wintitle', value=title0, format='str') +opObj11.addParameter(name='showprofile', value='0', format='int') +opObj11.addParameter(name='xmin', value=xmin, format='float') +opObj11.addParameter(name='xmax', value=xmax, format='float') +opObj11.addParameter(name='ymin', value=dbmin, format='int') +opObj11.addParameter(name='ymax', value=dbmax, format='int') +opObj11.addParameter(name='save', value='1', format='bool') +opObj11.addParameter(name='figpath', value = figpath+'/plots', format='str') +opObj11.addParameter(name='show', value = show, format='bool') + + + +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='SpectraWriter', optype='other') +opObj11.addParameter(name='path', value=figpath) +opObj11.addParameter(name='blocksPerFile', value='10', format='int') +opObj11.addParameter(name='datatype', value="4", format="int") #size of data to be saved + + +# procUnitConfObj2 = controllerObj.addProcUnit(name='SendToServer') +# procUnitConfObj2.addParameter(name='server', value='jro-app.igp.gob.pe', format='str') +# procUnitConfObj2.addParameter(name='username', value='wmaster', format='str') +# procUnitConfObj2.addParameter(name='password', value='mst2010vhf', format='str') +# procUnitConfObj2.addParameter(name='localfolder', value=pathFigure, format='str') +# procUnitConfObj2.addParameter(name='remotefolder', value=remotefolder, format='str') +# procUnitConfObj2.addParameter(name='ext', value='.png', format='str') +# procUnitConfObj2.addParameter(name='period', value=5, format='int') +# procUnitConfObj2.addParameter(name='protocol', value='ftp', format='str') +#----------------------------------------------------------------------------------------------- +procUnitConfObj2 = controllerObj.addProcUnit(datatype='ParametersProc', inputId=procUnitConfObjSpectraBeam0.getId()) +opObj20 = procUnitConfObj2.addOperation(name='GetMoments') + +opObj12 = procUnitConfObj2.addOperation(name='HDF5Writer', optype='other') +opObj12.addParameter(name='path', value=figpath+'/param') +opObj12.addParameter(name='blocksPerFile', value='10', format='int') +opObj12.addParameter(name='metadataList',value='type,inputUnit,heightList',format='list') +opObj12.addParameter(name='dataList',value='data_param,data_SNR,utctime',format='list') +opObj12.addParameter(name='mode',value='1',format='int') + + + +# print "Escribiendo el archivo XML" +# controllerObj.writeXml(path +'/'+filename) +# print "Leyendo el archivo XML" +# controllerObj.readXml(path +'/'+filename) + +controllerObj.createObjects() +controllerObj.connectObjects() +controllerObj.run() + +#21 3 pm + + diff --git a/schainpy/scripts/.svn/text-base/amisr_eej_proc_offline.pyc.svn-base b/schainpy/scripts/.svn/text-base/amisr_eej_proc_offline.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..c0c16bec766bc4189b618736513a1c8f7b1505b8 GIT binary patch literal 3794 zc$~#nX_2!tlh1q9M?)IbjPpu)Qb8Ci0rb%OIX|E7Ph zpZl~kBTMKZ4o^R|mc5#tcjn#MnLV8Rv#Wh}@vnCUsDFm>_Y8l&l>!j>)xZWYB3T1N z3*`hD36KD#B$S$1XofEUU(hBQ(hFxo&ggV7GM zmB@?^kR4F!1c81nAX-770itb)Cbjw~T|C@15FIcqI*A&`6J6Y198KnPCp<28a<584x#V zK4KK)Fo;{+j)Axh;tq&$5O-<9Vge)*PJ%?jDUd@Tra{~Tai7pH&}ob?XNEZ+fS3U} z0;QXrP)Ha^J_@BXvP@GF(}<;%^V0FL>5F2#C(vL$a(?9B8VksxdZY}=rch+ z6chS9416MNlCeR?mM>vbj19%HDDD-Gdo&jJILPtP^ASh68uuIzqx|k0Q9fp$Ck=hR z=RCx%pR)C{cpf6`Ib$#4Sj6=58>6S#XRTo#)){M@qYchcPs2D~G1l7<+hnY-A?Frj z{SC3#97~$9A1+~U*bf){HVhHIa|z#Nd?4-{eqNEDRhCYmG|QIn9eL6e(wjRk+bTg+LM8E)dz4d6_;$>)RIMmT zSvsnCZb5ZmM@YZmSruiu4qI*RZm+B6kkWsEl3td=GIifNaZI~#YFduIxi-7^{%~IB zV2)lNzS(+yw7t8w?&o6mZpHPK)Yl(vEY5CZmlgtRea%#+zT;ZHJdnQ9*VkYBQ~%P7 zY`fXkQMy3QQ4r-I=}z6UjNC(WPDFN@U%3^2EiUov;gX{KX8l(L&CG`1@QEp|5+fga zF=LMD=U05n^~48#qO4B{PCP}dY8AP($oUd`rK7qX#Q1msp$vswHy?I+VdW1-**$%S=ZM$!wj8bqeh_p|Fr4&7D?|Mr0E z*p?H-`qs6Tc_Q~{(a>m?Q>m&gp?WDOsq&^Uy$w(PUX@Ov#-SFY9u4%-w5!38i;GM0 zA=4LKuWTw-7Htkb7Mj|YuXt%&j^g+hY0>>ZA-wWzyQ!sb#>kPg*3}qE*-k;;$33$4bZ~-4)I(BM#~}w z=G4g7l=TG{F!y|o&tDMCXJcgZL2_|AN@AbxIbM&LZU;M|ii+)3ooOo4MdMS^f}
P4DLO%JX-Uk|R$@IE|pi$yx}<|;L=!(&`TjcOU> k&2;rquLq?>M!R^%v`ngjt|_ez*1h}C`$mYhwQKF#Ka{U4DgXcg literal 0 Hc$@rGKRV zsh|6_Gb2lJK;e1%skQ9Y?7TCxbL}o<{~YMOvGCUi8(NV=FEa9fGC0}ftZUDlSt2lSOBre zR&e?0Smz??kWZ*{Gtx=0X~rfPyLAA&#MopzmiWEIexGae8$-PmYu;urm)kWj#a@2* z4KMGo&iAQ0cR3I3()U>UetRAg>;YpB+p)ybqi?L9W1X?oJUnJ>g|R0Gu&11(kyO2B zjE$yZtBjpU#hx>k?#m1IsmG+1e>{rIDRBV$mI~5a$vzTC#v7uC~$~L!Bu^MAvbxDFbjMdxqFya|H zN}0NnP*<74J9vF&8!v0;Z~VM==>DEDaL{;n!&;!~($?V+(hpv(u9wfQ?D;Zq8q$lH zR>KK{N+2yEgW0`?t21Ou=q$cUw@bPM-=5Wwx*G{8>lHsxw(i4;kf9wozIK$yQqSJJ zTG5@c$#4*=Nm9GLV3y%>jtgJk5gLWHMsAW*t3aqMQtB^e^ z-r`qjiC^ybq-(3a~)4Q+!o~Ud*y0tORiBZ zX-UWPn|f8~L8AsRZ=v>fNEXRF#O zDo|8j)Ub<1hPI@BtsD%5mTfrRGwDP)CX!j!Ud)?irt_>TT=;En2UDY zo?qc=b03y;KiO<TU;Hu+Fc4#m5 zcrWo7C3u;2>O-|IgPm6WLMFojPUI|o=jgY{D>f13bAncEZQ;ljD-3s4Ah?c=P|p=h z#hqG}y>XRoxmD#-htQINY$z>Tj4X$*Lvm`?_qN!FR)W}YptQ0vpIno$Hgk0?orJ)FcWs&UZtW~eq_hVU)KHwpHNyDKtiR9czSB^m>B_sjP5!`P-007Y8^gv(W+;=xrzexo<~wp7IRj@# z+Y`;QgV{kNm-6&aH~r~25{;kiaOMDKq1Wg&{sC4z BRA2xA literal 0 Hc$@ no code + +opObj11 = procUnitConfObjBeam0.addOperation(name='Decoder', optype='other') +opObj11.addParameter(name='code', value=code, format='floatlist') +opObj11.addParameter(name='nCode', value=nCode, format='int') +opObj11.addParameter(name='nBaud', value=nBaud, format='int') +opObj11.addParameter(name='osamp', value=nosamp, format='int') + + +# opObj12 = procUnitConfObjBeam0.addOperation(name='selectHeights') +# opObj12.addParameter(name='minHei', value='50', format='float') +# opObj12.addParameter(name='maxHei', value='150', format='float') +#Coherent Integration +# opObj11 = procUnitConfObjBeam0.addOperation(name='CohInt', optype='other') +# opObj11.addParameter(name='n', value='2', format='int') + +# opObj11 = procUnitConfObjBeam0.addOperation(name='Scope', optype='other') +# opObj11.addParameter(name='id', value='121', format='int') + +#Spectra Unit Processing, getting spectras with nProfiles and nFFTPoints +procUnitConfObjSpectraBeam0 = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObjBeam0.getId()) +procUnitConfObjSpectraBeam0.addParameter(name='nFFTPoints', value=32, format='int') +# +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='IncohInt', optype='other') +opObj11.addParameter(name='n', value='60', format='int') +#opObj11.addParameter(name='timeInterval', value='30', format='float') + + +# # #RemoveDc +# # opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='removeDC') + +#Noise Estimation +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='getNoise') +opObj11.addParameter(name='minHei', value='650', format='float') +opObj11.addParameter(name='maxHei', value='800', format='float') +#opObj11.addParameter(name='minHei', value='15', format='float') +#opObj11.addParameter(name='maxHei', value='20', format='float') + +# #SpectraPlot +# opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='SpectraPlot', optype='other') +# opObj11.addParameter(name='id', value='1', format='int') +# opObj11.addParameter(name='wintitle', value='AMISR Beam 0', format='str') +# #opObj11.addParameter(name='zmin', value='38', format='int') +# opObj11.addParameter(name='zmin', value=dbmin, format='int') +# opObj11.addParameter(name='zmax', value=dbmax, format='int') +# opObj11.addParameter(name='save', value='1', format='bool') +# opObj11.addParameter(name='figpath', value = figpath, format='str') + + +# #RTIPlot +# #title0 = 'RTI AMISR Beam 0' +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='RTIPlot', optype='other') +opObj11.addParameter(name='id', value='2', format='int') +opObj11.addParameter(name='wintitle', value='ESF AMISR', format='str') +opObj11.addParameter(name='showprofile', value='0', format='int') +opObj11.addParameter(name='xmin', value=xmin, format='float') +opObj11.addParameter(name='xmax', value=xmax, format='float') +opObj11.addParameter(name='zmin', value=dbmin, format='int') +opObj11.addParameter(name='zmax', value=dbmax, format='int') +opObj11.addParameter(name='save', value='1', format='bool') +opObj11.addParameter(name='figpath', value = figpath+'/plots', format='str') +opObj11.addParameter(name='show', value = show, format='bool') +# # # +# # # +# #Noise +#title0 = 'RTI AMISR Beam 0' +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='Noise', optype='other') +opObj11.addParameter(name='id', value='3', format='int') +opObj11.addParameter(name='wintitle', value='ESF AMISR', format='str') +opObj11.addParameter(name='showprofile', value='0', format='int') +opObj11.addParameter(name='xmin', value=xmin, format='float') +opObj11.addParameter(name='xmax', value=xmax, format='float') +opObj11.addParameter(name='ymin', value=dbmin, format='int') +opObj11.addParameter(name='ymax', value=dbmax, format='int') +opObj11.addParameter(name='save', value='1', format='bool') +opObj11.addParameter(name='figpath', value = figpath+'/plots', format='str') +opObj11.addParameter(name='show', value = show, format='bool') + + +#Generate *.pdata from AMISR data +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='SpectraWriter', optype='other') +opObj11.addParameter(name='path', value=figpath) +opObj11.addParameter(name='blocksPerFile', value='10', format='int') +opObj11.addParameter(name='datatype', value="4", format="int") #size of data to be saved + +#generate moments +procUnitConfObj2 = controllerObj.addProcUnit(datatype='ParametersProc', inputId=procUnitConfObjSpectraBeam0.getId()) +opObj20 = procUnitConfObj2.addOperation(name='GetMoments') + +opObj12 = procUnitConfObj2.addOperation(name='HDF5Writer', optype='other') +opObj12.addParameter(name='path', value=figpath+'/param') +opObj12.addParameter(name='blocksPerFile', value='10', format='int') +opObj12.addParameter(name='metadataList',value='type,inputUnit,heightList',format='list') +opObj12.addParameter(name='dataList',value='data_param,data_SNR,utctime',format='list') +opObj12.addParameter(name='mode',value='1',format='int') + + +# procUnitConfObj2 = controllerObj.addProcUnit(name='SendToServer') +# procUnitConfObj2.addParameter(name='server', value='jro-app.igp.gob.pe', format='str') +# procUnitConfObj2.addParameter(name='username', value='wmaster', format='str') +# procUnitConfObj2.addParameter(name='password', value='mst2010vhf', format='str') +# procUnitConfObj2.addParameter(name='localfolder', value=pathFigure, format='str') +# procUnitConfObj2.addParameter(name='remotefolder', value=remotefolder, format='str') +# procUnitConfObj2.addParameter(name='ext', value='.png', format='str') +# procUnitConfObj2.addParameter(name='period', value=5, format='int') +# procUnitConfObj2.addParameter(name='protocol', value='ftp', format='str') +#----------------------------------------------------------------------------------------------- + + +print "Escribiendo el archivo XML" +controllerObj.writeXml(filename) +print "Leyendo el archivo XML" +controllerObj.readXml(filename) + +controllerObj.createObjects() +controllerObj.connectObjects() +controllerObj.run() + +#21 3 pm + + diff --git a/schainpy/scripts/.svn/text-base/amisr_esf_proc_offline.pyc.svn-base b/schainpy/scripts/.svn/text-base/amisr_esf_proc_offline.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..153900255d21a6faf871d8b8738cb82a757d011a GIT binary patch literal 4154 zc%02wZC?||7C)OnGzfyAfEa0RTa;QL2?A33aD7B*MQO0r?!7H{*_n`yo1NU*i4foV z&H9!4y1(9Y&SclUH2St>lkA!EKj+MOoYDMmVi2yPMA zL*R~p7zXzO$RZhYM?sE4YYapI1gf3~Q3Nppas<)5)8FMHZ#NF&0$dfNWE%GqWBhv& z+zAll;9deT0q!J-OW;m{m<0DSh$(QdfVd3qG>9wU&VZN(cNWA9xK}~Uf;$H?53Os^ zDzQ7)L0)IhJO~t+L#8w1el&nP>z0Yz`Ui+>oPiR^k21@TL6$SiPdLs`L6ksT2Qg16 z5@`1m5NHRPDETo6T%ybZUMiT*Bv#Em}#aSO!fguaDQcY$r*V4F)ImO(B+ z>n7I-axSVYLhCcm=?Z!5-U4|GTAwqg0-_3{24WS&ZJX;7`r@BZ+rPwcw9WwTxGnmKN(Ll`4~mHV4lStamRd`x zb*AuAJXmbtO&a`xe@_FtTo)buF?g}UzE&;in|K20dwaVF_41?Bj?_V0MwaQdgIFJG z=?SSwoo9QG%y42d z9!ILuj!Z>(#yhmUY2r0iTUKJ#QQFALLj)_24z@GUN!yE!)RklHH3DD7>``r#U$<-g z+NkpD&bpyMtMOx!SXxd#$&+Dxh)i|p#TM-@tDC%7<>-XhivwE5l!%3&Dhut(g5a!B zfTq`xoE1)TozuyB9nUmPk@SqG4TdYZE;15Kr^s_G37f8MZdGerx2uU*3RLfGRjc@6 zvnO8oiV0r{$ytvcq||+{Ydtfl`$k2Q!wHQk;7dhe5LsV;RH5;XwCYx&=9ib4nx1aATl#7Eh#Yw^LM!st9qAFD> zV%D)VPgQ`S(8lc`+K~Zou(4jXEbla7ZB}i@>(6)hLuFX~1UCpwC}VOFo3zZuW%1Z( zb}VkH6P$=f5K1n`DelrIyi+FLB%C)1C-z=j;Uk3wpiLXWG4)AIK2w?@PT+zVQrI*~FT;NC$(bX{x1;)1*F@W>4|K zz{{P7+w0a|-!IZIqm(vjJZkzUSg@G>Ax{-u;_mq&3d~Yd2FFc9C_Bk@O$LQ^uJsp( zY;%dpgQxYSuJNg5S*wj56VFlN>6keRa1>NohGkFt&ET~vzubGmhsG1x8vreCkXt!! zB3rPY%_-aOJ0odPpGwY35okW?3bu3n6TxH<#h6kJFL;74z^?dI?yVr(|?FK!&^w8fGW@MuJZVXImbr_;<@>vJn?6I^__v$YQ~t&!U@g5%eI|V z3XNzkEiQ~iLAqdhsIb@(E)o{?o$f}9)FSVGVrm(C)!{|#zp9)l{VMKwKHiGlUs@@H z7i3qboKCM|@7lOx@9X3uK2(hc9p@{Z9{c(gPE9wI-|$8CEB?$nqt0k<)|qssauc}% zKE+%qUm7Y57aUwU{U@Pv no code + +opObj11 = procUnitConfObjBeam0.addOperation(name='Decoder', optype='other') +opObj11.addParameter(name='code', value=code, format='floatlist') +opObj11.addParameter(name='nCode', value=nCode, format='int') +opObj11.addParameter(name='nBaud', value=nBaud, format='int') +opObj11.addParameter(name='osamp', value=nosamp, format='int') + + +# opObj12 = procUnitConfObjBeam0.addOperation(name='selectHeights') +# opObj12.addParameter(name='minHei', value='50', format='float') +# opObj12.addParameter(name='maxHei', value='150', format='float') +#Coherent Integration +# opObj11 = procUnitConfObjBeam0.addOperation(name='CohInt', optype='other') +# opObj11.addParameter(name='n', value='2', format='int') + +# opObj11 = procUnitConfObjBeam0.addOperation(name='Scope', optype='other') +# opObj11.addParameter(name='id', value='121', format='int') + +#Spectra Unit Processing, getting spectras with nProfiles and nFFTPoints +procUnitConfObjSpectraBeam0 = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObjBeam0.getId()) +procUnitConfObjSpectraBeam0.addParameter(name='nFFTPoints', value=32, format='int') +# +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='IncohInt', optype='other') +opObj11.addParameter(name='n', value='60', format='int') +#opObj11.addParameter(name='timeInterval', value='30', format='float') + + +# # #RemoveDc +# # opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='removeDC') + +#Noise Estimation +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='getNoise') +opObj11.addParameter(name='minHei', value='100', format='float') +opObj11.addParameter(name='maxHei', value='280', format='float') +#opObj11.addParameter(name='minHei', value='15', format='float') +#opObj11.addParameter(name='maxHei', value='20', format='float') + +#SpectraPlot +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='SpectraPlot', optype='other') +opObj11.addParameter(name='id', value='1', format='int') +opObj11.addParameter(name='wintitle', value='ESF AMISR', format='str') +#opObj11.addParameter(name='zmin', value='38', format='int') +opObj11.addParameter(name='zmin', value=dbmin, format='int') +opObj11.addParameter(name='zmax', value=dbmax, format='int') +opObj11.addParameter(name='save', value='0', format='bool') +opObj11.addParameter(name='figpath', value = figpath, format='str') +opObj11.addParameter(name='ftp', value='1', format='int') +opObj11.addParameter(name='wr_period', value='2', format='int') +opObj11.addParameter(name='exp_code', value='21', format='int') +opObj11.addParameter(name='sub_exp_code', value='4', format='int') +opObj11.addParameter(name='ftp_wei', value='0', format='int') +opObj11.addParameter(name='plot_pos', value='0', format='int') + + + +# #RTIPlot +# #title0 = 'RTI AMISR Beam 0' +opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='RTIPlot', optype='other') +opObj11.addParameter(name='id', value='2', format='int') +opObj11.addParameter(name='wintitle', value='ESF AMISR', format='str') +opObj11.addParameter(name='showprofile', value='0', format='int') +opObj11.addParameter(name='xmin', value=xmin, format='float') +opObj11.addParameter(name='xmax', value=xmax, format='float') +opObj11.addParameter(name='zmin', value=dbmin, format='int') +opObj11.addParameter(name='zmax', value=dbmax, format='int') +opObj11.addParameter(name='save', value='1', format='bool') +opObj11.addParameter(name='figpath', value = figpath, format='str') +opObj11.addParameter(name='show', value = show, format='bool') +opObj11.addParameter(name='ftp', value='1', format='int') +opObj11.addParameter(name='wr_period', value='2', format='int') +opObj11.addParameter(name='exp_code', value='21', format='int') +opObj11.addParameter(name='sub_exp_code', value='4', format='int') +opObj11.addParameter(name='ftp_wei', value='0', format='int') +opObj11.addParameter(name='plot_pos', value='0', format='int') + + +# #send to server +procUnitConfObj2 = controllerObj.addProcUnit(name='SendToServer') +#procUnitConfObj2.addParameter(name='server', value='jro-app.igp.gob.pe', format='str') +procUnitConfObj2.addParameter(name='server', value='10.10.120.125', format='str') +procUnitConfObj2.addParameter(name='username', value='wmaster', format='str') +procUnitConfObj2.addParameter(name='password', value='mst2010vhf', format='str') +procUnitConfObj2.addParameter(name='localfolder', value=figpath, format='str') +procUnitConfObj2.addParameter(name='remotefolder', value=remotefolder, format='str') +procUnitConfObj2.addParameter(name='ext', value='.png', format='str') +procUnitConfObj2.addParameter(name='period', value='300', format='int') +procUnitConfObj2.addParameter(name='protocol', value='ssh', format='str') + +# # # +# #Noise +#title0 = 'RTI AMISR Beam 0' +# opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='Noise', optype='other') +# opObj11.addParameter(name='id', value='3', format='int') +# opObj11.addParameter(name='wintitle', value='ESF AMISR', format='str') +# opObj11.addParameter(name='showprofile', value='0', format='int') +# opObj11.addParameter(name='xmin', value=xmin, format='float') +# opObj11.addParameter(name='xmax', value=xmax, format='float') +# opObj11.addParameter(name='ymin', value=dbmin, format='int') +# opObj11.addParameter(name='ymax', value=dbmax, format='int') +# opObj11.addParameter(name='save', value='1', format='bool') +# opObj11.addParameter(name='figpath', value = figpath, format='str') +# opObj11.addParameter(name='show', value = show, format='bool') + + +#Generate *.pdata from AMISR data +# opObj11 = procUnitConfObjSpectraBeam0.addOperation(name='SpectraWriter', optype='other') +# opObj11.addParameter(name='path', value=figpath) +# opObj11.addParameter(name='blocksPerFile', value='10', format='int') +# opObj11.addParameter(name='datatype', value="4", format="int") #size of data to be saved +# +# #generate moments +# procUnitConfObj2 = controllerObj.addProcUnit(datatype='ParametersProc', inputId=procUnitConfObjSpectraBeam0.getId()) +# opObj20 = procUnitConfObj2.addOperation(name='GetMoments') +# +# opObj12 = procUnitConfObj2.addOperation(name='HDF5Writer', optype='other') +# opObj12.addParameter(name='path', value=figpath+'/plots') +# opObj12.addParameter(name='blocksPerFile', value='10', format='int') +# opObj12.addParameter(name='metadataList',value='type,inputUnit,heightList',format='list') +# opObj12.addParameter(name='dataList',value='data_param,data_SNR,utctime',format='list') +# opObj12.addParameter(name='mode',value='1',format='int') + + +# procUnitConfObj2 = controllerObj.addProcUnit(name='SendToServer') +# procUnitConfObj2.addParameter(name='server', value='jro-app.igp.gob.pe', format='str') +# procUnitConfObj2.addParameter(name='username', value='wmaster', format='str') +# procUnitConfObj2.addParameter(name='password', value='mst2010vhf', format='str') +# procUnitConfObj2.addParameter(name='localfolder', value=pathFigure, format='str') +# procUnitConfObj2.addParameter(name='remotefolder', value=remotefolder, format='str') +# procUnitConfObj2.addParameter(name='ext', value='.png', format='str') +# procUnitConfObj2.addParameter(name='period', value=5, format='int') +# procUnitConfObj2.addParameter(name='protocol', value='ftp', format='str') +#----------------------------------------------------------------------------------------------- + + +print "Escribiendo el archivo XML" +controllerObj.writeXml(filename) +print "Leyendo el archivo XML" +controllerObj.readXml(filename) + +controllerObj.createObjects() +controllerObj.connectObjects() +controllerObj.run() + +#21 3 pm + + diff --git a/schainpy/scripts/.svn/text-base/amisr_esf_proc_online.pyc.svn-base b/schainpy/scripts/.svn/text-base/amisr_esf_proc_online.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..2bde68f1f704212dd723a91953d42c7b902794d8 GIT binary patch literal 4240 zc%02wTUQ%L60VUzwlEkB7=tZ4WF2hc3z9Ili8ohYFeJVZ;Uv!NMH!}BXylpcNl%MQ zUh{kQf9(I+=bUU+wPvEggmd=nOBhX0b$wOUb?fd!`9Bk5ch`RT&WFL@0=}Q)oBrzz zfWV&vA%L6H4!BN6m%uG$bQ#<-NPyl5^hTMez|R0bqx{GaeRAv~5Mv<65G^}{RnGHrlOWE)f*2>$ zxSp8c@jSRwASS`R0AdQ;f#;)nv*L3}{z5lbM^l^Y;&jhi6Rm1Phgg1BXu9Cxp?%@5e-Z4h@rUWeWiryoi# zD&BzJO-|Qca?xD|xeUDznX>|-4x#~~31ZczF_*pvVhzN7wsH&PtxRW$bjT;vd0=&N z>;_}=j6FPt-DGT`5L;*L@-UXi^byB&V<@KEAa7@yk2r$A4r|`dBKY_ZBKU-LrVDjG z^bMCSZ|ZDi-p)0+x(KT zua03aSZ}Iuy_cu>`HHbih1hGxwhOVZ8EX|{J41dR$KIU8@;rZYYMzUIJT1@Pp5n)M zoUiG^UUmu^xuag&ari%CSAhxbpl_d>``-_ zKlhsadC=g`!~2E;ZKls@ymL4EWzP`fG&0wr4;x-xXTz%;m++3#fTk&>VCnn%QdD0O zoDT}k93_(T!Rc*rB3Uo-OxILN&v@Ekppq*hW5INeyuo6y>E`;QM)T3VMkba6jfamK z4g9g$1225Xgs+6;e8*36>ao|io*C5rNyU=G35}`XN5x?fTVKCbq4D?o*nVnD}MTVbBa#P#& z6V4S0DAPq|H4_bk)NscIu{EGlFG|?codnxgd+g~Lg}AZtW?P|L8Z1(r6zo>)tL_%6 zQk7z6?Md@W1sDn~90l>F3~Wnd7MbN8W~|lq#_v`Nm0=SHxJY0^nUb5>qKjN$R!NO5 z@lR-ZKzN5tq~5+{H*B$X6(*YU&Hzm@CkQ3Ga+vvgnEQ$nyvz4DOM>lCGCwb5+scRTD&sC+N%sE~Sr zmeev*Mh+Nd4&S8Y)JhWXu@8gP5OxoX#tUd=l#dzZ8l>IyGF667q1^yOP>V8L^t9g% z_SNFsmoNBCc_EJqpygHSof3DNwRV(pPH5j`TU*kkHJu%$BCugsYAuB zM*OaaJLzb}$0JdzFqFDQ$FV&|@VI2lR1r2b!J9afe7)P_*2kXhC#=z{bF5xZ2|0p%UGz9e*>2Ktw-MOk83W4oyaJ5*Rt2s-n=i34LMxv+NfM8zEnX&^)Umt{t6_VBEkwH5V; zq#sK!YH)v`%4_TZk8hVVe0U(<%)xC>QwlNjzkyA2<)q2MuC|t^PU5R}uj|0bw~^he z6avv)ADkG8a&(EB^R{9!PBIoXkM76IROjD@^lQkjGi+o3T^;wuyEO59y!p6Ev{D8y z!M@Hp$x+?jr)k~Z$=PMww&(Ura>TBF94XNc<)?fj{TqjQXWSVt%{$Z1OlhiA!KYfP zm1`rF(TamJXYgcHY0{Za>C2 literal 0 Hc$@_V`ulB8Ej(p`$ z?&rRCX4Y&>OTD|YG{2eO92zP2=WyZK>R*4p=)m%jO=`JWv2l zADTIy^uR5^tq0PF*_sc^W2_gHPg0NUauD{xsqBGT9%L`n`aunlRjmN30L?*=eIOC) z2RQ%|g?U7CUdPQ4yBP*K2(xksZhb&Ea+t=4G)7osgqcS{;yVU%oWhY4ASXdi@i+}~ z2IM1RlKwOhAqGC zw#=|+4`OK~OStwZhD;LNNwTOaY+q&j<U!`$ z5-sKWh)h{msk%X&N@eSbj-56U>+BxxZ`&E1Y^h5XnwT5}Odd$#gnfcg&{9&1K**Mk zv~`JaCJBDqJ9u?+dU%j3+Y!_|(skEPlubphpWGpbyNMP1=0uJ;WcD2k*Kh-LKRA)N zErDScaJ5{it_Iaguv~R{T&hSC^ilB?t6+(|QrY15PAvnLS2ot3HiEDyT%Yb!_&;gkh)e z=nQZ|R5?B*`E(ex}d4o2h(4N^0`oBaCU3 zcO_kHn&^z^Iy$tktkavujV(7phoU3q`cio-ZYVW4#0x<1!Oe3sB3HHQrn+o89`0Ek ziG(u5)aU=J+1csTfVVi&PQAtJB;N^~=3Eh6IE5x?VBJVsqX-vwBHEOs9WC+=mJN1? z?vI9PsQ_=U`bBVMk_#J)x(aN)A#{`&;{t2iNhXPJg7k{&+#~NO=B4rWFw5TCo!mKF--A(V$&zcnU$En))17>y7i0U>~q^ou!e7rNzod)eJm`k6o3 z&qima*BTSfS7?bF$<4AP?{%n71qsh%y|%VAdpt65U~Ja5yTSHWf0FmtbkYrQ3J7t zxr*&7do8fnI*1LBRp>5qYv8w+KrTUdnJe4`@f^epmSdck@b!>fS3pjW8m?!O)v<&Q zH44St+JswY4pF^myh6y;AH2RPnnDA?2S?4a?#Pfrdk&3#`-eU2V* zXgi0pGZneMk(tO%lYi(!H%ui50)SdmNDT^Tu7`Oo3>x;siC zT|Z^-uErKeVBIUDNBoVtG0Q|ew}1yH(GYvGZf?|6f`_q)P&ECd!RtRE z_7F+X(LEX9>PL6MK$|<8hLH?x)CpB$w042jeKV1y!(g=E+0KstkaWlue&}h@kL5?& n9=nC4=5Kmczw8(AF8P~$&wGW*UGiV}H9zlFJbeAKSN8q_;IuH~ literal 0 Hc$@ \ No newline at end of file diff --git a/schainpy/scripts/.svn/text-base/amisr_reader_exp.py.svn-base b/schainpy/scripts/.svn/text-base/amisr_reader_exp.py.svn-base new file mode 100644 index 0000000..02b3033 --- /dev/null +++ b/schainpy/scripts/.svn/text-base/amisr_reader_exp.py.svn-base @@ -0,0 +1,47 @@ +import os, sys + +path = os.path.split(os.getcwd())[0] +sys.path.append(path) + +from controller import * + +desc = "AMISR Experiment Test" +filename = "amisr.xml" + +controllerObj = Project() + +controllerObj.setup(id = '191', name='test01', description=desc) + +path = '/home/administrator/Documents/amisr' + +readUnitConfObj = controllerObj.addReadUnit(datatype='AMISR', + path=path, + startDate='2014/08/18', + endDate='2014/08/18', + startTime='00:00:00', + endTime='23:59:59', + walk=1) + +procUnitConfObj0 = controllerObj.addProcUnit(datatype='Voltage', inputId=readUnitConfObj.getId()) + +opObj11 = procUnitConfObj0.addOperation(name='Scope', optype='other') +opObj11.addParameter(name='id', value='101', format='int') +opObj11.addParameter(name='wintitle', value='AMISR', format='str') +opObj11.addParameter(name='type', value='iq', format='str') + +opObj11 = procUnitConfObjBeam1.addOperation(name='ProfileSelector', optype='other') +opObj11.addParameter(name='profileRangeList', value='0,81', format='intlist') + +opObj11 = procUnitConfObj0.addOperation(name='PowerProfile', optype='other') +opObj11.addParameter(name='id', value='102', format='int') +opObj11.addParameter(name='wintitle', value='AMISR Power Profile', format='str') + + +print "Escribiendo el archivo XML" +controllerObj.writeXml(filename) +print "Leyendo el archivo XML" +controllerObj.readXml(filename) + +controllerObj.createObjects() +controllerObj.connectObjects() +controllerObj.run() diff --git a/schainpy/scripts/.svn/text-base/amisr_reader_exp.pyc.svn-base b/schainpy/scripts/.svn/text-base/amisr_reader_exp.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..dadeffe027a3c89ef451c44b85e04bc7d4d6c010 GIT binary patch literal 1692 zc$|GzS#R4$5FS#NWXX}G_^O?{shadq)5MhA6mWu~=#iie;2f~sHqcA3;jSaf6qnr{ z#ny9va-WNKW=JXS6>+(oo%7pocc9Aet>&G(fBYIl`D@erExo=S0%#fmqyWQ(9KbLD z127I@ToGXj-T=G_K!>n148a6qtAYtx8*p3&(i)uTB^cI0S7EperomCeCYUCSS3uW5 zlW7@r12ie?WUT~x1vnvjTmem^1$vd!>Ne;O=&LfXfnEo_0eTbk7U=gVvOa7{)T%^n zgWdttf^l1bLOASz>A?7^)Vl`yebBq2UjwrS<8{#!pbtP_2mK-FuAq5q`$%jpvEBHG z?WWj1zHHl=*ZSmtYJDm(pGi!wh*{wK{GIr2y#wDDmoVtt@Z(QR$tIZP;#lsKnytBp z7tCHEZ7-x9k?8D?dwX;-l0WJ9B;mW#3ur=~Zuw1`zkB@X_^A8vA~!CXm<+oo#-neL zMNJa#_AVwVhMYoUg+7CO16-nSrX~h!oQmB016(0d8y~wQ$HZp-Cat59otQ}JNs=WV zokHuP2R5E^86Qb{T;@213TL^&>Ku=h$Q6!|fp}C7A1JESq}6_Za5w57M1upY)6!&` zO>Z4fXd9l>_WSo`%-t4-{V(r-b&rNrIaldfBAl?>FE&N>%7~m~`4k^%L3JG4yx6bJ z7f>yZj1%d#N~fmahqz$3Q|l%QMU`YI+dL;B!L;xrKBT-P6Mla~ZsTXpo+ha|HmQk; zFYGW8h3-gYugoDa={c}}`(RMQ#FUhHg`@4cab=1U&c0t?oU)j^rQKg6{X;&nmkF_B zyC&@_7mt$Hw)_0?q2D6&p_%=MsmGB5+WKNMGk?T86fS(8CMX;bkMX${QRO)$LO#FP zX6S61nt}knG(rz!l3P_TXc!X#*!o+*)0g9-gu!VpS59etWR(6nqmoRYD;Gc5?3BGr zA4(UCPqlzWr&rH0w#XE+&7t=qT#c_$)fN?#$;ZHj$4&rvzLfZWMS)qKfP{0?jelVQ0V@2Q~`MS>O}0 zmoo``5)RG*8v};aSzr^u5FAH#L}BLu1=$pp)8I@2I}gq@uo-a91G@mu46v`jxd7}U zI9~yq1?M8LOW@1`y9~}HU{}Do4D4%gt^k_@=WAeB!I=Yg4V-JKC-+_a>w0%%=7J)Cq!S}Qa8ZaH0LHIr3_u$|M!cAZn zFdNu1uo~@AU$IV#iz&ql@Jd&4Wr*SfQe4ecd`OCwl;VBh_q#pUWKVuO-LuE76L)KX zi)Zo(>&j|~8w2b8(vv0NOT|3- zDaVtglwuWl_2iyZQ;Jwsb39RVJW)^06SbHpKj(Pzs-PztaIKgpuX8-nQi?io{p6nL zDMbUgk>iPxq?S^w1Fz?JQqS?Eerlf7i+Qq>NGYxYU(NAkHOG_HQ}blCm?yvIc=E2GCl7%?Eau4{ zIi5UBDXsxuJGm!oDaCc*>p7mR=XkPyYM!hY^Tf&V>u#sOS$Mrz|Y2C75_vBE+ZJb@JJ9$IKP>+iG&@p7wvKKM zQQh(z2nU!TTjt#3;F>4mZ%cfqb*>#F_L#-Ir zGR0=iuGpGEv8L)3U9VH}7`iws6T}s+IBIh-+D$ylrM4^fh0M4}xS@FFVoFU)VO2A$ zYOSi(gw*3clT^Rq4(4klWmR>BUfpIrLN`{dI=*O>L$~?SqvV&(Jipx$8%*Grc#uoq z=1tzfRHB>?+Pzr@VxNc9U)n~{Uv9I*=>)0NdN&ALuAtN5`GV9jX@$ENACRZP{szLb zy&oSTJzmgu8%MauHUdT)hqIe&UqAh6z?Qhg>dh!0E6OBVgq1$ew5SiBqd=UoCW|AoK8l

6Vx%i(x?-g(c6@Ei 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 literal 0 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 Tz9lQiA9vCzI{3N;r{Mexe2dw% literal 0 Hc$@FS9mi1F4wV+L@s!r$u>L&YYP&b6Yn4TJOF7^V`b=7S|TNKhf*{@BkD&9%KN~QuZM7 zKm$yDm^MUMfjfXZ!u=X=g7!iAaOVr?3D^SFV4OgYxmF-+L*9X?LwXaUE~pknJWSdAs}Iu$f>Vl5L5)B? z1NC{8-_rJl*oI>JQf%rgc=aoX+yUL=#(C=N1+rTstUTltMA};|_vGn*FpW|m)Rdv^UIGs%q<_pYR7*_itxoM}Dn zY!usMl729w%h#uFm&~Vn{y(Mz?yW>Ku40?J^KLzRmD=S1f7h7YD(S)0Q2dtU<0xw! z@V;acQ?2vEgr;gumT7w~XJ}ey3DR^I`h?}I_ zh4Qm0uGxF7@;NKDjpZPh>Z!%iVhJG!I+VKqk~g!@me_R8GGL8y8$$Vzv-=e^!h!I?|%UM)mVD~ literal 0 Hc$@ \ No newline at end of file diff --git a/schainpy/scripts/.svn/text-base/eej_plots.xml.svn-base b/schainpy/scripts/.svn/text-base/eej_plots.xml.svn-base new file mode 100644 index 0000000..599f185 --- /dev/null +++ b/schainpy/scripts/.svn/text-base/eej_plots.xml.svn-base @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/schainpy/scripts/.svn/text-base/hf_plot_pdata.py.svn-base b/schainpy/scripts/.svn/text-base/hf_plot_pdata.py.svn-base new file mode 100644 index 0000000..b61e3a4 --- /dev/null +++ b/schainpy/scripts/.svn/text-base/hf_plot_pdata.py.svn-base @@ -0,0 +1,197 @@ +import os, sys +#import timeit +import datetime + +path = os.path.split(os.getcwd())[0] +sys.path.append(path) + +from controller import * + +desc = "HF_EXAMPLE" +filename = "hf_test.xml" + +controllerObj = Project() + +controllerObj.setup(id = '191', name='test01', description=desc) + + +#path='/media/APOLLO/HF_rawdata/d2015026/0/cspec' +#path='/media/APOLLO/HF_rawdata/cspec' +#path='/media/APOLLO/bistatico' +#path='/home/alex/Downloads/pdata_hf/sousy' +path='/home/alex/Downloads/pdata_hf' +#path='/media/APOLLO/bistatico' + + + +#path="/media/APOLLO/HF_rawdata/d2015059/sp01_f0" #f0=2.72e6 +#path="/media/APOLLO/HF_rawdata/d2015059/sp01_f1" #f0=3.64e6 +#path='/media/APOLLO/HF_rawdata/test' +#figpath='/home/alex/Pictures/hf2_16/last_data' +figpath='/home/alex/Pictures/pdata_plot' +pathFigure='/home/alex/Pictures/hf2_16/last_data' +#path='/home/alex/Downloads/ICA_LAST_TEST' + +readUnitConfObj = controllerObj.addReadUnit(datatype='SpectraReader', + path=path, + startDate='2015/01/12', + endDate='2015/05/13', + startTime='00:00:00', + endTime='23:59:59', + online=0, + #set=1426485881, + delay=10, + walk=1 + #timezone=-5*3600 + ) + +procUnitConfObj1 = controllerObj.addProcUnit(datatype='SpectraProc', inputId=readUnitConfObj.getId()) + +opObj11 = procUnitConfObj1.addOperation(name='SpectraPlot', optype='other') +opObj11.addParameter(name='id', value='1000', format='int') +opObj11.addParameter(name='wintitle', value='HF_Jicamarca_Spc', format='str') +#opObj11.addParameter(name='channelList', value='0', format='intlist') +opObj11.addParameter(name='zmin', value='-120', format='float') +opObj11.addParameter(name='zmax', value='-70', format='float') +opObj11.addParameter(name='save', value='1', format='int') +opObj11.addParameter(name='figpath', value=figpath, format='str') +# opObj11.addParameter(name='figfile', value=figfile_spectra_name, format='str') +# opObj11.addParameter(name='wr_period', value='5', format='int') +#opObj11.addParameter(name='ftp_wei', value='0', format='int') +#opObj11.addParameter(name='exp_code', value='20', format='int') +#opObj11.addParameter(name='sub_exp_code', value='0', format='int') +#opObj11.addParameter(name='plot_pos', value='0', format='int') + + + +# # figfile_power_name="jro_power_image"+freq2+date+ext_img +# # print figfile_power_name +opObj11 = procUnitConfObj1.addOperation(name='RTIPlot', optype='other') +opObj11.addParameter(name='id', value='2000', format='int') +opObj11.addParameter(name='wintitle', value='HF_Jicamarca', format='str') +opObj11.addParameter(name='showprofile', value='0', format='int') +#opObj11.addParameter(name='channelList', value='0', format='intlist') +opObj11.addParameter(name='xmin', value='0', format='float') +opObj11.addParameter(name='xmax', value='24', format='float') +opObj11.addParameter(name='zmin', value='-110', format='float') +opObj11.addParameter(name='zmax', value='-50', format='float') +opObj11.addParameter(name='save', value='1', format='int') +opObj11.addParameter(name='figpath', value=figpath, format='str') +#opObj11.addParameter(name='figfile', value=figfile_power_name, format='str') +#opObj11.addParameter(name='wr_period', value='5', format='int') + +# +# opObj11 = procUnitConfObj1.addOperation(name='PowerProfile', optype='other') +# opObj11.addParameter(name='id', value='2004', format='int') +# opObj11.addParameter(name='wintitle', value='HF_Jicamarca', format='str') +# #opObj11.addParameter(name='channelList', value='0', format='intlist') +# opObj11.addParameter(name='save', value='1', format='bool') +# opObj11.addParameter(name='figpath', value=figpath, format='str') +# #opObj11.addParameter(name='xmin', value='10', format='int') +# #opObj11.addParameter(name='xmax', value='40', format='int') +# +# # figfile_phase_name="jro_phase_image"+freq1+date+ext_img +# # print figfile_phase_name +opObj11 = procUnitConfObj1.addOperation(name='CoherenceMap', optype='other') +opObj11.addParameter(name='id', value='3000', format='int') +opObj11.addParameter(name='wintitle', value='HF_Jicamarca', format='str') +opObj11.addParameter(name='showprofile', value='1', format='int') +opObj11.addParameter(name='xmin', value='0', format='float') +opObj11.addParameter(name='xmax', value='24', format='float') +#opObj11.addParameter(name='channelList', value='0', format='intlist') +opObj11.addParameter(name='save', value='1', format='bool') +opObj11.addParameter(name='figpath', value=figpath, format='str') + # opObj11.addParameter(name='figfile', value=figfile_phase_name, format='str') + # opObj11.addParameter(name='wr_period', value='5', format='int') + +# opObj11 = procUnitConfObj1.addOperation(name='CrossSpectraPlot', optype='other') +# opObj11.addParameter(name='id', value='6005', format='int') +# opObj11.addParameter(name='wintitle', value='HF_Jicamarca', format='str') +# opObj11.addParameter(name='zmin', value='-110', format='float') +# opObj11.addParameter(name='zmax', value='-50', format='float') +# #opObj11.addParameter(name='xmin', value='0', format='float') +# #opObj11.addParameter(name='xmax', value='24', format='float') +# #opObj11.addParameter(name='channelList', value='0,1,2,3', format='intlist') +# opObj11.addParameter(name='save', value='1', format='bool') +# opObj11.addParameter(name='figpath', value=figpath, format='str') +# +# +# +# xmin = 0 +# xmax = 24 +# +procUnitConfObj2 = controllerObj.addProcUnit(datatype='ParametersProc', inputId=procUnitConfObj1.getId()) +opObj20 = procUnitConfObj2.addOperation(name='GetMoments') + +# opObj21 = procUnitConfObj2.addOperation(name='MomentsPlot', optype='other') +# opObj21.addParameter(name='id', value='3', format='int') +# opObj21.addParameter(name='wintitle', value='Moments Plot', format='str') +# opObj21.addParameter(name='save', value='1', format='bool') +# opObj21.addParameter(name='figpath', value=pathFigure, format='str') +# opObj21.addParameter(name='zmin', value='5', format='int') +# opObj21.addParameter(name='zmax', value='90', format='int') +# +opObj21 = procUnitConfObj2.addOperation(name='ParametersPlot', optype='other') +opObj21.addParameter(name='id', value='4000', format='int') +opObj21.addParameter(name='wintitle', value='Radial Velocity Plot0', format='str') +opObj21.addParameter(name='channelList', value='0', format='intlist') +opObj21.addParameter(name='save', value='1', format='bool') +opObj21.addParameter(name='figpath', value=figpath, format='str') +opObj21.addParameter(name='SNR', value='1', format='bool') +opObj21.addParameter(name='SNRmin', value='-10', format='int') +opObj21.addParameter(name='SNRmax', value='50', format='int') +opObj21.addParameter(name='SNRthresh', value='0', format='float') +opObj21.addParameter(name='xmin', value=0, format='float') +opObj21.addParameter(name='xmax', value=24, format='float') +#opObj21.addParameter(name='parameterIndex', value=, format='int') + +# +opObj21 = procUnitConfObj2.addOperation(name='ParametersPlot', optype='other') +opObj21.addParameter(name='id', value='5000', format='int') +opObj21.addParameter(name='wintitle', value='Radial Velocity Plot1', format='str') +opObj21.addParameter(name='channelList', value='1', format='intlist') +opObj21.addParameter(name='save', value='1', format='bool') +opObj21.addParameter(name='figpath', value=figpath, format='str') +opObj21.addParameter(name='SNR', value='1', format='bool') +opObj21.addParameter(name='SNRmin', value='-20', format='int') +opObj21.addParameter(name='SNRmax', value='50', format='int') +opObj21.addParameter(name='SNRthresh', value='0', format='float') +opObj21.addParameter(name='xmin', value=0, format='float') +opObj21.addParameter(name='xmax', value=24, format='float') + +# +# +# opObj23 = procUnitConfObj2.addOperation(name='EWDriftsPlot', optype='other') +# opObj23.addParameter(name='id', value='4', format='int') +# opObj23.addParameter(name='wintitle', value='EW Drifts', format='str') +# opObj23.addParameter(name='save', value='1', format='bool') +# opObj23.addParameter(name='figpath', value = pathFigure, format='str') +# opObj23.addParameter(name='zminZonal', value='-150', format='int') +# opObj23.addParameter(name='zmaxZonal', value='150', format='int') +# opObj23.addParameter(name='zminVertical', value='-30', format='float') +# opObj23.addParameter(name='zmaxVertical', value='30', format='float') +# opObj23.addParameter(name='SNR_1', value='1', format='bool') +# opObj23.addParameter(name='SNRmax', value='5', format='int') +# # opObj23.addParameter(name='SNRthresh', value='-50', format='float') +# opObj23.addParameter(name='xmin', value=xmin, format='float') +# opObj23.addParameter(name='xmax', value=xmax, format='float') +# +# +# # opObj11 = procUnitConf.Obj1.addOperation(name='SendByFTP', optype='other') +# # opObj11.addParameter(name='ext', value='*.jpeg', format='str') +# # opObj11.addParameter(name='localfolder', value='/home/alex/Pictures/ftp', format='str') +# # opObj11.addParameter(name='remotefolder', value='/home/wmaster/web2/data/JRO/HFT/2015/03/11/figures/', format='str') +# # opObj11.addParameter(name='server', value='181.177.232.125', format='str') +# # opObj11.addParameter(name='username', value='wmaster', format='str') +# # opObj11.addParameter(name='password', value='mst2010vhf', format='str') +print "Escribiendo el archivo XML" +controllerObj.writeXml(filename) +print "Leyendo el archivo XML" +controllerObj.readXml(filename) + +controllerObj.createObjects() +controllerObj.connectObjects() + +#timeit.timeit('controllerObj.run()', number=2) + +controllerObj.run() \ No newline at end of file diff --git a/schainpy/scripts/.svn/text-base/hf_plot_pdata.pyc.svn-base b/schainpy/scripts/.svn/text-base/hf_plot_pdata.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..e6e94df3b736c5d75930b4295428b8b2dcf6d222 GIT binary patch literal 3479 zc$~#mZFAE`5MJ4igPjBdAz(uYDWz>n8!R~q6iQnt1PDzaO=!#bi|5dtv5YKfbY~Lx zEB~W^q(7^lJMHdDeu-<`4%2BZOWM0qiQptW}r0-G7oYZB%%e7MNlUY&02B>Frb`;+8oF^sGVf*Qy@=*#OFLsAy0!m z19Ac6S&)k$&w)G-vIMeBgyaQ~7eOw8yo3=8wRw(knj4-0mv)dzX)m(TIaYQiGB$3D#(vOe#|Tf*e8swGWO{Rc8#&m82fw#TVw3{SggXB zJ$62aFf}(kU!Q+8@*l{<9uu=YBFm`J!mS}Q&f+k=7tD4-IsL5CF zsmXXA@2kmhZeRa>ZvAThhO2pDsG84%I^WCuF7{Zp(ooO6AuY%$4CT8uf{n?kJRzq(_He?uM~pol%X6EtCu6bi{<<#Z<7<`~izREeGmQO1Eq5nq z`E-Jo_J6G9v;R>`xd)FPQ!!rvRY*P?-={qndp*=xqT*)jQr}u;3%^YVtNZv7^Zvl! zQ;)uDs}?>CJ+7G|J|91!Gh_*6$ zihxeGV`zv}+Ks))cwwL~VY|`{+o~dbbyRr}9tM6Wq^?9#7*TIF^zw0!JZ@-`=Eb~3t=GIQ8Ch?Hw$v9E+wF%yo2X_^9k$Bl^11A)9L z>#FT+R&1x@RLwLtRUk*8&5E-=828+3D^0W6_HF+6M)iT}`t8kI_-Ap#!1n@WrdS+b zbUlj8bPk38+T#_N8PMH}Lze@3LDVtZ@)(AKBrzk-l46FYiP@3$M))1YfgKx3kzXT> z+rsdod4XYx4$<(8ugrY1-cLMNv_TW7H3=g9?YNKx}NE-kcZ9G-KGcv?=9MSFFh>8a7FnmsBF`F6Ry12-O=X|-cj8#(CTHH zi8zEhS^ci=Z6#%}p!bOwufC3aFDbuQ%D9J;O%X*Hm9=!kz{H{Nr<;vV0**vW%0~rh zgUYwCmU)8?20VM&N~Tbz6YXE28H?$DedxWy{mwcIDQPqR5Fm|H*pAc2{V-@ygw%%? zmwl!Zs(;w(EVAYVnOE>^9v)w`e45x#)YU3MpW$~+etQB>>2d}PtNI- zD%qSiHjF|?)FCN56e7SzuZxx;?gXoRLiZnfyMGd@*mGZ34#W7hj)bc!8Y|EX;xIH7 z9d_b=Pt>g>r!gIue4N(#WW64Bnc|&xC_BFTn)aLi1s|o%Y-Y)t&lEFxE1xN3mZtLs zw6dqH{NO^YkXz1_tR-s+z4@9gCGTFFuKCiyrv9_b)|ui^-|&@tNB_ksYtF(uQ?!b? FKLLpC%}f9Q literal 0 Hc$@#7 z$k+a%{krGupXqPdk3BuMHT(-cqdU6Te5-5O989GBORNx1IAJCu#H{CKQi?Lx)Wzt&YSB78& z4&)HHmq1p)9R)cIZWZJRxNm^G1nwBfQEzVz^_w8Cg2ekZN-eL0ya93w1o>N# zA2G`_>jjXDAnP2Z=wq{w!#<7FC(pmc`KJo`Z-cts^IT@nm7-^ktq#EMGWIcJcXKRd zd9T2-2C8 zJbrCWigVll_jAj4)dBCS+l5_q2h^S3%)jAXJyXy;Db!*X)a?0MoSW0^`C5Ei%%5XV z3-kTs1+34UW(UkE$J_yae`4&2A%v_Z{02WmWhxvEU_R!>8Nx2d^V`b{pq!xFy1_va7sRqwyT&tsq7 z{__^z4BbA|qj+yN7VkE;H(oZ=(bD4TGLOb^)UchE1$$}1X*3_}3Mv*mu{tzWls49z zYfm3+?{2N>H*nZ)HI33{@uVA=5+#(Tj1T9YV}|eIu+DrV{_)(}A zaa`{z>5KY<-JPwiojS%(#IY1cpm@;i`YQ3FKv zh__6v-+2wzZZ(?DYCRCzG%2*XL_A11jTH|z*7uZg0{^{U$|b!X|!?ZEFUO`&c3KL2`NInY?Tzj6FpRf?2qjWJjM|%FDn>EakMPK}v3SHX zAuqT)~6U0ec zj^&JrW2XdGYz~N(R|&3|+7>YfSYp3t5w1P<0qlx|wwp?HUg$^4Y~yyILSL{zy81d% z7r6O?xhE=!Jl~wo5nwZ2uPwq*1+)ZNOPPRVqO|{bk2?ULR5)ho*tsg32=X4yjN7;k z+x~R#2x`1Gx042I*!mVe*XXEt=Hsr3=2S3;rEL2zqPeHrTbllx*;1!{ApdWFfAwnq zUCKo)BAu@EsqSriMVn}ksB!P=IPlYkK2*j#mMn@m#?V|uFA7Z(1pzjACEGYoE;V=! zI4JM$6Vvp&hp7?|I!;L|&L<&R;M#PsUCsEp$UDzEDHmmq;=MXit7a$Bx_^j=7%z#C zl8&iwLgYJv<0KnAjKUU0$ZTl&*`|`t3C{uA0CA?ytkb4K^PN~Ff{tV67sZGw*KL&=3oib}m*b#6eF*3z{5-^FT*K ze$x;0^Is*t_q=`_CC_y%JXP1&&3>3fk*VwGD9JVPX+3=#(MuwImBpt_?$d50j{@}> zwX6OI-lj`qrJ6Nas+NbX;SydW^c*eKMu#gXl_#v>voGP+XnCe`)vA@It=gp-t47~4 u$|KVxm1?P`I-NdyWBN``pUI@ZHe+3_7Iek$&};N}D%QA#SE*`MhkgOn7-1&> literal 0 Hc$@=RgGD zk7x&cXGrJ3&w&K!=Ak>mL;>CbyhDQ=toV754(o~_^CWf1FAvcq9Eb_@RSf^Bm_3 z5MP2^fbJrf2RVNUKHar_mKE6}~bl64T*KwJm$HHaIG^3-|*L=}X~QO130 z?BlUdJ@Xmm-{kyDWBD(Fyg2mSV$bby&yjBDe{?rl_YLcAj&vEyTVp6IAS)lDyggpo z$miQn_$;u`9g;hz((hP$cMO^M9)8@VqA!7*$=2oGK(acN5ObNDz|`7^y22Fhy;*;<`?i&Fo7J5y=BAOW*SzhG+UAB=Z#^{y6jZy3 zJhWw`b{nlnFYiBT?maSRknOZvRvKG<(~E455(=Bgn|I5z6L^neE41`P>brRT)rLGtor1oKe z;7eIoHr<-%dUg^y84K2w2mNwu+pf2H>UN-d(opDH?Kc00UL!?)^Y->F{BeVH9I05^ z0yiiMP87vuG{-@7qotG7e7|WP8L>&euWImxh4QBFG)a)YfS)u&i%K8YvP!(4EI|M(Tw7M|y2L z*gQfR^SQ-qpwN)eJx^q4(}2-YU2&sv(A20kyfpP~MiisIt#H=NC4oxKo-&pfaJ_cJ zyT%Q89ETYKO0#2UPQ$-Qm6fTv^x+ab)W-8O8xQI`}gZtX*^VqHe9_qF~dcZG`43{ z7I(`ek;+bw;klsD>)ZK>X2Cd5aJQ&JoG z*&_>VYZn{DWuHdgf7Q*fNZU`?uB{Gv^UH%rprH=&>EQteLeTT^bBwU(kWUB910A<1 z(7=WU%r=FrG+e-W3N{cAtZQ~UGv7~S8qj-y)9VCvUVW%+1}PPQE%-`Ghxuu=Mlx05k$bGuBa;N7bWPX^ zRGeyUU8DQyNRphm*_(}CI4uU$;+?A|Cyenj7b zlXNfTDy3opsr;N%JpGd1DdkrS=bTDz*{MveIu-inmziI5D!&(;83(Ui*(p!_2NdH6 ArT_o{ literal 0 Hc$@01#xj=e9OOVNaX7|y62~|3MSxUXdT|XqBeY_*vo$k9$S-;D zAIX2rb1LcXMMB65Re6r29nJLD-P8Sb&usS3sqy8tzkUng_;UfDhxpjva{v;59z+1u z-rR$#$MXzC8E9sqngve*G)AB?3N*>VM}Uv0Hv%W}k*;I}p1)8Yi_d|~GLiw0JdQv# z2F*NF^SB;`>Nv<8R3|{?$zydA)Fd>fK%(6k$UI0?Ky)0@tS2YQy_|yTG{|YF&VZbO z>MY1vsGbLT9;$O}e*xqiNE|QH*76d_%OJ1tI1dUnuYz0vc@1O%J?B|pfS&p-2!_4vAXCSUjeGhYuF`~H8)c)hz;R6y)_Vff@`mO9n|%%_EXk= z*3U){d(PO4q1Yy4KM%!Te#&qUd&St?Q0z7Pd@~e#%h+OnRy}Nsv5h`E`3qh1nD!#5 z3A*|{xqU3T(Us7mNS7ziZuVxkc!uwqouwUo5ru!_=gpFbQ#VFK*i;{MtU`KQrQ&lq zY#H59fwT1fdh%$e`1B}I232EM+*Q`uiB#@zUOH+)R%i>>UqvA&JKNd~pa^w(| z$`wZ@QrWUEVojT(5mK0;7t)IaRSF=tOZB3GE^@=ZIET@2zj(kEzpf6k=_-ETha{Bsw9@c;B{&4w%=S1dC+^ zRxMzMVVtzwrsU8!<3QIpW0yKiI1BQiT^++G*DTy&_+0PQJVB)tQoGAsj;PXDMeNsDmF=*V^8adBdvw|%pM6pG{e}E(K0fY3d9lb zppKIFftG1_D;rE<+q|cq)M?k%T;gVFd!wx#40FvPNt9Wh+BtG>^s-2j66ROh*Lx*ooqV@Y zg--@;ecWmcB*NOZHj+baT8GV3KCIW6_DBaJs_BUOjrKLFshv6&WSJjlDY8-$?{gr> z%&=ploep$l7jW^E&fi{$aqFUrioyi-@K6`uy?(_f;FanOftGGl!x8m(8n~z(oA!Oj zeV}6u+Y{Z3Lx!ez@b{Gq+LEVOSPa$Cbz+0M!2ax%0v$V}qez);uiMddL2%TyFjDMj z3Ku7uZ}%Ep469r#Nvn$8^DNxQGrnD+NLFc>rr|z0rND%gbXb3lL+56gzI1`DS|f+Y zI&^wiXEco+&(CbiU(lyr;R>MoTjW^KO~!fags>jCB@6|RIiG-Qee;!Ju8&U>-c#yb zGd&&@D$SV%TsVb#bTPZ>l$RJ6T@jVWwBjYc%6o%-*}K}XDS`tZyX?RwB2a!>3Zu32 zt!|l~B%XBNliy+Q_`!Ea`$^xx%#WakEDxlwP*!zVNDjeGw9+rZnL literal 0 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 H)~xk^a)kXh literal 0 Hc$@JmUOz?-|pUT_g3q^U&l);>%YAXq4S%;=LtS`c>qA-?LiDs z?ae)?dY}LrJ~aAx(hrvammWwT=Bqv^kFfzzK1n^Y>w|a@j$}Vnhd>TMbr{qLSyfA* zO3)YuIS3M=VUQyrQ82NgS-XuBN{JZq&fj=0veON#{x>c>JKBFoWg z3L4j0j-)>Y`5DO1LEd4;@3Ai!`;xJ{f5Da*`>N3H9%IXe*w>7$6k@B41%+6dFf~@l zrE-POHOB52+O0FTQHXuR*tdn)1I9KBu`R~FE9CN!vF{79M_1TA{yWw?*C$t=>-N7s z*QZzTcy_jDE-8>xla3l81w%;hw#N7e+|YUfjLNl!+3R zI%~&KQK`mp7Hel$FOt~#m2NR%5S@5;Jz#f{=rDjS+8bCFIhb?_ij zG7`bg_R)5L4%f<+b$gfOb)Bd{42p4ZM z6*?oBKqg$>jnIFD6UOZbt=GI%zo`@tiv<*8>Ly(?Mco~hx`F% zHTRWqT(paJb!B*VF5;%j6OGhJt)@*P9E)%Z&PfX=k&AP^-Q6GfZJl9CKPQONfmJp- zYjMHrjWVyTI9FT|6;4Xa9Mj2b$+G**x)z;scFAqcWlX~=bFPe~SQ|#Kh%8%0t<_U~ zvYM$5(O9C!Z0~?uiLg$Y;M9m(6l%-do9KvZhc@bHFpvprTiQrR$xf`pgDjudYdIm8 z9k*1(6w9owF0$iLOU03`t+_Fx*gQGz$=M~Q`Z&Xl$;aW*9;ZIfZC!%sc1|p-QFe05=TT!9Y$NOMHsI zf?V8jRq6UVz%GMSJ15;TkyG!mtqgT`r#Vx{g;QvVu~;{e2b1EWE28X~X1c_!tvA@6 zUddr4hi3tn(V5Ler~(_-MU)z?U0`+7^dwn3$Xk^SxJa<=tY&Ry_b}128LLNBYxWl$ y=KKY3$}jnY-k?9?FZ9uS(i{BX8u6$7+y0!laP`&yj~aB14|wAqK7Pq7d4B-tR#N}~ literal 0 Hc$@|}B0EWG8%nR~B{QYXq+#0eOJ<{8$8sdCW_KOO zJn+(=%rgV$9N7*9O&A_{!;)6J=R14$I~N_7ex0hUZvOTzg#K?HpGWxEl~DkRw+Asm zV>tJq;ei5Z`_L}&WCT6{eDFZ}u-NcHd5n#M@=5B^z7oV^urEiTF%EJR8WW((w5w48 zRe|;ekYgYbngCe_iNbM2OP;&{Xi!c^sJF0&kW z%|iPU%aQcwAin_lCCD4h_ze4sv9B4s`4_Cp*f)jyZZWn}h<(f0Y9Y49SWt-72vd`V zTfaNj0lw+pfF7`s!5-DT`vA-2WX_k~>UGxkFv_TZd-5C4u0^ZMxAygvTd zd3|yYkEiEg+l)Oc#Quv~`M)0ijLGNl;w80$%b+Immi3}9xiXN@;wrTUo-GV#i#)@= z__q2In`ZPo{$5AaN2?wVj)q(I29D3(ZJVg+?8;6ej-vEv<+(6Iir(_G(@dEtQK_?b zifmYOkj2{BwbLYaK1rl2;j4bH?ndyPibT0FvaYPF)!hZ0N@YV6WiHaGr4Ak>N=72s ze!TxUK!fYG`lh`}@|I3ipz%ZzqOP*RZWOwX!3mw4h@K{0H$gUq6RwvjH;#+9nF^f| zOdu1k<;wIQ;e>J90(n$$MH_=!J*eH~9V(Rsohk04la>tEYg;wC2Wn@)=GN_dc)L+{ zDHgq`N`8{FI*p@LMI2Qk(G~HrnGct#ktv833X zQta|cKWOWl_8NURRM>|RmWf_g@v<;sD>~83?|*#7{=QPZ0;ozm*$PtN6!q*L@#0L| zEROO*I8rX`N}gg^(GZ6q)TuK%j#Zvk`nK39B0CJ=uF-9*DmV4fhBt@p{0QYb*&coO z?5&V;PYL-`is#PY+VmGsb=ssYlex|t`Y!1k<`Z;=P`y4dfCq+bU^FL=wLQz_pNspZ z>H}N5*j|uoKgC@WIrSd<$$0;Cnlp7=IE5S07we{TXHr}YL=-*KNvqt`hJ)Q6)*6;@ zcpPB;9NSEUDzIToM5)o*1y*;=P?Gh6yhqu9s{{MZTGnHB_Y*BUv3fv7W`Dt9!C&%b t{fa;4jrnDNsf2HD#vA+SD*JQ(b$`KII{zyDqXuh@dQ%=ge#NVJe*jcIQkwt( literal 0 Hc$@K1h5}K*}z?sD_;pTCv*Mni(PF zSHI*R<%i`tm2~&6L^;_~@|vnhtJ#_U`tF`q;kT*Mo%P?}29SN`@%IRS_SYhS#K(gO zpf=chQ1d_mw0vk4cryYY06usieORpdpghKkpnRfwBv*iF6b|GF)W$#-p*9X`f~0CC zP$g)c133y3p>dECAdxtRXu*@`02Rtfs7*586i9rgLC%nJIScYU$T?o;L0$lP5#%M1 zmq9LoTm*RqBM^p&tK43x(I4K9iOi<%B4Pq z4wq?6@or(TTjU+i=>3(~IKaa{@bfyPnZDxT;%K>LujBgk?Y0RU&feZ>i=!|;y8TQT zAw_Tb>1m=&*jBN#b_yBW*42|pJG*+?j+{?gr7Pg8x>M(exlz)ttgBSrIowKR z0~01L)Ul<1lX6?hP?Wc~4z|jnHEWgXy1hyCrf#dUMvEdqUS-R>VcZ*6RwviH-?A(LPk2+vZ7s68Qz_UsG~U1Yt;>AYiQFJj!9^ObJE34=%SSG z)&2p$tuyRWuZ<{IYORtH#A#N#l<=N7e9l#NMg}@>q-QHm6!%P(V`zj&lxur!P&sKk z!l?IWRikbhRE<*IHFfGIo%T$_B^-)X=0q7w`Dz(`MRvt4hpUOof{i3{TpF0_ zwuN=dl#h&Pgn_mke+LzD|B-tc2Lp+)wyTYFrL=|7pUO$Ik%r-tdRK)UScSROX;Kfg zR2+MC(@m0#ox}Qo&ML87^#l!*j=h5&E*}MT7n`2mJNtWFUfa~&#OOwdb)hVtQkK(A zmfp2>Hojr6&`qSPau{Oc>17oy3llWM6TSTI)k}{4rRwECD=2*&+d_z+&eaj z!nC!Hlnc6&x0qy9#0d#>?2L{gl{O09Rt}L|9;9>E=oa>=oBBxL&0#AwpNwt(MZQoeIa7sQ z-oN~r(p{Wf=yO*2t_hubhofpNbA$FA10I}04Jd5gbQ)ERhdznYXgcu6O#*XUp6)*ng`@kG*@)*0K|+hg5$13oZ-( xk~iy@{84YzpYWFo`1WSJ(T~0p{+xfcxZo}Q^SAJ?xYF-P(VOz{=a;;a_a`jDg;@Xq literal 0 Hc$@ \ No newline at end of file diff --git a/schainpy/scripts/.svn/text-base/sousy.py.svn-base b/schainpy/scripts/.svn/text-base/sousy.py.svn-base new file mode 100644 index 0000000..a0d1ec9 --- /dev/null +++ b/schainpy/scripts/.svn/text-base/sousy.py.svn-base @@ -0,0 +1,105 @@ +#!python +''' +Created on Jul 7, 2015 + +@author: Miguel Urco +''' +import os, sys + +path = os.path.dirname(os.getcwd()) +path = os.path.dirname(path) +sys.path.insert(0, path) + +from schainpy.controller import Project + +desc = "Sousy_test" +filename = "sousy_processing.xml" + +controllerObj = Project() + +controllerObj.setup(id = '191', name='Test_sousy', description=desc) + +#path = '/media/data/data/vientos/57.2063km/echoes/NCO_Woodman' +#path2= '/media/' +#path2='/media/New Volume/LowTroposphere' +#path1='/media/New Volume/LT_shortpulse' +#path = path1 + ',' + path2 +path='G:\\LowTroposphere' + +path = '/media/signalchain/FVillanuevaR/LowTroposphere' +wr_path = '/media/signalchain/datos/sousy' +figures_path = '/home/signalchain/Pictures/sousy' + +readUnitConfObj = controllerObj.addReadUnit(datatype='Voltage', + path=path, + startDate='2014/07/08', + endDate='2014/07/08', + startTime='10:00:00', + endTime='17:59:59', + delay=0, + set=0, + online=0, + walk=1) + +opObj11 = readUnitConfObj.addOperation(name='printNumberOfBlock') +######################################################### +################ SOUSY################################### +######################################################### +# +procUnitConfObjSousy = controllerObj.addProcUnit(datatype='Voltage', inputId=readUnitConfObj.getId()) +# +# codigo64='1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,1,0,1,1,1,0,0,0,1,0,'+\ +# '1,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1,1,1,1,0,1,1,0,1,0,0,0,1,1,1,0,1' +opObj11 = procUnitConfObjSousy.addOperation(name='setRadarFrequency') +opObj11.addParameter(name='frequency', value='53.5e6', format='float') + + + +opObj11 = procUnitConfObjSousy.addOperation(name='filterByHeights') +opObj11.addParameter(name='window', value='2', format='int') + +codigo='1,-1' +opObj11 = procUnitConfObjSousy.addOperation(name='Decoder', optype='other') +opObj11.addParameter(name='code', value=codigo, format='floatlist') +opObj11.addParameter(name='nCode', value='2', format='int') +opObj11.addParameter(name='nBaud', value='1', format='int') + +opObj11 = procUnitConfObjSousy.addOperation(name='CohInt', optype='other') +opObj11.addParameter(name='n', value='2048', format='int') + +procUnitConfObjSousySpectra = controllerObj.addProcUnit(datatype='Spectra', inputId=procUnitConfObjSousy.getId()) +procUnitConfObjSousySpectra.addParameter(name='nFFTPoints', value='64', format='int') +procUnitConfObjSousySpectra.addParameter(name='nProfiles', value='64', format='int') + +opObj13 = procUnitConfObjSousySpectra.addOperation(name='removeDC') +opObj13.addParameter(name='mode', value='2', format='int') + +opObj11 = procUnitConfObjSousySpectra.addOperation(name='IncohInt', optype='other') +opObj11.addParameter(name='n', value='1', format='float') +# +# opObj11 = procUnitConfObjSousySpectra.addOperation(name='RTIPlot', optype='other') +# opObj11.addParameter(name='id', value='101', format='int') +# opObj11.addParameter(name='wintitle', value='Sousy_RTIPlot', format='str') +# opObj11.addParameter(name='zmin', value='30', format='int') +# opObj11.addParameter(name='zmax', value='100', format='int') +# opObj11.addParameter(name='ymin', value='0', format='int') +# opObj11.addParameter(name='ymax', value='10', format='int') +# opObj11.addParameter(name='xmin', value='10', format='float') +# opObj11.addParameter(name='xmax', value='18', format='float') +# opObj11.addParameter(name='showprofile', value='0', format='int') +# opObj11.addParameter(name='save', value='1', format='int') +# #opObj11.addParameter(name='figfile', value='rti0_sousy.png', format='str') +# opObj11.addParameter(name='figpath', value=figures_path, format='str') + +opObj11 = procUnitConfObjSousySpectra.addOperation(name='SpectraWriter', optype='other') +opObj11.addParameter(name='path', value=wr_path) +opObj11.addParameter(name='blocksPerFile', value='100', format='int') + +print "Escribiendo el archivo XML" +controllerObj.writeXml(filename) +print "Leyendo el archivo XML" +controllerObj.readXml(filename) + +controllerObj.createObjects() +controllerObj.connectObjects() +controllerObj.run() \ No newline at end of file diff --git a/schainpy/scripts/.svn/text-base/sousy.pyc.svn-base b/schainpy/scripts/.svn/text-base/sousy.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..e66d16b91453be31350abcfd64f7f9dd76cd13fc GIT binary patch literal 2520 zc$|Gy>r)#y5Z^n40S5;#k2nb-?whs=wt0kvrfC8xNjiBjggnO68IL##TjqSaN;+JB z&Y#@Rop!b7Gj2la^XXRm`0Ycx%KcR=+}`~AT>yjMBEAptHD@^h4$#2W1MWlULBq>v z9~wRg4>~#Mj1e&o9{@g}PHu#s%Q!x9^1yS%^ucpLV-QY2cM=+txF3hc6!1JW3LqvO zSmP3iOVF7HJ^_3ZI7$n^kvWCZoX4jfGB47485%|4Gtjt9HZ#CyfzJUiId^;>_yX`n zT9<%d0bT}v75Ft555G?9GOag&uOND%F$-cAI&>=S$#U0sk8KH^9H8=+Cvk`$T({w7)0qAJSZZgvON-54V8d2EIm~M=h() zQd}X+TIy#gtAB!eE?Xzr#;9!QYx6U{w#eqrsLilG+f<*$k@}QDlrzh_WO;AYawyxm zP?kpW6IJReh^v|Q{ZDfmYXAJdac_*C#n9%#XKYGT*P`Q(RP7f+dN_JckKoBuSB7gK z3aK$nn zD-*Yc7L-G^E4XA;BU=#*gEo^abc z3~Yh`sgj*^0W!;MKNeJow<@%(B`Bkq*|wc>C9q7}$5>+H^26G0R%_eU+Fh~`5qF|< z#Ut4j#sSxBJ2m&u)XoLlJ6regZ^x-VA?s5mjj%S4UloNiN<-+e@Kn+%m0UntM)qaW zJr?@a$!@5EQ-YRJoY-gF&ZQWKj5EEj#UF`?fX5iV~K~WDmY+F2W@$#D(_!BH%lmfF8UXUR&Qow*KBeXG@BHzGHDa^&EZrg z=Tg&Hxf)!-=6<>` z?pM>BaB%so#p(TXAKNeq#RHd}>EM$0%6{1^dGr3PpZD_ql)pTYcNEeyUjCzJ$}f$t ljFr4)_o7zWTXqj3Ec+`&mD1g8*;_(t+$(zc`US7x{R?D+KEVJ0 literal 0 Hc$@ \ No newline at end of file diff --git a/schainpy/scripts/.svn/text-base/testBLTR_block.py.svn-base b/schainpy/scripts/.svn/text-base/testBLTR_block.py.svn-base new file mode 100644 index 0000000..9eb238b --- /dev/null +++ b/schainpy/scripts/.svn/text-base/testBLTR_block.py.svn-base @@ -0,0 +1,170 @@ +''' +Created on Nov 09, 2016 + +@author: roj- LouVD +''' +import os, sys + + +path = os.path.split(os.getcwd())[0] +path = os.path.split(path)[0] + +sys.path.insert(0, path) + +from schainpy.controller import Project + +filename = 'test1.xml' +# path = '/home/jespinoza/workspace/data/bltr/' +path = '/home/erick/Documents/Data/BLTR_Data/sswma/' +desc = "read bltr data sswma file" +figpath = '/home/erick/workspace' +pathhdf5 = '/tmp/' + +controllerObj = Project() + +controllerObj.setup(id = '191', name='test1', description=desc) +readUnitConfObj = controllerObj.addReadUnit(datatype='testBLTRReader', + path=path, + startDate='2015/01/17', + endDate='2017/01/01', + startTime='00:00:00', + endTime='23:59:59', + ext='sswma') + +procUnitConfObj1 = controllerObj.addProcUnit(datatype='BLTRProcess', + inputId=readUnitConfObj.getId()) + +'''-------------------------------------------Processing--------------------------------------------''' + +'''MODE 1: LOW ATMOSPHERE: 0- 3 km''' +# opObj10 = procUnitConfObj1.addOperation(name='SnrFilter') +# opObj10.addParameter(name='snr_val', value='-10', format='float') +# opObj10.addParameter(name='modetofilter', value='1', format='int') +# +# opObj10 = procUnitConfObj1.addOperation(name='OutliersFilter') +# opObj10.addParameter(name='svalue', value='meridional', format='str') +# opObj10.addParameter(name='svalue2', value='inTime', format='str') +# opObj10.addParameter(name='method', value='0', format='float') +# opObj10.addParameter(name='factor', value='1', format='float') +# opObj10.addParameter(name='filter', value='0', format='float') +# opObj10.addParameter(name='npoints', value='5', format='float') +# opObj10.addParameter(name='modetofilter', value='1', format='int') +# # +# opObj10 = procUnitConfObj1.addOperation(name='OutliersFilter') +# opObj10.addParameter(name='svalue', value='zonal', format='str') +# opObj10.addParameter(name='svalue2', value='inTime', format='str') +# opObj10.addParameter(name='method', value='0', format='float') +# opObj10.addParameter(name='factor', value='1', format='float') +# opObj10.addParameter(name='filter', value='0', format='float') +# opObj10.addParameter(name='npoints', value='5', format='float') +# opObj10.addParameter(name='modetofilter', value='1', format='int') +# # +# opObj10 = procUnitConfObj1.addOperation(name='OutliersFilter') +# opObj10.addParameter(name='svalue', value='vertical', format='str') +# opObj10.addParameter(name='svalue2', value='inHeight', format='str') +# opObj10.addParameter(name='method', value='0', format='float') +# opObj10.addParameter(name='factor', value='2', format='float') +# opObj10.addParameter(name='filter', value='0', format='float') +# opObj10.addParameter(name='npoints', value='9', format='float') +# opObj10.addParameter(name='modetofilter', value='1', format='int') +# + +''' MODE 2: 0 - 10 km ''' + +opObj10 = procUnitConfObj1.addOperation(name='SnrFilter') +opObj10.addParameter(name='snr_val', value='-20', format='float') +opObj10.addParameter(name='modetofilter', value='2', format='int') + +opObj10 = procUnitConfObj1.addOperation(name='OutliersFilter') +opObj10.addParameter(name='svalue', value='meridional', format='str') +opObj10.addParameter(name='svalue2', value='inTime', format='str') +opObj10.addParameter(name='method', value='0', format='float') +opObj10.addParameter(name='factor', value='2', format='float') +opObj10.addParameter(name='filter', value='0', format='float') +opObj10.addParameter(name='npoints', value='9', format='float') +opObj10.addParameter(name='modetofilter', value='2', format='int') +# # +opObj10 = procUnitConfObj1.addOperation(name='OutliersFilter') +opObj10.addParameter(name='svalue', value='zonal', format='str') +opObj10.addParameter(name='svalue2', value='inTime', format='str') +opObj10.addParameter(name='method', value='0', format='float') +opObj10.addParameter(name='factor', value='2', format='float') +opObj10.addParameter(name='filter', value='0', format='float') +opObj10.addParameter(name='npoints', value='9', format='float') +opObj10.addParameter(name='modetofilter', value='2', format='int') +# # +opObj10 = procUnitConfObj1.addOperation(name='OutliersFilter') +opObj10.addParameter(name='svalue', value='vertical', format='str') +opObj10.addParameter(name='svalue2', value='inHeight', format='str') +opObj10.addParameter(name='method', value='0', format='float') +opObj10.addParameter(name='factor', value='2', format='float') +opObj10.addParameter(name='filter', value='0', format='float') +opObj10.addParameter(name='npoints', value='9', format='float') +opObj10.addParameter(name='modetofilter', value='2', format='int') + +# '''-----------------------------------------Writing-------------------------------------------''' +# +# # opObj10 = procUnitConfObj1.addOperation(name='testBLTRWriter',optype='other') +# # opObj10.addParameter(name='path', value = pathhdf5) +# # opObj10.addParameter(name='modetowrite', value = '2',format='int') +# # +# # opObj10 = procUnitConfObj1.addOperation(name='testBLTRWriter',optype='other') +# # opObj10.addParameter(name='path', value = pathhdf5) +# # opObj10.addParameter(name='modetowrite', value = '1',format='int') +# +# '''----------------------------------------Plotting--------------------------------------------''' +# +opObj10 = procUnitConfObj1.addOperation(name='prePlot') +opObj10.addParameter(name='modeselect',value='1',format='int') +# # +opObj10 = procUnitConfObj1.addOperation(name='WindProfilerPlot', optype='other') +opObj10.addParameter(name='id', value='1', format='int') +opObj10.addParameter(name='wintitle', value='', format='str') +opObj10.addParameter(name='channelList', value='0', format='intlist') +#opObj10.addParameter(name='save', value='1', format='bool') +#opObj10.addParameter(name='figpath', value=figpath, format='str') +opObj10.addParameter(name='SNRmin', value='-10', format='int') +opObj10.addParameter(name='SNRmax', value='50', format='int') +opObj10.addParameter(name='SNRthresh', value='0', format='float') +opObj10.addParameter(name='xmin', value='0', format='float') +opObj10.addParameter(name='xmax', value='24', format='float') +opObj10.addParameter(name='ymax', value='3', format='float') +opObj10.addParameter(name='zmin', value='-20', format='float') +opObj10.addParameter(name='zmax', value='20', format='float') +opObj10.addParameter(name='zmin_ver', value='-200', format='float') +opObj10.addParameter(name='zmax_ver', value='200', format='float') +#opObj10.addParameter(name='showprofile', value='1', format='bool') +#opObj10.addParameter(name='show', value='1', format='bool') + +opObj10 = procUnitConfObj1.addOperation(name='prePlot') +opObj10.addParameter(name='modeselect',value='2',format='int') +# +opObj10 = procUnitConfObj1.addOperation(name='WindProfilerPlot', optype='other') +opObj10.addParameter(name='id', value='2', format='int') +opObj10.addParameter(name='wintitle', value='', format='str') +#opObj10.addParameter(name='channelList', value='0', format='intlist') +#opObj10.addParameter(name='save', value='1', format='bool') +#opObj10.addParameter(name='figpath', value=figpath, format='str') +opObj10.addParameter(name='SNRmin', value='-20', format='int') +opObj10.addParameter(name='SNRmax', value='40', format='int') +opObj10.addParameter(name='SNRthresh', value='0', format='float') +opObj10.addParameter(name='xmin', value='0', format='float') +opObj10.addParameter(name='xmax', value='24', format='float') +#opObj10.addParameter(name='ymax', value='8', format='float') +opObj10.addParameter(name='zmin', value='-4', format='float') +opObj10.addParameter(name='zmax', value='4', format='float') +opObj10.addParameter(name='zmin_ver', value='-200', format='float') +opObj10.addParameter(name='zmax_ver', value='200', format='float') +#opObj10.addParameter(name='showprofile', value='1', format='bool') +#opObj10.addParameter(name='show', value='1', format='bool') + +# # print "Escribiendo el archivo XML" +# controllerObj.writeXml(filename) +# # print "Leyendo el archivo XML" +# controllerObj.readXml(filename) + +# controllerObj.createObjects() +# controllerObj.connectObjects() +# controllerObj.run() +controllerObj.start() + diff --git a/schainpy/scripts/.svn/text-base/testBLTR_block.pyc.svn-base b/schainpy/scripts/.svn/text-base/testBLTR_block.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..e3fa0a7ed18b4eb7e2af089b0194dc39d450ca33 GIT binary patch literal 3026 zc%0o-ZC4vb6u!G5A*9fxP$+2BSl`eVb`uN;))ouawjyAtFK55xEISjjVY9PmXTnQA z+W+7uKltPP2mS!Pb9WPRAmXvdPi8l>bLV;HzRsP@A5(?je*g6+57J)||C{)izhnUz zfPUtKnWL3=fK`CK3+yhi_Yw~V*!zTiK-h-~Hqi9Z6-|r8{+QUGT+(!pu=^vi zCBl|RdSDHCa2d0&*;gg3_Mb(y^1qDg(`%xtzh+dcuNl?azmDp&D^aaq!`=Y)Ij{%R z5yN{5SN9CCF9>@$G82!6BHFx!eL2)qmvufSY-=R8eNC3Wx(0hf*w-Vmr-VHli9ILm zn~~TKVc(9#b_v@XiR}~i-7toC(;a;o8F={~EH?E0yo^I(E9S1^tRlk7t~jaK>-Q@) zySiE^Y`Q(w7V$$E3`9%WGfIXwpo|(=Lt+$VXRL-duY{7jMClmT*EdxeR{fF*79!>Fg8F|u$F#!vh}p~D)HVca}%1KN+@ z9+z6k7t|XeByyU904UA1cbqUQY!+k7a5^tC6Hx>2SMP z5r)}BlNky(b%Pi+V*8;ElcxA-3r0p#hg?sIL}}|Hh%gdpT@tTO-o7LYI#Vae@x4^= z!>8OoYAa&aXj~@^QOx%Pp%ND{KFI?-q^gACkABE7m-=AE#L>n@M5jQT5~__RwDwbU z!dC%T`ovQmytW&LJlOH2O6!2Rk%@|f-9{JX{?t9ABU!hTBJDO*JLa-Yr|L`-lSxXe zu9AGNWgW!|i7%0t)URfz3n?Gvd`f6yM&uY3x!zxO&-7~240U^PzTd3PCKFz>Nh*X) zDt0a#dQ)=ZqQFn0IpWGYWoi8+>QXZr#{}TnJ74y&e_|0}3LBK1d{RJ8EjN}n8kubQ zN7O|5w42(jRaa9wmje}hhn>VaSG|bx>@udC@cR(GDW+G07Pds#((II@TY@;*#AED; z5*0sLPT5sD8HlA;$6 zR-$t&xo@P^zg(J!f$)x(qjSp013a9)fIlRgKjV-y<}+nu&YUqzX3oqR^q3Q7*(e&h g!82hNjbe7%C>v#y#*62lWE*93KAC6A#+B#pUrrTu4gdfE literal 0 Hc$@?(>8_NXp@iwq)q)$j#vr2X1&_8l4Iy= zesZ6C+L@7Uw!z6mF_uU3&3to_Muop7O3SN%{}w{`?=pTL;MW`u0Z9D!AO@)SWe@5e zD1fF9%>oNU@D|{$2hxXYbsv<+SP_&@T95n+5D&w?8UZ;3Cq86<49OzYM?nrleGF8I z80wcmU4rH~NHjxe3}gu;Dn}75c!W)WL>SjekW(P1L0$$q!|N=_IgnRC&V#&4smKM8 z*U)pcJ_%|Pnp4bp9W`Eknj>9iwi_VJY%s%RfM1^lHQTel$@X)g=Ae0nH6MZe7~~?z zPe6X^GV5cXG4^>L>oa|Ef$2-O{%WB063DMX-r{`nKHsp340FyEdEa+B~TFp66ZmTw~8~o#%Wn+Px1(`%m_LpY@#2RZv%ZJ|pb2 zk&n~IzGG~ivHR~}-!t~ZK))XudoU3DDc8k!>)PZTx89TE!w=;6=zr$;cp&!VVvc?6 zDP!CD9`~`I8T(}*cCl{x44yot>#zW7%#Hc;uI5@#LmQemC*9~vWtI|tPWF~w;9C>@ zgMTj~dVZEXTr4fO>?p1W2Q3jL2M1;xH+$;1ok+d7uZ%S%dZfYzqARDZ*!sjHZ2^CR z^}yoe1&L@WJ4}3NUk&Uf6s0m@7Ns`Q3G+)~g*{7^oxshnI=13i?J6Nv#uTZr4Ksy8 z1+jKZnabYItG(YVc8sE1k=cg=*(sM=HCU|#)k^K29l@Gg2MeHn1aPb*IX72s#$@ zq7+O+chXE_gWc($Vi?D|+TDv&ZdmQk%DTCZ!XvuUhmoSuQ1PP3!bbE)FTQ^M%*-SF zOq~sYmTuC8B3|wKV$RGiT~^N0q;cd<{#e-TfUFy-aCg)7f;!C%H<0wY5ra%7@sa$*4=FBi{pznCZV)--fWRa6#*CzX!QPE0C7RdH`!rnRjY z-Ol=&^sM5ZG*h8>ZdY{h-4QG487FwZrDZ!-KhT_*43`DJ>`nV6f7~DThW#`!^a wxzCtCgPN(K8L#Y>eO&zolDu*Oe+enFX0EHH&rnYG-CFb~{GvBeD0wCCUpM72qyPW_ literal 0 Hc$@cpQb&ILI*?$>t2YOSiwPQ@UE`K@GdES#3)$bR@K(PUU9P-Pt8K z>+P-B*=l4y18NASo;>9hHt(&uI(GTsZ~VLrsPWHvI9M94nu|ET*xH_7-P)Xg^yt~_ zqy1PVK~qI`c3T;1#t>JkQQir4<(*mBZ-&+3(f{JY=%Jg#Oi0|SdA5$H{?I4AUj_g6K>?kf?>(Gjt+EhZS zgtLo3x8Zm9fd)p0^X{AE@vnX0wU*__C)xOW3MU8dt)ak(j0ZRquW4l=7dThm*Ya+NFRMF`1w%k0wtGk&*if+$&oDoYb?N@r3>;lC-(HJ- zUSD@>BX$+ns2bF|Cvh(+(>>La!&zc4YCkSh?HpN=Z8o=8d!lg{)714|do$VEx!I>M z+@$Tl=*qB#M|AlB3&bR9-x^B#>OvgVm=3p8gjF5V_Kn~=QB7@?6PU^FW!-BEV^xx? zC88QswBdtdRI-a&baWeuo)>YvfJrXY^v(jFKT4{FD%@Qtn>Ggnu`p&&Cz3Z1FEw7d z{BFI&LMO!{WEu&P88J#bKreE zFr6l%=%j59cCM_6!@zPtcu6aJlBbv>dgQ1pINj-ywg( xpYf->X>Zz%?%O}(Bz})H!=pdlKXthF`QO)L$vXYssE2=yA={VDjN^RB`v=3?2VVdH literal 0 Hc$@jcCe|!+`qb2#=#s90PfpMv^%L5=k7-l3h6t z@*K$XATNNN0C^GQB*-a{mq1f>y68dsd+Io5ohHGc;3 zb7r`}(Slo?05#F!{{rNfAiv^ulsX6Xi@bgv@*SVM+y&-dVD7~@gG*4H?D2c~1UolLQcbettz&-QX03O6v>svKF?Kf* zyY~s~K4ae}Vh$euIyA`yGZ*k&TO#n=ywZ6CvSxN>8O*zU)f>|(Dz>XoC|UVk#SH;MY* zGWKI4R%Gm_|1Bp!GxkfO+<)gQxzj(DuU}8d*B;CKmS{_S!jBTml@l?^m`cPdj8zk{ z8e?7}R{y9^ofRT7v<-Q7r8~PC&w9^(JaZc)eht(ROg>p> z3NM$PnE-Dg?;rfV^yp%mad5CS+%T7Me6h1Tx3RN5x3>0ldhIY&k=Iaxo!(W(n$sj| zqP>!@%ll^ju;E*mmZVMLCx1I{`|ulxhOz^s6=iaHJB(AQOgZvG>*>H;M>^Y3(i2(Z zRRiIdYr+e%>#K8HZ(kL%4P*Dnh*EWvIbxN0wXK9y5l0saTeCxSlUotlRe?dK zkt*c!OW9l=AA1T(703^vd?CA#JCfVQtQxYG%iZCpBh>{83wM@oIGrbZb&c~Dq9`JwnNSanbo$2SvbSGnQ>bLRrTC6mf?58Zz|KzA`GMHF{UNuysB!?rRtfqlm+d1@$ai?jLV+2xx{Id&9{TNSOe)|FSSS;M9dyg=#$ z?#M!pI}$B&&*o?IvvZv%F3_qf>rP2&#-*wFTEsq*?cfoulZSnj$*oy1>bBTh`kt9D!bAljn? zKuZ==hv6QlirBVyH+t;GB|PldZToT9v0GSVe@#svv>S)Riuc0~cKu2VGs3#mq2&&` zF&_q1mcl*}entCKtr4Un)zDVO3udCb{|_3%U`u4Hk*IiO9k+y0(L3a#-B6G8oCw2t z3~#=wOY_*$6jT#g_`sr|+Bz5rg)s*@l3X!7CvX?%-qk9sHcpDUgwr)T*GeA7pr@5T zEuwPGd#9)0zIe{QJy)$H=psV*l7BPP)KM6}Z7I&FKfa|)Qy_bfYv`@Vc2 zd5STjMfSR^0~=}I$B0N#fSZH9(#GYYGnqA0LAp7>F05l)@#%M@V6#+@O)A?Aw;z%R zR2v~B9gVL7^ka-`6BCbgP$7|#m}e6cCg|*E3pzw7pYJH3ZNUoq<3R8zichb2xvh%Y zw5@GRMC2?+MeS1((Y}fn4)b;@QL4R3;>M3WtKQ|gHTHBIdVoY{ ziSiaTgLeK3Gx&j{!944>A$CT2KZ}jCZ$eSVYl&~9NNbxlx*2s>!d5oE5lxn^$-SOy zHEgl7ckz5_`szOI6!RwzlkSL{an87DXUrLJ2HYVx{Kr=N`khe+U-T&5mqs7@ogwF6?F~Mg literal 0 Hc$@P3vU75qJRmr#Y`8L>0UK>wU6cmm|zfL2K;`g4M1@K=RHsy z1knq{A&>(^S{w#B4Al`3sMil-00askI*4e-5W|4XVuYWgP#gtufu5vu0mK-Hiy+3y zoR|PH31SMwB@ojfE`yi>F$>}fh^rvxKwJZHoyQ;1^DPV&$3Tuj^&(r%;)+omXXXiJ z{usn3EHKH@gISycIn|Q?6vSsBKIipu5MMy?63B6=PBZ!?hS6m8NLEzOWjzTZ}~lZE3C7c%9r9_J0~|eCsSQHxeW4hOY;_M zu647vvD>Lw;^jBzdU=O+zCELJ_dPm&tn*!JWcL`m&)9=A*u!%&vd-8>D)xvgJ(|k- znDw5d>TNRiG&LX3&W&yBgJXNn*o#!X?Q^gl#=cL*{=a*YCq zykfoAsn{FFen`cNjQyC3{lwVMsn{?7iCdK5@e|s1Ga!fPj5Wls&6U~K3QexiHssOO z_Gperc#!YSJ9y%I|KRV1M<0QC10T8{A3Kq%N>|5Mar}I5e_?ZPcVT1WX?Ei@l#y4H zfzIyBSjQI-uf@7_;4AkiUOcV&+9Xb)Gx)OCY~6$Jz^O^yN8G4m*?JgGl=hyG=-_N60CG@I;j1*P|wp z7e^&2t2E}IntV)k2G;}R9vae(Q0h^fyi&e)4&|hhrPT%sOSf0n@Z#*L!1n^_aglmCg}&49 zh@5>oar`6p{ZMMIhn^r$BQMY|>a_zIZI>VL@^B|4th38Ty&$aXO`*q<;+H*N?nxh8 zKt+k|kh4K%m9EGr{)61kW$j$HkjpORvdg*bN-n#a%ihdoZ{@OU2oa39jRH1G*eGJ7 zjEzDzO4%r8ujOouVz7OSZ0Y^9vPTk zQw4c1*cMxPs4AO?kz~N@1&jUK3o*%&!-b$y29F-??#*SDHOq#%3g?6Xf)?FL@Dn55HrbMDbe<(PZG9vf<^V8Oz>byVp;m677B^ z*zO9m%G0n!$w)$7W1Zdo%`WQ&_A0KZlV%B6+hS{{EwiUBvxOwyJ=_Ej8kh+tk*7MQ zAa5*&!6DOOWgNe(e5%3-&LdelBjINxK8BJs*d@r`ag(a`!~=&69!tsi-YSI-7Mf5Lo&q{f-ln#~A2r zs$#S6lU|QJE#K6V-AeA#m}A9>mZ(4>tz=m7Y%UTmxw#h^;lFmR1jr4ykd55fh z8*D2avCp~if!!~{i4EbeJ??*{=RjQrT*igUHBi@x#p_trY~?dhGi@Hf0{Jz_9P@>2 zPC-4x>q{V)K_UBjkcGIOMX1b!vZ1~}uIPdD0-P5vmgl={`Ke_%)$2(Jbv=2;=vy0L zFblE-_0K`w0NPv@>R)iNZANc)?Q7*D` F-R#=edu)v`d6%(!J=lH59&}@!SP$F1 z*wOw2Yd`9a(&^Jba-Yt0_3158x7wDE+44`_aXQ#H7hq2qd&=084i@LP{t+%V*yb7A zJnyl2@e!Le+kD%XqfN$MGWO>lY>Tm1eX(uEcKZ6m}w%hM(_nNWq z`eFx+y}2+Ra?-W>{f8DE7AqIB_}2?q{NXpV_#+AE7vA_4lepjaAQ-PS^Gjto& z?Y8z2YdhV0?O>8I)fcNWR_lu$f7me{%w_CSU#!kPPx@jWV~y@zbugc?@4M`zh8N$` zw!Z{58oy|RWM#3vLX$gmIk5CqNBWv2e8-m;-{Ow}_kZ}e?b7dqMGFTrgu`yA>&h_^ z{bDGt6|yId>`T`X4G}sb`%?H#5w^0WLUApcjx|mihxN9?@>#<(Ho2B2Meu{78NmO( zXeg7W5Gpc-q8UR`s>li5z_{9vW^kTwDCvs)#*_V>a-ISlZkG3=5+TRBq4GLVp>R-J zMfqLVG0hN#p7@9LIKgPPV|LmQkx^m37K*Ct=*SFHY+;0H1JoM9~WO9ncsqsY1CBK}`sqju*F3=Pu7rMULZZ?ioxKn-VY3GFLOm>0gb2yIc z2Tijn-Pa^vq2Zr2xLkJ{{zbz+x^>GmOygiK#|=<*Jylj7wt)`g+yZ8ca?|D*SsLR+ zSaHjZ3?uJ^*Nm%N)nP-JBn{)CLiB>VAy>>T(UAOGI`{tqv17xJAu4k0eM33AT{Mz7 z4}YB`Qd;FE#1!K7r=lsjJ4^RDO{t!H*nqSb=UDi@@@Oy75U0A5Tg%;JtQ;T_pU1Lir-%+oU9Ex~FjC2EReMT9Pbs?E136)ma zOPNlVE+cm;ZrX^&h|Wws)Jq}=mNDn$nm$^_UZ%X8sKQqhZ78`Y7zjiZo$63BL5;}Z z@h-eOu5vrzi4$H`d(?LnH&hL6RI-p_HcUhbE(d;%6N!0nA5npaFk?VTYQOasa79oF-N{=^LU|gF*`Yg~-T+(y9UxRJwjI!cV+VtA{+p6dK#(ja zt_s`|f|Wwy*Ww0q_llGXiANkPxvVyQiRDS6?~0IimDK#m_3_PtR|9zxVJKQGt?z6+ zd&-W^n3X!6e4?BV3?Bp!kEZhXG8C{+g2jG|rTDmpu2FCBl{u79L^6|%6QfX%-o)lo zOuLVh_7Wu!HvL5^*83qUL;JOdE$5u%v4>BhKsYKNS31<%1ZB!1FX+8(hpsdOrBr|rvD`rK#4p0XG4 z|1?@$=@~QDBuVzTb;+KyGehZ=W6fI&_8cPkv8Sxe)B;JV46ThN>*qeRRwmunKeswF R)vId{S`!w2?NMuV;Qv}Kp(_9Y literal 0 Hc$@rqg}^xB(08iP2#@x zU-WPGxu=~ONyaA?oYSYq_GWgzx$U>Rv!y?0r&b$(eebdCZvlRv!%uIO858ieSio3o zC|j&$<+9CMHj|9?O00K|gfaFzW50ue&91acBUouvYmv5`X)TOaV!=2ICs=C&=I2;z zl8G_anqqPSBetfQoMyclCdy2VGcmyg7yvp6Xvq@O48n>T)|zEvmbK24^#vx*GXdiq zCK4B!m}lY=6K^rGz{DaGmzh{%;tG}}t}=0ri3$_fnYh8kO^7?y0>?SlyGZ$#L1VS% zDe@(X{5BKskilEDXlAz-m|V#1-(})GCf+AKc+IokBI$22@c|PnOx$MT!?gO3SnKkL zXZ1CntLP~&ljjD>^XvGU7D_&x9 zDfhffp7%!c46%>jfZZqT6T5%%~D z_9bCo6=FMYz@8BHbz#1zggq<7o)flPi0u*fO(C{V=VKPvJ)&*?+hfSo!5f+S_6}R?sSD3t#TmM4V?a{Rkv0n+}h1elsULhv3 zx{5GK*!e=NLotsEu`Xf$=&FWTkFe&5pEzb;euc}v%H&kqoP$hrE!W_rf(?MA>qF@V zN$@T-S3-C|{J-JvxsPwkiUorihhZ;KJ?R;J9b|XISw0SzpZFdRdE)WqCp_x&WUyR! z+zovxwKxvjz1(2!Gz^T5p@k_SeAhMS;D5wJY08*FYU8+O8bl$rm-w;qRiyDrtA$ed zy!P;mgWYBg6SQ}l`?`)uSB0{sVwrFctfj8)`JU+~Ae_nH?xh9l#i83t$hDD4?I__L z-&5L5U~X=>8N|}e!sI&@7=9%8B^NTGa$|0~W)h!R!xQt6L)B9-!=h@ATXP%4l#Il` zpmpb!-+>=WjoF;7dkyEF)%U^6|+>PKOZPZcPyyI54Hc@h&x?6Q!$GJ^$ zJ1Pmep=e=0Fg`}pkMLwv@v}eKk9)%r&&MhtgB|#-T*XI)UOQ$V-p5QI8BZ z=vV?}sr~`)3({{?yF&bPw*N=OM~C*EEZ{pJn~o zuoDz~)1g(+TFo3t+lkUTuP9K4IH^0%CIvfzs(cejbFIL%-R#0q*y{&c5=Gi1<~%V9 zr$I)ZYIvDLpVGXsLFwgb+@}2@n+Dlv{xaQ{bSpdl z5nVmZ(lIfudOI)RS(YA77_m46DAFlr$4E{#&63v}WPFmep?&x&-R(L>ZsJu`P2f|e zmq3%K@mlo~waVjo4GLO2Qip4BH*gJoFri+C)n=WAfS7B2q7p&GgxWwqa9(yhbVT4% z@}Q#vJfxU6k)bj&Q-sO%@{4Crsp~zJg92#fCdNWSpaatW4s?12`e8iS$0Rh>ao`)O;Yb?qM34wXKuClA zUc zOr@=3>yRhMFfDL$i@q=5@l3A5eMtJz3KIBg z&<8AkyWkjj$2B-t$2#VotflNHN|~Bg{bZ<#2etGq%^$?$DX$;b2mt; kpl&+TTa{Aw-&(XPrJ>du(az1E)!Jj$tOY-N%9=X&4{6vz8UO$Q literal 0 Hc$@r>lC5MRm0U<2h5@*pw9d6uStWdnK8G);IUB~1fkXp`|5=FlBjM%HPhbBI6Z zPwwYVyStJdhnUR7md<cP^x#Ieeev8}DQRBt91S0QDYiLEY-o zHq>oU0L=_EvrG)ZCxA~VV8d)Z1Il772P#8ci}W(!55s}XLVX0}5Y+Ra3ZzvZ1vLuI zF_1Zs!ypmOgDij=K{R8@Q9y%o4C>=7_XEgrkho5eaXATc3gk4%OCV=JUIuvu!`S^=l^dZD+sY_c2e3RMYxw>O#$? z&nUeoSq3rjpP+dIR1wr1sO!+2=cH^#Z}#Q&;DWq15$ilYr}N|jogC||56tWr#-1|v z>pAQhS8IGA_8aRx9~k?KZ^p6l-EnL(wlz@i`(l*a@alIux?7;~$t8Z7a&C7yw7Ek^ z$<*B*b&n~W6#EOWaHM$u;peSKQ)a=!#nAE~rioKob4sVJ(reEZEfKk*^jZXM5p_yc zr?M7bN+eEOht00Q^2e5MY%(fMhTta^g98f!(NZQy##L;biWx;xs@RRZ(0DqC*KuEN z=$0z$P({K;o{G!oj2|`=@8#NycZb{W_sSH-;m&?7t`1b+^IX%8F1BMvC<4eIR z^}tasqGR7~ES zN9${A>yFda>H*c2^|dGXaFKN2dx7%!Fow8NzUX*loMSo@{;8R!;36+DZ`-XS7405x z_}V??!lqg5McQRQUJ$m;jx-ZUBlFnv)xPqTYjl*j3%LN~Nt*^HKFPLOuqJ{N^~Q@0 z!ykm-Rxwf4%Hrcy);`uzOPJJ=@liCUuBt3n7MEyAf0n-Z{RY|7;fI@Xk*#kjS9gzv zD2^!DB#MMqx#2K`gufx$k~^{bn2WL>V#1N&qEID+moE?YG>XS8^>CF>D@f}Tb8qYf zu5Rq0#W5;99u?9m!XmIr#bHm!zQ*+XUHIB?kW~jeo$Q>U8_)QPPatW=-j(90V-s+V4b*oOB5BLHq!0MIP^Wk4RE52dnTC_VTe|_zOD{T zqS zj3qL=Gy!O+um>F?RH<|g(DAc@p(Jp;6=}1(eWskQtvwM@sF(wVe&hu>HL#z!!P>2` z!<2|3kx-kvTiY9a1|K=;CiNGUu_eOVGUdUC>|?*EpjITt0PktfM4nOaaheXNsS?d~ z!i`ZVhlPvH4@u<$+;mywFlq-2JkWbf{6}v_s>pLs%V#<|jYHw8a_lyQ7erc{a;)1? zj}vyv$%O7r&}42NR+htLcs^}u+4j{lN;$^=qj1e0vy0ZGU9fXj&d%FKJBQy1EBD1W sZ%^Cv_BE@R$z@$@&SILrQ}eWDahGti_>M9)%y@Rl8n^JZ3sxcfKg6_ZtpET3 literal 0 Hc$@)C9t`grfEn>NJyYSj=BfWqFu0zu1C8LxF7l@ zKeIohpZl~kBgs(L0a?rJymRmDDEHTJVZQSBTZg58*WrB#ulloxF#$h=d5qQCw83gd zMw_f=GRasY#~M9E^s*0(eE;Y=YW+;~vf2QX1=Oky zGC9Z^LrmnE=wkxV0VWDe_5+$T#2^EMVu;m-N$wLShM9nM1dWSPCdQZ;r}Y{W6HHuZ zVv>m|CZ?IV!Ng4_ZV^4h#BH!xsDa`LYmAboJHRn&V`O=pEPu*Gkp!+$O3bWHFgcOQ zf5yb;OngCn&>CZn>%{+(iLaQr%f#1A%qDTqvD)M%&3hlw{024UBx#mN^8%YEs|$pc zJ1~nd`!d${wU}kqmR=(13Q1QJ>2}7;l<~x+jHj5K$~0F;HHnw&Jwocf$gsr!+ zB)~RP7gs{!7dQS;^))m_#?0Hw4F9_T2 zs`rwxS6#6k>Ve^|Hg`$y$Br5&HQBqeCi_>^%zXj#i->`aEg!V7LRPxv=gHl( zs+4b3=Sm(rK97jqkcrdZQO%?)obEvn_mwJ@@Yp?}TZM7S^XQNcj^vjp*NqUGPzH{C znHq+^qT00qGJ6hg6vC?u)s(@{iLsV46n~$H9)+Q&2LD@cbrbeaa8Mk%a4*B6^olTO z>hAln`0nMlngn=Twz@#GIKU|2P$l(hsce);JgB|?>>jJgb2YWsiPX-SAd*KBSfvU& zVW8vC^U@Z^!9|v^Uud%RC3m&~XGH_*LSg5qk+_h$8SOnlkC-7B0;kvO0Q};GkJHUY z7#yR@P$IJv$(ZASBoAQ(kZorMu%XF7ZxT4nj!_yn2|G1qWwv&CjG;mfNlIenh{va} z?V@BS-59%CzJr0@mqv&*r3V`=K@Rd&`jaH#05%y5%N;j^S^B257xedh!8Y0QCnf z)8>#lV~m;wGjHV00dvO8!!u&!JDve^+`MB>8#B2)uK1Ya@ZL%29Poxx{^ck4Ki=(L NW7vS#EEt8Je*u$8p9BB^ literal 0 Hc$@2HPJ=k&TC3IJ&-$N-|btRPaL0R{mK zN+K-4CBUTu3}7P){;~ysYn5ord}c!c3QG`GX7H*Ai+~HTfn~N|x%$Ue5!(`A6{4Du zT7+yFhINSQpmd$dL=Dgl7&HM1N1$cEI$#5^N!F5L+X^79Rlqf-gVz9CfY)We0k{r$ z6R-`q0k}zbs?n-=T$5Y30JlJ|!r+=@4nfoc-Gae&iF6zA4&YtUldBHAe#2MSL07mQ z3hzxdH)k3?wAqzN8*^z>Br5vH?fcY`^f&$9r`#mRT{_LY{bF^D+U|TGW`2QmZw}w> zi}967Mnj!@7ru&p9J=N|x)%q>M*?G^v;V!&Hf75;^&EVawhz_}bmD!$fzg-fuebX| zV&w5q`w9cK^WC0bCK0tuY+Cr#)qvrwqB7=#M9~au!rVJ)%abCo} z@0U15A6rk{wPVzSZtqFh>xR8uVW)Fs(-rWTygT;Y?e58%!RCes5BDDL(vm0_adw_c zu8UI&ly4$;(!3b?w!rn#dE3Ei_a)6xUZWMGKm zB-d}LHMtQ{hx5l^FZ_hZn}4yCP0>IH`v<#)r;~ z>|9ff!^tpDzLVJ}R*Z$<)1kpprk`=;+#}lB!IoMNT0uo^(NhUl)sor@R#avFECqLh OcB!lyir%26YU&SyU_S%^ literal 0 Hc$@IIMvWBnitBz0(A5rP5O6Max01kn%mA&|qgsy+g81P-r& z7yyCL5Qt$AC>%tz=!h$Tgkluxqaen3e3i%JP#+_E^{XHzpgztl6CkdEm;^CJrp0v- z?|_)*_q!lUAZ~!T3E~zl6f+=Z(Z*2y8pvyKILWr>P~z05nC&{V-3Bqw3h!``P^eFX zoKE%M191n$`z*&*Q*ih$%Rd0|A&8Gad<|$oyJj zzov73l|YtK#xgUydBzN@T!K{@t1(v1u*8%57yMpk?FX#=S)!d`D~vtNV;R$<3rwH0 z_80klW!hi9CC6X!ny-6W_=YXq$mQ!>&Q~dyubUumruvUr{}#wwDf<+&uQK~u!k%I4 zjBWJ9p5!w4G{G_}&)yQrz{UN~uU^|4#(Y(FP z|J|JbGazTq~~)Gs;9j_81s5!2aNgo*fLBoCVOIyOZ;py*6L|baST^` zavm}^p2NfuJb6k-X%6I2($a&jnK*z zdRj&0<47Nw*z;xiiS`=Gk8lMqG&eGR6UC9Xvb^S5FGZIwpl@YDdmVY;nYqgd%TL!f zmQ{(O9HRITv8S=LV>o#c1=efI9q9?FIVG`YTXvYPaE!ttjWi=TqfpE4!?OFp4&qdX zf}k_SJxshIde?o#zf>&)s15Nk_{ev!I9$aoFwyFg?6*kK9G8=@i>V5 zBi@v*pW8a}nOKE!$37Ew9LFeZs6g(@K>8MgXa1N&?5Ck^VQ3S~&5Ao-*p$zeu?)ZV zf{rvaau+Mr&vZ#m7{oxm!dO4~Q0{AmdExy$pi(#6 zQd4+*64v*VHnVOp(;l@W-p4;>sBFtnJ>RP>t+-WpWwEwYaUU!vMZ`PKB|DL6uSQy9 zkkrxmh%QxDYIvY|8&fkJ8aaR846}GXku&L^SX}ie#EqtS?o}|}MC_fgI4NV4j&_w_ zU|85O15;!_Q@}e(0q(}Nq)2x+cV1OEI2@r4yRpovJ3+4Qz&kNF$ua8A2MRk&G%tgB zY{@P4I+}m^!*er@@N;?E16p{W3YJVp-O@QVJCq8xZ{k2DhomX3e=K*!p8ON;9-kQ9ovcP-gE&VMoh`ialF}IDriW0ak`mByV}kx9GHjRKF6if|+>|Rj zr@gc)IRmv`3e_`(s+&{J%abN@Ohx~)oty}Yi^iNaoLGs9m`1~`1M?W-Bo)!d=}x!+ z)DN?l`7!Grc>ViFx!z&0nW<1mk;TT+(U~MZEhl%pDW~QCN@mB*tt`c-?CKZTP&$G9 zicj<3_$n1Rkl@LR+OXY`Ca1G)doy9k7OG3^gCk?K7|oy#Q7glOn|ch literal 0 Hc$@r>lC5MRk)uz8tBh@lR3-!u)jY-0*EP0|FCbS6zG(1y{MjL@CojI7h>&S3bO zKe^M7opx_!3zvFoOQ*g4?c;XucbEBNCcm-y*LxrOzj=J0;j8|%0T@0O1ORR-Ti{y2 z0opdSGbD_`M}UtOFdJ4}8@NT-IB?r&E#sGgAPdKA4BQD|$d-%owb>Of;Ah6RaKN~H%RA;XW>pCkRn-}rkg%!ydHaL{IWs1|YD zdwx{j??pTo9UkiPF;`kmC3=l=rPm3xZ9*`e!B1_crpNFbdL6E_CKMVuHEmoNSAHxa zEo7+Ha9%x^9bQ#3lCkF1Jx_a87K@fv)z^D3o2v33lPeitsL1nq^;PV(gfG>=A&R^F z)DuOMaMGm0VEQ`ZI*$_*?T~wn$F#J_)8{&84!!nbjcK_uR&}RVuR1$bXG>4ul!wef zw}!{q0A*r3&MrLzvlOT|cAGo+& zH7Ye{tGP{*=AT9RyMnRW@nw zMX0ItD-?tdxXO`jIWZ;^rIS5S-X$l`ge|912GoF-I7_$ZrXxaEhF+kI$wsZ|^wnOE z)Cu2EJKZ<_9lIfXw9ioW1HkJI0NM-Gn`(~U9)74%OHe`^T1}Hy)5BPO!Rx72Q-mSz zsld&aWge8h*gqGSvV8K(8?}t^8-6_kS~nc0l(Jv^wK^nfnEWaVgr@vwT>DpyL@$ak z5Rul${f=c2^hs;Z4mGzW0#1j^vFG;x){QyENTvZl z+`!49IcIb}J;uy2`3;Gn=WrhPCog2!GBNu$hOJ~Xo-7{uY6ukd)qU%v`)K|S?~a7N z6GUIcYPA8Fo`GAi-bhFk3(ZeD2`$V@j7)XnL~}I6!WA7PtUScYKxJATcf)nM&C)^r znqDV(m-!b%mx=PvJrTxIYP@N>ajJ=~tI36>ssqM<;OS{}>Xqo4mio9OSvTNMh}b7M x6z!5#u=94-%Gx=*G=^W4%sXdghyFQxEmO2gR>`LE?%y`=xHV(pYv--J^$&YL^W^{l literal 0 Hc$@23X=g^ZtOGfXC3!C2emgrCIRk%Bjo)AU=c5PRzpHpZ$6Nn303h(PAONVRvITVu zBtX-K<^T(W@D<>z1;U2Kx}EXaS*yj?A=1fVgGGb`5DY_W1nMJT$q^!|kAfV9<`{@U z5C|UzF#=)~#29)9EHMuKJ;qs>05JiJVvH9^^bU zFLUHK(PGuFF#iJc-vV))0arO|VAqj0*Tdgo{36IjXkKH>T@d#``~YGF#E+bTKKds{ zUk7=;hyIz-MMmHM2EFBs8i)rV);aooCi;gN`wfscdR&i~ zYa`2*=HoHvBbUj?63C?<<1ZP;Wsu7~#wX19YxbO}?f2%8OZL6`#<$D9y$gM>zsr+&1Fv=|SvNuK(==J)pli9+ zvygI|lE>1WRJzL&j_muDw>Z!Kzxemorx9PV@L@*q@h(0x$L>gVqUDgiKUlg__r+u~Ml%ez1WTA6vM_HJwPBDO7$}fpJe|O}awH9BJg5 zh8d&u7&kWCu92Kj848wD&j-JidRQJtS%rZgN;AX>4cv~uLG#D z(}=4@dnnWB8n;wq4_8w{Lw;5`3GdvPx?9GYb3{pae~>mWQ@elqtu~gJc3XSEwQ004 z64KY5uI_%}0LvAJIhgii>?1LE4OdLRlkrPGki4YqIF6Y_0e5$)!zk(c9vvHlFE%(2 zWGhC*wMQw!auliTbrmKgocUghGQnI|IpS5tw()2IgIky&eGP>j8r)+a+fWr`P;g_f z;eS?zPY3&YG96^6vihYJ=mj+F%gzPZ6^@mXpfsOdcXW;F&574h;3u`h&h^d(i+-pv zA7-9kB@Gvwv9s!7mSYtJGOp1JiL=$W9UeCmI%(PwpQ5S!uscPc{kU5q8o?9)lv9z& zfvnMt*QgjZI#rE`xi+p4G`+ut7~nMOaaY+=;R)?GnP3hh8M|o{s0dx~r;m-n2)oRq?AfI3_wgdT;x<}*xl#sLY)`C56&)8#Der$LkkDp;{*v5Nk r+8X}uGiJ{XF4=QdzIWp@XXmUuT63h4ZY?AdT8FGD3vYYe8n^xfa*=TA literal 0 Hc$@)nlYADtC*Y9pK?V2(a5w8U;2E zr7?^`tGW-(A22R;tf3CivP zN{rGZVcsFk46uh}Fh!jKvxKmBTlSC09z#q+b%rF5fjt5C6|k>?eM42Yt>?&k7Wiz- z`dhO8j;z1GWDGzKB*b-$wnaFzy7g_P)f7`?a6w zR~mTwYQL^bJAFgH(l^u=>k8y|kepkr`epAf6S{#y=`Ca!k62guavJ&fYlnNAN11}}xjxU-gzqX5 zy8fxWgUW2pSJ|o^%52`stsGmc*^QkwX_1CA*UnajbZlSP*^RZMwc`jY+kCZL_6zIV zn{wg*Ibj?sV!N=nDIe-WT}RbJE}Mpn7MY^uX=n!(*O77%t+XtQ!u;}8c17w&iGQc=ir+pBY_%d+M(x%o_fKC?KVS)$C!BCOe}iK;y9 za+^?9(PnnI74l!}+;RUh)(J_RoG==M;vV-2bX+Euas`@a%K7=+kNe|xN z+B!NA7)MgTTz-{m@X?^`dR)@bcYKG?q@Kl+wP0O=@0 zkB3ElhtW}M%L*se2#%|IK*dz`{G!8j?uH_wb<45yMLp!A9#>HpQq)*9J)1FoZa?5P zrbdwuo6NfK%R0nRWK#%uXzM$WKt+J6T&@M6cM$>fL`C6Y8>90XiJMSX+tspKxCeHq zZ(Xdtt;}`u&bJNnxdgqKp!2jTE<#uFPqk>%>2fqpy+cNEG{pTX={mq}`pC3IdQ@TE zpQC?_c##Et6IVoyXL;y4XW0u8p2@&=cs3eUD1^#NQ4eED(8xxA8tvQnIQqjlmVvVn zM7#H8O|ZJhU+Ik^|G;J1Oc_(=ggIso7^&V~1HWd<)GI#SqekzQ?|?bpoi@jfRO>NP g-P6W2u4zr1)6w(gwr>lC5MRk)^L_+EcsStnNn60OO$ecB9wj8S1BEf^B;)B!M(7SKBl|SEGvF`% zl0UhhJMHdD77D`zJ-oNSz1!X2?rO;WGd{Au`R{uVlD|oOUgD$w&H)I#EeHS_scb>R z0twKvp_OA{06qbHvOw6d(6BR@oz+^b9i%k@Hdu6E4uU+i3(zQlB@1*=V+iCBw1z

PQRKw|>LBs3;LOhID` z#56RfIgWcE@SXuNOJR%qAm%_k05K0@0VG;3f}94i1fq!X6&f?VYnFFC1hEWq23q%- zA+Q^BAm^a`vicV1(Ektr{_truS1o**0=|wT)smhuHW>(m zlM0TrX$J7O*X(5g%p7vK@(DxQB!q3 zTh<&s#Odwu&5LSn=kZg#IZxpl*YrZkc^d3A^SuVeX-Pa>!I?na-nH zg&g@HiKdA$ld`j~x{+q(r5kjmAtx1v&Q#QP4MS&vLWu%tw*3xw!j_Y)-D_@%O4Z>U z*!6Ls3~Mn#{>4qq-xUhJ38b0on`WcTF$Xc3+P#cZKUFGV;hJ1icuulJ&lE{D?!_L$ znuPVrwv%Z3v7v%UI`hxDMrrZhM?SJ>#>q{fybFCSqc?sKJFYm6W5!TGs$DAlfv=4& zQW22HHPtmlc?SL+YZLMoO+MyRwzenS8>SMiCNd_f1 z@|ymoDt$OS&|~TNIGY>S?Lg0=;z0K9uwA7AVM3ISne6F0RfH?3!@xIO)^lmRE5RZX zhS{4L9^j^nJ=ELqunv(50vXlmGr-*3=#EZX@p000Lr%4&uqtu8Uiy)WWnvl0W(s0C zkacSKI#FMztmz z{*b0GeTc7eQ?+GTM!t7ZzEaVJ4qZ={WBMbdOj+YVrkb!c literal 0 Hc$@r>lC5MRk)jKKi|A%@UYebYyfP1+90bUICe7Fu2dw8`j;=g=OtjHFZV&Jcgj zpWM%#c5nT_owl-d+TGvY@Ah@2KWf#dU;gzI*1&|BSUF0)1$l^tHW?LGuy~7U6oGbXz3dog_{}aG>0Ry(zC+zS2 z(_V+}L$<#U_yORDfFA*V%$eNp`Q(50)ZHFgb9V3Ey2(tRPBM+L&lvlB0>dxh#{-wt zD#)tqjfYQ%mPaFtQyMNwme$77I!iPF7n@sdMt-KHdLaXpS2DPj`Z|e)4u0>+K&AmE zCRPLmD6BGpA!8o*WNx(xGL>6_iY(64B*w~2RFl8xIZ50YZhExX8CuS?>dM%fRg#aT zl}ZQuZwjfCjHrT3X{=cyC}U{5*?QL8X>D)4$x=%L3<=s2eOk|3c8b2aAivt!y=`fG zvt{SVg3`n~DQu#0(;z*}avOGqHX)II-EQuLC#Smy`ymJNZ*cGMWoXtJl9-6ls6uHg z!#!a|_|waaMqaNwOtZxSxEt6!m$+@AEZE2&SfzfVerYx)o_pvcAm@*Ggx?a!2SiZp5$z zuXJLG#aXW0;pR;0ACgoKx<|n;a*XPlYz`YlSmFXTx$gU}eOC!(uG~xs9e0vj6}&z^ z;*K53{(nH5k4IzHZlj9ZZ5|qBnA!Brxho*2Vv01eoCNhNzC#w1+)&VV+2L_VP_g=3 zF^#rXX)5)(8)PoEn=S6X3x7O=_nxO$-N7N!_6nBVGz{iaAf8KszvOiM0_l3F?5h0Q z?VBI?oYIvLZg@ExRS?t~6VM%snP7SlKQ(k%&v=5WIpR7K+QmqzxtQ-MD=3*OkppT-*V#)XeoOQf5Th#m;FV*?3MjlZ^L~_ hTJXvfzgd6Df8sa%2H_2F)!U%&v{&=!^{Zah`x~A`qj3NL literal 0 Hc$@53cNJ5GEmEaAu|-HHU@GGn&Tiw zK%jXVL1AhuU=z(@>iRF$1+3 z5I3N91H?_J-Q;X$LEv`|#4So*%!5Sx+aS??0VLWlf<*f}Ansz8nc5tC-D0mSh$WD7 z(41$Uz^tL;ZD=m=*_J`v1Ce7r23dsW9oF9m@c`sa5D!5-icTK;e3kII3-WH?XM}vj z*X;963BT0=Y>o4n9O{?9V!r}o)=;c?gu-}WJ`@LjrXDIe6!T>|g-#Mo7Vt#XTHCHU=w{W$U-z+i*!q&F#29h~AutU35m9~%}A2hIaLyr?v+79(g zTTA9vwgt;E^4@L52+QPrW_u?t*W-FWG_n#Ztc=6PZae7cH$u}d-U~krv0R6h13s@# zqs|XFu~8Cr15=u$lnCFi*OkR2`mlD|T?;`C3yx zMeYW-t(kx`6kP2|m5D5KXvzjkM!a(3u6+*3dIsj{ag z)cR23C?uI5sGmfATJEFz(JdOgc`Ps7Fm z=;j@~R6^fF)~j@bF*g^w{o`g7PU=p;M{WAZa5QVDZsBNY$0gSKeRDR8o;o(c;UC}v}wUDbyolmW30x4UPnJipriH3N8D86fuzBVrUDymJ` zX|M1PMEp{3@l|N}Em@GE>zowM{P08twj&EsZ9?DI1%+c4Yl3be`i;1_rjKZDR6gi( zj!#>@=y>uc8Y}e|z81`^F>lVAGv>IFO=nZ|NgHVspH$kMHq!BDJhf~r7+Dja!Ow+m U7|PoDNJ@5O`Y<0=SuMfop*T zXxq@vv2YE(0DQ4P*s$Q*1DHLiwOE^{F#$GMWH1L|0Xie#j^OwjxYt4C!5sxTLPp&& zkYmsu2T=eq0s_%d5U9M4XwDMjfR@DsxDy~I!JPzg1Kb-Rrof%zl{Z1)eG9}iITbS? zZiBc3Viv?4hTip&+E8qpvA099cZ}@}#fI>e zaq@nElO>Q#{Wa4Z|0LGwe|8Me#V9%K7oVF!#I4#n24urL0AcRN%b_dt$P zPg>%rr&;c6XmFp(g{5L9JzxnNzrIq(Qz7^lfBOL)6e||K%m}^?Ros@o(K9I5HtWUh z^F*qkBO_D%AhprssotQxdfo|*O@@TY;a}xx#o##uk=K!?Kn8JAxngLEklI&4VuCo* z4{+?X;*NCMvG%px3X?It+Z%RZ=_qaa2#F-wi$GY;D)x z961=0(^Ov43VglxzgKqHtsxRN`2ECOr=T$^bCF0hiG#o5(0EOGBt0P&?=$gC%Z$?T zYCL6X9&UFGN7ZuWiBrbA%7n^DT!kKAuKR%GYVuaCJS&&+?yt&#@ zY3N-9w~1&9=gbRF0?s2XYD#k)#{LOAN+q-xoD)7x!K)xL``ym5R0oYs#>X#riB;fp z96^+H&3j>{P~M7_LYI_7#>r{uH8lrw>V;jYNh+5rr7FkTh*ifkJv$~0v@yg&qZ@{s z-9|&EjHg9&9HVEho;RmWuByjXt}0wQTL)@ z_u4y^?5+_sxm3tnegCKvM4F;`R4HdF?>yadnOB}>Q`Y;6-UJ*IgFCgi>mOBsWN>M6 zdi9}HZ-Y?syp6J(XKfMItha`F<9aLnP3s=LMjZMS=w)TShN?bK30K>!%(Ut z=(h-+LL7VpiQ;35=)0VGaNJIvNYhO?ca%8HA9qnIhcYeLbIM67U>Q*FctX(W@MnYp zQopF)U@MLqWO*W;bASgbHxWCC6ND<2z5%LjHjqzuh^=>%yERq!OqGWzD}4u9rwp4_ zz4Tfw56G1PxmVp(V4v`aAL;FdWabM8M&d;JPH=A`gAoq;DoUE_Ml1Yf$zJ+(b}r)= z#XoV*Vs)Yu&zDY`G!@6j(Q#L0n&iSsKO1;(*Y_%`$puID96P%k%9qrMTH$NnUb1HG z8T+PPunP95y_7Gogin6TDqOinbJO|d^<`^`E_>OU=KuM0Jb0mQwlC-M)})1xJ!Xwr F{{hw5nc4sV literal 0 Hc$@~e;DZCwg=OCzz}!Kp!_qwQ1i0Xk!yH5fXpMqDiu?%pV<7Y37eS4ZQ@;eN z1kG`f1(2g45iNp5;TWPhM~(w}mJ{GlfSd$>666&4Qy{0op9VPt{tU=j@Mqb}Cm`{e z136Ct$OVv#An$-&0=WzdtyVyx)m@5Eu7bP=at-8tT&d{Kv4?r~PzL!as5xjZaNgkh zi=Y;vd57cs4CLn^zhLr*pCC4dlmHkwn;rEz(hAMQRTO7N*1ws*k)1J~b}Aisk>ItsA?y*oK}W z(^O*}M`5gNo@*S5PB>46r$w(sbP;l2r>L(YrM9TlV21;C6UIr~{vz!J((f=`1kS<; zLuS7TCqsU5+y-bB9x7uVy>XK$tSxOx6Ep<&t+N^E*rqzd za@3*MaoS{DJ1P_JLaN=3=9|-IwurLrgsVlR!isToGdfZ=_GKygj1brL2T0T(5=Wa^ zNJ+!}YmA{zBcFDe7dk$pHM%-9XsnaZ(!o)q-X~pgSG&gZhw5+epb>OHaAZ0mtl9(n z<2wLuWpk2-R=sa!-KR*1=Dd-y3Ki)%<2`_th>_`usQ76+Ugra_|1tahvjPvk;KIAo z>4ix|puDX3sn*srx}EkVNyp1hH#|&Ej;htoq{E>-!MSfo>M4z>`3*ly?y9rs&bc#g s!6~>!cQs#d@y;PfcYfL_{O2y_*4!m$)mhEHx9^3#GwI;#mYkCFFT*GMXaE2J literal 0 Hc$@^Kj{y3goA`dfSO1j*5cpUS0eA!3 z0?z^o(6XVGV`Buq0(`YV*l^3UhcJ8CYq2*^eFAK-h%g6H0otSBjbeWUyelB`;1xlR z5~()^atvDIAPOKxK_FTLfzB(4<}5J|$Sfwnn*cEh-Xw^t;9UhV1>O{hY4D~&Tm$bK zv&?|NXBNbD3P9WdF$dx%xAP!z)-8}YYk?vZw?ULZ+ySu&;x4yk5chD^ac>snEVQn3 zH22YCc{iAUj`<&e_>KqMk)I!4{R$JoTFJ7ism-R+gWBWII|MS zQpWX?xn42X>y&GN{lwUt;dKVsTgKiE$2VBzJ%|q=)_Ce9Je$ zHW}L*j`6}g_tJSk6DB7vo%fOFZC@J8C&qrc6#JF2ogpQNUHG_78?XqnNN33sdwtK{ z%tM_rZ3tWU2G)JH@W9rV_VF}_|KevaqyxTWVPi(IIY?AX21d`Ky}4d1Z=H2y61HV* z%Ach+dOY`rWsq4#L266RDj&71ug4=th3xY;0|=9Xho&Csw8{ zMd-&)Bk?=UFwk%RKSi4Z(N~b6T6tZeC+$3az4{6t&b#XJ&(o?Qh;lH!jx>|l`CUcE zZ^%RG3z=|LI=*R|B3+`!Pt2x|#TjFE_qkKSr^@A*u^{Mt;AgCThOkYARdE!?(&V|Y zk>3liQ?+T8Q$IQmc{3@bhBQZ!3XYjBwU8n_BYcKpO2XLeb=yZW*{`oNK7JlNN+IB- z!?@EmpM<%JcA%03^|39(M$>2x;lz)+Qd3+{+?Ov_RyoAFO4`0*ydEjErqJ4;$&pVg zVDci@B~0{Ah|;=7LaZ#i50|m6V(VhdSw((BYobDQx!RA(L^#P%4eQ+~TJP5DSZPW< zRpF7sELe_fCk@^w_c_ZHXL2S7enLW(iRM@q&^08AREe9|1{5wcwUv;}R9j;vZ4yqQ zws&ZnD5@qezsm9XQM5^dAWy~25qa$br+W}7lkR7Sg+m!C)9j~F(N>r@$c9u_RyF0mMF;dKM473wjLLoz zG{X~B{<6EHDf%7Ry98Q#KvE)FrPGr1^dW5t=b}4Nm?nrq3{C}`xGW}U=zh^b(?@Of zRst+=qM}G9hma|mZVXPm9!8R{lu4FfHgf-{l`bMpx5G7{0$?5bsv zZoI_*1%pO^7+j$E9}pZnrz$zt9Y2sxx^;pvOgak~Hj literal 0 Hc$@~XI zTz?VNA~f%Ce4l~*9OM@)UjnrR&1IH<3GyqD4?wPie8|z?*nB-;gF&qHYzl1i4cmO1 z+4Qju#x@82^)ZjJ3S-qG1P90?Y4)mx5L<@q1boqbB3|Ux3FEtW`|;X?DPAf z*b~N{4q);b{QQ#Ia2HgOCd-k}yOPzOgqVBO7N*wv)P1IKd{5SCw!^>i_d29;Uw80j zNAY!>>ZS^;p$%~G<4O7OI#FrZQn4++RmPg}Om30hylzF-B}dZc@KfEb+7bN5qNQws z9HLUCYRN<@6Qp5cLmiu^$a@XlQeIP=K*U;j$6;XGsWRSc9iJpBXh$OTUK}3m*S(W{ zFV?oDWGG?}9V?xhXaC>Bc`A}d7?|z<nZBBNU2pSHQ4ol-Gp({w!cU_f%H2} z7lE@d!jRc-!pV?dZ5t>oa+8Bb9RAkM`P;;VeAo;*#+9Ru~&1Hmci|u0&jC z!IfkZv%st^?Mf3g1h%QO8R*!iI>K_) zq1RyAXIwif6K_PS-Hqm((`L4avh9ScMWw=uaW6AEQZ@EvDfx^L*YyWT)E^Q@`&mdy zv;1p}p-v;8c9|DCKBG0dIy6_Tlh4w@$)esTU2#{t#^Z+SZ}6-UbVhJwIw7pu1N+lD z0B&V-l7?2jZ)M%5NQmaVk+BLD=|tm^$4bP=^h8wrv>mVW8Q6cB{r=&AXJ2sPUFr0~ zBqC5=R{T_J>lxin`;w&NWd|Id9w$e&>Sog6(4MrkY)9%Djj6%E53uB}I*aa{JL49d pf?IS~^92{L9CCE!r=7yTu3~P@U2<0G`S@DMJChDRZpkS*{{TN5`%nM? literal 0 Hc$@r>lC5MK#wuz98s0)!AZNn82=$qvxMbUK}ur0Gl`8AzuYed!$9Gsws~jqVKi zbN=Lh?zFor+aU}eYU{DLzkS^Pc28q}&(t@!|M@e9!Eb@?pXs)39{}m{AO(motUy!)J;6bv zI_NrdrU0ve6M%%)07*GX=$MC7K#_48qG@@~0M0-(3pfkW9N-*8^MLaZ-IFMv0p0_o z=K^m47Xj}BE&)COTn0^EE1=11m3N2_0oMQ@0j^V~TC^Y$7A3-Czy|0A=-ijO!H2yJRE9xvBp%1^k^il zi$o)JvawI|mi$YcUb(VhNLEdC&chZi(a@MIVxtA+yxDGD9w9 zaR%egsUnsxRoc^1eM^kmrsygsT}v`2gj|u3xK!KeGJeAj5{Q*`B{f!EmT}5fpBj_O z=Gw`bu*Shpj*h!YX4!4C8A|?kYA79h#6u|D+7ZQNS6!Fm6NUo?S&Wy?p}d%H?}OHZ;!cGvLTzNNy*olcJUR8NO_4b z$D?oKb47&rw_=mI!lbD#j$zm;9%kXJoupc(eTFL=S-v^#lu5Mf>BK) z`X?St%Y9n**SsZv!Jqf5Ue&MpYZZEvBu}qene(cj{A-izt5aa E4;8bx(*OVf literal 0 Hc$@;-@a>?#Gje;%KBgD9&~@R_`bzg|6v0Nd@Kk6oIY)VV}S%{ z*w9EYF$A9gK3O1an0M>}ojoYESehiB6gF4{n1EmynkjHn$Pa-t0wM{{D999nI%$w; zXpDgv29W}R+EEZF96@cu5@UeKVjP@t5E*bXASS?>05J*9BzsPQz-JmnmNpeR5Hld2 z@R|oP3t|q$JctE~N<0No0PzgOa}Zy!WD&#*+-c02200ClEJyGqN-QVG_%n?E62w<* z@PsP?wvz{$@7aIdv(G_emL=bS_!h(xi0?pr&zU?}|L~dhGFz{(^=ikuuPd^yG^pz% zl|fWMtZ_WKfq2&cE$?Gh8Eb>FUOmG4@qc`>9dQuuDMp|t0Q$}R40pKW)RlkM}%y^C7$@bv5waiog%Wx2YxQm$6@OY*F% zrhIU$`JQRTQWuX@cp6Es6}Yi}@wuIFja%HWT^=$dp>yb!bwjC_%m@XEHl`g(lR@S; z6&UwMo=8{7nDdHUQ#Ye@*o_;TT^G|!6GW-JQ7qxJ#s!q2Ak~B68CFjde5tg>PtUBc zsH|;OH}T=3sW9+EX_8#Dz-{|8R7u+Z&JAvTZWKA)NOKh^@0K@WO8dV{AEr>BrD$V6 zG)JxGm5h(C-?8P`Lt5BokK^#esAWC~GeP0X09(IPcf(Kyn$5iqbKq;kA$@d%mek}} zUal;!Ew6LT*D7whri*6+GS2kz_N9MQH<}Hbeuykrext;I*MUM$*17kj<4LM?inJ>| zMb+oJMBEzkQKsG%?x^~Q&~OVwUMuX6K@9frJoXJbWcr1w$@sk=NHfKCQrAe6tW%`~ z_q3!J@ViG-d*x%Z)S?U)-Po)9AJyW;;epPh`arh-L$&mbdPF%Y&1kxWMcPE(iLyZ9%I&>OKj!kK=dMY%r3IZ9QKyL)-7;*P0WIkt<)Pv>mRim?sG_A;_ zyF>flzriEIe#DY5qupc4y98E@+U*KK1OID?Ax~V%8xt zJrNZ;ZiP#Ho%I*J-@gj*8uM<8cPhTsk?YA~r_ixdrl?gb?n|O}v2$19opO43S&R9w zlvkrRNBFv_L@SVQXxcRXqlY=WVCC(cJ!KDD!}h3MNa7bMe3O&b@Z&$U$R?lLS*yTr Z!Jf0{@H=Pat%6lZB(02vubsBi)<07C>f`_b literal 0 Hc$@=PP@CZji*VlblTfz_qn~@y&H0Wmx?Rv{~QO<`@4tlYkW;H2O#lrAOi3QvID*Y z3ZUgeE62hJd;<97fOO%$?+#(^u-0L1p5_F&;1FRBq5`x>!5_u>2>7=^=D{BWHAjX=ye|ydM!|d@&U*)$cG>wfqcxGMUYQ$)p36s)HJkaIGS%z zr{vkxZFS?=2m{+mmGR!|_%KmHClaZ7^0}Q9 zR(N}j(|xA&@MCVFRi*NRAD-0KUeurCV<{UI-db(l5<=d#n_^feiRV)d*F+9S&_7RpTX*!O=SlK)$EfU>uhB8U3 zT#4v19?CAj#XsXJjf>RLSs3kk0R)&mixaIetJ?i zuv5H^wp`pQH!Mb*>9<5ja=EK(ywJ98zD0~IV;*b6g+ES1i;I`~c{dG}z6m3h9fDfL zPICJ7IqC?@lAq&-sF(%(?$Tj63$g5aQALX)4VvLcy?C- zo9UVZYBS!0Nun@IBQ{2GC0Pt(gMnH)%LXfnweGG4I<~2fB9$IMzq9Cca#K;re0)os z*}mn6vsSiZf7c#-1fgoRPe47)1o>>&*u}lf2SZeqK37Aev@=WyMSMj?Ji!ZW zw6{9Rylb3Tg^qL!^0B}?#5n1zDD`P4UgCRmFqpl;orCvfaOqv?^wK0EP+pe$RBP)Q z-AM \ No newline at end of file diff --git a/schainpy/scripts/WindProfiler_DBS01.pyc b/schainpy/scripts/WindProfiler_DBS01.pyc new file mode 100644 index 0000000000000000000000000000000000000000..20b5d0319229d2d734b06751a3690340543c356f GIT binary patch literal 3908 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 Q5;8w-O5F3o=4Cc>n+a literal 0 Hc$@Hq0H?3U%yqM^%=wG1wQ6UFM!0`0Uw}} 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
P4DLO%JX-Uk|R$@IE|pi$yx}<|;L=!(&`TjcOU> k&2;rquLq?>M!R^%v`ngjt|_ez*1h}C`$mYhwQKF#Ka{U4DgXcg literal 0 Hc$@rGKRV zsh|6_Gb2lJK;e1%skQ9Y?7TCxbL}o<{~YMOvGCUi8(NV=FEa9fGC0}ftZUDlSt2lSOBre zR&e?0Smz??kWZ*{Gtx=0X~rfPyLAA&#MopzmiWEIexGae8$-PmYu;urm)kWj#a@2* z4KMGo&iAQ0cR3I3()U>UetRAg>;YpB+p)ybqi?L9W1X?oJUnJ>g|R0Gu&11(kyO2B zjE$yZtBjpU#hx>k?#m1IsmG+1e>{rIDRBV$mI~5a$vzTC#v7uC~$~L!Bu^MAvbxDFbjMdxqFya|H zN}0NnP*<74J9vF&8!v0;Z~VM==>DEDaL{;n!&;!~($?V+(hpv(u9wfQ?D;Zq8q$lH zR>KK{N+2yEgW0`?t21Ou=q$cUw@bPM-=5Wwx*G{8>lHsxw(i4;kf9wozIK$yQqSJJ zTG5@c$#4*=Nm9GLV3y%>jtgJk5gLWHMsAW*t3aqMQtB^e^ z-r`qjiC^ybq-(3a~)4Q+!o~Ud*y0tORiBZ zX-UWPn|f8~L8AsRZ=v>fNEXRF#O zDo|8j)Ub<1hPI@BtsD%5mTfrRGwDP)CX!j!Ud)?irt_>TT=;En2UDY zo?qc=b03y;KiO<TU;Hu+Fc4#m5 zcrWo7C3u;2>O-|IgPm6WLMFojPUI|o=jgY{D>f13bAncEZQ;ljD-3s4Ah?c=P|p=h z#hqG}y>XRoxmD#-htQINY$z>Tj4X$*Lvm`?_qN!FR)W}YptQ0vpIno$Hgk0?orJ)FcWs&UZtW~eq_hVU)KHwpHNyDKtiR9czSB^m>B_sjP5!`P-007Y8^gv(W+;=xrzexo<~wp7IRj@# z+Y`;QgV{kNm-6&aH~r~25{;kiaOMDKq1Wg&{sC4z BRA2xA literal 0 Hc$@lkA!EKj+MOoYDMmVi2yPMA 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 literal 0 Hc$@_V`ulB8Ej(p`$ z?&rRCX4Y&>OTD|YG{2eO92zP2=WyZK>R*4p=)m%jO=`JWv2l zADTIy^uR5^tq0PF*_sc^W2_gHPg0NUauD{xsqBGT9%L`n`aunlRjmN30L?*=eIOC) z2RQ%|g?U7CUdPQ4yBP*K2(xksZhb&Ea+t=4G)7osgqcS{;yVU%oWhY4ASXdi@i+}~ z2IM1RlKwOhAqGC zw#=|+4`OK~OStwZhD;LNNwTOaY+q&j<U!`$ z5-sKWh)h{msk%X&N@eSbj-56U>+BxxZ`&E1Y^h5XnwT5}Odd$#gnfcg&{9&1K**Mk zv~`JaCJBDqJ9u?+dU%j3+Y!_|(skEPlubphpWGpbyNMP1=0uJ;WcD2k*Kh-LKRA)N zErDScaJ5{it_Iaguv~R{T&hSC^ilB?t6+(|QrY15PAvnLS2ot3HiEDyT%Yb!_&;gkh)e z=nQZ|R5?B*`E(ex}d4o2h(4N^0`oBaCU3 zcO_kHn&^z^Iy$tktkavujV(7phoU3q`cio-ZYVW4#0x<1!Oe3sB3HHQrn+o89`0Ek ziG(u5)aU=J+1csTfVVi&PQAtJB;N^~=3Eh6IE5x?VBJVsqX-vwBHEOs9WC+=mJN1? z?vI9PsQ_=U`bBVMk_#J)x(aN)A#{`&;{t2iNhXPJg7k{&+#~NO=B4rWFw5TCo!mKF--A(V$&zcnU$En))17>y7i0U>~q^ou!e7rNzod)eJm`k6o3 z&qima*BTSfS7?bF$<4AP?{%n71qsh%y|%VAdpt65U~Ja5yTSHWf0FmtbkYrQ3J7t zxr*&7do8fnI*1LBRp>5qYv8w+KrTUdnJe4`@f^epmSdck@b!>fS3pjW8m?!O)v<&Q zH44St+JswY4pF^myh6y;AH2RPnnDA?2S?4a?#Pfrdk&3#`-eU2V* zXgi0pGZneMk(tO%lYi(!H%ui50)SdmNDT^Tu7`Oo3>x;siC zT|Z^-uErKeVBIUDNBoVtG0Q|ew}1yH(GYvGZf?|6f`_q)P&ECd!RtRE z_7F+X(LEX9>PL6MK$|<8hLH?x)CpB$w042jeKV1y!(g=E+0KstkaWlue&}h@kL5?& n9=nC4=5Kmczw8(AF8P~$&wGW*UGiV}H9zlFJbeAKSN8q_;IuH~ literal 0 Hc$@ \ No newline at end of file diff --git a/schainpy/scripts/amisr_reader_exp.pyc b/schainpy/scripts/amisr_reader_exp.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dadeffe027a3c89ef451c44b85e04bc7d4d6c010 GIT binary patch literal 1692 zc$|GzS#R4$5FS#NWXX}G_^O?{shadq)5MhA6mWu~=#iie;2f~sHqcA3;jSaf6qnr{ z#ny9va-WNKW=JXS6>+(oo%7pocc9Aet>&G(fBYIl`D@erExo=S0%#fmqyWQ(9KbLD z127I@ToGXj-T=G_K!>n148a6qtAYtx8*p3&(i)uTB^cI0S7EperomCeCYUCSS3uW5 zlW7@r12ie?WUT~x1vnvjTmem^1$vd!>Ne;O=&LfXfnEo_0eTbk7U=gVvOa7{)T%^n zgWdttf^l1bLOASz>A?7^)Vl`yebBq2UjwrS<8{#!pbtP_2mK-FuAq5q`$%jpvEBHG z?WWj1zHHl=*ZSmtYJDm(pGi!wh*{wK{GIr2y#wDDmoVtt@Z(QR$tIZP;#lsKnytBp z7tCHEZ7-x9k?8D?dwX;-l0WJ9B;mW#3ur=~Zuw1`zkB@X_^A8vA~!CXm<+oo#-neL zMNJa#_AVwVhMYoUg+7CO16-nSrX~h!oQmB016(0d8y~wQ$HZp-Cat59otQ}JNs=WV zokHuP2R5E^86Qb{T;@213TL^&>Ku=h$Q6!|fp}C7A1JESq}6_Za5w57M1upY)6!&` zO>Z4fXd9l>_WSo`%-t4-{V(r-b&rNrIaldfBAl?>FE&N>%7~m~`4k^%L3JG4yx6bJ z7f>yZj1%d#N~fmahqz$3Q|l%QMU`YI+dL;B!L;xrKBT-P6Mla~ZsTXpo+ha|HmQk; zFYGW8h3-gYugoDa={c}}`(RMQ#FUhHg`@4cab=1U&c0t?oU)j^rQKg6{X;&nmkF_B zyC&@_7mt$Hw)_0?q2D6&p_%=MsmGB5+WKNMGk?T86fS(8CMX;bkMX${QRO)$LO#FP zX6S61nt}knG(rz!l3P_TXc!X#*!o+*)0g9-gu!VpS59etWR(6nqmoRYD;Gc5?3BGr zA4(UCPqlzWr&rH0w#XE+&7t=qT#c_$)fN?#$;ZHj$4&rvzLfZWMS)qKfP{0?jelVQ0V@2Q~`MS>O}0 zmoo``5)RG*8v};aSzr^u5FAH#L}BLu1=$pp)8I@2I}gq@uo-a91G@mu46v`jxd7}U zI9~yq1?M8LOW@1`y9~}HU{}Do4D4%gt^k_@=WAeB!I=Yg4V-JKC-+_a>w0%%=7J)Cq!S}Qa8ZaH0LHIr3_u$|M!cAZn zFdNu1uo~@AU$IV#iz&ql@Jd&4Wr*SfQe4ecd`OCwl;VBh_q#pUWKVuO-LuE76L)KX zi)Zo(>&j|~8w2b8(vv0NOT|3- zDaVtglwuWl_2iyZQ;Jwsb39RVJW)^06SbHpKj(Pzs-PztaIKgpuX8-nQi?io{p6nL zDMbUgk>iPxq?S^w1Fz?JQqS?Eerlf7i+Qq>NGYxYU(NAkHOG_HQ}blCm?yvIc=E2GCl7%?Eau4{ zIi5UBDXsxuJGm!oDaCc*>p7mR=XkPyYM!hY^Tf&V>u#sOS$Mrz|Y2C75_vBE+ZJb@JJ9$IKP>+iG&@p7wvKKM zQQh(z2nU!TTjt#3;F>4mZ%cfqb*>#F_L#-Ir zGR0=iuGpGEv8L)3U9VH}7`iws6T}s+IBIh-+D$ylrM4^fh0M4}xS@FFVoFU)VO2A$ zYOSi(gw*3clT^Rq4(4klWmR>BUfpIrLN`{dI=*O>L$~?SqvV&(Jipx$8%*Grc#uoq z=1tzfRHB>?+Pzr@VxNc9U)n~{Uv9I*=>)0NdN&ALuAtN5`GV9jX@$ENACRZP{szLb zy&oSTJzmgu8%MauHUdT)hqIe&UqAh6z?Qhg>dh!0E6OBVgq1$ew5SiBqd=UoCW|AoK8l

6Vx%i(x?-g(c6@Ei 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 literal 0 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 Tz9lQiA9vCzI{3N;r{Mexe2dw% literal 0 Hc$@FS9mi1F4wV+L@s!r$u>L&YYP&b6Yn4TJOF7^V`b=7S|TNKhf*{@BkD&9%KN~QuZM7 zKm$yDm^MUMfjfXZ!u=X=g7!iAaOVr?3D^SFV4OgYxmF-+L*9X?LwXaUE~pknJWSdAs}Iu$f>Vl5L5)B? z1NC{8-_rJl*oI>JQf%rgc=aoX+yUL=#(C=N1+rTstUTltMA};|_vGn*FpW|m)Rdv^UIGs%q<_pYR7*_itxoM}Dn zY!usMl729w%h#uFm&~Vn{y(Mz?yW>Ku40?J^KLzRmD=S1f7h7YD(S)0Q2dtU<0xw! z@V;acQ?2vEgr;gumT7w~XJ}ey3DR^I`h?}I_ zh4Qm0uGxF7@;NKDjpZPh>Z!%iVhJG!I+VKqk~g!@me_R8GGL8y8$$Vzv-=e^!h!I?|%UM)mVD~ literal 0 Hc$@ \ No newline at end of file diff --git a/schainpy/scripts/eej_plots.xml b/schainpy/scripts/eej_plots.xml new file mode 100644 index 0000000..599f185 --- /dev/null +++ b/schainpy/scripts/eej_plots.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/schainpy/scripts/hf_plot_pdata.pyc b/schainpy/scripts/hf_plot_pdata.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e6e94df3b736c5d75930b4295428b8b2dcf6d222 GIT binary patch literal 3479 zc$~#mZFAE`5MJ4igPjBdAz(uYDWz>n8!R~q6iQnt1PDzaO=!#bi|5dtv5YKfbY~Lx zEB~W^q(7^lJMHdDeu-<`4%2BZOWM0qiQptW}r0-G7oYZB%%e7MNlUY&02B>Frb`;+8oF^sGVf*Qy@=*#OFLsAy0!m z19Ac6S&)k$&w)G-vIMeBgyaQ~7eOw8yo3=8wRw(knj4-0mv)dzX)m(TIaYQiGB$3D#(vOe#|Tf*e8swGWO{Rc8#&m82fw#TVw3{SggXB zJ$62aFf}(kU!Q+8@*l{<9uu=YBFm`J!mS}Q&f+k=7tD4-IsL5CF zsmXXA@2kmhZeRa>ZvAThhO2pDsG84%I^WCuF7{Zp(ooO6AuY%$4CT8uf{n?kJRzq(_He?uM~pol%X6EtCu6bi{<<#Z<7<`~izREeGmQO1Eq5nq z`E-Jo_J6G9v;R>`xd)FPQ!!rvRY*P?-={qndp*=xqT*)jQr}u;3%^YVtNZv7^Zvl! zQ;)uDs}?>CJ+7G|J|91!Gh_*6$ zihxeGV`zv}+Ks))cwwL~VY|`{+o~dbbyRr}9tM6Wq^?9#7*TIF^zw0!JZ@-`=Eb~3t=GIQ8Ch?Hw$v9E+wF%yo2X_^9k$Bl^11A)9L z>#FT+R&1x@RLwLtRUk*8&5E-=828+3D^0W6_HF+6M)iT}`t8kI_-Ap#!1n@WrdS+b zbUlj8bPk38+T#_N8PMH}Lze@3LDVtZ@)(AKBrzk-l46FYiP@3$M))1YfgKx3kzXT> z+rsdod4XYx4$<(8ugrY1-cLMNv_TW7H3=g9?YNKx}NE-kcZ9G-KGcv?=9MSFFh>8a7FnmsBF`F6Ry12-O=X|-cj8#(CTHH zi8zEhS^ci=Z6#%}p!bOwufC3aFDbuQ%D9J;O%X*Hm9=!kz{H{Nr<;vV0**vW%0~rh zgUYwCmU)8?20VM&N~Tbz6YXE28H?$DedxWy{mwcIDQPqR5Fm|H*pAc2{V-@ygw%%? zmwl!Zs(;w(EVAYVnOE>^9v)w`e45x#)YU3MpW$~+etQB>>2d}PtNI- zD%qSiHjF|?)FCN56e7SzuZxx;?gXoRLiZnfyMGd@*mGZ34#W7hj)bc!8Y|EX;xIH7 z9d_b=Pt>g>r!gIue4N(#WW64Bnc|&xC_BFTn)aLi1s|o%Y-Y)t&lEFxE1xN3mZtLs zw6dqH{NO^YkXz1_tR-s+z4@9gCGTFFuKCiyrv9_b)|ui^-|&@tNB_ksYtF(uQ?!b? FKLLpC%}f9Q literal 0 Hc$@#7 z$k+a%{krGupXqPdk3BuMHT(-cqdU6Te5-5O989GBORNx1IAJCu#H{CKQi?Lx)Wzt&YSB78& z4&)HHmq1p)9R)cIZWZJRxNm^G1nwBfQEzVz^_w8Cg2ekZN-eL0ya93w1o>N# zA2G`_>jjXDAnP2Z=wq{w!#<7FC(pmc`KJo`Z-cts^IT@nm7-^ktq#EMGWIcJcXKRd zd9T2-2C8 zJbrCWigVll_jAj4)dBCS+l5_q2h^S3%)jAXJyXy;Db!*X)a?0MoSW0^`C5Ei%%5XV z3-kTs1+34UW(UkE$J_yae`4&2A%v_Z{02WmWhxvEU_R!>8Nx2d^V`b{pq!xFy1_va7sRqwyT&tsq7 z{__^z4BbA|qj+yN7VkE;H(oZ=(bD4TGLOb^)UchE1$$}1X*3_}3Mv*mu{tzWls49z zYfm3+?{2N>H*nZ)HI33{@uVA=5+#(Tj1T9YV}|eIu+DrV{_)(}A zaa`{z>5KY<-JPwiojS%(#IY1cpm@;i`YQ3FKv zh__6v-+2wzZZ(?DYCRCzG%2*XL_A11jTH|z*7uZg0{^{U$|b!X|!?ZEFUO`&c3KL2`NInY?Tzj6FpRf?2qjWJjM|%FDn>EakMPK}v3SHX zAuqT)~6U0ec zj^&JrW2XdGYz~N(R|&3|+7>YfSYp3t5w1P<0qlx|wwp?HUg$^4Y~yyILSL{zy81d% z7r6O?xhE=!Jl~wo5nwZ2uPwq*1+)ZNOPPRVqO|{bk2?ULR5)ho*tsg32=X4yjN7;k z+x~R#2x`1Gx042I*!mVe*XXEt=Hsr3=2S3;rEL2zqPeHrTbllx*;1!{ApdWFfAwnq zUCKo)BAu@EsqSriMVn}ksB!P=IPlYkK2*j#mMn@m#?V|uFA7Z(1pzjACEGYoE;V=! zI4JM$6Vvp&hp7?|I!;L|&L<&R;M#PsUCsEp$UDzEDHmmq;=MXit7a$Bx_^j=7%z#C zl8&iwLgYJv<0KnAjKUU0$ZTl&*`|`t3C{uA0CA?ytkb4K^PN~Ff{tV67sZGw*KL&=3oib}m*b#6eF*3z{5-^FT*K ze$x;0^Is*t_q=`_CC_y%JXP1&&3>3fk*VwGD9JVPX+3=#(MuwImBpt_?$d50j{@}> zwX6OI-lj`qrJ6Nas+NbX;SydW^c*eKMu#gXl_#v>voGP+XnCe`)vA@It=gp-t47~4 u$|KVxm1?P`I-NdyWBN``pUI@ZHe+3_7Iek$&};N}D%QA#SE*`MhkgOn7-1&> literal 0 Hc$@=RgGD zk7x&cXGrJ3&w&K!=Ak>mL;>CbyhDQ=toV754(o~_^CWf1FAvcq9Eb_@RSf^Bm_3 z5MP2^fbJrf2RVNUKHar_mKE6}~bl64T*KwJm$HHaIG^3-|*L=}X~QO130 z?BlUdJ@Xmm-{kyDWBD(Fyg2mSV$bby&yjBDe{?rl_YLcAj&vEyTVp6IAS)lDyggpo z$miQn_$;u`9g;hz((hP$cMO^M9)8@VqA!7*$=2oGK(acN5ObNDz|`7^y22Fhy;*;<`?i&Fo7J5y=BAOW*SzhG+UAB=Z#^{y6jZy3 zJhWw`b{nlnFYiBT?maSRknOZvRvKG<(~E455(=Bgn|I5z6L^neE41`P>brRT)rLGtor1oKe z;7eIoHr<-%dUg^y84K2w2mNwu+pf2H>UN-d(opDH?Kc00UL!?)^Y->F{BeVH9I05^ z0yiiMP87vuG{-@7qotG7e7|WP8L>&euWImxh4QBFG)a)YfS)u&i%K8YvP!(4EI|M(Tw7M|y2L z*gQfR^SQ-qpwN)eJx^q4(}2-YU2&sv(A20kyfpP~MiisIt#H=NC4oxKo-&pfaJ_cJ zyT%Q89ETYKO0#2UPQ$-Qm6fTv^x+ab)W-8O8xQI`}gZtX*^VqHe9_qF~dcZG`43{ z7I(`ek;+bw;klsD>)ZK>X2Cd5aJQ&JoG z*&_>VYZn{DWuHdgf7Q*fNZU`?uB{Gv^UH%rprH=&>EQteLeTT^bBwU(kWUB910A<1 z(7=WU%r=FrG+e-W3N{cAtZQ~UGv7~S8qj-y)9VCvUVW%+1}PPQE%-`Ghxuu=Mlx05k$bGuBa;N7bWPX^ zRGeyUU8DQyNRphm*_(}CI4uU$;+?A|Cyenj7b zlXNfTDy3opsr;N%JpGd1DdkrS=bTDz*{MveIu-inmziI5D!&(;83(Ui*(p!_2NdH6 ArT_o{ literal 0 Hc$@01#xj=e9OOVNaX7|y62~|3MSxUXdT|XqBeY_*vo$k9$S-;D zAIX2rb1LcXMMB65Re6r29nJLD-P8Sb&usS3sqy8tzkUng_;UfDhxpjva{v;59z+1u z-rR$#$MXzC8E9sqngve*G)AB?3N*>VM}Uv0Hv%W}k*;I}p1)8Yi_d|~GLiw0JdQv# z2F*NF^SB;`>Nv<8R3|{?$zydA)Fd>fK%(6k$UI0?Ky)0@tS2YQy_|yTG{|YF&VZbO z>MY1vsGbLT9;$O}e*xqiNE|QH*76d_%OJ1tI1dUnuYz0vc@1O%J?B|pfS&p-2!_4vAXCSUjeGhYuF`~H8)c)hz;R6y)_Vff@`mO9n|%%_EXk= z*3U){d(PO4q1Yy4KM%!Te#&qUd&St?Q0z7Pd@~e#%h+OnRy}Nsv5h`E`3qh1nD!#5 z3A*|{xqU3T(Us7mNS7ziZuVxkc!uwqouwUo5ru!_=gpFbQ#VFK*i;{MtU`KQrQ&lq zY#H59fwT1fdh%$e`1B}I232EM+*Q`uiB#@zUOH+)R%i>>UqvA&JKNd~pa^w(| z$`wZ@QrWUEVojT(5mK0;7t)IaRSF=tOZB3GE^@=ZIET@2zj(kEzpf6k=_-ETha{Bsw9@c;B{&4w%=S1dC+^ zRxMzMVVtzwrsU8!<3QIpW0yKiI1BQiT^++G*DTy&_+0PQJVB)tQoGAsj;PXDMeNsDmF=*V^8adBdvw|%pM6pG{e}E(K0fY3d9lb zppKIFftG1_D;rE<+q|cq)M?k%T;gVFd!wx#40FvPNt9Wh+BtG>^s-2j66ROh*Lx*ooqV@Y zg--@;ecWmcB*NOZHj+baT8GV3KCIW6_DBaJs_BUOjrKLFshv6&WSJjlDY8-$?{gr> z%&=ploep$l7jW^E&fi{$aqFUrioyi-@K6`uy?(_f;FanOftGGl!x8m(8n~z(oA!Oj zeV}6u+Y{Z3Lx!ez@b{Gq+LEVOSPa$Cbz+0M!2ax%0v$V}qez);uiMddL2%TyFjDMj z3Ku7uZ}%Ep469r#Nvn$8^DNxQGrnD+NLFc>rr|z0rND%gbXb3lL+56gzI1`DS|f+Y zI&^wiXEco+&(CbiU(lyr;R>MoTjW^KO~!fags>jCB@6|RIiG-Qee;!Ju8&U>-c#yb zGd&&@D$SV%TsVb#bTPZ>l$RJ6T@jVWwBjYc%6o%-*}K}XDS`tZyX?RwB2a!>3Zu32 zt!|l~B%XBNliy+Q_`!Ea`$^xx%#WakEDxlwP*!zVNDjeGw9+rZnL literal 0 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 H)~xk^a)kXh literal 0 Hc$@qQzGI7A7%j5<29r1-P4(L33J=nF0dUk4jr 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⋙)G4eR^N-InU7zNM9xIUt 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℘m&lv)xg~QiR5_jptY( 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 literal 0 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%0Akp>> z)o7bvE4_Cx1N*~D;H5(=>jR+sVnK&)gFZZRa%^1cNxqoALBwIQhBR@9H0HeJaie}l zM#fj52Fi?zigHj@jgSjI_VNLIu*f-MqdS898{nSlfWvHnhC7A~I@*=$#2=db%r$#& z0QXnlr|kbD%{ilJdTPok>6+rq8Bk7Zk4k<6RwtvSr3JhS;J&U&>@p(xgv?*Mvb8r% zI-WMj0nLsNPzz-H39-9#WVs1hwvJf<-w%cipio~$k;grf+N0$qC1QgLd$)IGX4vFU zK$wwS=viQ0US2owUc#a^3)%vJ&X(4D&3X~L@M4q`hFK*d! zy>#^vxNSUBe$N+ohynfn_3PIlQ=@BD2Mc<#iW~yM-^WW~H!uoLL)UfnDn)e^Fp>}z zRaFvDwnk#`He>iXPqo$nLy{ZBh@~0?b^-?d*5GlSTRnMjfAlt=MxJht61Y19SxS)j z-nG;n;SG2=M2H=8AuISc{$La&=>8+LQeO9+D$qK7y+Dy3xZ0V8^WJeQfe3xFe~PXG znY=4QPNqkY!~LHDuWxZG?1BMAZj$1|+egzQ14u;jihj2hAOZ2mD9eS6KJv}}Bfu^R9 zWu_sfWyFD5ABHGe?Mvq3;vxaO_;)#@M6zQ}i1hjCWT(p!Hl|(K#=dx_!If1*L*pmN z7swI(lL)c|6pLU_402uYWd{;pWD%k`HPH%;*Y*3j`Xp>4xJ#NraBH2lB+B+_G)L&t0csQzH|mwyg<^ zkB@)#?p?yaI0^du`)~5|cSo^Wy#P|>!X7fONO5<$6}BEE8Os?j}j@n62fDep3NlZlB5GzS_Q8ZbYDv?L#6 z=nAT<>4C@r8s+ya1(4vp6K4fqPpP!sau5kS`=y?YwsLnD-rwK9eU4w@sfM&$5f9W~ zS^n}lj#*F-h-tvT)P6YQdb}s!hiL-y%p|hNc?Dd1 z4Gk)gF~cdj8(3fc{yv~@@E(U5KLSh$626DT(E_vE8ZS#-3^{2T2?Y!tu*dUXegw~j zcD4v|I?$~u=2CNnG3;4xq)*&+VmCG7Kd8rD2ZmO{7vP)ec-)bUak37&u*b(3=hFQv@Cv@ZzBeVxee(cBG=lXIK8<#T$l z?Er_jIA<(O9u_1kiPL<%6+_42k#t$C=Ze_l$P*y6r5E+r4rlB2s{@f5j>k@Bszy_b zi8e10`vB#9k@G&_g3{kZ;`7@Gn}a!?4j|-p9Wd4?4Qb!W4QNp1@W zw2x}x(&&tV|9q_1{-=zp8Ph-2S6Ti`ef8cy)mNSM|9{y3@vw7c3N{hFE1$1VK!Df7 Mdpc^BcWs{k4-@QCF#rGn literal 0 Hc$@Yt~uv9 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�XvHS4!eg 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 z <pD89Ygc_^~VO?h(gs`TO_*V55J9E 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
    vW>vUQ_ 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 literal 0 Hc$@ \ No newline at end of file diff --git a/schainpy/scripts/testBLTR_block.py b/schainpy/scripts/testBLTR_block.py new file mode 100644 index 0000000..9eb238b --- /dev/null +++ b/schainpy/scripts/testBLTR_block.py @@ -0,0 +1,170 @@ +''' +Created on Nov 09, 2016 + +@author: roj- LouVD +''' +import os, sys + + +path = os.path.split(os.getcwd())[0] +path = os.path.split(path)[0] + +sys.path.insert(0, path) + +from schainpy.controller import Project + +filename = 'test1.xml' +# path = '/home/jespinoza/workspace/data/bltr/' +path = '/home/erick/Documents/Data/BLTR_Data/sswma/' +desc = "read bltr data sswma file" +figpath = '/home/erick/workspace' +pathhdf5 = '/tmp/' + +controllerObj = Project() + +controllerObj.setup(id = '191', name='test1', description=desc) +readUnitConfObj = controllerObj.addReadUnit(datatype='testBLTRReader', + path=path, + startDate='2015/01/17', + endDate='2017/01/01', + startTime='00:00:00', + endTime='23:59:59', + ext='sswma') + +procUnitConfObj1 = controllerObj.addProcUnit(datatype='BLTRProcess', + inputId=readUnitConfObj.getId()) + +'''-------------------------------------------Processing--------------------------------------------''' + +'''MODE 1: LOW ATMOSPHERE: 0- 3 km''' +# opObj10 = procUnitConfObj1.addOperation(name='SnrFilter') +# opObj10.addParameter(name='snr_val', value='-10', format='float') +# opObj10.addParameter(name='modetofilter', value='1', format='int') +# +# opObj10 = procUnitConfObj1.addOperation(name='OutliersFilter') +# opObj10.addParameter(name='svalue', value='meridional', format='str') +# opObj10.addParameter(name='svalue2', value='inTime', format='str') +# opObj10.addParameter(name='method', value='0', format='float') +# opObj10.addParameter(name='factor', value='1', format='float') +# opObj10.addParameter(name='filter', value='0', format='float') +# opObj10.addParameter(name='npoints', value='5', format='float') +# opObj10.addParameter(name='modetofilter', value='1', format='int') +# # +# opObj10 = procUnitConfObj1.addOperation(name='OutliersFilter') +# opObj10.addParameter(name='svalue', value='zonal', format='str') +# opObj10.addParameter(name='svalue2', value='inTime', format='str') +# opObj10.addParameter(name='method', value='0', format='float') +# opObj10.addParameter(name='factor', value='1', format='float') +# opObj10.addParameter(name='filter', value='0', format='float') +# opObj10.addParameter(name='npoints', value='5', format='float') +# opObj10.addParameter(name='modetofilter', value='1', format='int') +# # +# opObj10 = procUnitConfObj1.addOperation(name='OutliersFilter') +# opObj10.addParameter(name='svalue', value='vertical', format='str') +# opObj10.addParameter(name='svalue2', value='inHeight', format='str') +# opObj10.addParameter(name='method', value='0', format='float') +# opObj10.addParameter(name='factor', value='2', format='float') +# opObj10.addParameter(name='filter', value='0', format='float') +# opObj10.addParameter(name='npoints', value='9', format='float') +# opObj10.addParameter(name='modetofilter', value='1', format='int') +# + +''' MODE 2: 0 - 10 km ''' + +opObj10 = procUnitConfObj1.addOperation(name='SnrFilter') +opObj10.addParameter(name='snr_val', value='-20', format='float') +opObj10.addParameter(name='modetofilter', value='2', format='int') + +opObj10 = procUnitConfObj1.addOperation(name='OutliersFilter') +opObj10.addParameter(name='svalue', value='meridional', format='str') +opObj10.addParameter(name='svalue2', value='inTime', format='str') +opObj10.addParameter(name='method', value='0', format='float') +opObj10.addParameter(name='factor', value='2', format='float') +opObj10.addParameter(name='filter', value='0', format='float') +opObj10.addParameter(name='npoints', value='9', format='float') +opObj10.addParameter(name='modetofilter', value='2', format='int') +# # +opObj10 = procUnitConfObj1.addOperation(name='OutliersFilter') +opObj10.addParameter(name='svalue', value='zonal', format='str') +opObj10.addParameter(name='svalue2', value='inTime', format='str') +opObj10.addParameter(name='method', value='0', format='float') +opObj10.addParameter(name='factor', value='2', format='float') +opObj10.addParameter(name='filter', value='0', format='float') +opObj10.addParameter(name='npoints', value='9', format='float') +opObj10.addParameter(name='modetofilter', value='2', format='int') +# # +opObj10 = procUnitConfObj1.addOperation(name='OutliersFilter') +opObj10.addParameter(name='svalue', value='vertical', format='str') +opObj10.addParameter(name='svalue2', value='inHeight', format='str') +opObj10.addParameter(name='method', value='0', format='float') +opObj10.addParameter(name='factor', value='2', format='float') +opObj10.addParameter(name='filter', value='0', format='float') +opObj10.addParameter(name='npoints', value='9', format='float') +opObj10.addParameter(name='modetofilter', value='2', format='int') + +# '''-----------------------------------------Writing-------------------------------------------''' +# +# # opObj10 = procUnitConfObj1.addOperation(name='testBLTRWriter',optype='other') +# # opObj10.addParameter(name='path', value = pathhdf5) +# # opObj10.addParameter(name='modetowrite', value = '2',format='int') +# # +# # opObj10 = procUnitConfObj1.addOperation(name='testBLTRWriter',optype='other') +# # opObj10.addParameter(name='path', value = pathhdf5) +# # opObj10.addParameter(name='modetowrite', value = '1',format='int') +# +# '''----------------------------------------Plotting--------------------------------------------''' +# +opObj10 = procUnitConfObj1.addOperation(name='prePlot') +opObj10.addParameter(name='modeselect',value='1',format='int') +# # +opObj10 = procUnitConfObj1.addOperation(name='WindProfilerPlot', optype='other') +opObj10.addParameter(name='id', value='1', format='int') +opObj10.addParameter(name='wintitle', value='', format='str') +opObj10.addParameter(name='channelList', value='0', format='intlist') +#opObj10.addParameter(name='save', value='1', format='bool') +#opObj10.addParameter(name='figpath', value=figpath, format='str') +opObj10.addParameter(name='SNRmin', value='-10', format='int') +opObj10.addParameter(name='SNRmax', value='50', format='int') +opObj10.addParameter(name='SNRthresh', value='0', format='float') +opObj10.addParameter(name='xmin', value='0', format='float') +opObj10.addParameter(name='xmax', value='24', format='float') +opObj10.addParameter(name='ymax', value='3', format='float') +opObj10.addParameter(name='zmin', value='-20', format='float') +opObj10.addParameter(name='zmax', value='20', format='float') +opObj10.addParameter(name='zmin_ver', value='-200', format='float') +opObj10.addParameter(name='zmax_ver', value='200', format='float') +#opObj10.addParameter(name='showprofile', value='1', format='bool') +#opObj10.addParameter(name='show', value='1', format='bool') + +opObj10 = procUnitConfObj1.addOperation(name='prePlot') +opObj10.addParameter(name='modeselect',value='2',format='int') +# +opObj10 = procUnitConfObj1.addOperation(name='WindProfilerPlot', optype='other') +opObj10.addParameter(name='id', value='2', format='int') +opObj10.addParameter(name='wintitle', value='', format='str') +#opObj10.addParameter(name='channelList', value='0', format='intlist') +#opObj10.addParameter(name='save', value='1', format='bool') +#opObj10.addParameter(name='figpath', value=figpath, format='str') +opObj10.addParameter(name='SNRmin', value='-20', format='int') +opObj10.addParameter(name='SNRmax', value='40', format='int') +opObj10.addParameter(name='SNRthresh', value='0', format='float') +opObj10.addParameter(name='xmin', value='0', format='float') +opObj10.addParameter(name='xmax', value='24', format='float') +#opObj10.addParameter(name='ymax', value='8', format='float') +opObj10.addParameter(name='zmin', value='-4', format='float') +opObj10.addParameter(name='zmax', value='4', format='float') +opObj10.addParameter(name='zmin_ver', value='-200', format='float') +opObj10.addParameter(name='zmax_ver', value='200', format='float') +#opObj10.addParameter(name='showprofile', value='1', format='bool') +#opObj10.addParameter(name='show', value='1', format='bool') + +# # print "Escribiendo el archivo XML" +# controllerObj.writeXml(filename) +# # print "Leyendo el archivo XML" +# controllerObj.readXml(filename) + +# controllerObj.createObjects() +# controllerObj.connectObjects() +# controllerObj.run() +controllerObj.start() + diff --git a/schainpy/scripts/testBLTR_block.pyc b/schainpy/scripts/testBLTR_block.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3fa0a7ed18b4eb7e2af089b0194dc39d450ca33 GIT binary patch literal 3026 zc%0o-ZC4vb6u!G5A*9fxP$+2BSl`eVb`uN;))ouawjyAtFK55xEISjjVY9PmXTnQA z+W+7uKltPP2mS!Pb9WPRAmXvdPi8l>bLV;HzRsP@A5(?je*g6+57J)||C{)izhnUz zfPUtKnWL3=fK`CK3+yhi_Yw~V*!zTiK-h-~Hqi9Z6-|r8{+QUGT+(!pu=^vi zCBl|RdSDHCa2d0&*;gg3_Mb(y^1qDg(`%xtzh+dcuNl?azmDp&D^aaq!`=Y)Ij{%R z5yN{5SN9CCF9>@$G82!6BHFx!eL2)qmvufSY-=R8eNC3Wx(0hf*w-Vmr-VHli9ILm zn~~TKVc(9#b_v@XiR}~i-7toC(;a;o8F={~EH?E0yo^I(E9S1^tRlk7t~jaK>-Q@) zySiE^Y`Q(w7V$$E3`9%WGfIXwpo|(=Lt+$VXRL-duY{7jMClmT*EdxeR{fF*79!>Fg8F|u$F#!vh}p~D)HVca}%1KN+@ z9+z6k7t|XeByyU904UA1cbqUQY!+k7a5^tC6Hx>2SMP z5r)}BlNky(b%Pi+V*8;ElcxA-3r0p#hg?sIL}}|Hh%gdpT@tTO-o7LYI#Vae@x4^= z!>8OoYAa&aXj~@^QOx%Pp%ND{KFI?-q^gACkABE7m-=AE#L>n@M5jQT5~__RwDwbU z!dC%T`ovQmytW&LJlOH2O6!2Rk%@|f-9{JX{?t9ABU!hTBJDO*JLa-Yr|L`-lSxXe zu9AGNWgW!|i7%0t)URfz3n?Gvd`f6yM&uY3x!zxO&-7~240U^PzTd3PCKFz>Nh*X) zDt0a#dQ)=ZqQFn0IpWGYWoi8+>QXZr#{}TnJ74y&e_|0}3LBK1d{RJ8EjN}n8kubQ zN7O|5w42(jRaa9wmje}hhn>VaSG|bx>@udC@cR(GDW+G07Pds#((II@TY@;*#AED; z5*0sLPT5sD8HlA;$6 zR-$t&xo@P^zg(J!f$)x(qjSp013a9)fIlRgKjV-y<}+nu&YUqzX3oqR^q3Q7*(e&h g!82hNjbe7%C>v#y#*62lWE*93KAC6A#+B#pUrrTu4gdfE literal 0 Hc$@?(>8_NXp@iwq)q)$j#vr2X1&_8l4Iy= zesZ6C+L@7Uw!z6mF_uU3&3to_Muop7O3SN%{}w{`?=pTL;MW`u0Z9D!AO@)SWe@5e zD1fF9%>oNU@D|{$2hxXYbsv<+SP_&@T95n+5D&w?8UZ;3Cq86<49OzYM?nrleGF8I z80wcmU4rH~NHjxe3}gu;Dn}75c!W)WL>SjekW(P1L0$$q!|N=_IgnRC&V#&4smKM8 z*U)pcJ_%|Pnp4bp9W`Eknj>9iwi_VJY%s%RfM1^lHQTel$@X)g=Ae0nH6MZe7~~?z zPe6X^GV5cXG4^>L>oa|Ef$2-O{%WB063DMX-r{`nKHsp340FyEdEa+B~TFp66ZmTw~8~o#%Wn+Px1(`%m_LpY@#2RZv%ZJ|pb2 zk&n~IzGG~ivHR~}-!t~ZK))XudoU3DDc8k!>)PZTx89TE!w=;6=zr$;cp&!VVvc?6 zDP!CD9`~`I8T(}*cCl{x44yot>#zW7%#Hc;uI5@#LmQemC*9~vWtI|tPWF~w;9C>@ zgMTj~dVZEXTr4fO>?p1W2Q3jL2M1;xH+$;1ok+d7uZ%S%dZfYzqARDZ*!sjHZ2^CR z^}yoe1&L@WJ4}3NUk&Uf6s0m@7Ns`Q3G+)~g*{7^oxshnI=13i?J6Nv#uTZr4Ksy8 z1+jKZnabYItG(YVc8sE1k=cg=*(sM=HCU|#)k^K29l@Gg2MeHn1aPb*IX72s#$@ zq7+O+chXE_gWc($Vi?D|+TDv&ZdmQk%DTCZ!XvuUhmoSuQ1PP3!bbE)FTQ^M%*-SF zOq~sYmTuC8B3|wKV$RGiT~^N0q;cd<{#e-TfUFy-aCg)7f;!C%H<0wY5ra%7@sa$*4=FBi{pznCZV)--fWRa6#*CzX!QPE0C7RdH`!rnRjY z-Ol=&^sM5ZG*h8>ZdY{h-4QG487FwZrDZ!-KhT_*43`DJ>`nV6f7~DThW#`!^a wxzCtCgPN(K8L#Y>eO&zolDu*Oe+enFX0EHH&rnYG-CFb~{GvBeD0wCCUpM72qyPW_ literal 0 Hc$@cpQb&ILI*?$>t2YOSiwPQ@UE`K@GdES#3)$bR@K(PUU9P-Pt8K z>+P-B*=l4y18NASo;>9hHt(&uI(GTsZ~VLrsPWHvI9M94nu|ET*xH_7-P)Xg^yt~_ zqy1PVK~qI`c3T;1#t>JkQQir4<(*mBZ-&+3(f{JY=%Jg#Oi0|SdA5$H{?I4AUj_g6K>?kf?>(Gjt+EhZS zgtLo3x8Zm9fd)p0^X{AE@vnX0wU*__C)xOW3MU8dt)ak(j0ZRquW4l=7dThm*Ya+NFRMF`1w%k0wtGk&*if+$&oDoYb?N@r3>;lC-(HJ- zUSD@>BX$+ns2bF|Cvh(+(>>La!&zc4YCkSh?HpN=Z8o=8d!lg{)714|do$VEx!I>M z+@$Tl=*qB#M|AlB3&bR9-x^B#>OvgVm=3p8gjF5V_Kn~=QB7@?6PU^FW!-BEV^xx? zC88QswBdtdRI-a&baWeuo)>YvfJrXY^v(jFKT4{FD%@Qtn>Ggnu`p&&Cz3Z1FEw7d z{BFI&LMO!{WEu&P88J#bKreE zFr6l%=%j59cCM_6!@zPtcu6aJlBbv>dgQ1pINj-ywg( xpYf->X>Zz%?%O}(Bz})H!=pdlKXthF`QO)L$vXYssE2=yA={VDjN^RB`v=3?2VVdH literal 0 Hc$@jcCe|!+`qb2#=#s90PfpMv^%L5=k7-l3h6t z@*K$XATNNN0C^GQB*-a{mq1f>y68dsd+Io5ohHGc;3 zb7r`}(Slo?05#F!{{rNfAiv^ulsX6Xi@bgv@*SVM+y&-dVD7~@gG*4H?D2c~1UolLQcbettz&-QX03O6v>svKF?Kf* zyY~s~K4ae}Vh$euIyA`yGZ*k&TO#n=ywZ6CvSxN>8O*zU)f>|(Dz>XoC|UVk#SH;MY* zGWKI4R%Gm_|1Bp!GxkfO+<)gQxzj(DuU}8d*B;CKmS{_S!jBTml@l?^m`cPdj8zk{ z8e?7}R{y9^ofRT7v<-Q7r8~PC&w9^(JaZc)eht(ROg>p> z3NM$PnE-Dg?;rfV^yp%mad5CS+%T7Me6h1Tx3RN5x3>0ldhIY&k=Iaxo!(W(n$sj| zqP>!@%ll^ju;E*mmZVMLCx1I{`|ulxhOz^s6=iaHJB(AQOgZvG>*>H;M>^Y3(i2(Z zRRiIdYr+e%>#K8HZ(kL%4P*Dnh*EWvIbxN0wXK9y5l0saTeCxSlUotlRe?dK zkt*c!OW9l=AA1T(703^vd?CA#JCfVQtQxYG%iZCpBh>{83wM@oIGrbZb&c~Dq9`JwnNSanbo$2SvbSGnQ>bLRrTC6mf?58Zz|KzA`GMHF{UNuysB!?rRtfqlm+d1@$ai?jLV+2xx{Id&9{TNSOe)|FSSS;M9dyg=#$ z?#M!pI}$B&&*o?IvvZv%F3_qf>rP2&#-*wFTEsq*?cfoulZSnj$*oy1>bBTh`kt9D!bAljn? zKuZ==hv6QlirBVyH+t;GB|PldZToT9v0GSVe@#svv>S)Riuc0~cKu2VGs3#mq2&&` zF&_q1mcl*}entCKtr4Un)zDVO3udCb{|_3%U`u4Hk*IiO9k+y0(L3a#-B6G8oCw2t z3~#=wOY_*$6jT#g_`sr|+Bz5rg)s*@l3X!7CvX?%-qk9sHcpDUgwr)T*GeA7pr@5T zEuwPGd#9)0zIe{QJy)$H=psV*l7BPP)KM6}Z7I&FKfa|)Qy_bfYv`@Vc2 zd5STjMfSR^0~=}I$B0N#fSZH9(#GYYGnqA0LAp7>F05l)@#%M@V6#+@O)A?Aw;z%R zR2v~B9gVL7^ka-`6BCbgP$7|#m}e6cCg|*E3pzw7pYJH3ZNUoq<3R8zichb2xvh%Y zw5@GRMC2?+MeS1((Y}fn4)b;@QL4R3;>M3WtKQ|gHTHBIdVoY{ ziSiaTgLeK3Gx&j{!944>A$CT2KZ}jCZ$eSVYl&~9NNbxlx*2s>!d5oE5lxn^$-SOy zHEgl7ckz5_`szOI6!RwzlkSL{an87DXUrLJ2HYVx{Kr=N`khe+U-T&5mqs7@ogwF6?F~Mg literal 0 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
      YMz6YqW98Lo-iZ~ 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

      !RhC3Enah6L&(YQjsjmJbmt5;NE=ng6%U| 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

      ^c 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

    1. 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 literal 0 Hc$@ \ No newline at end of file diff --git a/schainpy/zerorpc/.svn/all-wcprops b/schainpy/zerorpc/.svn/all-wcprops new file mode 100644 index 0000000..1b802c5 --- /dev/null +++ b/schainpy/zerorpc/.svn/all-wcprops @@ -0,0 +1,29 @@ +K 25 +svn:wc:ra_dav:version-url +V 78 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/zerorpc +END +__init__.py +K 25 +svn:wc:ra_dav:version-url +V 90 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/zerorpc/__init__.py +END +MyServer.py +K 25 +svn:wc:ra_dav:version-url +V 90 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/zerorpc/MyServer.py +END +MyClient02.py +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/zerorpc/MyClient02.py +END +MyClient01.py +K 25 +svn:wc:ra_dav:version-url +V 92 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/zerorpc/MyClient01.py +END diff --git a/schainpy/zerorpc/.svn/entries b/schainpy/zerorpc/.svn/entries new file mode 100644 index 0000000..5bc2970 --- /dev/null +++ b/schainpy/zerorpc/.svn/entries @@ -0,0 +1,167 @@ +10 + +dir +1608 +http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainpy/zerorpc +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 + +MyClient01.py +file + + + + +2017-04-17T17:05:33.000000Z +695a9209a08cb052597a177f2976119b +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3930 + +MyClient02.py +file + + + + +2017-04-17T17:05:33.000000Z +ae58efbdf59693fc3b2729eea1e2885b +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +266 + +MyServer.py +file + + + + +2017-04-17T17:05:33.000000Z +01a27652e8181140d49393bc99728a7e +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +877 + +__init__.py +file + + + + +2017-04-17T17:05:33.000000Z +d41d8cd98f00b204e9800998ecf8427e +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +0 + +test +dir + diff --git a/schainpy/zerorpc/.svn/text-base/MyClient01.py.svn-base b/schainpy/zerorpc/.svn/text-base/MyClient01.py.svn-base new file mode 100644 index 0000000..0babed8 --- /dev/null +++ b/schainpy/zerorpc/.svn/text-base/MyClient01.py.svn-base @@ -0,0 +1,147 @@ +''' +Created on Jul 11, 2014 + +@author: roj-idl71 +''' +import time +from gevent import sleep + +import zerorpc +from schainpy.model import * +from schainpy.serializer.DataTranslate import serial2Obj, serial2Dict +# import schainpy.model.io.jroIO_usrp + +def createObjVolt(): + ''' + This function creates a processing object "VoltProc" with some operations. + such as: "CohInt", "Scope", etc + These class are found inside schainpy.model.proc and schainpy.model.graphics + ''' + procObj = VoltageProc() + + opObj = CohInt() + procObj.addOperation(opObj, 1) + + opObj = Scope() + procObj.addOperation(opObj, 2) + + return procObj + +def createObjSpec(): + ''' + This function creates a processing object "SpecProc" with some operation objects + such as: "IncohInt", "SpectraPlot", "RTIPlot", etc + These class are found inside schainpy.model.proc and schainpy.model.graphics + ''' + + procObj = SpectraProc() + + opObj = IncohInt() + procObj.addOperation(opObj, objId = 1) + + opObj = SpectraPlot() + procObj.addOperation(opObj, objId = 2) + + opObj = RTIPlot() + procObj.addOperation(opObj, objId = 3) + + opObj = SpectraPlot() + procObj.addOperation(opObj, objId = 4) + + opObj = RTIPlot() + procObj.addOperation(opObj, objId = 5) + + return procObj + +def processingSpec(procObj, dataInObj): + + procObj.setInput(dataInObj) + procObj.run(nFFTPoints = 16) + + procObj.call(opType = "external", + opId = 1, + n=1) + + procObj.call(opType = "external", + opId = 2, + id=191, + zmin=-100, + zmax=-40) + + procObj.call(opType = "external", + opId = 3, + id=192, + zmin=-100, + zmax=-40, + timerange=10*60) + +# procObj.call(opType = "self", +# opName = "selectChannels", +# channelList = [0,1]) +# +# procObj.call(opType = "self", +# opName = "selectHeights", +# minHei = 300, +# maxHei = 400) +# +# procObj.call(opType = "external", +# opId = 4, +# id=193, +# zmin=-100, +# zmax=-40) +# +# procObj.call(opType = "external", +# opId = 5, +# id=194, +# zmin=-100, +# zmax=-40, +# timerange=10*60) + +def printSpeed(deltaTime, mySerial): + + #################### + size = len(mySerial)/1024. + vel = 1.0*size / deltaTime + + print "Index [", replayerObj.getProfileIndex(), "]: ", + print "Total time %5.2f ms, Data size %5.2f KB, Speed %5.2f MB/s" %(deltaTime, size, vel) + #################### + +if __name__ == '__main__': + + procObj = createObjSpec() + + replayerObj = zerorpc.Client() + replayerObj.connect("tcp://127.0.0.1:4242") + + serializer = replayerObj.getSerializer() + + ini = time.time() + mySerialMetadata = replayerObj.getSerialMetaData() + deltaTime = (time.time() - ini)*1024 + + printSpeed(deltaTime, mySerialMetadata) + + myMetaDict = serial2Dict(mySerialMetadata, + serializer = serializer) +# print myMetaDict + while True: + ini = time.time() + mySerialData = replayerObj.getSerialData() + deltaTime = (time.time() - ini)*1024 + + if not mySerialData: + print "No more data" + break + +# myDataDict = SERIALIZER.loads(mySerialData) +# print myDataDict +# continue + + printSpeed(deltaTime, mySerialData) + + dataInObj = serial2Obj(mySerialData, + metadataDict=myMetaDict, + serializer = serializer) + processingSpec(procObj, dataInObj) + sleep(1e-1) \ No newline at end of file diff --git a/schainpy/zerorpc/.svn/text-base/MyClient02.py.svn-base b/schainpy/zerorpc/.svn/text-base/MyClient02.py.svn-base new file mode 100644 index 0000000..dffb82f --- /dev/null +++ b/schainpy/zerorpc/.svn/text-base/MyClient02.py.svn-base @@ -0,0 +1,13 @@ +''' +Created on Jul 11, 2014 + +@author: roj-idl71 +''' + +import zerorpc + +if __name__ == '__main__': + c = zerorpc.Client() + c.connect("tcp://127.0.0.1:4242") + c.load("file2") # AAAHH! The previously loaded model gets overwritten here! + print c.getModelName() \ No newline at end of file diff --git a/schainpy/zerorpc/.svn/text-base/MyServer.py.svn-base b/schainpy/zerorpc/.svn/text-base/MyServer.py.svn-base new file mode 100644 index 0000000..5d8ad2e --- /dev/null +++ b/schainpy/zerorpc/.svn/text-base/MyServer.py.svn-base @@ -0,0 +1,33 @@ +''' +Created on Jul 11, 2014 + +@author: roj-idl71 +''' +# import sys +import datetime +import zerorpc + +from schainpy.model.io.jrodataIO import USRPReaderAPI +# from schainpy.serializer.DataTranslate import serial2Obj + +if __name__ == '__main__': + + replayerObj = USRPReaderAPI(serializer='msgpack') + + replayerObj.setup(path='/Volumes/DATA/haystack/passive_radar/', + startDate=datetime.date(2000,1,1), + endDate=datetime.date(2015,1,1), + startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59), + online=1, + nSamples=500, + channelList = [0,1,2,3,4,5,6,7]) + + replayerObj.start() + + print "Initializing 'zerorpc' server" + s = zerorpc.Server(replayerObj) + s.bind("tcp://0.0.0.0:4242") + s.run() + + print "End" \ No newline at end of file diff --git a/schainpy/zerorpc/.svn/text-base/__init__.py.svn-base b/schainpy/zerorpc/.svn/text-base/__init__.py.svn-base new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/schainpy/zerorpc/.svn/text-base/__init__.py.svn-base diff --git a/schainpy/zerorpc/test/.svn/all-wcprops b/schainpy/zerorpc/test/.svn/all-wcprops new file mode 100644 index 0000000..39c9f17 --- /dev/null +++ b/schainpy/zerorpc/test/.svn/all-wcprops @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 83 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/zerorpc/test +END +testServer.py +K 25 +svn:wc:ra_dav:version-url +V 97 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/zerorpc/test/testServer.py +END +testServer_Voltage.py +K 25 +svn:wc:ra_dav:version-url +V 105 +/svn/jro_soft/schain/!svn/ver/1606/branches/schain_ebocanegra/schainpy/zerorpc/test/testServer_Voltage.py +END diff --git a/schainpy/zerorpc/test/.svn/entries b/schainpy/zerorpc/test/.svn/entries new file mode 100644 index 0000000..1fc12f0 --- /dev/null +++ b/schainpy/zerorpc/test/.svn/entries @@ -0,0 +1,96 @@ +10 + +dir +1608 +http://jro-dev.igp.gob.pe/svn/jro_soft/schain/branches/schain_ebocanegra/schainpy/zerorpc/test +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 + +testServer.py +file + + + + +2017-04-17T17:05:33.000000Z +b5043e55187c8869bdaaa2c6ff00e68c +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +3457 + +testServer_Voltage.py +file + + + + +2017-04-17T17:05:33.000000Z +ec7bf6d746b16175c546fdbd56127a81 +2017-04-12T22:42:28.822577Z +1606 +ebocanegra + + + + + + + + + + + + + + + + + + + + + +1011 + diff --git a/schainpy/zerorpc/test/.svn/text-base/testServer.py.svn-base b/schainpy/zerorpc/test/.svn/text-base/testServer.py.svn-base new file mode 100644 index 0000000..0f81f86 --- /dev/null +++ b/schainpy/zerorpc/test/.svn/text-base/testServer.py.svn-base @@ -0,0 +1,177 @@ +''' +Created on Jul 15, 2014 + +@author: roj-idl71 +''' + +import sys +import yaml +import numpy +import jsonpickle + +# import schainpy.serializer.DynamicSerializer as DynamicSerializer + + + +def isNotClassVar(myObj): + + return not hasattr(myObj,'__dict__') + +def isDictFormat(thisValue): + + if type(thisValue) != type({}): + return False + + if '__name__' not in thisValue.keys(): + return False + + return True + +def obj2Dict(myObj): + + myDict = {} + + myDict['__name__'] = myObj.__class__.__name__ + + for thisKey, thisValue in myObj.__dict__.items(): + + if isNotClassVar(thisValue): + myDict[thisKey] = thisValue + continue + + ## If this value is another class instance + myNewDict = obj2Dict(thisValue) + myDict[thisKey] = myNewDict + + return myDict + +def dict2Obj(myDict): + ''' + ''' + + if '__name__' not in myDict.keys(): + return None + + className = eval(myDict['__name__']) + + myObj = className() + + for thisKey, thisValue in myDict.items(): + + if thisKey == '__name__': + continue + + if not isDictFormat(thisValue): + setattr(myObj, thisKey, thisValue) + continue + + myNewObj = dict2Obj(thisValue) + setattr(myObj, thisKey, myNewObj) + + return myObj + +class myTestClass3(object): + + def __init__(self): + ''' + ''' + self.y1 = 'y1' + self.y2 = 'y2' + +class myTestClass2(object): + + def __init__(self): + ''' + ''' + self.x1 = 'x1' + self.x2 = 'x2' + self.otherObj = myTestClass3() + + +class myTestClass(object): + + flagNoData = True + value1 = 1 + value2 = 2 + myObj = None + + def __init__(self): + + ''' + ''' + self.flagNoData = True + self.value1 = 1 + self.value2 = 2 + self.myObj = myTestClass2() + + def get_dtype(self): + + ''' + ''' + return self.value1 + + def set_dtype(self, value): + + ''' + ''' + + self.value1 = value + + dtype = property(get_dtype, set_dtype) + +def myMsgPackTest(): + + import msgpack + import msgpack_numpy as m + import numpy as np + + x = np.random.rand(5) + x_enc = m.encode(x) + x_rec = m.decode(x_enc) + + print x_rec +# +# x_enc = msgpack.packb(x, default=m.encoder) +# x_rec = msgpack.unpackb(x_enc, object_hook=m.decoder) + +if __name__ == '__main__': + + myMsgPackTest() + + sys.exit() + + serializerObj = DynamicSerializer.DynamicSerializer('json') + serializerObj = jsonpickle + + myTestObj = myTestClass() + + myTestObj.flagNoData = False + myTestObj.value1 = [1+3.4j,4,'5',] + myTestObj.value2 = {'x2': numpy.complex(1,2),'x1': 'x1'} +# myTestObj.myObj.x2 = numpy.arange(15, dtype=numpy.complex) + + myDict = obj2Dict(myTestObj) + + myNewObj = dict2Obj(myDict) + +# print myDict +# print myTestObj.__dict__ +# print myNewObj.__dict__ + +# sys.exit() + print myDict + + newSerial = serializerObj.encode(myDict) +# print newSerial + + newDict = serializerObj.decode(newSerial) + print newDict + + myNewObj = dict2Obj(newDict) + + print + print + print 50*'###' + print myTestObj.__dict__ + print myNewObj.__dict__ + \ No newline at end of file diff --git a/schainpy/zerorpc/test/.svn/text-base/testServer_Voltage.py.svn-base b/schainpy/zerorpc/test/.svn/text-base/testServer_Voltage.py.svn-base new file mode 100644 index 0000000..4ce04bd --- /dev/null +++ b/schainpy/zerorpc/test/.svn/text-base/testServer_Voltage.py.svn-base @@ -0,0 +1,46 @@ +''' +Created on Jul 15, 2014 + +@author: roj-idl71 +''' + +import sys +import cPickle + +from schainpy.model.data.jrodata import Voltage +# from schainpy.model.io.jrodataIO import USRPReaderMP +from schainpy.serializer.DynamicSerializer import DynamicSerializer +from schainpy.serializer.DataTranslate import obj2Dict, dict2Obj + + +if __name__ == "__main__": + + serializerObj = DynamicSerializer('yaml') + + myTestObj = Voltage() + + myDict = obj2Dict(myTestObj) + + myNewObj = dict2Obj(myDict) + +# print myDict +# print myTestObj.__dict__ +# print myNewObj.__dict__ +# +# print +# print '#############################' +# print +# newValue = serializerObj.dumps(myDict) +# print newValue +# +# newValue = serializerObj.loads(newValue) +# print newValue + + + print '###########CPICKLE##################' + print myDict + newSerialized = cPickle.dumps(myDict, 2) +# print newValue + + newDict = cPickle.loads(newSerialized) + print newDict \ No newline at end of file

0!V)HbnJ_p7guk%1uqBx1=~K16S) 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 literal 0 Hc$@-aYTfy`8m1Q#1pkvGUx8hsLSbn8dN>5FD}V3)VZTmr=-uwBR1Wn zgs~7+A*nQsb!$+C1<@2W;930M*skL^@-n`p z@(nS`U$0@wM{fln+Fvh^sxrLWzy6kar%OC8?APn<4NT?VzqV4jC;9x>&+;FX|KC0k z%jNRiUGQkikwn1dUaHTjWl(4+5_EdFG5LgDx6uWAKV2rC+u-!B+nJD%&}gE{l0?XZ^ZepMSzR3!s_s@Ec}_t8 zrP^8}l0tyUq$j$o+IkFv&~V7x!tm+XJoYVqeyhyuK2u2H56(;TA%%}P-dWuF#M-(- z?hEb&@A~!3%TQ|C%+NGhNy#UEO-+L3zE_tE;51+-yTZdU*txmYZ%8TsoUFBb)wQ!X zAQF+9n#vWe_~yQppz~TBLwF{y%TLXn0-u4Mj4u_s<&nu zoaK`F9CJyis7m){M6ON-jD37sj=^PznVOpN&#u=yF24tN9-he%K31YfAS5Vg<#mWg z;i_TQl{JGWVF6 z2tskGSm3`eCxcBj^<5t=UMNs21otncp`o$U9YqFCk{KEr>UME@Kw5qse=y5mC=;w! zENkoe^;dV~#g8_p5ugC-w$GojAte=+0QbEgMj%u)tE~tj>f5(bOu8f6IR*p+!6H#g zNl8I|ltLcEysl@58{3D6A+@zUr$<{cK|#n+TQDZ^+>ak2=4swUjz9YR8Nv&8a&mKx z!O0+qm6g@&;$RHQp82>&PEJmZjtI3458uem%`LD=OiXO+?#`7aYjoM@ND**_Poh<6 zmQhxQ2W?Ng&d#sqrAa?{aILqu*U-)m*U`~2l7t=6d>~b-P`&s|i}xAn1|czVR$U#* z#zeJ5owGY=0j*cu5h zFF}{BnW&12`};q?5%k1R$>{2m>+0#1J1#3gZD30>9ZOs^i{8Dv+j6{s>2*9GdVJJ+ zg$-#oxv{(a9QOw~kRg}AGT!Rjsv@ecp{$(oQ%6f{ezaHz@>3K(kvw?IV$c$qm`LL0 z={fdI+6LsWk*#esolLahT${h!(X=Z9q^zu*$m>AsbGE^wsiig2*qkL3V?0&oP*5sz z^8FP^2$J4UpI*ep1(EUC&H-fMU!DRHefJqNGqc0`C^Pt`aFqAy)2Ddk+ORvgGF%cc#F3Hzw=tq)RgY`@879KM5w@abZoU=;fNjyL_L4*Us%W_E+G+*SPf7| zRzU&Y)@Uk`lBSrjFiIg9_C8P_9v;dnDwZBp+fFxRfE$MVO7t3OSy^#cS6AT+hmq~W z2iYg4rteaj&=FCwNwb?SC+%7hpqH;+%>#5RH|e3}<|g{~?OVZ)8ne>g?yjMYjo$JB zxJRVR%S!-uk|1#QZL=goaklsOks&uXx4E;eRy68q83DsKsLF1Z(%s#?_XNDSCJIm8 z4SY^+>$}aPj0`wFdlnEAgF7`fRp!2DhDFYc2SV;EUmm!dhl6<=8AXcZ#X7YiZ{FNQ z7V`rKzI^!-ggUp~43>z9NM9m55)vwwC`fwi_e=Bh{vd0R(a=o3RhUA4Wo2yl^crrk zwj9%X9Bt~YpM{0347UBk{N3}tfyFj|q+UtxOooM(!7NBAE1@DY6Oqd2n8xh$+h78E zg|?m^nN^!2pAwfkn~}u{lm7nx@n%mRu(r`(^As0LeJ={vwsq<0>2KY+gBa_vDjh|d z_;Z@i=>z)L6ZdrM@aPqi+cKph<`x!I77qrqWESVz10laaG+bkF z*A^oMBi@Vo6O|t4#}50eU(ulLK8}I8@p6;npOpgubW|3-CuW|CuK6?Hy^8>yuPXYA zJ2`P4Zq3F3Os{Kf9CO!`l-%FG-+Xl!FxlEfwRNbX$ikIh67psK8*BCI=i?x5q~NcTijSW~1n`doPQr3erM zP)_8uybe$al0D*3r%F9LoV26k;2;2rh642^^AUicDX?ieUWll3+o9F2wT*h5r!aqU zG}{AKiQRQmSMcm-C0L<0KpO$zx>WNt_P}pL!Tw7szh5tHjRyI-xH;YEHXlrEzdCd~ zJ3HHODEk43z2Up}06;~2`J(j1%&cR2nxehEorKc@uRDe+#`9=11ANeUle=Tomf>iT zRw9=*k#r0tHX0flGAe38_lu;Yh@%-#T=1UpdPn-2r{4lzGwWo6_w_b6GN~7d8XMF0 z_4Sn*b)o`@UGd5T+|eyV<&7+cXJ};=es#Vq0{KOe@z63dVgyiAv$5g5e*N0{a^rc} z%KYsx=g-@sV6jmrK^WbUe~S!Yw|OQZF%ex(PA-T3B?wQkx7;?QKIc0!&`>dhy1F{A z>n1t08afR!0E7Y&`n7BAfUmJn?-6DGR#n+>sFzh#bO45mefbg*UU$Lbfy@Vb1rq{*C*tMpZDeMK3hsV?b6Q7Br8q+~?E0@GUo0fq zwfILxVS5~`p@_a!Zdp^Y0VvX2bcEgYF}#4`?pOMEKPL1TJ*Ua(DU0q%L zmGK(pwzehrWKba>eLj5r_|5^)_d1)yf+W<|pCT~7ysTkPZnf?@MvSSf1;8o*se>GOpJW6df%%o_=Xsdi>&AwYC6by)zQOxZ|CNHE!&X_kHX zP$e3`5)B=lgnR0nH`fFN1OiI}gY%2Bvyq8e^(CdHrK5t|oIGuMi?W|;cd5Q`@+~(NiUHqJEUIBDv>O^ z7DLSY>(?5aNjAHgCej`xBqSi&2(xo@J32c%=VGHW@lrsZWM*YKM@LbKP=5UQvCe)T z@pOMR3rkV3LNY0>yq(B6T zvh&|}L0!4WEITq2uQ?6mRmZ1Kn0}|E+#@lQ-@e_oo&+SAp;K!ML609l*3{Ns06-(} zhVnZ!ab<&_pMtmY-2VpH5!=ym@2tc`Vn1CxcNr480*4$RMIu;3)UK}^h4DkCjTd*_a{d+MuKfqs5a3U^0G2Of~Zf{OC;Qug*`{d@qg zWaZ`6QhR!O=rpNvY0x>Z$G&GSV5rQRlb$P-5vcmi#1)?#2cTt-++IB z0YJCO4IhHzBu6d*7K{`EE~@=<4<7iZrBPkKemyom9)*X8N4NeNN&vOtc$pEvJ6PV_ zd6eka6+ztj^(#R}Mh46nfc_)H!qDMu2VljY<_mHdY!ged)qNfLuE|Eu2MiXgFp=@Aa z@V={S9@eU(#bkgc0uR>5vZ|_X06>HMfWf2YKH|rclarNHRfB+dO?>l) zE8n{<%tJDX%u{mJ=h?GohSt`TQ%14)e@|BFYMK3B?Q|Pvp-hx6(XG~Xy+zmtXf`fKnX1D;`V%Jh;F#UEZxH=kGO3nhW|V5d4x9con2i+D=QtNm>C%#@|iF9 zr&KEtB_$_E0+ljacT`O?PRD5Shdpj`j8F~^*D`rZDrO_n`@|i}Z6Tz26>3C1*4M}J z^z^)S`*w!)SV`{=NYY3$9vlGHJ-~HhwGd_1$^3ETr1@4`%PT%ZsIn4{A}8vlxzXf& z0X`R}t2Z)$JWOOWLJSBDB+EfZ;pI&D^@f$0V*D}usL05m($doYa$MnKNTXE0>n)dc z+>)N{Op~S32Ox3R-m!OgeC>Q*FXn9I1Lq!`f-|J$c+)jDWMCWf9G{L9s4?8T_Z}F< zxZ<_zN!aZf^^ymihHZX7aQq{0I0mkDod04207A|02ve{bB$F^Ol`}m^g}vMyLq(;- z|9)=9bd@k}_ge?ue`*aYF^^PN@d=}9W#W#)u8%ynvaN?qUGP*M`6~k@&k$Vnnlm*OErm9%nINOBNG!Ob93{haR7pI zo11X0!SMWe=fkH@kM(t0eT2vd-K;R|%oG$9qOMmc-^i>q`wXOL zReyPUIyDfYi@QsoNO)|?0|Ejd=H=5}~0)caZlW4FQ%SGv(f>kw;QPOq_v?H8lZ5e{w=RClwDn2!Fr92XJ%%`Il634T?4{w>11uB zupAJe;NiH5MUj9&l*`F$VCw+ULlC&)*rX&(sLo+Aq<`We&{`jQdjo*$0cJOT(Z$6D ze2WPE3puTP$&h%gha-dx6y?7pd2NBz^1CP0!dero%%u)iuy&G<|BH6Iee2eo@6{RA zYgU73;0)lxK}QE7Ceb|$`w!AOVd}Th5s};7#@aGuBxYN@lLV0OtNepZtMMof=`E46 zKZYMBe<^$ij4`ZMRwk+opZx?%UHxzj04NX_q^d!PQJkDSfa?GPO8EHrm~f(ruAzMX z_z?ku+1zotAIeVckBr1xY62KCJ~`Rh-;eVK0AutYrYzXr+uKv~l=%P5lEv)rX?b}y z&7<;x(FzIf8`gKtr-e}JCEAVPxhS6 z+MCk=9vUsYe-2X?WO%Z>R8~{d9ZtxEcjHD7SZrhz6q?(&QNT*b%F2qWs}lheY!8$d zdVrr%X9&%$TgW9PB`_!wvFc+fDk=trge)v{MF9K40d#j6h*}WyD_+70b{S{SV`9c` z5-DVNO{F)miNHGpZ&1|QE_0{|q&-&Q^(lqc@SHZQ$bod2j^F##36`CsqeKEOKifVh z@hGdP1SIj;83P{&S6*`ElR`lJj};1moDe)1etf*sLp4~e!}D~q2AfHvMDpp=dqDpM zn)E~)E%nAj(EsSz0ih#uxE^8D2)H^?z?B8Ykw#ZLHxCa)=ttk1z*(O&?C9udx2ubz z_?vFe_Z{Xtg8v1Cxps@{2!1KyJ zdIVb@GV+S{${)ZH5Cx)Qi_6NQgH(T>BH#)x3sJyzle5Z_HY<}~?xxW0-=$&ki%tBf zu&_2jNATGnr3z}@oY&UZk4`Y~xj8>Se>@*bg-1+`#=*f6C~mu5RIfccI?C(5dkYv4 zb0zA}QAc4z7vH~s2Rm3(-$_mP{vW$8lxYxDI7_!Cq_{;2mdy!-C0rRR)o->3V)W-! zJwclHp;ne&M7vNXkcBG%&`jQoKN&vuMTddoADl%x_ZKq=0T2$PMh8y&{akzCPQSnw z30Q=qu$GI%NwMu2E5O=iG>TI~H^R#jsBYTV9Z)1QTnjRHX0Sdkml+EUz6 zNJfWXpM8FQ9yiw8+iSo3{XsIHBPtOQ5ljiFxRjCRY2G#MG-SGAF2JGzDj*a-U7<@^ z44|HyY4!}^R(!%~Y-~I?KR@{2N~souz!J$X8&h=XXvoLiJ?gQEiOKrYf~F>N;OC`O zR9-$S0$2(c(D|KKAZUAcR~*=wJ)%qw^ZxhXGT5BgRAHzN;g)$)wY$6f_Fury**Mc5 zDF++coIzd~bWZEd-kkC_H4akw8)cyGU}QqWu-27SO7! zthfP&P1eK1X!K09eaND}tUZk6P#i!I-B;QIhN zTqC$c&A{*>-I~2l#;G^%F0a!HUQ<&OmQDC?nYBM6yB>zv20+(J2++FIqcmZ?t;1mw z-LM}^OYM`BWQrmeocykvMdZZD2x-2T^%=@Za%d7o{1-O&FM9=iuVf z-5bxuZZ*sxxbvQXpKP%678_exy#zJg-*LxoLcFTxvn>4SryAY?$K z+`MeXKurVSpkQNX_phwv09P3Ta>a0M_+6dP1wT1Cd71SXi>8*=-DSJ!20|cRL_uP8 z$57!yyq<^m%=(kzvVfbryV2KNdH%FcSS=r~-vYtT(^8aOU zbdEE&uzTz_!$fAzAHRAn+%?ZGQ1F+w39U(shZO-yj+ zDWnAC<S6+^!H1PiTMvn2mlAXB=pB=SY$rLXI#?=Q%K^*1_~0GG_e>; zp}Bd6BCeZbUZx7+}zv{L`FvT{l^bP$abm@0XTrAi{G-Pz+nmy zx0aR`YL86J>kl73{2RQh#8^m5BKM~VgaY0-+Wr0!;CjU~a;W9%(lc4elgP-(NLEpi zhv7RaaVEfnu<&qk4-bB`fz+td)=N@-eSLHcjE+pH2rP_;>p)k*bmFiv!39^OgM)*| z%S}T2`2wiV=f~J`L{K-pKS+-Jv&?||nNSM9(Pbk5tSpo+m%vizxQw$o-53g@u?Ev}Tg#)6!jA&% zBmiaz0v0>o)C5@l*cUG{nnXA_2*Bc$RaQ!vndSC72naN4i#USR1x-izP7hSUWpAy?evMs>o<)>&XP<43w=z;Op)=<6{1SC`vXRq$d3!$ewD5$6%03=AGa;0^{rCB6fPkxXANKXgO3(CI2 zu^lU+XmDCZL_j;{|_pNOQ^$d47 zQ%HNJr}gqkMz#O&jOg2yYQ;2R&59@2AVUB?-P zSs_~#Te50JYZc)J&giTVGm_qNki;@vLD8y+71S7fDW@H%-`1Vkyk zN+MS$iuVj!$f4MmF9X27W@l$p^YfDehbJl}6)Z->qfNsYP7BbAtdNg3tJ3%C^54%n zkt0X^eR&xP0!qlx+#F4`_rc%%vb4B(fEW#CCIczwJ3AnpiI}y6rW;+eq#}swJdap# z$a($1_JXS#O`m(K^3MXs6){ScmEIn9m#beb{b*x%Jx~JD(d5^}@RXF5{U7Hkz_#~z za`rN0zBAMWSP#e#Xy=9c<+WN%<^ll^z)eC11Vb1)x!IkuC=MTzs&G7ic+)r z!RmX08BNZI2qoS(#rV;mf(gOgAuS#9Odk-){in4VSey7ZlQqm3n3&GdOTY?rcXxlu zMSx114@tpCz)dkPz=9Mf%0*=b8FVP=vtwHdDj~Vz<_?~<+z_KAdIXOB0kz}|1 zkvFL^bnL^&DoDHs9(E$O7OP}5XNIu+{L<62U z&?H-?C;P#xe-Y=SKm><`hME9>$#D0se{e8LM`tGjq@bX%y|d&0>JgkZJX~fTfn7A0&~~Js@%w39#1)Xg0W&czHV3x&V~RhtHqY zJalcIK8-VKs{wV<-jmy8u+Sth{`1XlUp!^Yb<-X>r^Kx@XN!F>z z$%`sA9sXOh;N86WPLTDFYT>@~AJIbPdtR>G^Q-$nnRd7r$tBF(J+{9iB`Ntwr}XW3 zAB<@H5jHwr{{H^(^o(?tGL^HoQD)1{yMbf)T)<*bqvsdj1pW({?3-7YN3BLSHq+^c zGBK1k> zHD?>g6%CBRXt9pN$`_g<{bo{FJAe4lHc@TOZac+`MZtdq0Rh2cwnfNgbLw0AAuFIN z0C|~JRX3VF4myBqvfr8!IzB$877}Xi-eq1NE$#$oGXfF>DAv1+3Duu!|8yq6r2?Py zr&1mH#)_t4F3f|5bj|G7HRJ~dBE5X|YOuk1DVUguXaOYRd*IM^)=OJEK7PE`dU;yd z-YzWrXMhe!Euzd)ay3@TD~^&GE(NeOFw$34+&6WZ0wDyCiGb^7U}g@kujiX_U#5tp z5Eunc)$QbUqwCf}?X1t&yOO}z1!rc`LZWAf8_Fsw#w$H|zlz7oHh`ohN>cS;u<8Lz zF+V@=4-|vZ$?g)b&p9tV2m?=90VO4?pa7CPw4YoM+h}{bu+n@WBq@nZTtWh$kT4im ze>wr?*`dF%Tii8$G#qktAmpK;x0yi0 zF)%T4Fgyti{SlrS2FDEW2a+x>+`tfpzk8f#yg5}5tgM)p)=f#}r*TWVl(%p`=bU}~ z_)+;1;kw#C3vyqk_<9ibxVdJPw9%j5)Y&3kK0R26NBfY)03oBmqj|Q|4XeqO|I^1o z)r$b3(isr^zZ)^)PNUZj#GNKde(PNGYd4F*!jgfF)~vIq(f3%r{d1<73@jedlWP4B z6coAvMBcp6AYo)g1HDU7#Y1j7`H>XDJ^kd*1i%aS$IOx! zi;S3qkz0O`+&_N}SD`j_ZMG)2N%B+u3cTH231^U0aHu|=ZJ_|_kL_3+t3^gNYp@M? z2L}g-I;Yi_{nGnv?;5_aE35sZZgP;S)R^aQB$s2eJ^L?YLOspOZ`1*g^6)&w$KdQJ zs-LX2lTlH5*{)Y9+0DYrTKX?F2P*=CRX#0cH#c4)7TvIyFRyEAYEladl0)0=XjF3` z$u%p@umOZ4!75t{cmTM1C*kOM`13jN!{A_&p+}XAf27!bvjPc6Z^eRHx(3H=xj93)F8&*Q|1^XCfG?0K=mCBj z2Hu45KtW+46VN$$6cpHsiUUARU248(zl5OqKAE;yvfaVd-gU&$l@^*-(sddG zbAEKqKmMD9?~t6Z5-15>`jlX@F;Ts}z1;?Gqzq_hxOwfamo;eE5p*p?8Z#Z=Lvq$@ zPadAix^w5w@j?Xa7l0S!LLN7O_XpbpSP^dW!=q0V*L-lvc_CllcZvURsy7H=1rcPA zs;y=vVptqL82FRffG?Vc=Ax%uny*!DV=>eatf?Q#mrU6Arqru02`fC~q`Y&#tt;!nrR5a2ry+U&S0l64nTt*u%=Ej#VB13pz);hHgqV&l53e5!an0)=) z%R;W~(_QZ|F8645wINYrM+Z{s17-f10`VsM{{(=1@k-HB;(sdAzGoY?_}8xo05{yU zKO_gw`oZlAu!1l<%e}tWZW1Gu8>zw-*DjO^Q!uWGtdNwV@X0OV^KFTz(+z|a{7!7V zb+BOv{2>Zg-PYG5OnRc{;fVks>vxw-|K8@h03xjHFTzS=!>q*W|4>l~pVNd|_fllZ z{n4Yye%2=daz2w9h>H5{y5jBNO7>u(L<}hEGBco_EYS13v ziaoVn+B?Qt_2x&QM0kcl{p4v-Z292a)<9?HqQAGVpTm{+O@rwjEp2Vm-(u|Nj^$Nt zr{>~UV=s9s1Ausc#!G%2qhgU54)5GNJ31=sA|@e0x3jae;C%b`YPv|R8jW-LmOZ=d z#7mx0UM?UUh*|ZE%A0|Ykd>8flVfd07A=Ule*HQm`-+4aSXd#C{kB~Bq%zxS{-BVM zQA#YQaU6pjS6@oAne0GzM?0)p{oYC=yA8Pw?fX{P5F4f2N!}C2qH)iFV_fAEOVTYlWn;<@9CvISbr7H z+B(d;@ryCI{MWc54*9z25zK6?S~808cm?xkxcbw@0?Qm0r3Lr;ICwqw8PrR3wM>3Y zaaoV114{W~fz`XJX4ZkR23#uw z1VDCfaS@50o<8yITUt&|Rd+=T3kJB34kVbHyF1raWPQM4MlaixE}we=apnkyl1Z)| z0;BG6Oce)p?Ir}+HrA|iBLT)Vh!D--(|3uhD*l;iDA+;YpWcb=G=^O$|bReg07HtL|5 zv#TAgn>a!AForn$+S@PsYX!tqzRkPm22`)2ojoM3G+E@D6US+eZd^K6&Dac|RbCf< z?fSjSdXrY?40kkpH_cyL(eY0$?1u6n71rO17+eKHnT!1hxi;1<8BGxH+RziOXkk*_ zF#QInYjDR0XhujwLjyMPfO_xFc&sz;uM8qFsTZ{kzk5t3FoTv`kE#58kLp_Fvo~y}lcmP2qlWT_OY-GwtE0A7LE& zaj9wXzNR;)1VywhN^@#x+Piu8-@u}pQm-I*WqfZfcxA^QSA&KhQ1$r4gz?(&yW=h2 zs|XOCiHV8Sw{B&hgf?@x1+qv6)1^HSuoW4(lD~RADnxj72iv!#lGxd*qN;MudX;Ng zBWE$xb;YM-YEMH0Aw-90h>zm+x_+QP$Kt5;YShMFQoGG6^9bpR=hZ-Qb?vE-k0o<+ z?Op|HaITkrJU&sBfQ$dHzNv*O=Ab!CK5?c4Qe*|5&9+b`{EUE^*`0g$?!k|fz%vLy zq5SF}cAIks`O1D846{yE7Rf6y)gV=pw7^sf)}2b%ysQ+`Uz++rzeIAl(tW?>FyOI( z)^)3!52JCUhU5lS@R>X=b4HJY+#ld|qD>$1uifG_aaN0=y#WP9GFC=87n)C|Y{_no znB1i_T6(ZLmHwi)yqiHdSR_xirnb?6i24pJ+2}HRcA2{~+k-7EE$`mDmz`P(Oj0ID z0bCn=jA4C03v;*gqZQG_}*932P@Yu^jnCle5)5p-FY_<-G4CF z;}N?23_d2dL>>1yQW>SE7s`2_7gSL_v{#oplvU&EY^Zlv!`DfSc z6i=c9egnG~isH%qQl~|yhsFh~E;=4q0!V#SnX{f(jJ{M<(^ta;8KW_mh@E2;&szEMJO2AP2C?CsqL;minqdkbWvF~yY9NWgE{^9Jw?AtW75|g zB*l+CSG#@*H0-bPCJTg%#<>bBJ|r;-p%Z^U(@x3e5|*lLmFuaN2n?IOhYurgABga1Y&HvT2kmRdh!0a!kt0Lsv6O>uO!Ue^ zs(M>d`TT#amSPNoD88p%g>GtU+RJ!LBJ?2z#jNj@5OB*e0Rf0`e6zFTGXr5~{{g#2 z#;Grny?2PgPc>5A8wcu%p|Z0#l$XD0(0mt>gc@7EtEJ_k7)mMU>R^eeN1qjDUo2*u z>Fk4;2`$^K>;;MQ%+jG2`&9|cJkd)NtzLrbdao0(Ps-`OFdIzR(JNx?PdTNKplk#Q zPn?M@(KIY1nQVG`i_2D3eSOUMtZUgjXEEfENIiks7mZ3zC}&}|M>ui768UId$X2Ou zqBZX@b!=~Uczt(P=jYDb;lsprJVmFm)(fkkG@b_nLc426A!*+;o6J9FCjTXsd1oQ&Gnf=BqowR9l{W0kgP6 z{VMgu2P*U_V^Zfx9X9UjQ!WR(XVs4scq=jH4DH@gu)eb((zcD&KWpT)eCb!ZK9-AL zP^_fJtWZ7sK<7lD=`M3#AOX(M;>!BaS*_d=>7rdd-eI>~+MddVS;FW^%JRh7kV%Z! z^sB10vv=om1wZ08*LQL8VKKXpXPHeo$fDOkEn;xG^{J^zaQxdh1PF&pIP&u1tn-@| zX~wq}Z_mz!V1(cmi9#J=yje7ey59#OV99gH;p9@$^w>u287sl%e#HK9_0-pc%J|{v ztBCkztF67h7ooNdz3Ub=EGRRSw^K?tvT%kkNOq!cLZWW!mt2b>`-P#~n?_-BJ!2kx z3(LMQkG}V`S0{h9%^8k9Z0Y!zU}Ym`q;6_D6>ilU@PUA0p66snaXqtP@)QY=#rCy} zPd|db(#eR-S&Gx$VWCTprcFn(lLH;1-oEaGnqy8#bcz$JLt{4ve}ans`=qZxvfR5xou@AUc`o_Z6m}epkS=6{3FmA4pMA@%(hX zG?CkebjEEFJ5bz=MqA!z*4<)RJ7>}(PxWAty*`0c&SygtH!SaGj<-7w)snKc)91sk zqfj-0-MrpukC|62l#al4eO=O@X#a-C{}3h3?W^BM-|wlK&4RvK;W-|P^MNd)wGFZ{ zj{32bioUvhk)+T>9AfFGPw355de#Jpqfpud4)N!#8Z+jF`+~wLG|et5j3j}$s3uF8 zUCuquYM095o@rZLt3BvmgNh#eFTiJCshp&A$+_RcNu%?=RHPZ&Np002+K0*>q<$tD zY(qb(b781*iPFl^&}nd?@j#n9j~EKF$a^Pn$rzOE>R+kHIIDA!YN7ITwl(dlU9{jY zO_srIGqe|nZe0I);^2Ivc2-(e7F}Fie0xZa)d&dEL?KUZV-pi)b@h-}^ok38Z#dxR zOX?gJ;fLDb$4#(t>f4XPgr5$N;uF4>JMs-DOSLNbvMGlL6$vm3oy2e!7P?KV93>x_ zWT&hNIZ@#R*L{)Wr?+i%y4M=NKQ6`Mgx34KV8glc#p^r%VW*#4CY8kFGs^8KkVYew zQ^RwHL>O}{lHK)PN!CVi@C=H)KNNluS2$5TMELOx_vp|+p1w$!Mrfk9IU!B;4O`om zvFVGG^y!K(TA$R8)!tfa{@j-~-Kq}svdcfbocAbj9^Xlw9_o+lUDA)sXo22Ghg_^l z!Pyj|+$`fX7bA*!LOFO&(6&J^)S`)T-q1XA6lOJvoXzJ~R8$n3mKO8jgDg3}6Z&MW z9U9bhFsfrQQa}h~ZGF)&l8riRA?BVzVt*|PKl>%eHKS~ z^kMyhu(B!h=Vq1Cl$tShfp(RpzFNiF(f|VzjZ@*!?UY%JIz3NW`=;AMcU(|( zm$ZDUXK|sYFFbXsr98(NkI>9D5u2Bu`@BcvM0mXYRb`K9iaL2p-QDX+{LPRhV@+}f z=PV}c6zxyTg6bt#%j(Rc)s(|U-M=0{c4G|crF>gs0*~tuLanx?t{iaRN>`UW)&0lK z-=!zn+I!JdB9vs@PeqlL@quH9r?8@OFX=X{OooFkq@_{eK8AtMiIf(O+0H^&o%1?T zu0l%q`dDdadpiO=O%NZ?iTv#1^kBTfnF(&%0zVl^#X3#rdiYZdZVCe@w!ORC0gTMs zy&)?+TQr1c1KGz~2Pl&3VvRNVf;xq4qHp75o2YRI_g!N3?dY)CiA3UsCB{9{D_m`| zqE%CXeT6$wcuUqmHznEY7tG#=ob@sWCDh1`) zAT{-}0oUa4Avw4B{GAf}!YL{~xo=}PFO%p8&toA~d2ma;Kf8!DXz_cLkG5#f3MFLzj+1YIa1GvwhKZl27lai92nG_cm zG6^5gA=NcBz)x~S5VMBl<>l>aSxGo1y}Zv^(a1TaLVh}S+PwA6I{qli%F!mY34N8p zy=E$U*Is*LU25pP41*2A`(B~v8vL>`&q}k0lK50Nxt=o3(ib*wm0Kfx5#Jo_dmV~6 z^*SMMkTQ+>b1u^i*H0eYj9GcZ4^h2H6Z7p8sl)0^4IGHRdu~z2s+tE;RRnhi#)nr~ z$_^8&3=S?eH-c2(Jfr;ZN^*XiGX3jpT!8MXUbi=f0o1{D5{et@!BV-KKJE4Brd46z z_j5aq)$&>S)xq0j#`HKn#W8bphVUaZ@LX2cU)+p@V@ioC&gbGaeT3MdMlEY{F6n7H zt6vW^yrVCcPvVB>&?+h_;KyR#cRl!Iczkwd0%R3DHv?#OetlMvl>9%l0PC0>92~s7 zyy>o6Gra%PYO8B_c$Fda`vDupJUlMcg*XwOpWe^#F;s~pJ6P)RyaZc+kU^#{YF={~ zO?z>ho-z+#?avXoGuXP;V{dHhY$&PW4`~;QE-6iFe5WaS7L$^JlK1{ExDj5;&f(s<~&@xb7`sHl(rFaDCyy_|mT=xEQcY zG#__PVM&k87#nfyx|BMT`fSVACfK6EOQdvSwt!uTRgw3G6LLU;?l}Di-{T#P9GMMV zyrnyMx&>1od{`b;e>*Gwcv_akX{iGDI3xducdda2$$bKnTy3mGue089nGJaB?>~NY zbW4+-TAG*yPEF}TZBb-AY+lFqOG5uTp=~vRX<;={EpzrMIEaCM-txrrOaEqrJNh=O zWnz)iE!?dOO_s<_p1T7Y-hLWs35Qw2W8NDNEKzl6cIZ|Y3lBCiu42c&>N<)qyXm1s z-IrsB+NGnf`0Dek>K`v%YC=2{;wy~Bp0{Q!vL?Uu?d^JEFh#5vNLa}i64q;bFHw%U zE*W)A(6sn%HrI%nZk4+%WMQ2U=TE#w7^;P^Nzj_^FfV0JWfkUrAvaF)>s>amawYdi zwp9E=)NylnF=2OCilzjw-(lR=+uls#ucp3Re7_xje&YMbSFmrdvMHQgx`&P!G|{pz z6SqC;VA-Ry`Q~fCUm?Z)bsAz@l-<4gH}Pi^Gxo)D+cUz5d6-&@()XRV!aAN-X|hxBe)H&hhn~AzsY{)mx7mzZ zQoNgT#|5TRF?SAL0nyn+rmH>ows}3;jQ-__ngE~b2O7xFPolwQy1>LT9p?Zu^p_d; z6EURG{$$M2ol{hV1&{l~<0`}kad%qE%gdEVTR!&pOE34Uv>Th7hr(67=6_W2Cck|f zIdy-W`^aB93w(*Gs@~uv#SV{P3JsF}*BNz#`bQ6~tQZ3V1D*S?;owMHS()w-P*KH{ zu}x>hARr*{Tc5vw|DO8(eHC|oU0q!|;p9^y*#;=tOLxL&0Eruz$h)IEM22cuKTk+` zJ+T>xvrXlMEijwhNqL7JPxx43p9>+#_Mz=A(Q*kRp$lZ4nO1utxg81^PT;oP^)xi0 zEaN6SK6EhLQ<|H-u4n1~Ad15pfN*#kHBeKOGA;+fpr&CXF z;no!T3Df7Kj?w#~u;d_EHbRq#mSnz!Wd_i_aa@`O-yv=R^nh8$xt{2u(Rm`g+G`eS z3^9EXZDqo zvXeu%<_zDc)}_|Q&ycyRkg60>sFT}EHux;zdZC1!XY8I_(=pt=JICa?Dm=5IFWOex zhP%u-FzDl}7M$|pQr~aCvn}Gxk7(VWa28SDa_H~@XPE~_nRl9#V%cZ>^q+KwLosUC z%e1|o6Z?-#rc1o25^^DPvo76d;5hW9!ewlU5xE@y^Hf}n;+cCl>F;OgXlZF9|5M~_ zIbCD=GfKzY($*&G=IJSsH8>n5r;PA!rKo(wr-7Yq?PIv4a!_llNKtVyJZQ9Zyu0+t z$i^m$kV%~ysC{>Lcm7v|w{P8Ictxo9FOR?(#=RosLd`IFQMI@HWK~(f)5h2GxZ-|L zRs0lzTMg6p4z;C0BT>$w?rg-+B6Q-;NdQEkNs~o4wWo^E#(+%zX!}*kGgE;%tJlKc&}Z%rdefy z5C0PtzsKs}mN*bk@H5*lU%gV+*N?u*VP?408;`0Np-h|!50R}5W(~Ib`kEeZoF1&t zudQKFQBh^*<&9~!m`*o1!;0*YygUqGZfd90^=q6fXs&14G5IsvbZ(NyiwlyZZ|I439MM$O2c2lp+laY8zAW;uk0;ne zS0f!ub=C1HwnDJhR_6O&>nXIkG0bvdtfzW4hn+#;lfk^8qq;(rX}aq(;DLob+L@*Q zt2xVsG9q4e=6oQ&?{Nec%A`9|OjHyS6cn^y`9cHtQ+i^kdJZ=x@d*e5Qv_Ty!A&YC zD1=2sbi!kNbJpx@o{}=rVc*{)~=KiuA} zZt~*VA-bGUwSuP-lD{5GPw5o*r9I`#gsh{mB9~g9cx#h*`fsLjMOg zy2xV>VajFpzBi8jO#|DbI~&WnO8Gh{U0e^k)SKxsxmX#AIEbnX4g?V9N*WSs$Hf_m zG8ZIytJlW5)F0;Sh>xtleP}|{b^A$!`dCaCvLBy$x{@1bed*~qS6XNF^}0+SyK)k4 z<+NKwu_x2(I!I(S7~v+eU7i-ahrR%ScEM?Fh043Q5RQq-N%)`ZfM?y{W&!+c zKiO7f1K#aU{6j90v$x{P2E!w@Z=+Q&wlf>-iFL5MHgk+K%(Tax^i;~%m*t)1%rhEH z74AhIVyg>ckwS?*lb3cB;j-=7aV7hUnR<~uZYE3!W zNF%adN6p(h&pFVcC??rnEDo>1ja zu9$-XHKB01z_70D2G7#%hFV5Sk%LFoBWtv5UiX5=>DNuPOTMkWBROq6%|qo_=TEMh=URg*%q|`&Ogwexcmu?PIky=maawI3X5|gLr zi0q*&mTo!w$ z_{z%4Vd3E&n5<2Hzz7;&o}b7nD0KIy2!LPscXWuy#l^t|Ie4t7veL0of_sfU)8<`P zG(O>7BC`S?lKs#%hf0s;5g9u*Jr<32}m>_b@RNki!0hqUX;tBsJfc#p`2W~ z+m12(keAzPP67n&Ef0jIrBPkV=;D+Sj?DW*DY0TpybTLb>x;v)EFCz-(zpp zn9kv}!35iap3OD(ss)e2hWiT(uhw>`Ftf4u0>1-&isKmQG+HJ#+$U3wQ1CGvzQ2T< zy!O;8j~}!9oV&qo`jV0o$WJT~bsi7|e3$lThc?+cIYwRKgdV|tAez+-BEJp0x~tVr zTytNzdYw<1GnSB|D%7u{=)`%VG1u6mx;$KfJ8@gTHfBC>R9aU>YX3=wm7WsRf%W<7 zow8SpV)fM$G4;9oYpdBk;x*jFd=|m39Mj7o!_~x&l7mI2t|dKE{=7}bd;M(ph$th(6xXp4B*HIvh&Noeay zh24=$MxdWm!Mjn*V~0|F`yZ^ z$GD$*U^_F%URh8=Sb09cmSfGfn+pHo24l;SCz<*Z?RFN7XhwZ@fNV@5!IVYEt`E>BE!RHL|Tlk`PYUK{Hmz`#6)zS$unDk-^Ih%nA#$p#<`LUM_wl_p};C zBJ4&56h`;^9|z20ZAGS&%#%3ycQy6+PMWolUUxo|avYD7O`A2yL|ClP?s|;d!YNqW z?|-g~E%cTUAE7FF5p&&D!pa@orsaPju*z{eI z6cb&zUaWaJG1hC!Bhw?e2R|+(EcDq-_bn9eL*3*L;!43pu4a^MStU%ZjSDF;_zh_) z-MJUKvh8>_J^;8c*bQ#2Hm2O_#n?+dcCVEPU`;LCdc_i_ZKf1V=zM=uXPiH$!arup3 zk|~$MaOLt&tP+v4npV4z%KmgQ;w6Fk?}H-uGb`Snq2@c zS-5hIuZ#F?(jID7^%pHCJ1q1-1t9Bf&Jyh9tpf_OijI^iB{U2#+Oe&wGzP`)%shtf zUe6=6?u25G1#P^z@#68}`L^Dq%f#w&`+ET{ubwy*>5pGx-a0U;WV^f8)EQ1D^0&Ev zhS7e@xD^)fKqa{GpFdw}mpOjaJ>bLY-M& z{u9BWUSW}sas`5gDFh0p7Z$0Ms{9%k7%a@z3Qp5SZoz+EV$dZfbDW@}y< zsV*?@9h+4X=xT0n#|6&}KrE{y5bB`S)`wH#GdyeO759!28o1{N!lGG^J}Ty@|9CL_d14y}P>` zmy(jwaQq;O>)~LbrCOl{$%w~+CGW}M#trTWT}z>l#!>{B@|>8Mn8jsf3D%>POB5I+ zIh1@ZLkH9@jO^U^$)?fZB*MA0adPtU@=7BzP=Bvx(%5^$$jFHF+#_4t+@1vnIyw{t z)|6OR?wv=*#>S`%f=~rLJow4U$u;mQMQG3$-!i17r3on$)ZhP=W@(fA`SWXx_R>-w zC^iX#lu*l$9NgU2Yqo;D*}C-!!ThhldoN$U9P2lZ6}^8SJvT287a#xS=BB-AZoEGc z+k7`uBVqe_(qo0+1r_i8{QT6s}Hnt}&F8V*ezxn?C`;Ap?MXA|PGUV~jvNrtn zd{=4*|Fl^B4=pQL+yqN@;DT#zZZ>M`+%9`$Wl!ERRX^XI4$nbBdZ(4jg2wWRkI1N(9)i}hx5|c7yaSVKmiNCD$Yy7Xk9fm zM#D#sEIgGL%!py)b=MKr(A)Jbx5mzBO zx!15>*p$j{@(V)*tRN%u*qb7PpZhx3nHc!72)yr(^V36Q) z+i~2z7i07DX=Vk5ixV_RC9sk2o|w?@8yG-E zEG#YMwX`k@7N9S@y{4ESgBd3}!)?E}{s_zoEYm|k42GVeRdV@gf2#(V3N9t3)vRW+ z>knWbPzeOeq$GN3`Mx8&#Bb@j9o5+}%3_ybU?SlGt96c#kCEMq^&9QKt!ZF=^5m%M z#K+@ke>|^^zh)u33j66O%O$*$q1%tg5ON9%cKcbmz)7mYl`ynI980V4q`Cuq46pob z*;xJ#p4)-JcxUfzyR<~JF|o1L2aw!?6@hScksF@JZeS8=*w`*nxvipru&KB4?x&s( z2JXt^ee=!bVX~N*7}68-;h`;XtCZTtPUdqfg=?-ixGAM~8iNDLxW5h!k>9&_?~nW4 zt>{=YZGvyWx^bB2ouhva@hIYzj%*49EDPp2lW|$R-uCn4=Cv4QzGOi&@I<~F*g4eL zEG#T!WMV=^@CgayomNJ6c#FoLXRzF%Ld?v}Zn*E;!+gixjo6dxOR}=E^&lQX5Lort z(b>6GuGkUAUt)8(YjgGL)$0C!l4sAJ!K5^RBWIqLwBvF_kd;b1v+lt4dvRbL)^)>L zO2?&v?s&VsijEur0f#zsyBh1mm+|qh-le$+Ogd}Ywgy}(f>ryuj}O|1=;$}GvBBdt zK9f76p1m$sK8HG{5pPn@%PA_-!UFuSiBb_S)6$p%FPH+LItv!<>guWy+Dc5I_9vniLKOk(9@A@!jf>U7JMP z`(FkE0DxZl9rXtuhqQjXf+MT6Hhs$!{D*AJ3 zxNZSp5dvsEOGQNm)ujLc2;IB)Y;0vEduu2>=A`D506K=35O_EoZ!9wUi)38Vu-Xqm z&g(aCXr4GbU!bI<{0c%CF94ccd)M!W@|V!SXR2HD221s0$;_)}S# z>rV;hfxje}75|iAe(?YG2P=*?J7sq}V~<}#HwLwEEiA4hdOzasSrXPvHASo?3mm03 z9B(c3)-*Jv_V<$d`}@~`afjjL+4JY)OG`GLS9kv z4AN59{v*er{ztMbmGp<(xOfaQ-@vn=AQvuNAiiaEu`ZCzhploqzQGwPi^3ZK53j%e zvjHX>ac&1w2~f(*%dc0VU%4{BdlrTajA4=wXMcSB3a$b@CEy`6ckZa;oV^Dqf?QOs z&0GiFm$tU-hU2eag~p3UJkoSjSL zg2c#phd!3i4kz#ipeqr03}#;E3fbF?{hh? z1oQ9TN56E52>f!yZR5d108(J>eN~j@>%JNU&zb4V_vh0|50*zNm;p(;P-Hzy2%zz0 zdxAJ7c-?b5skBsM-x*NHuVmKcG~kioVuVW5;EHbU?q1BQSsZ?0zP^;$7EqO@0xGh> z1fBhzl}m^mBR=HV2#n=1iCEz#^;#X7^{GSv`@^qi1Hi~b)f^@!CIo41ZG8|loMV87 zii!#r;Zs;z!N&)TYr2^Ps1??}gAulU#w@w~HJ285kJm)D#sJ z-$h2EBJf1rWzz(CT2&AG1?l*qAuT8_iTtSY^!#ww zDXW1Ks^&;X^8o(`sL-dRq}CKy>+>jnzUp(^&+>Ua$lMDNMc_6HVqxK>X! zJ6y)ijP#ARe$+}_?sVDb~VF4wQIhO7EM z8wejB+uK`g7XT7rF_3@3)YKFf_k;Oc?K2350!yi>sW9VWdAJM(ftFI2qhAC^3RXkx z?oI|nv0hXpoJG?+`mPgH1O8l8R1booNEWVwy~VsXL*25+n zP)tI?Z?VM7%j*U=cRjFv|A#f+RcE(sFoW!5z>Nfc@d_N02fD ztCH8$^lxsKhLpd^YPjQe(x*=%Ot!9@v(G|8E&~(iAoI!0WC08n1)&uW5&@waoJ0^G zVM4to7!-hq#U~*6n4gaiS941gH;Rczl7xf=RI#zQ&sT~Y=<6FBDzQre(T1etD|<>@ zTs}8g+x12V@R~Of5xtA%?g!how86Zn$ZV$o)7tbOxd6$R-b&J~udl;Nlzw*uWo>PZ zk&*E=pUOwMu?B|Nw>nielOVbQ7e~K%@!K~)yf+^{1ON!gWS>{~qyrx5%a<sSLb{UED%^$7AK z7?|PZy2|dgE%1$P_+jW>swo*E-pM^Ky%ExnGiu~>5D2^T7FPT9`I+q zyct~F_L^s~zHV-+WF|&fNa#7on?P#x-Q}_sgo6cHn4ez-hH9`pR07q!jaolkE8ybd zS6Q?gd|XxBHatuLC50p6ew5A8!v@ zljd+3H-yl^TL@>>#*me5qt6Z|1k;Q0u?*;^{-%)-$oJ@E&yJVxg#nfLJ=`naf#;2 zl@KTqa=4&-@-;oXk}2>mSmjoE^-TB}(otMkP2nsxGqIl7WMomUgz8wB@@q3JnuTMv zM7kmm9$6G2!4fh4RL#Ky)($Hunm;B%U+3;f>JR^J%L zjDi4YhjP-ehVQ!C)5u6t_)Ri0GRRXnS5W__)PC+caBX@U(=AXA`T04_Rj@?Af-#GA z-zGWU%JwwPH?tZkC%I+Z3Oo+1YlFpFz*^CO+3~i<3Is1MTENSCczBR{O;x%dKw+Q5 zLpNAUd-LXHSkVI&WMQ>xyEs)XL#$iJ&sz{Ir(2`_Z6@o!G&EdT=*bKXg!=e!I|rJT z>y8yH0U{(MoE@#I;&5~VF(rtCpT2)j0*heZy-PXP)jX7j($t>E8?nGA+~DM_6*ykI zgjAzZxj|iTp^tKU!=(-Ye|&mI`EYRyGC@E$8KLWe5;u=xXlWUkk#QXn1VaOpqhz9a zXqcEVLK$Rx7Ao+Cq)wvV0e++LXl0}VI-cg176%?STG}&wE}O44t^oEk(3qy24&W$| zd*sQP{{DV+3=AP)iWnFeH%vROY85}ew;%kyM~_DG7qh#34+r8p)YYzjiUORckDs3( zM|x>&ELBgoE?W!ZC@DGZ@6U!%dF;X%11c0F-69@X#^0Un?cdUqS+E4*S^~Ex87X&K zPvHB#Pfbm&8eoNsj=Fj(yM&ejF!YY=tH{{oFX^A@+CCvT);Si8|)zU$!bdC ztP@ho1fB$@!-5eRyo>*f>KT=kmC=Gn1Y@3(k?}I@0e4)k%J!36w{AgoeI~Kc(9i;% zs=`9TgY6}#x|81qLLt>`ov@ghnVFg|U+!fe=+UI9C@XvA8MnbQh6g>mw5U+c@1>7V zkrT1u%XegdJ7f3>;TJ%rsIoG__3PJ_SU!do2##RHm5JVBQ2LlOik6a<)nh`?Jq?Iq z?bw$WoINfcV9CMFnjb&p@bU4fxw(mSbaY&XF)`c4N}X0(h2BPXrz$c`pXc;1xi@g* zuWeCn7G+HXhf=55z~EqUJ-xU(er|4Vm^)}?Wd+Pe6af5)wq2lpZoKox^p~Ci8LW3jyscOYXDfWva+gGx|QTtflwu}rmpg>#L{frpxC3Z8g5Y%84Fj<@Bp*v8_Eh{TaVdv#vTb#g-VDE)*1SYU> zJX5pi3K*A?l9CQiD4L;D;X(uc&8(8~I*Ee5qZWiKgTJH`I=uJbZNR(Xxur)lpb`*| zLjj0{g@pyj_TKL9eauh4wqbUKk8N$gRzEvqv;I>8M!y*u((~!Oz%?w6 zR#73ZU%!4jHl~ME1In>B>@-@?ohgrYrS*zf7qQ)o{D*(--KzPHPyzP$0gx}zXTNl9SYqDe|h4yym7YzW_Fj!PlioJHP&2?@01q=F$*&s|+gyzAd-J8XXA6>#By;8pn(T;S^y!~%tsl<>>T%Wpht#J{dtcoBfQZ%|Mj zz=<`$Rj656u@81u#6g5ncQ6XpFMvZRP?FqqS}}Abp|jWsH+FK}CC>F$Q_)b`*$+KM zX?5xaW&|0TnUJK9CC7R^kB+8TTwH`gjUb#b<3KI+md~IiB_{R-_jk%)2aDLC%Ixau zV3Bl>n3rmr|U zIxhVZl`^gQ+o3N@d{yN+d-EjG{EW-Qt4Xb#tx&)+j9C>ptAqw~UAMJ!`UVCzKfmL; zTh$iV`(7pq1>QUVmx}q{Pgav^h~)tN`Ui4~43~dSP;ISAZF3WMdOoQ3=oI)Y8x6?Bk3`@#5v>9r!l_g);MK%KH`)5XOtJ zaJX#FZvPTZ`X^}oexRt!Kit|)zbzy@4q%kWocj6mKZe<;nmyjq%L}|uar<%Hf55~U zf_UJj!i{Pj935ebbKQcov-9jg0W+-Yt`Js1f3EiptI#reZQ}DUuUz-ZrsWF1_`vA1 zER_ecjM<1-wwZEZ9^k)fnwpb<2E5*GdB=Vxn#bXJL*dWTG^uB24u3W{dv5zOW|@JT9}gwgwM< z8dT#_Q9+IeKB2!hQH$eB#HNvtu32Oy3gReRJG(@4E5Ot$T(*RM^(lH*VBTA}gr(pE z2y6eyseafubgKUh*$?<9LE;cqcq#Ah3 z&tRN)_x1o_ppbD{Ac%AOo0(! zjxoRqi~JYMbEN$qfJR`S{c&P)5|^0R~t?$I`9UTf#qZ5RU-o@mIGP8-iJT4OV z`7=(1>(2Q&v$=AYtu%Wrc=Sd=F+Mi-6aX*%L9HDKYmt=5NGU0)N1DRM&F`K8Y6g!b z0AEAL!V-P-C~?yT00~TOm=P5fMF$SDSPVpqFbadk_Yd~>#eplmuJR!~-22@-;y{D1 zU%!58LlC$-Kt;vImz|Me=w?YAOB|Y0$Dr?KNi_;Qh#4$^pXqI%#2al>o5W+UEDUC2 zWo?B?rES@?^*b%xqr|@)ZT@agrl!x+rwF(yEV{W^)}yeNqOtP0x9XSxcvl|X zq8ycM+Wpa!VoJ9=?hg?hC_HM$;6fixg2<%}1m=!$e z0@UQGLMm7)Xa71$1mqNU&w(=4_!#HJ0!d-5JXBb1e0vQZmV&{9F%qQ7p|bq9=8Fn3P??yLsN}pE?q4q9 z9P$`&2f*Z%A_IEr>XN!YzS?9J;kF(LXl|BC$q@jX2~j~yL*c5eReAxVlF$;K1)KD?*CUfh61 zu^mh|+@(UQmxs%MEnlrrQB-_E<#~t;MRvo&2+Aue*xhy?!}7jNZ1olPcrtFQZ|hS{ zFbM%rHFFCQ3W*x8AV1Ro1ugcEB*xF)X{T8p#L)ZDGcZgp_UAp|%0bWk1+CC^&3ynb zV3#+zLz$70F}AW244xf~Y#9y+lGrNurpY!}MybNX!#j)~bvJK*5xI0DQQ<#448X{) z&NJ^$a?M;7W~1w1Fn30-+Y7tkan|_r~6tO=sy=RqkOj)D?EgfqhOoI&zaR>;!8bTS)ATqK1fv;cVD5Fq7*zUNo! zw1N${J4)=(fN?gwj^%j9H+57E&uh!gCVqyj+vQP}5eOUr{55<3(=jP};(yHJiZB{Q?T&vWA2 z1+a=?NxKVLZ=SL2?~{6A!1(nnEwMltflowK)6+wU=$V`QPfY0lP6V1|j9!_Y^#!Dg z{x{W#b8_2!>=ztty>hCU`nUX>xn@BFk;#dP*T8=O^n?Tn0^RnRQy2v=Vb}|(v5VKx zywIjUTV*vc7Jvz5a3 zZz3XKvgY`~N|g@?0b%O~`#FV*=a&KX#*pRP!iTc@ii(P7&z>Fo=7$G$KL3l%c>JBr zxCI_zV`H~e&IFL$!XYJvWvbqDKv z6T~mU`WAtzAj;TXC!gQkMi;Qxz(2MEC@Crb4_g7nI7j0?RB*~s&YVZ&j_!hyT80%< zz;i>W-|>7m%V(aYkopa7RUaQZyMYi+t@!ar9TZOc>1GnxClKzXCMMDe2?>o&O~Lav zs79?;=Ewqu6Zq1^hF4I~CnkpVfr|awgedSQP!C96ULKzOyuGIQ*`ohuV8g51=B&Rp z^!nB95+;yzBcqng;xpHyGUX?CcXv(jYvN&&*nAhD?xOyLU%I;qm{l?m1hz~#*j}oM z;d6x@U2_cTCsxO6fN!$es>pZg8Dcl6yDy-sto)^;<1&mVfjOY0lr~cec$9ZPLwV}s zg9f#vaB0P=0Rx9S%uu2(H}@vo)B}-8ShzI`@~=I~0miQx8kpZ6HJ=vd2hKi#V80{)WzRP_%!UtXi z7^X&pXegQ@b2@*e&*T2XSB21m=-#8;&EI79dbHVxZ{I{j#Kf+^2$2W?Zmh@t1%SUb zFuxMa((dk)izGKcb??MG^$rF7C12Ptw7KH?6SH0UmP48i+*AjnXL7M5BQ5PKpntGC za#wfv!;x}lwG!Jzot=)ftP&XO_GZU^3HsG@FkU6?mb_)lQtzAFUAZ)vnEv$X5wq#a zdDHs`2d9TLE}M*L>FJz0>8YvrBqdJ;bUi&iU!0ZrMI>&X) zBs%U}%J4K99%(>CisH8ZT32^o*azDyAtB-8l!Sy_0?BqSsqP%#rK zN5|cJ0SQ`#un~=9mk@|t{v&cENx{(u&I+bN0?Ig^Sv2xBlGFTD_SH8ySlrQ(>oOi5 zEDiwEF-LF{Q$C)M=kb`}e=$0yU)3-g7>FEG*yG2Kk+{YN;O?P3bVI|1GicZ%E-s}y zG-MV5Db(nUOia%!Dk^ALd#7)U{lPF6iQ7+{rz>=Y=BpPZXDx$9>WXO!NK9S z&BWRL?Ir({gQ^plhp{%{&xVS?6C#15IoWso?k?#oqAP^*i3)xZIxZIg<2pTxpaxMi zR2kl^;P};>YSAiHVXm9kzX3ixbIv1nz$ty6S*fk-w|x_^g?R^OIs6L+ncR1e1nFr$9pqx zVq$`bbe^CfHvqv(J;;3V;!KuK1(Pya09;{#zu|iEwFaSs-l?d}TuTH)RZlTriE7((bdin}G zdpq@7dkyW)o4Nn7>+j7H7aWM{7M@ne!~0sriRrur*u;JQvZRBxW`Nc8W*QvD>yxS3V=E4_(Q%|U~UHqnX3%*rYVDnx^b z5-c_$b#;;v&lC4|QBeyNAK=*n1qHk9&-+LkN*=6T{vX1D)BmpZk6eHshtwM4;^Mb& z-=+o@XizmYHb8RAh?;`~ANcm$PgbdggoWkR)vr}hQc(qe`gC>98Mxfg_`81{J$#^d zKcc0jvTMJu@j(D4O`+Y|rgjIWA2QnV*FJQcmQ;Hxrxo`0Ra zkyLy|s0;Xh0B9}Rb(kp=9`=5^ZZMkd(HidT? z_8;*|0R#_rcwyC^w=M@k6wLXC$PU#~T3WDrvvqr!e;fq^&oJxiMP18sAp^pd&huSNYwy4rss$2=6v*Br^l0ZSb^?z zbaa3;AqZ?+l9nbpT0~>!;9aY8n3w|AaegcIs%iL0Je1QSo#hOuTM4o z*OBE9o_O$(FkKL~$O0~P9FYA7L3`^>Y;cbPxXJ=94dnc6Br`fH|Iwx*RB-n4@|x{T zz61lzbC`sXJ92Vz;+*|L-BdCpyZD<5fcY_B9x_kMCh9y_vYqVmy_UJq|Io#xf*>K{)lwRrS%t-f> z_G^ks)HiQ-P>V9^Jr&{rxC7aBvCSmhbVs(l80E!(mwEkbxQW~Q`qZGxEeM)F=jIB* z6wk4QVE(V!RmZQe$hh=Cn2J0FV*rmB;qFjY37_lsx4F*bt!3Jwkv`6dKlVO)hpMTj z>V20z>KM(*D>OwiGcyxY-F|1329l(R=Cc66nT6Yuu(2(0Bi-HIq-65q3hL_rb)Z0< z=biH78D{$(yJ@)6VgDFlefjDDrmyf{Nyz!{&5=lEp(zcCz?UNiB5b;q*AF5?Lqqu^ z!eP%STCsqq0M@Z7d7ZDYR(!1>1=koU94qc9+OMs>bDZ_nrko`M>oJOcwme~TOhBM`ut(vSH1q6028 z_SFk>b$eS3;3`6W_b%Dm+8R_m*4MuRn;GV`{+oj60SfZ$-y0wf^y^XB9skR7Nwa6B zreM3-Co2^@n_%*U@DW(V1do8(DtE7-o;d@tJT8t}SPQn8fH~=aFH#ePUAS-o9UJ>R zau#q65WfE3<_cT{J_J!3_N)DKbL9MdWSLP5Y5CFi;P=MHuW-sa&3jDBDM1VlOqKYm zVFhM8%+{3(zy8e6?*bHtfZGFQE0x08Iu#djso;T=)2KTUJ^j{4!vDi=2*u1lcSH1E z@6L|nQc;cmhcP|Fkau-;eH$K*Dwk=zFg8YAQTY3;4gk`v``^LZ2J2K1kW4P?k&Bp^ zm{1QIcHGDhqOeSby|jSO_fAe``01U?gpZNh#M*vzHAtA=EZ|?11;k#TZKotR7kV!N z$596$1VN^zrk>11JAL*za(UsE;Y6bWVgM&6r&9&zw6rwXh38XJ(mch`+GPEk*RK&{ zW8<^u&%-3kCwo&755a?<_5pbKkOoj$EWz#$=dF3=xx>RlH$bIe?E;uQ(gQM;9V~cQ z2}lPz7FI1FMYyD-Y3yE(|959Kz5xMUx9M-*ybNACV$?dZv|6Wrf1@5#6a%;>Y@k_G^N!Bi#KX!8G2 zazw}0oxg8^Fc|l=MYI!Xk9vH3Oe)GKFNObq+}hyjD)QJSO&&nv zk}ekKrvG<&H{kF(JVpT2K@=aQ1N{Y|{2hq>pFbB*@ZkkET|b@jinjZl8& zdUd{LC!Sf;(-mG#t;r8O4j5n+-&0m5$jHd}r86%ZXz&esA*F0r_9rwNDk|QvAB1M1 z#l43QKhm(d>*nAr?c%rTA_)40tR?abr-A&kA!fUuKm$?ywVHt3I@2vfQP^K9MLq%M zCBjU7Sm@`vQUU9bAkXV7cg~}kyxI}Fr`;`fdhGFr*raEuuxp+@9=64p3>FB25L4#3 z^cA>YJ$?P>!(~o(hjb)#>?YdU z+Ik){fQQQ~(9H7cc+#VdY#&cFrS9b9&mM>Fe!|3jy2rKL%I4!t@jU4dbCNLSMsslS}NJ~q@{&~GW^D|>I0ODeRu||p0 zFrWua0IaEJ`PHd_X#iiNNuj1WX((DJj(eRN?vl1v_9q#qcQ=J`hNr^^s zC*sPYcsKYPR0Ms>DDB9-8*^I6avx0?eWT||)_s2YlMNq%RFB;Sk?tJ2a2!^3?%M;T zPyMIQk@218(ahsq?7CuRZ5`avp@4t@<>iYPXOOY)Z)k~m>=}oKhfxqNF0TDrOg@Zu zgZiMkqv=hYxpYaB@+_wN1Ss=_52%!hw7n9UQoR~w)_Zr$E2CbmmX($*o}^OZPdnhG zX`Tq&WO)-B`r_V;^TWM6acFq|BpdTxnsx^cIJmga;4VzMN~VyuHigUwInJ|F)6+s9 z<)927G~31gyd0M;vkD&D}l1uTWX!zi=!dm~3`A!M?Ip||+ zvnl4&qcuXE?)?1xAV@XK^#p(dcVhr%{lQpavpwLsU@kwf`iZVoMZn~qgJ=cL25b%6 zO;h9&U?N__{^#Lsy)X8`x!F&Yv>GlKiyfr5^5n3zM%#b!*GRPQ0|TUhYxxET*Moo} z$Dke?sUAJv=2p|t(CNmIPx73E8snZ?B$mg~r5W3HxX{1>Jr;_Vnh>n^z_5 zrkmRV&q&Y8V%4s6Q}@B9==j+X`eNQzBsOxetLxLFrtmp1f-&k(R5LXaZyC4F-W}Zw z;y>OsNCY0*sp=qlxwwW?{=uV1iD1C(2Q7;ltcuKAKimn?+TmkiVNrH+D#F0T2yoppmNS-p1e{Vg@foybFOinv!R?%*7 zV4$m~C+WinatB98vw?imfdcagkD~=$^Toa#m-*CWC2j4@JmWS%G$gmSwwPF1d*0BB zcXf2c_vabAvSze2HFdIitYHF@lKT0x95CaKa_0@+mD<#j;y3g2W|`V$TvrEk=^PvL zgD@HjQC&vUtNgF*B=hrl-6Zqn`*}v?`}vI5SZX=EoZK6`1&VeDrMCCdWP`txGQ`Wa zPzZRG+uGV*l>m+w#D$^odj|$I!rs2UA0jC!nQz|9Dv^a*7I9r29?F9;X5!=1wyxL; z*U;2-82@?>+?7N~IE&`A>6zUH&Cz|8?}ePiqA5R_1g{ARv%T#XT%@7;EX1YfWkIdy zF56P!;U|Zy?Yr$T@$CY|T}SC#M$K}ru4RB{T$KQ%7GOoh)o5O41rUzMaDo4snVOQU zx+y4x07~}t00n33T?ICH9=E?PDzD}%w#gZ96&)ST#KhFmlc~w+Vt*ps$`$p1%ShQz zqj2hkLEBGcB*_Z%q*lwcO_5C9e`@&-qn zmQ)7UQzXBrNEI+Lm&Kg=&DEMqQnnQ597Ye43JR3L5)b{!)6w76_0x24Xea}OUm#RZ zEh#A(-2hHWXViLaqLzt`O%<4gj`I{jSVTm6S=r#mKHy8rs;V>2L%<%k7J7FE>p(nX z4Oa~^ld{If70b-Vxn%cfPUQ^(( zpwbe3SGA*Hu*lxQ0j^BPvWihxd0zk(h_7L|*KCA9A*+bMaqcLmjE6^MPquD$iQSCZ z%1FgPu}y-G=aIuwUyiVYgM-UjEfJXd#O7vc3Lg9W*REaTK2pE3PudR5KvyPtXR_g7 zXJu#KO;ps2iRt`Eu>-&mmz`lJ;Q;~ao~?>5YTFaTa|m+d+a1f0=T%}Hu!&J?bm&zF zd;2G>#(;cu)%p`TOf?c{mp_pQA?!V>a{pN&{OYlJO}BwMNA>KThVM5v&x706@k+tT zOiSxH+8NEJI+_)?<%xFLXyK-lu$yV^w)WT{qob#v??{x|-)r++zC*iZBzkBlD){Mh z`E9q9lqWSVBop3lTw{29PYH5Sm<`XMV2*9GoI7`}v9Xc#Gr+*Kj0|bVGVQ>?z=7OH z{@}M)CD_VWpO==Fb`1=qd3&EfS~M0=6c!eSz-ca0<7X~nLu+YiNh;uRsOLm$m=!yI zAXat3LiRX&%G_wfon}^k^HqTbb^doWXah84pY@#sO@x{X%tc(c%LpZI#!5tZOgRNk zjwJnzyuBTCcligHfz5Atva{y82a(~d+DsBm%*>qtPB)jVJr9xuFq5ZIJzjaCe9?B> zX5ksu9h}hWHHgyj$D?zU$r)Ll#<6F8RV&2xc;WRW_;o^DIG-z%r|Src2^%=o+Y@#7 zD&B8y+QV4{o~i5E8ML==#!K6dzWL!fj8&tsXqPGxvFUUHr(NK(H6K?hO@s06hNffL z%yB$x@9|}>G4$C-swig6&h=Zno(i8l-PQ&c5>HmwWbWMC!UOYj551ieX8QIvhB0?{ zb|wHnVRo>+6!NK_%2NyWBxr05>746YpK9WK^eXrTzDFF+xkDv@I3*NvU9$lZGVaF% zljB(lFZB7fAw~&#^?t#`RpmM z3Mdb;)uU;R^~B?wFRshD7m-!2-3TytkNMeI;zic8&6|Aj*BZi|I<{(?@f30w4m~UE zx3bkw%1g7##t!wG9mF4OSSfQS=x`XF85iaU&<(CGSRJtA=Vyq@4CcDwRhEA4m2YVt zp_f?>tGBGb2qezrY3q8f-|4MV4Su;!hJql}H`QfSHrbM|Mn#a;eTZlc_Ww@mLmMx6 zF?ZN`i(^ohzxU)i){cA|)}{NI30LKxfTbwHmuxx4g8Rvr|B56H#%^j^nPw3P9`u}Q z*rqpUuIrEx^>|z)Xn%|KlIl;h_5Ui=HNlUCWU0!_v-fEWzPv)V>h1u9p|^I6(MYu{~gZ&*{Ao{%U82dfxdmOkX*}GnIc? z4Guv(vr5Jf5SecERvjw`^RD~C5_^fX?Cf6XC3JPO-4C|s{1{?hcg|f*Yr>De_gS4B zMcl&WXsZ{k43lP(rD&OVwE1RNtpXR0%O5y+_PU7ItT>hXCp5|@f*~BP+ZIR1J5>=^ zmqscyK^Q2nrS$@2|$3%(9Mn*+SN=i=KC^vrLgMjDAibGqpT~Uc>bji8+oVGU; zU>#`+?iDMyMwjg!&5WFMR9kMkw+!-(=oAg~$l+b<7c{)`+j&aQa=OYKEMtd5yu16Psj}}mZ>cDaOSdmB?c1=hL^k(1 zsTacpBA?mZ#xY+EpA%usMbZ5e4MM;taB0QvE5tUu%rJjfTwLsNZYuV8lOc96J3T%0 zs{8J^kIPoKDjjgz5-|x0Azi?kfBN((YOd0!g;=K4ZeeatURJhE&*=BA6XehiRO3La2jz={veYqDJ8YFmF=kw2s)TdRU4Zea%>;K zUf^T^vc;Q{5KoS~l&~TLARBplpUa}}vq!Jh`Gr~{-7YrIJt+wVdHFZsB6Je(-@kX+ zY!?rE|2`EU#zMbwEY^OPR?w+~LB2Aj8Mh1 zA^FZ5Mp$HA(#EYHE~HpC8`g-VHbt;Sxh|K~b8v9HYvVs?HZ(Sl+TVA{Gio7K)Yi5P zU{6X*YlOX*R|@Nhs|Jb+3nM|)NMaCB@_77t!}squRw{O4*z4ZCzhxW=77us>5a{3r z5ab>C_{e@Stg!@o zuML=Izh_p>A~pz6FLPv>Y{bEr<{API7NN}F8Y{4(UT;+tm7AN3Vo9Q@AC;Z+F(;?J zIr?tzr=+AvS%D*txWb%}z!bhK^N(-81z}ECmr`wQ?OfUDQI_M0#1$jJEP^TVuh+qwV}Gb^j@vP=QsMwuU& z?~;0QUY;TpJNXfwLsz&*N(LBQfz4!Hlo=UwzwdxhKCt1@OqC&SWlL*oRUx70SFh2~ z+*?{&3ennpxpqT?BO^%(2ni+iwMZnNH+X+5zP#Wz zHCZokoTH$iuz9%AW)3)72(hO3<#dZh08Ah<0LW`rwdFHVe7V3YrAR$8%d^!e&pDl;NN z&2_w6FJLxQYy+%+X-C!EdXSc^o#99SFu2FwDztuI8ScjVTW!1v0EY;Oh@^hq>iJ2@ z#f`9F;}~Z#Kx>#-Si0xC)9Kg?FVcE# z&?tWb;6(g&EdDbLdNS+Ey(9paVd3FPbW-87)z8jo6k5E$nv08B{)qPVwYJPtQ>a{r zI|NJpdE!+^OV&qbO~scrf8V&V#Whye!Vfs!IdqQBO=21vk)))gZ=<6#^Yb}4xw*{& z(d2QMf7@2bekbc_#WYN7Ey&D_H%;-k#4J#B|XvQF4qPPIL1G zH;8R+Y~@)8u#`)|H@F261Z5BA0+5hQ$G9%D zlW|$xs3YD0QxoY!>GECr-Hk8!`1tQY7*1*sU}|d0?&amhKe#`59LPO#gDa{9ViAbo zLqkIiwwH&^1K6j(zoDgPV{3zNWP5C-PtUd|JlxZXtJ2FIcU&F&;*m!da*CdwyERnO zwzjz?N85uBz#4kbZ4E%`#9fL@->1m!Q*v_D+qd{_9tXfrTL(PUA~6H@PX;DuJv=x* z{>rUKjrgI_(UycP8ioUdgMsV;EW&}^ePiL_;nTo-4;1U)s;fVT2|WVxQmspe76ZQW zmBEjPKc9Y%$2oWU7J(Nd{7Id`D1riCJQSrl{UkawhCKW!s3!m0ue=h%hd*&t{(p0c alS{nyH#{zf>{-HpONh#dWC`g#|GxmdLP2W) literal 0 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 literal 0 Hc$@|}B0EWG8%nR~B{QYXq+#0eOJ<{8$8sdCW_KOO zJn+(=%rgV$9N7*9O&A_{!;)6J=R14$I~N_7ex0hUZvOTzg#K?HpGWxEl~DkRw+Asm zV>tJq;ei5Z`_L}&WCT6{eDFZ}u-NcHd5n#M@=5B^z7oV^urEiTF%EJR8WW((w5w48 zRe|;ekYgYbngCe_iNbM2OP;&{Xi!c^sJF0&kW z%|iPU%aQcwAin_lCCD4h_ze4sv9B4s`4_Cp*f)jyZZWn}h<(f0Y9Y49SWt-72vd`V zTfaNj0lw+pfF7`s!5-DT`vA-2WX_k~>UGxkFv_TZd-5C4u0^ZMxAygvTd zd3|yYkEiEg+l)Oc#Quv~`M)0ijLGNl;w80$%b+Immi3}9xiXN@;wrTUo-GV#i#)@= z__q2In`ZPo{$5AaN2?wVj)q(I29D3(ZJVg+?8;6ej-vEv<+(6Iir(_G(@dEtQK_?b zifmYOkj2{BwbLYaK1rl2;j4bH?ndyPibT0FvaYPF)!hZ0N@YV6WiHaGr4Ak>N=72s ze!TxUK!fYG`lh`}@|I3ipz%ZzqOP*RZWOwX!3mw4h@K{0H$gUq6RwvjH;#+9nF^f| zOdu1k<;wIQ;e>J90(n$$MH_=!J*eH~9V(Rsohk04la>tEYg;wC2Wn@)=GN_dc)L+{ zDHgq`N`8{FI*p@LMI2Qk(G~HrnGct#ktv833X zQta|cKWOWl_8NURRM>|RmWf_g@v<;sD>~83?|*#7{=QPZ0;ozm*$PtN6!q*L@#0L| zEROO*I8rX`N}gg^(GZ6q)TuK%j#Zvk`nK39B0CJ=uF-9*DmV4fhBt@p{0QYb*&coO z?5&V;PYL-`is#PY+VmGsb=ssYlex|t`Y!1k<`Z;=P`y4dfCq+bU^FL=wLQz_pNspZ z>H}N5*j|uoKgC@WIrSd<$$0;Cnlp7=IE5S07we{TXHr}YL=-*KNvqt`hJ)Q6)*6;@ zcpPB;9NSEUDzIToM5)o*1y*;=P?Gh6yhqu9s{{MZTGnHB_Y*BUv3fv7W`Dt9!C&%b t{fa;4jrnDNsf2HD#vA+SD*JQ(b$`KII{zyDqXuh@dQ%=ge#NVJe*jcIQkwt( literal 0 Hc$@K1h5}K*}z?sD_;pTCv*Mni(PF zSHI*R<%i`tm2~&6L^;_~@|vnhtJ#_U`tF`q;kT*Mo%P?}29SN`@%IRS_SYhS#K(gO zpf=chQ1d_mw0vk4cryYY06usieORpdpghKkpnRfwBv*iF6b|GF)W$#-p*9X`f~0CC zP$g)c133y3p>dECAdxtRXu*@`02Rtfs7*586i9rgLC%nJIScYU$T?o;L0$lP5#%M1 zmq9LoTm*RqBM^p&tK43x(I4K9iOi<%B4Pq z4wq?6@or(TTjU+i=>3(~IKaa{@bfyPnZDxT;%K>LujBgk?Y0RU&feZ>i=!|;y8TQT zAw_Tb>1m=&*jBN#b_yBW*42|pJG*+?j+{?gr7Pg8x>M(exlz)ttgBSrIowKR z0~01L)Ul<1lX6?hP?Wc~4z|jnHEWgXy1hyCrf#dUMvEdqUS-R>VcZ*6RwviH-?A(LPk2+vZ7s68Qz_UsG~U1Yt;>AYiQFJj!9^ObJE34=%SSG z)&2p$tuyRWuZ<{IYORtH#A#N#l<=N7e9l#NMg}@>q-QHm6!%P(V`zj&lxur!P&sKk z!l?IWRikbhRE<*IHFfGIo%T$_B^-)X=0q7w`Dz(`MRvt4hpUOof{i3{TpF0_ zwuN=dl#h&Pgn_mke+LzD|B-tc2Lp+)wyTYFrL=|7pUO$Ik%r-tdRK)UScSROX;Kfg zR2+MC(@m0#ox}Qo&ML87^#l!*j=h5&E*}MT7n`2mJNtWFUfa~&#OOwdb)hVtQkK(A zmfp2>Hojr6&`qSPau{Oc>17oy3llWM6TSTI)k}{4rRwECD=2*&+d_z+&eaj z!nC!Hlnc6&x0qy9#0d#>?2L{gl{O09Rt}L|9;9>E=oa>=oBBxL&0#AwpNwt(MZQoeIa7sQ z-oN~r(p{Wf=yO*2t_hubhofpNbA$FA10I}04Jd5gbQ)ERhdznYXgcu6O#*XUp6)*ng`@kG*@)*0K|+hg5$13oZ-( xk~iy@{84YzpYWFo`1WSJ(T~0p{+xfcxZo}Q^SAJ?xYF-P(VOz{=a;;a_a`jDg;@Xq literal 0 Hc$@q`N_+rMr>t z&TlT=`#i^U_B+P+{PB+OW9+RP_RYH2x~@5YG3UJQAQfc=0$gfb1VIR{UXiFx@E`1*oPj6p7Gb$EIoM~Ekg3^OI%Yk@YJvWQVlRwRZ~P#}MT=mx7)$DI~gY zEpBgg>*b8O&86l=#Ks0W&UIDv_THJZZ)$9O93Ovne}A9HXGy_)w`y#> z4}P30-t03Ub4t1yq(J9-ysfQ`#hdPCu4TVJow!@z+|3nI5)x_H2D7AwXl^{Cy0Fvm znkgwy(YinSB@8N$zs<-{N&fVSL_VC3bD-F@ zeME#yr|{gNdxg&l8F_jC3j2WqdxhlWWa1ZGI&8)!Cc$+zwY9i+^Q=0>wwB6{xHvR3 zq+0J^^ofp+wi&M_c$=6gLn-c-O^@UA>)X$t6=V4B1*@p5e{h_K2RaTn^z7NG(eF|0 zSd!hayeHYB6s`C44p%7{7#O69k4xj6JW2ASy&b*t#6(7ez0HMZb=jM1t&TsNX&HEU zRBW7`De?w6y%-tYcvga7>vObZWRAi9wdPstArC`C30Q8t!IvghQB{3Z6GCCMKHauG z5qSf-C?Otq$(8So$LiI`j~^rVJqoAC$KQ234Hi0Tel*>7wuZ*L++1?If-{1Gg6NJmzZUWR`jrm?Z93k@>@VCoY;AS*wD{Z7yZdr->-xV!KlOupN{!4_jjLBr=2{H~ zld>x7w|{^qvmLKxU}C~#Ret?2Dk`c+ASXLpEj?9Pxt3qVj^Ge zWMN&naN*mxZ{^%&`#!Mgx?jsbB_~TQ4VBbv43)UQOH4c#78Zt8^zK-w-(6ck5YUd9c_L(!&ywv&hD$GT<*kJO-M#gPSpM#NHRX8kT=g*&y82C9l zia|p|V##uFW_29YgbiDvyU)hkYwe}m542+D&+&AZWch5A9FZAbe zL-GJFV_e0H0W{zkKZPkA>8pKJP<60(ama5`uU0=1rUV9^Tg?_E?HZH@})& zZ7mKO7#U&aXodFmX+g3YLhxg?!~YC+Z_H5H2pRe21A+Rzt->-@hw9fBsw_R_@u)BG)w*V?L@v=Or%J)TzzI!4T7U zPj$QD_g5ormPe$K&>JQnm16C>*J4*)CnhHi#%n`kMC@6DgM*2wsm(ez0t2Tjs%4%B z25MP;i(m*03#-j)kqEhP>w|t@_Jc9ftf`uN?PWh(;=>~%h#TX?DDtcZPvu?9u{>Ow z^0RbsxcFR=`GayCuD7>083hFmhlh}5-{XV?dL?*_^wM26I=5*C-=)CP!`->$FJG#E zBwZW*`74>#h&WCI8dCcj7ZE5xc5Hh z%F2pnhCT+e;4F9dSB#hKuU>oq{yjZ2^9f%pg32&jF|8-@fq`@ue2=_8oC8RAhWowP zW0}hwKy=nWI+|j4W6qf<5%`vm2#p~0D_J(voa-0mwRw*0{EQEH_m1h3xOk1_>C>lG z&Xd{L+xwQ4m358SHzj@eP&qhA3){{a#y70{H&YH`zj0p_dH>;qndPldYVa%hE-Q>5 zuD`;HQcQAwE&r~ffxGNUM~B+P!~{J90|o_`cK*jqt-&PmmCdy57wqZp$GrbK+-j~XH6uG) zPD$yB@XS^$ziEcU%uO{74cSj>W4=TZNUNr?|KrCa^SxO%Ha1d*hKzKc>#C`gW@cu~ zYb}!RGBSuuAQsAtSnVmOsDgk~n+bgz@z;Fb^Kf6mUGs6^WxdiJN+ZN`zm>kDqay)0 zHaRub59`>Q$a({&6~TL))ETLTI5{~v&YW_u_%ANR@~*k%31yv^i-(OXUj5FFQfJ=I z-X4>vC^b1bxn_|QXJTSv!p%<+k&(XD)pD?PQmN`jKv3Tr8hn*lWHmJ@$HvD;$Hy^2 zRlwdJKYpBELV}KvkPu!V3r_%F8SYzF^_pSM{IjLI~fCmxB0r7nm7g8 zR)*`G{2>*=EXuC~B|LZUTi!ZPmXUEEzoold<2B-bbaCBX1WOF#fx%H1SHCa=Ig)K7AB$)=SeO8ggW0MBn({y&&JyI)x4=`C{=)OG^WTf*wJ{fo{vR zn^Z&-L{N|%sH(2+toM__B4?xFQcpME(}SR2Ha9o(y$(e6=vdLbNhExCH{@cfcTfL` z!Fw;<7M5_Ri*LGqy4KBQvLdIJ$Grxzwep=keFU}{&~|xqvo`oNJA%;B(c$3Y`UC`E zn>4=;>gmz6%^!t7i?_!@Y#bf^fcAe05$@vUV<7NHXJ>;!MbBIxQS5j&<;}okR{2N# zy-4*tQFwQjI~Qw+(MpeRlMyJ_Sq<>1l;Lo7@#GaPscE!1gR?vd- zYgQHpLO?)ZV`o>%-*V|)x7F%I{S`$;vtj+a^&GgWjP`=whx^Thj~a>p9RR;+=3>3^ z5~QR~O^#(!2-BZ#eLFVK&=gzMA8XPk5dDi^0<-V*X;Nx0nt(hlXEG_y!Q|6nB_1TW|Wtnf>#fkP5vVqzf0Fr~%^-a0xu0`%vzuH?OMYR}u> z9uE%;38@0L?WgCpb9vx!`dv7xPr<|meEeuybiys&c9)#*ePJPWZfWVZ(*57pTHy62Xl)Ka6+1YtIMLqRYUUx?a3ayY=HTkyV*@dS_ z2d^6%8kz=3nFRjgHxGwwBz zSJ%`SG`!%HKYKJ_-@+guaNGQqVv>){+j4LMyq0|zlhxP|DP?6sAeg5BG{CiAG&5yh zW3zH_;Da7S=~h?wjZ5?Pwu`W^Fg-Un5%?5&ATsv>L2-IF2=!iu2r9!r7XF%9^}vUu z6!SIx%hwMNx5|t_c2kPjy%*lS843QM%Ja?szDMIr0X%>!Y$U&^hza~2tkZc;&YI^J zZbiI$6_T8MUK66e##l-U0Xzy&IO|Dv>!WfFP!)2q`4s>}*bRxD%rEK|D=O>}5$kLGM(o0PbcP^q3}+G4o9 zJi0&<4)Poy?f^j)6cnCEMPVSpAtAh01Hzeczqr*uCr4nyt{{J~zW$_H4mFaXo`NzZ z^6+0g`>51&FW0>BH_0#5eD9)G7u@x`e@)yzE-tPuMT1*YORKW4kNVD?J8qWhY1%=M zhG@uvNejr!b9VQ)B#SIU9Sn`EKmLPoP5fu|#u4?#TkF(v{?A{$aB{*i_Wx7ee9g{z z6jg2bz}#q=GFHidecb`_c3sB~BjNq~;|IGNn62CIvobPNEHu>Aju&VXva+(0ojyHdX)XEzd_STB zs|zNS#)Deadgu~Lua_>JsjsicAtF+6bj-<@)L zrylNhm%ViKm^$1UOkeR_uD~{-1upH*ToIV`E2!;$yyB?sab3h94W->J!BX&4jj{aL zj~+d8>ozwuxOW22Jm|9Fxxpzdw>`cK7p}h61D!wte%ElRJ9y%nrb3e@YBbKlVzWiz!s}H&seP-j2TjBC_3Kx3+dX$3wEuS`yf(Q^ ztNObNiSG|=XY0r_UpOOq@a6NTn(?KjXJ2&a+~;{g%UAvQaSGtI?(4mV?9CR)kEc(c z#_$*%L-auzqvkY**JyE&K#^yMwheZ8%#T7BeTEGzcD^n^MR@h2Vecba)T;Gcmxbn- zcQc+pj{{k3AqNwm+L`&qtw;fFQaqqbE=Y2~G^O z+;sNUyT7g6lY0h6C-7(vo;Atb=W%HaB4w?vxN{o!#K7PnFZica!NL|sv2lSbk@10j z{r&G?!5Ye{>REr+K0B!J#ewP5xhofshOn=fX+B&puGJtjpA+cuTCFSU;)3{6Xn7;P z(r2C?)UWF{!;HFUJaP^sLHzDj1wMFY*R?4IX67VuLk7NUg`Rss2tba}zX&Jui$!V; zM(~GlhYB(KgXLyz$>NQ=pl1u#!=<60KeHj_sdw{irdt^RXU%eA!BtD_&GRFnOPP># zMO7gx3ABY%>gwu-&96mVR_j@7F#I0Y))f^wE%0ru%f&S}G^Aw7((_mUsiNEUFT3^6 zCDn~xU}q=A?)#FSUYB?|WMpZH`*6i*XLVAAEefr!X=`gQx5^S3^ygY`En;cu+jS2( z&UIal*JP<0KHL<#r9Aky=Pwl@>iagW;KbR(6D5Vt?bhBOv3&J*6i{Z_msoxn@R|5yt=lN z@L!t4;GU(;%xs@_;3fbO2#m{~o+VwIOQm~+zj3vszJesy_h4_!`M=TUnPZkfzJsGB zmmE+)2v|Y}VPVbJ0aMjMq&PS@JSJ{~R^ z7865RA~-WMlaZGP$SPD^QnJ!4wlpwT6wxsylMTFnMOj&1S{mbx_o1uDT9XiL5hS_G z&SZ2yb3PE02iPxR_f3xGcuAsAd0)t4*`%A&Z&gOdYC>WJEvePmP9yZJtk^+8K`1hq znX##V(PSX6H!v^=3=db()umfqU5$A8vX6`RuL1@hpZVQy7U#&#XIK-vy1HDB4z^a% zIv)6qv!3fDT-x~wzhvmQ=4N>(C&9zHvcoyuVgGZHQzQ$$S*$m2-Ll=BzoQf{K?{4s zRasft$1b=&+ldF)Ld!_Ab91(Po0j-zgo&?Sy$Z_e1oGJ5-w>b&p)L~P(9S1@7Xk#J zl{vK3|LoZ*&`}k2b=U~;sZ)$}vcK}vILugZ@I9U?&B0R#j0EqaLrMWNvWK-=mOzl_ zxwyK_O~eJ^^Lp*OfKwwC5D>`7$*IY;?5|!RWl`c0$p;!7%jwpw8maK* zwHc9G2SUU3J9h8hy|MQxD8;k0VJ*6lr>Cd? zL3{I=oBK8lPW=4IBql}!u-o_ZdHwQ2-f(3@1D;~iDG?EoEw+8~9M|0!lMT^%`Fbpo zIU5~`0HsFlAFhL_3@9lPf8)7%XMUjI){^LgEhnSw;dY(mKai@~?8}tAlHAFeyJ)Eq z0B6*fNJ0u=DQ7d3PMq4$&kyuC_RX6&m)F~Gj6*~$Q0MVNYC6pPNaEzWu48)Lc6a@O zQVb6UAt7PL*RPde`<4fthu^}2g1k9_Jb(T?L9fgUp^kTexDBqOIDJ~0E4m7F#pTPF zwff^;zdn~P^1tR-jU{e9lxAg}fnOQ9xRg__gVA+~M3k3szSu-oc~1VX#heL4$T=%N-TJ6+ZXN=> zRtb?=w!eyZ=FAyLeT*nYzwh4_L8qbxK4D=>P*4ypF%q7lTsnovW0kP<^z^E$tIOfH zfc`ZL?3lraR-6Bu@papn?VO7F&0$)ydE^hY(uH?UyKQ(}DLZJoJ3Y6DUD9`%_&6j@ zWkm(XQrS`IM9%l`-&@o5B*Dai@n!%T-PzgMn(e|jyVb3obTf$cjmxoXFE}c0-4H)P zLqlV$2Tvb%Rx+$bVh{hLa$IG&8X#@r|ECM^)v-?%c(!okweX`jF=xYxZ%@ItV<8p;`6MS!oIt4c z(g%v1xg`#_jWqAvd8-gk*HhxYRZ{ebJbNbSKHU1)`1s07-B~73Yt7BghLdmNcPrHD@GPu_{)vY2%79aSG!PeH+*^~7p-KF0w2xR!9<~6;J|C>PFy+ca3-i;1x zJx5Yc`5niZzNG7Z_w6CB(awa;LZ86;OglEX=ML((xheX8^-1F@^t%Vv>IldaJ;mc^ zf8>PJhqF)Gxkhtb`n_R|vHJHgE56IyxodO_>^A*|RPp;9U#KZQE$C>!`e@DIrb0=r z{EE)vk2^9t`9htTBbAxF%I`j4G-#C3+1bxRHA<1dODMhQ>godEmTHXV1^S(D)A^#6 z^ZCCC{)N85J)5VAZTFW~8@QPS1Wp6iT)A?k9DGQ2-u zr^Of4195#GK700TQuB z|EA&qQ0C7SnSnk@h>2Udcz+zE?wl3eA``T4VC7qdjbY;tL4 zAPfu)-iC@XKE_V~C=nBFYfRkAt{LJCWC~UuVnvn0-3CUhKL? zOh*^Cyliuhl@;Z1u(xA}K*FgMjn}SS+X!CF&lgUu>n|uMaEq*$S5OGK@f3repa0fA z`{l@Q->$4kJgTMWCnY7V*_fR*tL?^Ex&HEE{g=O}dMPPdm+x-|cOMTGY7_;EPB$7i z|Bh!LntpP8E`R%_U8Oe4=8KjdkdQI_ri5Tn2_&l9aeOM0Qux6l`1l;FUx0`sEoymb z_~ZT6?f9dev-t%D2JkafQX=I*gs_{i!l2N}u-S153FXz*UkGcW#*;p>eq?Sg1cdhX z_BLn&Vs?$R4(cy~OF$3%Da?PC;b!>O!|pfV7MMS07WtV*XoR;KEj6<^H#q|2DY3NE z9HT_Oq^9zsjS}DqFr4?>cO>_hWjVC6(Vh~esKa^CmslXh6B6jF>*}g{d#T(v=P?i$ z7Z-ZqQQ%GxS~3_iv~+ity{D%qkZ5~;VPT_BL`>|RM!IfB zcJ^a{d2q%`rIHs|%9wUH`>l=kHWyHf1TS3K9uH@dkf5Uxw0H>K<#5aUh(aOk%!6>v zAkoWfTe$xTUP%v#Rk$-LsRi2-F4~f*F!%=&+tsviJ5L2^67yxSez&RhW}?N`F1xwrMA{J zFm9EJnfq%S8=cgRx1)pNOhOIq7nCHr z`;vu5$g29woh$@Fmo_w%z{l5@xy5#@`XoLj4^nopNkjIpItJ;Y%*%SeWVnN`_Zl)R zdim-Pz(9S_O+-7{Gi(47M~4SuV)%Uge?CCxgNLHm$J<-JScfsrNh;9fb$4COmGs!Q z3HjOoS1Su5qfh@81|}9rKGzA7OKXk%-@bn@Wc5p~*RjVK>B%(O{waABlsD`}V_kM2 z*p;pq4*y*wu6(^?Mq+!!_aD5G00BXA+eI$j8_E@5bF7Ve`|?Pr59L!@qF%lXb{_Vm z*xOnX6839d=+9HVeftEG?>I*e%zgaEjT@1R6~vJrtxpmW)j@*sJos_$cPpSFl`rXU5`OeC}|lpphLzU!JudI$eU+O4DQ3 z_t)Z&s$=<0Rc_z*d;k6%Iv7MGxzE$}<&N+4^nL9jCjz!8Tu^Q}goL%=GyW>$O-xQo zvqYjk_?3{g|8KE?R%RbQL{_N(8ed4}r(~0J_S(v-ka1YqHqa?_;w><@S{f=@dT@3t zF_96KfZV0qiNa58Zr(g4BP)x6ynXw&C(rsUqW}M*S1fnQ{}-`;J0sxO5T#Wp8j072 zZa#O}J|8YFE=ZA-oa}(k6peB4kf(nZV?6x&l}}hy^cZr6mR1$`7y)bUugyi#U;l@f zUO07j@CcapAJVL|ODI9!@RIw+_4`e?#_|Edmt20ZgX*W zr+KY*nnGy5s|De6G|St3lCklXmbsRsH=mpFVwhwgA#=ba9bTLqkJO zLE)7f9#*V&pl*TPWxE28ov-y3o_h;X1BN${eY({0yh`W)2r+NhPLReDy>eZ9G z8*|tRD_2cHgSmL9s*+6nqFEI+wf8xwK^_@Dj z_H5yC-Sv0vnU+HDmh!Kb?{G;dHzy~7{Zym0zJ5Xl#-q2ycp@v>e zjHb7@S8IIoBIFiYae4|#`ug=5&}$==et4;+FH~1zL^V|v>c4#}mpoh{0tI0Nf)^dz zkdr&E#&#Mscn%gjnA20(?1c_9prolhJUvNBNijk89mm45%lNA-i06;R-WTzVpg&+8 zoBea?Z9gGXx4h3zcgnoP-8Scgx^>-~^k1Q+K9JiK@h?8Bu_5JsIp+N~8k|{X;gS1$ z!$t&+8roW0>7AkmbIdi|U+Z=_4E;}8d2F2%85tdY1iTCokIpD%W@e7@!XKK2 z4i^>&3NVvyUf7{P7%zas2*~qSYpzLrXeH+pq9}f@DW2J@y9ak(p z+%*>#7S2}iNUV=!Wx8YllRE~B>UcCyT;x`HGuX{q} zyY{nX9ISR=P|$uok>Z+jdaY{4BooQP}-JL6tAkyZf8yY>+#_Q=dk5ITtnuI=NE_*#f)h|~dH+ade; zm)HLCzbf4WQAPZ1sR}oc^3E()8-cy!h}12OkR_r;EBl3KV8!obnT+o5tZDW0^Ydpy znq`_>si~21aBvWlkQj{7&hi(SFM@9xotZg_pc5F^uM^aU(S|&Eg8x6paPU*7lu_sQ zdi%*N*qzpg5=o3^L2E+bnsqBaj zY#E?6iNZQ37gsG1tIbF`hUT3+29U!syhd0TsR_`w13FnXu@_;uD)y^g1+j))4Eqee z=qv*t-zf-*H@|Aq?jqi&9CiLgp}|inb#YojNol2>KX>P|S|FArM+OS)Q7{Iy#6U2y z39DgCs+~|T&?0&C1e7AxYxNJ}G5c~3Q;o4>WuBg%H9NBAW@bv_0#EO3kDop2`R~H> zoU$e6EawI`%V+cPONW2|uDBADoP0jNun?WL3m~LDl@||G3K5OAn?K)9Q3?yCI};ll``=DJ zb9PQ3IXzNy_O4za>K=!NhS2d4!0(ZT12E~^S*&=+uGXV z;N#1I`$H)`JNqIS-t4l%IW~SkZ zmmjVY;Ni)7cw9nj?a|S!&7ramLO+}1=Kfo`CVjHz$Q%(VKYHI4`t;InM#L3BNx-*5sAD`-n)gufkAah=`j`Ijw z3+4q)2V{GWnVA8d@gkdl)zpFgu@CK8=I zNfORb_-e8t`XBl!pVQ6ZE~Dsida_K3$how83}3mYHocqb>h3lI|BX;%rlzD+z2LlC zop6tj>Tvy|WX_G}$m-e}JQRVRp5F7QsGuqWF;UUPFJJJb#?J_k*M^dYKmAqw$;iz` zHA0@4h=_Emdfr`&zq-`dldYwEtJ`l>Jgx{n1T00T5oH4iqXxJm>v=#RX=-U1?yOE~ z=33l&mEQSGkRlNR_sW$k#NF}Wz*8NO1@*w8VpmdF%o^;o9*CHjSgI%FImkzyw76G_<{<^*J~9GU+u7}_)cc`$6l(WmG1R$t3Ul?dtppAKO%+Fq94 z!{yN`VeiA@p&x3GAsEIRxXUbT^?U#D5L@%&sr2EAP#`Tw9J3@5)wX<@SeM-iPW@0!Wy>};|FFctsBVQzp-*FCl7+6Q+S>9$LiqzPKva@}aC=bfe9h0nmRn|)b#h;C7UlkG?jep=jdFrN#N+LvYM_@=&(?k zR`5G_O|IN>uN(QHb+p@E#$#BG1F1ST-UMB2E}BmT1r@`?!xOA~;A<8W zcP`zMyZ)c}lPd4IKpT{_Au<7)1q{fkNS5nA`riC&LYH1Z;557X7b#iaL$PG=Q=oz< zxOJcsF@G%6uRHpTCY1gm{|Cuj=(_H)e`~Ps^2eY3UA}N0;B&R>fGe@oCK)&r*;qQ4^ zbB+HgSTccRRx0F*4?Hzk1M21x@Bq=T)Ud;v=Ltzn-nH+lu2e}6i zF6?eCg+F_CY8|9@XSZ3HUvd~Y2?yW+6I4k7wfR~tI$R#lnl zJYFW?*!n!qdTrxn%ZP~krp0k=Y_zs$mP768>bktL(k5o|*9n>2RA)y=!iNtBy8C~vp?sdzU~B4KAw)`67Be^`#K6?lbXiA< zhK8o6ug}RiaN*yM&V~J@ljUeXU!zC_{s$uwkdnd(lQl(nHka#C%x>jkeHU16UT=>S&fZ>k+E{x z=!7)Stcx`9241%H(bTNlgEZ=2e`>7`rnas@0GEPpp^f*2$w{J58 zikyV-AwK>{q^*q7yh<5-*();hlPbj-euH} zVm)jU9yujx$;Zd%m_h9mDxa*ZEEQedq0dHV-xp7R^_$Kc_F`|0;g!`64-P&hXf<#i zpGHvWJSXSr<8N1@y?ZhYWf_Dc`q;owW2JCq*zR|s z&Q~lA6m@ZA#&Pa}mL?6O6KC5WCGsZD8SAWytmMLA~`S#La+3)X0?{1N7}h2zpZ zE)t){G0H0|j}3bti3bMhWuItXa97u&Cj&!J zP!Pfpt9&T}+wX#F1q6@AHP=i)8nh!d^CL;K#7zM43cqyz{VLiJLeHsziLSA{ek4A! z6EjA1U0vB#)SSOs5jm-yO8KHFau!lGS8&W;f{t*MI z@+Xkh(xO(5mk32ik^$B}44%&kzTmpDkT=YD;lfEUs}+zCw(HZX=&?-Lg?l$e7@`|O zB}&uM2vNy9Rui(a-hLybKbBPIF5I-|o)cOQjQ2h)P_0`Pn>d6xT!z2yHEvz8vEfmU z6J>V2RHm?a%{yv;uy?)rzFK3q=wY2xn<4So;W zKb%ZUOY@O=OYD8cEJq81n3K+Yeg!-nDFo38Zf@?1_V!!bOGk&+E87q`Qh@TL=!L$0 z`{sT~6(MnJHSwyOTVYpVKx0VSbv9OXN?V#M8ZS3D7sB8jF)=Z~)@IAPbu9!pOZ-w$B=GeekumxK?3HRS*l`lUzh$q=H314c;T<+ zEg7EbUx(3E{_Sua@o!E{B&_-W_=SBF({1n2W5FMkVtpWt&;hbsC zKff7Ey<7__EW$JA3vP4+-Sb!t2w&RhxTRTOmz007KGTj)PVyR59-r^a!9ybcPiNAd z#$NnA3-JGs^Xb12?-toj;-c!wc}e&E$B*Mc?(*>xo)9~t7YSv%@0NLqpE`BwiD=!I zJ6Y(vkJp8d18-FU*kU4@IcBHPLfM-)VQ4oQ1dhzn;eqYMHxiUE=FZ&BwWtUrVX{G| z48+~YfI3gKYU20x_E!A(amu=MhlP+<^f5S*5qLmsw6!_XZ(W8C|F4gUI?j@TVGfAa zbvp?*xV=vZR{e~a6Fz)X^^Ex%F&Wu==VHYqnJZUtN_VDc_7C@#AW0Ae?VN1`(Y0~K z2c&_{LyNk#@4_Y6tRjQsAq4#X?;lcswnA`5SjAcos1R0my-)CTD57s^Nx;s|uJ#Y7 z*D>$jy$eyKu=ML>#$-b@Iu7wgw}hHH6bnI5^nx`-E0bJYTp3wevamZm`sL{G0vcmL zEgfQd($W|cb|MHm!N^IzUF5V-nRq#5J@>4n*O@Gnrem#|+JdJOm6esC;D~ ztjguzzbnqa)Y8)W+^xJHEKB6o+!OSr zYr^+i>7PeOkHfv!b*5;*#n8$k_y-K2+XW{{$%A!LG+|6z=nyH`43#@~E-aRL9f+Pe zb0$0N0Uh`^PZDBc1i`_<+4f%e*9U+gm@YN%DIIDnkIUgd<;&PLc}d9l<(^csOU1mQ zR%}~dgq2?EZGY?j%XSxXFQ=xT$hQpAP+_;!pt!)?E`KTyhmtEcF!($A0U$jhk|tC5 zg!uTrrEkLPT))^)z2;x?<$mR9FY(hJtpFz!6i|U?EpL4*%j+=RnnIUe;<>lUaOslv zYF6JKgf@@&p-24|76J7+!uZsb6w-9vyYJW~!(r!azhz#~MQz_L3-mO6J38I?Ba4{YzJ8AzHxfAIqCW5;{#e(L!G#(@afuyw}azL}W}gs@fFfm29bJY-Vo!RB4W za?5FVX9oqw{H4-81Su^o753b{I6F6|s-Y3^`7_%SN?w^&myL~$h6>N8eodq zY`9fM@cU>N6#(JMr&}L`H5&VbqWvXX-iXtHiIh`P!bd-lBQ3fw_aMGsC>NYr;FBlS z2V2A8Xd_NtUCY8lBUQ`q=y2%>)uHH2%!?P~koDJwn071ixD!A|p@X03iJ$m*q6Ev$ zp8R}ar8k$T*ww#4GGW>PDJZ=XByiuHuUMUI$V7##WtG2>_0W?Gw?2$)uZ+7)JXOfB z>=(SWT#kt#6ciN2u;S>vtg-QX;ny2K#l+QMklza@B57;PfsF>9)Bd5Uf?6 z>zYYOm5JC_pcZiM;1^S{KSSo&;TJP1%E@(L7XEmA?4eew2`PN1^VMa=@H`pr@e?P4 z=FH5^->RpKE-j&}`p*5ZzoDT)R!Ry%%OS4^(u*?ws!J4NU0VId^sS+RU+ZJr{RH(C z^Z+{g!7|jLwHA^ky5VS{6fmOIEa%(z@0InDtnS(B(ZGOb+k1KfYinzVxO{)CwCywFm;IJuo;J+BN9DR04iXKr0W{d*#lLlP6CC&VRkbucfJpqo=30y}gYf zur9s>1KPm9wf_9Glr(Ke_bn{sK>KH781UO~~g=KF%qQHp+50YuI#N?*o_L#IJ~W&%RG zxVnx)Bp`hz3;mf!*xEWeXqg@ze5IqKL;C12Gr&s-i-|FDa$fi7>Vvq>xZlQj@!~~# zKE6|6o-kXxjJdS)i50@>{62nUwX?IcY2eJG>}-Wqf!sVfIXOvr$t8of<;@u#J3GFc zH*dNX;oI>vp15kjbp_X6`a{e~KF86@6KK07G&B?zPWIL<(sknHK&2BJK}8o{wFZY0 zoQA9}G-K*}lhixqKJMB=*cK=OyX7(!Yl=3$ZFL|7(O&t)#N#M-4Mt|>6To-CJ|ZF_ zuwQ@*=(z($MMaPzXc!usn7|W|J$?EVJ)S2gcbt!(e{^OB9qdQzbYNb3dwZYd;L}}- z2|Z6`Yj1DF@(tf!`eqE?vr6rV3no5a1bTX@tiI;TuSa(^Y+uelhO|15Rj}gv9qa7u zT;AN2zkNGu;<1Zj(kXcSvANY%yJR&snv|s&StWIcrIM{Ne;O+ut&b3w6CLWhnwl}& z1DUYzXk!KFTtY%(d1C`TKCXKEwqFPZH+r)O`k?5zl~jNJ{VLxaBSXXG$!NX4xsKlw zwXnMLDht;;9V~hoFDAwbA;Xsg?XyN`Vvl9TN$yTFHNF&Ruy}Qnlm$JpmXwr)0;RHY z*fz)fn=uH7PSi}oiXabxmESFDC*73(*dCjz!4?I}hdimfRFt2O7LRjsa-1$<&NkqS zFq(xI&|mnqk>AMprMv9x?R<)=$EMB=);7U|I1hUYLD;gQ8;cGPfwakl>_w~AK=GCE zEk^dnZBvDt;6F+9y;x?Adr{ zc7vxua-&G@0V;b;w0)%kt$%$|1Mf7pJh(YWu=nfeA}A8{^CIwRMb%dMjf{+*#>50x zSIb!pm(m6W1>L`YpLn>XzFykPt8}}tu#mdGzFxi#^rDos^rP*<{QREzw;2HD=efAZ z^(e^5=$V+R?!TItFh*x9(%073o<>G8m0I1uukY!U+_K(K**0sx9zUF;rMDL#EoSH$ zcDPogKDV~H=`_8IuNm(-$3Ic2I>)c?xtY=uaZ(|*<>AJLh3C%BPGDG=yqenc-k((Y zVhyb~3~ilrk0xXWue0F9<+tZxN4s{RQJ$Ej#tmjOj*`#^WOq*^|1-Qu3HP41HQQ|NiPtPSS@+W?o# zIpRV>LKeMWYjPQ93Ol`USe|11k=&Du^N+p2i=5<}kxoS=8Z0AIDXd^Tu%op;EY4Wr z!QR$*1@_tM)Vv|wgoRIx>BXyxLK%#>zRaq&sa*|Q%?(Z4K{#;9OCy6ebK=!{r>daVaaSFdcj)~2>WVdv0 zbD;`+_mh_@m21;`t*RnisijW=u5i zvf>)@KJuKHoYdLKQV2T}^w-A(47%UcXq$AGL(gV_dYtdc#4J19P02reao0*(O^pm~ zVkRUcSY3FQEVL4WzT3Yq2$vO?jqL;T-o?#Q5@+{e93;Qvhfiu*r{(}RJ3AiQ#r8=5 z@BvF#R~LjIWW-~794Bj;M_hzWaYEK~V`F0@3k#u5uY^zuuV7@vpuCota2{_pZi~ii+yDmE7z##lgj`1ggz6tid%l zHQm~Fy)tu?X}49DNIIo+46wXbd~3k>t!#h{SF{m4c>d2f?&ztB@#-K_dDh{lU?*kY zs!-}kr>3U*X{Dl{O;lM`75XOc`Lk!oz*e9`@SxAec46Vrxn3_XFBf>%nhl^;^h1zP zb8kB)_l`YZP9rihvb~=<0`ouie^7g5%nG9C4qcBZ_(IeOQ(n9uk#AN1j2X45$jGOU zZz_XGS(ibkj)NtL5wKsip- z4-~M>yEX*L*5U+>kkD!NG&(xqUc-x^b|P+_LbBM{SWwi`SFZ-SG&VLWxwyF{0!_7u zZ=HGe?3t*2p+g)EpYavzXeq+LKeOJ+@oWCN;~?LiHjrd!u@OC7EY)xS06-0$b599Z z)zS)%Wn{EkpaT;|Ag|F+>=Cr=dmIrFvB=TSCMcAMo`wvg6AuRbbx;t0 z1}kRFcPE@SKAGvaj9FaZ`&RKE0AoiX+|YDa@FyWw&Ua(J`QftRvCDZnMNXsZGwrA+ z0_M#Gi3Kj%;cipcS67>r2nJamyNPd$$u)rnSGW-L=ww3!o>YHSGw34QqTpa$5J%^u z6v0NtqzcX7LZ>qCKX_2Fv-Xqou%^1UmXVj21cmG6qOGPySvT2Hffuy>c0#hlBM z^+Z3FPPY5!v}BoiPANLi_jc|#5f2wS&YdZg!0a*|-o-EYf6DvraIV+*{WnP(LfKnF zWkp71Z!%kCXM|+WvQvp9r=uu)BuSxUuL>bP_FiT0JtO>H4|TqEI@k64Uf1u>-?^@? z>zpH>&wD)2>%Q;TxF5SF1jFlNCrr0tSWMT@%S#+KHyH)Rm8BbmYBs5MF2aV9U3zTU z!XqP7Ro0zZEFerVQdlQ>d8h3clEvCRf-PKJgiwDSvUBRw(AlBY`oLRq@+nBUzChlO zjg1GDl$7c$1YV@1+>%eYshI+tM|98Ly>X4B$E`aABE>yvx94&cm6c^IERMv-$D_#) zSaqnZP#(-wzBXMPJTYMf6tUSV+!!M9&owC)&k-G1&K&T3-q_@zjr;KV%AUa%UE4bV z;*n8NZ%iu>pk6fj>DtIs2Z77vtWD+PVU5pKWh^a^P381Ih!&CBEkuH2;4?<81py#w z>nsXY*l!u6Wsgy#JpRocyJq0qO-lXAuCFh)qDlVJvNF_>1WdN=?UlV4nsM0fVY(d{ zxVNFPvCJrcbaeF6I}0+@&{R>O2$zas$X1K%QaT2aYi40#BGY`3bPGqdt16p!s-+Hb zM}*W_+Q;15MRG4B<7KlYM7*y(?$d%DpB8jXZMz7s&QqL)Kv-H{j{Km^LMXnith6~; zJS0u>PdSZ6Ua2{|&%ul&S>Q(%au}@{Ux0uS)sSK|F{^CO`Ge+t7?I?Z|YC zu{Pb=Pp{Ty(4WstQxCf~K!qdoHS8;bhzxTQUtiz*SvS7k+%+>>&a}fKKiIkAFBXJ9 zHq_yCbaW{3!OGA7R%DFD;pB%89}4yHPcaYugt+t71lm>KBtj^jzRo`WBJ=rk`ACb5 z#KfK3O}#lQRl#h^p-83WyG;6~rSTH(qxK1+6JF}t?eu;qE|-sw4;jNu^f7L`N1}<2ix|i4K3&Y06BF@mNsHEg{)G1!usWQU>@8p4YMy2MLdO!$ z?N+ty#Q=HyW0;o%kP z6P}{}{Z87ODQawnv}B_eg@`SkiS(miSpe?>{rkuRS!XsTsZTqcm3?qnSU5XdnR!>~ zuiPRfw}PA3Q!k9Jeq()&m7SfCo10sHd~-3)8+kpZXr*Q4p2QTDls>e*F(D%-zrC_@ zT|h`EJ}ZmTGLv>=V*{l;^!20amtf_g>HBCg_tHh+AW|9{qyU>U6B)HG%GOSvif7J@ zO&+Mg`(1+Y3%gcyttxR%{oNTB7KU6ZQQN;w{-n^e#Kfo882}$>)aLME0*DJ+O_7aB zEXh?tBjz!le#&7yEaKt@9?WAOZta36c~fFzHuzGJM=q`m7<^v|i9~6Af`a|`75kAz zH=qqN3H6e%HT#>A&!bX<04*^lnbM3p`+(E~(Z7^s_4HCFEU$-8pCUc`=+Pr)Uf$ZF z)oqpNc28w$|I?JxLt!?ugAS*9ZVWRZqoN~6j=YcA{B9m8dZWQA9|8c0oSfW|W5+&n zrWG`7U#vy3*Lu3=nhPi-RIgeYim)Z6q1hcIe+!mPp6)$5(d)+t98U2V7TpJM)GP9! zDY?5f7XfgCVQA#D<+U!}J7P!Fcm{tFa0<;p!Cy*v`Em~xuYoKY*Sy^O@lK!kHk>|C z96FSpqd2>?^a-GQyZ!VDpNWRH_SLMYAQH7vN_`vIn^_@MRaGVMh>#gi!MCA^OL

8vU zER%mcGqor5PMqvh(dH8Jv#Q3a%wVT8`7@dPliGMVB%8fY%&9kLx%eqv@oCOHqaWWd z85uC2iG}6pkk;uK{QcbeS$=e7R8U+JG- zkdfAdL-fns)?nGtpbQFq_fo9K8f>HoPD`H!lwf%Kj8Jav=w2VluiV_U8Nh2w4C@c& z@q%HCBdk?GuZ?hV`!|L9VxEI`Ne#K-2X43}FGGNL94(W^2e%R#J)?tv>A9jCdoi_@ zLIb%*4709fhz>UFL=JsHo97Y!I75^!H~dale}KnwmN^qPZ#*&3oAp&U5%& zY+OIcuU2KK0n}uh{VX34%EoE&JaLgEJ@ZfLRW)VcIln3D+VZmvzE9#ygn3nV(U0+E zo*(qWUd-X(yr5pvgrUazKpNAqhEHz!raMk9Q(NxXgVlH;>;>|x4q9bvIgnqRkXlqv zqu|F?feM7T->*-IXW?PjFuP0-K9GuD@nq8m;eAt7%_^ID=s;ay7G-uNk#m z%{Zun8;%)=@MBV`Q7hHhGh8iHadSn#r_8y0HHRnoJn?f({rf<%*8dnJ4LZivqPnnR za6vfF{Gh8i6HqMo=W{}-10xpp(skEz;(EvzP0PVcJ$!LFO|#;U%msgwyjRWZe?CHp z98d9bQh#`C4KGg&pwm6o@-0dEWl1Y8KaF_x6KX8j1U%k>oQhf$h>td_*`=rF`N4GQ z>Mm(tx_ZPm@PAj5RT$w=dpa%6+&mih+#rsuXFmzs504CxgZ)cF83+FdTQhJlM{|76 z*oYc!3$BDg8B=nDfSjq@_Q%Db_UsxeHc(#Jam+Y}0O{(gAr6vMsBbq z2UOl1Q{IDAw`r7gByCw|D*X=%>+EA=QQd5vR{x&KY&-kE`tB}vowLu&)(94FIbCO4 zNjDZJP82yitfcpkDRYs}L16fAdF*eF=$LGLF7#whe@bG^nG-6udd4^a*Sfjaw)sj* zzR?jlb>tbzue~@Zb9Gl=pGM0k>cVWWrse%$P5P+o$mw4hpKV_wXD z*o#yxQw6)E2jK9NbY{Eo^7GfH&zKEehjeZAH3pNV`fqvgUB4f*zx3-*U zBOb~A0vw`Va07b_#uo(yzEq9+;*!RKMuR`jXs8bzsGD9Jk7NAkhRsGp!uNZA9mT{V z*Lp^;E4Uu{gfZ+6g0GK1H?a$Y^MP_fKI46E;HUZ`^;0Ro zQ68gyrpvYRJR5!XKOkY5@Qdk2@|LoQVEcw|TyEmra2cdmwZyAh0#Yo|x>}4a%PZ2z zViW4%{cAJ6u!dyqt<)uiLnZv%xaq_mf8%a5zi=QB6C8(dpf&I0$j(WA0wU@DdG;hi b%`KV-NbX1ks+#l0lrf(x@2fsre)_)wGp1C< literal 0 Hc$@=self.startDate and thisDate <= self.endDate): + return amisr_dirname_format + except: + return None + + + def __findDataForDates(self,online=False): + + if not(self.status): + return None + + pat = '\d+.\d+' + dirnameList = [re.search(pat,x) for x in os.listdir(self.path)] + dirnameList = filter(lambda x:x!=None,dirnameList) + dirnameList = [x.string for x in dirnameList] + if not(online): + dirnameList = [self.__selDates(x) for x in dirnameList] + dirnameList = filter(lambda x:x!=None,dirnameList) + if len(dirnameList)>0: + self.status = 1 + self.dirnameList = dirnameList + self.dirnameList.sort() + else: + self.status = 0 + return None + + def __getTimeFromData(self): + startDateTime_Reader = datetime.datetime.combine(self.startDate,self.startTime) + endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime) + + print 'Filtering Files from %s to %s'%(startDateTime_Reader, endDateTime_Reader) + print '........................................' + filter_filenameList = [] + self.filenameList.sort() + #for i in range(len(self.filenameList)-1): + for i in range(len(self.filenameList)): + filename = self.filenameList[i] + fp = h5py.File(filename,'r') + time_str = fp.get('Time/RadacTimeString') + + startDateTimeStr_File = time_str[0][0].split('.')[0] + junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S') + startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec) + + endDateTimeStr_File = time_str[-1][-1].split('.')[0] + junk = time.strptime(endDateTimeStr_File, '%Y-%m-%d %H:%M:%S') + endDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec) + + fp.close() + + if self.timezone == 'lt': + startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300) + endDateTime_File = endDateTime_File - datetime.timedelta(minutes = 300) + + if (endDateTime_File>=startDateTime_Reader and endDateTime_File=endDateTime_Reader): + break + + + filter_filenameList.sort() + self.filenameList = filter_filenameList + return 1 + + def __filterByGlob1(self, dirName): + filter_files = glob.glob1(dirName, '*.*%s'%self.extension_file) + filter_files.sort() + filterDict = {} + filterDict.setdefault(dirName) + filterDict[dirName] = filter_files + return filterDict + + def __getFilenameList(self, fileListInKeys, dirList): + for value in fileListInKeys: + dirName = value.keys()[0] + for file in value[dirName]: + filename = os.path.join(dirName, file) + self.filenameList.append(filename) + + + def __selectDataForTimes(self, online=False): + #aun no esta implementado el filtro for tiempo + if not(self.status): + return None + + dirList = [os.path.join(self.path,x) for x in self.dirnameList] + + fileListInKeys = [self.__filterByGlob1(x) for x in dirList] + + self.__getFilenameList(fileListInKeys, dirList) + if not(online): + #filtro por tiempo + if not(self.all): + self.__getTimeFromData() + + if len(self.filenameList)>0: + self.status = 1 + self.filenameList.sort() + else: + self.status = 0 + return None + + else: + #get the last file - 1 + self.filenameList = [self.filenameList[-2]] + + new_dirnameList = [] + for dirname in self.dirnameList: + junk = numpy.array([dirname in x for x in self.filenameList]) + junk_sum = junk.sum() + if junk_sum > 0: + new_dirnameList.append(dirname) + self.dirnameList = new_dirnameList + return 1 + + def __searchFilesOnline(self, path, startDate, endDate, startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59),walk=True): + + if endDate ==None: + startDate = datetime.datetime.utcnow().date() + endDate = datetime.datetime.utcnow().date() + + self.__setParameters(path=path, startDate=startDate, endDate=endDate,startTime = startTime,endTime=endTime, walk=walk) + + self.__checkPath() + + self.__findDataForDates(online=True) + + self.dirnameList = [self.dirnameList[-1]] + + self.__selectDataForTimes(online=True) + + return + + + def __searchFilesOffline(self, + path, + startDate, + endDate, + startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59), + walk=True): + + self.__setParameters(path, startDate, endDate, startTime, endTime, walk) + + self.__checkPath() + + self.__findDataForDates() + + self.__selectDataForTimes() + + for i in range(len(self.filenameList)): + print "%s" %(self.filenameList[i]) + + return + + def __setNextFileOffline(self): + idFile = self.fileIndex + + while (True): + idFile += 1 + if not(idFile < len(self.filenameList)): + self.flagNoMoreFiles = 1 + print "No more Files" + return 0 + + filename = self.filenameList[idFile] + + amisrFilePointer = h5py.File(filename,'r') + + break + + self.flagIsNewFile = 1 + self.fileIndex = idFile + self.filename = filename + + self.amisrFilePointer = amisrFilePointer + + print "Setting the file: %s"%self.filename + + return 1 + + + def __setNextFileOnline(self): + filename = self.filenameList[0] + if self.__filename_online != None: + self.__selectDataForTimes(online=True) + filename = self.filenameList[0] + wait = 0 + while self.__filename_online == filename: + print 'waiting %d seconds to get a new file...'%(self.__waitForNewFile) + if wait == 5: + return 0 + sleep(self.__waitForNewFile) + self.__selectDataForTimes(online=True) + filename = self.filenameList[0] + wait += 1 + + self.__filename_online = filename + + self.amisrFilePointer = h5py.File(filename,'r') + self.flagIsNewFile = 1 + self.filename = filename + print "Setting the file: %s"%self.filename + return 1 + + + def readData(self): + buffer = self.amisrFilePointer.get('Raw11/Data/Samples/Data') + re = buffer[:,:,:,0] + im = buffer[:,:,:,1] + dataset = re + im*1j + self.radacTime = self.amisrFilePointer.get('Raw11/Data/RadacHeader/RadacTime') + timeset = self.radacTime[:,0] + return dataset,timeset + + def reshapeData(self): + #self.beamCodeByPulse, self.beamCode, self.nblocks, self.nprofiles, self.nsa, + channels = self.beamCodeByPulse[0,:] + nchan = self.nchannels + #self.newProfiles = self.nprofiles/nchan #must be defined on filljroheader + nblocks = self.nblocks + nsamples = self.nsa + + #Dimensions : nChannels, nProfiles, nSamples + new_block = numpy.empty((nblocks, nchan, self.newProfiles, nsamples), dtype="complex64") + ############################################ + + for thisChannel in range(nchan): + new_block[:,thisChannel,:,:] = self.dataset[:,numpy.where(channels==self.beamCode[0][thisChannel])[0],:] + + + new_block = numpy.transpose(new_block, (1,0,2,3)) + new_block = numpy.reshape(new_block, (nchan,-1, nsamples)) + + return new_block + + def updateIndexes(self): + + pass + + def fillJROHeader(self): + + #fill radar controller header + self.dataOut.radarControllerHeaderObj = RadarControllerHeader(ippKm=self.__ippKm, + txA=self.__txA, + txB=0, + nWindows=1, + nHeights=self.__nSamples, + firstHeight=self.__firstHeight, + deltaHeight=self.__deltaHeight, + codeType=self.__codeType, + nCode=self.__nCode, nBaud=self.__nBaud, + code = self.__code, + fClock=1) + + + + #fill system header + self.dataOut.systemHeaderObj = SystemHeader(nSamples=self.__nSamples, + nProfiles=self.newProfiles, + nChannels=len(self.__channelList), + adcResolution=14, + pciDioBusWith=32) + + self.dataOut.type = "Voltage" + + self.dataOut.data = None + + self.dataOut.dtype = numpy.dtype([('real','endDateTime_Reader): + return 0 + + self.jrodataset = self.reshapeData() + #----self.updateIndexes() + self.profileIndex = 0 + + return 1 + + + def __hasNotDataInBuffer(self): + if self.profileIndex >= (self.newProfiles*self.nblocks): + return 1 + return 0 + + + def getData(self): + + if self.flagNoMoreFiles: + self.dataOut.flagNoData = True + print 'Process finished' + return 0 + + if self.__hasNotDataInBuffer(): + if not (self.readNextFile(self.online)): + return 0 + + + if self.dataset is None: # setear esta condicion cuando no hayan datos por leers + self.dataOut.flagNoData = True + return 0 + + #self.dataOut.data = numpy.reshape(self.jrodataset[self.profileIndex,:],(1,-1)) + + self.dataOut.data = self.jrodataset[:,self.profileIndex,:] + + #self.dataOut.utctime = self.jrotimeset[self.profileIndex] + #verificar basic header de jro data y ver si es compatible con este valor + #self.dataOut.utctime = self.timeset + (self.profileIndex * self.ippSeconds * self.nchannels) + indexprof = numpy.mod(self.profileIndex, self.newProfiles) + indexblock = self.profileIndex/self.newProfiles + #print indexblock, indexprof + self.dataOut.utctime = self.timeset[indexblock] + (indexprof * self.ippSeconds * self.nchannels) + self.dataOut.profileIndex = self.profileIndex + self.dataOut.flagNoData = False +# if indexprof == 0: +# print self.dataOut.utctime + + self.profileIndex += 1 + + return self.dataOut.data + + + def run(self, **kwargs): + ''' + This method will be called many times so here you should put all your code + ''' + + if not self.isConfig: + self.setup(**kwargs) + self.isConfig = True + + self.getData() + +class Writer(Operation): + ''' + classdocs + ''' + + def __init__(self): + ''' + Constructor + ''' + self.dataOut = None + + self.isConfig = False + + def setup(self, dataIn, path, blocksPerFile, set=0, ext=None): + ''' + In this method we should set all initial parameters. + + Input: + dataIn : Input data will also be outputa data + + ''' + self.dataOut = dataIn + + + + + + self.isConfig = True + + return + + def run(self, dataIn, **kwargs): + ''' + This method will be called many times so here you should put all your code + + Inputs: + + dataIn : object with the data + + ''' + + if not self.isConfig: + self.setup(dataIn, **kwargs) + \ No newline at end of file diff --git a/schainpy/model/io/.svn/text-base/jroIO_kamisr.pyc.svn-base b/schainpy/model/io/.svn/text-base/jroIO_kamisr.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..c85cda1a9b49b9af44eae6934f929c7ec70dc3fd GIT binary patch literal 18549 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 literal 0 Hc$@60): +# self.utcmatcounter=0 + +# print self.utcmatcounter + print self.utcfirst + try: + datastuff=sio.loadmat(currentfile) + except: + return None, None + + dataphase=datastuff.get('phase') + data3=datastuff.get('doppler0') + data4=datastuff.get('doppler1') + data3= np.array(data3) + data4 = np.array(data4) + datacoh=datastuff.get('coherence2') + + datacohphase=datacoh*np.exp(-dataphase*1j) +# data31 = np.fliplr(data3) +# data41 = np.fliplr(data4) + + data31 = data3.reshape((1,data3.shape[0],data3.shape[1])) + data41 = data4.reshape((1,data4.shape[0],data4.shape[1])) + datacohphase1 = datacohphase.reshape((1,datacoh.shape[0],datacoh.shape[1])) + + datastack = np.vstack((data31,data41)) + + self.__setHeader(datastuff) + + spc = datastack + cspc = datacohphase1 + + return spc, cspc + + def __findFiles(self, path, startDate=None, endDate=None,startTime=datetime.time(0,0,0), endTime=datetime.time(23,59,59)): + + if startDate == None: + startDate = datetime.date(1970,1,1) + + if endDate == None: + endDate = datetime.date(2050,1,1) + + startsearch1=datetime.datetime.combine(startDate,startTime) + startsearch2=(startsearch1-datetime.datetime(1970,1,1)).total_seconds() + endsearch1=datetime.datetime.combine(endDate,endTime) + endsearch2=(endsearch1-datetime.datetime(1970,1,1)).total_seconds() + + dirList = listdir(path) + dirList = sorted(dirList) + + dirListFiltered=[] + fileListFiltered=[] + utclist=[] + + if not dirList: + print "No directories found" + return [] + + #if self.online: + # dirList= [dirList[-1]] + + if self.online: + currentdate = datetime.datetime.now() + strsplit1=currentdate.strftime('%Y.%m.%d') + dirList = fnmatch.filter(dirList,strsplit1+'*') + + for thisDir in dirList: + if not os.path.isdir(os.path.join(path, thisDir)): + continue + + strsplit=thisDir.split('.') + timeints=[int(i) for i in strsplit] + timelist=datetime.datetime(timeints[0],timeints[1],timeints[2],timeints[3],timeints[4],timeints[5]) + utctime=(timelist-datetime.datetime(1970,1,1)).total_seconds() + + if not self.online: + if (utctime > endsearch2): + continue + + if (utctime < startsearch2): + continue + + dirListFiltered.append(thisDir) + utclist.append(utctime) + + if not dirListFiltered: + print "filtro" + return [] + + for thisDir in dirListFiltered: + + pathFile = os.path.join(self.path, thisDir) + + fileList = os.listdir(pathFile) + + if not fileList: + continue + + for k in range(len(fileList)): + thisFile = str(k)+'.mat' + + if not os.path.isfile(os.path.join(pathFile, thisFile)): + continue + + fileListFiltered.append(os.path.join(pathFile, thisFile)) + + return fileListFiltered + + def __getNextOnlineFile(self, seconds = 40): + + filename = self.__getNextOfflineFile() + + if filename: + return filename + + ncurrentfiles = len(self.fileList) + + nTries = 0 + while (True): + filelist = self.__findFiles(self.path) + if len(filelist) > ncurrentfiles: + break + + nTries += 1 + + if nTries > 3: + break + + print "Waiting %d seconds ..." %seconds + time.sleep(40) + + if not (len(filelist) > ncurrentfiles): + return None + + self.fileList = filelist + filename = self.__getNextOfflineFile() + + return filename + + def __getNextOfflineFile(self): + + if self.index >= len(self.fileList): + return None + + filename=self.fileList[self.index] + self.index += 1 + return filename + + def __getNextFile(self): + + if self.online: + filename = self.__getNextOnlineFile() + else: + filename = self.__getNextOfflineFile() + return filename + + def setup(self, path, startDate=None, endDate=None,startTime=datetime.time(0,0,0), endTime=datetime.time(23,59,59)): + + fileList = self.__findFiles(path, startDate, endDate, startTime, endTime) + + if self.online: + self.index = len(fileList) -1 + else: + self.index = 0 + + self.fileList = fileList + + print "fin setup" + + def run(self,path=None,startDate=None, endDate=None, + startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59), + walk=True,timezone='ut', + all=0,online=False,ext=None,**kwargs): + + self.path=path + self.ext=ext + self.startDate=startDate + self.endDate=endDate + self.startTime=startTime + self.endTime=endTime + self.online = online + self.dataOut.flagNoData = True + + if (self.firsttime==True): + self.setup(path, startDate, endDate, startTime, endTime) + self.firsttime=False + + + if not self.fileList: + self.dataOut.flagNoData = True + print "lista vacia" + return + + currentfile = self.__getNextFile() + + if not currentfile: + "no file" + return + + spc, cspc = self.__readFile(currentfile) + + if spc!=None: + + self.dataOut.data_spc = spc + self.dataOut.data_cspc = cspc + self.dataOut.utctime = self.utcfirst + self.dataOut.flagNoData = False + + return 1 + \ No newline at end of file diff --git a/schainpy/model/io/.svn/text-base/jroIO_mira35c.py.svn-base b/schainpy/model/io/.svn/text-base/jroIO_mira35c.py.svn-base new file mode 100644 index 0000000..44c117a --- /dev/null +++ b/schainpy/model/io/.svn/text-base/jroIO_mira35c.py.svn-base @@ -0,0 +1,794 @@ +import os, sys +import glob +import fnmatch +import datetime +import time +import re +import h5py +import numpy +import matplotlib.pyplot as plt + +import pylab as plb +from scipy.optimize import curve_fit +from scipy import asarray as ar,exp +from scipy import stats + +from duplicity.path import Path +from numpy.ma.core import getdata + +SPEED_OF_LIGHT = 299792458 +SPEED_OF_LIGHT = 3e8 + +try: + from gevent import sleep +except: + from time import sleep + +from schainpy.model.data.jrodata import Spectra +#from schainpy.model.data.BLTRheaderIO import FileHeader, RecordHeader +from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation +#from schainpy.model.io.jroIO_bltr import BLTRReader +from numpy import imag, shape, NaN + + + +class Header(object): + + def __init__(self): + raise NotImplementedError + + + def read(self): + + raise NotImplementedError + + def write(self): + + raise NotImplementedError + + def printInfo(self): + + message = "#"*50 + "\n" + message += self.__class__.__name__.upper() + "\n" + message += "#"*50 + "\n" + + keyList = self.__dict__.keys() + keyList.sort() + + for key in keyList: + message += "%s = %s" %(key, self.__dict__[key]) + "\n" + + if "size" not in keyList: + attr = getattr(self, "size") + + if attr: + message += "%s = %s" %("size", attr) + "\n" + + #print message + + +FILE_HEADER = numpy.dtype([ #HEADER 1024bytes + ('Hname','a32'), #Original file name + ('Htime',numpy.str_,32), #Date and time when the file was created + ('Hoper',numpy.str_,64), #Name of operator who created the file + ('Hplace',numpy.str_,128), #Place where the measurements was carried out + ('Hdescr',numpy.str_,256), #Description of measurements + ('Hdummy',numpy.str_,512), #Reserved space + #Main chunk 8bytes + ('Msign',numpy.str_,4), #Main chunk signature FZKF or NUIG + ('MsizeData','=5 + ('SPARrawGate2',' 1180: + self.fp.seek(self.PointerReader , os.SEEK_SET) + + print ' ' + print 'First point in block: ',self.fp.tell() + print ' ' + + + + #Off2StartNxtRec = (16 + 84 + self.blocksize)*self.RecCounter + 1180 + + self.srviHeader = SRVIHeader() + + self.srviHeader.SRVIread(self.fp) #Se obtiene la cabecera del SRVI + + self.blocksize = self.srviHeader.SizeOfDataBlock1 # Se obtiene el tamao del bloque + + if self.blocksize == 148: + print 'blocksize == 148 bug' + jump = numpy.fromfile(self.fp,[('jump',numpy.str_,140)] ,1) + + self.srviHeader.SRVIread(self.fp) #Se obtiene la cabecera del SRVI + + if not self.srviHeader.SizeOfSRVI1: + self.fileSelector+=1 + self.nextfileflag==True + self.FileHeaderFlag == True + + self.recordheader = RecordHeader() + self.recordheader.RHread(self.fp) + RadarConst5 = self.recordheader.RadarConst + dwell = self.recordheader.time_t + + + self.dataOut.channelList = range(1) + self.dataOut.nIncohInt = self.Num_inCoh + self.dataOut.nProfiles = self.Num_Bins + self.dataOut.nCohInt = 1 + self.dataOut.windowOfFilter = 1 + self.dataOut.utctime = dwell + self.dataOut.timeZone=0 + + #self.__firstHeigth=rheader.StartRangeSamp + #self.__deltaHeigth=rheader.SampResolution + self.dataOut.heightList= self.SPARrawGate1*self.__deltaHeigth + numpy.array(range(self.Num_Hei))*self.__deltaHeigth + + #print 'self.Num_Bins', self.Num_Bins + #print 'self.Num_inCoh',self.Num_inCoh + + + self.HSDV = numpy.fromfile( self.fp, [('HSDV',numpy.str_,4)],1) + self.SizeHSDV = numpy.fromfile( self.fp, [('SizeHSDV',' 1: + print "[Reading] %d days were found in date range: %s - %s" %(len(dateList), startDate, endDate) + else: + print "[Reading] data was found for the date %s" %(dateList[0]) + + filenameList = [] + datetimeList = [] + + #---------------------------------------------------------------------------------- + + for thisPath in pathList: +# thisPath = pathList[pathDict[file]] + + fileList = glob.glob1(thisPath, "*%s" %ext) + fileList.sort() + + for file in fileList: + + filename = os.path.join(thisPath,file) + + if not isFileInDateRange(filename, startDate, endDate): + continue + + thisDatetime = self.__isFileInTimeRange(filename, startDate, endDate, startTime, endTime) + + if not(thisDatetime): + continue + + filenameList.append(filename) + datetimeList.append(thisDatetime) + + if not(filenameList): + print "[Reading] Any file was found int time range %s - %s" %(datetime.datetime.combine(startDate,startTime).ctime(), datetime.datetime.combine(endDate,endTime).ctime()) + return None, None + + print "[Reading] %d file(s) was(were) found in time range: %s - %s" %(len(filenameList), startTime, endTime) + print + + for i in range(len(filenameList)): + print "[Reading] %s -> [%s]" %(filenameList[i], datetimeList[i].ctime()) + + self.filenameList = filenameList + self.datetimeList = datetimeList + + return pathList, filenameList + + def __isFileInTimeRange(self,filename, startDate, endDate, startTime, endTime): + + """ + Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado. + + Inputs: + filename : nombre completo del archivo de datos en formato Jicamarca (.r) + + startDate : fecha inicial del rango seleccionado en formato datetime.date + + endDate : fecha final del rango seleccionado en formato datetime.date + + startTime : tiempo inicial del rango seleccionado en formato datetime.time + + endTime : tiempo final del rango seleccionado en formato datetime.time + + Return: + Boolean : Retorna True si el archivo de datos contiene datos en el rango de + fecha especificado, de lo contrario retorna False. + + Excepciones: + Si el archivo no existe o no puede ser abierto + Si la cabecera no puede ser leida. + + """ + + try: + fp = h5py.File(filename,'r') + grp1 = fp['Data'] + + except IOError: + traceback.print_exc() + raise IOError, "The file %s can't be opened" %(filename) + #chino rata + #In case has utctime attribute + grp2 = grp1['utctime'] +# thisUtcTime = grp2.value[0] - 5*3600 #To convert to local time + thisUtcTime = grp2.value[0] + + fp.close() + + if self.timezone == 'lt': + thisUtcTime -= 5*3600 + + thisDatetime = datetime.datetime.fromtimestamp(thisUtcTime[0] + 5*3600) +# thisDatetime = datetime.datetime.fromtimestamp(thisUtcTime[0]) + thisDate = thisDatetime.date() + thisTime = thisDatetime.time() + + startUtcTime = (datetime.datetime.combine(thisDate,startTime)- datetime.datetime(1970, 1, 1)).total_seconds() + endUtcTime = (datetime.datetime.combine(thisDate,endTime)- datetime.datetime(1970, 1, 1)).total_seconds() + + #General case + # o>>>>>>>>>>>>>><<<<<<<<<<<<<= startTime: + thisUtcLog = numpy.logical_and(thisUtcTime > startUtcTime, thisUtcTime < endUtcTime) + if numpy.any(thisUtcLog): #If there is one block between the hours mentioned + return thisDatetime + return None + + #If endTime < startTime then endTime belongs to the next day + #<<<<<<<<<<>>>>>>>>>> + #-----------o----------------------------o----------- + # endTime startTime + + if (thisDate == startDate) and numpy.all(thisUtcTime < startUtcTime): + return None + + if (thisDate == endDate) and numpy.all(thisUtcTime > endUtcTime): + return None + + if numpy.all(thisUtcTime < startUtcTime) and numpy.all(thisUtcTime > endUtcTime): + return None + + return thisDatetime + + def __setNextFileOffline(self): + + self.fileIndex += 1 + idFile = self.fileIndex + + if not(idFile < len(self.filenameList)): + print "No more Files" + return 0 + + filename = self.filenameList[idFile] + + filePointer = h5py.File(filename,'r') + + self.filename = filename + + self.fp = filePointer + + print "Setting the file: %s"%self.filename + +# self.__readMetadata() + self.__setBlockList() + self.__readData() +# self.nRecords = self.fp['Data'].attrs['blocksPerFile'] +# self.nRecords = self.fp['Data'].attrs['nRecords'] + self.blockIndex = 0 + return 1 + + def __setBlockList(self): + ''' + Selects the data within the times defined + + self.fp + self.startTime + self.endTime + + self.blockList + self.blocksPerFile + + ''' + fp = self.fp + startTime = self.startTime + endTime = self.endTime + + grp = fp['Data'] + thisUtcTime = grp['utctime'].value.astype(numpy.float)[0] + + #ERROOOOR + if self.timezone == 'lt': + thisUtcTime -= 5*3600 + + thisDatetime = datetime.datetime.fromtimestamp(thisUtcTime[0] + 5*3600) + + thisDate = thisDatetime.date() + thisTime = thisDatetime.time() + + startUtcTime = (datetime.datetime.combine(thisDate,startTime) - datetime.datetime(1970, 1, 1)).total_seconds() + endUtcTime = (datetime.datetime.combine(thisDate,endTime) - datetime.datetime(1970, 1, 1)).total_seconds() + + ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0] + + self.blockList = ind + self.blocksPerFile = len(ind) + + return + + def __readMetadata(self): + ''' + Reads Metadata + + self.pathMeta + + self.listShapes + self.listMetaname + self.listMeta + + ''' + +# grp = self.fp['Data'] +# pathMeta = os.path.join(self.path, grp.attrs['metadata']) +# +# if pathMeta == self.pathMeta: +# return +# else: +# self.pathMeta = pathMeta +# +# filePointer = h5py.File(self.pathMeta,'r') +# groupPointer = filePointer['Metadata'] + + filename = self.filenameList[0] + + fp = h5py.File(filename,'r') + + gp = fp['Metadata'] + + listMetaname = [] + listMetadata = [] + for item in gp.items(): + name = item[0] + + if name=='array dimensions': + table = gp[name][:] + listShapes = {} + for shapes in table: + listShapes[shapes[0]] = numpy.array([shapes[1],shapes[2],shapes[3],shapes[4],shapes[5]]) + else: + data = gp[name].value + listMetaname.append(name) + listMetadata.append(data) + +# if name=='type': +# self.__initDataOut(data) + + self.listShapes = listShapes + self.listMetaname = listMetaname + self.listMeta = listMetadata + + fp.close() + return + + def __readData(self): + grp = self.fp['Data'] + listdataname = [] + listdata = [] + + for item in grp.items(): + name = item[0] + listdataname.append(name) + + array = self.__setDataArray(grp[name],self.listShapes[name]) + listdata.append(array) + + self.listDataname = listdataname + self.listData = listdata + return + + def __setDataArray(self, dataset, shapes): + + nDims = shapes[0] + + nDim2 = shapes[1] #Dimension 0 + + nDim1 = shapes[2] #Dimension 1, number of Points or Parameters + + nDim0 = shapes[3] #Dimension 2, number of samples or ranges + + mode = shapes[4] #Mode of storing + + blockList = self.blockList + + blocksPerFile = self.blocksPerFile + + #Depending on what mode the data was stored + if mode == 0: #Divided in channels + arrayData = dataset.value.astype(numpy.float)[0][blockList] + if mode == 1: #Divided in parameter + strds = 'table' + nDatas = nDim1 + newShapes = (blocksPerFile,nDim2,nDim0) + elif mode==2: #Concatenated in a table + strds = 'table0' + arrayData = dataset[strds].value + #Selecting part of the dataset + utctime = arrayData[:,0] + u, indices = numpy.unique(utctime, return_index=True) + + if blockList.size != indices.size: + indMin = indices[blockList[0]] + if blockList[-1] + 1 >= indices.size: + arrayData = arrayData[indMin:,:] + else: + indMax = indices[blockList[-1] + 1] + arrayData = arrayData[indMin:indMax,:] + return arrayData + + #------- One dimension --------------- + if nDims == 0: + arrayData = dataset.value.astype(numpy.float)[0][blockList] + + #------- Two dimensions ----------- + elif nDims == 2: + arrayData = numpy.zeros((blocksPerFile,nDim1,nDim0)) + newShapes = (blocksPerFile,nDim0) + nDatas = nDim1 + + for i in range(nDatas): + data = dataset[strds + str(i)].value + arrayData[:,i,:] = data[blockList,:] + + #------- Three dimensions --------- + else: + arrayData = numpy.zeros((blocksPerFile,nDim2,nDim1,nDim0)) + for i in range(nDatas): + + data = dataset[strds + str(i)].value + + for b in range(blockList.size): + arrayData[b,:,i,:] = data[:,:,blockList[b]] + + return arrayData + + def __setDataOut(self): + listMeta = self.listMeta + listMetaname = self.listMetaname + listDataname = self.listDataname + listData = self.listData + listShapes = self.listShapes + + blockIndex = self.blockIndex +# blockList = self.blockList + + for i in range(len(listMeta)): + setattr(self.dataOut,listMetaname[i],listMeta[i]) + + for j in range(len(listData)): + nShapes = listShapes[listDataname[j]][0] + mode = listShapes[listDataname[j]][4] + if nShapes == 1: + setattr(self.dataOut,listDataname[j],listData[j][blockIndex]) + elif nShapes > 1: + setattr(self.dataOut,listDataname[j],listData[j][blockIndex,:]) + elif mode==0: + setattr(self.dataOut,listDataname[j],listData[j][blockIndex]) + #Mode Meteors + elif mode ==2: + selectedData = self.__selectDataMode2(listData[j], blockIndex) + setattr(self.dataOut, listDataname[j], selectedData) + return + + def __selectDataMode2(self, data, blockIndex): + utctime = data[:,0] + aux, indices = numpy.unique(utctime, return_inverse=True) + selInd = numpy.where(indices == blockIndex)[0] + selData = data[selInd,:] + + return selData + + def getData(self): + +# if self.flagNoMoreFiles: +# self.dataOut.flagNoData = True +# print 'Process finished' +# return 0 +# + if self.blockIndex==self.blocksPerFile: + if not( self.__setNextFileOffline() ): + self.dataOut.flagNoData = True + return 0 + +# if self.datablock == None: # setear esta condicion cuando no hayan datos por leers +# self.dataOut.flagNoData = True +# return 0 +# self.__readData() + self.__setDataOut() + self.dataOut.flagNoData = False + + self.blockIndex += 1 + + return + + def run(self, **kwargs): + + if not(self.isConfig): + self.setup(**kwargs) +# self.setObjProperties() + self.isConfig = True + + self.getData() + + return + +class ParamWriter(Operation): + ''' + HDF5 Writer, stores parameters data in HDF5 format files + + path: path where the files will be stored + + blocksPerFile: number of blocks that will be saved in per HDF5 format file + + mode: selects the data stacking mode: '0' channels, '1' parameters, '3' table (for meteors) + + metadataList: list of attributes that will be stored as metadata + + dataList: list of attributes that will be stores as data + + ''' + + + ext = ".hdf5" + + optchar = "D" + + metaoptchar = "M" + + metaFile = None + + filename = None + + path = None + + setFile = None + + fp = None + + grp = None + + ds = None + + firsttime = True + + #Configurations + + blocksPerFile = None + + blockIndex = None + + dataOut = None + + #Data Arrays + + dataList = None + + metadataList = None + +# arrayDim = None + + dsList = None #List of dictionaries with dataset properties + + tableDim = None + +# dtype = [('arrayName', 'S20'),('nChannels', 'i'), ('nPoints', 'i'), ('nSamples', 'i'),('mode', 'b')] + + dtype = [('arrayName', 'S20'),('nDimensions', 'i'), ('dim2', 'i'), ('dim1', 'i'),('dim0', 'i'),('mode', 'b')] + + currentDay = None + + lastTime = None + + def __init__(self): + + Operation.__init__(self) + self.isConfig = False + return + + def setup(self, dataOut, **kwargs): + + self.path = kwargs['path'] + + if kwargs.has_key('blocksPerFile'): + self.blocksPerFile = kwargs['blocksPerFile'] + else: + self.blocksPerFile = 10 + + self.metadataList = kwargs['metadataList'] + self.dataList = kwargs['dataList'] + self.dataOut = dataOut + + if kwargs.has_key('mode'): + mode = kwargs['mode'] + + if type(mode) == int: + mode = numpy.zeros(len(self.dataList)) + mode + else: + mode = numpy.ones(len(self.dataList)) + + self.mode = mode + + arrayDim = numpy.zeros((len(self.dataList),5)) + + #Table dimensions + dtype0 = self.dtype + tableList = [] + + #Dictionary and list of tables + dsList = [] + + for i in range(len(self.dataList)): + dsDict = {} + dataAux = getattr(self.dataOut, self.dataList[i]) + dsDict['variable'] = self.dataList[i] + #--------------------- Conditionals ------------------------ + #There is no data + if dataAux == None: + return 0 + + #Not array, just a number + #Mode 0 + if type(dataAux)==float or type(dataAux)==int: + dsDict['mode'] = 0 + dsDict['nDim'] = 0 + arrayDim[i,0] = 0 + dsList.append(dsDict) + + #Mode 2: meteors + elif mode[i] == 2: +# dsDict['nDim'] = 0 + dsDict['dsName'] = 'table0' + dsDict['mode'] = 2 # Mode meteors + dsDict['shape'] = dataAux.shape[-1] + dsDict['nDim'] = 0 + dsDict['dsNumber'] = 1 + + arrayDim[i,3] = dataAux.shape[-1] + arrayDim[i,4] = mode[i] #Mode the data was stored + + dsList.append(dsDict) + + #Mode 1 + else: + arrayDim0 = dataAux.shape #Data dimensions + arrayDim[i,0] = len(arrayDim0) #Number of array dimensions + arrayDim[i,4] = mode[i] #Mode the data was stored + + strtable = 'table' + dsDict['mode'] = 1 # Mode parameters + + # Three-dimension arrays + if len(arrayDim0) == 3: + arrayDim[i,1:-1] = numpy.array(arrayDim0) + nTables = int(arrayDim[i,2]) + dsDict['dsNumber'] = nTables + dsDict['shape'] = arrayDim[i,2:4] + dsDict['nDim'] = 3 + + for j in range(nTables): + dsDict = dsDict.copy() + dsDict['dsName'] = strtable + str(j) + dsList.append(dsDict) + + # Two-dimension arrays + elif len(arrayDim0) == 2: + arrayDim[i,2:-1] = numpy.array(arrayDim0) + nTables = int(arrayDim[i,2]) + dsDict['dsNumber'] = nTables + dsDict['shape'] = arrayDim[i,3] + dsDict['nDim'] = 2 + + for j in range(nTables): + dsDict = dsDict.copy() + dsDict['dsName'] = strtable + str(j) + dsList.append(dsDict) + + # One-dimension arrays + elif len(arrayDim0) == 1: + arrayDim[i,3] = arrayDim0[0] + dsDict['shape'] = arrayDim0[0] + dsDict['dsNumber'] = 1 + dsDict['dsName'] = strtable + str(0) + dsDict['nDim'] = 1 + dsList.append(dsDict) + + table = numpy.array((self.dataList[i],) + tuple(arrayDim[i,:]),dtype = dtype0) + tableList.append(table) + +# self.arrayDim = arrayDim + self.dsList = dsList + self.tableDim = numpy.array(tableList, dtype = dtype0) + self.blockIndex = 0 + + timeTuple = time.localtime(dataOut.utctime) + self.currentDay = timeTuple.tm_yday + return 1 + + def putMetadata(self): + + fp = self.createMetadataFile() + self.writeMetadata(fp) + fp.close() + return + + def createMetadataFile(self): + ext = self.ext + path = self.path + setFile = self.setFile + + timeTuple = time.localtime(self.dataOut.utctime) + + subfolder = '' + fullpath = os.path.join( path, subfolder ) + + if not( os.path.exists(fullpath) ): + os.mkdir(fullpath) + setFile = -1 #inicializo mi contador de seteo + + subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday) + fullpath = os.path.join( path, subfolder ) + + if not( os.path.exists(fullpath) ): + os.mkdir(fullpath) + setFile = -1 #inicializo mi contador de seteo + + else: + filesList = os.listdir( fullpath ) + filesList = sorted( filesList, key=str.lower ) + if len( filesList ) > 0: + filesList = [k for k in filesList if 'M' in k] + filen = filesList[-1] + # el filename debera tener el siguiente formato + # 0 1234 567 89A BCDE (hex) + # x YYYY DDD SSS .ext + if isNumber( filen[8:11] ): + setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file + else: + setFile = -1 + else: + setFile = -1 #inicializo mi contador de seteo + + setFile += 1 + + file = '%s%4.4d%3.3d%3.3d%s' % (self.metaoptchar, + timeTuple.tm_year, + timeTuple.tm_yday, + setFile, + ext ) + + filename = os.path.join( path, subfolder, file ) + self.metaFile = file + #Setting HDF5 File + fp = h5py.File(filename,'w') + + return fp + + def writeMetadata(self, fp): + + grp = fp.create_group("Metadata") + grp.create_dataset('array dimensions', data = self.tableDim, dtype = self.dtype) + + for i in range(len(self.metadataList)): + grp.create_dataset(self.metadataList[i], data=getattr(self.dataOut, self.metadataList[i])) + return + + def timeFlag(self): + currentTime = self.dataOut.utctime + + if self.lastTime is None: + self.lastTime = currentTime + + #Day + timeTuple = time.localtime(currentTime) + dataDay = timeTuple.tm_yday + + #Time + timeDiff = currentTime - self.lastTime + + #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora + if dataDay != self.currentDay: + self.currentDay = dataDay + return True + elif timeDiff > 3*60*60: + self.lastTime = currentTime + return True + else: + self.lastTime = currentTime + return False + + def setNextFile(self): + + ext = self.ext + path = self.path + setFile = self.setFile + mode = self.mode + + timeTuple = time.localtime(self.dataOut.utctime) + subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday) + + fullpath = os.path.join( path, subfolder ) + + if os.path.exists(fullpath): + filesList = os.listdir( fullpath ) + filesList = [k for k in filesList if 'D' in k] + if len( filesList ) > 0: + filesList = sorted( filesList, key=str.lower ) + filen = filesList[-1] + # el filename debera tener el siguiente formato + # 0 1234 567 89A BCDE (hex) + # x YYYY DDD SSS .ext + if isNumber( filen[8:11] ): + setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file + else: + setFile = -1 + else: + setFile = -1 #inicializo mi contador de seteo + else: + os.mkdir(fullpath) + setFile = -1 #inicializo mi contador de seteo + + setFile += 1 + + file = '%s%4.4d%3.3d%3.3d%s' % (self.optchar, + timeTuple.tm_year, + timeTuple.tm_yday, + setFile, + ext ) + + filename = os.path.join( path, subfolder, file ) + + #Setting HDF5 File + fp = h5py.File(filename,'w') + #write metadata + self.writeMetadata(fp) + #Write data + grp = fp.create_group("Data") +# grp.attrs['metadata'] = self.metaFile + +# grp.attrs['blocksPerFile'] = 0 + ds = [] + data = [] + dsList = self.dsList + i = 0 + while i < len(dsList): + dsInfo = dsList[i] + #One-dimension data + if dsInfo['mode'] == 0: +# ds0 = grp.create_dataset(self.dataList[i], (1,1), maxshape=(1,self.blocksPerFile) , chunks = True, dtype='S20') + ds0 = grp.create_dataset(dsInfo['variable'], (1,1), maxshape=(1,self.blocksPerFile) , chunks = True, dtype=numpy.float64) + ds.append(ds0) + data.append([]) + i += 1 + continue +# nDimsForDs.append(nDims[i]) + + elif dsInfo['mode'] == 2: + grp0 = grp.create_group(dsInfo['variable']) + ds0 = grp0.create_dataset(dsInfo['dsName'], (1,dsInfo['shape']), data = numpy.zeros((1,dsInfo['shape'])) , maxshape=(None,dsInfo['shape']), chunks=True) + ds.append(ds0) + data.append([]) + i += 1 + continue + + elif dsInfo['mode'] == 1: + grp0 = grp.create_group(dsInfo['variable']) + + for j in range(dsInfo['dsNumber']): + dsInfo = dsList[i] + tableName = dsInfo['dsName'] + shape = dsInfo['shape'] + + if dsInfo['nDim'] == 3: + ds0 = grp0.create_dataset(tableName, (shape[0],shape[1],1) , data = numpy.zeros((shape[0],shape[1],1)), maxshape = (None,shape[1],None), chunks=True) + else: + ds0 = grp0.create_dataset(tableName, (1,shape), data = numpy.zeros((1,shape)) , maxshape=(None,shape), chunks=True) + + ds.append(ds0) + data.append([]) + i += 1 +# nDimsForDs.append(nDims[i]) + + fp.flush() + fp.close() + +# self.nDatas = nDatas +# self.nDims = nDims +# self.nDimsForDs = nDimsForDs + #Saving variables + print 'Writing the file: %s'%filename + self.filename = filename +# self.fp = fp +# self.grp = grp +# self.grp.attrs.modify('nRecords', 1) + self.ds = ds + self.data = data +# self.setFile = setFile + self.firsttime = True + self.blockIndex = 0 + return + + def putData(self): + + if self.blockIndex == self.blocksPerFile or self.timeFlag(): + self.setNextFile() + +# if not self.firsttime: + self.readBlock() + self.setBlock() #Prepare data to be written + self.writeBlock() #Write data + + return + + def readBlock(self): + + ''' + data Array configured + + + self.data + ''' + dsList = self.dsList + ds = self.ds + #Setting HDF5 File + fp = h5py.File(self.filename,'r+') + grp = fp["Data"] + ind = 0 + +# grp.attrs['blocksPerFile'] = 0 + while ind < len(dsList): + dsInfo = dsList[ind] + + if dsInfo['mode'] == 0: + ds0 = grp[dsInfo['variable']] + ds[ind] = ds0 + ind += 1 + else: + + grp0 = grp[dsInfo['variable']] + + for j in range(dsInfo['dsNumber']): + dsInfo = dsList[ind] + ds0 = grp0[dsInfo['dsName']] + ds[ind] = ds0 + ind += 1 + + self.fp = fp + self.grp = grp + self.ds = ds + + return + + def setBlock(self): + ''' + data Array configured + + + self.data + ''' + #Creating Arrays + dsList = self.dsList + data = self.data + ind = 0 + + while ind < len(dsList): + dsInfo = dsList[ind] + dataAux = getattr(self.dataOut, dsInfo['variable']) + + mode = dsInfo['mode'] + nDim = dsInfo['nDim'] + + if mode == 0 or mode == 2 or nDim == 1: + data[ind] = dataAux + ind += 1 +# elif nDim == 1: +# data[ind] = numpy.reshape(dataAux,(numpy.size(dataAux),1)) +# ind += 1 + elif nDim == 2: + for j in range(dsInfo['dsNumber']): + data[ind] = dataAux[j,:] + ind += 1 + elif nDim == 3: + for j in range(dsInfo['dsNumber']): + data[ind] = dataAux[:,j,:] + ind += 1 + + self.data = data + return + + def writeBlock(self): + ''' + Saves the block in the HDF5 file + ''' + dsList = self.dsList + + for i in range(len(self.ds)): + dsInfo = dsList[i] + nDim = dsInfo['nDim'] + mode = dsInfo['mode'] + + # First time + if self.firsttime: +# self.ds[i].resize(self.data[i].shape) +# self.ds[i][self.blockIndex,:] = self.data[i] + if type(self.data[i]) == numpy.ndarray: + + if nDim == 3: + self.data[i] = self.data[i].reshape((self.data[i].shape[0],self.data[i].shape[1],1)) + self.ds[i].resize(self.data[i].shape) + if mode == 2: + self.ds[i].resize(self.data[i].shape) + self.ds[i][:] = self.data[i] + else: + + # From second time + # Meteors! + if mode == 2: + dataShape = self.data[i].shape + dsShape = self.ds[i].shape + self.ds[i].resize((self.ds[i].shape[0] + dataShape[0],self.ds[i].shape[1])) + self.ds[i][dsShape[0]:,:] = self.data[i] + # No dimension + elif mode == 0: + self.ds[i].resize((self.ds[i].shape[0], self.ds[i].shape[1] + 1)) + self.ds[i][0,-1] = self.data[i] + # One dimension + elif nDim == 1: + self.ds[i].resize((self.ds[i].shape[0] + 1, self.ds[i].shape[1])) + self.ds[i][-1,:] = self.data[i] + # Two dimension + elif nDim == 2: + self.ds[i].resize((self.ds[i].shape[0] + 1,self.ds[i].shape[1])) + self.ds[i][self.blockIndex,:] = self.data[i] + # Three dimensions + elif nDim == 3: + self.ds[i].resize((self.ds[i].shape[0],self.ds[i].shape[1],self.ds[i].shape[2]+1)) + self.ds[i][:,:,-1] = self.data[i] + + self.firsttime = False + self.blockIndex += 1 + + #Close to save changes + self.fp.flush() + self.fp.close() + return + + def run(self, dataOut, **kwargs): + + if not(self.isConfig): + flagdata = self.setup(dataOut, **kwargs) + + if not(flagdata): + return + + self.isConfig = True +# self.putMetadata() + self.setNextFile() + + self.putData() + return + + diff --git a/schainpy/model/io/.svn/text-base/jroIO_param.pyc.svn-base b/schainpy/model/io/.svn/text-base/jroIO_param.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..cd81edc3b29093c8c1a812bd0af51852d1ac3fe3 GIT binary patch literal 23367 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 0: + channelList = [] + for channel in range(self.dataOut.nChannels): + channelList.append(channel) + channelList.append(channel) + + pairsList = [] + if self.dataOut.nPairs > 0: + for pair in self.dataOut.pairsList: + pairsList.append(pair[0]) + pairsList.append(pair[1]) + + spectraComb = channelList + pairsList + spectraComb = numpy.array(spectraComb, dtype="u1") + self.processingHeaderObj.spectraComb = spectraComb + + if self.dataOut.code is not None: + self.processingHeaderObj.code = self.dataOut.code + self.processingHeaderObj.nCode = self.dataOut.nCode + self.processingHeaderObj.nBaud = self.dataOut.nBaud + + if self.processingHeaderObj.nWindows != 0: + self.processingHeaderObj.firstHeight = self.dataOut.heightList[0] + self.processingHeaderObj.deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0] + self.processingHeaderObj.nHeights = self.dataOut.nHeights + self.processingHeaderObj.samplesWin = self.dataOut.nHeights + + self.processingHeaderObj.processFlags = self.getProcessFlags() + + self.setBasicHeader() diff --git a/schainpy/model/io/.svn/text-base/jroIO_spectra.pyc.svn-base b/schainpy/model/io/.svn/text-base/jroIO_spectra.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..b5f4be0da04f796f0ca0eb18e7f12d52a93c124a GIT binary patch literal 17096 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 literal 0 Hc$@ endDate: + break + + dateList.append(thisDate) + thisDatetime += datetime.timedelta(1) + + return dateList + + def setup(self, path = None, + startDate = None, + endDate = None, + startTime = datetime.time(0,0,0), + endTime = datetime.time(23,59,59), + channelList = None, + nSamples = None, + ippKm = 60, + online = False, + delay = 60, + buffer_size = 1024, + **kwargs): + ''' + In this method we should set all initial parameters. + + Inputs: + path + startDate + endDate + startTime + endTime + set + expLabel + ext + online + delay + ''' + + if not os.path.isdir(path): + raise ValueError, "[Reading] Directory %s does not exist" %path + + try: + self.digitalReadObj = digital_rf_hdf5.read_hdf5(path, load_all_metadata=True) + except: + self.digitalReadObj = digital_rf_hdf5.read_hdf5(path) + + channelNameList = self.digitalReadObj.get_channels() + + if not channelNameList: + raise ValueError, "[Reading] Directory %s does not have any files" %path + + if not channelList: + channelList = range(len(channelNameList)) + + ########## Reading metadata ###################### + + metadata_dict = self.digitalReadObj.get_rf_file_metadata(channelNameList[channelList[0]]) + + self.__sample_rate = metadata_dict['sample_rate'][0] +# self.__samples_per_file = metadata_dict['samples_per_file'][0] + self.__deltaHeigth = 1e6*0.15/self.__sample_rate + + this_metadata_file = self.digitalReadObj.get_metadata(channelNameList[channelList[0]]) + + self.__frequency = None + try: + self.__frequency = this_metadata_file['center_frequencies'].value + except: + self.__frequency = this_metadata_file['fc'].value + + if not self.__frequency: + raise ValueError, "Center Frequency is not defined in metadata file" + + try: + self.__timezone = this_metadata_file['timezone'].value + except: + self.__timezone = 0 + + self.__firstHeigth = 0 + + try: + codeType = this_metadata_file['codeType'].value + except: + codeType = 0 + + nCode = 1 + nBaud = 1 + code = numpy.ones((nCode, nBaud), dtype=numpy.int) + + if codeType: + nCode = this_metadata_file['nCode'].value + nBaud = this_metadata_file['nBaud'].value + code = this_metadata_file['code'].value + + if not ippKm: + try: + #seconds to km + ippKm = 1e6*0.15*this_metadata_file['ipp'].value + except: + ippKm = None + + #################################################### + startUTCSecond = None + endUTCSecond = None + + if startDate: + startDatetime = datetime.datetime.combine(startDate, startTime) + startUTCSecond = (startDatetime-datetime.datetime(1970,1,1)).total_seconds() + self.__timezone + + if endDate: + endDatetime = datetime.datetime.combine(endDate, endTime) + endUTCSecond = (endDatetime-datetime.datetime(1970,1,1)).total_seconds() + self.__timezone + + start_index, end_index = self.digitalReadObj.get_bounds(channelNameList[channelList[0]]) + + if not startUTCSecond: + startUTCSecond = start_index/self.__sample_rate + + if start_index > startUTCSecond*self.__sample_rate: + startUTCSecond = start_index/self.__sample_rate + + if not endUTCSecond: + endUTCSecond = end_index/self.__sample_rate + + if end_index < endUTCSecond*self.__sample_rate: + endUTCSecond = end_index/self.__sample_rate + + if not nSamples: + if not ippKm: + raise ValueError, "[Reading] nSamples or ippKm should be defined" + + nSamples = int(ippKm / (1e6*0.15/self.__sample_rate)) + + channelBoundList = [] + channelNameListFiltered = [] + + for thisIndexChannel in channelList: + thisChannelName = channelNameList[thisIndexChannel] + start_index, end_index = self.digitalReadObj.get_bounds(thisChannelName) + channelBoundList.append((start_index, end_index)) + channelNameListFiltered.append(thisChannelName) + + self.profileIndex = 0 + + self.__delay = delay + self.__ippKm = ippKm + self.__codeType = codeType + self.__nCode = nCode + self.__nBaud = nBaud + self.__code = code + + self.__datapath = path + self.__online = online + self.__channelList = channelList + self.__channelNameList = channelNameListFiltered + self.__channelBoundList = channelBoundList + self.__nSamples = nSamples + self.__samples_to_read = int(buffer_size*nSamples) + self.__nChannels = len(self.__channelList) + + self.__startUTCSecond = startUTCSecond + self.__endUTCSecond = endUTCSecond + + self.__timeInterval = 1.0 * self.__samples_to_read/self.__sample_rate #Time interval + + if online: +# self.__thisUnixSample = int(endUTCSecond*self.__sample_rate - 4*self.__samples_to_read) + startUTCSecond = numpy.floor(endUTCSecond) + + self.__thisUnixSample = int(startUTCSecond*self.__sample_rate) - self.__samples_to_read + + self.__data_buffer = numpy.zeros((self.__nChannels, self.__samples_to_read), dtype = numpy.complex) + + self.__setFileHeader() + self.isConfig = True + + print "[Reading] USRP Data was found from %s to %s " %( + datetime.datetime.utcfromtimestamp(self.__startUTCSecond - self.__timezone), + datetime.datetime.utcfromtimestamp(self.__endUTCSecond - self.__timezone) + ) + + print "[Reading] Starting process from %s to %s" %(datetime.datetime.utcfromtimestamp(startUTCSecond - self.__timezone), + datetime.datetime.utcfromtimestamp(endUTCSecond - self.__timezone) + ) + + def __reload(self): + + if not self.__online: + return + +# print +# print "%s not in range [%s, %s]" %( +# datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone), +# datetime.datetime.utcfromtimestamp(self.__startUTCSecond - self.__timezone), +# datetime.datetime.utcfromtimestamp(self.__endUTCSecond - self.__timezone) +# ) + print "[Reading] reloading metadata ..." + + try: + self.digitalReadObj.reload(complete_update=True) + except: + self.digitalReadObj.reload() + + start_index, end_index = self.digitalReadObj.get_bounds(self.__channelNameList[self.__channelList[0]]) + + if start_index > self.__startUTCSecond*self.__sample_rate: + self.__startUTCSecond = 1.0*start_index/self.__sample_rate + + if end_index > self.__endUTCSecond*self.__sample_rate: + self.__endUTCSecond = 1.0*end_index/self.__sample_rate + print + print "[Reading] New timerange found [%s, %s] " %( + datetime.datetime.utcfromtimestamp(self.__startUTCSecond - self.__timezone), + datetime.datetime.utcfromtimestamp(self.__endUTCSecond - self.__timezone) + ) + + return True + + return False + + def __readNextBlock(self, seconds=30, volt_scale = 218776): + ''' + ''' + + #Set the next data + self.__flagDiscontinuousBlock = False + self.__thisUnixSample += self.__samples_to_read + + if self.__thisUnixSample + 2*self.__samples_to_read > self.__endUTCSecond*self.__sample_rate: + print "[Reading] There are no more data into selected time-range" + + self.__reload() + + if self.__thisUnixSample + 2*self.__samples_to_read > self.__endUTCSecond*self.__sample_rate: + self.__thisUnixSample -= self.__samples_to_read + return False + + indexChannel = 0 + + dataOk = False + + for thisChannelName in self.__channelNameList: + + try: + result = self.digitalReadObj.read_vector_c81d(self.__thisUnixSample, + self.__samples_to_read, + thisChannelName) + + except IOError, e: + #read next profile + self.__flagDiscontinuousBlock = True + print "[Reading] %s" %datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone), e + break + + if result.shape[0] != self.__samples_to_read: + self.__flagDiscontinuousBlock = True + print "[Reading] %s: Too few samples were found, just %d/%d samples" %(datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone), + result.shape[0], + self.__samples_to_read) + break + + self.__data_buffer[indexChannel,:] = result*volt_scale + + indexChannel += 1 + + dataOk = True + + self.__utctime = self.__thisUnixSample/self.__sample_rate + + if not dataOk: + return False + + print "[Reading] %s: %d samples <> %f sec" %(datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone), + self.__samples_to_read, + self.__timeInterval) + + self.__bufferIndex = 0 + + return True + + def __isBufferEmpty(self): + + if self.__bufferIndex <= self.__samples_to_read - self.__nSamples: + return False + + return True + + def getData(self, seconds=30, nTries=5): + + ''' + This method gets the data from files and put the data into the dataOut object + + In addition, increase el the buffer counter in one. + + Return: + data : retorna un perfil de voltages (alturas * canales) copiados desde el + buffer. Si no hay mas archivos a leer retorna None. + + Affected: + self.dataOut + self.profileIndex + self.flagDiscontinuousBlock + self.flagIsNewBlock + ''' + + err_counter = 0 + self.dataOut.flagNoData = True + + if self.__isBufferEmpty(): + + self.__flagDiscontinuousBlock = False + + while True: + if self.__readNextBlock(): + break + + if self.__thisUnixSample > self.__endUTCSecond*self.__sample_rate: + return False + + if self.__flagDiscontinuousBlock: + print '[Reading] discontinuous block found ... continue with the next block' + continue + + if not self.__online: + return False + + err_counter += 1 + if err_counter > nTries: + return False + + print '[Reading] waiting %d seconds to read a new block' %seconds + sleep(seconds) + + self.dataOut.data = self.__data_buffer[:,self.__bufferIndex:self.__bufferIndex+self.__nSamples] + self.dataOut.utctime = (self.__thisUnixSample + self.__bufferIndex)/self.__sample_rate + self.dataOut.flagNoData = False + self.dataOut.flagDiscontinuousBlock = self.__flagDiscontinuousBlock + self.dataOut.profileIndex = self.profileIndex + + self.__bufferIndex += self.__nSamples + self.profileIndex += 1 + + if self.profileIndex == self.dataOut.nProfiles: + self.profileIndex = 0 + + return True + + def printInfo(self): + ''' + ''' + if self.__printInfo == False: + return + +# self.systemHeaderObj.printInfo() +# self.radarControllerHeaderObj.printInfo() + + self.__printInfo = False + + def printNumberOfBlock(self): + ''' + ''' + + print self.profileIndex + + def run(self, **kwargs): + ''' + This method will be called many times so here you should put all your code + ''' + + if not self.isConfig: + self.setup(**kwargs) + + self.getData(seconds=self.__delay) + + return + +class USRPWriter(Operation): + ''' + classdocs + ''' + + def __init__(self): + ''' + Constructor + ''' + self.dataOut = None + + def setup(self, dataIn, path, blocksPerFile, set=0, ext=None): + ''' + In this method we should set all initial parameters. + + Input: + dataIn : Input data will also be outputa data + + ''' + self.dataOut = dataIn + + + + + + self.isConfig = True + + return + + def run(self, dataIn, **kwargs): + ''' + This method will be called many times so here you should put all your code + + Inputs: + + dataIn : object with the data + + ''' + + if not self.isConfig: + self.setup(dataIn, **kwargs) + + +if __name__ == '__main__': + + readObj = USRPReader() + + while True: + readObj.run(path='/Volumes/DATA/haystack/passive_radar/') +# readObj.printInfo() + readObj.printNumberOfBlock() + + \ No newline at end of file diff --git a/schainpy/model/io/.svn/text-base/jroIO_usrp.pyc.svn-base b/schainpy/model/io/.svn/text-base/jroIO_usrp.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..4645de4cce89036127a995c2edc46ae477350077 GIT binary patch literal 14370 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 20: + break + + sleep(1e-12) + + +# if not self.getData(): +# self.__isBufferEmpty = False +# return None + + if self.dataOut.flagNoData: + return None + + myMetadataSerial = obj2Serial(self.dataOut, + serializer = self.__serializer) + + return myMetadataSerial + + def getSerialData(self): + + if self.__isBufferEmpty: + ini = time.time() + + while True: + + if not self.__isBufferEmpty: + break + + if time.time() - ini > 20: + break + + sleep(1e-12) + + +# if not self.getData(): +# self.__isBufferEmpty = False +# return None + + if self.dataOut.flagNoData: + return None + + self.__isBufferEmpty = True + + return self.__mySerial + + def run(self): + + ''' + This method will be called once when start() is called + ''' + + if not self.isConfig: + raise RuntimeError, 'setup() method has to be called before start()' + + print "Running ..." + + while True: + + if not self.__isBufferEmpty: + sleep(1e-12) + continue + + if not self.getData(): + break + + print ".", + + self.__mySerial = obj2Serial(self.dataOut, + keyList = self.__DATAKEYLIST, + serializer = self.__serializer) + self.__isBufferEmpty = False + +# print self.profileIndex +# print 'wait 1 second' + +# sleep(0.1) + + print "Closing thread" + + return \ No newline at end of file diff --git a/schainpy/model/io/.svn/text-base/jroIO_voltage.py.svn-base b/schainpy/model/io/.svn/text-base/jroIO_voltage.py.svn-base new file mode 100644 index 0000000..74e3a9d --- /dev/null +++ b/schainpy/model/io/.svn/text-base/jroIO_voltage.py.svn-base @@ -0,0 +1,637 @@ +''' +Created on Jul 2, 2014 + +@author: roj-idl71 +''' + +import numpy + +from jroIO_base import LOCALTIME, JRODataReader, JRODataWriter +from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation +from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader +from schainpy.model.data.jrodata import Voltage +# from _sha import blocksize + +class VoltageReader(JRODataReader, ProcessingUnit): + """ + Esta clase permite leer datos de voltage desde archivos en formato rawdata (.r). La lectura + de los datos siempre se realiza por bloques. Los datos leidos (array de 3 dimensiones: + perfiles*alturas*canales) son almacenados en la variable "buffer". + + perfiles * alturas * canales + + Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader, + RadarControllerHeader y Voltage. Los tres primeros se usan para almacenar informacion de la + cabecera de datos (metadata), y el cuarto (Voltage) para obtener y almacenar un perfil de + datos desde el "buffer" cada vez que se ejecute el metodo "getData". + + Example: + + dpath = "/home/myuser/data" + + startTime = datetime.datetime(2010,1,20,0,0,0,0,0,0) + + endTime = datetime.datetime(2010,1,21,23,59,59,0,0,0) + + readerObj = VoltageReader() + + readerObj.setup(dpath, startTime, endTime) + + while(True): + + #to get one profile + profile = readerObj.getData() + + #print the profile + print profile + + #If you want to see all datablock + print readerObj.datablock + + if readerObj.flagNoMoreFiles: + break + + """ + + ext = ".r" + + optchar = "D" + dataOut = None + + def __init__(self): + """ + Inicializador de la clase VoltageReader para la lectura de datos de voltage. + + Input: + dataOut : Objeto de la clase Voltage. Este objeto sera utilizado para + almacenar un perfil de datos cada vez que se haga un requerimiento + (getData). El perfil sera obtenido a partir del buffer de datos, + si el buffer esta vacio se hara un nuevo proceso de lectura de un + bloque de datos. + Si este parametro no es pasado se creara uno internamente. + + Variables afectadas: + self.dataOut + + Return: + None + """ + + ProcessingUnit.__init__(self) + + self.isConfig = False + + self.datablock = None + + self.utc = 0 + + self.ext = ".r" + + self.optchar = "D" + + self.basicHeaderObj = BasicHeader(LOCALTIME) + + self.systemHeaderObj = SystemHeader() + + self.radarControllerHeaderObj = RadarControllerHeader() + + self.processingHeaderObj = ProcessingHeader() + + self.online = 0 + + self.fp = None + + self.idFile = None + + self.dtype = None + + self.fileSizeByHeader = None + + self.filenameList = [] + + self.filename = None + + self.fileSize = None + + self.firstHeaderSize = 0 + + self.basicHeaderSize = 24 + + self.pathList = [] + + self.filenameList = [] + + self.lastUTTime = 0 + + self.maxTimeStep = 30 + + self.flagNoMoreFiles = 0 + + self.set = 0 + + self.path = None + + self.profileIndex = 2**32-1 + + self.delay = 3 #seconds + + self.nTries = 3 #quantity tries + + self.nFiles = 3 #number of files for searching + + self.nReadBlocks = 0 + + self.flagIsNewFile = 1 + + self.__isFirstTimeOnline = 1 + +# self.ippSeconds = 0 + + self.flagDiscontinuousBlock = 0 + + self.flagIsNewBlock = 0 + + self.nTotalBlocks = 0 + + self.blocksize = 0 + + self.dataOut = self.createObjByDefault() + + self.nTxs = 1 + + self.txIndex = 0 + + def createObjByDefault(self): + + dataObj = Voltage() + + return dataObj + + def __hasNotDataInBuffer(self): + + if self.profileIndex >= self.processingHeaderObj.profilesPerBlock*self.nTxs: + return 1 + + return 0 + + + def getBlockDimension(self): + """ + Obtiene la cantidad de puntos a leer por cada bloque de datos + + Affected: + self.blocksize + + Return: + None + """ + pts2read = self.processingHeaderObj.profilesPerBlock * self.processingHeaderObj.nHeights * self.systemHeaderObj.nChannels + self.blocksize = pts2read + + + def readBlock(self): + """ + readBlock lee el bloque de datos desde la posicion actual del puntero del archivo + (self.fp) y actualiza todos los parametros relacionados al bloque de datos + (metadata + data). La data leida es almacenada en el buffer y el contador del buffer + es seteado a 0 + + Inputs: + None + + Return: + None + + Affected: + self.profileIndex + self.datablock + self.flagIsNewFile + self.flagIsNewBlock + self.nTotalBlocks + + Exceptions: + Si un bloque leido no es un bloque valido + """ + current_pointer_location = self.fp.tell() + junk = numpy.fromfile( self.fp, self.dtype, self.blocksize ) + + try: + junk = junk.reshape( (self.processingHeaderObj.profilesPerBlock, self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels) ) + except: + #print "The read block (%3d) has not enough data" %self.nReadBlocks + + if self.waitDataBlock(pointer_location=current_pointer_location): + junk = numpy.fromfile( self.fp, self.dtype, self.blocksize ) + junk = junk.reshape( (self.processingHeaderObj.profilesPerBlock, self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels) ) +# return 0 + + #Dimensions : nChannels, nProfiles, nSamples + + junk = numpy.transpose(junk, (2,0,1)) + self.datablock = junk['real'] + junk['imag']*1j + + self.profileIndex = 0 + + self.flagIsNewFile = 0 + self.flagIsNewBlock = 1 + + self.nTotalBlocks += 1 + self.nReadBlocks += 1 + + return 1 + + def getFirstHeader(self): + + self.getBasicHeader() + + self.dataOut.systemHeaderObj = self.systemHeaderObj.copy() + + self.dataOut.radarControllerHeaderObj = self.radarControllerHeaderObj.copy() + + if self.nTxs > 1: + self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds/self.nTxs + + #Time interval and code are propierties of dataOut. Its value depends of radarControllerHeaderObj. + +# self.dataOut.timeInterval = self.radarControllerHeaderObj.ippSeconds * self.processingHeaderObj.nCohInt +# +# if self.radarControllerHeaderObj.code is not None: +# +# self.dataOut.nCode = self.radarControllerHeaderObj.nCode +# +# self.dataOut.nBaud = self.radarControllerHeaderObj.nBaud +# +# self.dataOut.code = self.radarControllerHeaderObj.code + + self.dataOut.dtype = self.dtype + + self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock + + self.dataOut.heightList = numpy.arange(self.processingHeaderObj.nHeights) *self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight + + self.dataOut.channelList = range(self.systemHeaderObj.nChannels) + + self.dataOut.nCohInt = self.processingHeaderObj.nCohInt + + self.dataOut.flagDecodeData = self.processingHeaderObj.flag_decode #asumo q la data no esta decodificada + + self.dataOut.flagDeflipData = self.processingHeaderObj.flag_deflip #asumo q la data no esta sin flip + + self.dataOut.flagShiftFFT = self.processingHeaderObj.shif_fft + + def reshapeData(self): + + if self.nTxs < 0: + return + + if self.nTxs == 1: + return + + if self.nTxs < 1 and self.processingHeaderObj.profilesPerBlock % (1./self.nTxs) != 0: + raise ValueError, "1./nTxs (=%f), should be a multiple of nProfiles (=%d)" %(1./self.nTxs, self.processingHeaderObj.profilesPerBlock) + + if self.nTxs > 1 and self.processingHeaderObj.nHeights % self.nTxs != 0: + raise ValueError, "nTxs (=%d), should be a multiple of nHeights (=%d)" %(self.nTxs, self.processingHeaderObj.nHeights) + + self.datablock = self.datablock.reshape((self.systemHeaderObj.nChannels, self.processingHeaderObj.profilesPerBlock*self.nTxs, self.processingHeaderObj.nHeights/self.nTxs)) + + self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock*self.nTxs + self.dataOut.heightList = numpy.arange(self.processingHeaderObj.nHeights/self.nTxs) *self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight + self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds/self.nTxs + + return + + def getData(self): + """ + getData obtiene una unidad de datos del buffer de lectura, un perfil, y la copia al objeto self.dataOut + del tipo "Voltage" con todos los parametros asociados a este (metadata). cuando no hay datos + en el buffer de lectura es necesario hacer una nueva lectura de los bloques de datos usando + "readNextBlock" + + Ademas incrementa el contador del buffer "self.profileIndex" en 1. + + Return: + + Si el flag self.getByBlock ha sido seteado el bloque completo es copiado a self.dataOut y el self.profileIndex + es igual al total de perfiles leidos desde el archivo. + + Si self.getByBlock == False: + + self.dataOut.data = buffer[:, thisProfile, :] + + shape = [nChannels, nHeis] + + Si self.getByBlock == True: + + self.dataOut.data = buffer[:, :, :] + + shape = [nChannels, nProfiles, nHeis] + + Variables afectadas: + self.dataOut + self.profileIndex + + Affected: + self.dataOut + self.profileIndex + self.flagDiscontinuousBlock + self.flagIsNewBlock + """ + + if self.flagNoMoreFiles: + self.dataOut.flagNoData = True + print 'Process finished' + return 0 + + self.flagDiscontinuousBlock = 0 + self.flagIsNewBlock = 0 + + if self.__hasNotDataInBuffer(): + + if not( self.readNextBlock() ): + return 0 + + self.getFirstHeader() + + self.reshapeData() + + if self.datablock is None: + self.dataOut.flagNoData = True + return 0 + + if not self.getByBlock: + + """ + Return profile by profile + + If nTxs > 1 then one profile is divided by nTxs and number of total + blocks is increased by nTxs (nProfiles *= nTxs) + """ + self.dataOut.flagDataAsBlock = False + self.dataOut.data = self.datablock[:,self.profileIndex,:] + self.dataOut.profileIndex = self.profileIndex + + self.profileIndex += 1 + +# elif self.selBlocksize==None or self.selBlocksize==self.dataOut.nProfiles: +# """ +# Return all block +# """ +# self.dataOut.flagDataAsBlock = True +# self.dataOut.data = self.datablock +# self.dataOut.profileIndex = self.dataOut.nProfiles - 1 +# +# self.profileIndex = self.dataOut.nProfiles + + else: + """ + Return a block + """ + if self.selBlocksize == None: self.selBlocksize = self.dataOut.nProfiles + if self.selBlocktime != None: + if self.dataOut.nCohInt is not None: + nCohInt = self.dataOut.nCohInt + else: + nCohInt = 1 + self.selBlocksize = int(self.dataOut.nProfiles*round(self.selBlocktime/(nCohInt*self.dataOut.ippSeconds*self.dataOut.nProfiles))) + + self.dataOut.data = self.datablock[:,self.profileIndex:self.profileIndex+self.selBlocksize,:] + self.profileIndex += self.selBlocksize + datasize = self.dataOut.data.shape[1] + + if datasize < self.selBlocksize: + buffer = numpy.zeros((self.dataOut.data.shape[0],self.selBlocksize,self.dataOut.data.shape[2]), dtype = 'complex') + buffer[:,:datasize,:] = self.dataOut.data + + while datasize < self.selBlocksize: #Not enough profiles to fill the block + if not( self.readNextBlock() ): + return 0 + self.getFirstHeader() + self.reshapeData() + if self.datablock is None: + self.dataOut.flagNoData = True + return 0 + #stack data + blockIndex = self.selBlocksize - datasize + datablock1 = self.datablock[:,:blockIndex,:] + + buffer[:,datasize:datasize+datablock1.shape[1],:] = datablock1 + datasize += datablock1.shape[1] + + self.dataOut.data = buffer + self.profileIndex = blockIndex + + self.dataOut.flagDataAsBlock = True + self.dataOut.nProfiles = self.dataOut.data.shape[1] + + self.dataOut.flagNoData = False + + self.getBasicHeader() + + self.dataOut.realtime = self.online + + return self.dataOut.data + +class VoltageWriter(JRODataWriter, Operation): + """ + Esta clase permite escribir datos de voltajes a archivos procesados (.r). La escritura + de los datos siempre se realiza por bloques. + """ + + ext = ".r" + + optchar = "D" + + shapeBuffer = None + + + def __init__(self): + """ + Inicializador de la clase VoltageWriter para la escritura de datos de espectros. + + Affected: + self.dataOut + + Return: None + """ + Operation.__init__(self) + + self.nTotalBlocks = 0 + + self.profileIndex = 0 + + self.isConfig = False + + self.fp = None + + self.flagIsNewFile = 1 + + self.blockIndex = 0 + + self.flagIsNewBlock = 0 + + self.setFile = None + + self.dtype = None + + self.path = None + + self.filename = None + + self.basicHeaderObj = BasicHeader(LOCALTIME) + + self.systemHeaderObj = SystemHeader() + + self.radarControllerHeaderObj = RadarControllerHeader() + + self.processingHeaderObj = ProcessingHeader() + + def hasAllDataInBuffer(self): + if self.profileIndex >= self.processingHeaderObj.profilesPerBlock: + return 1 + return 0 + + + def setBlockDimension(self): + """ + Obtiene las formas dimensionales del los subbloques de datos que componen un bloque + + Affected: + self.shape_spc_Buffer + self.shape_cspc_Buffer + self.shape_dc_Buffer + + Return: None + """ + self.shapeBuffer = (self.processingHeaderObj.profilesPerBlock, + self.processingHeaderObj.nHeights, + self.systemHeaderObj.nChannels) + + self.datablock = numpy.zeros((self.systemHeaderObj.nChannels, + self.processingHeaderObj.profilesPerBlock, + self.processingHeaderObj.nHeights), + dtype=numpy.dtype('complex64')) + + def writeBlock(self): + """ + Escribe el buffer en el file designado + + Affected: + self.profileIndex + self.flagIsNewFile + self.flagIsNewBlock + self.nTotalBlocks + self.blockIndex + + Return: None + """ + data = numpy.zeros( self.shapeBuffer, self.dtype ) + + junk = numpy.transpose(self.datablock, (1,2,0)) + + data['real'] = junk.real + data['imag'] = junk.imag + + data = data.reshape( (-1) ) + + data.tofile( self.fp ) + + self.datablock.fill(0) + + self.profileIndex = 0 + self.flagIsNewFile = 0 + self.flagIsNewBlock = 1 + + self.blockIndex += 1 + self.nTotalBlocks += 1 + +# print "[Writing] Block = %04d" %self.blockIndex + + def putData(self): + """ + Setea un bloque de datos y luego los escribe en un file + + Affected: + self.flagIsNewBlock + self.profileIndex + + Return: + 0 : Si no hay data o no hay mas files que puedan escribirse + 1 : Si se escribio la data de un bloque en un file + """ + if self.dataOut.flagNoData: + return 0 + + self.flagIsNewBlock = 0 + + if self.dataOut.flagDiscontinuousBlock: + self.datablock.fill(0) + self.profileIndex = 0 + self.setNextFile() + + if self.profileIndex == 0: + self.setBasicHeader() + + self.datablock[:,self.profileIndex,:] = self.dataOut.data + + self.profileIndex += 1 + + if self.hasAllDataInBuffer(): + #if self.flagIsNewFile: + self.writeNextBlock() +# self.setFirstHeader() + + return 1 + + def __getBlockSize(self): + ''' + Este metodos determina el cantidad de bytes para un bloque de datos de tipo Voltage + ''' + + dtype_width = self.getDtypeWidth() + + blocksize = int(self.dataOut.nHeights * self.dataOut.nChannels * self.profilesPerBlock * dtype_width * 2) + + return blocksize + + def setFirstHeader(self): + + """ + Obtiene una copia del First Header + + Affected: + self.systemHeaderObj + self.radarControllerHeaderObj + self.dtype + + Return: + None + """ + + self.systemHeaderObj = self.dataOut.systemHeaderObj.copy() + self.systemHeaderObj.nChannels = self.dataOut.nChannels + self.radarControllerHeaderObj = self.dataOut.radarControllerHeaderObj.copy() + + self.processingHeaderObj.dtype = 0 # Voltage + self.processingHeaderObj.blockSize = self.__getBlockSize() + self.processingHeaderObj.profilesPerBlock = self.profilesPerBlock + self.processingHeaderObj.dataBlocksPerFile = self.blocksPerFile + self.processingHeaderObj.nWindows = 1 #podria ser 1 o self.dataOut.processingHeaderObj.nWindows + self.processingHeaderObj.nCohInt = self.dataOut.nCohInt + self.processingHeaderObj.nIncohInt = 1 # Cuando la data de origen es de tipo Voltage + self.processingHeaderObj.totalSpectra = 0 # Cuando la data de origen es de tipo Voltage + + if self.dataOut.code is not None: + self.processingHeaderObj.code = self.dataOut.code + self.processingHeaderObj.nCode = self.dataOut.nCode + self.processingHeaderObj.nBaud = self.dataOut.nBaud + + if self.processingHeaderObj.nWindows != 0: + self.processingHeaderObj.firstHeight = self.dataOut.heightList[0] + self.processingHeaderObj.deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0] + self.processingHeaderObj.nHeights = self.dataOut.nHeights + self.processingHeaderObj.samplesWin = self.dataOut.nHeights + + self.processingHeaderObj.processFlags = self.getProcessFlags() + + self.setBasicHeader() \ No newline at end of file diff --git a/schainpy/model/io/.svn/text-base/jroIO_voltage.pyc.svn-base b/schainpy/model/io/.svn/text-base/jroIO_voltage.pyc.svn-base new file mode 100644 index 0000000000000000000000000000000000000000..c2b47f7a85e51d302d14b02d685aaf1ceb550908 GIT binary patch literal 16529 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 + ('SPARrawGate2','T}oOXC{XHYG`wy{fO_1L*14 zvYl|g{PKl!5>Df{hkn@UJ99SSLEb{@1O##h>N<(%WUlkJAV~U%qVJ(t&?)GHIX$d ztx9ubk4u^ht<0e{N~&mXy1OPHd&Tq2sJ$n1q3C$Rf_nTr(GMUvl{v>;3AV)FQZ02! z8ONHXR1}2IC8GsjD7taV70zYCGb|(~L=?gh0yA5G;~H+NjNi2C)+Zos54r2L-Q9l? CY<=|r literal 0 Hc$@ dateFile)): + continue + + self.fileList.append(thisFile) + self.dateFileList.append(dateFile) + + return 1 + + + def setNextFile(self): + + idFile = self.fileIndex + + while (True): + idFile += 1 + if idFile >= len(self.fileList): + print '\nNo more files in the folder' + print 'Total number of file(s) read : {}'.format(self.fileIndex + 1) + print 'Time of processing : {}'.format(datetime.datetime.now()- self.hoy) + self.flagNoMoreFiles = 1 + return 0 + if self.isConfig: print '------------------------[Next File]---------------------------' + filename = os.path.join(self.path, self.fileList[idFile]) + self.Open(filename) + + print '\n[Setting file] (%s) ...' % self.fileList[idFile] + + break + + self.flagIsNewFile =0 + + self.fileIndex = idFile + self.filename = filename + print 'File:',self.filename + + return 1 + + def readDataBlock(self): + + + self.readHeader() + self.dataRecords(0) + + print '[New Record] record: {} /{} // file {}/{}'.format(self.counter_records,self.nrecords,self.fileIndex+1,len(self.fileList)) + + self.setDataBuffer() + + self.flagIsNewBlock = 1 + + if self.counter_records > self.nrecords: + self.flagIsNewFile = 1 + return 0 + + return 1 + + def setDataBuffer(self): + + ''' + Storing data from one block + + ''' + self.t = datetime.datetime(self.year, self.month, self.day) + self.doy = time.localtime(time.mktime(self.t.timetuple())).tm_yday + self.buffer = numpy.squeeze(numpy.array([[self.one_snr],[self.one_zonal],[self.one_vertical],[self.one_meridional], + [self.time],[self.height],[self.fileIndex], + [self.year],[self.month],[self.day],[self.t],[self.doy]])) + + self.dataOut.time1 = self.time1 + + def Open(self, filename): + ''' + Opening BLTR rawdata file defined by filename + + Inputs: + + filename - Full path name of BLTR rawdata file + + ''' + [dir, name] = os.path.split(filename) + strFile = name.split('.') + self.siteFile = strFile[0] # 'peru2' ---> Piura - 'peru1' ---> Huancayo or Porcuya + + self.filename = filename + if os.path.isfile(self.filename) == False: + print 'File do not exist. Check "filename"' + sys.exit(0) + + self.h_file = numpy.dtype([ + ('FMN', '= 0., self.dataOut.height[0, :] <= self.hcm, numpy.isfinite(self.dataOut.height[0, :]))) + else: + h_select = numpy.where(numpy.bitwise_and(self.dataOut.height[0, :] >= 0., self.dataOut.height[0, :] < 20, numpy.isfinite(self.dataOut.height[0, :]))) + + ht = h_select[0] + + self.o_height = self.dataOut.height[self.im, ht] + self.o_zon = self.z_zon[ht, self.im] + self.o_mer = self.z_mer[ht, self.im] + self.o_ver = self.z_ver[ht, self.im] + o_snr = self.dataOut.data_SNR[ :, :, self.im] + + o_snr = o_snr[ht, :] + + ndiv = numpy.nansum((numpy.isfinite(o_snr)), 1) + ndiv = ndiv.astype(float) + + sel_div = numpy.where(ndiv == 0.) + ndiv[sel_div] = numpy.nan + + if self.nchannels > 1: + msnr = numpy.nansum(o_snr, axis=1) + else: + msnr = o_snr + + try: + self.msnr = 10 * numpy.log10(msnr / ndiv) + except ZeroDivisionError: + self.msnr = 10 * numpy.log10(msnr /1) + print 'Number of division (ndiv) egal to 1 by default. Check SNR' + + time_t = time.gmtime(self.dataOut.time1) + year = time_t.tm_year + month = time_t.tm_mon + day = time_t.tm_mday + hour = time_t.tm_hour + minute = time_t.tm_min + second = time_t.tm_sec + timedate_0 = datetime.datetime(year, month, day, hour, minute, second) + + # 1d parameters + GDLATR = self.lat + GDLONR = self.lon + GDLAT2 = self.lat + GLON2 = self.lon + + # 2d parameters + GDALT = self.o_height + + SNL = self.msnr + VN1P2 = self.o_zon + VN2P2 = self.o_mer + EL2 = self.o_ver + NROW = len(self.o_height) + + startTime = timedate_0 + endTime = startTime + self.dataRec = madrigal.cedar.MadrigalDataRecord(self.kinst, + self.kindat, + startTime.year, + startTime.month, + startTime.day, + startTime.hour, + startTime.minute, + startTime.second, + 0, + endTime.year, + endTime.month, + endTime.day, + endTime.hour, + endTime.minute, + endTime.second, + 0, + ('gdlatr', 'gdlonr', 'gdlat2', 'glon2'), + ('gdalt', 'snl', 'vn1p2', 'vn2p2', 'el2'), + NROW, ind2DList=['gdalt']) + + # Setting 1d values + self.dataRec.set1D('gdlatr', GDLATR) + self.dataRec.set1D('gdlonr', GDLONR) + self.dataRec.set1D('gdlat2', GDLAT2) + self.dataRec.set1D('glon2', GLON2) + + # Setting 2d values + for n in range(self.o_height.shape[0]): + self.dataRec.set2D('gdalt', n, GDALT[n]) + self.dataRec.set2D('snl', n, SNL[n]) + self.dataRec.set2D('vn1p2', n, VN1P2[n]) + self.dataRec.set2D('vn2p2', n, VN2P2[n]) + self.dataRec.set2D('el2', n, EL2[n]) + + # Appending new data record + ''' + [MADRIGAL3]There are two ways to write to a MadrigalCedarFile. Either this method (write) is called after all the + records have been appended to the MadrigalCedarFile, or dump is called after a certain number of records are appended, + and then at the end dump is called a final time if there were any records not yet dumped, followed by addArray. + ''' + + self.cedarObj.append(self.dataRec) + print ' [Writing] records {} (mode {}).'.format(self.dataOut.counter_records,self.im+1) + self.cedarObj.dump() + + + + + def setHeader(self): + ''' + - Creating self.catHeadObj + - Adding information catalog + - Writing file header + + ''' + self.catHeadObj = madrigal.cedar.CatalogHeaderCreator(self.fullname) + kindatDesc, comments, analyst, history, principleInvestigator = self._info_BLTR() + + self.catHeadObj.createCatalog(principleInvestigator="Jarjar", + expPurpose='characterize the atmospheric dynamics in this region where frequently it happens the El Nino', + sciRemarks="http://madrigal3.haystack.mit.edu/static/CEDARMadrigalHdf5Format.pdf") + + self.catHeadObj.createHeader(kindatDesc, analyst, comments, history) + + self.catHeadObj.write() + + print '[File created] path: %s' % (self.fullname) + + def putData(self): + + if self.dataOut.flagNoData: + return 0 + + if self.dataOut.counter_records == 1: + self.setFile() + print '[Writing] Setting new hdf5 file for the mode {}'.format(self.im+1) + + if self.dataOut.counter_records <= self.dataOut.nrecords: + self.writeBlock() + + + if self.dataOut.counter_records == self.dataOut.nrecords: + self.cedarObj.addArray() + + self.setHeader() + self.flagIsNewFile = 1 + + def _info_BLTR(self): + + kindatDesc = '''--This header is for KINDAT = %d''' % self.kindat + history = None + analyst = '''Jarjar''' + principleInvestigator = ''' + Jarjar + Radio Observatorio de Jicamarca + Instituto Geofisico del Peru + + ''' + if self.type == 1: + comments = ''' + + --These data are provided by two Boundary Layer and Tropospheric Radar (BLTR) deployed at two different locations at Peru(GMT-5), one of them at Piura(5.17 S, 80.64W) and another located at Huancayo (12.04 S, 75.32 W). + + --The purpose of conducting these observations is to measure wind in the differents levels of height, this radar makes measurements the Zonal(U), Meridional(V) and Vertical(W) wind velocities component in northcoast from Peru. And the main purpose of these mensurations is to characterize the atmospheric dynamics in this region where frequently it happens the 'El Nino Phenomenon' + + --In Kindat = 1600, contains information of wind velocities component since 0 Km to 3 Km. + + --In Kindat = 1601, contains information of wind velocities component since 0 Km to 10 Km. + + --The Huancayo-BLTR is a VHF Profiler Radar System is a 3 channel coherent receiver pulsed radar utilising state-of-the-art software and computing techniques to acquire, decode, and translate signals obtained from partial reflection echoes in the troposphere, lower stratosphere and mesosphere. It uses an array of three horizontal spaced and vertically directed receiving antennas. The data is recorded thirty seconds, averaged to one minute mean values of Height, Zonal, Meridional and Vertical wind. + + --The Huancayo-BLTR was installed in January 2010. This instrument was designed and constructed by Genesis Soft Pty. Ltd. Is constituted by three groups of spaced antennas (distributed) forming an isosceles triangle. + + + Station _______ Geographic Coord ______ Geomagnetic Coord + + _______________ Latitude _ Longitude __ Latitude _ Longitude + + Huancayo (HUA) __12.04 S ___ 75.32 W _____ -12.05 ____ 352.85 + Piura (PIU) _____ 5.17 S ___ 80.64 W ______ 5.18 ____ 350.93 + + WIND OBSERVATIONS + + --To obtain wind the BLTR uses Spaced Antenna technique (e.g., Briggs 1984). The scatter and reflection it still provided by variations in the refractive index as in the Doppler method(Gage and Basley,1978; Balsley and Gage 1982; Larsen and Rottger 1982), but instead of using the Doppler shift to derive the velocity components, the cross-correlation between signals in an array of three horizontally spaced and vertically directed receiving antennas is used. + + ...................................................................... + For more information, consult the following references: + - Balsley, B. B., and K. S. Gage., On the use of radars for operational wind profiling, Bull. Amer. Meteor.Soc.,63, 1009-1018, 1982. + + - Briggs, B. H., The analysis of spaced sensor data by correations techniques, Handbook for MAP, Vol. 13, SCOTEP Secretariat, University of Illinois, Urbana, 166-186, 1984. + + - Gage, K. S., and B.B. Balsley., Doppler radar probing of the clear atmosphere, Bull. Amer. Meteor.Soc., 59, 1074-1093, 1978. + + - Larsen, M. F., The Spaced Antenna Technique for Radar Wind Profiling, Journal of Atm. and Ocean. Technology. , Vol.6, 920-937, 1989. + + - Larsen, M. F., A method for single radar voracity measurements?, Handbook for MAP,SCOSTEP Secretariat, University of the Illinois, Urban, in press, 1989. + ...................................................................... + + ACKNOWLEDGEMENTS: + + --The Piura and Huancayo BLTR are part of the network of instruments operated by the Jicamarca Radio Observatory. + + --The Jicamarca Radio Observatory is a facility of the Instituto Geofisico del Peru operated with support from the NSF Cooperative Agreement ATM-0432565 through Cornell University + + ...................................................................... + + Further questions and comments should be addressed to: + Radio Observatorio de Jicamarca + Instituto Geofisico del Peru + Lima, Peru + Web URL: http://jro.igp.gob.pe + ...................................................................... + ''' + + return kindatDesc, comments, analyst, history, principleInvestigator + diff --git a/schainpy/model/io/io_bltr_block.pyc b/schainpy/model/io/io_bltr_block.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce803599b800c4324a04160f9a3e410aa6c5a24e GIT binary patch literal 30940 zc$~d`dvF}tde`Y0&B!B5mMqJ%WP81B-|K7HR~k$5V|RTwx$9j&cWv1jdDnZjcQdy& z-7{)wrhDAoBU!r^1@R3xDFO)u0tt^w1qko(NEHPkz=c3kq>3t_ig%zA3aS$R0TKw| z{u936_np%{qmjLLAzqE<=)C&8`g@=69OZvwWT^hXf8qU_(m#3nzCqvksil;w)Cz@` za&xL_sTIq_b801T;sa`Bz{Cq`rC{PkwNm7G9(7uSYGqJaNDtuo);_hePtpa|EUDIz zS{agb5q-7xtCjt#HLO;KC3g@lwzyGF?^DeY)jFV74ye|sS{aqxl4_2r);1U zRP&f>9ak&ImE}#V^_P@8s%Xi$a7;B%sMgDB<>j>Spz>_>G)Lv*$~&OyRO^uXx>8S- z`pU{lLazzO0`i=%!c2qTYYlX!9R=A8$X3iq9&24?jp7Uq}H zkYaRDcwH+wzz8CFyfZ`w0QQI!@JiEPZ&0o80|vLr83R}%au867$T(mTkwc0=5s?WEiYtc! zhKNk6iojhB3-uCx@w(o^)GeV3J3RHB9EW)h2RJPB#Ob~46gfV~;XbU>PDwQ=K7^&( z+0XgI9FA~!fWuJ^$2dI5;W&qfIGo_{Fo%;I9^r6`!)XqWa(Ilx<0{Fi^}Kqb7)R;P z`T&rOBGm%k6e2|v8N|2|*=KS}Xa$iWM3!fO9!m^Q@zz$$VPx|GA~X99_AG^g$2D#^ z&Dg6H4enH{K4D0;nv7$88Kdv5uD`i`&8s_|W+Le6B+k7~!jJo{(Djm0R1P}<;Z8O3 zYGLHY+?pQ~>eT%PSEx6g#!`5fpcsf8GgPm3>UBb&mr|tmn)M1s$~YP)PLx~&HltfF za5yac z5~eRa-Zjr}tjQ|G0p?ogI6a!iH@z&srQ?jtSgDxX3~Fmm5O~d)D+Q4gG^hk)-lo2I zU0XzQ)_C+Tb&bDGCy~EYvXALs!V5XWFBU=kHU;O`!j^a5i~QQg`K>V8h}%xhJ0DYz zeh`IWay||_QJT}&$G05ci2i5R4*W4;9Rn>2c*m${zrLtLrar=0~WxchT+u&s>i= zufIIz+cM^L`n3$MGM(LF)(qN{*EqeN!=#A2-n>P`lY#;l#r8Xi zemx53TyL}NH`?V!xLR&|S1!!Y&!2A-XZC7Id_E>F<22`ZfzEIF8~*vbPSA0hRoAOt z^T20`3p#EX#ds?p@7PXaf4mb{!FdS%iB)dfcbsi6vYo)SA4Fk0jN5B?B{nlsdj@># ztR2@Pzn#q5;Fk8LN6YRfz8CXT%S#oz9)&IYTse-3df7n7I4($s_RtcOw+hmX4?(!a zf7e1mQCX{*d3#u^A$S`3QtQy`oz6AqL zuPFv00;l+k9AQKt7-}% z4G+}RVQAyEVNzRp8G()9^9W8NIAzx5g)9zUPSgn+XnLQZm^En)=a@J1w(JnEMmqgO*+}T8fRFipqcsLd5UM@k$Mt{2NLbE3tpQf(5hE-OK!BP_tV~ zBQgMV7QTzx`&9hH;7(w@mYUR^P{9y}6ko9z#h1bXqHbc7qk3&PEFpt6)dW(&C?bUjc2uk$_0pMH*XQZua9E*kSYQt!U5KEDTZwO zV9m23c-ww#2Vr7wI!)hYVIlrNiX%_T1P5)xtJ)d~(RQ-t#hwj0n}`!qc0Fv8EPBO0 z9hZqVy|w1mHtaJg|31T*eMWQeGd5FvbQuu;mBx=^Sf(Rtl$j#hv*#$_@$Om7@MB75 zAc9xEGllF4rA7PqoMy+n4&j<%JlW3(LKJh2WswTlT;&T0P8%lk(1`+?tFD?X(MVBO z2oEaM!q%#%lN5uGm zrVZhad8H!*>hXU@@wE?s2{QK+(Krg~B#GX%nomlA*Em*>mKe8;`f-wEaug47@gM3c zE&|+7lCX~A{apOlbuqC7X%CSh6X81f9Q8+S;yKoGs3KKCVIDF+@M>6XSSqwE;3UNd zR6JzqewhNVmoR`#Xh(XO(^Tsr=|;;lEUtcJb+LAPnIR8|M9j(tOC)&Sf>gs`4EP3K zW)HAxjrxw=BmveA>rycZ?KZ2n^hmAQaY_58XFo{sZdPO5hgnlu>~_%ZBv-mJ@Wb?A z&c2U739yRrwr_xO?=xw4^x(4BBuPR>$6P#FBMJga(ff=S?C}685PtKSPY|V;Be5v) zf|w*BtN{}qy$-ZOZtnxx%$Th(3F%sSz0gEpV&Lt$)3N{S(35@>!EYh>76P!=8ITah z>P9nMWrRm$K~xq}-Gyp^%VXR(jGiGX&{C(h>P1W({2&qfF`%om#NxEu^qyu$o<}T1 zG3hj$ctObs%Q>L9TI)(x8uU9aDh(|o6RbtFaRI?a(~ueEi=#Q$sJS0OyYpy$1Udj% z{19sZBi0B}8E6Gr_yy~5Zi@bnSreJGJz!|hZz#j}NxXjiv(SK}UjQ{CQuK-_4I&;v zDzel@K}DM&P$XXGftT_uRX!pz_W&~KMUn`xUex0I`k+z7zzL*>mgwlBKHWB1Us5e<958{Z7~V}#Je;Cwx_vS z$qU1R8`Rv-r<^wjK09O`CI#TIb%OZrfK^iate35k+!%3O){coMGxXz|O1&Sc9;sJ^ zT}vP=$Lggrs^)+eYzgd-fYUKpQ^lt&m9qTGT7xkhbw5e$4Oo*mrX&JDN@#PE0LNJh z2ne?93R`(Tw8h#3=&{e^dtM0Z$2*h~+Q}v-5KzFNwx8}78stbTvApf0hB^h>ge0)> zzA{o7-fJu>%$saCVudb!({EzcD_=#QmU-1LPK6oKGvd)8^FN^zSj|*^h~DU2j%ZzO z9B(;$qX*0zMP;!bXbnVVukmSKOGyb6CxnCg4awVk%CCOCq~BA*)Cl1SS395@(%`6x zjG4$m6DgR;xQQGx5z9n!CXzRi0TUTQq%o{Vf?-T>{$UO$RrN4K51Vb`%c@KESx&+T zL_uT;2nb=|*}SU#wvDBkBPki!#l_e}&M424H|Qj_;WRk~#A$7$1sv(Lo1z3Kt?IV1 zskz}cb8{k?^h((X^Qhx_ABj*eW1a)FxN+& z%DI%rv5m8!hqJ(D%Fh5!D-JdHKb5gT6i-@bta^aZ=W*{wdSvDaNZCcb8bGe!X*%aTF9?MAWDn*6T#XnT7kV-pM0D80pS} zZyWX=tup)Ya|UhPWV@}aU0f1_aDs<*Ka$hw%h}wW6HCu&9`}N7XL$SID@qICVnk~< z{iN~=@_?NpImDQ3g?9&G1+D;ND;o$tHg(pjsKc`hA(DWIv>~JrsbEQ-C?D4VCtPEu z$WK(hrnGgT;U&DoIizH(^Ijc`&x88Ni%9tKQl7~M2`-HZB16j_Sk6#mHV=IkvI3-nH78yQS$4S{i1adx z=>u3)Zj?m9ezEU|Qe!901(W)`-uWX+T+OHI&9Z9*2I1@^Aw)mGQX+2|;z3CcrsAVA z1>bLpOi0OT-Ec{pIY~z{SwmgAP7dUFSCXhRkzj-e%)_MbXjy^PsIEkj6ODW(JfM+L zQ#>fW?t?C5VkI@5&*_R|=81zQGOpzpot)5-brY!?sYE9wa>OJhG9_a1kk@3i zAu{Ju`qo6yQrdvZwZcw9?1(9g&={sRk*U*3*fe?@ZWn`DnhBQ>JGPH`iD(9ll1y4Z z3)$!@HMf`&p~9#&Oyp;P#P;FbD2eZ*)*c+UAM&sGJIGVRD&v#W!}7?rcdw8Y{oYkZxIr6p}u(75T$@ zJfiJ^c;}$yjq8<3tyf<#tMb8sS(S9Jn3e;}a}skUDo&G4*ihxZt=xB%dq=rQSJxI{iINqO|J#lUd#UCT}v!8#Z}|v%C?LXJ>f_Ox}qsZ`9}GLDEFe%il)>NQG%o%Djn5T=^0wS zy=ou(RJD(Ps@gB@QClmE^vuAX&zw-n%UaC~jA=0dkj zB8D~Lse7t?ng0kl%=N%UEr|R}vN_)hQUwkILC-!zkScL(T`?&Z7E*&twH1@JgEkVU zQQ1~n$>P>(VXH+-QCzvCjB-}LSh;LOmPR|S#)*@3WGA&Ad5^?Rk|OhBuYm)VxB_`i z5<;R1d}l;&oaav4QC&2eTDT@&R;+%-Y_w^IO(*g{Vvic>-oMBLj~+t{qj^@&r$P?+ z0O?ck6dOs?QP7|T)=E?KIOcIXwR)Ab;6}2>v*e`HkS=4-sU~67Nm^m7MINV0YIJRl z^~L5|l`=$ilqfIssvpFhVrMcxU?Wsf$7?knP|JB-BdOcHfL~%w1S}89GoN6s3 zkl;0{>zDet+8|yRSDu*3QjQZi&Fz>}d#p3>vU7*}eX#n;#xG1bvvYBKsU2+4)S~$g z_tc||F$RDL76H$#)*Tm{?BJxGpf5WGCd^H`bk@VD>cIAZ0aJt;Wk+64hj5un_{FBH z+zz*BU?V!^G#gYYS!;>>`?wm@#KaSrTL5Gk@Gj~lX|+w%7y)affybO0@9w143XqtZ{g>hq&_>sPxKiZe`$9Ct$#@5+e??=1qWu}ZQmNOM-U7!L~JPF5mQEsrg5RGLd$iw z#iqd4N>V1f_ix#~fy9e2(0=B;^;1n2UYySN-PGJRbiSWO>jP74D9G%T_zcr0|NrzE z&7ZI)=rhIPL{7q@b=VrWPEgrck4<#%&$u;7Uwlpsl&l%6%%6+aaPITe+Cg}H@uy#B zFIjA06h)?*I#MWYW7KhDUDQd581*OhjnqkrluWXuRS%u)HYcWv->^vzckSq;>fQm9 zJfQb=baJ#y5?97Jc+eydYOPBryA6e@PBvkZ6Dr;8W=l?H-*Yx$-fMY@<2pFq^hpLi zc3JoTq=H$FcL~xX3E0A5>lWiuC-&|DaQPeq?;Wx&?KTAMO{XbNiM;pl*x;j(lwLwn z`DX|~BP#zK!M{L|(uB&tL;#HcEKDOmOwIio&;&k9svsaY`kW8%LSiun4LB|jm|aLQ zlXRPl;Fy==<2me1xHG_Efx{w)gY2BRPd)w#=uy``{4t#8!R96V6=Ello%IGxMqXzW zOvZrDD4L9d&M2|zTA+T)9b`ksdJ6aZSPe`V>RmQjKUJ0m=foj(1Wt~FroH{r-lN;< zVIo+O$F3%}E-j1Zr89Y}(>=hM117W3m02*E#jebv$sFv;6kp8!dJP5H>bwbyA`3o{ ziJ+Wxbbxywg@KCdyuQ0E4=>3LHiWz`KGN$34PE~I-ke^QdR{c+zTz}emwg9VQ>2%I z>7~#=g2J97D0CtDGe^)@+&6+lW&}mkOR;|h#XUz*>>?!396?`k-v|zy5e%AM2Kz@a zxW@>xmIwqNe^n)Bhl9$lefSPLxGESo+=JX^I>7ySVw!Rf%bxoBbl)8In`sQF*B`x; zf4FC@J?12vM^&-79K#+z%$@%|pONc*Vrv;w!I)`p$YfDCu+F&iN=`GA<7x5n4CJaW zWlLW@kpV*W6NqxC$!t-m{Gt(JEBB4;SZ{_- z!q5EfZ~WXhmwX6=Y;>48nTov-bH!f&uTmaWNqN+{9=SEf$=gVFm%t1nFJ5zqT{4UN z*QVDk97?GCn^d%fUwh@>B6x)0-yvw588K%Ru@u^Q<=-PONZBLr9I)7q^UIYof-hnM z!>Odnrkk!c&34BiIPbNRzi7G?lMx%!NJ@}Rb!h`Dy7A(8FivAx^de&H_o;m+dJgH0 zkSHjh(bz>2u1O$@Tx8$xm9ha|^_?Cv#)DQ4&d?B~W5DMX1`n z-Er3B>$6MP=Slss%p7lP9eSJO}fzFn4W-FgG zgAq&o*7SK=_*7J@tSePX&v83VO7huCK4vJVRd8-w_Ow{vVbux8HrS7vH@0Nw58hnt zJ0bhH*udlsI^L6FC51&WhJnie=$ZTrfi+maAnNfBYB66bmx`s~QYlkP#;sv{c)oPJ zG+sJTI!C4FN+YGQQoA%&y4!P@{bA%MU5DB6_V_S6=*_1%%s#-8BE&XC1|hT|!kz_) zlyG>QjnI8?i`7gePsnIV&YbMbn-kUr6Ul3xsanj=hw=HU%-w`-B;_@?en}1j@v%F8 z@tmAW-#I2Mo0(Y4&q7YeC_c!go4RnpFKGvx8qf-`jKA-o@AD}>M<+Sbbv6+adBN9rFpDvvBWDncW|FcF7zW!c_&j;I1!!Qlu(9Pt4bk%9$^bg>;+6#vSI?>J zP~uc>$l?VtUj~$4#)2>aOg#|?eqJ4d1Dwu#!z3-8O!$(Kby=_UT%x7HNc5X^bJ$QP z3mV#VvZz5#CkG9{$y57GzHtfGNfzF!=8S@<*jm5NYZbdXVoo0%FmOC7zPs%H*5kK` zO{L8)A&KM-eor`u5O`bmIfnIKD!rGpBG!M)o}1%H*2>I+P2$bs*`B&`9%;_DadzGh z*eti}a8&lw>rx|bi#PGo#7D6Uv`&c_RkrVT;>2F{Y_FjuC>g}8ed^<#Q#}VG%Qk!8 z@TmpyUTjqW4dT4cK+IAF%PXmdE=QAVt;!!X90BKYaQ11JTV6&4gs=6YM&&nOC^-Oj z203<8p`X%-b%F$gQmUkP#mrfFu(MQU|0iNW>OT3tlh?pWh%kwmr6wT(TvGb@i=~2l zyQ<`*%KM<%y2|XXDtW2$v67QDs8Yh)AeEcYO1y^~Ilkdzzadp>_t^-ov}$dBP}PfS zQqV{olC`Qlq}3GdZ#-;DN3;q}s2m-!++m%>LCDl0dDyr(OB3+hIG|4M6trJ4sa%ab zOcuWQbQIKOctIEG&mm0h^3I@kh{j~tdO&)vacd}Q1xULzJlWSZ9nz$?UslOD>|9#s z9L7yHPmSO5!(dtsBuCW7kc$41W$l!RU{AsY<%n8-p9Zl!1E7olOE==r+1DVPxBNgK z{uMVh_9uo);yJZ7L1t2wLUXZB4~A~|L5%Zz@A$ISe4CO{2fM)bOe^qOVdB@$?tX%( zOxGh|8(o$AkiKiUUFRihp6f*S*iyG=<;G9l{FRR;ern>IjR}s;e6w+Ze~x^U`S`Vo8*qNTTxMHl(JKnX!6#2N8d zDfE90!GFzbZBZN)-=LxRS1E{blg0;p`1->u_U%?XjAMUQPHoB!Gv+mEi>kfl(|As` z95?bCPP5Eq<-0oh7EnFL!@0%`N3_!;*0A|n@WCu;y>*Cm%@d@j4qJ!vW5k4xQEY@a zMe^3mlrC5WVM@p8d&Dp$EPtwn%6)0{`@Oj=VhnG&u6p_B)XR6(8+cB=^bDSOZRae4 z5Mnb3%?=5y#9c#TGh6}3R-aic9BG4()TDbSd(?whHH(?Vjf0N*o#>kQ(uVpp{mQxA z>786wU31=aE?NxDY3Y;7Ou>lZ*t-i37$&~E!0ZOWgxL2|bX9saa*F9mu6Nw9xEHZ! zq~|9V)jSxcoO4`7Mh3Ex&Ac3GI=i_B>Uz@pjIdziiJ2UPTd67zllEj9_oO9XfZv1Z!G1|#&|0Eno+q}CFf38S_fP<*6>2th7()Tp`K=3uW@$wBlnj29%)2Qd(E%e%`j*@=gF%Nu=+PW z2q~y-x*>QFcMhA?ggu_6PW7YxT|N8hUHxCZ^PszXoEDa`%C&xH?HPiAo@bVq?l7b^ z7Uu04xjGCh8!!Yg{GQ#_%X>=;_c78XuaiVnd&}o>*{-kMbqIE6JSR@JoXDjfTj%4m zv$pTq>|?{#ceS_p3GFS~GeH<7Yr7lF9Ci9zy?zI6UJrQ7ig0sN6agn_H1(_FCX8!O ze*-;Uw#g$oz& zGx2q4OX)2auD|K?oiH;rq0O_l*D$smLN8Ztt~4iAmzOGX2dhia7nx`nL|N{lx#1gD~wNQ10mB{SUqmhh4{h3Bi9r@E=v?Beq6LN9sT32PR6S zKsHe_FB!fjhs2)M>S6j;FdGmL8tq;G1l2Oy2;Ojs4CE*0ny>tWv!4 zMawwU!DTwxt^6+V)DT>-w5L5P;x3@-JU=Jwz(nsYRkB=xb|%9T12JW|ClbjyO!#z+ zNEVk7nUULOEB78|*PZbOXz=26Ow5d#ARn3ghfp(r4E;>cSoFz_S|8^+xuM)~YnneZ zxyjryYm^ks5h|O?6-li;K?>$kQbG@#Z4v&Q$m>{M&LQJ7$~T{m?z-_bzbl2$;rt;! zP3T!3^8$ds*0UV{f_U@cB)WX}Ya&S6yZ= zUDub|RM8;{&{av(Mlmpn!)his@fFwV|BR13mV+E4>=EC0w*#l;*Yy2KBws~d1A}AV0vo>W9TL5oBzh(G z8eh&OQkH$4WIsO$rp=>{)Ox$V~Z4Dbhh$AZ|!+z;6_hieX(_$_o1F)+oqWHsfO55Ezjoq2=Y z*-MelXS|0hwp#h*gY=+VVB3=9=o@+p28XhZI&MYmT-Us~R{7(G7R!+lF(A=$;?~*9 z9qUEA8Q#wGAzNV0lyxkJ%T)(+)48rwsduxRl64UefzScc`WEbui1?;sBhNe(Qzu3Q+wE(E+4^%-nM z|1WCpL%d7uNz3`-achX^@RT)@r!RJ34Sh`SqQn?dpXJHyx_739E|WtsFA@F2^1lKq zs5h$ls>+o7)eE%dXnTn_zvkv1fFcMXg6@T-edqSlwW|;8@32q1mAmk6ecDY7@gtO| zCu{dj%#@&)lit+aQy0csQbkB)CFP_}f=~^WoA!M#>hx}O_M`+ra^t%Ov#S=Sq_1mr z*ki06g`2)B*UThaq5Y|@Zg#zPGu(zQn()IonFT#CvEhWzrzTK@k;baT(0nGndK>uh`48_N(*d%NHM>v4z6j)X z62IxQ_Z(ynZ!WCQ(R-OANy(1GIt&jULmQ^i5d`pRYk~iW{YpdIsXglWkvB`Y4uyS| zD<_c?#7%70i5Y~zeie&Fy)p!nc8?o}Xh`*@HcU{XVRlPpl9Ci^u?c@n8Xke8vB9B} zmKW<}nHK7HVs~P`6<%A#7?dNA9Q&3=e8%c-l2bO5ZL#V z?XrC*p;6tAr6L%RW(vH>jVSE2d6wxK%L>{vE=hTjzl!>2!693+z_g%YT=Q@>DHXFZ zsc+KH`S~QoS(a0Ic2$15je&3BY_px^w;Wo8#1wo|!`0p&;)B{SNYT{F_>BBdYCGd! zx8A*amRiwl44oQICIhhNP;`kC_JvD}nFk% z|2LZZ+1r1cbXY(IjrwZRD)Th&)kpv+%j01)Y!DNbm8Ye9ZE=3?wF|HC8ou`FM|o8f zDIO6h3S7x}V4ES4H@v!TZQ{#&zyQ7ZCIW<#vzLg3XiCSd?(3M4auDb~1egq|+#y#N0w zeS$La;Q3FB1Yf7O*zA4}&r$ocv9UK?+-bK-=QICP!Lyf^Z$P*a;zblfbwY!FZlWPjW6_b$8Qm}+_UJRw`#vzxpT$N{@Yg9f7*Hh>)Er2a@K;k zulP&}d=$G5S-gjW_Ypiq0P`#xa9^BVuR>k4^IbzNa^m9n>j?0V9pp?5 zAA$OEYN=$?BpV`OAmr9w@L49@lKp;88dM30`CHz>#wa9tC&a843lcM zyImW>aA@i|MsMIwV7t4#nBd@Fmo z>93XpC#ZJ<)(K+SWJVh|ItejD{ePPHC>p=R7YimlmDlAQ-*@t^E;d(-`Y_R==$-|6iT1v(Eqk literal 0 Hc$@ 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 a+|k^lxp(JsxqNOQmmj|}@h1xZZvQ_k_S;eb literal 0 Hc$@ vertical) + ('AntennaCoord0',' endFp: + sys.stderr.write("Warning %s: Size value read from System Header is lower than it has to be\n" %fp) + return 0 + + if OffRHeader < endFp: + sys.stderr.write("Warning %s: Size value read from System Header size is greater than it has to be\n" %fp) + return 0 + + return 1 + + +class BLTRReader (ProcessingUnit,FileHeaderBLTR,RecordHeaderBLTR): + + path = None + startDate = None + endDate = None + startTime = None + endTime = None + walk = None + isConfig = False + + + fileList= None + + #metadata + TimeZone= None + Interval= None + heightList= None + + #data + data= None + utctime= None + + + + def __init__(self): + + #Eliminar de la base la herencia + ProcessingUnit.__init__(self) + +# self.isConfig = False + + #self.pts2read_SelfSpectra = 0 + #self.pts2read_CrossSpectra = 0 + #self.pts2read_DCchannels = 0 + #self.datablock = None + self.utc = None + self.ext = ".fdt" + self.optchar = "P" + self.fpFile=None + self.fp = None + self.BlockCounter=0 + self.dtype = None + self.fileSizeByHeader = None + self.filenameList = [] + self.fileSelector = 0 + self.Off2StartNxtRec=0 + self.RecCounter=0 + self.flagNoMoreFiles = 0 + self.data_spc=None + self.data_cspc=None + self.data_output=None + self.path = None + self.OffsetStartHeader=0 + self.Off2StartData=0 + self.ipp = 0 + self.nFDTdataRecors=0 + self.blocksize = 0 + self.dataOut = Spectra() + self.profileIndex = 1 #Always + self.dataOut.flagNoData=False + self.dataOut.nRdPairs = 0 + self.dataOut.pairsList = [] + self.dataOut.data_spc=None + self.dataOut.noise=[] + self.dataOut.velocityX=[] + self.dataOut.velocityY=[] + self.dataOut.velocityV=[] + + + + def Files2Read(self, fp): + ''' + Function that indicates the number of .fdt files that exist in the folder to be read. + It also creates an organized list with the names of the files to read. + ''' + #self.__checkPath() + + ListaData=os.listdir(fp) #Gets the list of files within the fp address + ListaData=sorted(ListaData) #Sort the list of files from least to largest by names + nFiles=0 #File Counter + FileList=[] #A list is created that will contain the .fdt files + for IndexFile in ListaData : + if '.fdt' in IndexFile: + FileList.append(IndexFile) + nFiles+=1 + + #print 'Files2Read' + #print 'Existen '+str(nFiles)+' archivos .fdt' + + self.filenameList=FileList #List of files from least to largest by names + + + def run(self, **kwargs): + ''' + This method will be the one that will initiate the data entry, will be called constantly. + You should first verify that your Setup () is set up and then continue to acquire + the data to be processed with getData (). + ''' + if not self.isConfig: + self.setup(**kwargs) + self.isConfig = True + + self.getData() + #print 'running' + + + def setup(self, path=None, + startDate=None, + endDate=None, + startTime=None, + endTime=None, + walk=True, + timezone='utc', + code = None, + online=False, + ReadMode=None): + + self.isConfig = True + + self.path=path + self.startDate=startDate + self.endDate=endDate + self.startTime=startTime + self.endTime=endTime + self.walk=walk + self.ReadMode=int(ReadMode) + + pass + + + def getData(self): + ''' + Before starting this function, you should check that there is still an unread file, + If there are still blocks to read or if the data block is empty. + + You should call the file "read". + + ''' + + if self.flagNoMoreFiles: + self.dataOut.flagNoData = True + print 'NoData se vuelve true' + return 0 + + self.fp=self.path + self.Files2Read(self.fp) + self.readFile(self.fp) + self.dataOut.data_spc = self.data_spc + self.dataOut.data_cspc =self.data_cspc + self.dataOut.data_output=self.data_output + + print 'self.dataOut.data_output', shape(self.dataOut.data_output) + + #self.removeDC() + return self.dataOut.data_spc + + + def readFile(self,fp): + ''' + You must indicate if you are reading in Online or Offline mode and load the + The parameters for this file reading mode. + + Then you must do 2 actions: + + 1. Get the BLTR FileHeader. + 2. Start reading the first block. + ''' + + #The address of the folder is generated the name of the .fdt file that will be read + print "File: ",self.fileSelector+1 + + if self.fileSelector < len(self.filenameList): + + self.fpFile=str(fp)+'/'+str(self.filenameList[self.fileSelector]) + #print self.fpFile + fheader = FileHeaderBLTR() + fheader.FHread(self.fpFile) #Bltr FileHeader Reading + self.nFDTdataRecors=fheader.nFDTdataRecors + + self.readBlock() #Block reading + else: + print 'readFile FlagNoData becomes true' + self.flagNoMoreFiles=True + self.dataOut.flagNoData = True + return 0 + + def getVelRange(self, extrapoints=0): + Lambda= SPEED_OF_LIGHT/50000000 + PRF = self.dataOut.PRF#1./(self.dataOut.ippSeconds * self.dataOut.nCohInt) + Vmax=-Lambda/(4.*(1./PRF)*self.dataOut.nCohInt*2.) + deltafreq = PRF / (self.nProfiles) + deltavel = (Vmax*2) / (self.nProfiles) + freqrange = deltafreq*(numpy.arange(self.nProfiles)-self.nProfiles/2.) - deltafreq/2 + velrange = deltavel*(numpy.arange(self.nProfiles)-self.nProfiles/2.) + return velrange + + def readBlock(self): + ''' + It should be checked if the block has data, if it is not passed to the next file. + + Then the following is done: + + 1. Read the RecordHeader + 2. Fill the buffer with the current block number. + + ''' + + if self.BlockCounter < self.nFDTdataRecors-2: + print self.nFDTdataRecors, 'CONDICION!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + if self.ReadMode==1: + rheader = RecordHeaderBLTR(RecCounter=self.BlockCounter+1) + elif self.ReadMode==0: + rheader = RecordHeaderBLTR(RecCounter=self.BlockCounter) + + rheader.RHread(self.fpFile) #Bltr FileHeader Reading + + self.OffsetStartHeader=rheader.OffsetStartHeader + self.RecCounter=rheader.RecCounter + self.Off2StartNxtRec=rheader.Off2StartNxtRec + self.Off2StartData=rheader.Off2StartData + self.nProfiles=rheader.nProfiles + self.nChannels=rheader.nChannels + self.nHeights=rheader.nHeights + self.frequency=rheader.TransmitFrec + self.DualModeIndex=rheader.DualModeIndex + + self.pairsList =[(0,1),(0,2),(1,2)] + self.dataOut.pairsList = self.pairsList + + self.nRdPairs=len(self.dataOut.pairsList) + self.dataOut.nRdPairs = self.nRdPairs + + self.__firstHeigth=rheader.StartRangeSamp + self.__deltaHeigth=rheader.SampResolution + self.dataOut.heightList= self.__firstHeigth + numpy.array(range(self.nHeights))*self.__deltaHeigth + self.dataOut.channelList = range(self.nChannels) + self.dataOut.nProfiles=rheader.nProfiles + self.dataOut.nIncohInt=rheader.nIncohInt + self.dataOut.nCohInt=rheader.nCohInt + self.dataOut.ippSeconds= 1/float(rheader.PRFhz) + self.dataOut.PRF=rheader.PRFhz + self.dataOut.nFFTPoints=rheader.nProfiles + self.dataOut.utctime=rheader.nUtime + self.dataOut.timeZone=0 + self.dataOut.normFactor= self.dataOut.nProfiles*self.dataOut.nIncohInt*self.dataOut.nCohInt + self.dataOut.outputInterval= self.dataOut.ippSeconds * self.dataOut.nCohInt * self.dataOut.nIncohInt * self.nProfiles + + self.data_output=numpy.ones([3,rheader.nHeights])*numpy.NaN + print 'self.data_output', shape(self.data_output) + self.dataOut.velocityX=[] + self.dataOut.velocityY=[] + self.dataOut.velocityV=[] + + '''Block Reading, the Block Data is received and Reshape is used to give it + shape. + ''' + + #Procedure to take the pointer to where the date block starts + startDATA = open(self.fpFile,"rb") + OffDATA= self.OffsetStartHeader + self.RecCounter*self.Off2StartNxtRec+self.Off2StartData + startDATA.seek(OffDATA, os.SEEK_SET) + + def moving_average(x, N=2): + return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):] + + def gaus(xSamples,a,x0,sigma): + return a*exp(-(xSamples-x0)**2/(2*sigma**2)) + + def Find(x,value): + for index in range(len(x)): + if x[index]==value: + return index + + def pol2cart(rho, phi): + x = rho * numpy.cos(phi) + y = rho * numpy.sin(phi) + return(x, y) + + + + + if self.DualModeIndex==self.ReadMode: + + self.data_fft = numpy.fromfile( startDATA, [('complex',' 0.0001) : +# +# try: +# popt,pcov = curve_fit(gaus,xSamples,yMean,p0=[1,meanGauss,sigma]) +# +# if numpy.amax(popt)>numpy.amax(yMean)*0.3: +# FitGauss=gaus(xSamples,*popt) +# +# else: +# FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean) +# print 'Verificador: Dentro', Height +# except RuntimeError: +# +# try: +# for j in range(len(ySamples[1])): +# yMean2=numpy.append(yMean2,numpy.average([ySamples[1,j],ySamples[2,j]])) +# popt,pcov = curve_fit(gaus,xSamples,yMean2,p0=[1,meanGauss,sigma]) +# FitGauss=gaus(xSamples,*popt) +# print 'Verificador: Exepcion1', Height +# except RuntimeError: +# +# try: +# popt,pcov = curve_fit(gaus,xSamples,ySamples[1],p0=[1,meanGauss,sigma]) +# FitGauss=gaus(xSamples,*popt) +# print 'Verificador: Exepcion2', Height +# except RuntimeError: +# FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean) +# print 'Verificador: Exepcion3', Height +# else: +# FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean) +# #print 'Verificador: Fuera', Height +# +# +# +# Maximun=numpy.amax(yMean) +# eMinus1=Maximun*numpy.exp(-1) +# +# HWpos=Find(FitGauss,min(FitGauss, key=lambda value:abs(value-eMinus1))) +# HalfWidth= xFrec[HWpos] +# GCpos=Find(FitGauss, numpy.amax(FitGauss)) +# Vpos=Find(FactNorm, numpy.amax(FactNorm)) +# #Vpos=numpy.sum(FactNorm)/len(FactNorm) +# #Vpos=Find(FactNorm, min(FactNorm, key=lambda value:abs(value- numpy.mean(FactNorm) ))) +# #print 'GCpos',GCpos, numpy.amax(FitGauss), 'HWpos',HWpos +# '''****** Getting Fij ******''' +# +# GaussCenter=xFrec[GCpos] +# if (GaussCenter<0 and HalfWidth>0) or (GaussCenter>0 and HalfWidth<0): +# Fij=abs(GaussCenter)+abs(HalfWidth)+0.0000001 +# else: +# Fij=abs(GaussCenter-HalfWidth)+0.0000001 +# +# '''****** Getting Frecuency range of significant data ******''' +# +# Rangpos=Find(FitGauss,min(FitGauss, key=lambda value:abs(value-Maximun*0.10))) +# +# if Rangpos5 and len(FrecRange) 0.: +# self.dataOut.velocityX=numpy.append(self.dataOut.velocityX, Vzon) #Vmag +# #print 'Vmag',Vmag +# else: +# self.dataOut.velocityX=numpy.append(self.dataOut.velocityX, NaN) +# +# if abs(Vx)<100 and abs(Vx) > 0.: +# self.dataOut.velocityY=numpy.append(self.dataOut.velocityY, Vmer) #Vang +# #print 'Vang',Vang +# else: +# self.dataOut.velocityY=numpy.append(self.dataOut.velocityY, NaN) +# +# if abs(GaussCenter)<2: +# self.dataOut.velocityV=numpy.append(self.dataOut.velocityV, xFrec[Vpos]) +# +# else: +# self.dataOut.velocityV=numpy.append(self.dataOut.velocityV, NaN) +# +# +# # print '********************************************' +# # print 'HalfWidth ', HalfWidth +# # print 'Maximun ', Maximun +# # print 'eMinus1 ', eMinus1 +# # print 'Rangpos ', Rangpos +# # print 'GaussCenter ',GaussCenter +# # print 'E01 ',E01 +# # print 'N01 ',N01 +# # print 'E02 ',E02 +# # print 'N02 ',N02 +# # print 'E12 ',E12 +# # print 'N12 ',N12 +# #print 'self.dataOut.velocityX ', self.dataOut.velocityX +# # print 'Fij ', Fij +# # print 'cC ', cC +# # print 'cF ', cF +# # print 'cG ', cG +# # print 'cA ', cA +# # print 'cB ', cB +# # print 'cH ', cH +# # print 'Vx ', Vx +# # print 'Vy ', Vy +# # print 'Vmag ', Vmag +# # print 'Vang ', Vang*180/numpy.pi +# # print 'PhaseSlope ',PhaseSlope[0] +# # print 'PhaseSlope ',PhaseSlope[1] +# # print 'PhaseSlope ',PhaseSlope[2] +# # print '********************************************' +# #print 'data_output',shape(self.dataOut.velocityX), shape(self.dataOut.velocityY) +# +# #print 'self.dataOut.velocityX', len(self.dataOut.velocityX) +# #print 'self.dataOut.velocityY', len(self.dataOut.velocityY) +# #print 'self.dataOut.velocityV', self.dataOut.velocityV +# +# self.data_output[0]=numpy.array(self.dataOut.velocityX) +# self.data_output[1]=numpy.array(self.dataOut.velocityY) +# self.data_output[2]=numpy.array(self.dataOut.velocityV) +# +# prin= self.data_output[0][~numpy.isnan(self.data_output[0])] +# print ' ' +# print 'VmagAverage',numpy.mean(prin) +# print ' ' +# # plt.figure(5) +# # plt.subplot(211) +# # plt.plot(self.dataOut.velocityX,'yo:') +# # plt.subplot(212) +# # plt.plot(self.dataOut.velocityY,'yo:') +# +# # plt.figure(1) +# # # plt.subplot(121) +# # # plt.plot(xFrec,ySamples[0],'k',label='Ch0') +# # # plt.plot(xFrec,ySamples[1],'g',label='Ch1') +# # # plt.plot(xFrec,ySamples[2],'r',label='Ch2') +# # # plt.plot(xFrec,FitGauss,'yo:',label='fit') +# # # plt.legend() +# # plt.title('DATOS A ALTURA DE 2850 METROS') +# # +# # plt.xlabel('Frecuencia (KHz)') +# # plt.ylabel('Magnitud') +# # # plt.subplot(122) +# # # plt.title('Fit for Time Constant') +# # #plt.plot(xFrec,zline) +# # #plt.plot(xFrec,SmoothSPC,'g') +# # plt.plot(xFrec,FactNorm) +# # plt.axis([-4, 4, 0, 0.15]) +# # # plt.xlabel('SelfSpectra KHz') +# # +# # plt.figure(10) +# # # plt.subplot(121) +# # plt.plot(xFrec,ySamples[0],'b',label='Ch0') +# # plt.plot(xFrec,ySamples[1],'y',label='Ch1') +# # plt.plot(xFrec,ySamples[2],'r',label='Ch2') +# # # plt.plot(xFrec,FitGauss,'yo:',label='fit') +# # plt.legend() +# # plt.title('SELFSPECTRA EN CANALES') +# # +# # plt.xlabel('Frecuencia (KHz)') +# # plt.ylabel('Magnitud') +# # # plt.subplot(122) +# # # plt.title('Fit for Time Constant') +# # #plt.plot(xFrec,zline) +# # #plt.plot(xFrec,SmoothSPC,'g') +# # # plt.plot(xFrec,FactNorm) +# # # plt.axis([-4, 4, 0, 0.15]) +# # # plt.xlabel('SelfSpectra KHz') +# # +# # plt.figure(9) +# # +# # +# # plt.title('DATOS SUAVIZADOS') +# # plt.xlabel('Frecuencia (KHz)') +# # plt.ylabel('Magnitud') +# # plt.plot(xFrec,SmoothSPC,'g') +# # +# # #plt.plot(xFrec,FactNorm) +# # plt.axis([-4, 4, 0, 0.15]) +# # # plt.xlabel('SelfSpectra KHz') +# # # +# # plt.figure(2) +# # # #plt.subplot(121) +# # plt.plot(xFrec,yMean,'r',label='Mean SelfSpectra') +# # plt.plot(xFrec,FitGauss,'yo:',label='Ajuste Gaussiano') +# # # plt.plot(xFrec[Rangpos],FitGauss[Find(FitGauss,min(FitGauss, key=lambda value:abs(value-Maximun*0.1)))],'bo') +# # # #plt.plot(xFrec,phase) +# # # plt.xlabel('Suavizado, promediado KHz') +# # plt.title('SELFSPECTRA PROMEDIADO') +# # # #plt.subplot(122) +# # # #plt.plot(xSamples,zline) +# # plt.xlabel('Frecuencia (KHz)') +# # plt.ylabel('Magnitud') +# # plt.legend() +# # # +# # # plt.figure(3) +# # # plt.subplot(311) +# # # #plt.plot(xFrec,phase[0]) +# # # plt.plot(xFrec,phase[0],'g') +# # # plt.subplot(312) +# # # plt.plot(xFrec,phase[1],'g') +# # # plt.subplot(313) +# # # plt.plot(xFrec,phase[2],'g') +# # # #plt.plot(xFrec,phase[2]) +# # # +# # # plt.figure(4) +# # # +# # # plt.plot(xSamples,coherence[0],'b') +# # # plt.plot(xSamples,coherence[1],'r') +# # # plt.plot(xSamples,coherence[2],'g') +# # plt.show() +# # # +# # # plt.clf() +# # # plt.cla() +# # # plt.close() +# +# print ' ' + + + + self.BlockCounter+=2 + + else: + self.fileSelector+=1 + self.BlockCounter=0 + print "Next File" + + + +class BLTRWriter(ProcessingUnit): + ''' + classdocs + ''' + + def __init__(self): + ''' + Constructor + ''' + self.dataOut = None + + self.isConfig = False + + def setup(self, dataIn, path, blocksPerFile, set=0, ext=None): + ''' + In this method we should set all initial parameters. + + Input: + dataIn : Input data will also be outputa data + + ''' + self.dataOut = dataIn + + self.isConfig = True + + return + + def run(self, dataIn, **kwargs): + ''' + This method will be called many times so here you should put all your code + + Inputs: + + dataIn : object with the data + + ''' + + if not self.isConfig: + self.setup(dataIn, **kwargs) + diff --git a/schainpy/model/io/jroIO_bltr.pyc b/schainpy/model/io/jroIO_bltr.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c88055eb2f2cfe3ae43c158305e24148ef122c49 GIT binary patch literal 21410 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 literal 0 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 literal 0 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 q^@^&~1WJ8>fYWFZhbvlDx$k4;=5 + ('SPARrawGate2',' 1180: + self.fp.seek(self.PointerReader , os.SEEK_SET) + self.FirstPoint = self.PointerReader + + else : + self.FirstPoint = 1180 + + + + self.srviHeader = SRVIHeader() + + self.srviHeader.SRVIread(self.fp) #Se obtiene la cabecera del SRVI + + self.blocksize = self.srviHeader.SizeOfDataBlock1 # Se obtiene el tamao del bloque + + if self.blocksize == 148: + print 'blocksize == 148 bug' + jump = numpy.fromfile(self.fp,[('jump',numpy.str_,140)] ,1) + + self.srviHeader.SRVIread(self.fp) #Se obtiene la cabecera del SRVI + + if not self.srviHeader.SizeOfSRVI1: + self.fileSelector+=1 + self.nextfileflag==True + self.FileHeaderFlag == True + + self.recordheader = RecordHeader() + self.recordheader.RHread(self.fp) + self.RadarConst = self.recordheader.RadarConst + dwell = self.recordheader.time_t + npw1 = self.recordheader.npw1 + npw2 = self.recordheader.npw2 + + + self.dataOut.channelList = range(2) + self.dataOut.nIncohInt = self.Num_inCoh + self.dataOut.nProfiles = self.Num_Bins + self.dataOut.nCohInt = 1 + self.dataOut.windowOfFilter = 1 + self.dataOut.utctime = dwell + self.dataOut.timeZone=0 + + self.dataOut.outputInterval = self.dataOut.getTimeInterval() + self.dataOut.heightList = self.SPARrawGate1*self.__deltaHeigth + numpy.array(range(self.Num_Hei))*self.__deltaHeigth + + + + self.HSDVsign = numpy.fromfile( self.fp, [('HSDV',numpy.str_,4)],1) + self.SizeHSDV = numpy.fromfile( self.fp, [('SizeHSDV',' 0. , self.data_spc, 0) + + self.dataOut.COFA = numpy.array([self.COFA_Co , self.COFA_Cx]) + + + print ' ' + print 'SPC',numpy.shape(self.dataOut.data_spc) + #print 'SPC',self.dataOut.data_spc + + noinor1 = 713031680 + noinor2 = 30 + + #print 'npw1 db' , npw1 + + npw1 = 10**(npw1/10) * noinor1 * noinor2 + npw2 = 10**(npw2/10) * noinor1 * noinor2 + self.dataOut.NPW = numpy.array([npw1, npw2]) + + + print ' ' + #print numpy.__version__ + self.data_spc = numpy.transpose(self.data_spc, (2,1,0)) + self.data_spc = numpy.fft.fftshift(self.data_spc, axes = 1) + + self.data_spc = numpy.fliplr(self.data_spc) + + + + '''Block Reading, the Block Data is received and Reshape is used to give it + shape. + ''' + + self.PointerReader = self.fp.tell() + + + + + + + \ No newline at end of file diff --git a/schainpy/model/io/jroIO_mira35c.pyc b/schainpy/model/io/jroIO_mira35c.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dce19e7f96195db888b9e577b7e0962621499f64 GIT binary patch literal 20685 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 08c4507d6c3c48f6c52326d5dedfa1972fb26356 son almacenados en tres buffer's para el Self Spectra, el Cross Spectra y el DC Channel. paresCanalesIguales * alturas * perfiles (Self Spectra) paresCanalesDiferentes * alturas * perfiles (Cross Spectra) canales * alturas (DC Channels) +<<<<<<< HEAD Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader, RadarControllerHeader y Spectra. Los tres primeros se usan para almacenar informacion de la cabecera de datos (metadata), y el cuarto (Spectra) para obtener y almacenar un bloque de @@ -74,18 +81,80 @@ class SpectraReader(JRODataReader, ProcessingUnit): Inicializador de la clase SpectraReader para la lectura de datos de espectros. Inputs: +======= + Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader, + RadarControllerHeader y Spectra. Los tres primeros se usan para almacenar informacion de la + cabecera de datos (metadata), y el cuarto (Spectra) para obtener y almacenar un bloque de + datos desde el "buffer" cada vez que se ejecute el metodo "getData". + + Example: + dpath = "/home/myuser/data" + + startTime = datetime.datetime(2010,1,20,0,0,0,0,0,0) + + endTime = datetime.datetime(2010,1,21,23,59,59,0,0,0) + + readerObj = SpectraReader() + + readerObj.setup(dpath, startTime, endTime) + + while(True): + + readerObj.getData() + + print readerObj.data_spc + + print readerObj.data_cspc + + print readerObj.data_dc + + if readerObj.flagNoMoreFiles: + break + + """ + + pts2read_SelfSpectra = 0 + + pts2read_CrossSpectra = 0 + + pts2read_DCchannels = 0 + + ext = ".pdata" + + optchar = "P" + + dataOut = None + + nRdChannels = None + + nRdPairs = None + + rdPairList = [] + + def __init__(self): + """ + Inicializador de la clase SpectraReader para la lectura de datos de espectros. + + Inputs: +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 dataOut : Objeto de la clase Spectra. Este objeto sera utilizado para almacenar un perfil de datos cada vez que se haga un requerimiento (getData). El perfil sera obtenido a partir del buffer de datos, si el buffer esta vacio se hara un nuevo proceso de lectura de un bloque de datos. Si este parametro no es pasado se creara uno internamente. +<<<<<<< HEAD Affected: +======= + + Affected: +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 self.dataOut Return : None """ +<<<<<<< HEAD #Eliminar de la base la herencia ProcessingUnit.__init__(self, **kwargs) @@ -170,15 +239,109 @@ class SpectraReader(JRODataReader, ProcessingUnit): self.dataOut = self.createObjByDefault() +======= + + #Eliminar de la base la herencia + ProcessingUnit.__init__(self) + +# self.isConfig = False + + self.pts2read_SelfSpectra = 0 + + self.pts2read_CrossSpectra = 0 + + self.pts2read_DCchannels = 0 + + self.datablock = None + + self.utc = None + + self.ext = ".pdata" + + self.optchar = "P" + + self.basicHeaderObj = BasicHeader(LOCALTIME) + + self.systemHeaderObj = SystemHeader() + + self.radarControllerHeaderObj = RadarControllerHeader() + + self.processingHeaderObj = ProcessingHeader() + + self.online = 0 + + self.fp = None + + self.idFile = None + + self.dtype = None + + self.fileSizeByHeader = None + + self.filenameList = [] + + self.filename = None + + self.fileSize = None + + self.firstHeaderSize = 0 + + self.basicHeaderSize = 24 + + self.pathList = [] + + self.lastUTTime = 0 + + self.maxTimeStep = 30 + + self.flagNoMoreFiles = 0 + + self.set = 0 + + self.path = None + + self.delay = 60 #seconds + + self.nTries = 3 #quantity tries + + self.nFiles = 3 #number of files for searching + + self.nReadBlocks = 0 + + self.flagIsNewFile = 1 + + self.__isFirstTimeOnline = 1 + +# self.ippSeconds = 0 + + self.flagDiscontinuousBlock = 0 + + self.flagIsNewBlock = 0 + + self.nTotalBlocks = 0 + + self.blocksize = 0 + + self.dataOut = self.createObjByDefault() + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 self.profileIndex = 1 #Always def createObjByDefault(self): +<<<<<<< HEAD dataObj = Spectra() return dataObj +======= + + dataObj = Spectra() + + return dataObj + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 def __hasNotDataInBuffer(self): return 1 @@ -186,7 +349,11 @@ class SpectraReader(JRODataReader, ProcessingUnit): def getBlockDimension(self): """ Obtiene la cantidad de puntos a leer por cada bloque de datos +<<<<<<< HEAD +======= + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 Affected: self.nRdChannels self.nRdPairs @@ -203,15 +370,24 @@ class SpectraReader(JRODataReader, ProcessingUnit): self.nRdChannels = 0 self.nRdPairs = 0 self.rdPairList = [] +<<<<<<< HEAD for i in range(0, self.processingHeaderObj.totalSpectra*2, 2): if self.processingHeaderObj.spectraComb[i] == self.processingHeaderObj.spectraComb[i+1]: self.nRdChannels = self.nRdChannels + 1 #par de canales iguales +======= + + + for i in range(0, self.processingHeaderObj.totalSpectra*2, 2): + if self.processingHeaderObj.spectraComb[i] == self.processingHeaderObj.spectraComb[i+1]: + self.nRdChannels = self.nRdChannels + 1 #par de canales iguales +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 else: self.nRdPairs = self.nRdPairs + 1 #par de canales diferentes self.rdPairList.append((self.processingHeaderObj.spectraComb[i], self.processingHeaderObj.spectraComb[i+1])) pts2read = self.processingHeaderObj.nHeights * self.processingHeaderObj.profilesPerBlock +<<<<<<< HEAD self.pts2read_SelfSpectra = int(self.nRdChannels * pts2read) self.blocksize = self.pts2read_SelfSpectra @@ -227,17 +403,42 @@ class SpectraReader(JRODataReader, ProcessingUnit): # self.blocksize = self.pts2read_SelfSpectra + self.pts2read_CrossSpectra + self.pts2read_DCchannels +======= + + self.pts2read_SelfSpectra = int(self.nRdChannels * pts2read) + self.blocksize = self.pts2read_SelfSpectra + + if self.processingHeaderObj.flag_cspc: + self.pts2read_CrossSpectra = int(self.nRdPairs * pts2read) + self.blocksize += self.pts2read_CrossSpectra + + if self.processingHeaderObj.flag_dc: + self.pts2read_DCchannels = int(self.systemHeaderObj.nChannels * self.processingHeaderObj.nHeights) + self.blocksize += self.pts2read_DCchannels + +# self.blocksize = self.pts2read_SelfSpectra + self.pts2read_CrossSpectra + self.pts2read_DCchannels + + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 def readBlock(self): """ Lee el bloque de datos desde la posicion actual del puntero del archivo (self.fp) y actualiza todos los parametros relacionados al bloque de datos (metadata + data). La data leida es almacenada en el buffer y el contador del buffer es seteado a 0 +<<<<<<< HEAD Return: None Variables afectadas: +======= + + Return: None + + Variables afectadas: + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 self.flagIsNewFile self.flagIsNewBlock self.nTotalBlocks @@ -245,14 +446,30 @@ class SpectraReader(JRODataReader, ProcessingUnit): self.data_cspc self.data_dc +<<<<<<< HEAD Exceptions: Si un bloque leido no es un bloque valido """ +======= + Exceptions: + Si un bloque leido no es un bloque valido + """ + print ' ======================================================== ' + print ' ' + print ' ' + print self.processingHeaderObj.totalSpectra, 'TotalSpectra', type(self.processingHeaderObj.totalSpectra) + print self.processingHeaderObj.spectraComb, 'SpectraComb', type(self.processingHeaderObj.spectraComb) + print ' ' + print ' ' + print ' ======================================================== ' + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 blockOk_flag = False fpointer = self.fp.tell() spc = numpy.fromfile( self.fp, self.dtype[0], self.pts2read_SelfSpectra ) spc = spc.reshape( (self.nRdChannels, self.processingHeaderObj.nHeights, self.processingHeaderObj.profilesPerBlock) ) #transforma a un arreglo 3D +<<<<<<< HEAD if self.processingHeaderObj.flag_cspc: cspc = numpy.fromfile( self.fp, self.dtype, self.pts2read_CrossSpectra ) @@ -263,10 +480,23 @@ class SpectraReader(JRODataReader, ProcessingUnit): dc = dc.reshape( (self.systemHeaderObj.nChannels, self.processingHeaderObj.nHeights) ) #transforma a un arreglo 2D +======= + + if self.processingHeaderObj.flag_cspc: + cspc = numpy.fromfile( self.fp, self.dtype, self.pts2read_CrossSpectra ) + cspc = cspc.reshape( (self.nRdPairs, self.processingHeaderObj.nHeights, self.processingHeaderObj.profilesPerBlock) ) #transforma a un arreglo 3D + + if self.processingHeaderObj.flag_dc: + dc = numpy.fromfile( self.fp, self.dtype, self.pts2read_DCchannels ) #int(self.processingHeaderObj.nHeights*self.systemHeaderObj.nChannels) ) + dc = dc.reshape( (self.systemHeaderObj.nChannels, self.processingHeaderObj.nHeights) ) #transforma a un arreglo 2D + + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 if not(self.processingHeaderObj.shif_fft): #desplaza a la derecha en el eje 2 determinadas posiciones shift = int(self.processingHeaderObj.profilesPerBlock/2) spc = numpy.roll( spc, shift , axis=2 ) +<<<<<<< HEAD if self.processingHeaderObj.flag_cspc: #desplaza a la derecha en el eje 2 determinadas posiciones @@ -277,11 +507,27 @@ class SpectraReader(JRODataReader, ProcessingUnit): self.data_spc = spc if self.processingHeaderObj.flag_cspc: +======= + + if self.processingHeaderObj.flag_cspc: + #desplaza a la derecha en el eje 2 determinadas posiciones + cspc = numpy.roll( cspc, shift, axis=2 ) + + #Dimensions : nChannels, nProfiles, nSamples + spc = numpy.transpose( spc, (0,2,1) ) + self.data_spc = spc + + if self.processingHeaderObj.flag_cspc: +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 cspc = numpy.transpose( cspc, (0,2,1) ) self.data_cspc = cspc['real'] + cspc['imag']*1j else: self.data_cspc = None +<<<<<<< HEAD +======= + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 if self.processingHeaderObj.flag_dc: self.data_dc = dc['real'] + dc['imag']*1j else: @@ -294,6 +540,7 @@ class SpectraReader(JRODataReader, ProcessingUnit): self.nReadBlocks += 1 return 1 +<<<<<<< HEAD def getFirstHeader(self): @@ -348,6 +595,62 @@ class SpectraReader(JRODataReader, ProcessingUnit): Affected: self.dataOut +======= + + def getFirstHeader(self): + + self.getBasicHeader() + + self.dataOut.systemHeaderObj = self.systemHeaderObj.copy() + + self.dataOut.radarControllerHeaderObj = self.radarControllerHeaderObj.copy() + +# self.dataOut.ippSeconds = self.ippSeconds + +# self.dataOut.timeInterval = self.radarControllerHeaderObj.ippSeconds * self.processingHeaderObj.nCohInt * self.processingHeaderObj.nIncohInt * self.processingHeaderObj.profilesPerBlock + + self.dataOut.dtype = self.dtype + +# self.dataOut.nPairs = self.nPairs + + self.dataOut.pairsList = self.rdPairList + + self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock + + self.dataOut.nFFTPoints = self.processingHeaderObj.profilesPerBlock + + self.dataOut.nCohInt = self.processingHeaderObj.nCohInt + + self.dataOut.nIncohInt = self.processingHeaderObj.nIncohInt + + xf = self.processingHeaderObj.firstHeight + self.processingHeaderObj.nHeights*self.processingHeaderObj.deltaHeight + + self.dataOut.heightList = numpy.arange(self.processingHeaderObj.firstHeight, xf, self.processingHeaderObj.deltaHeight) + + self.dataOut.channelList = range(self.systemHeaderObj.nChannels) + + self.dataOut.flagShiftFFT = True #Data is always shifted + + self.dataOut.flagDecodeData = self.processingHeaderObj.flag_decode #asumo q la data no esta decodificada + + self.dataOut.flagDeflipData = self.processingHeaderObj.flag_deflip #asumo q la data esta sin flip + + def getData(self): + """ + First method to execute before "RUN" is called. + + Copia el buffer de lectura a la clase "Spectra", + con todos los parametros asociados a este (metadata). cuando no hay datos en el buffer de + lectura es necesario hacer una nueva lectura de los bloques de datos usando "readNextBlock" + + Return: + 0 : Si no hay mas archivos disponibles + 1 : Si hizo una buena copia del buffer + + Affected: + self.dataOut + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 self.flagDiscontinuousBlock self.flagIsNewBlock """ @@ -356,21 +659,34 @@ class SpectraReader(JRODataReader, ProcessingUnit): self.dataOut.flagNoData = True print 'Process finished' return 0 +<<<<<<< HEAD self.flagDiscontinuousBlock = 0 self.flagIsNewBlock = 0 if self.__hasNotDataInBuffer(): +======= + + self.flagDiscontinuousBlock = 0 + self.flagIsNewBlock = 0 + + if self.__hasNotDataInBuffer(): +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 if not( self.readNextBlock() ): self.dataOut.flagNoData = True return 0 +<<<<<<< HEAD +======= + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 #data es un numpy array de 3 dmensiones (perfiles, alturas y canales) if self.data_spc is None: self.dataOut.flagNoData = True return 0 +<<<<<<< HEAD self.getBasicHeader() @@ -418,6 +734,55 @@ class SpectraWriter(JRODataWriter, Operation): Inicializador de la clase SpectraWriter para la escritura de datos de espectros. Affected: +======= + + self.getBasicHeader() + + self.getFirstHeader() + + self.dataOut.data_spc = self.data_spc + + self.dataOut.data_cspc = self.data_cspc + + self.dataOut.data_dc = self.data_dc + + self.dataOut.flagNoData = False + + self.dataOut.realtime = self.online + + return self.dataOut.data_spc + +class SpectraWriter(JRODataWriter, Operation): + + """ + Esta clase permite escribir datos de espectros a archivos procesados (.pdata). La escritura + de los datos siempre se realiza por bloques. + """ + + ext = ".pdata" + + optchar = "P" + + shape_spc_Buffer = None + + shape_cspc_Buffer = None + + shape_dc_Buffer = None + + data_spc = None + + data_cspc = None + + data_dc = None + +# dataOut = None + + def __init__(self): + """ + Inicializador de la clase SpectraWriter para la escritura de datos de espectros. + + Affected: +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 self.dataOut self.basicHeaderObj self.systemHeaderObj @@ -426,6 +791,7 @@ class SpectraWriter(JRODataWriter, Operation): Return: None """ +<<<<<<< HEAD Operation.__init__(self, **kwargs) @@ -437,11 +803,25 @@ class SpectraWriter(JRODataWriter, Operation): self.data_cspc = None +======= + + Operation.__init__(self) + + self.isConfig = False + + self.nTotalBlocks = 0 + + self.data_spc = None + + self.data_cspc = None + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 self.data_dc = None self.fp = None self.flagIsNewFile = 1 +<<<<<<< HEAD self.nTotalBlocks = 0 @@ -470,6 +850,36 @@ class SpectraWriter(JRODataWriter, Operation): return 1 +======= + + self.nTotalBlocks = 0 + + self.flagIsNewBlock = 0 + + self.setFile = None + + self.dtype = None + + self.path = None + + self.noMoreFiles = 0 + + self.filename = None + + self.basicHeaderObj = BasicHeader(LOCALTIME) + + self.systemHeaderObj = SystemHeader() + + self.radarControllerHeaderObj = RadarControllerHeader() + + self.processingHeaderObj = ProcessingHeader() + + + def hasAllDataInBuffer(self): + return 1 + + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 def setBlockDimension(self): """ Obtiene las formas dimensionales del los subbloques de datos que componen un bloque @@ -488,6 +898,7 @@ class SpectraWriter(JRODataWriter, Operation): self.shape_cspc_Buffer = (self.dataOut.nPairs, self.processingHeaderObj.nHeights, self.processingHeaderObj.profilesPerBlock) +<<<<<<< HEAD self.shape_dc_Buffer = (self.dataOut.nChannels, self.processingHeaderObj.nHeights) @@ -497,6 +908,17 @@ class SpectraWriter(JRODataWriter, Operation): """ Escribe el buffer en el file designado +======= + + self.shape_dc_Buffer = (self.dataOut.nChannels, + self.processingHeaderObj.nHeights) + + + def writeBlock(self): + """ + Escribe el buffer en el file designado + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 Affected: self.data_spc self.data_cspc @@ -504,11 +926,19 @@ class SpectraWriter(JRODataWriter, Operation): self.flagIsNewFile self.flagIsNewBlock self.nTotalBlocks +<<<<<<< HEAD self.nWriteBlocks Return: None """ +======= + self.nWriteBlocks + + Return: None + """ + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 spc = numpy.transpose( self.data_spc, (0,2,1) ) if not( self.processingHeaderObj.shif_fft ): spc = numpy.roll( spc, self.processingHeaderObj.profilesPerBlock/2, axis=2 ) #desplaza a la derecha en el eje 2 determinadas posiciones @@ -525,7 +955,11 @@ class SpectraWriter(JRODataWriter, Operation): data['imag'] = cspc.imag data = data.reshape((-1)) data.tofile(self.fp) +<<<<<<< HEAD +======= + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 if self.data_dc is not None: data = numpy.zeros( self.shape_dc_Buffer, self.dtype ) dc = self.data_dc @@ -535,6 +969,7 @@ class SpectraWriter(JRODataWriter, Operation): data.tofile(self.fp) # self.data_spc.fill(0) +<<<<<<< HEAD # # if self.data_dc is not None: # self.data_dc.fill(0) @@ -542,11 +977,21 @@ class SpectraWriter(JRODataWriter, Operation): # if self.data_cspc is not None: # self.data_cspc.fill(0) +======= +# +# if self.data_dc is not None: +# self.data_dc.fill(0) +# +# if self.data_cspc is not None: +# self.data_cspc.fill(0) + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 self.flagIsNewFile = 0 self.flagIsNewBlock = 1 self.nTotalBlocks += 1 self.nWriteBlocks += 1 self.blockIndex += 1 +<<<<<<< HEAD # print "[Writing] Block = %d04" %self.blockIndex @@ -554,11 +999,21 @@ class SpectraWriter(JRODataWriter, Operation): """ Setea un bloque de datos y luego los escribe en un file +======= + +# print "[Writing] Block = %d04" %self.blockIndex + + def putData(self): + """ + Setea un bloque de datos y luego los escribe en un file + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 Affected: self.data_spc self.data_cspc self.data_dc +<<<<<<< HEAD Return: 0 : Si no hay data o no hay mas files que puedan escribirse 1 : Si se escribio la data de un bloque en un file @@ -588,17 +1043,53 @@ class SpectraWriter(JRODataWriter, Operation): if self.dataOut.data_dc is not None: self.data_dc = self.dataOut.data_dc.copy() +======= + Return: + 0 : Si no hay data o no hay mas files que puedan escribirse + 1 : Si se escribio la data de un bloque en un file + """ + + if self.dataOut.flagNoData: + return 0 + + self.flagIsNewBlock = 0 + + if self.dataOut.flagDiscontinuousBlock: + self.data_spc.fill(0) + self.data_cspc.fill(0) + self.data_dc.fill(0) + self.setNextFile() + + if self.flagIsNewFile == 0: + self.setBasicHeader() + + self.data_spc = self.dataOut.data_spc.copy() + + if self.dataOut.data_cspc is not None: + self.data_cspc = self.dataOut.data_cspc.copy() + + if self.dataOut.data_dc is not None: + self.data_dc = self.dataOut.data_dc.copy() + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 # #self.processingHeaderObj.dataBlocksPerFile) if self.hasAllDataInBuffer(): # self.setFirstHeader() self.writeNextBlock() +<<<<<<< HEAD return 1 +======= + + return 1 + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 def __getBlockSize(self): ''' Este metodos determina el cantidad de bytes para un bloque de datos de tipo Spectra ''' +<<<<<<< HEAD dtype_width = self.getDtypeWidth() @@ -624,11 +1115,39 @@ class SpectraWriter(JRODataWriter, Operation): """ Obtiene una copia del First Header +======= + + dtype_width = self.getDtypeWidth() + + pts2write = self.dataOut.nHeights * self.dataOut.nFFTPoints + + pts2write_SelfSpectra = int(self.dataOut.nChannels * pts2write) + blocksize = (pts2write_SelfSpectra*dtype_width) + + if self.dataOut.data_cspc is not None: + pts2write_CrossSpectra = int(self.dataOut.nPairs * pts2write) + blocksize += (pts2write_CrossSpectra*dtype_width*2) + + if self.dataOut.data_dc is not None: + pts2write_DCchannels = int(self.dataOut.nChannels * self.dataOut.nHeights) + blocksize += (pts2write_DCchannels*dtype_width*2) + +# blocksize = blocksize #* datatypeValue * 2 #CORREGIR ESTO + + return blocksize + + def setFirstHeader(self): + + """ + Obtiene una copia del First Header + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 Affected: self.systemHeaderObj self.radarControllerHeaderObj self.dtype +<<<<<<< HEAD Return: None """ @@ -637,43 +1156,82 @@ class SpectraWriter(JRODataWriter, Operation): self.systemHeaderObj.nChannels = self.dataOut.nChannels self.radarControllerHeaderObj = self.dataOut.radarControllerHeaderObj.copy() +======= + Return: + None + """ + + self.systemHeaderObj = self.dataOut.systemHeaderObj.copy() + self.systemHeaderObj.nChannels = self.dataOut.nChannels + self.radarControllerHeaderObj = self.dataOut.radarControllerHeaderObj.copy() + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 self.processingHeaderObj.dtype = 1 # Spectra self.processingHeaderObj.blockSize = self.__getBlockSize() self.processingHeaderObj.profilesPerBlock = self.dataOut.nFFTPoints self.processingHeaderObj.dataBlocksPerFile = self.blocksPerFile self.processingHeaderObj.nWindows = 1 #podria ser 1 o self.dataOut.processingHeaderObj.nWindows self.processingHeaderObj.nCohInt = self.dataOut.nCohInt# Se requiere para determinar el valor de timeInterval +<<<<<<< HEAD self.processingHeaderObj.nIncohInt = self.dataOut.nIncohInt self.processingHeaderObj.totalSpectra = self.dataOut.nPairs + self.dataOut.nChannels self.processingHeaderObj.shif_fft = self.dataOut.flagShiftFFT +======= + self.processingHeaderObj.nIncohInt = self.dataOut.nIncohInt + self.processingHeaderObj.totalSpectra = self.dataOut.nPairs + self.dataOut.nChannels + self.processingHeaderObj.shif_fft = self.dataOut.flagShiftFFT + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 if self.processingHeaderObj.totalSpectra > 0: channelList = [] for channel in range(self.dataOut.nChannels): channelList.append(channel) channelList.append(channel) +<<<<<<< HEAD +======= + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 pairsList = [] if self.dataOut.nPairs > 0: for pair in self.dataOut.pairsList: pairsList.append(pair[0]) pairsList.append(pair[1]) +<<<<<<< HEAD spectraComb = channelList + pairsList spectraComb = numpy.array(spectraComb, dtype="u1") self.processingHeaderObj.spectraComb = spectraComb +======= + + spectraComb = channelList + pairsList + spectraComb = numpy.array(spectraComb, dtype="u1") + self.processingHeaderObj.spectraComb = spectraComb + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 if self.dataOut.code is not None: self.processingHeaderObj.code = self.dataOut.code self.processingHeaderObj.nCode = self.dataOut.nCode self.processingHeaderObj.nBaud = self.dataOut.nBaud +<<<<<<< HEAD +======= + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 if self.processingHeaderObj.nWindows != 0: self.processingHeaderObj.firstHeight = self.dataOut.heightList[0] self.processingHeaderObj.deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0] self.processingHeaderObj.nHeights = self.dataOut.nHeights self.processingHeaderObj.samplesWin = self.dataOut.nHeights +<<<<<<< HEAD self.processingHeaderObj.processFlags = self.getProcessFlags() +======= + + self.processingHeaderObj.processFlags = self.getProcessFlags() + +>>>>>>> 08c4507d6c3c48f6c52326d5dedfa1972fb26356 self.setBasicHeader() diff --git a/schainpy/model/io/jroIO_spectra.pyc b/schainpy/model/io/jroIO_spectra.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b0c1fc606ae08d5e9fc8500c2c52f8490344565 GIT binary patch literal 17096 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 WC78_ytr7b)U7i~0n6tkXU;Zyqunn95 literal 0 Hc$@3>D9{$|OObxR@0>Fv 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