##// END OF EJS Templates
buscando samplerate
Jose Chavez -
r978:68700bf93d29
parent child
Show More
@@ -1,596 +1,605
1 1 '''
2 2 Created on Jul 3, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6 import os
7 7 import datetime
8 8 import numpy
9 9
10 10 try:
11 11 from gevent import sleep
12 12 except:
13 13 from time import sleep
14 14
15 15 from schainpy.model.data.jroheaderIO import RadarControllerHeader, SystemHeader
16 16 from schainpy.model.data.jrodata import Voltage
17 17 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation
18 18
19 19 try:
20 20 import digital_rf
21 21 except:
22 22 print 'You should install "digital_rf" module if you want to read Digital RF data'
23 23
24 24 class DigitalRFReader(ProcessingUnit):
25 25 '''
26 26 classdocs
27 27 '''
28 28
29 29 def __init__(self, **kwargs):
30 30 '''
31 31 Constructor
32 32 '''
33 33
34 34 ProcessingUnit.__init__(self, **kwargs)
35 35
36 36 self.dataOut = Voltage()
37 37 self.__printInfo = True
38 38 self.__flagDiscontinuousBlock = False
39 39 self.__bufferIndex = 9999999
40 40
41 41 self.__ippKm = None
42 42 self.__codeType = 0
43 43 self.__nCode = None
44 44 self.__nBaud = None
45 45 self.__code = None
46 46
47 47 def __getCurrentSecond(self):
48 48
49 49 return self.__thisUnixSample/self.__sample_rate
50 50
51 51 thisSecond = property(__getCurrentSecond, "I'm the 'thisSecond' property.")
52 52
53 53 def __setFileHeader(self):
54 54 '''
55 55 In this method will be initialized every parameter of dataOut object (header, no data)
56 56 '''
57 57 ippSeconds = 1.0*self.__nSamples/self.__sample_rate
58 58
59 59 nProfiles = 1.0/ippSeconds #Number of profiles in one second
60 60
61 61 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(ippKm=self.__ippKm,
62 62 txA=0,
63 63 txB=0,
64 64 nWindows=1,
65 65 nHeights=self.__nSamples,
66 66 firstHeight=self.__firstHeigth,
67 67 deltaHeight=self.__deltaHeigth,
68 68 codeType=self.__codeType,
69 69 nCode=self.__nCode, nBaud=self.__nBaud,
70 70 code = self.__code)
71 71
72 72 self.dataOut.systemHeaderObj = SystemHeader(nSamples=self.__nSamples,
73 73 nProfiles=nProfiles,
74 74 nChannels=len(self.__channelList),
75 75 adcResolution=14)
76 76
77 77 self.dataOut.type = "Voltage"
78 78
79 79 self.dataOut.data = None
80 80
81 81 self.dataOut.dtype = numpy.dtype([('real','<i8'),('imag','<i8')])
82 82
83 83 # self.dataOut.nChannels = 0
84 84
85 85 # self.dataOut.nHeights = 0
86 86
87 87 self.dataOut.nProfiles = nProfiles
88 88
89 89 self.dataOut.heightList = self.__firstHeigth + numpy.arange(self.__nSamples, dtype = numpy.float)*self.__deltaHeigth
90 90
91 91 self.dataOut.channelList = self.__channelList
92 92
93 93 self.dataOut.blocksize = self.dataOut.getNChannels() * self.dataOut.getNHeights()
94 94
95 95 # self.dataOut.channelIndexList = None
96 96
97 97 self.dataOut.flagNoData = True
98 98
99 99 #Set to TRUE if the data is discontinuous
100 100 self.dataOut.flagDiscontinuousBlock = False
101 101
102 102 self.dataOut.utctime = None
103 103
104 104 self.dataOut.timeZone = self.__timezone/60 #timezone like jroheader, difference in minutes between UTC and localtime
105 105
106 106 self.dataOut.dstFlag = 0
107 107
108 108 self.dataOut.errorCount = 0
109 109
110 110 self.dataOut.nCohInt = 1
111 111
112 112 self.dataOut.flagDecodeData = False #asumo que la data esta decodificada
113 113
114 114 self.dataOut.flagDeflipData = False #asumo que la data esta sin flip
115 115
116 116 self.dataOut.flagShiftFFT = False
117 117
118 118 self.dataOut.ippSeconds = ippSeconds
119 119
120 120 #Time interval between profiles
121 121 #self.dataOut.timeInterval = self.dataOut.ippSeconds * self.dataOut.nCohInt
122 122
123 123 self.dataOut.frequency = self.__frequency
124 124
125 125 self.dataOut.realtime = self.__online
126 126
127 127 def findDatafiles(self, path, startDate=None, endDate=None):
128 128
129 129 if not os.path.isdir(path):
130 130 return []
131 131
132 132 try:
133 133 digitalReadObj = digital_rf.DigitalRFReader(path, load_all_metadata=True)
134 134 except:
135 135 digitalReadObj = digital_rf.DigitalRFReader(path)
136 136
137 137 channelNameList = digitalReadObj.get_channels()
138 138
139 139 if not channelNameList:
140 140 return []
141 141
142 142 metadata_dict = digitalReadObj.get_rf_file_metadata(channelNameList[0])
143 143
144 144 sample_rate = metadata_dict['sample_rate'][0]
145 145
146 146 this_metadata_file = digitalReadObj.get_metadata(channelNameList[0])
147 147
148 148 try:
149 149 timezone = this_metadata_file['timezone'].value
150 150 except:
151 151 timezone = 0
152 152
153 153 startUTCSecond, endUTCSecond = digitalReadObj.get_bounds(channelNameList[0])/sample_rate - timezone
154 154
155 155 startDatetime = datetime.datetime.utcfromtimestamp(startUTCSecond)
156 156 endDatatime = datetime.datetime.utcfromtimestamp(endUTCSecond)
157 157
158 158 if not startDate:
159 159 startDate = startDatetime.date()
160 160
161 161 if not endDate:
162 162 endDate = endDatatime.date()
163 163
164 164 dateList = []
165 165
166 166 thisDatetime = startDatetime
167 167
168 168 while(thisDatetime<=endDatatime):
169 169
170 170 thisDate = thisDatetime.date()
171 171
172 172 if thisDate < startDate:
173 173 continue
174 174
175 175 if thisDate > endDate:
176 176 break
177 177
178 178 dateList.append(thisDate)
179 179 thisDatetime += datetime.timedelta(1)
180 180
181 181 return dateList
182 182
183 183 def setup(self, path = None,
184 184 startDate = None,
185 185 endDate = None,
186 186 startTime = datetime.time(0,0,0),
187 187 endTime = datetime.time(23,59,59),
188 188 channelList = None,
189 189 nSamples = None,
190 190 ippKm = 60,
191 191 online = False,
192 192 delay = 60,
193 193 buffer_size = 1024,
194 194 **kwargs):
195 195 '''
196 196 In this method we should set all initial parameters.
197 197
198 198 Inputs:
199 199 path
200 200 startDate
201 201 endDate
202 202 startTime
203 203 endTime
204 204 set
205 205 expLabel
206 206 ext
207 207 online
208 208 delay
209 209 '''
210 210
211 211 if not os.path.isdir(path):
212 212 raise ValueError, "[Reading] Directory %s does not exist" %path
213 213
214 214 try:
215 215 self.digitalReadObj = digital_rf.DigitalRFReader(path, load_all_metadata=True)
216 216 except:
217 217 self.digitalReadObj = digital_rf.DigitalRFReader(path)
218 218
219 219 channelNameList = self.digitalReadObj.get_channels()
220 220
221 221 if not channelNameList:
222 222 raise ValueError, "[Reading] Directory %s does not have any files" %path
223 223
224 224 if not channelList:
225 225 channelList = range(len(channelNameList))
226 226
227 227 ########## Reading metadata ######################
228 228
229 229 metadata_dict = self.digitalReadObj.get_properties(channelNameList[channelList[0]])
230 230
231 231 self.__sample_rate = metadata_dict['sample_rate_numerator'] / metadata_dict['sample_rate_denominator']
232 232 # self.__samples_per_file = metadata_dict['samples_per_file'][0]
233 233 self.__deltaHeigth = 1e6*0.15/self.__sample_rate ## why 0.15?
234 234
235 235 this_metadata_file = self.digitalReadObj.get_digital_metadata(channelNameList[channelList[0]])
236 236 metadata_bounds = this_metadata_file.get_bounds()
237 237 self.fixed_metadata_dict = this_metadata_file.read(metadata_bounds[0])[metadata_bounds[0]] ##GET FIRST HEADER
238 238
239 239 self.__frequency = None
240 240 try:
241 241 self.__frequency = self.fixed_metadata_dict['frequency']
242 242 except:
243 243 self.__frequency = None
244 244
245 245 try:
246 246 self.__timezone = self.fixed_metadata_dict['timezone']
247 247 except:
248 248 self.__timezone = 0
249 249
250 250 self.__firstHeigth = 0
251 251
252 252
253 253 try:
254 254 codeType = self.fixed_metadata_dict['codeType']
255 255 except:
256 256 codeType = 0
257 257
258 258 nCode = 1
259 259 nBaud = 1
260 260 code = numpy.ones((nCode, nBaud), dtype=numpy.int)
261 261
262 262 if codeType:
263 263 nCode = self.fixed_metadata_dict['nCode']
264 264 nBaud = self.fixed_metadata_dict['nBaud']
265 265 code = self.fixed_metadata_dict['code']
266 266
267 267 if not ippKm:
268 268 try:
269 269 #seconds to km
270 270 ippKm = 1e6*0.15*self.fixed_metadata_dict['ipp']
271 271 except:
272 272 ippKm = None
273 273 ####################################################
274 274 startUTCSecond = None
275 275 endUTCSecond = None
276 276
277 277 if startDate:
278 278 startDatetime = datetime.datetime.combine(startDate, startTime)
279 279 startUTCSecond = (startDatetime-datetime.datetime(1970,1,1)).total_seconds() + self.__timezone
280 280
281 281 if endDate:
282 282 endDatetime = datetime.datetime.combine(endDate, endTime)
283 283 endUTCSecond = (endDatetime-datetime.datetime(1970,1,1)).total_seconds() + self.__timezone
284 284
285 285 start_index, end_index = self.digitalReadObj.get_bounds(channelNameList[channelList[0]])
286 286
287 287 if not startUTCSecond:
288 288 startUTCSecond = start_index/self.__sample_rate
289 289
290 290 if start_index > startUTCSecond*self.__sample_rate:
291 291 startUTCSecond = start_index/self.__sample_rate
292 292
293 293 if not endUTCSecond:
294 294 endUTCSecond = end_index/self.__sample_rate
295 295
296 296 if end_index < endUTCSecond*self.__sample_rate:
297 297 endUTCSecond = end_index/self.__sample_rate
298 298
299 299 if not nSamples:
300 300 if not ippKm:
301 301 raise ValueError, "[Reading] nSamples or ippKm should be defined"
302 302 nSamples = int(ippKm / (1e6*0.15/self.__sample_rate))
303 303
304 304 channelBoundList = []
305 305 channelNameListFiltered = []
306 306
307 307 for thisIndexChannel in channelList:
308 308 thisChannelName = channelNameList[thisIndexChannel]
309 309 start_index, end_index = self.digitalReadObj.get_bounds(thisChannelName)
310 310 channelBoundList.append((start_index, end_index))
311 311 channelNameListFiltered.append(thisChannelName)
312 312
313 313 self.profileIndex = 0
314 314
315 315 self.__delay = delay
316 316 self.__ippKm = ippKm
317 317 self.__codeType = codeType
318 318 self.__nCode = nCode
319 319 self.__nBaud = nBaud
320 320 self.__code = code
321 321
322 322 self.__datapath = path
323 323 self.__online = online
324 324 self.__channelList = channelList
325 325 self.__channelNameList = channelNameListFiltered
326 326 self.__channelBoundList = channelBoundList
327 327 self.__nSamples = nSamples
328 328 self.__samples_to_read = long(buffer_size*nSamples) #FIJO: AHORA 40
329 329 self.__nChannels = len(self.__channelList)
330 330
331 331 self.__startUTCSecond = startUTCSecond
332 332 self.__endUTCSecond = endUTCSecond
333 333
334 334 self.__timeInterval = 1.0 * self.__samples_to_read/self.__sample_rate #Time interval
335 335
336 336 if online:
337 337 # self.__thisUnixSample = int(endUTCSecond*self.__sample_rate - 4*self.__samples_to_read)
338 338 startUTCSecond = numpy.floor(endUTCSecond)
339 339
340 340 self.__thisUnixSample = long(startUTCSecond*self.__sample_rate) - self.__samples_to_read ##por que en el otro metodo lo primero q se hace es sumar samplestoread
341 341
342 342 self.__data_buffer = numpy.zeros((self.__nChannels, self.__samples_to_read), dtype = numpy.complex)
343 343
344 344 self.__setFileHeader()
345 345 self.isConfig = True
346 346
347 347 print "[Reading] Digital RF Data was found from %s to %s " %(
348 348 datetime.datetime.utcfromtimestamp(self.__startUTCSecond - self.__timezone),
349 349 datetime.datetime.utcfromtimestamp(self.__endUTCSecond - self.__timezone)
350 350 )
351 351
352 352 print "[Reading] Starting process from %s to %s" %(datetime.datetime.utcfromtimestamp(startUTCSecond - self.__timezone),
353 353 datetime.datetime.utcfromtimestamp(endUTCSecond - self.__timezone)
354 354 )
355 355
356 356 def __reload(self):
357 357 # print
358 358 # print "%s not in range [%s, %s]" %(
359 359 # datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
360 360 # datetime.datetime.utcfromtimestamp(self.__startUTCSecond - self.__timezone),
361 361 # datetime.datetime.utcfromtimestamp(self.__endUTCSecond - self.__timezone)
362 362 # )
363 363 print "[Reading] reloading metadata ..."
364 364
365 365 try:
366 366 self.digitalReadObj.reload(complete_update=True)
367 367 except:
368 368 self.digitalReadObj.reload()
369 369
370 370 start_index, end_index = self.digitalReadObj.get_bounds(self.__channelNameList[self.__channelList[0]])
371 371
372 372 if start_index > self.__startUTCSecond*self.__sample_rate:
373 373 self.__startUTCSecond = 1.0*start_index/self.__sample_rate
374 374
375 375 if end_index > self.__endUTCSecond*self.__sample_rate:
376 376 self.__endUTCSecond = 1.0*end_index/self.__sample_rate
377 377 print
378 378 print "[Reading] New timerange found [%s, %s] " %(
379 379 datetime.datetime.utcfromtimestamp(self.__startUTCSecond - self.__timezone),
380 380 datetime.datetime.utcfromtimestamp(self.__endUTCSecond - self.__timezone)
381 381 )
382 382
383 383 return True
384 384
385 385 return False
386 386
387 387 def __readNextBlock(self, seconds=30, volt_scale = 218776):
388 388 '''
389 389 '''
390 390
391 391 #Set the next data
392 392 self.__flagDiscontinuousBlock = False
393 393 self.__thisUnixSample += self.__samples_to_read
394 394
395 395 if self.__thisUnixSample + 2*self.__samples_to_read > self.__endUTCSecond*self.__sample_rate:
396 396 print "[Reading] There are no more data into selected time-range"
397 397 if self.__online:
398 398 self.__reload()
399 399 else:
400 400 return False
401 401
402 402 if self.__thisUnixSample + 2*self.__samples_to_read > self.__endUTCSecond*self.__sample_rate:
403 403 return False
404 404 self.__thisUnixSample -= self.__samples_to_read
405 405
406 406 indexChannel = 0
407 407
408 408 dataOk = False
409 409
410 410 for thisChannelName in self.__channelNameList: ##TODO VARIOS CHANNELS?
411 411
412 412 try:
413 413 result = self.digitalReadObj.read_vector_c81d(self.__thisUnixSample,
414 414 self.__samples_to_read,
415 415 thisChannelName)
416 416 except IOError, e:
417 417 #read next profile
418 418 self.__flagDiscontinuousBlock = True
419 419 print "[Reading] %s" %datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone), e
420 420 break
421 421
422 422 if result.shape[0] != self.__samples_to_read:
423 423 self.__flagDiscontinuousBlock = True
424 424 print "[Reading] %s: Too few samples were found, just %d/%d samples" %(datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
425 425 result.shape[0],
426 426 self.__samples_to_read)
427 427 break
428 428
429 429 self.__data_buffer[indexChannel,:] = result*volt_scale
430 430
431 431 indexChannel += 1
432 432
433 433 dataOk = True
434 434
435 435 self.__utctime = self.__thisUnixSample/self.__sample_rate
436 436
437 437 if not dataOk:
438 438 return False
439 439
440 440 print "[Reading] %s: %d samples <> %f sec" %(datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
441 441 self.__samples_to_read,
442 442 self.__timeInterval)
443 443
444 444 self.__bufferIndex = 0
445 445
446 446 return True
447 447
448 448 def __isBufferEmpty(self):
449 449 return self.__bufferIndex > self.__samples_to_read - self.__nSamples #40960 - 40
450 450
451 451 def getData(self, seconds=30, nTries=5):
452 452
453 453 '''
454 454 This method gets the data from files and put the data into the dataOut object
455 455
456 456 In addition, increase el the buffer counter in one.
457 457
458 458 Return:
459 459 data : retorna un perfil de voltages (alturas * canales) copiados desde el
460 460 buffer. Si no hay mas archivos a leer retorna None.
461 461
462 462 Affected:
463 463 self.dataOut
464 464 self.profileIndex
465 465 self.flagDiscontinuousBlock
466 466 self.flagIsNewBlock
467 467 '''
468 468
469 469 err_counter = 0
470 470 self.dataOut.flagNoData = True
471 471
472 472 if self.__isBufferEmpty():
473 473
474 474 self.__flagDiscontinuousBlock = False
475 475
476 476 while True:
477 477 if self.__readNextBlock():
478 478 break
479 479 if self.__thisUnixSample > self.__endUTCSecond*self.__sample_rate:
480 480 return False
481 481
482 482 if self.__flagDiscontinuousBlock:
483 483 print '[Reading] discontinuous block found ... continue with the next block'
484 484 continue
485 485
486 486 if not self.__online:
487 487 return False
488 488
489 489 err_counter += 1
490 490 if err_counter > nTries:
491 491 return False
492 492
493 493 print '[Reading] waiting %d seconds to read a new block' %seconds
494 494 sleep(seconds)
495 495
496 496 self.dataOut.data = self.__data_buffer[:,self.__bufferIndex:self.__bufferIndex+self.__nSamples]
497 497 self.dataOut.utctime = (self.__thisUnixSample + self.__bufferIndex)/self.__sample_rate
498 498 self.dataOut.flagNoData = False
499 499 self.dataOut.flagDiscontinuousBlock = self.__flagDiscontinuousBlock
500 500 self.dataOut.profileIndex = self.profileIndex
501 501
502 502 self.__bufferIndex += self.__nSamples
503 503 self.profileIndex += 1
504 504
505 505 if self.profileIndex == self.dataOut.nProfiles:
506 506 self.profileIndex = 0
507 507
508 508 return True
509 509
510 510 def printInfo(self):
511 511 '''
512 512 '''
513 513 if self.__printInfo == False:
514 514 return
515 515
516 516 # self.systemHeaderObj.printInfo()
517 517 # self.radarControllerHeaderObj.printInfo()
518 518
519 519 self.__printInfo = False
520 520
521 521 def printNumberOfBlock(self):
522 522 '''
523 523 '''
524 524 return
525 525 #print self.profileIndex
526 526
527 527 def run(self, **kwargs):
528 528 '''
529 529 This method will be called many times so here you should put all your code
530 530 '''
531 531
532 532 if not self.isConfig:
533 533 self.setup(**kwargs)
534 534
535 535 self.getData(seconds=self.__delay)
536 536
537 537 return
538 538
539 539 class DigitalRFWriter(Operation):
540 540 '''
541 541 classdocs
542 542 '''
543 543
544 544 def __init__(self, **kwargs):
545 545 '''
546 546 Constructor
547 547 '''
548 548 Operation.__init__(self, **kwargs)
549 549 self.dataOut = None
550 550
551 551 def setup(self, dataIn, path, blocksPerFile, set=0, ext='.h5'):
552 552 '''
553 553 In this method we should set all initial parameters.
554 554
555 555 Input:
556 556 dataIn : Input data will also be outputa data
557 557
558 558 '''
559 559 self.dataOut = dataIn
560 560
561 561
562 562
563 563
564 564
565 565 self.isConfig = True
566 566
567 567 return
568 568
569 569 def run(self, dataIn, path=None, **kwargs):
570 570 '''
571 571 This method will be called many times so here you should put all your code
572 572
573 573 Inputs:
574 574
575 575 dataIn : object with the data
576 576
577 577 '''
578 578 print dir(dataIn)
579 579 print 'blocksize', dataIn.blocksize
580 580 print 'channelIndexList', dataIn.channelIndexList
581 581 print 'ippSeconds', dataIn.ippSeconds
582 582 print 'frequency', dataIn.frequency
583 583 print 'nProfiles', dataIn.nProfiles
584 print 'deltaH', dataIn.getDeltaH()
584 585 print 'systemHeaderObj.nSamples', dataIn.systemHeaderObj.nSamples
586 nSamples = dataIn.systemHeaderObj.nSamples
587 ippSeconds = dataIn.ippSeconds
588
589 self.__samplerate = 1.0*nSamples/ippSeconds
590 # ippKm = 1e6*0.15*self.fixed_metadata_dict['ipp']
591 # nSamples = int(ippKm / (1e6*0.15/self.__sample_rate))
592 # ippSeconds = 1.0*self.__nSamples/self.__sample_rate
593
585 594 if not self.isConfig:
586 595 self.setup(dataIn, path, **kwargs)
587 596
588 597
589 598 if __name__ == '__main__':
590 599
591 600 readObj = DigitalRFReader()
592 601
593 602 while True:
594 603 readObj.run(path='/home/jchavez/jicamarca/mocked_data/')
595 604 # readObj.printInfo()
596 605 readObj.printNumberOfBlock()
@@ -1,1 +1,1
1 <Project description="Segundo Test" id="191" name="test01"><ReadUnit datatype="VoltageReader" id="1911" inputId="0" name="VoltageReader"><Operation id="19111" name="run" priority="1" type="self"><Parameter format="str" id="191111" name="datatype" value="VoltageReader" /><Parameter format="str" id="191112" name="path" value="/home/jchavez/jicamarca/jro_data/rawdata" /><Parameter format="date" id="191113" name="startDate" value="2010/10/28" /><Parameter format="date" id="191114" name="endDate" value="2017/10/28" /><Parameter format="time" id="191115" name="startTime" value="00:00:00" /><Parameter format="time" id="191116" name="endTime" value="23:59:59" /><Parameter format="int" id="191118" name="online" value="0" /><Parameter format="int" id="191119" name="walk" value="0" /></Operation><Operation id="19112" name="printNumberOfBlock" priority="2" type="self" /></ReadUnit><ProcUnit datatype="VoltageProc" id="1912" inputId="1911" name="VoltageProc"><Operation id="19121" name="run" priority="1" type="self" /><Operation id="19122" name="DigitalRFWriter" priority="2" type="other"><Parameter format="str" id="191221" name="path" value="/home/jchavez/jicamarca/data_sink/" /></Operation></ProcUnit></Project>
1 <Project description="Segundo Test" id="191" name="test01"><ReadUnit datatype="VoltageReader" id="1911" inputId="0" name="VoltageReader"><Operation id="19111" name="run" priority="1" type="self"><Parameter format="str" id="191111" name="datatype" value="VoltageReader" /><Parameter format="str" id="191112" name="path" value="/home/jchavez/jicamarca/jro_data/rawdata" /><Parameter format="date" id="191113" name="startDate" value="2010/10/28" /><Parameter format="date" id="191114" name="endDate" value="2017/10/28" /><Parameter format="time" id="191115" name="startTime" value="00:00:00" /><Parameter format="time" id="191116" name="endTime" value="23:59:59" /><Parameter format="int" id="191118" name="online" value="0" /><Parameter format="int" id="191119" name="walk" value="0" /></Operation><Operation id="19112" name="printNumberOfBlock" priority="2" type="self" /></ReadUnit><ProcUnit datatype="VoltageProc" id="1912" inputId="1911" name="VoltageProc"><Operation id="19121" name="run" priority="1" type="self" /><Operation id="19122" name="DigitalRFWriter" priority="2" type="other"><Parameter format="str" id="191221" name="path" value="/home/jchavez/jicamarca/data_sink/" /></Operation></ProcUnit></Project> No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now