##// END OF EJS Templates
merged branches
joabAM -
r1370:81f892b894eb merge
parent child
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,28
1 This software, unless otherwise noted, is licensed under the BSD 3-clause.
2
3 Copyright (c) 2012-2020 Jicamarca Radio Observatory
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice, this
9 list of conditions and the following disclaimer.
10
11 * Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
14
15 * Neither the name of the copyright holder nor the names of its
16 contributors may be used to endorse or promote products derived from
17 this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,82
1 #include <Python.h>
2 #include <numpy/arrayobject.h>
3 #include <math.h>
4
5
6 static PyObject *hildebrand_sekhon(PyObject *self, PyObject *args) {
7 double navg;
8 PyObject *data_obj, *data_array;
9
10 if (!PyArg_ParseTuple(args, "Od", &data_obj, &navg)) {
11 return NULL;
12 }
13
14 data_array = PyArray_FROM_OTF(data_obj, NPY_FLOAT64, NPY_IN_ARRAY);
15
16 if (data_array == NULL) {
17 Py_XDECREF(data_array);
18 Py_XDECREF(data_obj);
19 return NULL;
20 }
21 double *sortdata = (double*)PyArray_DATA(data_array);
22 int lenOfData = (int)PyArray_SIZE(data_array) ;
23 double nums_min = lenOfData*0.2;
24 if (nums_min <= 5) nums_min = 5;
25 double sump = 0;
26 double sumq = 0;
27 long j = 0;
28 int cont = 1;
29 double rtest = 0;
30 while ((cont == 1) && (j < lenOfData)) {
31 sump = sump + sortdata[j];
32 sumq = sumq + pow(sortdata[j], 2);
33 if (j > nums_min) {
34 rtest = (double)j/(j-1) + 1/navg;
35 if ((sumq*j) > (rtest*pow(sump, 2))) {
36 j = j - 1;
37 sump = sump - sortdata[j];
38 sumq = sumq - pow(sortdata[j],2);
39 cont = 0;
40 }
41 }
42 j = j + 1;
43 }
44
45 double lnoise = sump / j;
46
47 Py_DECREF(data_array);
48
49 // return PyLong_FromLong(lnoise);
50 return PyFloat_FromDouble(lnoise);
51 }
52
53
54 static PyMethodDef noiseMethods[] = {
55 { "hildebrand_sekhon", hildebrand_sekhon, METH_VARARGS, "Get noise with hildebrand_sekhon algorithm" },
56 { NULL, NULL, 0, NULL }
57 };
58
59 #if PY_MAJOR_VERSION >= 3
60
61 static struct PyModuleDef noisemodule = {
62 PyModuleDef_HEAD_INIT,
63 "_noise",
64 "Get noise with hildebrand_sekhon algorithm",
65 -1,
66 noiseMethods
67 };
68
69 #endif
70
71 #if PY_MAJOR_VERSION >= 3
72 PyMODINIT_FUNC PyInit__noise(void) {
73 Py_Initialize();
74 import_array();
75 return PyModule_Create(&noisemodule);
76 }
77 #else
78 PyMODINIT_FUNC init_noise() {
79 Py_InitModule("_noise", noiseMethods);
80 import_array();
81 }
82 #endif
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100755
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100755
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100755
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100755
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100755
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100755
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100755
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,114 +1,102
1 1 # Byte-compiled / optimized / DLL files
2 2 __pycache__/
3 3 *.py[cod]
4 4 *$py.class
5 5
6 6 # C extensions
7 7 *.so
8 8
9 9 # Distribution / packaging
10 10 .Python
11 11 env/
12 12 build/
13 13 develop-eggs/
14 14 dist/
15 15 downloads/
16 16 eggs/
17 17 .eggs/
18 18 lib/
19 19 lib64/
20 20 parts/
21 21 sdist/
22 22 var/
23 23 wheels/
24 24 *.egg-info/
25 25 .installed.cfg
26 26 *.egg
27 27
28 28 # PyInstaller
29 29 # Usually these files are written by a python script from a template
30 30 # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 31 *.manifest
32 32 *.spec
33 33
34 34 # Installer logs
35 35 pip-log.txt
36 36 pip-delete-this-directory.txt
37 37
38 38 # Unit test / coverage reports
39 39 htmlcov/
40 40 .tox/
41 41 .coverage
42 42 .coverage.*
43 43 .cache
44 44 nosetests.xml
45 45 coverage.xml
46 46 *,cover
47 47 .hypothesis/
48 48
49 49 # Translations
50 50 *.mo
51 51 *.pot
52 52
53 53 # Django stuff:
54 54 *.log
55 55 local_settings.py
56 56
57 57 # Flask stuff:
58 58 instance/
59 59 .webassets-cache
60 60
61 61 # Scrapy stuff:
62 62 .scrapy
63 63
64 64 # Sphinx documentation
65 65 docs/_build/
66 66
67 67 # PyBuilder
68 68 target/
69 69
70 70 # Jupyter Notebook
71 71 .ipynb_checkpoints
72 72
73 73 # pyenv
74 74 .python-version
75 75
76 76 # celery beat schedule file
77 77 celerybeat-schedule
78 78
79 79 # SageMath parsed files
80 80 *.sage.py
81 81
82 82 # dotenv
83 83 .env
84 84
85 85 # virtualenv
86 86 .venv
87 87 venv/
88 88 ENV/
89 89
90 90 # Spyder project settings
91 91 .spyderproject
92 92 .spyproject
93 93
94 94 # Rope project settings
95 95 .ropeproject
96 96
97 97 # mkdocs documentation
98 98 /site
99 99
100 100 # eclipse
101 101 .project
102 102 .pydevproject
103 # vscode
104
105 .vscode
106
107 schaingui/node_modules/
108 schainpy/scripts/
109 .svn/
110 *.png
111 *.pyc
112 .vscode
113 trash
114 *.log
@@ -1,119 +1,141
1 ## CHANGELOG:
1 # CHANGELOG
2 2
3 ### 3.0
4 * Python 3.x compatible
5 * New architecture with multiprocessing and IPC communication
6 * Add @MPDecorator for multiprocessing Units and Operations
3 ## 3.0.0
4
5 * Python 3.x & 2.X compatible
6 * New architecture with multiprocessing support
7 * Add @MPDecorator for multiprocessing Operations (Plots, Writers and Publishers)
7 8 * Added new type of operation `external` for non-locking operations
8 9 * New plotting architecture with buffering/throttle capabilities to speed up plots
10 * Clean controller to optimize scripts (format & optype are no longer required)
11 * Replace `ParamReader` and `ParamWriter` with new flexible `HDFReader` and `HDFWriter`
12 * New GUI with dynamic load of Units and operations (use Kivy framework)
13 * Clean code
14
15 ## 2.3
9 16
10 ### 2.3
11 17 * Added support for Madrigal formats (reading/writing).
12 18 * Added support for reading BLTR parameters (*.sswma).
13 19 * Added support for reading Julia format (*.dat).
14 20 * Added high order function `MPProject` for multiprocessing scripts.
15 21 * Added two new Processing Units `PublishData` and `ReceiverData` for receiving and sending dataOut through multiple ways (tcp, ipc, inproc).
16 22 * Added a new graphics Processing Unit `PlotterReceiver`. It is decoupled from normal processing sequence with support for data generated by multiprocessing scripts.
17 23 * Added support for sending realtime graphic to web server.
18 * GUI command `schain` is now `schainGUI`.
19 * Added a CLI tool named `schain`.
20 * Scripts templates can be now generated with `schain generate`.
21 * Now it is possible to search Processing Units and Operations with `schain search [module]` to get the right name and its allowed parameters.
22 * `schain xml` to run xml scripts.
24 * GUI command `schain` is now `schainGUI`.
25 * Added a CLI tool named `schain`.
26 * Scripts templates can be now generated with `schain generate`.
27 * Now it is possible to search Processing Units and Operations with `schain search [module]` to get the right name and its allowed parameters.
28 * `schain xml` to run xml scripts.
23 29 * Added suggestions when parameters are poorly written.
24 30 * `Controller.start()` now runs in a different process than the process calling it.
25 31 * Added `schainpy.utils.log` for log standarization.
26 32 * Running script on online mode no longer ignores date and hour. Issue #1109.
27 33 * Added support for receving voltage data directly from JARS (tcp, ipc).
28 34 * Updated README for MAC OS GUI installation.
29 35 * Setup now installs numpy.
30 36
31 ### 2.2.6
37 ## 2.2.6
38
32 39 * Graphics generated by the GUI are now the same as generated by scripts. Issue #1074.
33 40 * Added support for C extensions.
34 41 * Function `hildebrand_sehkon` optimized with a C wrapper.
35 42 * Numpy version updated.
36 43 * Migration to GIT.
37 44
38 ### 2.2.5:
45 ## 2.2.5
46
39 47 * splitProfiles and combineProfiles modules were added to VoltageProc and Signal Chain GUI.
40 48 * nProfiles of USRP data (hdf5) is the number of profiles thera are in one second.
41 49 * jroPlotter works directly with data objects instead of dictionaries
42 50 * script "schain" was added to Signal Chain installer
43 51
44 ### 2.2.4.1:
45 * jroIO_usrp.py is update to read Sandra's data
52 ## 2.2.4.1
53
54 * jroIO_usrp.py is update to read Sandra's data
46 55 * decimation in Spectra and RTI plots is always enabled.
47 56 * time* window option added to GUI
48 57
49 ### 2.2.4:
58 ## 2.2.4
59
50 60 * jroproc_spectra_lags.py added to schainpy
51 61 * Bug fixed in schainGUI: ProcUnit was created with the same id in some cases.
52 62 * Bug fixed in jroHeaderIO: Header size validation.
53 63
54 ### 2.2.3.1:
64 ## 2.2.3.1
65
55 66 * Filtering block by time has been added.
56 67 * Bug fixed plotting RTI, CoherenceMap and others using xmin and xmax parameters. The first day worked
57 68 properly but the next days did not.
58 69
59 ### 2.2.3:
70 ## 2.2.3
71
60 72 * Bug fixed in GUI: Error getting(reading) Code value
61 73 * Bug fixed in GUI: Flip option always needs channelList field
62 74 * Bug fixed in jrodata: when one branch modified a value in "dataOut" (example: dataOut.code) this value
63 75 was modified for every branch (because this was a reference). It was modified in data.copy()
64 76 * Bug fixed in jroproc_voltage.profileSelector(): rangeList replaces to profileRangeList.
65 77
66 ### 2.2.2:
78 ## 2.2.2
79
67 80 * VoltageProc: ProfileSelector, Reshape, Decoder with nTxs!=1 and getblock=True was tested
68 81 * Rawdata and testRawdata.py added to Signal Chain project
69 82
70 ### 2.2.1:
83 ## 2.2.1
84
71 85 * Bugs fixed in GUI
72 86 * Views were improved in GUI
73 87 * Support to MST* ISR experiments
74 88 * Bug fixed getting noise using hyldebrant. (minimum number of points > 20%)
75 89 * handleError added to jroplotter.py
76 90
77 ### 2.2.0:
91 ## 2.2.0
92
78 93 * GUI: use of external plotter
79 94 * Compatible with matplotlib 1.5.0
80 95
81 ### 2.1.5:
96 ## 2.1.5
97
82 98 * serializer module added to Signal Chain
83 99 * jroplotter.py added to Signal Chain
84 100
85 ### 2.1.4.2:
101 ## 2.1.4.2
102
86 103 * A new Plotter Class was added
87 104 * Project.start() does not accept filename as a parameter anymore
88 105
89 ### 2.1.4.1:
106 ## 2.1.4.1
107
90 108 * Send notifications when an error different to ValueError is detected
91 109
92 ### 2.1.4:
110 ## 2.1.4
111
93 112 * Sending error notifications to signal chain administrator
94 113 * Login to email server added
95 114
96 ### 2.1.3.3:
115 ## 2.1.3.3
116
97 117 * Colored Button Icons were added to GUI
98 118
99 ### 2.1.3.2:
119 ## 2.1.3.2
120
100 121 * GUI: user interaction enhanced
101 122 * controller_api.py: Safe access to ControllerThead
102 123
103 ### 2.1.3.1:
124 ## 2.1.3.1
125
104 126 * GUI: every icon were resized
105 127 * jroproc_voltage.py: Print a message when "Read from code" option is selected and the code is not defined inside data file
106 128
107 ### 2.1.3:
129 ## 2.1.3
130
108 131 * jroplot_heispectra.py: SpectraHeisScope was not showing the right channels
109 * jroproc_voltage.py: Bug fixed selecting profiles (self.nProfiles took a wrong value),
110 Bug fixed selecting heights by block (selecting profiles instead heights)
132 * jroproc_voltage.py: Bug fixed selecting profiles (self.nProfiles took a wrong value), Bug fixed selecting heights by block (selecting profiles instead heights)
111 133 * jroproc_voltage.py: New feature added: decoding data by block using FFT.
112 134 * jroIO_heispectra.py: Bug fixed in FitsReader. Using local Fits instance instead schainpy.mode.data.jrodata.Fits.
113 135 * jroIO_heispectra.py: Channel index list does not exist.
114 136
115 ### 2.1.2:
116 * jroutils_ftp.py: Bug fixed, Any error sending file stopped the Server Thread
117 Server thread opens and closes remote server each time file list is sent
137 ## 2.1.2
138
139 * 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
118 140 * jroplot_spectra.py: Noise path was not being created when noise data is saved.
119 * jroIO_base.py: startTime can be greater than endTime. Example: SpreadF [18:00 * 07:00] No newline at end of file
141 * jroIO_base.py: startTime can be greater than endTime. Example: SpreadF
@@ -1,155 +1,104
1 1 # Signal Chain
2 2
3 ## Introduction
3 Signal Chain is a radar data processing library wich includes modules to read,
4 and write different files formats, besides modules to process and visualize the
5 data.
4 6
5 Signal Chain (SCh) is a radar data processing library developed using [Python](www.python.org) at JRO. SCh provides modules to read, write, process and plot data.
7 ## Dependencies
6 8
7 ## Installation
8
9 Install system dependencies, clone the latest version from [here](http://jro-dev.igp.gob.pe/rhodecode/schain/) and install it as a normal python package.
9 - GCC (gcc or gfortran)
10 - Python.h (python-dev or python-devel)
11 - Python-TK (python-tk)
12 - HDF5 libraries (libhdf5-dev)
10 13
11 ### Linux based system
12 ```
13 $ sudo apt-get install python-pip python-dev gfortran libpng-dev freetype* libblas-dev liblapack-dev libatlas-base-dev python-qt4 python-tk libssl-dev libhdf5-dev
14 $ git clone http://jro-dev.igp.gob.pe/rhodecode/schain/
15 $ cd schain
16 $ sudo pip install ./
17
18 ```
14 ## Installation
19 15
20 ### MAC Os
21 ```
22 $ brew install python
23 $ brew install cartr/qt4/pyqt
24 $ git clone http://jro-dev.igp.gob.pe/rhodecode/schain/
25 $ cd schain
26 $ pip install ./
27 ```
16 To get started the easiest way to install it is through
17 [PyPI](https://pypi.org/project/schainpy/) with pip. We strongly recommend to
18 use an virtual environment like virtualenv or anaconda.
28 19
29 **It is recommended to install schain in a virtual environment**
30 ```
31 $ virtualenv /path/to/virtual
32 $ source /path/to/virtual/bin/activate
33 (virtual) $ cd schain
34 (virtual) $ pip install ./
35 (virtual) $ bash link_PyQt4.sh
20 ```bash
21 pip install schainpy
36 22 ```
37 23
38 ### Docker
24 ### From source
39 25
40 Download Dockerfile from the repository, and create a docker image
26 First, ensure that you have the above-listed dependencies installed, then clone
27 the repository and install as normal python package:
41 28
29 ```bash
30 git clone https://github.com/JRO-Peru/schainpy.git
31 cd schain
32 git checkout `branch-name` (optional)
33 sudo pip install ./
42 34 ```
43 $ docker build -t schain .
44 ```
45
46 You can run a container using an xml file or a schain script also you need to mount a volume for the data input and for the output files/plots
47 ```
48 $ docker run -it --rm --volume /path/to/host/data:/data schain xml /data/test.xml
49 $ docker run -it --rm --volume /path/to/host/data:/data --entrypoint /urs/local/bin/python schain /data/test.py
50 ```
51
52 ## First Script
53
54 Read Spectra data (.pdata) - remove dc - plot spectra & RTI
55
56 Import SCh and creating a project
57
58 ```python
59 #!/usr/bin/python
60 35
61 from schainpy.controller import Project
62
63 controller = Project()
64 controller.setup(id = '100',
65 name='test',
66 description='Basic experiment')
36 ### Using Docker
67 37
38 Download Dockerfile from the repository, and create a docker image:
68 39
40 ```bash
41 docker build -t schain .
69 42 ```
70 43
71 Adding read unit and operations
72
73 ```python
74 read_unit = controller.addReadUnit(datatype='Spectra',
75 path='/path/to/pdata/',
76 startDate='2014/01/31',
77 endDate='2014/03/31',
78 startTime='00:00:00',
79 endTime='23:59:59',
80 online=0,
81 walk=0)
82
83 proc_unit = controller.addProcUnit(datatype='Spectra',
84 inputId=read_unit.getId())
85
86 op = proc_unit.addOperation(name='selectChannels')
87 op.addParameter(name='channelList', value='0,1', format='intlist')
88
89 op = proc_unit.addOperation(name='selectHeights')
90 op.addParameter(name='minHei', value='80', format='float')
91 op.addParameter(name='maxHei', value='200', format='float')
92
93 op = proc_unit.addOperation(name='removeDC')
44 You can run a container using an xml file or a schain script also you need to
45 mount a volume for the data input and for the output files/plots:
94 46
47 ```bash
48 docker run -it --rm --volume /path/to/host/data:/data schain xml /data/test.xml
49 docker run -it --rm --volume /path/to/host/data:/data --entrypoint /urs/local/bin/python schain /data/test.py
95 50 ```
96 51
97 Plotting data & start project
52 ## CLI (command line interface)
98 53
99 ```python
100 op = proc_unit.addOperation(name='SpectraPlot', optype='other')
101 op.addParameter(name='id', value='1', format='int')
102 op.addParameter(name='wintitle', value='Spectra', format='str')
54 Signal Chain provides the following commands:
103 55
104 op = procUnitConfObj1.addOperation(name='RTIPlot', optype='other')
105 op.addParameter(name='id', value='2', format='int')
106 op.addParameter(name='wintitle', value='RTI', format='str')
56 - schainGUI: Open the GUI
57 - schain: Signal chain command line
107 58
108 controller.start()
109
110 ```
111
112 Full script
59 ## Example
113 60
61 Here you can find an script to read Spectra data (.pdata), remove dc and plot
62 self-spectra & RTI:
114 63
115 64 ```python
116 65 #!/usr/bin/python
117 66
118 67 from schainpy.controller import Project
119 68
120 controller = Project()
121 controller.setup(id = '100',
122 name='test',
123 description='Basic experiment')
124 read_unit = controller.addReadUnit(datatype='Spectra',
125 path='/path/to/pdata/',
126 startDate='2014/01/31',
127 endDate='2014/03/31',
128 startTime='00:00:00',
129 endTime='23:59:59',
130 online=0,
131 walk=0)
132
133 proc_unit = controller.addProcUnit(datatype='Spectra',
134 inputId=read_unit.getId())
69 prj = Project()
70
71 read_unit = prj.addReadUnit(
72 datatype='Spectra',
73 path='/path/to/pdata/',
74 startDate='2014/01/31',
75 endDate='2014/03/31',
76 startTime='00:00:00',
77 endTime='23:59:59',
78 online=0,
79 walk=0
80 )
81
82 proc_unit = prj.addProcUnit(
83 datatype='Spectra',
84 inputId=read_unit.getId()
85 )
135 86
136 87 op = proc_unit.addOperation(name='selectChannels')
137 op.addParameter(name='channelList', value='0,1', format='intlist')
88 op.addParameter(name='channelList', value='0,1')
138 89
139 90 op = proc_unit.addOperation(name='selectHeights')
140 op.addParameter(name='minHei', value='80', format='float')
141 op.addParameter(name='maxHei', value='200', format='float')
91 op.addParameter(name='minHei', value='80')
92 op.addParameter(name='maxHei', value='200')
142 93
143 94 op = proc_unit.addOperation(name='removeDC')
144 95
145 op = proc_unit.addOperation(name='SpectraPlot', optype='other')
146 op.addParameter(name='id', value='6', format='int')
96 op = proc_unit.addOperation(name='SpectraPlot')
147 97 op.addParameter(name='wintitle', value='Spectra', format='str')
148 98
149 op = procUnitConfObj1.addOperation(name='RTIPlot', optype='other')
150 op.addParameter(name='id', value='2', format='int')
99 op = proc_unit.addOperation(name='RTIPlot')
151 100 op.addParameter(name='wintitle', value='RTI', format='str')
152 101
153 controller.start()
102 prj.start()
154 103
155 ``` No newline at end of file
104 ```
@@ -1,7 +1,8
1 '''
2 Created on Jul 3, 2018
1 """Signal chain python package"""
3 2
4 @author $Author$
5 @version $Id$
6 '''
7 __version__ = '3.0'
3 try:
4 from schainpy.controller import Project
5 except:
6 pass
7
8 __version__ = '3.0.0b6'
@@ -1,236 +1,238
1 1 import click
2 import schainpy
3 2 import subprocess
4 3 import os
5 4 import sys
6 5 import glob
7 save_stdout = sys.stdout
8 sys.stdout = open('/dev/null', 'w')
9 from multiprocessing import cpu_count
6 import schainpy
10 7 from schainpy.controller import Project
11 8 from schainpy.model import Operation, ProcessingUnit
12 9 from schainpy.utils import log
13 10 from importlib import import_module
14 11 from pydoc import locate
15 12 from fuzzywuzzy import process
16 13 from schainpy.cli import templates
17 14 import inspect
18 15 try:
19 16 from queue import Queue
20 17 except:
21 18 from Queue import Queue
22 sys.stdout = save_stdout
23 19
24 20
25 21 def getProcs():
26 22 modules = dir(schainpy.model)
27 23 procs = check_module(modules, 'processing')
28 24 try:
29 25 procs.remove('ProcessingUnit')
30 26 except Exception as e:
31 27 pass
32 28 return procs
33 29
34 30 def getOperations():
35 31 module = dir(schainpy.model)
36 32 noProcs = [x for x in module if not x.endswith('Proc')]
37 33 operations = check_module(noProcs, 'operation')
38 34 try:
39 35 operations.remove('Operation')
40 36 operations.remove('Figure')
41 37 operations.remove('Plot')
42 38 except Exception as e:
43 39 pass
44 40 return operations
45 41
46 42 def getArgs(op):
47 43 module = locate('schainpy.model.{}'.format(op))
48
49 if hasattr(module, '__attrs__'):
50 args = module.__attrs__
44 try:
45 obj = module(1, 2, 3, Queue())
46 except:
47 obj = module()
48
49 if hasattr(obj, '__attrs__'):
50 args = obj.__attrs__
51 51 else:
52 args = inspect.getargspec(module.run).args
52 if hasattr(obj, 'myrun'):
53 args = inspect.getfullargspec(obj.myrun).args
54 else:
55 args = inspect.getfullargspec(obj.run).args
56
53 57 try:
54 58 args.remove('self')
55 59 except Exception as e:
56 60 pass
57 61 try:
58 62 args.remove('dataOut')
59 63 except Exception as e:
60 64 pass
61 65 return args
62 66
63 67 def getDoc(obj):
64 68 module = locate('schainpy.model.{}'.format(obj))
65 69 try:
66 obj = module(1,2,3,Queue(),5,6)
70 obj = module(1, 2, 3, Queue())
67 71 except:
68 72 obj = module()
69 73 return obj.__doc__
70 74
71 75 def getAll():
72 76 modules = getOperations()
73 77 modules.extend(getProcs())
74 78 return modules
75 79
76 80
77 81 def print_version(ctx, param, value):
78 82 if not value or ctx.resilient_parsing:
79 83 return
80 84 click.echo(schainpy.__version__)
81 85 ctx.exit()
82 86
83 87
84 88 PREFIX = 'experiment'
85 89
86 90 @click.command()
87 91 @click.option('--version', '-v', is_flag=True, callback=print_version, help='SChain version', type=str)
88 92 @click.argument('command', default='run', required=True)
89 93 @click.argument('nextcommand', default=None, required=False, type=str)
90 94 def main(command, nextcommand, version):
91 95 """COMMAND LINE INTERFACE FOR SIGNAL CHAIN - JICAMARCA RADIO OBSERVATORY V3.0\n
92 Available commands.\n
96 Available commands:\n
93 97 xml: runs a schain XML generated file\n
94 run: runs any python script starting 'experiment_'\n
98 run: runs any python script'\n
95 99 generate: generates a template schain script\n
96 100 list: return a list of available procs and operations\n
97 101 search: return avilable operations, procs or arguments of the given
98 102 operation/proc\n"""
99 103 if command == 'xml':
100 104 runFromXML(nextcommand)
101 105 elif command == 'generate':
102 106 generate()
103 107 elif command == 'test':
104 108 test()
105 109 elif command == 'run':
106 110 runschain(nextcommand)
107 111 elif command == 'search':
108 112 search(nextcommand)
109 113 elif command == 'list':
110 114 cmdlist(nextcommand)
111 115 else:
112 116 log.error('Command {} is not defined'.format(command))
113 117
114 118
115 119 def check_module(possible, instance):
116 120 def check(x):
117 121 try:
118 122 instancia = locate('schainpy.model.{}'.format(x))
119 123 ret = instancia.proc_type == instance
120 124 return ret
121 125 except Exception as e:
122 126 return False
123 127 clean = clean_modules(possible)
124 128 return [x for x in clean if check(x)]
125 129
126 130
127 131 def clean_modules(module):
128 132 noEndsUnder = [x for x in module if not x.endswith('__')]
129 133 noStartUnder = [x for x in noEndsUnder if not x.startswith('__')]
130 134 noFullUpper = [x for x in noStartUnder if not x.isupper()]
131 135 return noFullUpper
132 136
133 137 def cmdlist(nextcommand):
134 138 if nextcommand is None:
135 139 log.error('Missing argument, available arguments: procs, operations', '')
136 140 elif nextcommand == 'procs':
137 141 procs = getProcs()
138 142 log.success(
139 143 'Current ProcessingUnits are:\n {}'.format('\n '.join(procs)), '')
140 144 elif nextcommand == 'operations':
141 145 operations = getOperations()
142 146 log.success('Current Operations are:\n {}'.format(
143 147 '\n '.join(operations)), '')
144 148 else:
145 149 log.error('Wrong argument', '')
146 150
147 151 def search(nextcommand):
148 152 if nextcommand is None:
149 153 log.error('There is no Operation/ProcessingUnit to search', '')
150 154 else:
151 try:
155 try:
152 156 args = getArgs(nextcommand)
153 157 doc = getDoc(nextcommand)
154 if len(args) == 0:
155 log.success('\n{} has no arguments'.format(nextcommand), '')
156 else:
157 log.success('{}\n{}\n\narguments:\n {}'.format(
158 nextcommand, doc, ', '.join(args)), '')
158 log.success('{}\n{}\n\nparameters:\n {}'.format(
159 nextcommand, doc, ', '.join(args)), ''
160 )
159 161 except Exception as e:
160 162 log.error('Module `{}` does not exists'.format(nextcommand), '')
161 163 allModules = getAll()
162 164 similar = [t[0] for t in process.extract(nextcommand, allModules, limit=12) if t[1]>80]
163 165 log.success('Possible modules are: {}'.format(', '.join(similar)), '')
164 166
165 167 def runschain(nextcommand):
166 168 if nextcommand is None:
167 169 currentfiles = glob.glob('./{}_*.py'.format(PREFIX))
168 170 numberfiles = len(currentfiles)
169 171 if numberfiles > 1:
170 172 log.error('There is more than one file to run')
171 173 elif numberfiles == 1:
172 174 subprocess.call(['python ' + currentfiles[0]], shell=True)
173 175 else:
174 176 log.error('There is no file to run')
175 177 else:
176 178 try:
177 179 subprocess.call(['python ' + nextcommand], shell=True)
178 180 except Exception as e:
179 181 log.error("I cannot run the file. Does it exists?")
180 182
181 183
182 184 def basicInputs():
183 185 inputs = {}
184 186 inputs['name'] = click.prompt(
185 187 'Name of the project', default="project", type=str)
186 188 inputs['desc'] = click.prompt(
187 189 'Enter a description', default="A schain project", type=str)
188 190 inputs['multiprocess'] = click.prompt(
189 191 '''Select data type:
190 192
191 193 - Voltage (*.r): [1]
192 194 - Spectra (*.pdata): [2]
193 195 - Voltage and Spectra (*.r): [3]
194 196
195 197 -->''', type=int)
196 198 inputs['path'] = click.prompt('Data path', default=os.getcwd(
197 199 ), type=click.Path(exists=True, resolve_path=True))
198 200 inputs['startDate'] = click.prompt(
199 201 'Start date', default='1970/01/01', type=str)
200 202 inputs['endDate'] = click.prompt(
201 203 'End date', default='2018/12/31', type=str)
202 204 inputs['startHour'] = click.prompt(
203 205 'Start hour', default='00:00:00', type=str)
204 206 inputs['endHour'] = click.prompt('End hour', default='23:59:59', type=str)
205 207 inputs['figpath'] = inputs['path'] + '/figs'
206 208 return inputs
207 209
208 210
209 211 def generate():
210 212 inputs = basicInputs()
211 213
212 214 if inputs['multiprocess'] == 1:
213 215 current = templates.voltage.format(**inputs)
214 216 elif inputs['multiprocess'] == 2:
215 217 current = templates.spectra.format(**inputs)
216 218 elif inputs['multiprocess'] == 3:
217 219 current = templates.voltagespectra.format(**inputs)
218 220 scriptname = '{}_{}.py'.format(PREFIX, inputs['name'])
219 221 script = open(scriptname, 'w')
220 222 try:
221 223 script.write(current)
222 224 log.success('Script {} generated'.format(scriptname))
223 225 except Exception as e:
224 226 log.error('I cannot create the file. Do you have writing permissions?')
225 227
226 228
227 229 def test():
228 230 log.warning('testing')
229 231
230 232
231 233 def runFromXML(filename):
232 234 controller = Project()
233 235 if not controller.readXml(filename):
234 236 return
235 237 controller.start()
236 238 return
This diff has been collapsed as it changes many lines, (929 lines changed) Show them Hide them
@@ -1,1295 +1,918
1 '''
2 Updated on January , 2018, for multiprocessing purposes
3 Author: Sergio Cortez
4 Created on September , 2012
5 '''
6 from platform import python_version
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
3 #
4 # Distributed under the terms of the BSD 3-clause license.
5 """API to create signal chain projects
6
7 The API is provide through class: Project
8 """
9
10 import re
7 11 import sys
8 12 import ast
9 13 import datetime
10 14 import traceback
11 import math
12 15 import time
13 import zmq
14 from multiprocessing import Process, Queue, Event, Value, cpu_count
16 import multiprocessing
17 from multiprocessing import Process, Queue
15 18 from threading import Thread
16 from xml.etree.ElementTree import ElementTree, Element, SubElement, tostring
17 from xml.dom import minidom
18
19 from xml.etree.ElementTree import ElementTree, Element, SubElement
19 20
20 21 from schainpy.admin import Alarm, SchainWarning
21 22 from schainpy.model import *
22 23 from schainpy.utils import log
23 24
25 if 'darwin' in sys.platform and sys.version_info[0] == 3 and sys.version_info[1] > 7:
26 multiprocessing.set_start_method('fork')
24 27
25 28 DTYPES = {
26 29 'Voltage': '.r',
27 30 'Spectra': '.pdata'
28 31 }
29 32
30 33
31 34 def MPProject(project, n=cpu_count()):
32 35 '''
33 36 Project wrapper to run schain in n processes
34 37 '''
35 38
36 39 rconf = project.getReadUnitObj()
37 40 op = rconf.getOperationObj('run')
38 41 dt1 = op.getParameterValue('startDate')
39 42 dt2 = op.getParameterValue('endDate')
40 43 tm1 = op.getParameterValue('startTime')
41 44 tm2 = op.getParameterValue('endTime')
42 45 days = (dt2 - dt1).days
43 46
44 47 for day in range(days + 1):
45 48 skip = 0
46 49 cursor = 0
47 50 processes = []
48 51 dt = dt1 + datetime.timedelta(day)
49 52 dt_str = dt.strftime('%Y/%m/%d')
50 53 reader = JRODataReader()
51 54 paths, files = reader.searchFilesOffLine(path=rconf.path,
52 55 startDate=dt,
53 56 endDate=dt,
54 57 startTime=tm1,
55 58 endTime=tm2,
56 59 ext=DTYPES[rconf.datatype])
57 60 nFiles = len(files)
58 61 if nFiles == 0:
59 62 continue
60 63 skip = int(math.ceil(nFiles / n))
61 64 while nFiles > cursor * skip:
62 65 rconf.update(startDate=dt_str, endDate=dt_str, cursor=cursor,
63 66 skip=skip)
64 67 p = project.clone()
65 68 p.start()
66 69 processes.append(p)
67 70 cursor += 1
68 71
69 72 def beforeExit(exctype, value, trace):
70 73 for process in processes:
71 74 process.terminate()
72 75 process.join()
73 76 print(traceback.print_tb(trace))
74 77
75 78 sys.excepthook = beforeExit
76 79
77 80 for process in processes:
78 81 process.join()
79 82 process.terminate()
80 83
81 84 time.sleep(3)
82 85
83 86 def wait(context):
84 87
85 88 time.sleep(1)
86 89 c = zmq.Context()
87 90 receiver = c.socket(zmq.SUB)
88 91 receiver.connect('ipc:///tmp/schain_{}_pub'.format(self.id))
89 92 receiver.setsockopt(zmq.SUBSCRIBE, self.id.encode())
90 93 msg = receiver.recv_multipart()[1]
91 94 context.terminate()
92 95
93 96 class ParameterConf():
94 97
95 98 id = None
96 99 name = None
97 100 value = None
98 101 format = None
99 102
100 103 __formated_value = None
101 104
102 105 ELEMENTNAME = 'Parameter'
103 106
104 107 def __init__(self):
105 108
106 109 self.format = 'str'
107 110
108 111 def getElementName(self):
109 112
110 113 return self.ELEMENTNAME
111 114
112 115 def getValue(self):
113 116
114 117 value = self.value
115 118 format = self.format
116 119
117 120 if self.__formated_value != None:
118 121
119 122 return self.__formated_value
120 123
121 124 if format == 'obj':
122 125 return value
123 126
124 127 if format == 'str':
125 128 self.__formated_value = str(value)
126 129 return self.__formated_value
127 130
128 131 if value == '':
129 132 raise ValueError('%s: This parameter value is empty' % self.name)
130 133
131 134 if format == 'list':
132 135 strList = [s.strip() for s in value.split(',')]
133 136 self.__formated_value = strList
134 137
135 138 return self.__formated_value
136 139
137 140 if format == 'intlist':
138 141 '''
139 142 Example:
140 143 value = (0,1,2)
141 144 '''
142 145
143 146 new_value = ast.literal_eval(value)
144 147
145 148 if type(new_value) not in (tuple, list):
146 149 new_value = [int(new_value)]
147 150
148 151 self.__formated_value = new_value
149 152
150 153 return self.__formated_value
151 154
152 155 if format == 'floatlist':
153 156 '''
154 157 Example:
155 158 value = (0.5, 1.4, 2.7)
156 159 '''
157 160
158 161 new_value = ast.literal_eval(value)
159 162
160 163 if type(new_value) not in (tuple, list):
161 164 new_value = [float(new_value)]
162 165
163 166 self.__formated_value = new_value
164 167
165 168 return self.__formated_value
166 169
167 170 if format == 'date':
168 171 strList = value.split('/')
169 172 intList = [int(x) for x in strList]
170 173 date = datetime.date(intList[0], intList[1], intList[2])
171 174
172 175 self.__formated_value = date
173 176
174 177 return self.__formated_value
175 178
176 179 if format == 'time':
177 180 strList = value.split(':')
178 181 intList = [int(x) for x in strList]
179 182 time = datetime.time(intList[0], intList[1], intList[2])
180 183
181 184 self.__formated_value = time
182 185
183 186 return self.__formated_value
184 187
185 188 if format == 'pairslist':
186 189 '''
187 190 Example:
188 191 value = (0,1),(1,2)
189 192 '''
190 193
191 194 new_value = ast.literal_eval(value)
192 195
193 196 if type(new_value) not in (tuple, list):
194 197 raise ValueError('%s has to be a tuple or list of pairs' % value)
195 198
196 199 if type(new_value[0]) not in (tuple, list):
197 200 if len(new_value) != 2:
198 201 raise ValueError('%s has to be a tuple or list of pairs' % value)
199 202 new_value = [new_value]
200 203
201 204 for thisPair in new_value:
202 205 if len(thisPair) != 2:
203 206 raise ValueError('%s has to be a tuple or list of pairs' % value)
204 207
205 208 self.__formated_value = new_value
206 209
207 210 return self.__formated_value
208 211
209 212 if format == 'multilist':
210 213 '''
211 214 Example:
212 215 value = (0,1,2),(3,4,5)
213 216 '''
214 217 multiList = ast.literal_eval(value)
215 218
216 219 if type(multiList[0]) == int:
217 220 multiList = ast.literal_eval('(' + value + ')')
218 221
219 222 self.__formated_value = multiList
220 223
221 224 return self.__formated_value
222 225
223 226 if format == 'bool':
224 227 value = int(value)
225 228
226 229 if format == 'int':
227 230 value = float(value)
228 231
229 232 format_func = eval(format)
230 233
231 234 self.__formated_value = format_func(value)
232 235
233 236 return self.__formated_value
234 237
235 238 def updateId(self, new_id):
236 239
237 240 self.id = str(new_id)
238 241
239 242 def setup(self, id, name, value, format='str'):
240 243 self.id = str(id)
241 244 self.name = name
242 245 if format == 'obj':
243 246 self.value = value
244 247 else:
245 248 self.value = str(value)
246 249 self.format = str.lower(format)
247 250
248 251 self.getValue()
249 252
250 253 return 1
251 254
252 255 def update(self, name, value, format='str'):
253 256
254 257 self.name = name
255 258 self.value = str(value)
256 259 self.format = format
257 260
258 261 def makeXml(self, opElement):
259 262 if self.name not in ('queue',):
260 263 parmElement = SubElement(opElement, self.ELEMENTNAME)
261 264 parmElement.set('id', str(self.id))
262 265 parmElement.set('name', self.name)
263 266 parmElement.set('value', self.value)
264 267 parmElement.set('format', self.format)
265 268
266 269 def readXml(self, parmElement):
267 270
268 271 self.id = parmElement.get('id')
269 272 self.name = parmElement.get('name')
270 273 self.value = parmElement.get('value')
271 274 self.format = str.lower(parmElement.get('format'))
272 275
273 276 # Compatible with old signal chain version
274 277 if self.format == 'int' and self.name == 'idfigure':
275 278 self.name = 'id'
276 279
277 280 def printattr(self):
278 281
279 282 print('Parameter[%s]: name = %s, value = %s, format = %s, project_id = %s' % (self.id, self.name, self.value, self.format, self.project_id))
280 283
281 284 class OperationConf():
282 285
283 286 ELEMENTNAME = 'Operation'
284 287
285 288 def __init__(self):
286 289
287 290 self.id = '0'
288 291 self.name = None
289 292 self.priority = None
290 self.topic = None
291
292 def __getNewId(self):
293
294 return int(self.id) * 10 + len(self.parmConfObjList) + 1
293 self.parameters = {}
294 self.object = None
295 self.operations = []
295 296
296 297 def getId(self):
298
297 299 return self.id
298 300
301 def getNewId(self):
302
303 return int(self.id) * 10 + len(self.operations) + 1
304
299 305 def updateId(self, new_id):
300 306
301 307 self.id = str(new_id)
302 308
303 309 n = 1
304 for parmObj in self.parmConfObjList:
305
306 idParm = str(int(new_id) * 10 + n)
307 parmObj.updateId(idParm)
308
310 for conf in self.operations:
311 conf_id = str(int(new_id) * 10 + n)
312 conf.updateId(conf_id)
309 313 n += 1
310 314
311 def getElementName(self):
312
313 return self.ELEMENTNAME
314
315 def getParameterObjList(self):
316
317 return self.parmConfObjList
318
319 def getParameterObj(self, parameterName):
315 def getKwargs(self):
320 316
321 for parmConfObj in self.parmConfObjList:
317 params = {}
322 318
323 if parmConfObj.name != parameterName:
324 continue
319 for key, value in self.parameters.items():
320 if value not in (None, '', ' '):
321 params[key] = value
325 322
326 return parmConfObj
323 return params
327 324
328 return None
325 def update(self, **kwargs):
329 326
330 def getParameterObjfromValue(self, parameterValue):
327 for key, value in kwargs.items():
328 self.addParameter(name=key, value=value)
331 329
332 for parmConfObj in self.parmConfObjList:
330 def addParameter(self, name, value, format=None):
331 '''
332 '''
333 333
334 if parmConfObj.getValue() != parameterValue:
335 continue
334 if isinstance(value, str) and re.search(r'(\d+/\d+/\d+)', value):
335 self.parameters[name] = datetime.date(*[int(x) for x in value.split('/')])
336 elif isinstance(value, str) and re.search(r'(\d+:\d+:\d+)', value):
337 self.parameters[name] = datetime.time(*[int(x) for x in value.split(':')])
338 else:
339 try:
340 self.parameters[name] = ast.literal_eval(value)
341 except:
342 if isinstance(value, str) and ',' in value:
343 self.parameters[name] = value.split(',')
344 else:
345 self.parameters[name] = value
346
347 def getParameters(self):
348
349 params = {}
350 for key, value in self.parameters.items():
351 s = type(value).__name__
352 if s == 'date':
353 params[key] = value.strftime('%Y/%m/%d')
354 elif s == 'time':
355 params[key] = value.strftime('%H:%M:%S')
356 else:
357 params[key] = str(value)
336 358
337 return parmConfObj.getValue()
359 return params
338 360
339 return None
361 def makeXml(self, element):
340 362
341 def getParameterValue(self, parameterName):
363 xml = SubElement(element, self.ELEMENTNAME)
364 for label in self.xml_labels:
365 xml.set(label, str(getattr(self, label)))
342 366
343 parameterObj = self.getParameterObj(parameterName)
367 for key, value in self.getParameters().items():
368 xml_param = SubElement(xml, 'Parameter')
369 xml_param.set('name', key)
370 xml_param.set('value', value)
344 371
345 # if not parameterObj:
346 # return None
372 for conf in self.operations:
373 conf.makeXml(xml)
347 374
348 value = parameterObj.getValue()
375 def __str__(self):
349 376
350 return value
377 if self.ELEMENTNAME == 'Operation':
378 s = ' {}[id={}]\n'.format(self.name, self.id)
379 else:
380 s = '{}[id={}, inputId={}]\n'.format(self.name, self.id, self.inputId)
351 381
352 def getKwargs(self):
382 for key, value in self.parameters.items():
383 if self.ELEMENTNAME == 'Operation':
384 s += ' {}: {}\n'.format(key, value)
385 else:
386 s += ' {}: {}\n'.format(key, value)
353 387
354 kwargs = {}
388 for conf in self.operations:
389 s += str(conf)
355 390
356 for parmConfObj in self.parmConfObjList:
357 if self.name == 'run' and parmConfObj.name == 'datatype':
358 continue
391 return s
359 392
360 kwargs[parmConfObj.name] = parmConfObj.getValue()
393 class OperationConf(ConfBase):
361 394
362 return kwargs
395 ELEMENTNAME = 'Operation'
396 xml_labels = ['id', 'name']
363 397
364 def setup(self, id, name, priority, type, project_id, err_queue, lock):
398 def setup(self, id, name, priority, project_id, err_queue):
365 399
366 400 self.id = str(id)
367 401 self.project_id = project_id
368 402 self.name = name
369 self.type = type
370 self.priority = priority
403 self.type = 'other'
371 404 self.err_queue = err_queue
372 self.lock = lock
373 self.parmConfObjList = []
374 405
375 def removeParameters(self):
406 def readXml(self, element, project_id, err_queue):
376 407
377 for obj in self.parmConfObjList:
378 del obj
379
380 self.parmConfObjList = []
381
382 def addParameter(self, name, value, format='str'):
383
384 if value is None:
385 return None
386 id = self.__getNewId()
387
388 parmConfObj = ParameterConf()
389 if not parmConfObj.setup(id, name, value, format):
390 return None
391
392 self.parmConfObjList.append(parmConfObj)
393
394 return parmConfObj
395
396 def changeParameter(self, name, value, format='str'):
397
398 parmConfObj = self.getParameterObj(name)
399 parmConfObj.update(name, value, format)
400
401 return parmConfObj
402
403 def makeXml(self, procUnitElement):
404
405 opElement = SubElement(procUnitElement, self.ELEMENTNAME)
406 opElement.set('id', str(self.id))
407 opElement.set('name', self.name)
408 opElement.set('type', self.type)
409 opElement.set('priority', str(self.priority))
410
411 for parmConfObj in self.parmConfObjList:
412 parmConfObj.makeXml(opElement)
413
414 def readXml(self, opElement, project_id):
415
416 self.id = opElement.get('id')
417 self.name = opElement.get('name')
418 self.type = opElement.get('type')
419 self.priority = opElement.get('priority')
408 self.id = element.get('id')
409 self.name = element.get('name')
410 self.type = 'other'
420 411 self.project_id = str(project_id)
412 self.err_queue = err_queue
421 413
422 # Compatible with old signal chain version
423 # Use of 'run' method instead 'init'
424 if self.type == 'self' and self.name == 'init':
425 self.name = 'run'
426
427 self.parmConfObjList = []
428
429 parmElementList = opElement.iter(ParameterConf().getElementName())
430
431 for parmElement in parmElementList:
432 parmConfObj = ParameterConf()
433 parmConfObj.readXml(parmElement)
434
435 # Compatible with old signal chain version
436 # If an 'plot' OPERATION is found, changes name operation by the value of its type PARAMETER
437 if self.type != 'self' and self.name == 'Plot':
438 if parmConfObj.format == 'str' and parmConfObj.name == 'type':
439 self.name = parmConfObj.value
440 continue
441
442 self.parmConfObjList.append(parmConfObj)
443
444 def printattr(self):
445
446 print('%s[%s]: name = %s, type = %s, priority = %s, project_id = %s' % (self.ELEMENTNAME,
447 self.id,
448 self.name,
449 self.type,
450 self.priority,
451 self.project_id))
452
453 for parmConfObj in self.parmConfObjList:
454 parmConfObj.printattr()
414 for elm in element.iter('Parameter'):
415 self.addParameter(elm.get('name'), elm.get('value'))
455 416
456 417 def createObject(self):
457 418
458 419 className = eval(self.name)
459 420
460 if self.type == 'other':
461 opObj = className()
462 elif self.type == 'external':
421 if 'Plot' in self.name or 'Writer' in self.name or 'Send' in self.name or 'print' in self.name:
463 422 kwargs = self.getKwargs()
464 opObj = className(self.id, self.id, self.project_id, self.err_queue, self.lock, 'Operation', **kwargs)
423 opObj = className(self.id, self.id, self.project_id, self.err_queue, **kwargs)
465 424 opObj.start()
466 self.opObj = opObj
425 self.type = 'external'
426 else:
427 opObj = className()
467 428
429 self.object = opObj
468 430 return opObj
469 431
470 class ProcUnitConf():
432 class ProcUnitConf(ConfBase):
471 433
472 434 ELEMENTNAME = 'ProcUnit'
435 xml_labels = ['id', 'inputId', 'name']
473 436
474 def __init__(self):
475
476 self.id = None
477 self.datatype = None
478 self.name = None
479 self.inputId = None
480 self.opConfObjList = []
481 self.procUnitObj = None
482 self.opObjDict = {}
483
484 def __getPriority(self):
485
486 return len(self.opConfObjList) + 1
487
488 def __getNewId(self):
489
490 return int(self.id) * 10 + len(self.opConfObjList) + 1
491
492 def getElementName(self):
493
494 return self.ELEMENTNAME
495
496 def getId(self):
497
498 return self.id
499
500 def updateId(self, new_id):
501 '''
502 new_id = int(parentId) * 10 + (int(self.id) % 10)
503 new_inputId = int(parentId) * 10 + (int(self.inputId) % 10)
504
505 # If this proc unit has not inputs
506 #if self.inputId == '0':
507 #new_inputId = 0
508
509 n = 1
510 for opConfObj in self.opConfObjList:
511
512 idOp = str(int(new_id) * 10 + n)
513 opConfObj.updateId(idOp)
514
515 n += 1
516
517 self.parentId = str(parentId)
518 self.id = str(new_id)
519 #self.inputId = str(new_inputId)
520 '''
521 n = 1
522
523 def getInputId(self):
524
525 return self.inputId
526
527 def getOperationObjList(self):
528
529 return self.opConfObjList
530
531 def getOperationObj(self, name=None):
532
533 for opConfObj in self.opConfObjList:
534
535 if opConfObj.name != name:
536 continue
537
538 return opConfObj
539
540 return None
541
542 def getOpObjfromParamValue(self, value=None):
543
544 for opConfObj in self.opConfObjList:
545 if opConfObj.getParameterObjfromValue(parameterValue=value) != value:
546 continue
547 return opConfObj
548 return None
549
550 def getProcUnitObj(self):
551
552 return self.procUnitObj
553
554 def setup(self, project_id, id, name, datatype, inputId, err_queue, lock):
437 def setup(self, project_id, id, name, datatype, inputId, err_queue):
555 438 '''
556 id sera el topico a publicar
557 inputId sera el topico a subscribirse
558 439 '''
559 440
560 # Compatible with old signal chain version
561 441 if datatype == None and name == None:
562 442 raise ValueError('datatype or name should be defined')
563 443
564 #Definir una condicion para inputId cuando sea 0
565
566 444 if name == None:
567 445 if 'Proc' in datatype:
568 446 name = datatype
569 447 else:
570 448 name = '%sProc' % (datatype)
571 449
572 450 if datatype == None:
573 451 datatype = name.replace('Proc', '')
574 452
575 453 self.id = str(id)
576 454 self.project_id = project_id
577 455 self.name = name
578 456 self.datatype = datatype
579 457 self.inputId = inputId
580 458 self.err_queue = err_queue
581 self.lock = lock
582 self.opConfObjList = []
583
584 self.addOperation(name='run', optype='self')
585
586 def removeOperations(self):
459 self.operations = []
460 self.parameters = {}
587 461
588 for obj in self.opConfObjList:
589 del obj
462 def removeOperation(self, id):
590 463
591 self.opConfObjList = []
592 self.addOperation(name='run')
464 i = [1 if x.id==id else 0 for x in self.operations]
465 self.operations.pop(i.index(1))
593 466
594 def addParameter(self, **kwargs):
595 '''
596 Add parameters to 'run' operation
597 '''
598 opObj = self.opConfObjList[0]
467 def getOperation(self, id):
599 468
600 opObj.addParameter(**kwargs)
601
602 return opObj
469 for conf in self.operations:
470 if conf.id == id:
471 return conf
603 472
604 473 def addOperation(self, name, optype='self'):
605 474 '''
606 Actualizacion - > proceso comunicacion
607 En el caso de optype='self', elminar. DEfinir comuncacion IPC -> Topic
608 definir el tipoc de socket o comunicacion ipc++
609
610 475 '''
611 476
612 id = self.__getNewId()
613 priority = self.__getPriority() # Sin mucho sentido, pero puede usarse
614 opConfObj = OperationConf()
615 opConfObj.setup(id, name=name, priority=priority, type=optype, project_id=self.project_id, err_queue=self.err_queue, lock=self.lock)
616 self.opConfObjList.append(opConfObj)
617
618 return opConfObj
619
620 def makeXml(self, projectElement):
621
622 procUnitElement = SubElement(projectElement, self.ELEMENTNAME)
623 procUnitElement.set('id', str(self.id))
624 procUnitElement.set('name', self.name)
625 procUnitElement.set('datatype', self.datatype)
626 procUnitElement.set('inputId', str(self.inputId))
477 id = self.getNewId()
478 conf = OperationConf()
479 conf.setup(id, name=name, priority='0', project_id=self.project_id, err_queue=self.err_queue)
480 self.operations.append(conf)
627 481
628 for opConfObj in self.opConfObjList:
629 opConfObj.makeXml(procUnitElement)
482 return conf
630 483
631 def readXml(self, upElement, project_id):
484 def readXml(self, element, project_id, err_queue):
632 485
633 self.id = upElement.get('id')
634 self.name = upElement.get('name')
635 self.datatype = upElement.get('datatype')
636 self.inputId = upElement.get('inputId')
486 self.id = element.get('id')
487 self.name = element.get('name')
488 self.inputId = None if element.get('inputId') == 'None' else element.get('inputId')
489 self.datatype = element.get('datatype', self.name.replace(self.ELEMENTNAME.replace('Unit', ''), ''))
637 490 self.project_id = str(project_id)
491 self.err_queue = err_queue
492 self.operations = []
493 self.parameters = {}
638 494
639 if self.ELEMENTNAME == 'ReadUnit':
640 self.datatype = self.datatype.replace('Reader', '')
641
642 if self.ELEMENTNAME == 'ProcUnit':
643 self.datatype = self.datatype.replace('Proc', '')
644
645 if self.inputId == 'None':
646 self.inputId = '0'
647
648 self.opConfObjList = []
649
650 opElementList = upElement.iter(OperationConf().getElementName())
651
652 for opElement in opElementList:
653 opConfObj = OperationConf()
654 opConfObj.readXml(opElement, project_id)
655 self.opConfObjList.append(opConfObj)
656
657 def printattr(self):
658
659 print('%s[%s]: name = %s, datatype = %s, inputId = %s, project_id = %s' % (self.ELEMENTNAME,
660 self.id,
661 self.name,
662 self.datatype,
663 self.inputId,
664 self.project_id))
665
666 for opConfObj in self.opConfObjList:
667 opConfObj.printattr()
668
669 def getKwargs(self):
670
671 opObj = self.opConfObjList[0]
672 kwargs = opObj.getKwargs()
673
674 return kwargs
495 for elm in element:
496 if elm.tag == 'Parameter':
497 self.addParameter(elm.get('name'), elm.get('value'))
498 elif elm.tag == 'Operation':
499 conf = OperationConf()
500 conf.readXml(elm, project_id, err_queue)
501 self.operations.append(conf)
675 502
676 503 def createObjects(self):
677 504 '''
678 505 Instancia de unidades de procesamiento.
679 506 '''
680 507
681 508 className = eval(self.name)
682 509 #print(self.name)
683 510 kwargs = self.getKwargs()
684 #print(kwargs)
685 #print("mark_a")
686 procUnitObj = className(self.id, self.inputId, self.project_id, self.err_queue, self.lock, 'ProcUnit', **kwargs)
687 #print("mark_b")
511 procUnitObj = className()
512 procUnitObj.name = self.name
688 513 log.success('creating process...', self.name)
689 514
690 for opConfObj in self.opConfObjList:
515 for conf in self.operations:
691 516
692 if opConfObj.type == 'self' and opConfObj.name == 'run':
693 continue
694 elif opConfObj.type == 'self':
695 opObj = getattr(procUnitObj, opConfObj.name)
696 else:
697 opObj = opConfObj.createObject()
517 opObj = conf.createObject()
698 518
699 519 log.success('adding operation: {}, type:{}'.format(
700 opConfObj.name,
701 opConfObj.type), self.name)
702
703 procUnitObj.addOperation(opConfObj, opObj)
520 conf.name,
521 conf.type), self.name)
704 522
705 procUnitObj.start()
706 self.procUnitObj = procUnitObj
523 procUnitObj.addOperation(conf, opObj)
707 524
708 def close(self):
709
710 for opConfObj in self.opConfObjList:
711 if opConfObj.type == 'self':
712 continue
525 self.object = procUnitObj
713 526
714 opObj = self.procUnitObj.getOperationObj(opConfObj.id)
715 opObj.close()
716
717 self.procUnitObj.close()
527 def run(self):
528 '''
529 '''
718 530
719 return
531 return self.object.call(**self.getKwargs())
720 532
721 533
722 534 class ReadUnitConf(ProcUnitConf):
723 535
724 536 ELEMENTNAME = 'ReadUnit'
725 537
726 538 def __init__(self):
727 539
728 540 self.id = None
729 541 self.datatype = None
730 542 self.name = None
731 543 self.inputId = None
732 self.opConfObjList = []
733 self.lock = Event()
734 self.lock.set()
735 self.lock.n = Value('d', 0)
736
737 def getElementName(self):
738
739 return self.ELEMENTNAME
544 self.operations = []
545 self.parameters = {}
740 546
741 547 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
742 548 startTime='', endTime='', server=None, **kwargs):
743 549
744
745 '''
746 *****el id del proceso sera el Topico
747
748 Adicion de {topic}, si no esta presente -> error
749 kwargs deben ser trasmitidos en la instanciacion
750
751 '''
752
753 # Compatible with old signal chain version
754 550 if datatype == None and name == None:
755 551 raise ValueError('datatype or name should be defined')
756 552 if name == None:
757 553 if 'Reader' in datatype:
758 554 name = datatype
759 555 datatype = name.replace('Reader','')
760 556 else:
761 557 name = '{}Reader'.format(datatype)
762 558 if datatype == None:
763 559 if 'Reader' in name:
764 560 datatype = name.replace('Reader','')
765 561 else:
766 562 datatype = name
767 563 name = '{}Reader'.format(name)
768 564
769 565 self.id = id
770 566 self.project_id = project_id
771 567 self.name = name
772 568 self.datatype = datatype
773 if path != '':
774 self.path = os.path.abspath(path)
775 print (self.path)
776 self.startDate = startDate
777 self.endDate = endDate
778 self.startTime = startTime
779 self.endTime = endTime
780 self.server = server
781 569 self.err_queue = err_queue
782 self.addRunOperation(**kwargs)
783 570
784 def update(self, **kwargs):
785
786 if 'datatype' in kwargs:
787 datatype = kwargs.pop('datatype')
788 if 'Reader' in datatype:
789 self.name = datatype
790 else:
791 self.name = '%sReader' % (datatype)
792 self.datatype = self.name.replace('Reader', '')
793
794 attrs = ('path', 'startDate', 'endDate',
795 'startTime', 'endTime')
796
797 for attr in attrs:
798 if attr in kwargs:
799 setattr(self, attr, kwargs.pop(attr))
800
801 self.updateRunOperation(**kwargs)
802
803 def removeOperations(self):
571 self.addParameter(name='path', value=path)
572 self.addParameter(name='startDate', value=startDate)
573 self.addParameter(name='endDate', value=endDate)
574 self.addParameter(name='startTime', value=startTime)
575 self.addParameter(name='endTime', value=endTime)
804 576
805 for obj in self.opConfObjList:
806 del obj
807
808 self.opConfObjList = []
809
810 def addRunOperation(self, **kwargs):
811
812 opObj = self.addOperation(name='run', optype='self')
813
814 if self.server is None:
815 opObj.addParameter(
816 name='datatype', value=self.datatype, format='str')
817 opObj.addParameter(name='path', value=self.path, format='str')
818 opObj.addParameter(
819 name='startDate', value=self.startDate, format='date')
820 opObj.addParameter(
821 name='endDate', value=self.endDate, format='date')
822 opObj.addParameter(
823 name='startTime', value=self.startTime, format='time')
824 opObj.addParameter(
825 name='endTime', value=self.endTime, format='time')
826
827 for key, value in list(kwargs.items()):
828 opObj.addParameter(name=key, value=value,
829 format=type(value).__name__)
830 else:
831 opObj.addParameter(name='server', value=self.server, format='str')
832
833 return opObj
834
835 def updateRunOperation(self, **kwargs):
836
837 opObj = self.getOperationObj(name='run')
838 opObj.removeParameters()
839
840 opObj.addParameter(name='datatype', value=self.datatype, format='str')
841 opObj.addParameter(name='path', value=self.path, format='str')
842 opObj.addParameter(
843 name='startDate', value=self.startDate, format='date')
844 opObj.addParameter(name='endDate', value=self.endDate, format='date')
845 opObj.addParameter(
846 name='startTime', value=self.startTime, format='time')
847 opObj.addParameter(name='endTime', value=self.endTime, format='time')
848
849 for key, value in list(kwargs.items()):
850 opObj.addParameter(name=key, value=value,
851 format=type(value).__name__)
852
853 return opObj
854
855 def readXml(self, upElement, project_id):
856
857 self.id = upElement.get('id')
858 self.name = upElement.get('name')
859 self.datatype = upElement.get('datatype')
860 self.project_id = str(project_id) #yong
861
862 if self.ELEMENTNAME == 'ReadUnit':
863 self.datatype = self.datatype.replace('Reader', '')
864
865 self.opConfObjList = []
866
867 opElementList = upElement.iter(OperationConf().getElementName())
868
869 for opElement in opElementList:
870 opConfObj = OperationConf()
871 opConfObj.readXml(opElement, project_id)
872 self.opConfObjList.append(opConfObj)
873
874 if opConfObj.name == 'run':
875 self.path = opConfObj.getParameterValue('path')
876 self.startDate = opConfObj.getParameterValue('startDate')
877 self.endDate = opConfObj.getParameterValue('endDate')
878 self.startTime = opConfObj.getParameterValue('startTime')
879 self.endTime = opConfObj.getParameterValue('endTime')
577 for key, value in kwargs.items():
578 self.addParameter(name=key, value=value)
880 579
881 580
882 581 class Project(Process):
582 """API to create signal chain projects"""
883 583
884 584 ELEMENTNAME = 'Project'
885 585
886 def __init__(self):
586 def __init__(self, name=''):
887 587
888 588 Process.__init__(self)
889 self.id = None
589 self.id = '1'
590 if name:
591 self.name = '{} ({})'.format(Process.__name__, name)
890 592 self.filename = None
891 593 self.description = None
892 594 self.email = None
893 self.alarm = None
894 self.procUnitConfObjDict = {}
895 self.err_queue = Queue()
595 self.alarm = []
596 self.configurations = {}
597 # self.err_queue = Queue()
598 self.err_queue = None
599 self.started = False
896 600
897 def __getNewId(self):
601 def getNewId(self):
898 602
899 idList = list(self.procUnitConfObjDict.keys())
603 idList = list(self.configurations.keys())
900 604 id = int(self.id) * 10
901 605
902 606 while True:
903 607 id += 1
904 608
905 609 if str(id) in idList:
906 610 continue
907 611
908 612 break
909 613
910 614 return str(id)
911 615
912 def getElementName(self):
913
914 return self.ELEMENTNAME
915
916 def getId(self):
917
918 return self.id
919
920 616 def updateId(self, new_id):
921 617
922 618 self.id = str(new_id)
923 619
924 keyList = list(self.procUnitConfObjDict.keys())
620 keyList = list(self.configurations.keys())
925 621 keyList.sort()
926 622
927 623 n = 1
928 newProcUnitConfObjDict = {}
624 new_confs = {}
929 625
930 626 for procKey in keyList:
931 627
932 procUnitConfObj = self.procUnitConfObjDict[procKey]
628 conf = self.configurations[procKey]
933 629 idProcUnit = str(int(self.id) * 10 + n)
934 procUnitConfObj.updateId(idProcUnit)
935 newProcUnitConfObjDict[idProcUnit] = procUnitConfObj
630 conf.updateId(idProcUnit)
631 new_confs[idProcUnit] = conf
936 632 n += 1
937 633
938 self.procUnitConfObjDict = newProcUnitConfObjDict
634 self.configurations = new_confs
939 635
940 636 def setup(self, id=1, name='', description='', email=None, alarm=[]):
941 637
942 print(' ')
943 print('*' * 60)
944 print('* Starting SIGNAL CHAIN PROCESSING (Multiprocessing) v%s *' % schainpy.__version__)
945 print('*' * 60)
946 print("* Python " + python_version() + " *")
947 print('*' * 19)
948 print(' ')
949 638 self.id = str(id)
950 639 self.description = description
951 640 self.email = email
952 641 self.alarm = alarm
953 642 if name:
954 643 self.name = '{} ({})'.format(Process.__name__, name)
955 644
956 645 def update(self, **kwargs):
957 646
958 for key, value in list(kwargs.items()):
647 for key, value in kwargs.items():
959 648 setattr(self, key, value)
960 649
961 650 def clone(self):
962 651
963 652 p = Project()
964 p.procUnitConfObjDict = self.procUnitConfObjDict
653 p.id = self.id
654 p.name = self.name
655 p.description = self.description
656 p.configurations = self.configurations.copy()
657
965 658 return p
966 659
967 660 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
968 661
969 662 '''
970 Actualizacion:
971 Se agrego un nuevo argumento: topic -relativo a la forma de comunicar los procesos simultaneos
972
973 * El id del proceso sera el topico al que se deben subscribir los procUnits para recibir la informacion(data)
974
975 663 '''
976 664
977 665 if id is None:
978 idReadUnit = self.__getNewId()
666 idReadUnit = self.getNewId()
979 667 else:
980 668 idReadUnit = str(id)
981 669
982 readUnitConfObj = ReadUnitConf()
983 readUnitConfObj.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
984 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
670 conf = ReadUnitConf()
671 conf.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
672 self.configurations[conf.id] = conf
985 673
986 return readUnitConfObj
674 return conf
987 675
988 def addProcUnit(self, inputId='0', datatype=None, name=None):
676 def addProcUnit(self, id=None, inputId='0', datatype=None, name=None):
989 677
990 678 '''
991 Actualizacion:
992 Se agrego dos nuevos argumentos: topic_read (lee data de otro procUnit) y topic_write(escribe o envia data a otro procUnit)
993 Deberia reemplazar a "inputId"
994
995 ** A fin de mantener el inputID, este sera la representaacion del topicoal que deben subscribirse. El ID propio de la intancia
996 (proceso) sera el topico de la publicacion, todo sera asignado de manera dinamica.
997
998 679 '''
999 680
1000 idProcUnit = self.__getNewId()
1001 procUnitConfObj = ProcUnitConf()
1002 input_proc = self.procUnitConfObjDict[inputId]
1003 procUnitConfObj.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue, input_proc.lock)
1004 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
1005
1006 return procUnitConfObj
1007
1008 def removeProcUnit(self, id):
681 if id is None:
682 idProcUnit = self.getNewId()
683 else:
684 idProcUnit = id
1009 685
1010 if id in list(self.procUnitConfObjDict.keys()):
1011 self.procUnitConfObjDict.pop(id)
686 conf = ProcUnitConf()
687 conf.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue)
688 self.configurations[conf.id] = conf
1012 689
1013 def getReadUnitId(self):
690 return conf
1014 691
1015 readUnitConfObj = self.getReadUnitObj()
692 def removeProcUnit(self, id):
1016 693
1017 return readUnitConfObj.id
694 if id in self.configurations:
695 self.configurations.pop(id)
1018 696
1019 def getReadUnitObj(self):
697 def getReadUnit(self):
1020 698
1021 for obj in list(self.procUnitConfObjDict.values()):
1022 if obj.getElementName() == 'ReadUnit':
699 for obj in list(self.configurations.values()):
700 if obj.ELEMENTNAME == 'ReadUnit':
1023 701 return obj
1024 702
1025 703 return None
1026 704
1027 def getProcUnitObj(self, id=None, name=None):
1028
1029 if id != None:
1030 return self.procUnitConfObjDict[id]
705 def getProcUnit(self, id):
1031 706
1032 if name != None:
1033 return self.getProcUnitObjByName(name)
1034
1035 return None
707 return self.configurations[id]
1036 708
1037 def getProcUnitObjByName(self, name):
709 def getUnits(self):
1038 710
1039 for obj in list(self.procUnitConfObjDict.values()):
1040 if obj.name == name:
1041 return obj
711 keys = list(self.configurations)
712 keys.sort()
1042 713
1043 return None
714 for key in keys:
715 yield self.configurations[key]
1044 716
1045 def procUnitItems(self):
717 def updateUnit(self, id, **kwargs):
1046 718
1047 return list(self.procUnitConfObjDict.items())
719 conf = self.configurations[id].update(**kwargs)
1048 720
1049 721 def makeXml(self):
1050 722
1051 projectElement = Element('Project')
1052 projectElement.set('id', str(self.id))
1053 projectElement.set('name', self.name)
1054 projectElement.set('description', self.description)
723 xml = Element('Project')
724 xml.set('id', str(self.id))
725 xml.set('name', self.name)
726 xml.set('description', self.description)
1055 727
1056 for procUnitConfObj in list(self.procUnitConfObjDict.values()):
1057 procUnitConfObj.makeXml(projectElement)
728 for conf in self.configurations.values():
729 conf.makeXml(xml)
1058 730
1059 self.projectElement = projectElement
731 self.xml = xml
1060 732
1061 733 def writeXml(self, filename=None):
1062 734
1063 735 if filename == None:
1064 736 if self.filename:
1065 737 filename = self.filename
1066 738 else:
1067 739 filename = 'schain.xml'
1068 740
1069 741 if not filename:
1070 742 print('filename has not been defined. Use setFilename(filename) for do it.')
1071 743 return 0
1072 744
1073 745 abs_file = os.path.abspath(filename)
1074 746
1075 747 if not os.access(os.path.dirname(abs_file), os.W_OK):
1076 748 print('No write permission on %s' % os.path.dirname(abs_file))
1077 749 return 0
1078 750
1079 751 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
1080 752 print('File %s already exists and it could not be overwriten' % abs_file)
1081 753 return 0
1082 754
1083 755 self.makeXml()
1084 756
1085 ElementTree(self.projectElement).write(abs_file, method='xml')
757 ElementTree(self.xml).write(abs_file, method='xml')
1086 758
1087 759 self.filename = abs_file
1088 760
1089 761 return 1
1090 762
1091 def readXml(self, filename=None):
1092
1093 if not filename:
1094 print('filename is not defined')
1095 return 0
763 def readXml(self, filename):
1096 764
1097 765 abs_file = os.path.abspath(filename)
1098 766
1099 if not os.path.isfile(abs_file):
1100 print('%s file does not exist' % abs_file)
1101 return 0
1102
1103 self.projectElement = None
1104 self.procUnitConfObjDict = {}
767 self.configurations = {}
1105 768
1106 769 try:
1107 self.projectElement = ElementTree().parse(abs_file)
770 self.xml = ElementTree().parse(abs_file)
1108 771 except:
1109 print('Error reading %s, verify file format' % filename)
772 log.error('Error reading %s, verify file format' % filename)
1110 773 return 0
1111 774
1112 self.project = self.projectElement.tag
1113
1114 self.id = self.projectElement.get('id')
1115 self.name = self.projectElement.get('name')
1116 self.description = self.projectElement.get('description')
1117
1118 readUnitElementList = self.projectElement.iter(
1119 ReadUnitConf().getElementName())
1120
1121 for readUnitElement in readUnitElementList:
1122 readUnitConfObj = ReadUnitConf()
1123 readUnitConfObj.readXml(readUnitElement, self.id)
1124 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
1125
1126 procUnitElementList = self.projectElement.iter(
1127 ProcUnitConf().getElementName())
1128
1129 for procUnitElement in procUnitElementList:
1130 procUnitConfObj = ProcUnitConf()
1131 procUnitConfObj.readXml(procUnitElement, self.id)
1132 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
775 self.id = self.xml.get('id')
776 self.name = self.xml.get('name')
777 self.description = self.xml.get('description')
778
779 for element in self.xml:
780 if element.tag == 'ReadUnit':
781 conf = ReadUnitConf()
782 conf.readXml(element, self.id, self.err_queue)
783 self.configurations[conf.id] = conf
784 elif element.tag == 'ProcUnit':
785 conf = ProcUnitConf()
786 input_proc = self.configurations[element.get('inputId')]
787 conf.readXml(element, self.id, self.err_queue)
788 self.configurations[conf.id] = conf
1133 789
1134 790 self.filename = abs_file
1135 791
1136 792 return 1
1137 793
1138 794 def __str__(self):
1139 795
1140 print('Project: name = %s, description = %s, id = %s' % (
1141 self.name,
1142 self.description,
1143 self.id))
796 text = '\nProject[id=%s, name=%s, description=%s]\n\n' % (
797 self.id,
798 self.name,
799 self.description,
800 )
801
802 for conf in self.configurations.values():
803 text += '{}'.format(conf)
1144 804
1145 for procUnitConfObj in self.procUnitConfObjDict.values():
1146 print(procUnitConfObj)
805 return text
1147 806
1148 807 def createObjects(self):
1149 808
1150
1151 keys = list(self.procUnitConfObjDict.keys())
809 keys = list(self.configurations.keys())
1152 810 keys.sort()
1153 811 for key in keys:
1154 self.procUnitConfObjDict[key].createObjects()
812 conf = self.configurations[key]
813 conf.createObjects()
814 if conf.inputId is not None:
815 conf.object.setInput(self.configurations[conf.inputId].object)
1155 816
1156 817 def monitor(self):
1157 818
1158 t = Thread(target=self.__monitor, args=(self.err_queue, self.ctx))
819 t = Thread(target=self._monitor, args=(self.err_queue, self.ctx))
1159 820 t.start()
1160 821
1161 def __monitor(self, queue, ctx):
822 def _monitor(self, queue, ctx):
1162 823
1163 824 import socket
1164 825
1165 826 procs = 0
1166 827 err_msg = ''
1167 828
1168 829 while True:
1169 830 msg = queue.get()
1170 831 if '#_start_#' in msg:
1171 832 procs += 1
1172 833 elif '#_end_#' in msg:
1173 834 procs -=1
1174 835 else:
1175 836 err_msg = msg
1176 837
1177 838 if procs == 0 or 'Traceback' in err_msg:
1178 839 break
1179 840 time.sleep(0.1)
1180 841
1181 842 if '|' in err_msg:
1182 843 name, err = err_msg.split('|')
1183 844 if 'SchainWarning' in err:
1184 845 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), name)
1185 846 elif 'SchainError' in err:
1186 847 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
1187 848 else:
1188 849 log.error(err, name)
1189 850 else:
1190 851 name, err = self.name, err_msg
1191 852
1192 time.sleep(2)
1193
1194 for conf in self.procUnitConfObjDict.values():
1195 for confop in conf.opConfObjList:
1196 if confop.type == 'external':
1197 confop.opObj.terminate()
1198 conf.procUnitObj.terminate()
853 time.sleep(1)
1199 854
1200 855 ctx.term()
1201 856
1202 857 message = ''.join(err)
1203 858
1204 859 if err_msg:
1205 860 subject = 'SChain v%s: Error running %s\n' % (
1206 861 schainpy.__version__, self.name)
1207 862
1208 863 subtitle = 'Hostname: %s\n' % socket.gethostbyname(
1209 864 socket.gethostname())
1210 865 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
1211 866 subtitle += 'Configuration file: %s\n' % self.filename
1212 867 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
1213 868
1214 readUnitConfObj = self.getReadUnitObj()
869 readUnitConfObj = self.getReadUnit()
1215 870 if readUnitConfObj:
1216 871 subtitle += '\nInput parameters:\n'
1217 subtitle += '[Data path = %s]\n' % readUnitConfObj.path
1218 subtitle += '[Data type = %s]\n' % readUnitConfObj.datatype
1219 subtitle += '[Start date = %s]\n' % readUnitConfObj.startDate
1220 subtitle += '[End date = %s]\n' % readUnitConfObj.endDate
1221 subtitle += '[Start time = %s]\n' % readUnitConfObj.startTime
1222 subtitle += '[End time = %s]\n' % readUnitConfObj.endTime
872 subtitle += '[Data path = %s]\n' % readUnitConfObj.parameters['path']
873 subtitle += '[Start date = %s]\n' % readUnitConfObj.parameters['startDate']
874 subtitle += '[End date = %s]\n' % readUnitConfObj.parameters['endDate']
875 subtitle += '[Start time = %s]\n' % readUnitConfObj.parameters['startTime']
876 subtitle += '[End time = %s]\n' % readUnitConfObj.parameters['endTime']
1223 877
1224 878 a = Alarm(
1225 879 modes=self.alarm,
1226 880 email=self.email,
1227 881 message=message,
1228 882 subject=subject,
1229 883 subtitle=subtitle,
1230 884 filename=self.filename
1231 885 )
1232 886
1233 887 a.start()
1234 888
1235 def isPaused(self):
1236 return 0
1237
1238 def isStopped(self):
1239 return 0
1240
1241 def runController(self):
1242 '''
1243 returns 0 when this process has been stopped, 1 otherwise
1244 '''
1245
1246 if self.isPaused():
1247 print('Process suspended')
1248
1249 while True:
1250 time.sleep(0.1)
1251
1252 if not self.isPaused():
1253 break
1254
1255 if self.isStopped():
1256 break
1257
1258 print('Process reinitialized')
1259
1260 if self.isStopped():
1261 print('Process stopped')
1262 return 0
1263
1264 return 1
1265
1266 889 def setFilename(self, filename):
1267 890
1268 891 self.filename = filename
1269 892
1270 def setProxy(self):
893 def runProcs(self):
1271 894
1272 if not os.path.exists('/tmp/schain'):
1273 os.mkdir('/tmp/schain')
895 err = False
896 n = len(self.configurations)
1274 897
1275 self.ctx = zmq.Context()
1276 xpub = self.ctx.socket(zmq.XPUB)
1277 xpub.bind('ipc:///tmp/schain/{}_pub'.format(self.id))
1278 xsub = self.ctx.socket(zmq.XSUB)
1279 xsub.bind('ipc:///tmp/schain/{}_sub'.format(self.id))
1280 self.monitor()
1281 try:
1282 zmq.proxy(xpub, xsub)
1283 except zmq.ContextTerminated:
1284 xpub.close()
1285 xsub.close()
898 while not err:
899 for conf in self.getUnits():
900 ok = conf.run()
901 if ok == 'Error':
902 n -= 1
903 continue
904 elif not ok:
905 break
906 if n == 0:
907 err = True
1286 908
1287 909 def run(self):
1288 910
1289 log.success('Starting {}: {}'.format(self.name, self.id), tag='')
911 log.success('\nStarting Project {} [id={}]'.format(self.name, self.id), tag='')
912 self.started = True
1290 913 self.start_time = time.time()
1291 914 self.createObjects()
1292 self.setProxy()
1293 log.success('{} Done (Time: {}s)'.format(
915 self.runProcs()
916 log.success('{} Done (Time: {:4.2f}s)'.format(
1294 917 self.name,
1295 918 time.time()-self.start_time), '')
@@ -1,1 +0,0
1 from viewcontroller import * No newline at end of file
@@ -1,39 +1,325
1 1 #!/usr/bin/env python
2 2 import os
3 3 import sys
4 import ast
5
6 from schainpy.controller import Project
7 from schainpy.cli import cli
4 8 from schainpy.utils import log
5 9
6 10 try:
7 from PyQt4 import QtCore, QtGui
8 from PyQt4.QtGui import QApplication
11 import kivy
12 from kivy.app import App
13 from kivy.uix.label import Label
14 from kivy.uix.boxlayout import BoxLayout
15 from kivy.uix.gridlayout import GridLayout
16 from kivy.uix.textinput import TextInput
17 from kivy.uix.button import Button
18 from kivy.uix.dropdown import DropDown
19 from kivy.uix.togglebutton import ToggleButton
20 from kivy.uix.popup import Popup
21 from kivy.uix.filechooser import FileChooserListView
9 22 except:
10 23 log.error(
11 'You should install PyQt4 module in order to run the GUI. See the README.')
24 'You should install kivy module in order to run the GUI.')
12 25 sys.exit()
13 26
14 from schainpy.gui.viewcontroller.initwindow import InitWindow
15 from schainpy.gui.viewcontroller.basicwindow import BasicWindow
16 from schainpy.gui.viewcontroller.workspace import Workspace
17 27
28 DEFAULTS = {
29 'path': os.path.expanduser('~'),
30 'startDate': '2018/01/01',
31 'endDate': '2020/01/01',
32 'startTime': '00:00:00',
33 'endTime': '23:59:59',
34 'online': '1',
35 'delay': '30',
36 'walk': '1',
37 'show': '1',
38 'zmin': '10',
39 'zmax': '40',
40 }
41
42
43 class MainLayout(BoxLayout):
44 def __init__(self, **kwargs):
45 super(MainLayout, self).__init__(**kwargs)
46
47 self.workspace = os.path.join(os.path.expanduser('~'), 'workspace/scripts')
48 self.current_unit_id = None
49 self._units = []
50 self.project = Project()
51 self.project.setup(id='1', name='test', description='')
52
53 self.sidebar_left = BoxLayout(orientation='vertical', size_hint_x=0.4, spacing=5)
54 self.body = BoxLayout(orientation='vertical', spacing=5)
55 self.sidebar_right = BoxLayout(orientation='vertical', size_hint_x=0.6, spacing=5)
56
57 bt_prj = Button(text='Project')
58 bt_prj.bind(on_press=self.show_project)
59 self.sidebar_left.add_widget(bt_prj)
60
61 bt_add_unit = Button(text='Add Unit')
62 bt_add_unit.bind(on_press=self.select_unit)
63 self.sidebar_left.add_widget(bt_add_unit)
64
65 bt_add_operation = Button(text='Add Operation')
66 bt_add_operation.bind(on_press=self.select_operation)
67 self.sidebar_left.add_widget(bt_add_operation)
68
69 bt_import = Button(text='Import')
70 bt_import.bind(on_press=self.load)
71 self.sidebar_left.add_widget(bt_import)
72
73 bt_export = Button(text='Export')
74 bt_export.bind(on_press=self.export)
75 self.sidebar_left.add_widget(bt_export)
76
77 bt_run = Button(text='Run')
78 bt_run.bind(on_press=self.run)
79 self.sidebar_left.add_widget(bt_run)
80
81 bt_stop = Button(text='Stop')
82 bt_stop.bind(on_press = self.stop)
83 self.sidebar_left.add_widget(bt_stop)
84
85 bt_exit = Button(text = 'Exit', height = 40, size_hint_y = None, background_color=(1, 0, 0, 1))
86 bt_exit.bind(on_press=App.get_running_app().stop)
87 self.sidebar_left.add_widget(bt_exit)
88
89 self.add_widget(self.sidebar_left)
90 self.add_widget(self.body)
91 self.add_widget(self.sidebar_right)
92
93 def update_body(self):
94
95 self._units = []
96 self.body.clear_widgets()
97 self.sidebar_right.clear_widgets()
98
99 for unit in self.project.getUnits():
100 box = GridLayout(cols=3)
101 bt = ToggleButton(text=unit.name, group='units')
102 bt._obj = unit
103 bt.bind(on_press=self.show_parameters)
104 box.add_widget(bt)
105 self._units.append(bt)
106
107 for operation in unit.operations:
108 bt_op = Button(text = operation.name, background_color=(1, 0.5, 0, 1))
109 bt_op._id = unit.id
110 bt_op._obj = operation
111 bt_op.bind(on_press=self.show_parameters)
112 box.add_widget(bt_op)
113
114 self.body.add_widget(box)
115
116 print(self.project)
117
118 def show_parameters(self, instance):
119
120 obj = instance._obj
121 self.current_unit_id = obj.id
122 self.sidebar_right.clear_widgets()
123
124 if obj and obj.parameters:
125 self._params = {}
126
127 for key, value in obj.getParameters().items():
128 self.sidebar_right.add_widget(Label(text=key))
129 text = TextInput(text=value, multiline=False)
130 self._params[key] = text
131 self.sidebar_right.add_widget(text)
132
133 bt_save = Button(text = 'Save', height = 40, size_hint_y = None, background_color=(0, 1, 0, 1))
134 bt_save._obj = obj
135 if hasattr(instance, '_id'):
136 bt_save._id = instance._id
137 self.current_unit_id = None
138 bt_save.bind(on_press=self.save_parameters)
139 self.sidebar_right.add_widget(bt_save)
140
141 bt_delete = Button(text = 'Delete', height = 40, size_hint_y = None, background_color=(1, 0, 0, 1))
142 bt_delete._obj = obj
143 if hasattr(instance, '_id'):
144 bt_delete._id = instance._id
145 self.current_unit_id = obj.id
146 bt_delete.bind(on_press=self.delete_object)
147 self.sidebar_right.add_widget(bt_delete)
148
149 def save_parameters(self, instance):
150
151 obj = instance._obj
152 params = {}
153 for key in self._params:
154 if self._params[key]:
155 params[key] = self._params[key].text
156
157 if hasattr(instance, '_id'):
158 unit = self.project.getProcUnit(instance._id)
159 op = unit.getOperation(obj.id)
160 op.update(**params)
161 else:
162 unit = self.project.getProcUnit(obj.id)
163 unit.update(**params)
164
165 def delete_object(self, instance):
166
167 obj = instance._obj
168
169 if hasattr(instance, '_id'):
170 unit = self.project.getProcUnit(instance._id)
171 unit.removeOperation(obj.id)
172 else:
173 self.project.removeProcUnit(obj.id)
174
175 self.project.updateId(self.project.id)
176 self.update_body()
177
178 def show_project(self, instance):
179
180 self.sidebar_right.clear_widgets()
181 self._params = {}
182 for label in ['Id', 'Name', 'Description']:
183 self.sidebar_right.add_widget(Label(text=label))
184 text = TextInput(text=getattr(self.project, label.lower()), multiline=False)
185 self._params[label] = text
186 self.sidebar_right.add_widget(text)
187
188 self.sidebar_right.add_widget(Label(text='Workspace'))
189 text = TextInput(text=getattr(self, 'workspace'), multiline=False)
190 self._params['Workspace'] = text
191 self.sidebar_right.add_widget(text)
192
193 bt_save = Button(text = 'Save', height = 40, size_hint_y = None, background_color=(0, 1, 0, 1))
194 bt_save.bind(on_press = self.save_project_parameters)
195 self.sidebar_right.add_widget(bt_save)
196
197 def save_project_parameters(self, instance):
198
199 for label in ['Id', 'Name', 'Description']:
200 setattr(self.project, label.lower(), self._params[label].text)
201
202 setattr(self, 'workspace', self._params['Workspace'].text)
203
204 def select_unit(self, instance):
205
206 self.sidebar_right.clear_widgets()
207 bt_main = Button(text = 'Select Unit', height = 40, size_hint_y = None)
208 dropdown = DropDown()
209
210 for unit in cli.getProcs():
211
212 btn = Button(text = unit, size_hint_y = None, height = 40)
213 btn.bind(on_release = lambda btn: dropdown.select(btn.text))
214 dropdown.add_widget(btn)
215
216 bt_main.bind(on_release = dropdown.open)
217 dropdown.bind(on_select = lambda instance, x: setattr(bt_main, 'text', x))
218
219 bt_add = Button(text = 'Add', height = 40, size_hint_y = None, background_color=(0, 1, 0, 1))
220 bt_add.bind(on_press = lambda instance: self.add_unit(bt_main.text))
221
222 self.sidebar_right.add_widget(bt_main)
223 self.sidebar_right.add_widget(bt_add)
224
225 def add_unit(self, s):
226
227 if s:
228 if 'Reader' in s:
229 unit = self.project.addReadUnit(name=s)
230 else:
231 *_, last = self.project.getUnits()
232 unit = self.project.addProcUnit(name=s, inputId=last.id)
233
234 keys = cli.getArgs(unit.name)
235 values = [DEFAULTS[key] if key in DEFAULTS else '' for key in keys]
236 unit.update(**dict(zip(keys, values)))
237 self.update_body()
238
239 def select_operation(self, instance):
240
241 self.sidebar_right.clear_widgets()
242 btns = [bt.state == 'down' for bt in self._units]
243 if True in btns:
244 bt_main = Button(text = 'Select Operation', height = 40, size_hint_y = None)
245 dropdown = DropDown()
246
247 for unit in cli.getOperations():
248
249 btn = Button(text = unit, size_hint_y = None, height = 40)
250 btn.bind(on_release = lambda btn: dropdown.select(btn.text))
251 dropdown.add_widget(btn)
252
253 bt_main.bind(on_release = dropdown.open)
254 dropdown.bind(on_select = lambda instance, x: setattr(bt_main, 'text', x))
255
256 bt_add = Button(text = 'Add', height = 40, size_hint_y = None, background_color=(0, 1, 0, 1))
257 bt_add.bind(on_press = lambda instance: self.add_operation(bt_main.text))
258
259 self.sidebar_right.add_widget(bt_main)
260 self.sidebar_right.add_widget(bt_add)
261 else:
262 self.sidebar_right.add_widget(Label(text='Select Unit'))
263
264 def add_operation(self, s):
265
266 if s:
267 unit = self.project.getProcUnit(self.current_unit_id)
268 op = unit.addOperation(name=s)
269 keys = cli.getArgs(op.name)
270 values = [DEFAULTS[key] if key in DEFAULTS else '' for key in keys]
271 op.update(**dict(zip(keys, values)))
272 self.update_body()
273
274 def run(self, instance):
275
276 if self.project and self.project.is_alive():
277 self.sidebar_right.clear_widgets()
278 self.sidebar_right.add_widget(Label(text='Project running'))
279 else:
280 if self.project.exitcode is None:
281 self.project.start()
282 else:
283 self.project = self.project.clone()
284 self.project.start()
285
286 def stop(self, instance):
287
288 if self.project and self.project.is_alive():
289 self.project.kill()
290 log.error('Project Stopped by user', 'GUI')
291 else:
292 self.sidebar_right.clear_widgets()
293 self.sidebar_right.add_widget(Label(text='Project not running'))
294
295 def load(self, instance):
296
297 self.sidebar_right.clear_widgets()
298 textinput = FileChooserListView(
299 path=self.workspace, size_hint=(1, 1), dirselect=False, filters=['*.xml'])
18 300
19 def main():
301 self.sidebar_right.add_widget(textinput)
302 bt_open = Button(text = 'Open', height = 40, size_hint_y = None, background_color=(0, 1, 0, 1))
303 bt_open.textinput = textinput
304 bt_open.bind(on_press = self.load_file)
305 self.sidebar_right.add_widget(bt_open)
306
307 def load_file(self, instance):
20 308
21 app = QtGui.QApplication(sys.argv)
309 self.project.readXml(instance.textinput.selection[0])
310 self.update_body()
22 311
23 Welcome = InitWindow()
312 def export(self, instance):
24 313
25 if not Welcome.exec_():
26 sys.exit(-1)
314 filename = os.path.join(self.workspace, '{}.xml'.format(self.project.name))
315 self.project.writeXml(filename)
316 log.success('File created: {}'.format(filename), 'GUI')
27 317
28 WorkPathspace = Workspace()
29 if not WorkPathspace.exec_():
30 sys.exit(-1)
31 318
32 MainGUI = BasicWindow()
33 MainGUI.setWorkSpaceGUI(WorkPathspace.dirComBox.currentText())
34 MainGUI.show()
35 sys.exit(app.exec_())
319 class SignalChainApp(App):
320 def build(self):
321 return MainLayout(spacing=10)
36 322
37 323
38 324 if __name__ == "__main__":
39 main()
325 SignalChainApp().run() No newline at end of file
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from schainpy/gui/figures/__init__.py to schainpy/scripts/restore.spst
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
This diff has been collapsed as it changes many lines, (1765 lines changed) Show them Hide them
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now