##// END OF EJS Templates
Move schaincli to schainpy.cli
Juan C. Espinoza -
r1113:f2689c814816
parent child
Show More
1 NO CONTENT: file renamed from schaincli/README.md to schainpy/cli/README.md
1 NO CONTENT: file renamed from schaincli/__init__.py to schainpy/cli/__init__.py
@@ -1,168 +1,168
1 1 import click
2 2 import schainpy
3 3 import subprocess
4 4 import os
5 5 import sys
6 6 import glob
7 7 save_stdout = sys.stdout
8 8 sys.stdout = open('trash', 'w')
9 9 from multiprocessing import cpu_count
10 from schaincli import templates
11 10 from schainpy.controller import Project
12 11 from schainpy.model import Operation, ProcessingUnit
13 12 from schainpy.utils import log
14 13 from importlib import import_module
15 14 from pydoc import locate
16 15 from fuzzywuzzy import process
17 16 from schainpy.utils import paramsFinder
17 import templates
18 18 sys.stdout = save_stdout
19 19
20 20
21 21 def print_version(ctx, param, value):
22 22 if not value or ctx.resilient_parsing:
23 23 return
24 24 click.echo(schainpy.__version__)
25 25 ctx.exit()
26 26
27 27
28 28 cliLogger = log.makelogger('schain cli')
29 29 PREFIX = 'experiment'
30 30
31 31
32 32 @click.command()
33 33 @click.option('--version', '-v', is_flag=True, callback=print_version, help='SChain version', type=str)
34 34 @click.argument('command', default='run', required=True)
35 35 @click.argument('nextcommand', default=None, required=False, type=str)
36 36 def main(command, nextcommand, version):
37 37 """COMMAND LINE INTERFACE FOR SIGNAL CHAIN - JICAMARCA RADIO OBSERVATORY \n
38 38 Available commands.\n
39 39 --xml: runs a schain XML generated file\n
40 40 run: runs any python script starting 'experiment_'\n
41 41 generate: generates a template schain script\n
42 42 search: return avilable operations, procs or arguments of the give operation/proc\n"""
43 43 if command == 'xml':
44 44 runFromXML(nextcommand)
45 45 elif command == 'generate':
46 46 generate()
47 47 elif command == 'test':
48 48 test()
49 49 elif command == 'run':
50 50 runschain(nextcommand)
51 51 elif command == 'search':
52 52 search(nextcommand)
53 53 else:
54 54 log.error('Command {} is not defined'.format(command))
55 55
56 56
57 57 def check_module(possible, instance):
58 58 def check(x):
59 59 try:
60 60 instancia = locate('schainpy.model.{}'.format(x))
61 61 return isinstance(instancia(), instance)
62 62 except Exception as e:
63 63 return False
64 64 clean = clean_modules(possible)
65 65 return [x for x in clean if check(x)]
66 66
67 67
68 68 def clean_modules(module):
69 69 noEndsUnder = [x for x in module if not x.endswith('__')]
70 70 noStartUnder = [x for x in noEndsUnder if not x.startswith('__')]
71 71 noFullUpper = [x for x in noStartUnder if not x.isupper()]
72 72 return noFullUpper
73 73
74 74
75 75 def search(nextcommand):
76 76 if nextcommand is None:
77 77 log.error('There is no Operation/ProcessingUnit to search')
78 78 elif nextcommand == 'procs':
79 79 procs = paramsFinder.getProcs()
80 80 log.success(
81 81 'Current ProcessingUnits are:\n\033[1m{}\033[0m'.format('\n'.join(procs)))
82 82
83 83 elif nextcommand == 'operations':
84 84 operations = paramsFinder.getOperations()
85 85 log.success('Current Operations are:\n\033[1m{}\033[0m'.format(
86 86 '\n'.join(operations)))
87 87 else:
88 88 try:
89 89 args = paramsFinder.getArgs(nextcommand)
90 90 log.warning(
91 91 'Use this feature with caution. It may not return all the allowed arguments')
92 92 if len(args) == 0:
93 93 log.success('{} has no arguments'.format(nextcommand))
94 94 else:
95 95 log.success('Showing {} arguments:\n\033[1m{}\033[0m'.format(
96 96 nextcommand, '\n'.join(args)))
97 97 except Exception as e:
98 98 log.error('Module {} does not exists'.format(nextcommand))
99 99 allModules = paramsFinder.getAll()
100 100 similar = process.extractOne(nextcommand, allModules)[0]
101 101 log.success('Showing {} instead'.format(similar))
102 102 search(similar)
103 103
104 104
105 105 def runschain(nextcommand):
106 106 if nextcommand is None:
107 107 currentfiles = glob.glob('./{}_*.py'.format(PREFIX))
108 108 numberfiles = len(currentfiles)
109 109 if numberfiles > 1:
110 110 log.error('There is more than one file to run')
111 111 elif numberfiles == 1:
112 112 subprocess.call(['python ' + currentfiles[0]], shell=True)
113 113 else:
114 114 log.error('There is no file to run')
115 115 else:
116 116 try:
117 117 subprocess.call(['python ' + nextcommand], shell=True)
118 118 except Exception as e:
119 119 log.error("I cannot run the file. Does it exists?")
120 120
121 121
122 122 def basicInputs():
123 123 inputs = {}
124 124 inputs['desc'] = click.prompt(
125 125 'Enter a description', default="A schain project", type=str)
126 126 inputs['name'] = click.prompt(
127 127 'Name of the project', default="project", type=str)
128 128 inputs['path'] = click.prompt('Data path', default=os.getcwd(
129 129 ), type=click.Path(exists=True, resolve_path=True))
130 130 inputs['startDate'] = click.prompt(
131 131 'Start date', default='1970/01/01', type=str)
132 132 inputs['endDate'] = click.prompt(
133 133 'End date', default='2017/12/31', type=str)
134 134 inputs['startHour'] = click.prompt(
135 135 'Start hour', default='00:00:00', type=str)
136 136 inputs['endHour'] = click.prompt('End hour', default='23:59:59', type=str)
137 137 inputs['figpath'] = inputs['path'] + '/figs'
138 138 return inputs
139 139
140 140
141 141 def generate():
142 142 inputs = basicInputs()
143 143 inputs['multiprocess'] = click.confirm('Is this a multiprocess script?')
144 144 if inputs['multiprocess']:
145 145 inputs['nProcess'] = click.prompt(
146 146 'How many process?', default=cpu_count(), type=int)
147 147 current = templates.multiprocess.format(**inputs)
148 148 else:
149 149 current = templates.basic.format(**inputs)
150 150 scriptname = '{}_{}.py'.format(PREFIX, inputs['name'])
151 151 script = open(scriptname, 'w')
152 152 try:
153 153 script.write(current)
154 154 log.success('Script {} generated'.format(scriptname))
155 155 except Exception as e:
156 156 log.error('I cannot create the file. Do you have writing permissions?')
157 157
158 158
159 159 def test():
160 160 log.warning('testing')
161 161
162 162
163 163 def runFromXML(filename):
164 164 controller = Project()
165 165 if not controller.readXml(filename):
166 166 return
167 167 controller.start()
168 168 return
1 NO CONTENT: file renamed from schaincli/templates.py to schainpy/cli/templates.py
1 NO CONTENT: file renamed from schaincli/tests/__init__.py to schainpy/cli/tests/__init__.py
@@ -1,29 +1,29
1 1 import pytest
2 2 from click.testing import CliRunner
3 from schaincli import cli
3 from schainpy.cli import cli
4 4
5 5
6 6 @pytest.fixture
7 7 def runner():
8 8 return CliRunner()
9 9
10 10
11 11 def test_cli(runner):
12 12 result = runner.invoke(cli.main)
13 13 assert result.exit_code == 0
14 14 assert not result.exception
15 15 assert result.output.strip() == 'Hello, world.'
16 16
17 17
18 18 def test_cli_with_option(runner):
19 19 result = runner.invoke(cli.main, ['--as-cowboy'])
20 20 assert not result.exception
21 21 assert result.exit_code == 0
22 22 assert result.output.strip() == 'Howdy, world.'
23 23
24 24
25 25 def test_cli_with_arg(runner):
26 26 result = runner.invoke(cli.main, ['Jicamarca'])
27 27 assert result.exit_code == 0
28 28 assert not result.exception
29 29 assert result.output.strip() == 'Hello, Jicamarca.'
@@ -1,40 +1,39
1 1 #!/usr/bin/env python
2 2 import os
3 3 import sys
4 4 from schainpy.utils import log
5 5
6 6 try:
7 7 from PyQt4 import QtCore, QtGui
8 8 from PyQt4.QtGui import QApplication
9 9 except:
10 10 log.error(
11 11 'You should install PyQt4 module in order to run the GUI. See the README.')
12 12 sys.exit()
13 13
14
15 14 from schainpy.gui.viewcontroller.initwindow import InitWindow
16 15 from schainpy.gui.viewcontroller.basicwindow import BasicWindow
17 16 from schainpy.gui.viewcontroller.workspace import Workspace
18 17
19 18
20 19 def main():
21 20
22 21 app = QtGui.QApplication(sys.argv)
23 22
24 23 Welcome = InitWindow()
25 24
26 25 if not Welcome.exec_():
27 26 sys.exit(-1)
28 27
29 28 WorkPathspace = Workspace()
30 29 if not WorkPathspace.exec_():
31 30 sys.exit(-1)
32 31
33 32 MainGUI = BasicWindow()
34 33 MainGUI.setWorkSpaceGUI(WorkPathspace.dirComBox.currentText())
35 34 MainGUI.show()
36 35 sys.exit(app.exec_())
37 36
38 37
39 38 if __name__ == "__main__":
40 39 main()
@@ -1,635 +1,636
1 1 '''
2 2 @author: Juan C. Espinoza
3 3 '''
4 4
5 5 import time
6 6 import json
7 7 import numpy
8 8 import paho.mqtt.client as mqtt
9 9 import zmq
10 10 import datetime
11 11 from zmq.utils.monitor import recv_monitor_message
12 12 from functools import wraps
13 13 from threading import Thread
14 14 from multiprocessing import Process
15 15
16 16 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
17 17 from schainpy.model.data.jrodata import JROData
18 18 from schainpy.utils import log
19 19
20 20 MAXNUMX = 100
21 21 MAXNUMY = 100
22 22
23 23 class PrettyFloat(float):
24 24 def __repr__(self):
25 25 return '%.2f' % self
26 26
27 27 def roundFloats(obj):
28 28 if isinstance(obj, list):
29 29 return map(roundFloats, obj)
30 30 elif isinstance(obj, float):
31 31 return round(obj, 2)
32 32
33 33 def decimate(z, MAXNUMY):
34 34 dy = int(len(z[0])/MAXNUMY) + 1
35 35
36 36 return z[::, ::dy]
37 37
38 38 class throttle(object):
39 39 '''
40 40 Decorator that prevents a function from being called more than once every
41 41 time period.
42 42 To create a function that cannot be called more than once a minute, but
43 43 will sleep until it can be called:
44 44 @throttle(minutes=1)
45 45 def foo():
46 46 pass
47 47
48 48 for i in range(10):
49 49 foo()
50 50 print "This function has run %s times." % i
51 51 '''
52 52
53 53 def __init__(self, seconds=0, minutes=0, hours=0):
54 54 self.throttle_period = datetime.timedelta(
55 55 seconds=seconds, minutes=minutes, hours=hours
56 56 )
57 57
58 58 self.time_of_last_call = datetime.datetime.min
59 59
60 60 def __call__(self, fn):
61 61 @wraps(fn)
62 62 def wrapper(*args, **kwargs):
63 63 coerce = kwargs.pop('coerce', None)
64 64 if coerce:
65 65 self.time_of_last_call = datetime.datetime.now()
66 66 return fn(*args, **kwargs)
67 67 else:
68 68 now = datetime.datetime.now()
69 69 time_since_last_call = now - self.time_of_last_call
70 70 time_left = self.throttle_period - time_since_last_call
71 71
72 72 if time_left > datetime.timedelta(seconds=0):
73 73 return
74 74
75 75 self.time_of_last_call = datetime.datetime.now()
76 76 return fn(*args, **kwargs)
77 77
78 78 return wrapper
79 79
80 80 class Data(object):
81 81 '''
82 82 Object to hold data to be plotted
83 83 '''
84 84
85 85 def __init__(self, plottypes, throttle_value):
86 86 self.plottypes = plottypes
87 87 self.throttle = throttle_value
88 88 self.ended = False
89 89 self.localtime = False
90 90 self.__times = []
91 91 self.__heights = []
92 92
93 93 def __str__(self):
94 94 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
95 95 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
96 96
97 97 def __len__(self):
98 98 return len(self.__times)
99 99
100 100 def __getitem__(self, key):
101 101 if key not in self.data:
102 102 raise KeyError(log.error('Missing key: {}'.format(key)))
103 103
104 104 if 'spc' in key:
105 105 ret = self.data[key]
106 106 else:
107 107 ret = numpy.array([self.data[key][x] for x in self.times])
108 108 if ret.ndim > 1:
109 109 ret = numpy.swapaxes(ret, 0, 1)
110 110 return ret
111 111
112 112 def __contains__(self, key):
113 113 return key in self.data
114 114
115 115 def setup(self):
116 116 '''
117 117 Configure object
118 118 '''
119 119
120 120 self.ended = False
121 121 self.data = {}
122 122 self.__times = []
123 123 self.__heights = []
124 124 self.__all_heights = set()
125 125 for plot in self.plottypes:
126 126 if 'snr' in plot:
127 127 plot = 'snr'
128 128 self.data[plot] = {}
129 129
130 130 def shape(self, key):
131 131 '''
132 132 Get the shape of the one-element data for the given key
133 133 '''
134 134
135 135 if len(self.data[key]):
136 136 if 'spc' in key:
137 137 return self.data[key].shape
138 138 return self.data[key][self.__times[0]].shape
139 139 return (0,)
140 140
141 141 def update(self, dataOut, tm):
142 142 '''
143 143 Update data object with new dataOut
144 144 '''
145 145
146 146 if tm in self.__times:
147 147 return
148 148
149 149 self.parameters = getattr(dataOut, 'parameters', [])
150 self.pairs = dataOut.pairsList
150 if hasattr(dataOut, 'pairsList'):
151 self.pairs = dataOut.pairsList
151 152 self.channels = dataOut.channelList
152 153 self.interval = dataOut.getTimeInterval()
153 154 self.localtime = dataOut.useLocalTime
154 155 if 'spc' in self.plottypes or 'cspc' in self.plottypes:
155 156 self.xrange = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
156 157 self.__heights.append(dataOut.heightList)
157 158 self.__all_heights.update(dataOut.heightList)
158 159 self.__times.append(tm)
159 160
160 161 for plot in self.plottypes:
161 162 if plot == 'spc':
162 163 z = dataOut.data_spc/dataOut.normFactor
163 164 self.data[plot] = 10*numpy.log10(z)
164 165 if plot == 'cspc':
165 166 self.data[plot] = dataOut.data_cspc
166 167 if plot == 'noise':
167 168 self.data[plot][tm] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
168 169 if plot == 'rti':
169 170 self.data[plot][tm] = dataOut.getPower()
170 171 if plot == 'snr_db':
171 172 self.data['snr'][tm] = dataOut.data_SNR
172 173 if plot == 'snr':
173 174 self.data[plot][tm] = 10*numpy.log10(dataOut.data_SNR)
174 175 if plot == 'dop':
175 176 self.data[plot][tm] = 10*numpy.log10(dataOut.data_DOP)
176 177 if plot == 'mean':
177 178 self.data[plot][tm] = dataOut.data_MEAN
178 179 if plot == 'std':
179 180 self.data[plot][tm] = dataOut.data_STD
180 181 if plot == 'coh':
181 182 self.data[plot][tm] = dataOut.getCoherence()
182 183 if plot == 'phase':
183 184 self.data[plot][tm] = dataOut.getCoherence(phase=True)
184 185 if plot == 'output':
185 186 self.data[plot][tm] = dataOut.data_output
186 187 if plot == 'param':
187 188 self.data[plot][tm] = dataOut.data_param
188 189
189 190 def normalize_heights(self):
190 191 '''
191 192 Ensure same-dimension of the data for different heighList
192 193 '''
193 194
194 195 H = numpy.array(list(self.__all_heights))
195 196 H.sort()
196 197 for key in self.data:
197 198 shape = self.shape(key)[:-1] + H.shape
198 199 for tm, obj in self.data[key].items():
199 200 h = self.__heights[self.__times.index(tm)]
200 201 if H.size == h.size:
201 202 continue
202 203 index = numpy.where(numpy.in1d(H, h))[0]
203 204 dummy = numpy.zeros(shape) + numpy.nan
204 205 if len(shape) == 2:
205 206 dummy[:, index] = obj
206 207 else:
207 208 dummy[index] = obj
208 209 self.data[key][tm] = dummy
209 210
210 211 self.__heights = [H for tm in self.__times]
211 212
212 213 def jsonify(self, decimate=False):
213 214 '''
214 215 Convert data to json
215 216 '''
216 217
217 218 ret = {}
218 219 tm = self.times[-1]
219 220
220 221 for key, value in self.data:
221 222 if key in ('spc', 'cspc'):
222 223 ret[key] = roundFloats(self.data[key].to_list())
223 224 else:
224 225 ret[key] = roundFloats(self.data[key][tm].to_list())
225 226
226 227 ret['timestamp'] = tm
227 228 ret['interval'] = self.interval
228 229
229 230 @property
230 231 def times(self):
231 232 '''
232 233 Return the list of times of the current data
233 234 '''
234 235
235 236 ret = numpy.array(self.__times)
236 237 ret.sort()
237 238 return ret
238 239
239 240 @property
240 241 def heights(self):
241 242 '''
242 243 Return the list of heights of the current data
243 244 '''
244 245
245 246 return numpy.array(self.__heights[-1])
246 247
247 248 class PublishData(Operation):
248 249 '''
249 250 Operation to send data over zmq.
250 251 '''
251 252
252 253 __attrs__ = ['host', 'port', 'delay', 'zeromq', 'mqtt', 'verbose']
253 254
254 255 def __init__(self, **kwargs):
255 256 """Inicio."""
256 257 Operation.__init__(self, **kwargs)
257 258 self.isConfig = False
258 259 self.client = None
259 260 self.zeromq = None
260 261 self.mqtt = None
261 262
262 263 def on_disconnect(self, client, userdata, rc):
263 264 if rc != 0:
264 265 log.warning('Unexpected disconnection.')
265 266 self.connect()
266 267
267 268 def connect(self):
268 269 log.warning('trying to connect')
269 270 try:
270 271 self.client.connect(
271 272 host=self.host,
272 273 port=self.port,
273 274 keepalive=60*10,
274 275 bind_address='')
275 276 self.client.loop_start()
276 277 # self.client.publish(
277 278 # self.topic + 'SETUP',
278 279 # json.dumps(setup),
279 280 # retain=True
280 281 # )
281 282 except:
282 283 log.error('MQTT Conection error.')
283 284 self.client = False
284 285
285 286 def setup(self, port=1883, username=None, password=None, clientId="user", zeromq=1, verbose=True, **kwargs):
286 287 self.counter = 0
287 288 self.topic = kwargs.get('topic', 'schain')
288 289 self.delay = kwargs.get('delay', 0)
289 290 self.plottype = kwargs.get('plottype', 'spectra')
290 291 self.host = kwargs.get('host', "10.10.10.82")
291 292 self.port = kwargs.get('port', 3000)
292 293 self.clientId = clientId
293 294 self.cnt = 0
294 295 self.zeromq = zeromq
295 296 self.mqtt = kwargs.get('plottype', 0)
296 297 self.client = None
297 298 self.verbose = verbose
298 299 setup = []
299 300 if mqtt is 1:
300 301 self.client = mqtt.Client(
301 302 client_id=self.clientId + self.topic + 'SCHAIN',
302 303 clean_session=True)
303 304 self.client.on_disconnect = self.on_disconnect
304 305 self.connect()
305 306 for plot in self.plottype:
306 307 setup.append({
307 308 'plot': plot,
308 309 'topic': self.topic + plot,
309 310 'title': getattr(self, plot + '_' + 'title', False),
310 311 'xlabel': getattr(self, plot + '_' + 'xlabel', False),
311 312 'ylabel': getattr(self, plot + '_' + 'ylabel', False),
312 313 'xrange': getattr(self, plot + '_' + 'xrange', False),
313 314 'yrange': getattr(self, plot + '_' + 'yrange', False),
314 315 'zrange': getattr(self, plot + '_' + 'zrange', False),
315 316 })
316 317 if zeromq is 1:
317 318 context = zmq.Context()
318 319 self.zmq_socket = context.socket(zmq.PUSH)
319 320 server = kwargs.get('server', 'zmq.pipe')
320 321
321 322 if 'tcp://' in server:
322 323 address = server
323 324 else:
324 325 address = 'ipc:///tmp/%s' % server
325 326
326 327 self.zmq_socket.connect(address)
327 328 time.sleep(1)
328 329
329 330
330 331 def publish_data(self):
331 332 self.dataOut.finished = False
332 333 if self.mqtt is 1:
333 334 yData = self.dataOut.heightList[:2].tolist()
334 335 if self.plottype == 'spectra':
335 336 data = getattr(self.dataOut, 'data_spc')
336 337 z = data/self.dataOut.normFactor
337 338 zdB = 10*numpy.log10(z)
338 339 xlen, ylen = zdB[0].shape
339 340 dx = int(xlen/MAXNUMX) + 1
340 341 dy = int(ylen/MAXNUMY) + 1
341 342 Z = [0 for i in self.dataOut.channelList]
342 343 for i in self.dataOut.channelList:
343 344 Z[i] = zdB[i][::dx, ::dy].tolist()
344 345 payload = {
345 346 'timestamp': self.dataOut.utctime,
346 347 'data': roundFloats(Z),
347 348 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
348 349 'interval': self.dataOut.getTimeInterval(),
349 350 'type': self.plottype,
350 351 'yData': yData
351 352 }
352 353
353 354 elif self.plottype in ('rti', 'power'):
354 355 data = getattr(self.dataOut, 'data_spc')
355 356 z = data/self.dataOut.normFactor
356 357 avg = numpy.average(z, axis=1)
357 358 avgdB = 10*numpy.log10(avg)
358 359 xlen, ylen = z[0].shape
359 360 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
360 361 AVG = [0 for i in self.dataOut.channelList]
361 362 for i in self.dataOut.channelList:
362 363 AVG[i] = avgdB[i][::dy].tolist()
363 364 payload = {
364 365 'timestamp': self.dataOut.utctime,
365 366 'data': roundFloats(AVG),
366 367 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
367 368 'interval': self.dataOut.getTimeInterval(),
368 369 'type': self.plottype,
369 370 'yData': yData
370 371 }
371 372 elif self.plottype == 'noise':
372 373 noise = self.dataOut.getNoise()/self.dataOut.normFactor
373 374 noisedB = 10*numpy.log10(noise)
374 375 payload = {
375 376 'timestamp': self.dataOut.utctime,
376 377 'data': roundFloats(noisedB.reshape(-1, 1).tolist()),
377 378 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
378 379 'interval': self.dataOut.getTimeInterval(),
379 380 'type': self.plottype,
380 381 'yData': yData
381 382 }
382 383 elif self.plottype == 'snr':
383 384 data = getattr(self.dataOut, 'data_SNR')
384 385 avgdB = 10*numpy.log10(data)
385 386
386 387 ylen = data[0].size
387 388 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
388 389 AVG = [0 for i in self.dataOut.channelList]
389 390 for i in self.dataOut.channelList:
390 391 AVG[i] = avgdB[i][::dy].tolist()
391 392 payload = {
392 393 'timestamp': self.dataOut.utctime,
393 394 'data': roundFloats(AVG),
394 395 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
395 396 'type': self.plottype,
396 397 'yData': yData
397 398 }
398 399 else:
399 400 print "Tipo de grafico invalido"
400 401 payload = {
401 402 'data': 'None',
402 403 'timestamp': 'None',
403 404 'type': None
404 405 }
405 406
406 407 self.client.publish(self.topic + self.plottype, json.dumps(payload), qos=0)
407 408
408 409 if self.zeromq is 1:
409 410 if self.verbose:
410 411 log.log(
411 412 'Sending {} - {}'.format(self.dataOut.type, self.dataOut.datatime),
412 413 self.name
413 414 )
414 415 self.zmq_socket.send_pyobj(self.dataOut)
415 416
416 417 def run(self, dataOut, **kwargs):
417 418 self.dataOut = dataOut
418 419 if not self.isConfig:
419 420 self.setup(**kwargs)
420 421 self.isConfig = True
421 422
422 423 self.publish_data()
423 424 time.sleep(self.delay)
424 425
425 426 def close(self):
426 427 if self.zeromq is 1:
427 428 self.dataOut.finished = True
428 429 self.zmq_socket.send_pyobj(self.dataOut)
429 430 time.sleep(0.1)
430 431 self.zmq_socket.close()
431 432 if self.client:
432 433 self.client.loop_stop()
433 434 self.client.disconnect()
434 435
435 436
436 437 class ReceiverData(ProcessingUnit):
437 438
438 439 __attrs__ = ['server']
439 440
440 441 def __init__(self, **kwargs):
441 442
442 443 ProcessingUnit.__init__(self, **kwargs)
443 444
444 445 self.isConfig = False
445 446 server = kwargs.get('server', 'zmq.pipe')
446 447 if 'tcp://' in server:
447 448 address = server
448 449 else:
449 450 address = 'ipc:///tmp/%s' % server
450 451
451 452 self.address = address
452 453 self.dataOut = JROData()
453 454
454 455 def setup(self):
455 456
456 457 self.context = zmq.Context()
457 458 self.receiver = self.context.socket(zmq.PULL)
458 459 self.receiver.bind(self.address)
459 460 time.sleep(0.5)
460 461 log.success('ReceiverData from {}'.format(self.address))
461 462
462 463
463 464 def run(self):
464 465
465 466 if not self.isConfig:
466 467 self.setup()
467 468 self.isConfig = True
468 469
469 470 self.dataOut = self.receiver.recv_pyobj()
470 471 log.log('{} - {}'.format(self.dataOut.type,
471 472 self.dataOut.datatime.ctime(),),
472 473 'Receiving')
473 474
474 475
475 476 class PlotterReceiver(ProcessingUnit, Process):
476 477
477 478 throttle_value = 5
478 479 __attrs__ = ['server', 'plottypes', 'realtime', 'localtime', 'throttle']
479 480
480 481 def __init__(self, **kwargs):
481 482
482 483 ProcessingUnit.__init__(self, **kwargs)
483 484 Process.__init__(self)
484 485 self.mp = False
485 486 self.isConfig = False
486 487 self.isWebConfig = False
487 488 self.connections = 0
488 489 server = kwargs.get('server', 'zmq.pipe')
489 490 plot_server = kwargs.get('plot_server', 'zmq.web')
490 491 if 'tcp://' in server:
491 492 address = server
492 493 else:
493 494 address = 'ipc:///tmp/%s' % server
494 495
495 496 if 'tcp://' in plot_server:
496 497 plot_address = plot_server
497 498 else:
498 499 plot_address = 'ipc:///tmp/%s' % plot_server
499 500
500 501 self.address = address
501 502 self.plot_address = plot_address
502 self.plottypes = [s.strip() for s in kwargs.get('plottypes', 'rti').split(',')]
503 self.plottypes = [s.strip() for s in kwargs.get('plottypes', '').split(',') if s]
503 504 self.realtime = kwargs.get('realtime', False)
504 505 self.localtime = kwargs.get('localtime', True)
505 506 self.throttle_value = kwargs.get('throttle', 5)
506 507 self.sendData = self.initThrottle(self.throttle_value)
507 508 self.dates = []
508 509 self.setup()
509 510
510 511 def setup(self):
511 512
512 513 self.data = Data(self.plottypes, self.throttle_value)
513 514 self.isConfig = True
514 515
515 516 def event_monitor(self, monitor):
516 517
517 518 events = {}
518 519
519 520 for name in dir(zmq):
520 521 if name.startswith('EVENT_'):
521 522 value = getattr(zmq, name)
522 523 events[value] = name
523 524
524 525 while monitor.poll():
525 526 evt = recv_monitor_message(monitor)
526 527 if evt['event'] == 32:
527 528 self.connections += 1
528 529 if evt['event'] == 512:
529 530 pass
530 531
531 532 evt.update({'description': events[evt['event']]})
532 533
533 534 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
534 535 break
535 536 monitor.close()
536 537 print('event monitor thread done!')
537 538
538 539 def initThrottle(self, throttle_value):
539 540
540 541 @throttle(seconds=throttle_value)
541 542 def sendDataThrottled(fn_sender, data):
542 543 fn_sender(data)
543 544
544 545 return sendDataThrottled
545 546
546 547 def send(self, data):
547 548 log.success('Sending {}'.format(data), self.name)
548 549 self.sender.send_pyobj(data)
549 550
550 551 def run(self):
551 552
552 553 log.success(
553 554 'Starting from {}'.format(self.address),
554 555 self.name
555 556 )
556 557
557 558 self.context = zmq.Context()
558 559 self.receiver = self.context.socket(zmq.PULL)
559 560 self.receiver.bind(self.address)
560 561 monitor = self.receiver.get_monitor_socket()
561 562 self.sender = self.context.socket(zmq.PUB)
562 563 if self.realtime:
563 564 self.sender_web = self.context.socket(zmq.PUB)
564 565 self.sender_web.connect(self.plot_address)
565 566 time.sleep(1)
566 567
567 568 if 'server' in self.kwargs:
568 569 self.sender.bind("ipc:///tmp/{}.plots".format(self.kwargs['server']))
569 570 else:
570 571 self.sender.bind("ipc:///tmp/zmq.plots")
571 572
572 573 time.sleep(2)
573 574
574 575 t = Thread(target=self.event_monitor, args=(monitor,))
575 576 t.start()
576 577
577 578 while True:
578 579 dataOut = self.receiver.recv_pyobj()
579 580 if not dataOut.flagNoData:
580 581 if dataOut.type == 'Parameters':
581 582 tm = dataOut.utctimeInit
582 583 else:
583 584 tm = dataOut.utctime
584 585 if dataOut.useLocalTime:
585 586 if not self.localtime:
586 587 tm += time.timezone
587 588 dt = datetime.datetime.fromtimestamp(tm).date()
588 589 else:
589 590 if self.localtime:
590 591 tm -= time.timezone
591 592 dt = datetime.datetime.utcfromtimestamp(tm).date()
592 593 coerce = False
593 594 if dt not in self.dates:
594 595 if self.data:
595 596 self.data.ended = True
596 597 self.send(self.data)
597 598 coerce = True
598 599 self.data.setup()
599 600 self.dates.append(dt)
600 601
601 602 self.data.update(dataOut, tm)
602 603
603 604 if dataOut.finished is True:
604 605 self.connections -= 1
605 606 if self.connections == 0 and dt in self.dates:
606 607 self.data.ended = True
607 608 self.send(self.data)
608 609 self.data.setup()
609 610 else:
610 611 if self.realtime:
611 612 self.send(self.data)
612 613 # self.sender_web.send_string(self.data.jsonify())
613 614 else:
614 615 self.sendData(self.send, self.data, coerce=coerce)
615 616 coerce = False
616 617
617 618 return
618 619
619 620 def sendToWeb(self):
620 621
621 622 if not self.isWebConfig:
622 623 context = zmq.Context()
623 624 sender_web_config = context.socket(zmq.PUB)
624 625 if 'tcp://' in self.plot_address:
625 626 dum, address, port = self.plot_address.split(':')
626 627 conf_address = '{}:{}:{}'.format(dum, address, int(port)+1)
627 628 else:
628 629 conf_address = self.plot_address + '.config'
629 630 sender_web_config.bind(conf_address)
630 631 time.sleep(1)
631 632 for kwargs in self.operationKwargs.values():
632 633 if 'plot' in kwargs:
633 634 log.success('[Sending] Config data to web for {}'.format(kwargs['code'].upper()))
634 635 sender_web_config.send_string(json.dumps(kwargs))
635 636 self.isWebConfig = True
@@ -1,69 +1,69
1 1 '''
2 2 Created on Jul 16, 2014
3 3
4 4 @author: Miguel Urco
5 5 '''
6 6
7 7 import os
8 8 from setuptools import setup, Extension
9 9 from setuptools.command.build_ext import build_ext as _build_ext
10 10 from schainpy import __version__
11 11
12 12 class build_ext(_build_ext):
13 13 def finalize_options(self):
14 14 _build_ext.finalize_options(self)
15 15 # Prevent numpy from thinking it is still in its setup process:
16 16 __builtins__.__NUMPY_SETUP__ = False
17 17 import numpy
18 18 self.include_dirs.append(numpy.get_include())
19 19
20 setup(name="schainpy",
21 version=__version__,
22 description="Python tools to read, write and process Jicamarca data",
23 author="Miguel Urco",
24 author_email="miguel.urco@jro.igp.gob.pe",
25 url="http://jro.igp.gob.pe",
26 packages={'schainpy',
20 setup(name = "schainpy",
21 version = __version__,
22 description = "Python tools to read, write and process Jicamarca data",
23 author = "Miguel Urco",
24 author_email = "miguel.urco@jro.igp.gob.pe",
25 url = "http://jro.igp.gob.pe",
26 packages = {'schainpy',
27 27 'schainpy.model',
28 28 'schainpy.model.data',
29 29 'schainpy.model.graphics',
30 30 'schainpy.model.io',
31 31 'schainpy.model.proc',
32 32 'schainpy.model.serializer',
33 33 'schainpy.model.utils',
34 34 'schainpy.utils',
35 35 'schainpy.gui',
36 36 'schainpy.gui.figures',
37 37 'schainpy.gui.viewcontroller',
38 38 'schainpy.gui.viewer',
39 'schainpy.gui.viewer.windows'},
40 ext_package='schainpy',
41 py_modules=[''],
42 package_data={'': ['schain.conf.template'],
43 'schainpy.gui.figures': ['*.png', '*.jpg'],
44 },
45 include_package_data=False,
46 scripts=['schainpy/gui/schainGUI'],
47 ext_modules=[
48 Extension("cSchain", ["schainpy/model/proc/extensions.c"]
49 )],
50 entry_points={
39 'schainpy.gui.viewer.windows',
40 'schainpy.cli'},
41 ext_package = 'schainpy',
42 package_data = {'': ['schain.conf.template'],
43 'schainpy.gui.figures': ['*.png', '*.jpg'],
44 },
45 include_package_data = False,
46 scripts = ['schainpy/gui/schainGUI'],
47 ext_modules = [
48 Extension("cSchain", ["schainpy/model/proc/extensions.c"])
49 ],
50 entry_points = {
51 51 'console_scripts': [
52 'schain = schaincli.cli:main',
52 'schain = schainpy.cli.cli:main',
53 53 ],
54 54 },
55 cmdclass={'build_ext': build_ext},
56 setup_requires=["numpy >= 1.11.2"],
57 install_requires=[
55 cmdclass = {'build_ext': build_ext},
56 setup_requires = ["numpy >= 1.11.2"],
57 install_requires = [
58 58 "scipy >= 0.14.0",
59 59 "h5py >= 2.2.1",
60 60 "matplotlib >= 2.0.0",
61 61 "pyfits >= 3.4",
62 62 "paramiko >= 2.1.2",
63 63 "paho-mqtt >= 1.2",
64 64 "zmq",
65 65 "fuzzywuzzy",
66 66 "click",
67 67 "python-Levenshtein"
68 ],
69 )
68 ],
69 )
General Comments 0
You need to be logged in to leave comments. Login now