##// 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
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
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
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
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
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
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
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
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 # Byte-compiled / optimized / DLL files
1 # Byte-compiled / optimized / DLL files
2 __pycache__/
2 __pycache__/
3 *.py[cod]
3 *.py[cod]
4 *$py.class
4 *$py.class
5
5
6 # C extensions
6 # C extensions
7 *.so
7 *.so
8
8
9 # Distribution / packaging
9 # Distribution / packaging
10 .Python
10 .Python
11 env/
11 env/
12 build/
12 build/
13 develop-eggs/
13 develop-eggs/
14 dist/
14 dist/
15 downloads/
15 downloads/
16 eggs/
16 eggs/
17 .eggs/
17 .eggs/
18 lib/
18 lib/
19 lib64/
19 lib64/
20 parts/
20 parts/
21 sdist/
21 sdist/
22 var/
22 var/
23 wheels/
23 wheels/
24 *.egg-info/
24 *.egg-info/
25 .installed.cfg
25 .installed.cfg
26 *.egg
26 *.egg
27
27
28 # PyInstaller
28 # PyInstaller
29 # Usually these files are written by a python script from a template
29 # Usually these files are written by a python script from a template
30 # before PyInstaller builds the exe, so as to inject date/other infos into it.
30 # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 *.manifest
31 *.manifest
32 *.spec
32 *.spec
33
33
34 # Installer logs
34 # Installer logs
35 pip-log.txt
35 pip-log.txt
36 pip-delete-this-directory.txt
36 pip-delete-this-directory.txt
37
37
38 # Unit test / coverage reports
38 # Unit test / coverage reports
39 htmlcov/
39 htmlcov/
40 .tox/
40 .tox/
41 .coverage
41 .coverage
42 .coverage.*
42 .coverage.*
43 .cache
43 .cache
44 nosetests.xml
44 nosetests.xml
45 coverage.xml
45 coverage.xml
46 *,cover
46 *,cover
47 .hypothesis/
47 .hypothesis/
48
48
49 # Translations
49 # Translations
50 *.mo
50 *.mo
51 *.pot
51 *.pot
52
52
53 # Django stuff:
53 # Django stuff:
54 *.log
54 *.log
55 local_settings.py
55 local_settings.py
56
56
57 # Flask stuff:
57 # Flask stuff:
58 instance/
58 instance/
59 .webassets-cache
59 .webassets-cache
60
60
61 # Scrapy stuff:
61 # Scrapy stuff:
62 .scrapy
62 .scrapy
63
63
64 # Sphinx documentation
64 # Sphinx documentation
65 docs/_build/
65 docs/_build/
66
66
67 # PyBuilder
67 # PyBuilder
68 target/
68 target/
69
69
70 # Jupyter Notebook
70 # Jupyter Notebook
71 .ipynb_checkpoints
71 .ipynb_checkpoints
72
72
73 # pyenv
73 # pyenv
74 .python-version
74 .python-version
75
75
76 # celery beat schedule file
76 # celery beat schedule file
77 celerybeat-schedule
77 celerybeat-schedule
78
78
79 # SageMath parsed files
79 # SageMath parsed files
80 *.sage.py
80 *.sage.py
81
81
82 # dotenv
82 # dotenv
83 .env
83 .env
84
84
85 # virtualenv
85 # virtualenv
86 .venv
86 .venv
87 venv/
87 venv/
88 ENV/
88 ENV/
89
89
90 # Spyder project settings
90 # Spyder project settings
91 .spyderproject
91 .spyderproject
92 .spyproject
92 .spyproject
93
93
94 # Rope project settings
94 # Rope project settings
95 .ropeproject
95 .ropeproject
96
96
97 # mkdocs documentation
97 # mkdocs documentation
98 /site
98 /site
99
99
100 # eclipse
100 # eclipse
101 .project
101 .project
102 .pydevproject
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
3 ## 3.0.0
4 * Python 3.x compatible
4
5 * New architecture with multiprocessing and IPC communication
5 * Python 3.x & 2.X compatible
6 * Add @MPDecorator for multiprocessing Units and Operations
6 * New architecture with multiprocessing support
7 * Add @MPDecorator for multiprocessing Operations (Plots, Writers and Publishers)
7 * Added new type of operation `external` for non-locking operations
8 * Added new type of operation `external` for non-locking operations
8 * New plotting architecture with buffering/throttle capabilities to speed up plots
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 * Added support for Madrigal formats (reading/writing).
17 * Added support for Madrigal formats (reading/writing).
12 * Added support for reading BLTR parameters (*.sswma).
18 * Added support for reading BLTR parameters (*.sswma).
13 * Added support for reading Julia format (*.dat).
19 * Added support for reading Julia format (*.dat).
14 * Added high order function `MPProject` for multiprocessing scripts.
20 * Added high order function `MPProject` for multiprocessing scripts.
15 * Added two new Processing Units `PublishData` and `ReceiverData` for receiving and sending dataOut through multiple ways (tcp, ipc, inproc).
21 * Added two new Processing Units `PublishData` and `ReceiverData` for receiving and sending dataOut through multiple ways (tcp, ipc, inproc).
16 * Added a new graphics Processing Unit `PlotterReceiver`. It is decoupled from normal processing sequence with support for data generated by multiprocessing scripts.
22 * Added a new graphics Processing Unit `PlotterReceiver`. It is decoupled from normal processing sequence with support for data generated by multiprocessing scripts.
17 * Added support for sending realtime graphic to web server.
23 * Added support for sending realtime graphic to web server.
18 * GUI command `schain` is now `schainGUI`.
24 * GUI command `schain` is now `schainGUI`.
19 * Added a CLI tool named `schain`.
25 * Added a CLI tool named `schain`.
20 * Scripts templates can be now generated with `schain generate`.
26 * 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.
27 * 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.
28 * `schain xml` to run xml scripts.
23 * Added suggestions when parameters are poorly written.
29 * Added suggestions when parameters are poorly written.
24 * `Controller.start()` now runs in a different process than the process calling it.
30 * `Controller.start()` now runs in a different process than the process calling it.
25 * Added `schainpy.utils.log` for log standarization.
31 * Added `schainpy.utils.log` for log standarization.
26 * Running script on online mode no longer ignores date and hour. Issue #1109.
32 * Running script on online mode no longer ignores date and hour. Issue #1109.
27 * Added support for receving voltage data directly from JARS (tcp, ipc).
33 * Added support for receving voltage data directly from JARS (tcp, ipc).
28 * Updated README for MAC OS GUI installation.
34 * Updated README for MAC OS GUI installation.
29 * Setup now installs numpy.
35 * Setup now installs numpy.
30
36
31 ### 2.2.6
37 ## 2.2.6
38
32 * Graphics generated by the GUI are now the same as generated by scripts. Issue #1074.
39 * Graphics generated by the GUI are now the same as generated by scripts. Issue #1074.
33 * Added support for C extensions.
40 * Added support for C extensions.
34 * Function `hildebrand_sehkon` optimized with a C wrapper.
41 * Function `hildebrand_sehkon` optimized with a C wrapper.
35 * Numpy version updated.
42 * Numpy version updated.
36 * Migration to GIT.
43 * Migration to GIT.
37
44
38 ### 2.2.5:
45 ## 2.2.5
46
39 * splitProfiles and combineProfiles modules were added to VoltageProc and Signal Chain GUI.
47 * splitProfiles and combineProfiles modules were added to VoltageProc and Signal Chain GUI.
40 * nProfiles of USRP data (hdf5) is the number of profiles thera are in one second.
48 * nProfiles of USRP data (hdf5) is the number of profiles thera are in one second.
41 * jroPlotter works directly with data objects instead of dictionaries
49 * jroPlotter works directly with data objects instead of dictionaries
42 * script "schain" was added to Signal Chain installer
50 * script "schain" was added to Signal Chain installer
43
51
44 ### 2.2.4.1:
52 ## 2.2.4.1
53
45 * jroIO_usrp.py is update to read Sandra's data
54 * jroIO_usrp.py is update to read Sandra's data
46 * decimation in Spectra and RTI plots is always enabled.
55 * decimation in Spectra and RTI plots is always enabled.
47 * time* window option added to GUI
56 * time* window option added to GUI
48
57
49 ### 2.2.4:
58 ## 2.2.4
59
50 * jroproc_spectra_lags.py added to schainpy
60 * jroproc_spectra_lags.py added to schainpy
51 * Bug fixed in schainGUI: ProcUnit was created with the same id in some cases.
61 * Bug fixed in schainGUI: ProcUnit was created with the same id in some cases.
52 * Bug fixed in jroHeaderIO: Header size validation.
62 * Bug fixed in jroHeaderIO: Header size validation.
53
63
54 ### 2.2.3.1:
64 ## 2.2.3.1
65
55 * Filtering block by time has been added.
66 * Filtering block by time has been added.
56 * Bug fixed plotting RTI, CoherenceMap and others using xmin and xmax parameters. The first day worked
67 * Bug fixed plotting RTI, CoherenceMap and others using xmin and xmax parameters. The first day worked
57 properly but the next days did not.
68 properly but the next days did not.
58
69
59 ### 2.2.3:
70 ## 2.2.3
71
60 * Bug fixed in GUI: Error getting(reading) Code value
72 * Bug fixed in GUI: Error getting(reading) Code value
61 * Bug fixed in GUI: Flip option always needs channelList field
73 * Bug fixed in GUI: Flip option always needs channelList field
62 * Bug fixed in jrodata: when one branch modified a value in "dataOut" (example: dataOut.code) this value
74 * Bug fixed in jrodata: when one branch modified a value in "dataOut" (example: dataOut.code) this value
63 was modified for every branch (because this was a reference). It was modified in data.copy()
75 was modified for every branch (because this was a reference). It was modified in data.copy()
64 * Bug fixed in jroproc_voltage.profileSelector(): rangeList replaces to profileRangeList.
76 * Bug fixed in jroproc_voltage.profileSelector(): rangeList replaces to profileRangeList.
65
77
66 ### 2.2.2:
78 ## 2.2.2
79
67 * VoltageProc: ProfileSelector, Reshape, Decoder with nTxs!=1 and getblock=True was tested
80 * VoltageProc: ProfileSelector, Reshape, Decoder with nTxs!=1 and getblock=True was tested
68 * Rawdata and testRawdata.py added to Signal Chain project
81 * Rawdata and testRawdata.py added to Signal Chain project
69
82
70 ### 2.2.1:
83 ## 2.2.1
84
71 * Bugs fixed in GUI
85 * Bugs fixed in GUI
72 * Views were improved in GUI
86 * Views were improved in GUI
73 * Support to MST* ISR experiments
87 * Support to MST* ISR experiments
74 * Bug fixed getting noise using hyldebrant. (minimum number of points > 20%)
88 * Bug fixed getting noise using hyldebrant. (minimum number of points > 20%)
75 * handleError added to jroplotter.py
89 * handleError added to jroplotter.py
76
90
77 ### 2.2.0:
91 ## 2.2.0
92
78 * GUI: use of external plotter
93 * GUI: use of external plotter
79 * Compatible with matplotlib 1.5.0
94 * Compatible with matplotlib 1.5.0
80
95
81 ### 2.1.5:
96 ## 2.1.5
97
82 * serializer module added to Signal Chain
98 * serializer module added to Signal Chain
83 * jroplotter.py added to Signal Chain
99 * jroplotter.py added to Signal Chain
84
100
85 ### 2.1.4.2:
101 ## 2.1.4.2
102
86 * A new Plotter Class was added
103 * A new Plotter Class was added
87 * Project.start() does not accept filename as a parameter anymore
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 * Send notifications when an error different to ValueError is detected
108 * Send notifications when an error different to ValueError is detected
91
109
92 ### 2.1.4:
110 ## 2.1.4
111
93 * Sending error notifications to signal chain administrator
112 * Sending error notifications to signal chain administrator
94 * Login to email server added
113 * Login to email server added
95
114
96 ### 2.1.3.3:
115 ## 2.1.3.3
116
97 * Colored Button Icons were added to GUI
117 * Colored Button Icons were added to GUI
98
118
99 ### 2.1.3.2:
119 ## 2.1.3.2
120
100 * GUI: user interaction enhanced
121 * GUI: user interaction enhanced
101 * controller_api.py: Safe access to ControllerThead
122 * controller_api.py: Safe access to ControllerThead
102
123
103 ### 2.1.3.1:
124 ## 2.1.3.1
125
104 * GUI: every icon were resized
126 * GUI: every icon were resized
105 * jroproc_voltage.py: Print a message when "Read from code" option is selected and the code is not defined inside data file
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 * jroplot_heispectra.py: SpectraHeisScope was not showing the right channels
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),
132 * jroproc_voltage.py: Bug fixed selecting profiles (self.nProfiles took a wrong value), Bug fixed selecting heights by block (selecting profiles instead heights)
110 Bug fixed selecting heights by block (selecting profiles instead heights)
111 * jroproc_voltage.py: New feature added: decoding data by block using FFT.
133 * jroproc_voltage.py: New feature added: decoding data by block using FFT.
112 * jroIO_heispectra.py: Bug fixed in FitsReader. Using local Fits instance instead schainpy.mode.data.jrodata.Fits.
134 * jroIO_heispectra.py: Bug fixed in FitsReader. Using local Fits instance instead schainpy.mode.data.jrodata.Fits.
113 * jroIO_heispectra.py: Channel index list does not exist.
135 * jroIO_heispectra.py: Channel index list does not exist.
114
136
115 ### 2.1.2:
137 ## 2.1.2
116 * jroutils_ftp.py: Bug fixed, Any error sending file stopped the Server Thread
138
117 Server thread opens and closes remote server each time file list is sent
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 * jroplot_spectra.py: Noise path was not being created when noise data is saved.
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 # Signal Chain
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
8
9 - GCC (gcc or gfortran)
10 - Python.h (python-dev or python-devel)
11 - Python-TK (python-tk)
12 - HDF5 libraries (libhdf5-dev)
6
13
7 ## Installation
14 ## Installation
8
15
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.
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.
10
19
11 ### Linux based system
20 ```bash
21 pip install schainpy
12 ```
22 ```
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
23
18 ```
24 ### From source
19
25
20 ### MAC Os
26 First, ensure that you have the above-listed dependencies installed, then clone
21 ```
27 the repository and install as normal python package:
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 ```
28
28
29 **It is recommended to install schain in a virtual environment**
29 ```bash
30 ```
30 git clone https://github.com/JRO-Peru/schainpy.git
31 $ virtualenv /path/to/virtual
31 cd schain
32 $ source /path/to/virtual/bin/activate
32 git checkout `branch-name` (optional)
33 (virtual) $ cd schain
33 sudo pip install ./
34 (virtual) $ pip install ./
35 (virtual) $ bash link_PyQt4.sh
36 ```
34 ```
37
35
38 ### Docker
36 ### Using Docker
39
37
40 Download Dockerfile from the repository, and create a docker image
38 Download Dockerfile from the repository, and create a docker image:
41
39
40 ```bash
41 docker build -t schain .
42 ```
42 ```
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
61 from schainpy.controller import Project
62
63 controller = Project()
64 controller.setup(id = '100',
65 name='test',
66 description='Basic experiment')
67
43
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:
68
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
69 ```
50 ```
70
51
71 Adding read unit and operations
52 ## CLI (command line interface)
72
53
73 ```python
54 Signal Chain provides the following commands:
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
55
83 proc_unit = controller.addProcUnit(datatype='Spectra',
56 - schainGUI: Open the GUI
84 inputId=read_unit.getId())
57 - schain: Signal chain command line
85
58
86 op = proc_unit.addOperation(name='selectChannels')
59 ## Example
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')
94
95 ```
96
97 Plotting data & start project
98
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')
103
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')
107
108 controller.start()
109
110 ```
111
112 Full script
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 ```python
64 ```python
116 #!/usr/bin/python
65 #!/usr/bin/python
117
66
118 from schainpy.controller import Project
67 from schainpy.controller import Project
119
68
120 controller = Project()
69 prj = Project()
121 controller.setup(id = '100',
70
122 name='test',
71 read_unit = prj.addReadUnit(
123 description='Basic experiment')
72 datatype='Spectra',
124 read_unit = controller.addReadUnit(datatype='Spectra',
125 path='/path/to/pdata/',
73 path='/path/to/pdata/',
126 startDate='2014/01/31',
74 startDate='2014/01/31',
127 endDate='2014/03/31',
75 endDate='2014/03/31',
128 startTime='00:00:00',
76 startTime='00:00:00',
129 endTime='23:59:59',
77 endTime='23:59:59',
130 online=0,
78 online=0,
131 walk=0)
79 walk=0
80 )
132
81
133 proc_unit = controller.addProcUnit(datatype='Spectra',
82 proc_unit = prj.addProcUnit(
134 inputId=read_unit.getId())
83 datatype='Spectra',
84 inputId=read_unit.getId()
85 )
135
86
136 op = proc_unit.addOperation(name='selectChannels')
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 op = proc_unit.addOperation(name='selectHeights')
90 op = proc_unit.addOperation(name='selectHeights')
140 op.addParameter(name='minHei', value='80', format='float')
91 op.addParameter(name='minHei', value='80')
141 op.addParameter(name='maxHei', value='200', format='float')
92 op.addParameter(name='maxHei', value='200')
142
93
143 op = proc_unit.addOperation(name='removeDC')
94 op = proc_unit.addOperation(name='removeDC')
144
95
145 op = proc_unit.addOperation(name='SpectraPlot', optype='other')
96 op = proc_unit.addOperation(name='SpectraPlot')
146 op.addParameter(name='id', value='6', format='int')
147 op.addParameter(name='wintitle', value='Spectra', format='str')
97 op.addParameter(name='wintitle', value='Spectra', format='str')
148
98
149 op = procUnitConfObj1.addOperation(name='RTIPlot', optype='other')
99 op = proc_unit.addOperation(name='RTIPlot')
150 op.addParameter(name='id', value='2', format='int')
151 op.addParameter(name='wintitle', value='RTI', format='str')
100 op.addParameter(name='wintitle', value='RTI', format='str')
152
101
153 controller.start()
102 prj.start()
154
103
155 ```
104 ```
@@ -1,7 +1,8
1 '''
1 """Signal chain python package"""
2 Created on Jul 3, 2018
3
2
4 @author $Author$
3 try:
5 @version $Id$
4 from schainpy.controller import Project
6 '''
5 except:
7 __version__ = '3.0'
6 pass
7
8 __version__ = '3.0.0b6'
@@ -1,236 +1,238
1 import click
1 import click
2 import schainpy
3 import subprocess
2 import subprocess
4 import os
3 import os
5 import sys
4 import sys
6 import glob
5 import glob
7 save_stdout = sys.stdout
6 import schainpy
8 sys.stdout = open('/dev/null', 'w')
9 from multiprocessing import cpu_count
10 from schainpy.controller import Project
7 from schainpy.controller import Project
11 from schainpy.model import Operation, ProcessingUnit
8 from schainpy.model import Operation, ProcessingUnit
12 from schainpy.utils import log
9 from schainpy.utils import log
13 from importlib import import_module
10 from importlib import import_module
14 from pydoc import locate
11 from pydoc import locate
15 from fuzzywuzzy import process
12 from fuzzywuzzy import process
16 from schainpy.cli import templates
13 from schainpy.cli import templates
17 import inspect
14 import inspect
18 try:
15 try:
19 from queue import Queue
16 from queue import Queue
20 except:
17 except:
21 from Queue import Queue
18 from Queue import Queue
22 sys.stdout = save_stdout
23
19
24
20
25 def getProcs():
21 def getProcs():
26 modules = dir(schainpy.model)
22 modules = dir(schainpy.model)
27 procs = check_module(modules, 'processing')
23 procs = check_module(modules, 'processing')
28 try:
24 try:
29 procs.remove('ProcessingUnit')
25 procs.remove('ProcessingUnit')
30 except Exception as e:
26 except Exception as e:
31 pass
27 pass
32 return procs
28 return procs
33
29
34 def getOperations():
30 def getOperations():
35 module = dir(schainpy.model)
31 module = dir(schainpy.model)
36 noProcs = [x for x in module if not x.endswith('Proc')]
32 noProcs = [x for x in module if not x.endswith('Proc')]
37 operations = check_module(noProcs, 'operation')
33 operations = check_module(noProcs, 'operation')
38 try:
34 try:
39 operations.remove('Operation')
35 operations.remove('Operation')
40 operations.remove('Figure')
36 operations.remove('Figure')
41 operations.remove('Plot')
37 operations.remove('Plot')
42 except Exception as e:
38 except Exception as e:
43 pass
39 pass
44 return operations
40 return operations
45
41
46 def getArgs(op):
42 def getArgs(op):
47 module = locate('schainpy.model.{}'.format(op))
43 module = locate('schainpy.model.{}'.format(op))
44 try:
45 obj = module(1, 2, 3, Queue())
46 except:
47 obj = module()
48
48
49 if hasattr(module, '__attrs__'):
49 if hasattr(obj, '__attrs__'):
50 args = module.__attrs__
50 args = obj.__attrs__
51 else:
52 if hasattr(obj, 'myrun'):
53 args = inspect.getfullargspec(obj.myrun).args
51 else:
54 else:
52 args = inspect.getargspec(module.run).args
55 args = inspect.getfullargspec(obj.run).args
56
53 try:
57 try:
54 args.remove('self')
58 args.remove('self')
55 except Exception as e:
59 except Exception as e:
56 pass
60 pass
57 try:
61 try:
58 args.remove('dataOut')
62 args.remove('dataOut')
59 except Exception as e:
63 except Exception as e:
60 pass
64 pass
61 return args
65 return args
62
66
63 def getDoc(obj):
67 def getDoc(obj):
64 module = locate('schainpy.model.{}'.format(obj))
68 module = locate('schainpy.model.{}'.format(obj))
65 try:
69 try:
66 obj = module(1,2,3,Queue(),5,6)
70 obj = module(1, 2, 3, Queue())
67 except:
71 except:
68 obj = module()
72 obj = module()
69 return obj.__doc__
73 return obj.__doc__
70
74
71 def getAll():
75 def getAll():
72 modules = getOperations()
76 modules = getOperations()
73 modules.extend(getProcs())
77 modules.extend(getProcs())
74 return modules
78 return modules
75
79
76
80
77 def print_version(ctx, param, value):
81 def print_version(ctx, param, value):
78 if not value or ctx.resilient_parsing:
82 if not value or ctx.resilient_parsing:
79 return
83 return
80 click.echo(schainpy.__version__)
84 click.echo(schainpy.__version__)
81 ctx.exit()
85 ctx.exit()
82
86
83
87
84 PREFIX = 'experiment'
88 PREFIX = 'experiment'
85
89
86 @click.command()
90 @click.command()
87 @click.option('--version', '-v', is_flag=True, callback=print_version, help='SChain version', type=str)
91 @click.option('--version', '-v', is_flag=True, callback=print_version, help='SChain version', type=str)
88 @click.argument('command', default='run', required=True)
92 @click.argument('command', default='run', required=True)
89 @click.argument('nextcommand', default=None, required=False, type=str)
93 @click.argument('nextcommand', default=None, required=False, type=str)
90 def main(command, nextcommand, version):
94 def main(command, nextcommand, version):
91 """COMMAND LINE INTERFACE FOR SIGNAL CHAIN - JICAMARCA RADIO OBSERVATORY V3.0\n
95 """COMMAND LINE INTERFACE FOR SIGNAL CHAIN - JICAMARCA RADIO OBSERVATORY V3.0\n
92 Available commands.\n
96 Available commands:\n
93 xml: runs a schain XML generated file\n
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 generate: generates a template schain script\n
99 generate: generates a template schain script\n
96 list: return a list of available procs and operations\n
100 list: return a list of available procs and operations\n
97 search: return avilable operations, procs or arguments of the given
101 search: return avilable operations, procs or arguments of the given
98 operation/proc\n"""
102 operation/proc\n"""
99 if command == 'xml':
103 if command == 'xml':
100 runFromXML(nextcommand)
104 runFromXML(nextcommand)
101 elif command == 'generate':
105 elif command == 'generate':
102 generate()
106 generate()
103 elif command == 'test':
107 elif command == 'test':
104 test()
108 test()
105 elif command == 'run':
109 elif command == 'run':
106 runschain(nextcommand)
110 runschain(nextcommand)
107 elif command == 'search':
111 elif command == 'search':
108 search(nextcommand)
112 search(nextcommand)
109 elif command == 'list':
113 elif command == 'list':
110 cmdlist(nextcommand)
114 cmdlist(nextcommand)
111 else:
115 else:
112 log.error('Command {} is not defined'.format(command))
116 log.error('Command {} is not defined'.format(command))
113
117
114
118
115 def check_module(possible, instance):
119 def check_module(possible, instance):
116 def check(x):
120 def check(x):
117 try:
121 try:
118 instancia = locate('schainpy.model.{}'.format(x))
122 instancia = locate('schainpy.model.{}'.format(x))
119 ret = instancia.proc_type == instance
123 ret = instancia.proc_type == instance
120 return ret
124 return ret
121 except Exception as e:
125 except Exception as e:
122 return False
126 return False
123 clean = clean_modules(possible)
127 clean = clean_modules(possible)
124 return [x for x in clean if check(x)]
128 return [x for x in clean if check(x)]
125
129
126
130
127 def clean_modules(module):
131 def clean_modules(module):
128 noEndsUnder = [x for x in module if not x.endswith('__')]
132 noEndsUnder = [x for x in module if not x.endswith('__')]
129 noStartUnder = [x for x in noEndsUnder if not x.startswith('__')]
133 noStartUnder = [x for x in noEndsUnder if not x.startswith('__')]
130 noFullUpper = [x for x in noStartUnder if not x.isupper()]
134 noFullUpper = [x for x in noStartUnder if not x.isupper()]
131 return noFullUpper
135 return noFullUpper
132
136
133 def cmdlist(nextcommand):
137 def cmdlist(nextcommand):
134 if nextcommand is None:
138 if nextcommand is None:
135 log.error('Missing argument, available arguments: procs, operations', '')
139 log.error('Missing argument, available arguments: procs, operations', '')
136 elif nextcommand == 'procs':
140 elif nextcommand == 'procs':
137 procs = getProcs()
141 procs = getProcs()
138 log.success(
142 log.success(
139 'Current ProcessingUnits are:\n {}'.format('\n '.join(procs)), '')
143 'Current ProcessingUnits are:\n {}'.format('\n '.join(procs)), '')
140 elif nextcommand == 'operations':
144 elif nextcommand == 'operations':
141 operations = getOperations()
145 operations = getOperations()
142 log.success('Current Operations are:\n {}'.format(
146 log.success('Current Operations are:\n {}'.format(
143 '\n '.join(operations)), '')
147 '\n '.join(operations)), '')
144 else:
148 else:
145 log.error('Wrong argument', '')
149 log.error('Wrong argument', '')
146
150
147 def search(nextcommand):
151 def search(nextcommand):
148 if nextcommand is None:
152 if nextcommand is None:
149 log.error('There is no Operation/ProcessingUnit to search', '')
153 log.error('There is no Operation/ProcessingUnit to search', '')
150 else:
154 else:
151 try:
155 try:
152 args = getArgs(nextcommand)
156 args = getArgs(nextcommand)
153 doc = getDoc(nextcommand)
157 doc = getDoc(nextcommand)
154 if len(args) == 0:
158 log.success('{}\n{}\n\nparameters:\n {}'.format(
155 log.success('\n{} has no arguments'.format(nextcommand), '')
159 nextcommand, doc, ', '.join(args)), ''
156 else:
160 )
157 log.success('{}\n{}\n\narguments:\n {}'.format(
158 nextcommand, doc, ', '.join(args)), '')
159 except Exception as e:
161 except Exception as e:
160 log.error('Module `{}` does not exists'.format(nextcommand), '')
162 log.error('Module `{}` does not exists'.format(nextcommand), '')
161 allModules = getAll()
163 allModules = getAll()
162 similar = [t[0] for t in process.extract(nextcommand, allModules, limit=12) if t[1]>80]
164 similar = [t[0] for t in process.extract(nextcommand, allModules, limit=12) if t[1]>80]
163 log.success('Possible modules are: {}'.format(', '.join(similar)), '')
165 log.success('Possible modules are: {}'.format(', '.join(similar)), '')
164
166
165 def runschain(nextcommand):
167 def runschain(nextcommand):
166 if nextcommand is None:
168 if nextcommand is None:
167 currentfiles = glob.glob('./{}_*.py'.format(PREFIX))
169 currentfiles = glob.glob('./{}_*.py'.format(PREFIX))
168 numberfiles = len(currentfiles)
170 numberfiles = len(currentfiles)
169 if numberfiles > 1:
171 if numberfiles > 1:
170 log.error('There is more than one file to run')
172 log.error('There is more than one file to run')
171 elif numberfiles == 1:
173 elif numberfiles == 1:
172 subprocess.call(['python ' + currentfiles[0]], shell=True)
174 subprocess.call(['python ' + currentfiles[0]], shell=True)
173 else:
175 else:
174 log.error('There is no file to run')
176 log.error('There is no file to run')
175 else:
177 else:
176 try:
178 try:
177 subprocess.call(['python ' + nextcommand], shell=True)
179 subprocess.call(['python ' + nextcommand], shell=True)
178 except Exception as e:
180 except Exception as e:
179 log.error("I cannot run the file. Does it exists?")
181 log.error("I cannot run the file. Does it exists?")
180
182
181
183
182 def basicInputs():
184 def basicInputs():
183 inputs = {}
185 inputs = {}
184 inputs['name'] = click.prompt(
186 inputs['name'] = click.prompt(
185 'Name of the project', default="project", type=str)
187 'Name of the project', default="project", type=str)
186 inputs['desc'] = click.prompt(
188 inputs['desc'] = click.prompt(
187 'Enter a description', default="A schain project", type=str)
189 'Enter a description', default="A schain project", type=str)
188 inputs['multiprocess'] = click.prompt(
190 inputs['multiprocess'] = click.prompt(
189 '''Select data type:
191 '''Select data type:
190
192
191 - Voltage (*.r): [1]
193 - Voltage (*.r): [1]
192 - Spectra (*.pdata): [2]
194 - Spectra (*.pdata): [2]
193 - Voltage and Spectra (*.r): [3]
195 - Voltage and Spectra (*.r): [3]
194
196
195 -->''', type=int)
197 -->''', type=int)
196 inputs['path'] = click.prompt('Data path', default=os.getcwd(
198 inputs['path'] = click.prompt('Data path', default=os.getcwd(
197 ), type=click.Path(exists=True, resolve_path=True))
199 ), type=click.Path(exists=True, resolve_path=True))
198 inputs['startDate'] = click.prompt(
200 inputs['startDate'] = click.prompt(
199 'Start date', default='1970/01/01', type=str)
201 'Start date', default='1970/01/01', type=str)
200 inputs['endDate'] = click.prompt(
202 inputs['endDate'] = click.prompt(
201 'End date', default='2018/12/31', type=str)
203 'End date', default='2018/12/31', type=str)
202 inputs['startHour'] = click.prompt(
204 inputs['startHour'] = click.prompt(
203 'Start hour', default='00:00:00', type=str)
205 'Start hour', default='00:00:00', type=str)
204 inputs['endHour'] = click.prompt('End hour', default='23:59:59', type=str)
206 inputs['endHour'] = click.prompt('End hour', default='23:59:59', type=str)
205 inputs['figpath'] = inputs['path'] + '/figs'
207 inputs['figpath'] = inputs['path'] + '/figs'
206 return inputs
208 return inputs
207
209
208
210
209 def generate():
211 def generate():
210 inputs = basicInputs()
212 inputs = basicInputs()
211
213
212 if inputs['multiprocess'] == 1:
214 if inputs['multiprocess'] == 1:
213 current = templates.voltage.format(**inputs)
215 current = templates.voltage.format(**inputs)
214 elif inputs['multiprocess'] == 2:
216 elif inputs['multiprocess'] == 2:
215 current = templates.spectra.format(**inputs)
217 current = templates.spectra.format(**inputs)
216 elif inputs['multiprocess'] == 3:
218 elif inputs['multiprocess'] == 3:
217 current = templates.voltagespectra.format(**inputs)
219 current = templates.voltagespectra.format(**inputs)
218 scriptname = '{}_{}.py'.format(PREFIX, inputs['name'])
220 scriptname = '{}_{}.py'.format(PREFIX, inputs['name'])
219 script = open(scriptname, 'w')
221 script = open(scriptname, 'w')
220 try:
222 try:
221 script.write(current)
223 script.write(current)
222 log.success('Script {} generated'.format(scriptname))
224 log.success('Script {} generated'.format(scriptname))
223 except Exception as e:
225 except Exception as e:
224 log.error('I cannot create the file. Do you have writing permissions?')
226 log.error('I cannot create the file. Do you have writing permissions?')
225
227
226
228
227 def test():
229 def test():
228 log.warning('testing')
230 log.warning('testing')
229
231
230
232
231 def runFromXML(filename):
233 def runFromXML(filename):
232 controller = Project()
234 controller = Project()
233 if not controller.readXml(filename):
235 if not controller.readXml(filename):
234 return
236 return
235 controller.start()
237 controller.start()
236 return
238 return
This diff has been collapsed as it changes many lines, (921 lines changed) Show them Hide them
@@ -1,1295 +1,918
1 '''
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 Updated on January , 2018, for multiprocessing purposes
2 # All rights reserved.
3 Author: Sergio Cortez
3 #
4 Created on September , 2012
4 # Distributed under the terms of the BSD 3-clause license.
5 '''
5 """API to create signal chain projects
6 from platform import python_version
6
7 The API is provide through class: Project
8 """
9
10 import re
7 import sys
11 import sys
8 import ast
12 import ast
9 import datetime
13 import datetime
10 import traceback
14 import traceback
11 import math
12 import time
15 import time
13 import zmq
16 import multiprocessing
14 from multiprocessing import Process, Queue, Event, Value, cpu_count
17 from multiprocessing import Process, Queue
15 from threading import Thread
18 from threading import Thread
16 from xml.etree.ElementTree import ElementTree, Element, SubElement, tostring
19 from xml.etree.ElementTree import ElementTree, Element, SubElement
17 from xml.dom import minidom
18
19
20
20 from schainpy.admin import Alarm, SchainWarning
21 from schainpy.admin import Alarm, SchainWarning
21 from schainpy.model import *
22 from schainpy.model import *
22 from schainpy.utils import log
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 DTYPES = {
28 DTYPES = {
26 'Voltage': '.r',
29 'Voltage': '.r',
27 'Spectra': '.pdata'
30 'Spectra': '.pdata'
28 }
31 }
29
32
30
33
31 def MPProject(project, n=cpu_count()):
34 def MPProject(project, n=cpu_count()):
32 '''
35 '''
33 Project wrapper to run schain in n processes
36 Project wrapper to run schain in n processes
34 '''
37 '''
35
38
36 rconf = project.getReadUnitObj()
39 rconf = project.getReadUnitObj()
37 op = rconf.getOperationObj('run')
40 op = rconf.getOperationObj('run')
38 dt1 = op.getParameterValue('startDate')
41 dt1 = op.getParameterValue('startDate')
39 dt2 = op.getParameterValue('endDate')
42 dt2 = op.getParameterValue('endDate')
40 tm1 = op.getParameterValue('startTime')
43 tm1 = op.getParameterValue('startTime')
41 tm2 = op.getParameterValue('endTime')
44 tm2 = op.getParameterValue('endTime')
42 days = (dt2 - dt1).days
45 days = (dt2 - dt1).days
43
46
44 for day in range(days + 1):
47 for day in range(days + 1):
45 skip = 0
48 skip = 0
46 cursor = 0
49 cursor = 0
47 processes = []
50 processes = []
48 dt = dt1 + datetime.timedelta(day)
51 dt = dt1 + datetime.timedelta(day)
49 dt_str = dt.strftime('%Y/%m/%d')
52 dt_str = dt.strftime('%Y/%m/%d')
50 reader = JRODataReader()
53 reader = JRODataReader()
51 paths, files = reader.searchFilesOffLine(path=rconf.path,
54 paths, files = reader.searchFilesOffLine(path=rconf.path,
52 startDate=dt,
55 startDate=dt,
53 endDate=dt,
56 endDate=dt,
54 startTime=tm1,
57 startTime=tm1,
55 endTime=tm2,
58 endTime=tm2,
56 ext=DTYPES[rconf.datatype])
59 ext=DTYPES[rconf.datatype])
57 nFiles = len(files)
60 nFiles = len(files)
58 if nFiles == 0:
61 if nFiles == 0:
59 continue
62 continue
60 skip = int(math.ceil(nFiles / n))
63 skip = int(math.ceil(nFiles / n))
61 while nFiles > cursor * skip:
64 while nFiles > cursor * skip:
62 rconf.update(startDate=dt_str, endDate=dt_str, cursor=cursor,
65 rconf.update(startDate=dt_str, endDate=dt_str, cursor=cursor,
63 skip=skip)
66 skip=skip)
64 p = project.clone()
67 p = project.clone()
65 p.start()
68 p.start()
66 processes.append(p)
69 processes.append(p)
67 cursor += 1
70 cursor += 1
68
71
69 def beforeExit(exctype, value, trace):
72 def beforeExit(exctype, value, trace):
70 for process in processes:
73 for process in processes:
71 process.terminate()
74 process.terminate()
72 process.join()
75 process.join()
73 print(traceback.print_tb(trace))
76 print(traceback.print_tb(trace))
74
77
75 sys.excepthook = beforeExit
78 sys.excepthook = beforeExit
76
79
77 for process in processes:
80 for process in processes:
78 process.join()
81 process.join()
79 process.terminate()
82 process.terminate()
80
83
81 time.sleep(3)
84 time.sleep(3)
82
85
83 def wait(context):
86 def wait(context):
84
87
85 time.sleep(1)
88 time.sleep(1)
86 c = zmq.Context()
89 c = zmq.Context()
87 receiver = c.socket(zmq.SUB)
90 receiver = c.socket(zmq.SUB)
88 receiver.connect('ipc:///tmp/schain_{}_pub'.format(self.id))
91 receiver.connect('ipc:///tmp/schain_{}_pub'.format(self.id))
89 receiver.setsockopt(zmq.SUBSCRIBE, self.id.encode())
92 receiver.setsockopt(zmq.SUBSCRIBE, self.id.encode())
90 msg = receiver.recv_multipart()[1]
93 msg = receiver.recv_multipart()[1]
91 context.terminate()
94 context.terminate()
92
95
93 class ParameterConf():
96 class ParameterConf():
94
97
95 id = None
98 id = None
96 name = None
99 name = None
97 value = None
100 value = None
98 format = None
101 format = None
99
102
100 __formated_value = None
103 __formated_value = None
101
104
102 ELEMENTNAME = 'Parameter'
105 ELEMENTNAME = 'Parameter'
103
106
104 def __init__(self):
107 def __init__(self):
105
108
106 self.format = 'str'
109 self.format = 'str'
107
110
108 def getElementName(self):
111 def getElementName(self):
109
112
110 return self.ELEMENTNAME
113 return self.ELEMENTNAME
111
114
112 def getValue(self):
115 def getValue(self):
113
116
114 value = self.value
117 value = self.value
115 format = self.format
118 format = self.format
116
119
117 if self.__formated_value != None:
120 if self.__formated_value != None:
118
121
119 return self.__formated_value
122 return self.__formated_value
120
123
121 if format == 'obj':
124 if format == 'obj':
122 return value
125 return value
123
126
124 if format == 'str':
127 if format == 'str':
125 self.__formated_value = str(value)
128 self.__formated_value = str(value)
126 return self.__formated_value
129 return self.__formated_value
127
130
128 if value == '':
131 if value == '':
129 raise ValueError('%s: This parameter value is empty' % self.name)
132 raise ValueError('%s: This parameter value is empty' % self.name)
130
133
131 if format == 'list':
134 if format == 'list':
132 strList = [s.strip() for s in value.split(',')]
135 strList = [s.strip() for s in value.split(',')]
133 self.__formated_value = strList
136 self.__formated_value = strList
134
137
135 return self.__formated_value
138 return self.__formated_value
136
139
137 if format == 'intlist':
140 if format == 'intlist':
138 '''
141 '''
139 Example:
142 Example:
140 value = (0,1,2)
143 value = (0,1,2)
141 '''
144 '''
142
145
143 new_value = ast.literal_eval(value)
146 new_value = ast.literal_eval(value)
144
147
145 if type(new_value) not in (tuple, list):
148 if type(new_value) not in (tuple, list):
146 new_value = [int(new_value)]
149 new_value = [int(new_value)]
147
150
148 self.__formated_value = new_value
151 self.__formated_value = new_value
149
152
150 return self.__formated_value
153 return self.__formated_value
151
154
152 if format == 'floatlist':
155 if format == 'floatlist':
153 '''
156 '''
154 Example:
157 Example:
155 value = (0.5, 1.4, 2.7)
158 value = (0.5, 1.4, 2.7)
156 '''
159 '''
157
160
158 new_value = ast.literal_eval(value)
161 new_value = ast.literal_eval(value)
159
162
160 if type(new_value) not in (tuple, list):
163 if type(new_value) not in (tuple, list):
161 new_value = [float(new_value)]
164 new_value = [float(new_value)]
162
165
163 self.__formated_value = new_value
166 self.__formated_value = new_value
164
167
165 return self.__formated_value
168 return self.__formated_value
166
169
167 if format == 'date':
170 if format == 'date':
168 strList = value.split('/')
171 strList = value.split('/')
169 intList = [int(x) for x in strList]
172 intList = [int(x) for x in strList]
170 date = datetime.date(intList[0], intList[1], intList[2])
173 date = datetime.date(intList[0], intList[1], intList[2])
171
174
172 self.__formated_value = date
175 self.__formated_value = date
173
176
174 return self.__formated_value
177 return self.__formated_value
175
178
176 if format == 'time':
179 if format == 'time':
177 strList = value.split(':')
180 strList = value.split(':')
178 intList = [int(x) for x in strList]
181 intList = [int(x) for x in strList]
179 time = datetime.time(intList[0], intList[1], intList[2])
182 time = datetime.time(intList[0], intList[1], intList[2])
180
183
181 self.__formated_value = time
184 self.__formated_value = time
182
185
183 return self.__formated_value
186 return self.__formated_value
184
187
185 if format == 'pairslist':
188 if format == 'pairslist':
186 '''
189 '''
187 Example:
190 Example:
188 value = (0,1),(1,2)
191 value = (0,1),(1,2)
189 '''
192 '''
190
193
191 new_value = ast.literal_eval(value)
194 new_value = ast.literal_eval(value)
192
195
193 if type(new_value) not in (tuple, list):
196 if type(new_value) not in (tuple, list):
194 raise ValueError('%s has to be a tuple or list of pairs' % value)
197 raise ValueError('%s has to be a tuple or list of pairs' % value)
195
198
196 if type(new_value[0]) not in (tuple, list):
199 if type(new_value[0]) not in (tuple, list):
197 if len(new_value) != 2:
200 if len(new_value) != 2:
198 raise ValueError('%s has to be a tuple or list of pairs' % value)
201 raise ValueError('%s has to be a tuple or list of pairs' % value)
199 new_value = [new_value]
202 new_value = [new_value]
200
203
201 for thisPair in new_value:
204 for thisPair in new_value:
202 if len(thisPair) != 2:
205 if len(thisPair) != 2:
203 raise ValueError('%s has to be a tuple or list of pairs' % value)
206 raise ValueError('%s has to be a tuple or list of pairs' % value)
204
207
205 self.__formated_value = new_value
208 self.__formated_value = new_value
206
209
207 return self.__formated_value
210 return self.__formated_value
208
211
209 if format == 'multilist':
212 if format == 'multilist':
210 '''
213 '''
211 Example:
214 Example:
212 value = (0,1,2),(3,4,5)
215 value = (0,1,2),(3,4,5)
213 '''
216 '''
214 multiList = ast.literal_eval(value)
217 multiList = ast.literal_eval(value)
215
218
216 if type(multiList[0]) == int:
219 if type(multiList[0]) == int:
217 multiList = ast.literal_eval('(' + value + ')')
220 multiList = ast.literal_eval('(' + value + ')')
218
221
219 self.__formated_value = multiList
222 self.__formated_value = multiList
220
223
221 return self.__formated_value
224 return self.__formated_value
222
225
223 if format == 'bool':
226 if format == 'bool':
224 value = int(value)
227 value = int(value)
225
228
226 if format == 'int':
229 if format == 'int':
227 value = float(value)
230 value = float(value)
228
231
229 format_func = eval(format)
232 format_func = eval(format)
230
233
231 self.__formated_value = format_func(value)
234 self.__formated_value = format_func(value)
232
235
233 return self.__formated_value
236 return self.__formated_value
234
237
235 def updateId(self, new_id):
238 def updateId(self, new_id):
236
239
237 self.id = str(new_id)
240 self.id = str(new_id)
238
241
239 def setup(self, id, name, value, format='str'):
242 def setup(self, id, name, value, format='str'):
240 self.id = str(id)
243 self.id = str(id)
241 self.name = name
244 self.name = name
242 if format == 'obj':
245 if format == 'obj':
243 self.value = value
246 self.value = value
244 else:
247 else:
245 self.value = str(value)
248 self.value = str(value)
246 self.format = str.lower(format)
249 self.format = str.lower(format)
247
250
248 self.getValue()
251 self.getValue()
249
252
250 return 1
253 return 1
251
254
252 def update(self, name, value, format='str'):
255 def update(self, name, value, format='str'):
253
256
254 self.name = name
257 self.name = name
255 self.value = str(value)
258 self.value = str(value)
256 self.format = format
259 self.format = format
257
260
258 def makeXml(self, opElement):
261 def makeXml(self, opElement):
259 if self.name not in ('queue',):
262 if self.name not in ('queue',):
260 parmElement = SubElement(opElement, self.ELEMENTNAME)
263 parmElement = SubElement(opElement, self.ELEMENTNAME)
261 parmElement.set('id', str(self.id))
264 parmElement.set('id', str(self.id))
262 parmElement.set('name', self.name)
265 parmElement.set('name', self.name)
263 parmElement.set('value', self.value)
266 parmElement.set('value', self.value)
264 parmElement.set('format', self.format)
267 parmElement.set('format', self.format)
265
268
266 def readXml(self, parmElement):
269 def readXml(self, parmElement):
267
270
268 self.id = parmElement.get('id')
271 self.id = parmElement.get('id')
269 self.name = parmElement.get('name')
272 self.name = parmElement.get('name')
270 self.value = parmElement.get('value')
273 self.value = parmElement.get('value')
271 self.format = str.lower(parmElement.get('format'))
274 self.format = str.lower(parmElement.get('format'))
272
275
273 # Compatible with old signal chain version
276 # Compatible with old signal chain version
274 if self.format == 'int' and self.name == 'idfigure':
277 if self.format == 'int' and self.name == 'idfigure':
275 self.name = 'id'
278 self.name = 'id'
276
279
277 def printattr(self):
280 def printattr(self):
278
281
279 print('Parameter[%s]: name = %s, value = %s, format = %s, project_id = %s' % (self.id, self.name, self.value, self.format, self.project_id))
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 class OperationConf():
284 class OperationConf():
282
285
283 ELEMENTNAME = 'Operation'
286 ELEMENTNAME = 'Operation'
284
287
285 def __init__(self):
288 def __init__(self):
286
289
287 self.id = '0'
290 self.id = '0'
288 self.name = None
291 self.name = None
289 self.priority = None
292 self.priority = None
290 self.topic = None
293 self.parameters = {}
291
294 self.object = None
292 def __getNewId(self):
295 self.operations = []
293
294 return int(self.id) * 10 + len(self.parmConfObjList) + 1
295
296
296 def getId(self):
297 def getId(self):
298
297 return self.id
299 return self.id
298
300
301 def getNewId(self):
302
303 return int(self.id) * 10 + len(self.operations) + 1
304
299 def updateId(self, new_id):
305 def updateId(self, new_id):
300
306
301 self.id = str(new_id)
307 self.id = str(new_id)
302
308
303 n = 1
309 n = 1
304 for parmObj in self.parmConfObjList:
310 for conf in self.operations:
305
311 conf_id = str(int(new_id) * 10 + n)
306 idParm = str(int(new_id) * 10 + n)
312 conf.updateId(conf_id)
307 parmObj.updateId(idParm)
308
309 n += 1
313 n += 1
310
314
311 def getElementName(self):
315 def getKwargs(self):
312
313 return self.ELEMENTNAME
314
316
315 def getParameterObjList(self):
317 params = {}
316
318
317 return self.parmConfObjList
319 for key, value in self.parameters.items():
320 if value not in (None, '', ' '):
321 params[key] = value
318
322
319 def getParameterObj(self, parameterName):
323 return params
320
324
321 for parmConfObj in self.parmConfObjList:
325 def update(self, **kwargs):
322
326
323 if parmConfObj.name != parameterName:
327 for key, value in kwargs.items():
324 continue
328 self.addParameter(name=key, value=value)
325
329
326 return parmConfObj
330 def addParameter(self, name, value, format=None):
331 '''
332 '''
327
333
328 return None
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
329
346
330 def getParameterObjfromValue(self, parameterValue):
347 def getParameters(self):
331
348
332 for parmConfObj in self.parmConfObjList:
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)
333
358
334 if parmConfObj.getValue() != parameterValue:
359 return params
335 continue
336
360
337 return parmConfObj.getValue()
361 def makeXml(self, element):
338
362
339 return None
363 xml = SubElement(element, self.ELEMENTNAME)
364 for label in self.xml_labels:
365 xml.set(label, str(getattr(self, label)))
340
366
341 def getParameterValue(self, 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)
342
371
343 parameterObj = self.getParameterObj(parameterName)
372 for conf in self.operations:
373 conf.makeXml(xml)
344
374
345 # if not parameterObj:
375 def __str__(self):
346 # return None
347
376
348 value = parameterObj.getValue()
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)
349
381
350 return value
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)
351
387
352 def getKwargs(self):
388 for conf in self.operations:
389 s += str(conf)
353
390
354 kwargs = {}
391 return s
355
392
356 for parmConfObj in self.parmConfObjList:
393 class OperationConf(ConfBase):
357 if self.name == 'run' and parmConfObj.name == 'datatype':
358 continue
359
394
360 kwargs[parmConfObj.name] = parmConfObj.getValue()
395 ELEMENTNAME = 'Operation'
361
396 xml_labels = ['id', 'name']
362 return kwargs
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 self.id = str(id)
400 self.id = str(id)
367 self.project_id = project_id
401 self.project_id = project_id
368 self.name = name
402 self.name = name
369 self.type = type
403 self.type = 'other'
370 self.priority = priority
371 self.err_queue = err_queue
404 self.err_queue = err_queue
372 self.lock = lock
373 self.parmConfObjList = []
374
375 def removeParameters(self):
376
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
405
411 for parmConfObj in self.parmConfObjList:
406 def readXml(self, element, project_id, err_queue):
412 parmConfObj.makeXml(opElement)
413
407
414 def readXml(self, opElement, project_id):
408 self.id = element.get('id')
415
409 self.name = element.get('name')
416 self.id = opElement.get('id')
410 self.type = 'other'
417 self.name = opElement.get('name')
418 self.type = opElement.get('type')
419 self.priority = opElement.get('priority')
420 self.project_id = str(project_id)
411 self.project_id = str(project_id)
412 self.err_queue = err_queue
421
413
422 # Compatible with old signal chain version
414 for elm in element.iter('Parameter'):
423 # Use of 'run' method instead 'init'
415 self.addParameter(elm.get('name'), elm.get('value'))
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()
455
416
456 def createObject(self):
417 def createObject(self):
457
418
458 className = eval(self.name)
419 className = eval(self.name)
459
420
460 if self.type == 'other':
421 if 'Plot' in self.name or 'Writer' in self.name or 'Send' in self.name or 'print' in self.name:
461 opObj = className()
462 elif self.type == 'external':
463 kwargs = self.getKwargs()
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 opObj.start()
424 opObj.start()
466 self.opObj = opObj
425 self.type = 'external'
426 else:
427 opObj = className()
467
428
429 self.object = opObj
468 return opObj
430 return opObj
469
431
470 class ProcUnitConf():
432 class ProcUnitConf(ConfBase):
471
433
472 ELEMENTNAME = 'ProcUnit'
434 ELEMENTNAME = 'ProcUnit'
435 xml_labels = ['id', 'inputId', 'name']
473
436
474 def __init__(self):
437 def setup(self, project_id, id, name, datatype, inputId, err_queue):
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):
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 if datatype == None and name == None:
441 if datatype == None and name == None:
562 raise ValueError('datatype or name should be defined')
442 raise ValueError('datatype or name should be defined')
563
443
564 #Definir una condicion para inputId cuando sea 0
565
566 if name == None:
444 if name == None:
567 if 'Proc' in datatype:
445 if 'Proc' in datatype:
568 name = datatype
446 name = datatype
569 else:
447 else:
570 name = '%sProc' % (datatype)
448 name = '%sProc' % (datatype)
571
449
572 if datatype == None:
450 if datatype == None:
573 datatype = name.replace('Proc', '')
451 datatype = name.replace('Proc', '')
574
452
575 self.id = str(id)
453 self.id = str(id)
576 self.project_id = project_id
454 self.project_id = project_id
577 self.name = name
455 self.name = name
578 self.datatype = datatype
456 self.datatype = datatype
579 self.inputId = inputId
457 self.inputId = inputId
580 self.err_queue = err_queue
458 self.err_queue = err_queue
581 self.lock = lock
459 self.operations = []
582 self.opConfObjList = []
460 self.parameters = {}
583
461
584 self.addOperation(name='run', optype='self')
462 def removeOperation(self, id):
585
463
586 def removeOperations(self):
464 i = [1 if x.id==id else 0 for x in self.operations]
587
465 self.operations.pop(i.index(1))
588 for obj in self.opConfObjList:
589 del obj
590
591 self.opConfObjList = []
592 self.addOperation(name='run')
593
594 def addParameter(self, **kwargs):
595 '''
596 Add parameters to 'run' operation
597 '''
598 opObj = self.opConfObjList[0]
599
466
600 opObj.addParameter(**kwargs)
467 def getOperation(self, id):
601
468
602 return opObj
469 for conf in self.operations:
470 if conf.id == id:
471 return conf
603
472
604 def addOperation(self, name, optype='self'):
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()
477 id = self.getNewId()
613 priority = self.__getPriority() # Sin mucho sentido, pero puede usarse
478 conf = OperationConf()
614 opConfObj = OperationConf()
479 conf.setup(id, name=name, priority='0', project_id=self.project_id, err_queue=self.err_queue)
615 opConfObj.setup(id, name=name, priority=priority, type=optype, project_id=self.project_id, err_queue=self.err_queue, lock=self.lock)
480 self.operations.append(conf)
616 self.opConfObjList.append(opConfObj)
617
618 return opConfObj
619
481
620 def makeXml(self, projectElement):
482 return conf
621
483
622 procUnitElement = SubElement(projectElement, self.ELEMENTNAME)
484 def readXml(self, element, project_id, err_queue):
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))
627
485
628 for opConfObj in self.opConfObjList:
486 self.id = element.get('id')
629 opConfObj.makeXml(procUnitElement)
487 self.name = element.get('name')
630
488 self.inputId = None if element.get('inputId') == 'None' else element.get('inputId')
631 def readXml(self, upElement, project_id):
489 self.datatype = element.get('datatype', self.name.replace(self.ELEMENTNAME.replace('Unit', ''), ''))
632
633 self.id = upElement.get('id')
634 self.name = upElement.get('name')
635 self.datatype = upElement.get('datatype')
636 self.inputId = upElement.get('inputId')
637 self.project_id = str(project_id)
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':
495 for elm in element:
640 self.datatype = self.datatype.replace('Reader', '')
496 if elm.tag == 'Parameter':
641
497 self.addParameter(elm.get('name'), elm.get('value'))
642 if self.ELEMENTNAME == 'ProcUnit':
498 elif elm.tag == 'Operation':
643 self.datatype = self.datatype.replace('Proc', '')
499 conf = OperationConf()
644
500 conf.readXml(elm, project_id, err_queue)
645 if self.inputId == 'None':
501 self.operations.append(conf)
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
675
502
676 def createObjects(self):
503 def createObjects(self):
677 '''
504 '''
678 Instancia de unidades de procesamiento.
505 Instancia de unidades de procesamiento.
679 '''
506 '''
680
507
681 className = eval(self.name)
508 className = eval(self.name)
682 #print(self.name)
509 #print(self.name)
683 kwargs = self.getKwargs()
510 kwargs = self.getKwargs()
684 #print(kwargs)
511 procUnitObj = className()
685 #print("mark_a")
512 procUnitObj.name = self.name
686 procUnitObj = className(self.id, self.inputId, self.project_id, self.err_queue, self.lock, 'ProcUnit', **kwargs)
687 #print("mark_b")
688 log.success('creating process...', self.name)
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':
517 opObj = conf.createObject()
693 continue
694 elif opConfObj.type == 'self':
695 opObj = getattr(procUnitObj, opConfObj.name)
696 else:
697 opObj = opConfObj.createObject()
698
518
699 log.success('adding operation: {}, type:{}'.format(
519 log.success('adding operation: {}, type:{}'.format(
700 opConfObj.name,
520 conf.name,
701 opConfObj.type), self.name)
521 conf.type), self.name)
702
703 procUnitObj.addOperation(opConfObj, opObj)
704
522
705 procUnitObj.start()
523 procUnitObj.addOperation(conf, opObj)
706 self.procUnitObj = procUnitObj
707
524
708 def close(self):
525 self.object = procUnitObj
709
526
710 for opConfObj in self.opConfObjList:
527 def run(self):
711 if opConfObj.type == 'self':
528 '''
712 continue
529 '''
713
714 opObj = self.procUnitObj.getOperationObj(opConfObj.id)
715 opObj.close()
716
717 self.procUnitObj.close()
718
530
719 return
531 return self.object.call(**self.getKwargs())
720
532
721
533
722 class ReadUnitConf(ProcUnitConf):
534 class ReadUnitConf(ProcUnitConf):
723
535
724 ELEMENTNAME = 'ReadUnit'
536 ELEMENTNAME = 'ReadUnit'
725
537
726 def __init__(self):
538 def __init__(self):
727
539
728 self.id = None
540 self.id = None
729 self.datatype = None
541 self.datatype = None
730 self.name = None
542 self.name = None
731 self.inputId = None
543 self.inputId = None
732 self.opConfObjList = []
544 self.operations = []
733 self.lock = Event()
545 self.parameters = {}
734 self.lock.set()
735 self.lock.n = Value('d', 0)
736
737 def getElementName(self):
738
739 return self.ELEMENTNAME
740
546
741 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
547 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
742 startTime='', endTime='', server=None, **kwargs):
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 if datatype == None and name == None:
550 if datatype == None and name == None:
755 raise ValueError('datatype or name should be defined')
551 raise ValueError('datatype or name should be defined')
756 if name == None:
552 if name == None:
757 if 'Reader' in datatype:
553 if 'Reader' in datatype:
758 name = datatype
554 name = datatype
759 datatype = name.replace('Reader','')
555 datatype = name.replace('Reader','')
760 else:
556 else:
761 name = '{}Reader'.format(datatype)
557 name = '{}Reader'.format(datatype)
762 if datatype == None:
558 if datatype == None:
763 if 'Reader' in name:
559 if 'Reader' in name:
764 datatype = name.replace('Reader','')
560 datatype = name.replace('Reader','')
765 else:
561 else:
766 datatype = name
562 datatype = name
767 name = '{}Reader'.format(name)
563 name = '{}Reader'.format(name)
768
564
769 self.id = id
565 self.id = id
770 self.project_id = project_id
566 self.project_id = project_id
771 self.name = name
567 self.name = name
772 self.datatype = datatype
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 self.err_queue = err_queue
569 self.err_queue = err_queue
782 self.addRunOperation(**kwargs)
783
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
570
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:
577 for key, value in kwargs.items():
806 del obj
578 self.addParameter(name=key, value=value)
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')
880
579
881
580
882 class Project(Process):
581 class Project(Process):
582 """API to create signal chain projects"""
883
583
884 ELEMENTNAME = 'Project'
584 ELEMENTNAME = 'Project'
885
585
886 def __init__(self):
586 def __init__(self, name=''):
887
587
888 Process.__init__(self)
588 Process.__init__(self)
889 self.id = None
589 self.id = '1'
590 if name:
591 self.name = '{} ({})'.format(Process.__name__, name)
890 self.filename = None
592 self.filename = None
891 self.description = None
593 self.description = None
892 self.email = None
594 self.email = None
893 self.alarm = None
595 self.alarm = []
894 self.procUnitConfObjDict = {}
596 self.configurations = {}
895 self.err_queue = Queue()
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 id = int(self.id) * 10
604 id = int(self.id) * 10
901
605
902 while True:
606 while True:
903 id += 1
607 id += 1
904
608
905 if str(id) in idList:
609 if str(id) in idList:
906 continue
610 continue
907
611
908 break
612 break
909
613
910 return str(id)
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 def updateId(self, new_id):
616 def updateId(self, new_id):
921
617
922 self.id = str(new_id)
618 self.id = str(new_id)
923
619
924 keyList = list(self.procUnitConfObjDict.keys())
620 keyList = list(self.configurations.keys())
925 keyList.sort()
621 keyList.sort()
926
622
927 n = 1
623 n = 1
928 newProcUnitConfObjDict = {}
624 new_confs = {}
929
625
930 for procKey in keyList:
626 for procKey in keyList:
931
627
932 procUnitConfObj = self.procUnitConfObjDict[procKey]
628 conf = self.configurations[procKey]
933 idProcUnit = str(int(self.id) * 10 + n)
629 idProcUnit = str(int(self.id) * 10 + n)
934 procUnitConfObj.updateId(idProcUnit)
630 conf.updateId(idProcUnit)
935 newProcUnitConfObjDict[idProcUnit] = procUnitConfObj
631 new_confs[idProcUnit] = conf
936 n += 1
632 n += 1
937
633
938 self.procUnitConfObjDict = newProcUnitConfObjDict
634 self.configurations = new_confs
939
635
940 def setup(self, id=1, name='', description='', email=None, alarm=[]):
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 self.id = str(id)
638 self.id = str(id)
950 self.description = description
639 self.description = description
951 self.email = email
640 self.email = email
952 self.alarm = alarm
641 self.alarm = alarm
953 if name:
642 if name:
954 self.name = '{} ({})'.format(Process.__name__, name)
643 self.name = '{} ({})'.format(Process.__name__, name)
955
644
956 def update(self, **kwargs):
645 def update(self, **kwargs):
957
646
958 for key, value in list(kwargs.items()):
647 for key, value in kwargs.items():
959 setattr(self, key, value)
648 setattr(self, key, value)
960
649
961 def clone(self):
650 def clone(self):
962
651
963 p = Project()
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 return p
658 return p
966
659
967 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
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 if id is None:
665 if id is None:
978 idReadUnit = self.__getNewId()
666 idReadUnit = self.getNewId()
979 else:
667 else:
980 idReadUnit = str(id)
668 idReadUnit = str(id)
981
669
982 readUnitConfObj = ReadUnitConf()
670 conf = ReadUnitConf()
983 readUnitConfObj.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
671 conf.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
984 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
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()
681 if id is None:
1001 procUnitConfObj = ProcUnitConf()
682 idProcUnit = self.getNewId()
1002 input_proc = self.procUnitConfObjDict[inputId]
683 else:
1003 procUnitConfObj.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue, input_proc.lock)
684 idProcUnit = id
1004 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
1005
1006 return procUnitConfObj
1007
1008 def removeProcUnit(self, id):
1009
685
1010 if id in list(self.procUnitConfObjDict.keys()):
686 conf = ProcUnitConf()
1011 self.procUnitConfObjDict.pop(id)
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()):
699 for obj in list(self.configurations.values()):
1022 if obj.getElementName() == 'ReadUnit':
700 if obj.ELEMENTNAME == 'ReadUnit':
1023 return obj
701 return obj
1024
702
1025 return None
703 return None
1026
704
1027 def getProcUnitObj(self, id=None, name=None):
705 def getProcUnit(self, id):
1028
1029 if id != None:
1030 return self.procUnitConfObjDict[id]
1031
706
1032 if name != None:
707 return self.configurations[id]
1033 return self.getProcUnitObjByName(name)
1034
708
1035 return None
709 def getUnits(self):
1036
1037 def getProcUnitObjByName(self, name):
1038
710
1039 for obj in list(self.procUnitConfObjDict.values()):
711 keys = list(self.configurations)
1040 if obj.name == name:
712 keys.sort()
1041 return obj
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 def makeXml(self):
721 def makeXml(self):
1050
722
1051 projectElement = Element('Project')
723 xml = Element('Project')
1052 projectElement.set('id', str(self.id))
724 xml.set('id', str(self.id))
1053 projectElement.set('name', self.name)
725 xml.set('name', self.name)
1054 projectElement.set('description', self.description)
726 xml.set('description', self.description)
1055
727
1056 for procUnitConfObj in list(self.procUnitConfObjDict.values()):
728 for conf in self.configurations.values():
1057 procUnitConfObj.makeXml(projectElement)
729 conf.makeXml(xml)
1058
730
1059 self.projectElement = projectElement
731 self.xml = xml
1060
732
1061 def writeXml(self, filename=None):
733 def writeXml(self, filename=None):
1062
734
1063 if filename == None:
735 if filename == None:
1064 if self.filename:
736 if self.filename:
1065 filename = self.filename
737 filename = self.filename
1066 else:
738 else:
1067 filename = 'schain.xml'
739 filename = 'schain.xml'
1068
740
1069 if not filename:
741 if not filename:
1070 print('filename has not been defined. Use setFilename(filename) for do it.')
742 print('filename has not been defined. Use setFilename(filename) for do it.')
1071 return 0
743 return 0
1072
744
1073 abs_file = os.path.abspath(filename)
745 abs_file = os.path.abspath(filename)
1074
746
1075 if not os.access(os.path.dirname(abs_file), os.W_OK):
747 if not os.access(os.path.dirname(abs_file), os.W_OK):
1076 print('No write permission on %s' % os.path.dirname(abs_file))
748 print('No write permission on %s' % os.path.dirname(abs_file))
1077 return 0
749 return 0
1078
750
1079 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
751 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
1080 print('File %s already exists and it could not be overwriten' % abs_file)
752 print('File %s already exists and it could not be overwriten' % abs_file)
1081 return 0
753 return 0
1082
754
1083 self.makeXml()
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 self.filename = abs_file
759 self.filename = abs_file
1088
760
1089 return 1
761 return 1
1090
762
1091 def readXml(self, filename=None):
763 def readXml(self, filename):
1092
1093 if not filename:
1094 print('filename is not defined')
1095 return 0
1096
764
1097 abs_file = os.path.abspath(filename)
765 abs_file = os.path.abspath(filename)
1098
766
1099 if not os.path.isfile(abs_file):
767 self.configurations = {}
1100 print('%s file does not exist' % abs_file)
1101 return 0
1102
1103 self.projectElement = None
1104 self.procUnitConfObjDict = {}
1105
768
1106 try:
769 try:
1107 self.projectElement = ElementTree().parse(abs_file)
770 self.xml = ElementTree().parse(abs_file)
1108 except:
771 except:
1109 print('Error reading %s, verify file format' % filename)
772 log.error('Error reading %s, verify file format' % filename)
1110 return 0
773 return 0
1111
774
1112 self.project = self.projectElement.tag
775 self.id = self.xml.get('id')
1113
776 self.name = self.xml.get('name')
1114 self.id = self.projectElement.get('id')
777 self.description = self.xml.get('description')
1115 self.name = self.projectElement.get('name')
778
1116 self.description = self.projectElement.get('description')
779 for element in self.xml:
1117
780 if element.tag == 'ReadUnit':
1118 readUnitElementList = self.projectElement.iter(
781 conf = ReadUnitConf()
1119 ReadUnitConf().getElementName())
782 conf.readXml(element, self.id, self.err_queue)
1120
783 self.configurations[conf.id] = conf
1121 for readUnitElement in readUnitElementList:
784 elif element.tag == 'ProcUnit':
1122 readUnitConfObj = ReadUnitConf()
785 conf = ProcUnitConf()
1123 readUnitConfObj.readXml(readUnitElement, self.id)
786 input_proc = self.configurations[element.get('inputId')]
1124 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
787 conf.readXml(element, self.id, self.err_queue)
1125
788 self.configurations[conf.id] = conf
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
1133
789
1134 self.filename = abs_file
790 self.filename = abs_file
1135
791
1136 return 1
792 return 1
1137
793
1138 def __str__(self):
794 def __str__(self):
1139
795
1140 print('Project: name = %s, description = %s, id = %s' % (
796 text = '\nProject[id=%s, name=%s, description=%s]\n\n' % (
797 self.id,
1141 self.name,
798 self.name,
1142 self.description,
799 self.description,
1143 self.id))
800 )
1144
801
1145 for procUnitConfObj in self.procUnitConfObjDict.values():
802 for conf in self.configurations.values():
1146 print(procUnitConfObj)
803 text += '{}'.format(conf)
1147
804
1148 def createObjects(self):
805 return text
1149
806
807 def createObjects(self):
1150
808
1151 keys = list(self.procUnitConfObjDict.keys())
809 keys = list(self.configurations.keys())
1152 keys.sort()
810 keys.sort()
1153 for key in keys:
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 def monitor(self):
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 t.start()
820 t.start()
1160
821
1161 def __monitor(self, queue, ctx):
822 def _monitor(self, queue, ctx):
1162
823
1163 import socket
824 import socket
1164
825
1165 procs = 0
826 procs = 0
1166 err_msg = ''
827 err_msg = ''
1167
828
1168 while True:
829 while True:
1169 msg = queue.get()
830 msg = queue.get()
1170 if '#_start_#' in msg:
831 if '#_start_#' in msg:
1171 procs += 1
832 procs += 1
1172 elif '#_end_#' in msg:
833 elif '#_end_#' in msg:
1173 procs -=1
834 procs -=1
1174 else:
835 else:
1175 err_msg = msg
836 err_msg = msg
1176
837
1177 if procs == 0 or 'Traceback' in err_msg:
838 if procs == 0 or 'Traceback' in err_msg:
1178 break
839 break
1179 time.sleep(0.1)
840 time.sleep(0.1)
1180
841
1181 if '|' in err_msg:
842 if '|' in err_msg:
1182 name, err = err_msg.split('|')
843 name, err = err_msg.split('|')
1183 if 'SchainWarning' in err:
844 if 'SchainWarning' in err:
1184 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), name)
845 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), name)
1185 elif 'SchainError' in err:
846 elif 'SchainError' in err:
1186 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
847 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
1187 else:
848 else:
1188 log.error(err, name)
849 log.error(err, name)
1189 else:
850 else:
1190 name, err = self.name, err_msg
851 name, err = self.name, err_msg
1191
852
1192 time.sleep(2)
853 time.sleep(1)
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()
1199
854
1200 ctx.term()
855 ctx.term()
1201
856
1202 message = ''.join(err)
857 message = ''.join(err)
1203
858
1204 if err_msg:
859 if err_msg:
1205 subject = 'SChain v%s: Error running %s\n' % (
860 subject = 'SChain v%s: Error running %s\n' % (
1206 schainpy.__version__, self.name)
861 schainpy.__version__, self.name)
1207
862
1208 subtitle = 'Hostname: %s\n' % socket.gethostbyname(
863 subtitle = 'Hostname: %s\n' % socket.gethostbyname(
1209 socket.gethostname())
864 socket.gethostname())
1210 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
865 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
1211 subtitle += 'Configuration file: %s\n' % self.filename
866 subtitle += 'Configuration file: %s\n' % self.filename
1212 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
867 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
1213
868
1214 readUnitConfObj = self.getReadUnitObj()
869 readUnitConfObj = self.getReadUnit()
1215 if readUnitConfObj:
870 if readUnitConfObj:
1216 subtitle += '\nInput parameters:\n'
871 subtitle += '\nInput parameters:\n'
1217 subtitle += '[Data path = %s]\n' % readUnitConfObj.path
872 subtitle += '[Data path = %s]\n' % readUnitConfObj.parameters['path']
1218 subtitle += '[Data type = %s]\n' % readUnitConfObj.datatype
873 subtitle += '[Start date = %s]\n' % readUnitConfObj.parameters['startDate']
1219 subtitle += '[Start date = %s]\n' % readUnitConfObj.startDate
874 subtitle += '[End date = %s]\n' % readUnitConfObj.parameters['endDate']
1220 subtitle += '[End date = %s]\n' % readUnitConfObj.endDate
875 subtitle += '[Start time = %s]\n' % readUnitConfObj.parameters['startTime']
1221 subtitle += '[Start time = %s]\n' % readUnitConfObj.startTime
876 subtitle += '[End time = %s]\n' % readUnitConfObj.parameters['endTime']
1222 subtitle += '[End time = %s]\n' % readUnitConfObj.endTime
1223
877
1224 a = Alarm(
878 a = Alarm(
1225 modes=self.alarm,
879 modes=self.alarm,
1226 email=self.email,
880 email=self.email,
1227 message=message,
881 message=message,
1228 subject=subject,
882 subject=subject,
1229 subtitle=subtitle,
883 subtitle=subtitle,
1230 filename=self.filename
884 filename=self.filename
1231 )
885 )
1232
886
1233 a.start()
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 def setFilename(self, filename):
889 def setFilename(self, filename):
1267
890
1268 self.filename = filename
891 self.filename = filename
1269
892
1270 def setProxy(self):
893 def runProcs(self):
1271
894
1272 if not os.path.exists('/tmp/schain'):
895 err = False
1273 os.mkdir('/tmp/schain')
896 n = len(self.configurations)
1274
897
1275 self.ctx = zmq.Context()
898 while not err:
1276 xpub = self.ctx.socket(zmq.XPUB)
899 for conf in self.getUnits():
1277 xpub.bind('ipc:///tmp/schain/{}_pub'.format(self.id))
900 ok = conf.run()
1278 xsub = self.ctx.socket(zmq.XSUB)
901 if ok == 'Error':
1279 xsub.bind('ipc:///tmp/schain/{}_sub'.format(self.id))
902 n -= 1
1280 self.monitor()
903 continue
1281 try:
904 elif not ok:
1282 zmq.proxy(xpub, xsub)
905 break
1283 except zmq.ContextTerminated:
906 if n == 0:
1284 xpub.close()
907 err = True
1285 xsub.close()
1286
908
1287 def run(self):
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 self.start_time = time.time()
913 self.start_time = time.time()
1291 self.createObjects()
914 self.createObjects()
1292 self.setProxy()
915 self.runProcs()
1293 log.success('{} Done (Time: {}s)'.format(
916 log.success('{} Done (Time: {:4.2f}s)'.format(
1294 self.name,
917 self.name,
1295 time.time()-self.start_time), '')
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 #!/usr/bin/env python
1 #!/usr/bin/env python
2 import os
2 import os
3 import sys
3 import sys
4 import ast
5
6 from schainpy.controller import Project
7 from schainpy.cli import cli
4 from schainpy.utils import log
8 from schainpy.utils import log
5
9
6 try:
10 try:
7 from PyQt4 import QtCore, QtGui
11 import kivy
8 from PyQt4.QtGui import QApplication
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 except:
22 except:
10 log.error(
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 sys.exit()
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'])
300
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)
18
306
19 def main():
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_():
314 filename = os.path.join(self.workspace, '{}.xml'.format(self.project.name))
26 sys.exit(-1)
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()
319 class SignalChainApp(App):
33 MainGUI.setWorkSpaceGUI(WorkPathspace.dirComBox.currentText())
320 def build(self):
34 MainGUI.show()
321 return MainLayout(spacing=10)
35 sys.exit(app.exec_())
36
322
37
323
38 if __name__ == "__main__":
324 if __name__ == "__main__":
39 main()
325 SignalChainApp().run() No newline at end of file
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
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
NO CONTENT: file renamed from schainpy/gui/figures/__init__.py to schainpy/scripts/restore.spst
1 NO CONTENT: modified file
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
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
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
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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