##// END OF EJS Templates
Merge branch 'schain_alarm' of http://jro-dev.igp.gob.pe/rhodecode/schain into v2.3
jespinoza -
r1131:e8ab492363ef merge
parent child
Show More
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
@@ -1,395 +1,498
1 1 """The admin module contains all administrative classes relating to the schain python api.
2 2
3 3 The main role of this module is to send some reports. It contains a
4 4 notification class and a standard error handing class.
5 5
6 6 $Id: admin.py 3966 2015-12-01 14:32:29Z miguel.urco $
7 7 """
8 import os, sys
8 import os
9 import sys
10 import time
9 11 import traceback
10 12 import smtplib
11 13 import ConfigParser
12 14 import StringIO
13
15 from threading import Thread
16 from multiprocessing import Process
14 17 from email.mime.text import MIMEText
15 18 from email.mime.application import MIMEApplication
16 19 from email.mime.multipart import MIMEMultipart
17 20
18 class SchainConfigure():
21 from schainpy.utils import log
22 from schainpy.model.graphics.jroplot_data import popup
23
24 def get_path():
25 '''
26 Return schainpy path
27 '''
28
29 try:
30 root = __file__
31 if os.path.islink(root):
32 root = os.path.realpath(root)
33
34 return os.path.dirname(os.path.abspath(root))
35 except:
36 log.error('I am sorry, but something is wrong... __file__ not found')
37
38 class Alarm(Process):
39 '''
40 modes:
41 0 - All
42 1 - Sound alarm
43 2 - Send email
44 3 - Popup message
45 4 - Send to alarm system TODO
46 '''
47
48 def __init__(self, modes=[1], **kwargs):
49 Process.__init__(self)
50 self.modes = modes
51 self.kwargs = kwargs
52
53 @staticmethod
54 def play_sound():
55 sound = os.path.join(get_path(), 'alarm1.oga')
56 if os.path.exists(sound):
57 for __ in range(2):
58 os.system('paplay {}'.format(sound))
59 time.sleep(0.5)
60 else:
61 log.warning('Unable to play alarm, sound file not found', 'ADMIN')
62
63 @staticmethod
64 def send_email(**kwargs):
65 notifier = SchainNotify()
66 notifier.notify(**kwargs)
67
68 @staticmethod
69 def show_popup(message='Error'):
70 popup(message)
71
72 @staticmethod
73 def send_alarm():
74 pass
75
76 @staticmethod
77 def get_kwargs(kwargs, keys):
78 ret = {}
79 for key in keys:
80 ret[key] = kwargs[key]
81 return ret
82
83 def run(self):
84 tasks = {
85 1 : self.send_email,
86 2 : self.play_sound,
87 3 : self.show_popup,
88 4 : self.send_alarm,
89 }
90
91 tasks_args = {
92 1: ['email', 'message', 'subject', 'subtitle', 'filename'],
93 2: [],
94 3: ['message'],
95 4: [],
96 }
97 procs = []
98 for mode in self.modes:
99 if 0 in self.modes:
100 for x in tasks:
101 t = Thread(target=tasks[x], kwargs=self.get_kwargs(self.kwargs, tasks_args[x]))
102 t.start()
103 procs.append(t)
104 break
105 else:
106 t = Thread(target=tasks[mode], kwargs=self.get_kwargs(self.kwargs, tasks_args[mode]))
107 t.start()
108 procs.append(t)
109 for t in procs:
110 t.join()
111
112
113 class SchainConfigure():
19 114
20 __DEFAULT_ADMINISTRATOR_EMAIL = ""
115 __DEFAULT_ADMINISTRATOR_EMAIL = "juan.espinoza@jro.igp.gob.pe"
21 116 __DEFAULT_EMAIL_SERVER = "jro-zimbra.igp.gob.pe"
22 117 __DEFAULT_SENDER_EMAIL = "notifier-schain@jro.igp.gob.pe"
23 118 __DEFAULT_SENDER_PASS = ""
24 119
25 120 __SCHAIN_ADMINISTRATOR_EMAIL = "CONTACT"
26 121 __SCHAIN_EMAIL_SERVER = "MAILSERVER"
27 122 __SCHAIN_SENDER_EMAIL = "MAILSERVER_ACCOUNT"
28 123 __SCHAIN_SENDER_PASS = "MAILSERVER_PASSWORD"
29 124
30 125 def __init__(self, initFile = None):
31 126
32 127 # Set configuration file
33 128 if (initFile == None):
34 129 self.__confFilePath = "/etc/schain.conf"
35 130 else:
36 131 self.__confFilePath = initFile
37 132
38 133 # open configuration file
39 134 try:
40 135 self.__confFile = open(self.__confFilePath, "r")
41 136 except IOError:
42 137 # can't read from file - use all hard-coded values
43 138 self.__initFromHardCode()
44 139 return
45 140
46 141 # create Parser using standard module ConfigParser
47 142 self.__parser = ConfigParser.ConfigParser()
48 143
49 144 # read conf file into a StringIO with "[madrigal]\n" section heading prepended
50 145 strConfFile = StringIO.StringIO("[schain]\n" + self.__confFile.read())
51 146
52 147 # parse StringIO configuration file
53 148 self.__parser.readfp(strConfFile)
54 149
55 150 # read information from configuration file
56 151 self.__readConfFile()
57 152
58 153 # close conf file
59 154 self.__confFile.close()
60 155
61 156
62 157 def __initFromHardCode(self):
63 158
64 159 self.__sender_email = self.__DEFAULT_SENDER_EMAIL
65 160 self.__sender_pass = self.__DEFAULT_SENDER_PASS
66 161 self.__admin_email = self.__DEFAULT_ADMINISTRATOR_EMAIL
67 162 self.__email_server = self.__DEFAULT_EMAIL_SERVER
68 163
69 164 def __readConfFile(self):
70 165 """__readConfFile is a private helper function that reads information from the parsed config file.
71 166
72 167 Inputs: None
73 168
74 169 Returns: Void.
75 170
76 171 Affects: Initializes class member variables that are found in the config file.
77 172
78 173 Exceptions: MadrigalError thrown if any key not found.
79 174 """
80 175
81 176 # get the sender email
82 177 try:
83 178 self.__sender_email = self.__parser.get("schain", self.__SCHAIN_SENDER_EMAIL)
84 179 except:
85 180 self.__sender_email = self.__DEFAULT_SENDER_EMAIL
86 181
87 182 # get the sender password
88 183 try:
89 184 self.__sender_pass = self.__parser.get("schain", self.__SCHAIN_SENDER_PASS)
90 185 except:
91 186 self.__sender_pass = self.__DEFAULT_SENDER_PASS
92 187
93 188 # get the administrator email
94 189 try:
95 190 self.__admin_email = self.__parser.get("schain", self.__SCHAIN_ADMINISTRATOR_EMAIL)
96 191 except:
97 192 self.__admin_email = self.__DEFAULT_ADMINISTRATOR_EMAIL
98 193
99 194 # get the server email
100 195 try:
101 196 self.__email_server = self.__parser.get("schain", self.__SCHAIN_EMAIL_SERVER)
102 197 except:
103 198 self.__email_server = self.__DEFAULT_EMAIL_SERVER
104 199
105 200 def getEmailServer(self):
106 201
107 202 return self.__email_server
108 203
109 204 def getSenderEmail(self):
110 205
111 206 return self.__sender_email
112 207
113 208 def getSenderPass(self):
114 209
115 210 return self.__sender_pass
116 211
117 212 def getAdminEmail(self):
118 213
119 214 return self.__admin_email
120 215
121 216 class SchainNotify:
122 217 """SchainNotify is an object used to send messages to an administrator about a Schain software.
123 218
124 219 This object provides functions needed to send messages to an administrator about a Schain , for now
125 220 only sendAlert, which sends an email to the site administrator found is ADMIN_EMAIL
126 221
127 222 Usage example:
128 223
129 224 import schainpy.admin
130 225
131 226 try:
132 227
133 228 adminObj = schainpy.admin.SchainNotify()
134 229 adminObj.sendAlert('This is important!', 'Important Message')
135 230
136 231 except schainpy.admin.SchainError, e:
137 232
138 233 print e.getExceptionStr()
139 234
140 235
141 236 Non-standard Python modules used:
142 237 None
143 238
144 239 Exceptions thrown: None - Note that SchainNotify tries every trick it knows to avoid
145 240 throwing exceptions, since this is the class that will generally be called when there is a problem.
146 241
147 242 Change history:
148 243
149 244 Written by "Miguel Urco":mailto:miguel.urco@jro.igp.gob.pe Dec. 1, 2015
150 245 """
151 246
152 247 #constants
153 248
154 249 def __init__(self):
155 250 """__init__ initializes SchainNotify by getting some basic information from SchainDB and SchainSite.
156 251
157 252 Note that SchainNotify tries every trick it knows to avoid throwing exceptions, since
158 253 this is the class that will generally be called when there is a problem.
159 254
160 255 Inputs: Existing SchainDB object, by default = None.
161 256
162 257 Returns: void
163 258
164 259 Affects: Initializes self.__binDir.
165 260
166 261 Exceptions: None.
167 262 """
168 263
169 264 # note that the main configuration file is unavailable
170 265 # the best that can be done is send an email to root using localhost mailserver
171 266 confObj = SchainConfigure()
172 267
173 268 self.__emailFromAddress = confObj.getSenderEmail()
174 269 self.__emailPass = confObj.getSenderPass()
175 270 self.__emailToAddress = confObj.getAdminEmail()
176 271 self.__emailServer = confObj.getEmailServer()
177 272
178 273 def sendEmail(self, email_from, email_to, subject='Error running ...', message="", subtitle="", filename="", html_format=True):
179
274
180 275 if not email_to:
181 276 return 0
182 277
183 278 if not self.__emailServer:
184 279 return 0
185 280
281 log.success('Sending email to {}...'.format(email_to), 'System')
282
186 283 msg = MIMEMultipart()
187 284 msg['Subject'] = subject
188 285 msg['From'] = "(Python SChain API): " + email_from
189 286 msg['Reply-to'] = email_from
190 287 msg['To'] = email_to
191 288
192 289 # That is what u see if dont have an email reader:
193 290 msg.preamble = 'SChainPy'
194 291
195 292 if html_format:
196 293 message = "<h1> %s </h1>" %subject + "<h3>" + subtitle.replace("\n", "</h3><h3>\n") + "</h3>" + message.replace("\n", "<br>\n")
197 294 message = "<html>\n" + message + '</html>'
198 295
199 296 # This is the textual part:
200 297 part = MIMEText(message, "html")
201 298 else:
202 299 message = subject + "\n" + subtitle + "\n" + message
203 300 part = MIMEText(message)
204 301
205 302 msg.attach(part)
206 303
207 if os.path.isfile(filename):
304 if filename and os.path.isfile(filename):
208 305 # This is the binary part(The Attachment):
209 306 part = MIMEApplication(open(filename,"rb").read())
210 307 part.add_header('Content-Disposition',
211 308 'attachment',
212 309 filename=os.path.basename(filename))
213 310 msg.attach(part)
214 311
215 312 # Create an instance in SMTP server
216 313 try:
217 314 smtp = smtplib.SMTP(self.__emailServer)
218 315 except:
219 print "***** Could not connect to server %s *****" %self.__emailServer
316 log.error('Could not connect to server {}'.format(self.__emailServer), 'System')
220 317 return 0
221 318
222 319 # Start the server:
223 # smtp.ehlo()
320 # smtp.ehlo()
224 321 if self.__emailPass:
225 322 smtp.login(self.__emailFromAddress, self.__emailPass)
226 323
227 324 # Send the email
228 325 try:
229 326 smtp.sendmail(msg['From'], msg['To'], msg.as_string())
230 327 except:
231 print "***** Could not send the email to %s *****" %msg['To']
328 log.error('Could not send the email to {}'.format(msg['To']), 'System')
232 329 smtp.quit()
233 330 return 0
234 331
235 332 smtp.quit()
333
334 log.success('Email sent ', 'System')
236 335
237 336 return 1
238 337
239 338 def sendAlert(self, message, subject = "", subtitle="", filename=""):
240 339 """sendAlert sends an email with the given message and optional title.
241 340
242 341 Inputs: message (string), and optional title (string)
243 342
244 343 Returns: void
245 344
246 345 Affects: none
247 346
248 347 Exceptions: None.
249 348 """
250 349
251 350 if not self.__emailToAddress:
252 351 return 0
253 352
254 353 print "***** Sending alert to %s *****" %self.__emailToAddress
255 354 # set up message
256 355
257 356 sent=self.sendEmail(email_from=self.__emailFromAddress,
258 357 email_to=self.__emailToAddress,
259 358 subject=subject,
260 359 message=message,
261 360 subtitle=subtitle,
262 361 filename=filename)
263 362
264 363 if not sent:
265 364 return 0
266 365
267 print "***** Your system administrator has been notified *****"
268
269 366 return 1
270 367
271 368 def notify(self, email, message, subject = "", subtitle="", filename=""):
272 369 """notify sends an email with the given message and title to email.
273 370
274 371 Inputs: email (string), message (string), and subject (string)
275 372
276 373 Returns: void
277 374
278 375 Affects: none
279 376
280 377 Exceptions: None.
281 378 """
282 379
283 print "Notifying to %s ..." %email
284
285 self.sendEmail(email_from=self.__emailFromAddress,
286 email_to=email,
287 subject=subject,
288 message=message,
289 subtitle=subtitle,
290 filename=filename)
380 if email is None:
381 email = self.__emailToAddress
291 382
292 print "***** Your system administrator has been notified *****"
383 self.sendEmail(
384 email_from=self.__emailFromAddress,
385 email_to=email,
386 subject=subject,
387 message=message,
388 subtitle=subtitle,
389 filename=filename
390 )
391
293 392
294 393 class SchainError(Exception):
295 394 """SchainError is an exception class that is thrown for all known errors using Schain Py lib.
296 395
297 396 Usage example:
298 397
299 398 import sys, traceback
300 399 import schainpy.admin
301 400
302 401 try:
303 402
304 403 test = open('ImportantFile.txt', 'r')
305 404
306 405 except:
307 406
308 407 raise schainpy.admin.SchainError('ImportantFile.txt not opened!',
309 408 traceback.format_exception(sys.exc_info()[0],
310 409 sys.exc_info()[1],
311 410 sys.exc_info()[2]))
312 411 """
313 412
314 413
315 414 def __init__(self, strInterpretation, exceptionList=None):
316 415 """ __init__ gathers the interpretation string along with all information from sys.exc_info().
317 416
318 417 Inputs:
319 418 strIntepretation - A string representing the programmer's interpretation of
320 419 why the exception occurred
321 420
322 421 exceptionList - a list of strings completely describing the exception.
323 422 Generated by traceback.format_exception(sys.exc_info()[0],
324 423 sys.exc_info()[1],
325 424 sys.exc_info()[2])
326 425
327 426 Returns: Void.
328 427
329 428 Affects: Initializes class member variables _strInterp, _strExcList.
330 429
331 430 Exceptions: None.
332 431 """
333 432
334 433 if not exceptionList:
335 434 exceptionList = traceback.format_exception(sys.exc_info()[0],
336 435 sys.exc_info()[1],
337 436 sys.exc_info()[2])
338 437
339 438 self._strInterp = strInterpretation
340 439 self._strExcList = exceptionList
341 440
342 441
343 442 def getExceptionStr(self):
344 443 """ getExceptionStr returns a formatted string ready for printing completely describing the exception.
345 444
346 445 Inputs: None
347 446
348 447 Returns: A formatted string ready for printing completely describing the exception.
349 448
350 449 Affects: None
351 450
352 451 Exceptions: None.
353 452 """
354 453 excStr = ''
355 454 excStr = excStr + self._strInterp + '\n\n'
356 455
357 456 if self._strExcList != None:
358 457 for item in self._strExcList:
359 458 excStr = excStr + str(item) + '\n'
360 459
361 460 return excStr
362 461
363 462 def __str__(self):
364 463
365 464 return(self.getExceptionStr())
366 465
367 466
368 467 def getExceptionHtml(self):
369 468 """ getExceptionHtml returns an Html formatted string completely describing the exception.
370 469
371 470 Inputs: None
372 471
373 472 Returns: A formatted string ready for printing completely describing the exception.
374 473
375 474 Affects: None
376 475
377 476 Exceptions: None.
378 477 """
379 478
380 479 excStr = '<BR>The following Schain Python exception has occurred:\n<BR>'
381 480 excStr = excStr + self._strInterp + '\n<BR>\n'
382 481
383 482 if self._strExcList != None:
384 483 for item in self._strExcList:
385 484 excStr = excStr + str(item) + '\n<BR>'
386 485
387 486 return excStr
388 487
488 class SchainWarning(Exception):
489 pass
490
491
389 492 if __name__ == '__main__':
390 493
391 494 test = SchainNotify()
392 495
393 496 test.sendAlert('This is a message from the python module SchainNotify', 'Test from SchainNotify')
394 497
395 498 print 'Hopefully message sent - check.'
@@ -1,1323 +1,1330
1 1 '''
2 2 Created on September , 2012
3 3 @author:
4 4 '''
5 5
6 6 import sys
7 7 import ast
8 8 import datetime
9 9 import traceback
10 10 import math
11 11 import time
12 12 from multiprocessing import Process, cpu_count
13 13
14 14 from xml.etree.ElementTree import ElementTree, Element, SubElement, tostring
15 15 from xml.dom import minidom
16 16
17 17 import schainpy
18 import schainpy.admin
18 from schainpy.admin import Alarm, SchainWarning
19 19 from schainpy.model import *
20 20 from schainpy.utils import log
21 21
22 22 DTYPES = {
23 23 'Voltage': '.r',
24 24 'Spectra': '.pdata'
25 25 }
26 26
27 27
28 28 def MPProject(project, n=cpu_count()):
29 29 '''
30 30 Project wrapper to run schain in n processes
31 31 '''
32 32
33 33 rconf = project.getReadUnitObj()
34 34 op = rconf.getOperationObj('run')
35 35 dt1 = op.getParameterValue('startDate')
36 36 dt2 = op.getParameterValue('endDate')
37 37 tm1 = op.getParameterValue('startTime')
38 38 tm2 = op.getParameterValue('endTime')
39 39 days = (dt2 - dt1).days
40 40
41 41 for day in range(days + 1):
42 42 skip = 0
43 43 cursor = 0
44 44 processes = []
45 45 dt = dt1 + datetime.timedelta(day)
46 46 dt_str = dt.strftime('%Y/%m/%d')
47 47 reader = JRODataReader()
48 48 paths, files = reader.searchFilesOffLine(path=rconf.path,
49 49 startDate=dt,
50 50 endDate=dt,
51 51 startTime=tm1,
52 52 endTime=tm2,
53 53 ext=DTYPES[rconf.datatype])
54 54 nFiles = len(files)
55 55 if nFiles == 0:
56 56 continue
57 57 skip = int(math.ceil(nFiles / n))
58 58 while nFiles > cursor * skip:
59 59 rconf.update(startDate=dt_str, endDate=dt_str, cursor=cursor,
60 60 skip=skip)
61 61 p = project.clone()
62 62 p.start()
63 63 processes.append(p)
64 64 cursor += 1
65 65
66 66 def beforeExit(exctype, value, trace):
67 67 for process in processes:
68 68 process.terminate()
69 69 process.join()
70 70 print traceback.print_tb(trace)
71 71
72 72 sys.excepthook = beforeExit
73 73
74 74 for process in processes:
75 75 process.join()
76 76 process.terminate()
77 77
78 78 time.sleep(3)
79 79
80 80
81 81 class ParameterConf():
82 82
83 83 id = None
84 84 name = None
85 85 value = None
86 86 format = None
87 87
88 88 __formated_value = None
89 89
90 90 ELEMENTNAME = 'Parameter'
91 91
92 92 def __init__(self):
93 93
94 94 self.format = 'str'
95 95
96 96 def getElementName(self):
97 97
98 98 return self.ELEMENTNAME
99 99
100 100 def getValue(self):
101 101
102 102 value = self.value
103 103 format = self.format
104 104
105 105 if self.__formated_value != None:
106 106
107 107 return self.__formated_value
108 108
109 109 if format == 'obj':
110 110 return value
111 111
112 112 if format == 'str':
113 113 self.__formated_value = str(value)
114 114 return self.__formated_value
115 115
116 116 if value == '':
117 117 raise ValueError, '%s: This parameter value is empty' % self.name
118 118
119 119 if format == 'list':
120 120 strList = value.split(',')
121 121
122 122 self.__formated_value = strList
123 123
124 124 return self.__formated_value
125 125
126 126 if format == 'intlist':
127 127 '''
128 128 Example:
129 129 value = (0,1,2)
130 130 '''
131 131
132 132 new_value = ast.literal_eval(value)
133 133
134 134 if type(new_value) not in (tuple, list):
135 135 new_value = [int(new_value)]
136 136
137 137 self.__formated_value = new_value
138 138
139 139 return self.__formated_value
140 140
141 141 if format == 'floatlist':
142 142 '''
143 143 Example:
144 144 value = (0.5, 1.4, 2.7)
145 145 '''
146 146
147 147 new_value = ast.literal_eval(value)
148 148
149 149 if type(new_value) not in (tuple, list):
150 150 new_value = [float(new_value)]
151 151
152 152 self.__formated_value = new_value
153 153
154 154 return self.__formated_value
155 155
156 156 if format == 'date':
157 157 strList = value.split('/')
158 158 intList = [int(x) for x in strList]
159 159 date = datetime.date(intList[0], intList[1], intList[2])
160 160
161 161 self.__formated_value = date
162 162
163 163 return self.__formated_value
164 164
165 165 if format == 'time':
166 166 strList = value.split(':')
167 167 intList = [int(x) for x in strList]
168 168 time = datetime.time(intList[0], intList[1], intList[2])
169 169
170 170 self.__formated_value = time
171 171
172 172 return self.__formated_value
173 173
174 174 if format == 'pairslist':
175 175 '''
176 176 Example:
177 177 value = (0,1),(1,2)
178 178 '''
179 179
180 180 new_value = ast.literal_eval(value)
181 181
182 182 if type(new_value) not in (tuple, list):
183 183 raise ValueError, '%s has to be a tuple or list of pairs' % value
184 184
185 185 if type(new_value[0]) not in (tuple, list):
186 186 if len(new_value) != 2:
187 187 raise ValueError, '%s has to be a tuple or list of pairs' % value
188 188 new_value = [new_value]
189 189
190 190 for thisPair in new_value:
191 191 if len(thisPair) != 2:
192 192 raise ValueError, '%s has to be a tuple or list of pairs' % value
193 193
194 194 self.__formated_value = new_value
195 195
196 196 return self.__formated_value
197 197
198 198 if format == 'multilist':
199 199 '''
200 200 Example:
201 201 value = (0,1,2),(3,4,5)
202 202 '''
203 203 multiList = ast.literal_eval(value)
204 204
205 205 if type(multiList[0]) == int:
206 206 multiList = ast.literal_eval('(' + value + ')')
207 207
208 208 self.__formated_value = multiList
209 209
210 210 return self.__formated_value
211 211
212 212 if format == 'bool':
213 213 value = int(value)
214 214
215 215 if format == 'int':
216 216 value = float(value)
217 217
218 218 format_func = eval(format)
219 219
220 220 self.__formated_value = format_func(value)
221 221
222 222 return self.__formated_value
223 223
224 224 def updateId(self, new_id):
225 225
226 226 self.id = str(new_id)
227 227
228 228 def setup(self, id, name, value, format='str'):
229 229 self.id = str(id)
230 230 self.name = name
231 231 if format == 'obj':
232 232 self.value = value
233 233 else:
234 234 self.value = str(value)
235 235 self.format = str.lower(format)
236 236
237 237 self.getValue()
238 238
239 239 return 1
240 240
241 241 def update(self, name, value, format='str'):
242 242
243 243 self.name = name
244 244 self.value = str(value)
245 245 self.format = format
246 246
247 247 def makeXml(self, opElement):
248 248 if self.name not in ('queue',):
249 249 parmElement = SubElement(opElement, self.ELEMENTNAME)
250 250 parmElement.set('id', str(self.id))
251 251 parmElement.set('name', self.name)
252 252 parmElement.set('value', self.value)
253 253 parmElement.set('format', self.format)
254 254
255 255 def readXml(self, parmElement):
256 256
257 257 self.id = parmElement.get('id')
258 258 self.name = parmElement.get('name')
259 259 self.value = parmElement.get('value')
260 260 self.format = str.lower(parmElement.get('format'))
261 261
262 262 # Compatible with old signal chain version
263 263 if self.format == 'int' and self.name == 'idfigure':
264 264 self.name = 'id'
265 265
266 266 def printattr(self):
267 267
268 268 print 'Parameter[%s]: name = %s, value = %s, format = %s' % (self.id, self.name, self.value, self.format)
269 269
270 270
271 271 class OperationConf():
272 272
273 273 id = None
274 274 name = None
275 275 priority = None
276 276 type = None
277 277
278 278 parmConfObjList = []
279 279
280 280 ELEMENTNAME = 'Operation'
281 281
282 282 def __init__(self):
283 283
284 284 self.id = '0'
285 285 self.name = None
286 286 self.priority = None
287 287 self.type = 'self'
288 288
289 289 def __getNewId(self):
290 290
291 291 return int(self.id) * 10 + len(self.parmConfObjList) + 1
292 292
293 293 def updateId(self, new_id):
294 294
295 295 self.id = str(new_id)
296 296
297 297 n = 1
298 298 for parmObj in self.parmConfObjList:
299 299
300 300 idParm = str(int(new_id) * 10 + n)
301 301 parmObj.updateId(idParm)
302 302
303 303 n += 1
304 304
305 305 def getElementName(self):
306 306
307 307 return self.ELEMENTNAME
308 308
309 309 def getParameterObjList(self):
310 310
311 311 return self.parmConfObjList
312 312
313 313 def getParameterObj(self, parameterName):
314 314
315 315 for parmConfObj in self.parmConfObjList:
316 316
317 317 if parmConfObj.name != parameterName:
318 318 continue
319 319
320 320 return parmConfObj
321 321
322 322 return None
323 323
324 324 def getParameterObjfromValue(self, parameterValue):
325 325
326 326 for parmConfObj in self.parmConfObjList:
327 327
328 328 if parmConfObj.getValue() != parameterValue:
329 329 continue
330 330
331 331 return parmConfObj.getValue()
332 332
333 333 return None
334 334
335 335 def getParameterValue(self, parameterName):
336 336
337 337 parameterObj = self.getParameterObj(parameterName)
338 338
339 339 # if not parameterObj:
340 340 # return None
341 341
342 342 value = parameterObj.getValue()
343 343
344 344 return value
345 345
346 346 def getKwargs(self):
347 347
348 348 kwargs = {}
349 349
350 350 for parmConfObj in self.parmConfObjList:
351 351 if self.name == 'run' and parmConfObj.name == 'datatype':
352 352 continue
353 353
354 354 kwargs[parmConfObj.name] = parmConfObj.getValue()
355 355
356 356 return kwargs
357 357
358 358 def setup(self, id, name, priority, type):
359 359
360 360 self.id = str(id)
361 361 self.name = name
362 362 self.type = type
363 363 self.priority = priority
364 364
365 365 self.parmConfObjList = []
366 366
367 367 def removeParameters(self):
368 368
369 369 for obj in self.parmConfObjList:
370 370 del obj
371 371
372 372 self.parmConfObjList = []
373 373
374 374 def addParameter(self, name, value, format='str'):
375 375
376 376 if value is None:
377 377 return None
378 378 id = self.__getNewId()
379 379
380 380 parmConfObj = ParameterConf()
381 381 if not parmConfObj.setup(id, name, value, format):
382 382 return None
383 383
384 384 self.parmConfObjList.append(parmConfObj)
385 385
386 386 return parmConfObj
387 387
388 388 def changeParameter(self, name, value, format='str'):
389 389
390 390 parmConfObj = self.getParameterObj(name)
391 391 parmConfObj.update(name, value, format)
392 392
393 393 return parmConfObj
394 394
395 395 def makeXml(self, procUnitElement):
396 396
397 397 opElement = SubElement(procUnitElement, self.ELEMENTNAME)
398 398 opElement.set('id', str(self.id))
399 399 opElement.set('name', self.name)
400 400 opElement.set('type', self.type)
401 401 opElement.set('priority', str(self.priority))
402 402
403 403 for parmConfObj in self.parmConfObjList:
404 404 parmConfObj.makeXml(opElement)
405 405
406 406 def readXml(self, opElement):
407 407
408 408 self.id = opElement.get('id')
409 409 self.name = opElement.get('name')
410 410 self.type = opElement.get('type')
411 411 self.priority = opElement.get('priority')
412 412
413 413 # Compatible with old signal chain version
414 414 # Use of 'run' method instead 'init'
415 415 if self.type == 'self' and self.name == 'init':
416 416 self.name = 'run'
417 417
418 418 self.parmConfObjList = []
419 419
420 420 parmElementList = opElement.iter(ParameterConf().getElementName())
421 421
422 422 for parmElement in parmElementList:
423 423 parmConfObj = ParameterConf()
424 424 parmConfObj.readXml(parmElement)
425 425
426 426 # Compatible with old signal chain version
427 427 # If an 'plot' OPERATION is found, changes name operation by the value of its type PARAMETER
428 428 if self.type != 'self' and self.name == 'Plot':
429 429 if parmConfObj.format == 'str' and parmConfObj.name == 'type':
430 430 self.name = parmConfObj.value
431 431 continue
432 432
433 433 self.parmConfObjList.append(parmConfObj)
434 434
435 435 def printattr(self):
436 436
437 437 print '%s[%s]: name = %s, type = %s, priority = %s' % (self.ELEMENTNAME,
438 438 self.id,
439 439 self.name,
440 440 self.type,
441 441 self.priority)
442 442
443 443 for parmConfObj in self.parmConfObjList:
444 444 parmConfObj.printattr()
445 445
446 446 def createObject(self, plotter_queue=None):
447 447
448 448 if self.type == 'self':
449 449 raise ValueError, 'This operation type cannot be created'
450 450
451 451 if self.type == 'plotter':
452 452 if not plotter_queue:
453 453 raise ValueError, 'plotter_queue is not defined. Use:\nmyProject = Project()\nmyProject.setPlotterQueue(plotter_queue)'
454 454
455 455 opObj = Plotter(self.name, plotter_queue)
456 456
457 457 if self.type == 'external' or self.type == 'other':
458 458
459 459 className = eval(self.name)
460 460 kwargs = self.getKwargs()
461 461
462 462 opObj = className(**kwargs)
463 463
464 464 return opObj
465 465
466 466
467 467 class ProcUnitConf():
468 468
469 469 id = None
470 470 name = None
471 471 datatype = None
472 472 inputId = None
473 473 parentId = None
474 474
475 475 opConfObjList = []
476 476
477 477 procUnitObj = None
478 478 opObjList = []
479 479
480 480 ELEMENTNAME = 'ProcUnit'
481 481
482 482 def __init__(self):
483 483
484 484 self.id = None
485 485 self.datatype = None
486 486 self.name = None
487 487 self.inputId = None
488 488
489 489 self.opConfObjList = []
490 490
491 491 self.procUnitObj = None
492 492 self.opObjDict = {}
493 493
494 494 def __getPriority(self):
495 495
496 496 return len(self.opConfObjList) + 1
497 497
498 498 def __getNewId(self):
499 499
500 500 return int(self.id) * 10 + len(self.opConfObjList) + 1
501 501
502 502 def getElementName(self):
503 503
504 504 return self.ELEMENTNAME
505 505
506 506 def getId(self):
507 507
508 508 return self.id
509 509
510 510 def updateId(self, new_id, parentId=parentId):
511 511
512 512 new_id = int(parentId) * 10 + (int(self.id) % 10)
513 513 new_inputId = int(parentId) * 10 + (int(self.inputId) % 10)
514 514
515 515 # If this proc unit has not inputs
516 516 if self.inputId == '0':
517 517 new_inputId = 0
518 518
519 519 n = 1
520 520 for opConfObj in self.opConfObjList:
521 521
522 522 idOp = str(int(new_id) * 10 + n)
523 523 opConfObj.updateId(idOp)
524 524
525 525 n += 1
526 526
527 527 self.parentId = str(parentId)
528 528 self.id = str(new_id)
529 529 self.inputId = str(new_inputId)
530 530
531 531 def getInputId(self):
532 532
533 533 return self.inputId
534 534
535 535 def getOperationObjList(self):
536 536
537 537 return self.opConfObjList
538 538
539 539 def getOperationObj(self, name=None):
540 540
541 541 for opConfObj in self.opConfObjList:
542 542
543 543 if opConfObj.name != name:
544 544 continue
545 545
546 546 return opConfObj
547 547
548 548 return None
549 549
550 550 def getOpObjfromParamValue(self, value=None):
551 551
552 552 for opConfObj in self.opConfObjList:
553 553 if opConfObj.getParameterObjfromValue(parameterValue=value) != value:
554 554 continue
555 555 return opConfObj
556 556 return None
557 557
558 558 def getProcUnitObj(self):
559 559
560 560 return self.procUnitObj
561 561
562 562 def setup(self, id, name, datatype, inputId, parentId=None):
563 563
564 564 # Compatible with old signal chain version
565 565 if datatype == None and name == None:
566 566 raise ValueError, 'datatype or name should be defined'
567 567
568 568 if name == None:
569 569 if 'Proc' in datatype:
570 570 name = datatype
571 571 else:
572 572 name = '%sProc' % (datatype)
573 573
574 574 if datatype == None:
575 575 datatype = name.replace('Proc', '')
576 576
577 577 self.id = str(id)
578 578 self.name = name
579 579 self.datatype = datatype
580 580 self.inputId = inputId
581 581 self.parentId = parentId
582 582
583 583 self.opConfObjList = []
584 584
585 585 self.addOperation(name='run', optype='self')
586 586
587 587 def removeOperations(self):
588 588
589 589 for obj in self.opConfObjList:
590 590 del obj
591 591
592 592 self.opConfObjList = []
593 593 self.addOperation(name='run')
594 594
595 595 def addParameter(self, **kwargs):
596 596 '''
597 597 Add parameters to 'run' operation
598 598 '''
599 599 opObj = self.opConfObjList[0]
600 600
601 601 opObj.addParameter(**kwargs)
602 602
603 603 return opObj
604 604
605 605 def addOperation(self, name, optype='self'):
606 606
607 607 id = self.__getNewId()
608 608 priority = self.__getPriority()
609 609
610 610 opConfObj = OperationConf()
611 611 opConfObj.setup(id, name=name, priority=priority, type=optype)
612 612
613 613 self.opConfObjList.append(opConfObj)
614 614
615 615 return opConfObj
616 616
617 617 def makeXml(self, projectElement):
618 618
619 619 procUnitElement = SubElement(projectElement, self.ELEMENTNAME)
620 620 procUnitElement.set('id', str(self.id))
621 621 procUnitElement.set('name', self.name)
622 622 procUnitElement.set('datatype', self.datatype)
623 623 procUnitElement.set('inputId', str(self.inputId))
624 624
625 625 for opConfObj in self.opConfObjList:
626 626 opConfObj.makeXml(procUnitElement)
627 627
628 628 def readXml(self, upElement):
629 629
630 630 self.id = upElement.get('id')
631 631 self.name = upElement.get('name')
632 632 self.datatype = upElement.get('datatype')
633 633 self.inputId = upElement.get('inputId')
634 634
635 635 if self.ELEMENTNAME == 'ReadUnit':
636 636 self.datatype = self.datatype.replace('Reader', '')
637 637
638 638 if self.ELEMENTNAME == 'ProcUnit':
639 639 self.datatype = self.datatype.replace('Proc', '')
640 640
641 641 if self.inputId == 'None':
642 642 self.inputId = '0'
643 643
644 644 self.opConfObjList = []
645 645
646 646 opElementList = upElement.iter(OperationConf().getElementName())
647 647
648 648 for opElement in opElementList:
649 649 opConfObj = OperationConf()
650 650 opConfObj.readXml(opElement)
651 651 self.opConfObjList.append(opConfObj)
652 652
653 653 def printattr(self):
654 654
655 655 print '%s[%s]: name = %s, datatype = %s, inputId = %s' % (self.ELEMENTNAME,
656 656 self.id,
657 657 self.name,
658 658 self.datatype,
659 659 self.inputId)
660 660
661 661 for opConfObj in self.opConfObjList:
662 662 opConfObj.printattr()
663 663
664 664 def getKwargs(self):
665 665
666 666 opObj = self.opConfObjList[0]
667 667 kwargs = opObj.getKwargs()
668 668
669 669 return kwargs
670 670
671 671 def createObjects(self, plotter_queue=None):
672 672
673 673 className = eval(self.name)
674 674 kwargs = self.getKwargs()
675 675 procUnitObj = className(**kwargs)
676 676
677 677 for opConfObj in self.opConfObjList:
678 678
679 679 if opConfObj.type == 'self' and self.name == 'run':
680 680 continue
681 681 elif opConfObj.type == 'self':
682 682 procUnitObj.addOperationKwargs(
683 683 opConfObj.id, **opConfObj.getKwargs())
684 684 continue
685 685
686 686 opObj = opConfObj.createObject(plotter_queue)
687 687
688 688 self.opObjDict[opConfObj.id] = opObj
689 689
690 690 procUnitObj.addOperation(opObj, opConfObj.id)
691 691
692 692 self.procUnitObj = procUnitObj
693 693
694 694 return procUnitObj
695 695
696 696 def run(self):
697 697
698 698 is_ok = False
699 699
700 700 for opConfObj in self.opConfObjList:
701 701
702 702 kwargs = {}
703 703 for parmConfObj in opConfObj.getParameterObjList():
704 704 if opConfObj.name == 'run' and parmConfObj.name == 'datatype':
705 705 continue
706 706
707 707 kwargs[parmConfObj.name] = parmConfObj.getValue()
708 708
709 709 sts = self.procUnitObj.call(opType=opConfObj.type,
710 710 opName=opConfObj.name,
711 711 opId=opConfObj.id)
712 712
713 713 is_ok = is_ok or sts
714 714
715 715 return is_ok
716 716
717 717 def close(self):
718 718
719 719 for opConfObj in self.opConfObjList:
720 720 if opConfObj.type == 'self':
721 721 continue
722 722
723 723 opObj = self.procUnitObj.getOperationObj(opConfObj.id)
724 724 opObj.close()
725 725
726 726 self.procUnitObj.close()
727 727
728 728 return
729 729
730 730
731 731 class ReadUnitConf(ProcUnitConf):
732 732
733 733 path = None
734 734 startDate = None
735 735 endDate = None
736 736 startTime = None
737 737 endTime = None
738 738
739 739 ELEMENTNAME = 'ReadUnit'
740 740
741 741 def __init__(self):
742 742
743 743 self.id = None
744 744 self.datatype = None
745 745 self.name = None
746 746 self.inputId = None
747 747
748 748 self.parentId = None
749 749
750 750 self.opConfObjList = []
751 751 self.opObjList = []
752 752
753 753 def getElementName(self):
754 754
755 755 return self.ELEMENTNAME
756 756
757 757 def setup(self, id, name, datatype, path='', startDate='', endDate='',
758 758 startTime='', endTime='', parentId=None, server=None, **kwargs):
759 759
760 760 # Compatible with old signal chain version
761 761 if datatype == None and name == None:
762 762 raise ValueError, 'datatype or name should be defined'
763 763 if name == None:
764 764 if 'Reader' in datatype:
765 765 name = datatype
766 766 datatype = name.replace('Reader','')
767 767 else:
768 768 name = '{}Reader'.format(datatype)
769 769 if datatype == None:
770 770 if 'Reader' in name:
771 771 datatype = name.replace('Reader','')
772 772 else:
773 773 datatype = name
774 774 name = '{}Reader'.format(name)
775 775
776 776 self.id = id
777 777 self.name = name
778 778 self.datatype = datatype
779 779 if path != '':
780 780 self.path = os.path.abspath(path)
781 781 self.startDate = startDate
782 782 self.endDate = endDate
783 783 self.startTime = startTime
784 784 self.endTime = endTime
785 785 self.inputId = '0'
786 786 self.parentId = parentId
787 787 self.server = server
788 788 self.addRunOperation(**kwargs)
789 789
790 790 def update(self, **kwargs):
791 791
792 792 if 'datatype' in kwargs:
793 793 datatype = kwargs.pop('datatype')
794 794 if 'Reader' in datatype:
795 795 self.name = datatype
796 796 else:
797 797 self.name = '%sReader' % (datatype)
798 798 self.datatype = self.name.replace('Reader', '')
799 799
800 800 attrs = ('path', 'startDate', 'endDate',
801 801 'startTime', 'endTime', 'parentId')
802 802
803 803 for attr in attrs:
804 804 if attr in kwargs:
805 805 setattr(self, attr, kwargs.pop(attr))
806 806
807 807 self.inputId = '0'
808 808 self.updateRunOperation(**kwargs)
809 809
810 810 def removeOperations(self):
811 811
812 812 for obj in self.opConfObjList:
813 813 del obj
814 814
815 815 self.opConfObjList = []
816 816
817 817 def addRunOperation(self, **kwargs):
818 818
819 819 opObj = self.addOperation(name='run', optype='self')
820 820
821 821 if self.server is None:
822 822 opObj.addParameter(
823 823 name='datatype', value=self.datatype, format='str')
824 824 opObj.addParameter(name='path', value=self.path, format='str')
825 825 opObj.addParameter(
826 826 name='startDate', value=self.startDate, format='date')
827 827 opObj.addParameter(
828 828 name='endDate', value=self.endDate, format='date')
829 829 opObj.addParameter(
830 830 name='startTime', value=self.startTime, format='time')
831 831 opObj.addParameter(
832 832 name='endTime', value=self.endTime, format='time')
833 833
834 834 for key, value in kwargs.items():
835 835 opObj.addParameter(name=key, value=value,
836 836 format=type(value).__name__)
837 837 else:
838 838 opObj.addParameter(name='server', value=self.server, format='str')
839 839
840 840 return opObj
841 841
842 842 def updateRunOperation(self, **kwargs):
843 843
844 844 opObj = self.getOperationObj(name='run')
845 845 opObj.removeParameters()
846 846
847 847 opObj.addParameter(name='datatype', value=self.datatype, format='str')
848 848 opObj.addParameter(name='path', value=self.path, format='str')
849 849 opObj.addParameter(
850 850 name='startDate', value=self.startDate, format='date')
851 851 opObj.addParameter(name='endDate', value=self.endDate, format='date')
852 852 opObj.addParameter(
853 853 name='startTime', value=self.startTime, format='time')
854 854 opObj.addParameter(name='endTime', value=self.endTime, format='time')
855 855
856 856 for key, value in kwargs.items():
857 857 opObj.addParameter(name=key, value=value,
858 858 format=type(value).__name__)
859 859
860 860 return opObj
861 861
862 862 def readXml(self, upElement):
863 863
864 864 self.id = upElement.get('id')
865 865 self.name = upElement.get('name')
866 866 self.datatype = upElement.get('datatype')
867 867 self.inputId = upElement.get('inputId')
868 868
869 869 if self.ELEMENTNAME == 'ReadUnit':
870 870 self.datatype = self.datatype.replace('Reader', '')
871 871
872 872 if self.inputId == 'None':
873 873 self.inputId = '0'
874 874
875 875 self.opConfObjList = []
876 876
877 877 opElementList = upElement.iter(OperationConf().getElementName())
878 878
879 879 for opElement in opElementList:
880 880 opConfObj = OperationConf()
881 881 opConfObj.readXml(opElement)
882 882 self.opConfObjList.append(opConfObj)
883 883
884 884 if opConfObj.name == 'run':
885 885 self.path = opConfObj.getParameterValue('path')
886 886 self.startDate = opConfObj.getParameterValue('startDate')
887 887 self.endDate = opConfObj.getParameterValue('endDate')
888 888 self.startTime = opConfObj.getParameterValue('startTime')
889 889 self.endTime = opConfObj.getParameterValue('endTime')
890 890
891 891
892 892 class Project(Process):
893 893
894 894 id = None
895 895 # name = None
896 896 description = None
897 897 filename = None
898 898
899 899 procUnitConfObjDict = None
900 900
901 901 ELEMENTNAME = 'Project'
902 902
903 903 plotterQueue = None
904 904
905 905 def __init__(self, plotter_queue=None):
906 906
907 907 Process.__init__(self)
908 self.id = None
909 # self.name = None
908 self.id = None
910 909 self.description = None
911
910 self.email = None
911 self.alarm = [0]
912 912 self.plotterQueue = plotter_queue
913
914 913 self.procUnitConfObjDict = {}
915 914
916 915 def __getNewId(self):
917 916
918 917 idList = self.procUnitConfObjDict.keys()
919 918
920 919 id = int(self.id) * 10
921 920
922 921 while True:
923 922 id += 1
924 923
925 924 if str(id) in idList:
926 925 continue
927 926
928 927 break
929 928
930 929 return str(id)
931 930
932 931 def getElementName(self):
933 932
934 933 return self.ELEMENTNAME
935 934
936 935 def getId(self):
937 936
938 937 return self.id
939 938
940 939 def updateId(self, new_id):
941 940
942 941 self.id = str(new_id)
943 942
944 943 keyList = self.procUnitConfObjDict.keys()
945 944 keyList.sort()
946 945
947 946 n = 1
948 947 newProcUnitConfObjDict = {}
949 948
950 949 for procKey in keyList:
951 950
952 951 procUnitConfObj = self.procUnitConfObjDict[procKey]
953 952 idProcUnit = str(int(self.id) * 10 + n)
954 953 procUnitConfObj.updateId(idProcUnit, parentId=self.id)
955
956 954 newProcUnitConfObjDict[idProcUnit] = procUnitConfObj
957 955 n += 1
958 956
959 957 self.procUnitConfObjDict = newProcUnitConfObjDict
960 958
961 def setup(self, id, name='', description=''):
959 def setup(self, id, name='', description='', email=None, alarm=[0]):
962 960
963 961 print
964 962 print '*' * 60
965 963 print ' Starting SIGNAL CHAIN PROCESSING v%s ' % schainpy.__version__
966 964 print '*' * 60
967 965 print
968 966 self.id = str(id)
969 self.description = description
967 self.description = description
968 self.email = email
969 self.alarm = alarm
970 970
971 def update(self, name, description):
971 def update(self, **kwargs):
972 972
973 self.description = description
973 for key, value in kwargs:
974 setattr(self, key, value)
974 975
975 976 def clone(self):
976 977
977 978 p = Project()
978 979 p.procUnitConfObjDict = self.procUnitConfObjDict
979 980 return p
980 981
981 982 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
982 983
983 984 if id is None:
984 985 idReadUnit = self.__getNewId()
985 986 else:
986 987 idReadUnit = str(id)
987 988
988 989 readUnitConfObj = ReadUnitConf()
989 990 readUnitConfObj.setup(idReadUnit, name, datatype,
990 991 parentId=self.id, **kwargs)
991 992
992 993 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
993 994
994 995 return readUnitConfObj
995 996
996 997 def addProcUnit(self, inputId='0', datatype=None, name=None):
997 998
998 999 idProcUnit = self.__getNewId()
999 1000
1000 1001 procUnitConfObj = ProcUnitConf()
1001 1002 procUnitConfObj.setup(idProcUnit, name, datatype,
1002 1003 inputId, parentId=self.id)
1003 1004
1004 1005 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
1005 1006
1006 1007 return procUnitConfObj
1007 1008
1008 1009 def removeProcUnit(self, id):
1009 1010
1010 1011 if id in self.procUnitConfObjDict.keys():
1011 1012 self.procUnitConfObjDict.pop(id)
1012 1013
1013 1014 def getReadUnitId(self):
1014 1015
1015 1016 readUnitConfObj = self.getReadUnitObj()
1016 1017
1017 1018 return readUnitConfObj.id
1018 1019
1019 1020 def getReadUnitObj(self):
1020 1021
1021 1022 for obj in self.procUnitConfObjDict.values():
1022 1023 if obj.getElementName() == 'ReadUnit':
1023 1024 return obj
1024 1025
1025 1026 return None
1026 1027
1027 1028 def getProcUnitObj(self, id=None, name=None):
1028 1029
1029 1030 if id != None:
1030 1031 return self.procUnitConfObjDict[id]
1031 1032
1032 1033 if name != None:
1033 1034 return self.getProcUnitObjByName(name)
1034 1035
1035 1036 return None
1036 1037
1037 1038 def getProcUnitObjByName(self, name):
1038 1039
1039 1040 for obj in self.procUnitConfObjDict.values():
1040 1041 if obj.name == name:
1041 1042 return obj
1042 1043
1043 1044 return None
1044 1045
1045 1046 def procUnitItems(self):
1046 1047
1047 1048 return self.procUnitConfObjDict.items()
1048 1049
1049 1050 def makeXml(self):
1050 1051
1051 1052 projectElement = Element('Project')
1052 1053 projectElement.set('id', str(self.id))
1053 1054 projectElement.set('name', self.name)
1054 1055 projectElement.set('description', self.description)
1055 1056
1056 1057 for procUnitConfObj in self.procUnitConfObjDict.values():
1057 1058 procUnitConfObj.makeXml(projectElement)
1058 1059
1059 1060 self.projectElement = projectElement
1060 1061
1061 1062 def writeXml(self, filename=None):
1062 1063
1063 1064 if filename == None:
1064 1065 if self.filename:
1065 1066 filename = self.filename
1066 1067 else:
1067 1068 filename = 'schain.xml'
1068 1069
1069 1070 if not filename:
1070 1071 print 'filename has not been defined. Use setFilename(filename) for do it.'
1071 1072 return 0
1072 1073
1073 1074 abs_file = os.path.abspath(filename)
1074 1075
1075 1076 if not os.access(os.path.dirname(abs_file), os.W_OK):
1076 1077 print 'No write permission on %s' % os.path.dirname(abs_file)
1077 1078 return 0
1078 1079
1079 1080 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
1080 1081 print 'File %s already exists and it could not be overwriten' % abs_file
1081 1082 return 0
1082 1083
1083 1084 self.makeXml()
1084 1085
1085 1086 ElementTree(self.projectElement).write(abs_file, method='xml')
1086 1087
1087 1088 self.filename = abs_file
1088 1089
1089 1090 return 1
1090 1091
1091 1092 def readXml(self, filename=None):
1092 1093
1093 1094 if not filename:
1094 1095 print 'filename is not defined'
1095 1096 return 0
1096 1097
1097 1098 abs_file = os.path.abspath(filename)
1098 1099
1099 1100 if not os.path.isfile(abs_file):
1100 1101 print '%s file does not exist' % abs_file
1101 1102 return 0
1102 1103
1103 1104 self.projectElement = None
1104 1105 self.procUnitConfObjDict = {}
1105 1106
1106 1107 try:
1107 1108 self.projectElement = ElementTree().parse(abs_file)
1108 1109 except:
1109 1110 print 'Error reading %s, verify file format' % filename
1110 1111 return 0
1111 1112
1112 1113 self.project = self.projectElement.tag
1113 1114
1114 1115 self.id = self.projectElement.get('id')
1115 1116 self.name = self.projectElement.get('name')
1116 1117 self.description = self.projectElement.get('description')
1117 1118
1118 1119 readUnitElementList = self.projectElement.iter(
1119 1120 ReadUnitConf().getElementName())
1120 1121
1121 1122 for readUnitElement in readUnitElementList:
1122 1123 readUnitConfObj = ReadUnitConf()
1123 1124 readUnitConfObj.readXml(readUnitElement)
1124 1125
1125 1126 if readUnitConfObj.parentId == None:
1126 1127 readUnitConfObj.parentId = self.id
1127 1128
1128 1129 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
1129 1130
1130 1131 procUnitElementList = self.projectElement.iter(
1131 1132 ProcUnitConf().getElementName())
1132 1133
1133 1134 for procUnitElement in procUnitElementList:
1134 1135 procUnitConfObj = ProcUnitConf()
1135 1136 procUnitConfObj.readXml(procUnitElement)
1136 1137
1137 1138 if procUnitConfObj.parentId == None:
1138 1139 procUnitConfObj.parentId = self.id
1139 1140
1140 1141 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
1141 1142
1142 1143 self.filename = abs_file
1143 1144
1144 1145 return 1
1145 1146
1146 1147 def printattr(self):
1147 1148
1148 1149 print 'Project[%s]: name = %s, description = %s' % (self.id,
1149 1150 self.name,
1150 1151 self.description)
1151 1152
1152 1153 for procUnitConfObj in self.procUnitConfObjDict.values():
1153 1154 procUnitConfObj.printattr()
1154 1155
1155 1156 def createObjects(self):
1156 1157
1157 1158 for procUnitConfObj in self.procUnitConfObjDict.values():
1158 1159 procUnitConfObj.createObjects(self.plotterQueue)
1159 1160
1160 1161 def __connect(self, objIN, thisObj):
1161 1162
1162 1163 thisObj.setInput(objIN.getOutputObj())
1163 1164
1164 1165 def connectObjects(self):
1165 1166
1166 1167 for thisPUConfObj in self.procUnitConfObjDict.values():
1167 1168
1168 1169 inputId = thisPUConfObj.getInputId()
1169 1170
1170 1171 if int(inputId) == 0:
1171 1172 continue
1172 1173
1173 1174 # Get input object
1174 1175 puConfINObj = self.procUnitConfObjDict[inputId]
1175 1176 puObjIN = puConfINObj.getProcUnitObj()
1176 1177
1177 1178 # Get current object
1178 1179 thisPUObj = thisPUConfObj.getProcUnitObj()
1179 1180
1180 1181 self.__connect(puObjIN, thisPUObj)
1181 1182
1182 def __handleError(self, procUnitConfObj, send_email=False):
1183 def __handleError(self, procUnitConfObj, modes=None):
1183 1184
1184 1185 import socket
1185 1186
1187 if modes is None:
1188 modes = self.alarm
1189
1186 1190 err = traceback.format_exception(sys.exc_info()[0],
1187 1191 sys.exc_info()[1],
1188 1192 sys.exc_info()[2])
1189
1190 print '***** Error occurred in %s *****' % (procUnitConfObj.name)
1191 print '***** %s' % err[-1]
1193
1194 log.error('{}'.format(err[-1]), procUnitConfObj.name)
1192 1195
1193 1196 message = ''.join(err)
1194 1197
1195 1198 sys.stderr.write(message)
1196 1199
1197 if not send_email:
1198 return
1199
1200 1200 subject = 'SChain v%s: Error running %s\n' % (
1201 1201 schainpy.__version__, procUnitConfObj.name)
1202 1202
1203 1203 subtitle = '%s: %s\n' % (
1204 1204 procUnitConfObj.getElementName(), procUnitConfObj.name)
1205 1205 subtitle += 'Hostname: %s\n' % socket.gethostbyname(
1206 1206 socket.gethostname())
1207 1207 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
1208 1208 subtitle += 'Configuration file: %s\n' % self.filename
1209 1209 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
1210 1210
1211 1211 readUnitConfObj = self.getReadUnitObj()
1212 1212 if readUnitConfObj:
1213 1213 subtitle += '\nInput parameters:\n'
1214 1214 subtitle += '[Data path = %s]\n' % readUnitConfObj.path
1215 1215 subtitle += '[Data type = %s]\n' % readUnitConfObj.datatype
1216 1216 subtitle += '[Start date = %s]\n' % readUnitConfObj.startDate
1217 1217 subtitle += '[End date = %s]\n' % readUnitConfObj.endDate
1218 1218 subtitle += '[Start time = %s]\n' % readUnitConfObj.startTime
1219 1219 subtitle += '[End time = %s]\n' % readUnitConfObj.endTime
1220 1220
1221 adminObj = schainpy.admin.SchainNotify()
1222 adminObj.sendAlert(message=message,
1223 subject=subject,
1224 subtitle=subtitle,
1225 filename=self.filename)
1221 a = Alarm(
1222 modes=modes,
1223 email=self.email,
1224 message=message,
1225 subject=subject,
1226 subtitle=subtitle,
1227 filename=self.filename
1228 )
1229
1230 a.start()
1226 1231
1227 1232 def isPaused(self):
1228 1233 return 0
1229 1234
1230 1235 def isStopped(self):
1231 1236 return 0
1232 1237
1233 1238 def runController(self):
1234 1239 '''
1235 1240 returns 0 when this process has been stopped, 1 otherwise
1236 1241 '''
1237 1242
1238 1243 if self.isPaused():
1239 1244 print 'Process suspended'
1240 1245
1241 1246 while True:
1242 1247 time.sleep(0.1)
1243 1248
1244 1249 if not self.isPaused():
1245 1250 break
1246 1251
1247 1252 if self.isStopped():
1248 1253 break
1249 1254
1250 1255 print 'Process reinitialized'
1251 1256
1252 1257 if self.isStopped():
1253 1258 print 'Process stopped'
1254 1259 return 0
1255 1260
1256 1261 return 1
1257 1262
1258 1263 def setFilename(self, filename):
1259 1264
1260 1265 self.filename = filename
1261 1266
1262 1267 def setPlotterQueue(self, plotter_queue):
1263 1268
1264 1269 raise NotImplementedError, 'Use schainpy.controller_api.ControllerThread instead Project class'
1265 1270
1266 1271 def getPlotterQueue(self):
1267 1272
1268 1273 raise NotImplementedError, 'Use schainpy.controller_api.ControllerThread instead Project class'
1269 1274
1270 1275 def useExternalPlotter(self):
1271 1276
1272 1277 raise NotImplementedError, 'Use schainpy.controller_api.ControllerThread instead Project class'
1273 1278
1274 1279 def run(self):
1275 1280
1276 1281 log.success('Starting {}'.format(self.name))
1277 1282 self.start_time = time.time()
1278 1283 self.createObjects()
1279 1284 self.connectObjects()
1280 1285
1281 1286 keyList = self.procUnitConfObjDict.keys()
1282 1287 keyList.sort()
1283 1288
1284 1289 while(True):
1285 1290
1286 1291 is_ok = False
1287 1292
1288 1293 for procKey in keyList:
1289 1294
1290 1295 procUnitConfObj = self.procUnitConfObjDict[procKey]
1291 1296
1292 1297 try:
1293 1298 sts = procUnitConfObj.run()
1294 1299 is_ok = is_ok or sts
1300 except SchainWarning:
1301 self.__handleError(procUnitConfObj, modes=[2, 3])
1295 1302 except KeyboardInterrupt:
1296 1303 is_ok = False
1297 1304 break
1298 1305 except ValueError, e:
1299 1306 time.sleep(0.5)
1300 self.__handleError(procUnitConfObj, send_email=True)
1307 self.__handleError(procUnitConfObj)
1301 1308 is_ok = False
1302 1309 break
1303 1310 except:
1304 1311 time.sleep(0.5)
1305 1312 self.__handleError(procUnitConfObj)
1306 1313 is_ok = False
1307 1314 break
1308 1315
1309 1316 # If every process unit finished so end process
1310 1317 if not(is_ok):
1311 1318 break
1312 1319
1313 1320 if not self.runController():
1314 1321 break
1315 1322
1316 1323 # Closing every process
1317 1324 for procKey in keyList:
1318 1325 procUnitConfObj = self.procUnitConfObjDict[procKey]
1319 1326 procUnitConfObj.close()
1320 1327
1321 1328 log.success('{} finished (time: {}s)'.format(
1322 1329 self.name,
1323 1330 time.time()-self.start_time))
@@ -1,965 +1,971
1 1
2 2 import os
3 3 import time
4 4 import glob
5 5 import datetime
6 6 from multiprocessing import Process
7 7
8 8 import zmq
9 9 import numpy
10 10 import matplotlib
11 11 import matplotlib.pyplot as plt
12 12 from mpl_toolkits.axes_grid1 import make_axes_locatable
13 13 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
14 14
15 15 from schainpy.model.proc.jroproc_base import Operation
16 16 from schainpy.utils import log
17 17
18 18 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
19 19 blu_values = matplotlib.pyplot.get_cmap(
20 20 'seismic_r', 20)(numpy.arange(20))[10:15]
21 21 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
22 22 'jro', numpy.vstack((blu_values, jet_values)))
23 23 matplotlib.pyplot.register_cmap(cmap=ncmap)
24 24
25 25 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis', 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
26 26
27 27
28 28 def figpause(interval):
29 29 backend = plt.rcParams['backend']
30 30 if backend in matplotlib.rcsetup.interactive_bk:
31 31 figManager = matplotlib._pylab_helpers.Gcf.get_active()
32 32 if figManager is not None:
33 33 canvas = figManager.canvas
34 34 if canvas.figure.stale:
35 35 canvas.draw()
36 36 canvas.start_event_loop(interval)
37 37 return
38 38
39 def popup(message):
40 fig = plt.figure(figsize=(12, 8), facecolor='r')
41 fig.text(0.5, 0.5, message, ha='center', va='center', size='20', weight='heavy', color='w')
42 fig.show()
43 figpause(1000)
44
39 45
40 46 class PlotData(Operation, Process):
41 47 '''
42 48 Base class for Schain plotting operations
43 49 '''
44 50
45 51 CODE = 'Figure'
46 52 colormap = 'jro'
47 53 bgcolor = 'white'
48 54 CONFLATE = False
49 55 __missing = 1E30
50 56
51 57 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
52 58 'zlimits', 'xlabel', 'ylabel', 'xaxis','cb_label', 'title',
53 59 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
54 60 'showprofile', 'decimation']
55 61
56 62 def __init__(self, **kwargs):
57 63
58 64 Operation.__init__(self, plot=True, **kwargs)
59 65 Process.__init__(self)
60 66
61 67 self.kwargs['code'] = self.CODE
62 68 self.mp = False
63 69 self.data = None
64 70 self.isConfig = False
65 71 self.figures = []
66 72 self.axes = []
67 73 self.cb_axes = []
68 74 self.localtime = kwargs.pop('localtime', True)
69 75 self.show = kwargs.get('show', True)
70 76 self.save = kwargs.get('save', False)
71 77 self.colormap = kwargs.get('colormap', self.colormap)
72 78 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
73 79 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
74 80 self.colormaps = kwargs.get('colormaps', None)
75 81 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
76 82 self.showprofile = kwargs.get('showprofile', False)
77 83 self.title = kwargs.get('wintitle', self.CODE.upper())
78 84 self.cb_label = kwargs.get('cb_label', None)
79 85 self.cb_labels = kwargs.get('cb_labels', None)
80 86 self.xaxis = kwargs.get('xaxis', 'frequency')
81 87 self.zmin = kwargs.get('zmin', None)
82 88 self.zmax = kwargs.get('zmax', None)
83 89 self.zlimits = kwargs.get('zlimits', None)
84 90 self.xmin = kwargs.get('xmin', None)
85 91 self.xmax = kwargs.get('xmax', None)
86 92 self.xrange = kwargs.get('xrange', 24)
87 93 self.ymin = kwargs.get('ymin', None)
88 94 self.ymax = kwargs.get('ymax', None)
89 95 self.xlabel = kwargs.get('xlabel', None)
90 96 self.decimation = kwargs.get('decimation', None)
91 97 self.showSNR = kwargs.get('showSNR', False)
92 98 self.oneFigure = kwargs.get('oneFigure', True)
93 99 self.width = kwargs.get('width', None)
94 100 self.height = kwargs.get('height', None)
95 101 self.colorbar = kwargs.get('colorbar', True)
96 102 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
97 103 self.titles = kwargs.get('titles', [])
98 104 self.polar = False
99 105
100 106 def __fmtTime(self, x, pos):
101 107 '''
102 108 '''
103 109
104 110 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
105 111
106 112 def __setup(self):
107 113 '''
108 114 Common setup for all figures, here figures and axes are created
109 115 '''
110 116
111 117 if self.CODE not in self.data:
112 118 raise ValueError(log.error('Missing data for {}'.format(self.CODE),
113 119 self.name))
114 120
115 121 self.setup()
116 122
117 123 self.time_label = 'LT' if self.localtime else 'UTC'
118 124 if self.data.localtime:
119 125 self.getDateTime = datetime.datetime.fromtimestamp
120 126 else:
121 127 self.getDateTime = datetime.datetime.utcfromtimestamp
122 128
123 129 if self.width is None:
124 130 self.width = 8
125 131
126 132 self.figures = []
127 133 self.axes = []
128 134 self.cb_axes = []
129 135 self.pf_axes = []
130 136 self.cmaps = []
131 137
132 138 size = '15%' if self.ncols == 1 else '30%'
133 139 pad = '4%' if self.ncols == 1 else '8%'
134 140
135 141 if self.oneFigure:
136 142 if self.height is None:
137 143 self.height = 1.4 * self.nrows + 1
138 144 fig = plt.figure(figsize=(self.width, self.height),
139 145 edgecolor='k',
140 146 facecolor='w')
141 147 self.figures.append(fig)
142 148 for n in range(self.nplots):
143 149 ax = fig.add_subplot(self.nrows, self.ncols,
144 150 n + 1, polar=self.polar)
145 151 ax.tick_params(labelsize=8)
146 152 ax.firsttime = True
147 153 ax.index = 0
148 154 ax.press = None
149 155 self.axes.append(ax)
150 156 if self.showprofile:
151 157 cax = self.__add_axes(ax, size=size, pad=pad)
152 158 cax.tick_params(labelsize=8)
153 159 self.pf_axes.append(cax)
154 160 else:
155 161 if self.height is None:
156 162 self.height = 3
157 163 for n in range(self.nplots):
158 164 fig = plt.figure(figsize=(self.width, self.height),
159 165 edgecolor='k',
160 166 facecolor='w')
161 167 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
162 168 ax.tick_params(labelsize=8)
163 169 ax.firsttime = True
164 170 ax.index = 0
165 171 ax.press = None
166 172 self.figures.append(fig)
167 173 self.axes.append(ax)
168 174 if self.showprofile:
169 175 cax = self.__add_axes(ax, size=size, pad=pad)
170 176 cax.tick_params(labelsize=8)
171 177 self.pf_axes.append(cax)
172 178
173 179 for n in range(self.nrows):
174 180 if self.colormaps is not None:
175 181 cmap = plt.get_cmap(self.colormaps[n])
176 182 else:
177 183 cmap = plt.get_cmap(self.colormap)
178 184 cmap.set_bad(self.bgcolor, 1.)
179 185 self.cmaps.append(cmap)
180 186
181 187 for fig in self.figures:
182 188 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
183 189 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
184 190 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
185 191 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
186 192 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
187 193 if self.show:
188 194 fig.show()
189 195
190 196 def OnKeyPress(self, event):
191 197 '''
192 198 Event for pressing keys (up, down) change colormap
193 199 '''
194 200 ax = event.inaxes
195 201 if ax in self.axes:
196 202 if event.key == 'down':
197 203 ax.index += 1
198 204 elif event.key == 'up':
199 205 ax.index -= 1
200 206 if ax.index < 0:
201 207 ax.index = len(CMAPS) - 1
202 208 elif ax.index == len(CMAPS):
203 209 ax.index = 0
204 210 cmap = CMAPS[ax.index]
205 211 ax.cbar.set_cmap(cmap)
206 212 ax.cbar.draw_all()
207 213 ax.plt.set_cmap(cmap)
208 214 ax.cbar.patch.figure.canvas.draw()
209 215 self.colormap = cmap.name
210 216
211 217 def OnBtnScroll(self, event):
212 218 '''
213 219 Event for scrolling, scale figure
214 220 '''
215 221 cb_ax = event.inaxes
216 222 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
217 223 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
218 224 pt = ax.cbar.ax.bbox.get_points()[:, 1]
219 225 nrm = ax.cbar.norm
220 226 vmin, vmax, p0, p1, pS = (
221 227 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
222 228 scale = 2 if event.step == 1 else 0.5
223 229 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
224 230 ax.cbar.norm.vmin = point - scale * (point - vmin)
225 231 ax.cbar.norm.vmax = point - scale * (point - vmax)
226 232 ax.plt.set_norm(ax.cbar.norm)
227 233 ax.cbar.draw_all()
228 234 ax.cbar.patch.figure.canvas.draw()
229 235
230 236 def onBtnPress(self, event):
231 237 '''
232 238 Event for mouse button press
233 239 '''
234 240 cb_ax = event.inaxes
235 241 if cb_ax is None:
236 242 return
237 243
238 244 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
239 245 cb_ax.press = event.x, event.y
240 246 else:
241 247 cb_ax.press = None
242 248
243 249 def onMotion(self, event):
244 250 '''
245 251 Event for move inside colorbar
246 252 '''
247 253 cb_ax = event.inaxes
248 254 if cb_ax is None:
249 255 return
250 256 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
251 257 return
252 258 if cb_ax.press is None:
253 259 return
254 260
255 261 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
256 262 xprev, yprev = cb_ax.press
257 263 dx = event.x - xprev
258 264 dy = event.y - yprev
259 265 cb_ax.press = event.x, event.y
260 266 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
261 267 perc = 0.03
262 268
263 269 if event.button == 1:
264 270 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
265 271 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
266 272 elif event.button == 3:
267 273 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
268 274 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
269 275
270 276 ax.cbar.draw_all()
271 277 ax.plt.set_norm(ax.cbar.norm)
272 278 ax.cbar.patch.figure.canvas.draw()
273 279
274 280 def onBtnRelease(self, event):
275 281 '''
276 282 Event for mouse button release
277 283 '''
278 284 cb_ax = event.inaxes
279 285 if cb_ax is not None:
280 286 cb_ax.press = None
281 287
282 288 def __add_axes(self, ax, size='30%', pad='8%'):
283 289 '''
284 290 Add new axes to the given figure
285 291 '''
286 292 divider = make_axes_locatable(ax)
287 293 nax = divider.new_horizontal(size=size, pad=pad)
288 294 ax.figure.add_axes(nax)
289 295 return nax
290 296
291 297 self.setup()
292 298
293 299 def setup(self):
294 300 '''
295 301 This method should be implemented in the child class, the following
296 302 attributes should be set:
297 303
298 304 self.nrows: number of rows
299 305 self.ncols: number of cols
300 306 self.nplots: number of plots (channels or pairs)
301 307 self.ylabel: label for Y axes
302 308 self.titles: list of axes title
303 309
304 310 '''
305 311 raise(NotImplementedError, 'Implement this method in child class')
306 312
307 313 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
308 314 '''
309 315 Create a masked array for missing data
310 316 '''
311 317 if x_buffer.shape[0] < 2:
312 318 return x_buffer, y_buffer, z_buffer
313 319
314 320 deltas = x_buffer[1:] - x_buffer[0:-1]
315 321 x_median = numpy.median(deltas)
316 322
317 323 index = numpy.where(deltas > 5 * x_median)
318 324
319 325 if len(index[0]) != 0:
320 326 z_buffer[::, index[0], ::] = self.__missing
321 327 z_buffer = numpy.ma.masked_inside(z_buffer,
322 328 0.99 * self.__missing,
323 329 1.01 * self.__missing)
324 330
325 331 return x_buffer, y_buffer, z_buffer
326 332
327 333 def decimate(self):
328 334
329 335 # dx = int(len(self.x)/self.__MAXNUMX) + 1
330 336 dy = int(len(self.y) / self.decimation) + 1
331 337
332 338 # x = self.x[::dx]
333 339 x = self.x
334 340 y = self.y[::dy]
335 341 z = self.z[::, ::, ::dy]
336 342
337 343 return x, y, z
338 344
339 345 def format(self):
340 346 '''
341 347 Set min and max values, labels, ticks and titles
342 348 '''
343 349
344 350 if self.xmin is None:
345 351 xmin = self.min_time
346 352 else:
347 353 if self.xaxis is 'time':
348 354 dt = self.getDateTime(self.min_time)
349 355 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
350 356 datetime.datetime(1970, 1, 1)).total_seconds()
351 357 if self.data.localtime:
352 358 xmin += time.timezone
353 359 else:
354 360 xmin = self.xmin
355 361
356 362 if self.xmax is None:
357 363 xmax = xmin + self.xrange * 60 * 60
358 364 else:
359 365 if self.xaxis is 'time':
360 366 dt = self.getDateTime(self.max_time)
361 367 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
362 368 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
363 369 if self.data.localtime:
364 370 xmax += time.timezone
365 371 else:
366 372 xmax = self.xmax
367 373
368 374 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
369 375 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
370 376
371 377 Y = numpy.array([5, 10, 20, 50, 100, 200, 500, 1000, 2000])
372 378 i = 1 if numpy.where(ymax-ymin < Y)[0][0] < 0 else numpy.where(ymax-ymin < Y)[0][0]
373 379 ystep = Y[i] / 5
374 380
375 381 for n, ax in enumerate(self.axes):
376 382 if ax.firsttime:
377 383 ax.set_facecolor(self.bgcolor)
378 384 ax.yaxis.set_major_locator(MultipleLocator(ystep))
379 385 if self.xaxis is 'time':
380 386 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
381 387 ax.xaxis.set_major_locator(LinearLocator(9))
382 388 if self.xlabel is not None:
383 389 ax.set_xlabel(self.xlabel)
384 390 ax.set_ylabel(self.ylabel)
385 391 ax.firsttime = False
386 392 if self.showprofile:
387 393 self.pf_axes[n].set_ylim(ymin, ymax)
388 394 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
389 395 self.pf_axes[n].set_xlabel('dB')
390 396 self.pf_axes[n].grid(b=True, axis='x')
391 397 [tick.set_visible(False)
392 398 for tick in self.pf_axes[n].get_yticklabels()]
393 399 if self.colorbar:
394 400 ax.cbar = plt.colorbar(
395 401 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
396 402 ax.cbar.ax.tick_params(labelsize=8)
397 403 ax.cbar.ax.press = None
398 404 if self.cb_label:
399 405 ax.cbar.set_label(self.cb_label, size=8)
400 406 elif self.cb_labels:
401 407 ax.cbar.set_label(self.cb_labels[n], size=8)
402 408 else:
403 409 ax.cbar = None
404 410
405 411 if not self.polar:
406 412 ax.set_xlim(xmin, xmax)
407 413 ax.set_ylim(ymin, ymax)
408 414 ax.set_title('{} - {} {}'.format(
409 415 self.titles[n],
410 416 self.getDateTime(self.max_time).strftime('%H:%M:%S'),
411 417 self.time_label),
412 418 size=8)
413 419 else:
414 420 ax.set_title('{}'.format(self.titles[n]), size=8)
415 421 ax.set_ylim(0, 90)
416 422 ax.set_yticks(numpy.arange(0, 90, 20))
417 423 ax.yaxis.labelpad = 40
418 424
419 425 def __plot(self):
420 426 '''
421 427 '''
422 428 log.success('Plotting', self.name)
423 429
424 430 try:
425 431 self.plot()
426 432 self.format()
427 433 except:
428 434 log.warning('{} Plot could not be updated... check data'.format(self.CODE), self.name)
429 435
430 436 for n, fig in enumerate(self.figures):
431 437 if self.nrows == 0 or self.nplots == 0:
432 438 log.warning('No data', self.name)
433 439 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
434 440 fig.canvas.manager.set_window_title(self.CODE)
435 441 continue
436 442
437 443 fig.tight_layout()
438 444 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
439 445 self.getDateTime(self.max_time).strftime('%Y/%m/%d')))
440 446 fig.canvas.draw()
441 447
442 448 if self.save and self.data.ended:
443 449 channels = range(self.nrows)
444 450 if self.oneFigure:
445 451 label = ''
446 452 else:
447 453 label = '_{}'.format(channels[n])
448 454 figname = os.path.join(
449 455 self.save,
450 456 '{}{}_{}.png'.format(
451 457 self.CODE,
452 458 label,
453 459 self.getDateTime(self.saveTime).strftime(
454 460 '%Y%m%d_%H%M%S'),
455 461 )
456 462 )
457 463 log.log('Saving figure: {}'.format(figname), self.name)
458 464 fig.savefig(figname)
459 465
460 466 def plot(self):
461 467 '''
462 468 '''
463 469 raise(NotImplementedError, 'Implement this method in child class')
464 470
465 471 def run(self):
466 472
467 473 log.success('Starting', self.name)
468 474
469 475 context = zmq.Context()
470 476 receiver = context.socket(zmq.SUB)
471 477 receiver.setsockopt(zmq.SUBSCRIBE, '')
472 478 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
473 479
474 480 if 'server' in self.kwargs['parent']:
475 481 receiver.connect(
476 482 'ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
477 483 else:
478 484 receiver.connect("ipc:///tmp/zmq.plots")
479 485
480 486 while True:
481 487 try:
482 488 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
483 489 if self.data.localtime and self.localtime:
484 490 self.times = self.data.times
485 491 elif self.data.localtime and not self.localtime:
486 492 self.times = self.data.times + time.timezone
487 493 elif not self.data.localtime and self.localtime:
488 494 self.times = self.data.times - time.timezone
489 495 else:
490 496 self.times = self.data.times
491 497
492 498 self.min_time = self.times[0]
493 499 self.max_time = self.times[-1]
494 500
495 501 if self.isConfig is False:
496 502 self.__setup()
497 503 self.isConfig = True
498 504
499 505 self.__plot()
500 506
501 507 except zmq.Again as e:
502 508 log.log('Waiting for data...')
503 509 if self.data:
504 510 figpause(self.data.throttle)
505 511 else:
506 512 time.sleep(2)
507 513
508 514 def close(self):
509 515 if self.data:
510 516 self.__plot()
511 517
512 518
513 519 class PlotSpectraData(PlotData):
514 520 '''
515 521 Plot for Spectra data
516 522 '''
517 523
518 524 CODE = 'spc'
519 525 colormap = 'jro'
520 526
521 527 def setup(self):
522 528 self.nplots = len(self.data.channels)
523 529 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
524 530 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
525 531 self.width = 3.4 * self.ncols
526 532 self.height = 3 * self.nrows
527 533 self.cb_label = 'dB'
528 534 if self.showprofile:
529 535 self.width += 0.8 * self.ncols
530 536
531 537 self.ylabel = 'Range [km]'
532 538
533 539 def plot(self):
534 540 if self.xaxis == "frequency":
535 541 x = self.data.xrange[0]
536 542 self.xlabel = "Frequency (kHz)"
537 543 elif self.xaxis == "time":
538 544 x = self.data.xrange[1]
539 545 self.xlabel = "Time (ms)"
540 546 else:
541 547 x = self.data.xrange[2]
542 548 self.xlabel = "Velocity (m/s)"
543 549
544 550 if self.CODE == 'spc_mean':
545 551 x = self.data.xrange[2]
546 552 self.xlabel = "Velocity (m/s)"
547 553
548 554 self.titles = []
549 555
550 556 y = self.data.heights
551 557 self.y = y
552 558 z = self.data['spc']
553 559
554 560 for n, ax in enumerate(self.axes):
555 561 noise = self.data['noise'][n][-1]
556 562 if self.CODE == 'spc_mean':
557 563 mean = self.data['mean'][n][-1]
558 564 if ax.firsttime:
559 565 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
560 566 self.xmin = self.xmin if self.xmin else -self.xmax
561 567 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
562 568 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
563 569 ax.plt = ax.pcolormesh(x, y, z[n].T,
564 570 vmin=self.zmin,
565 571 vmax=self.zmax,
566 572 cmap=plt.get_cmap(self.colormap)
567 573 )
568 574
569 575 if self.showprofile:
570 576 ax.plt_profile = self.pf_axes[n].plot(
571 577 self.data['rti'][n][-1], y)[0]
572 578 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
573 579 color="k", linestyle="dashed", lw=1)[0]
574 580 if self.CODE == 'spc_mean':
575 581 ax.plt_mean = ax.plot(mean, y, color='k')[0]
576 582 else:
577 583 ax.plt.set_array(z[n].T.ravel())
578 584 if self.showprofile:
579 585 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
580 586 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
581 587 if self.CODE == 'spc_mean':
582 588 ax.plt_mean.set_data(mean, y)
583 589
584 590 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
585 591 self.saveTime = self.max_time
586 592
587 593
588 594 class PlotCrossSpectraData(PlotData):
589 595
590 596 CODE = 'cspc'
591 597 zmin_coh = None
592 598 zmax_coh = None
593 599 zmin_phase = None
594 600 zmax_phase = None
595 601
596 602 def setup(self):
597 603
598 604 self.ncols = 4
599 605 self.nrows = len(self.data.pairs)
600 606 self.nplots = self.nrows * 4
601 607 self.width = 3.4 * self.ncols
602 608 self.height = 3 * self.nrows
603 609 self.ylabel = 'Range [km]'
604 610 self.showprofile = False
605 611
606 612 def plot(self):
607 613
608 614 if self.xaxis == "frequency":
609 615 x = self.data.xrange[0]
610 616 self.xlabel = "Frequency (kHz)"
611 617 elif self.xaxis == "time":
612 618 x = self.data.xrange[1]
613 619 self.xlabel = "Time (ms)"
614 620 else:
615 621 x = self.data.xrange[2]
616 622 self.xlabel = "Velocity (m/s)"
617 623
618 624 self.titles = []
619 625
620 626 y = self.data.heights
621 627 self.y = y
622 628 spc = self.data['spc']
623 629 cspc = self.data['cspc']
624 630
625 631 for n in range(self.nrows):
626 632 noise = self.data['noise'][n][-1]
627 633 pair = self.data.pairs[n]
628 634 ax = self.axes[4 * n]
629 635 ax3 = self.axes[4 * n + 3]
630 636 if ax.firsttime:
631 637 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
632 638 self.xmin = self.xmin if self.xmin else -self.xmax
633 639 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
634 640 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
635 641 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
636 642 vmin=self.zmin,
637 643 vmax=self.zmax,
638 644 cmap=plt.get_cmap(self.colormap)
639 645 )
640 646 else:
641 647 ax.plt.set_array(spc[pair[0]].T.ravel())
642 648 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
643 649
644 650 ax = self.axes[4 * n + 1]
645 651 if ax.firsttime:
646 652 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
647 653 vmin=self.zmin,
648 654 vmax=self.zmax,
649 655 cmap=plt.get_cmap(self.colormap)
650 656 )
651 657 else:
652 658 ax.plt.set_array(spc[pair[1]].T.ravel())
653 659 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
654 660
655 661 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
656 662 coh = numpy.abs(out)
657 663 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
658 664
659 665 ax = self.axes[4 * n + 2]
660 666 if ax.firsttime:
661 667 ax.plt = ax.pcolormesh(x, y, coh.T,
662 668 vmin=0,
663 669 vmax=1,
664 670 cmap=plt.get_cmap(self.colormap_coh)
665 671 )
666 672 else:
667 673 ax.plt.set_array(coh.T.ravel())
668 674 self.titles.append(
669 675 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
670 676
671 677 ax = self.axes[4 * n + 3]
672 678 if ax.firsttime:
673 679 ax.plt = ax.pcolormesh(x, y, phase.T,
674 680 vmin=-180,
675 681 vmax=180,
676 682 cmap=plt.get_cmap(self.colormap_phase)
677 683 )
678 684 else:
679 685 ax.plt.set_array(phase.T.ravel())
680 686 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
681 687
682 688 self.saveTime = self.max_time
683 689
684 690
685 691 class PlotSpectraMeanData(PlotSpectraData):
686 692 '''
687 693 Plot for Spectra and Mean
688 694 '''
689 695 CODE = 'spc_mean'
690 696 colormap = 'jro'
691 697
692 698
693 699 class PlotRTIData(PlotData):
694 700 '''
695 701 Plot for RTI data
696 702 '''
697 703
698 704 CODE = 'rti'
699 705 colormap = 'jro'
700 706
701 707 def setup(self):
702 708 self.xaxis = 'time'
703 709 self.ncols = 1
704 710 self.nrows = len(self.data.channels)
705 711 self.nplots = len(self.data.channels)
706 712 self.ylabel = 'Range [km]'
707 713 self.cb_label = 'dB'
708 714 self.titles = ['{} Channel {}'.format(
709 715 self.CODE.upper(), x) for x in range(self.nrows)]
710 716
711 717 def plot(self):
712 718 self.x = self.times
713 719 self.y = self.data.heights
714 720 self.z = self.data[self.CODE]
715 721 self.z = numpy.ma.masked_invalid(self.z)
716 722
717 723 if self.decimation is None:
718 724 x, y, z = self.fill_gaps(self.x, self.y, self.z)
719 725 else:
720 726 x, y, z = self.fill_gaps(*self.decimate())
721 727
722 728 for n, ax in enumerate(self.axes):
723 729 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
724 730 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
725 731 if ax.firsttime:
726 732 ax.plt = ax.pcolormesh(x, y, z[n].T,
727 733 vmin=self.zmin,
728 734 vmax=self.zmax,
729 735 cmap=plt.get_cmap(self.colormap)
730 736 )
731 737 if self.showprofile:
732 738 ax.plot_profile = self.pf_axes[n].plot(
733 739 self.data['rti'][n][-1], self.y)[0]
734 740 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
735 741 color="k", linestyle="dashed", lw=1)[0]
736 742 else:
737 743 ax.collections.remove(ax.collections[0])
738 744 ax.plt = ax.pcolormesh(x, y, z[n].T,
739 745 vmin=self.zmin,
740 746 vmax=self.zmax,
741 747 cmap=plt.get_cmap(self.colormap)
742 748 )
743 749 if self.showprofile:
744 750 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
745 751 ax.plot_noise.set_data(numpy.repeat(
746 752 self.data['noise'][n][-1], len(self.y)), self.y)
747 753
748 754 self.saveTime = self.min_time
749 755
750 756
751 757 class PlotCOHData(PlotRTIData):
752 758 '''
753 759 Plot for Coherence data
754 760 '''
755 761
756 762 CODE = 'coh'
757 763
758 764 def setup(self):
759 765 self.xaxis = 'time'
760 766 self.ncols = 1
761 767 self.nrows = len(self.data.pairs)
762 768 self.nplots = len(self.data.pairs)
763 769 self.ylabel = 'Range [km]'
764 770 if self.CODE == 'coh':
765 771 self.cb_label = ''
766 772 self.titles = [
767 773 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
768 774 else:
769 775 self.cb_label = 'Degrees'
770 776 self.titles = [
771 777 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
772 778
773 779
774 780 class PlotPHASEData(PlotCOHData):
775 781 '''
776 782 Plot for Phase map data
777 783 '''
778 784
779 785 CODE = 'phase'
780 786 colormap = 'seismic'
781 787
782 788
783 789 class PlotNoiseData(PlotData):
784 790 '''
785 791 Plot for noise
786 792 '''
787 793
788 794 CODE = 'noise'
789 795
790 796 def setup(self):
791 797 self.xaxis = 'time'
792 798 self.ncols = 1
793 799 self.nrows = 1
794 800 self.nplots = 1
795 801 self.ylabel = 'Intensity [dB]'
796 802 self.titles = ['Noise']
797 803 self.colorbar = False
798 804
799 805 def plot(self):
800 806
801 807 x = self.times
802 808 xmin = self.min_time
803 809 xmax = xmin + self.xrange * 60 * 60
804 810 Y = self.data[self.CODE]
805 811
806 812 if self.axes[0].firsttime:
807 813 for ch in self.data.channels:
808 814 y = Y[ch]
809 815 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
810 816 plt.legend()
811 817 else:
812 818 for ch in self.data.channels:
813 819 y = Y[ch]
814 820 self.axes[0].lines[ch].set_data(x, y)
815 821
816 822 self.ymin = numpy.nanmin(Y) - 5
817 823 self.ymax = numpy.nanmax(Y) + 5
818 824 self.saveTime = self.min_time
819 825
820 826
821 827 class PlotSNRData(PlotRTIData):
822 828 '''
823 829 Plot for SNR Data
824 830 '''
825 831
826 832 CODE = 'snr'
827 833 colormap = 'jet'
828 834
829 835
830 836 class PlotDOPData(PlotRTIData):
831 837 '''
832 838 Plot for DOPPLER Data
833 839 '''
834 840
835 841 CODE = 'dop'
836 842 colormap = 'jet'
837 843
838 844
839 845 class PlotSkyMapData(PlotData):
840 846 '''
841 847 Plot for meteors detection data
842 848 '''
843 849
844 850 CODE = 'param'
845 851
846 852 def setup(self):
847 853
848 854 self.ncols = 1
849 855 self.nrows = 1
850 856 self.width = 7.2
851 857 self.height = 7.2
852 858 self.nplots = 1
853 859 self.xlabel = 'Zonal Zenith Angle (deg)'
854 860 self.ylabel = 'Meridional Zenith Angle (deg)'
855 861 self.polar = True
856 862 self.ymin = -180
857 863 self.ymax = 180
858 864 self.colorbar = False
859 865
860 866 def plot(self):
861 867
862 868 arrayParameters = numpy.concatenate(self.data['param'])
863 869 error = arrayParameters[:, -1]
864 870 indValid = numpy.where(error == 0)[0]
865 871 finalMeteor = arrayParameters[indValid, :]
866 872 finalAzimuth = finalMeteor[:, 3]
867 873 finalZenith = finalMeteor[:, 4]
868 874
869 875 x = finalAzimuth * numpy.pi / 180
870 876 y = finalZenith
871 877
872 878 ax = self.axes[0]
873 879
874 880 if ax.firsttime:
875 881 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
876 882 else:
877 883 ax.plot.set_data(x, y)
878 884
879 885 dt1 = self.getDateTime(self.min_time).strftime('%y/%m/%d %H:%M:%S')
880 886 dt2 = self.getDateTime(self.max_time).strftime('%y/%m/%d %H:%M:%S')
881 887 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
882 888 dt2,
883 889 len(x))
884 890 self.titles[0] = title
885 891 self.saveTime = self.max_time
886 892
887 893
888 894 class PlotParamData(PlotRTIData):
889 895 '''
890 896 Plot for data_param object
891 897 '''
892 898
893 899 CODE = 'param'
894 900 colormap = 'seismic'
895 901
896 902 def setup(self):
897 903 self.xaxis = 'time'
898 904 self.ncols = 1
899 905 self.nrows = self.data.shape(self.CODE)[0]
900 906 self.nplots = self.nrows
901 907 if self.showSNR:
902 908 self.nrows += 1
903 909 self.nplots += 1
904 910
905 911 self.ylabel = 'Height [km]'
906 912 if not self.titles:
907 913 self.titles = self.data.parameters \
908 914 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
909 915 if self.showSNR:
910 916 self.titles.append('SNR')
911 917
912 918 def plot(self):
913 919 self.data.normalize_heights()
914 920 self.x = self.times
915 921 self.y = self.data.heights
916 922 if self.showSNR:
917 923 self.z = numpy.concatenate(
918 924 (self.data[self.CODE], self.data['snr'])
919 925 )
920 926 else:
921 927 self.z = self.data[self.CODE]
922 928
923 929 self.z = numpy.ma.masked_invalid(self.z)
924 930
925 931 if self.decimation is None:
926 932 x, y, z = self.fill_gaps(self.x, self.y, self.z)
927 933 else:
928 934 x, y, z = self.fill_gaps(*self.decimate())
929 935
930 936 for n, ax in enumerate(self.axes):
931 937
932 938 self.zmax = self.zmax if self.zmax is not None else numpy.max(
933 939 self.z[n])
934 940 self.zmin = self.zmin if self.zmin is not None else numpy.min(
935 941 self.z[n])
936 942
937 943 if ax.firsttime:
938 944 if self.zlimits is not None:
939 945 self.zmin, self.zmax = self.zlimits[n]
940 946
941 947 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
942 948 vmin=self.zmin,
943 949 vmax=self.zmax,
944 950 cmap=self.cmaps[n]
945 951 )
946 952 else:
947 953 if self.zlimits is not None:
948 954 self.zmin, self.zmax = self.zlimits[n]
949 955 ax.collections.remove(ax.collections[0])
950 956 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
951 957 vmin=self.zmin,
952 958 vmax=self.zmax,
953 959 cmap=self.cmaps[n]
954 960 )
955 961
956 962 self.saveTime = self.min_time
957 963
958 964
959 965 class PlotOutputData(PlotParamData):
960 966 '''
961 967 Plot data_output object
962 968 '''
963 969
964 970 CODE = 'output'
965 971 colormap = 'seismic'
@@ -1,69 +1,70
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 20 setup(name = "schainpy",
21 21 version = __version__,
22 22 description = "Python tools to read, write and process Jicamarca data",
23 23 author = "Miguel Urco",
24 24 author_email = "miguel.urco@jro.igp.gob.pe",
25 25 url = "http://jro.igp.gob.pe",
26 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 39 'schainpy.gui.viewer.windows',
40 40 'schainpy.cli'},
41 41 ext_package = 'schainpy',
42 42 package_data = {'': ['schain.conf.template'],
43 43 'schainpy.gui.figures': ['*.png', '*.jpg'],
44 'schainpy.files': ['*.oga']
44 45 },
45 46 include_package_data = False,
46 47 scripts = ['schainpy/gui/schainGUI'],
47 48 ext_modules = [
48 49 Extension("cSchain", ["schainpy/model/proc/extensions.c"])
49 50 ],
50 51 entry_points = {
51 52 'console_scripts': [
52 53 'schain = schainpy.cli.cli:main',
53 54 ],
54 55 },
55 56 cmdclass = {'build_ext': build_ext},
56 57 setup_requires = ["numpy >= 1.11.2"],
57 58 install_requires = [
58 59 "scipy >= 0.14.0",
59 60 "h5py >= 2.2.1",
60 61 "matplotlib >= 2.0.0",
61 62 "pyfits >= 3.4",
62 63 "paramiko >= 2.1.2",
63 64 "paho-mqtt >= 1.2",
64 65 "zmq",
65 66 "fuzzywuzzy",
66 67 "click",
67 68 "python-Levenshtein"
68 69 ],
69 70 )
General Comments 0
You need to be logged in to leave comments. Login now