From 3fb7c359028f170fccfd865c2f1945db66a10802 2017-09-25 19:09:07 From: Juan C. Espinoza Date: 2017-09-25 19:09:07 Subject: [PATCH] Change multiSchain by MPProject --- diff --git a/schainpy/controller.py b/schainpy/controller.py index 47e0c03..412bc2d 100644 --- a/schainpy/controller.py +++ b/schainpy/controller.py @@ -9,56 +9,53 @@ import datetime import traceback import math import time -from multiprocessing import Process, Queue, cpu_count - -import schainpy -import schainpy.admin -from schainpy.utils.log import logToFile +from multiprocessing import Process, cpu_count from xml.etree.ElementTree import ElementTree, Element, SubElement, tostring from xml.dom import minidom +import schainpy +import schainpy.admin from schainpy.model import * -from time import sleep - - - -def prettify(elem): - """Return a pretty-printed XML string for the Element. - """ - rough_string = tostring(elem, 'utf-8') - reparsed = minidom.parseString(rough_string) - return reparsed.toprettyxml(indent=" ") - -def multiSchain(child, nProcess=cpu_count(), startDate=None, endDate=None, by_day=False): - skip = 0 - cursor = 0 - nFiles = None - processes = [] - dt1 = datetime.datetime.strptime(startDate, '%Y/%m/%d') - dt2 = datetime.datetime.strptime(endDate, '%Y/%m/%d') +from schainpy.utils import log + +DTYPES = { + 'Voltage': '.r', + 'Spectra': '.pdata' +} + +def MPProject(project, n=cpu_count()): + ''' + Project wrapper to run schain in n processes + ''' + + rconf = project.getReadUnitObj() + op = rconf.getOperationObj('run') + dt1 = op.getParameterValue('startDate') + dt2 = op.getParameterValue('endDate') days = (dt2 - dt1).days - + for day in range(days+1): skip = 0 cursor = 0 - q = Queue() processes = [] - dt = (dt1 + datetime.timedelta(day)).strftime('%Y/%m/%d') - firstProcess = Process(target=child, args=(cursor, skip, q, dt)) - firstProcess.start() - if by_day: - continue - nFiles = q.get() - if nFiles==0: + dt = dt1 + datetime.timedelta(day) + dt_str = dt.strftime('%Y/%m/%d') + reader = JRODataReader() + paths, files = reader.searchFilesOffLine(path=rconf.path, + startDate=dt, + endDate=dt, + ext=DTYPES[rconf.datatype]) + nFiles = len(files) + if nFiles == 0: continue - firstProcess.terminate() - skip = int(math.ceil(nFiles/nProcess)) - while True: - processes.append(Process(target=child, args=(cursor, skip, q, dt))) - processes[cursor].start() - if nFiles < cursor*skip: - break + skip = int(math.ceil(nFiles/n)) + while nFiles > cursor*skip: + rconf.update(startDate=dt_str, endDate=dt_str, cursor=cursor, + skip=skip) + p = project.clone() + p.start() + processes.append(p) cursor += 1 def beforeExit(exctype, value, trace): @@ -75,7 +72,6 @@ def multiSchain(child, nProcess=cpu_count(), startDate=None, endDate=None, by_da time.sleep(3) - class ParameterConf(): id = None @@ -112,7 +108,7 @@ class ParameterConf(): return self.__formated_value if value == '': - raise ValueError, "%s: This parameter value is empty" %self.name + raise ValueError, '%s: This parameter value is empty' %self.name if format == 'list': strList = value.split(',') @@ -122,10 +118,10 @@ class ParameterConf(): return self.__formated_value if format == 'intlist': - """ + ''' Example: value = (0,1,2) - """ + ''' new_value = ast.literal_eval(value) @@ -137,10 +133,10 @@ class ParameterConf(): return self.__formated_value if format == 'floatlist': - """ + ''' Example: value = (0.5, 1.4, 2.7) - """ + ''' new_value = ast.literal_eval(value) @@ -170,38 +166,38 @@ class ParameterConf(): return self.__formated_value if format == 'pairslist': - """ + ''' Example: value = (0,1),(1,2) - """ + ''' new_value = ast.literal_eval(value) if type(new_value) not in (tuple, list): - raise ValueError, "%s has to be a tuple or list of pairs" %value + raise ValueError, '%s has to be a tuple or list of pairs' %value if type(new_value[0]) not in (tuple, list): if len(new_value) != 2: - raise ValueError, "%s has to be a tuple or list of pairs" %value + raise ValueError, '%s has to be a tuple or list of pairs' %value new_value = [new_value] for thisPair in new_value: if len(thisPair) != 2: - raise ValueError, "%s has to be a tuple or list of pairs" %value + raise ValueError, '%s has to be a tuple or list of pairs' %value self.__formated_value = new_value return self.__formated_value if format == 'multilist': - """ + ''' Example: value = (0,1,2),(3,4,5) - """ + ''' multiList = ast.literal_eval(value) if type(multiList[0]) == int: - multiList = ast.literal_eval("(" + value + ")") + multiList = ast.literal_eval('(' + value + ')') self.__formated_value = multiList @@ -263,9 +259,9 @@ class ParameterConf(): def printattr(self): - print "Parameter[%s]: name = %s, value = %s, format = %s" %(self.id, self.name, self.value, self.format) + print 'Parameter[%s]: name = %s, value = %s, format = %s' %(self.id, self.name, self.value, self.format) -class OperationConf(): +class OperationConf(): id = None name = None @@ -371,7 +367,9 @@ class OperationConf(): self.parmConfObjList = [] def addParameter(self, name, value, format='str'): - + + if value is None: + return None id = self.__getNewId() parmConfObj = ParameterConf() @@ -431,7 +429,7 @@ class OperationConf(): def printattr(self): - print "%s[%s]: name = %s, type = %s, priority = %s" %(self.ELEMENTNAME, + print '%s[%s]: name = %s, type = %s, priority = %s' %(self.ELEMENTNAME, self.id, self.name, self.type, @@ -444,12 +442,11 @@ class OperationConf(): if self.type == 'self': - raise ValueError, "This operation type cannot be created" + raise ValueError, 'This operation type cannot be created' - if self.type == 'plotter': - #Plotter(plotter_name) + if self.type == 'plotter': if not plotter_queue: - raise ValueError, "plotter_queue is not defined. Use:\nmyProject = Project()\nmyProject.setPlotterQueue(plotter_queue)" + raise ValueError, 'plotter_queue is not defined. Use:\nmyProject = Project()\nmyProject.setPlotterQueue(plotter_queue)' opObj = Plotter(self.name, plotter_queue) @@ -564,7 +561,7 @@ class ProcUnitConf(): #Compatible with old signal chain version if datatype==None and name==None: - raise ValueError, "datatype or name should be defined" + raise ValueError, 'datatype or name should be defined' if name==None: if 'Proc' in datatype: @@ -595,7 +592,7 @@ class ProcUnitConf(): def addParameter(self, **kwargs): ''' - Add parameters to "run" operation + Add parameters to 'run' operation ''' opObj = self.opConfObjList[0] @@ -633,11 +630,11 @@ class ProcUnitConf(): self.datatype = upElement.get('datatype') self.inputId = upElement.get('inputId') - if self.ELEMENTNAME == "ReadUnit": - self.datatype = self.datatype.replace("Reader", "") + if self.ELEMENTNAME == 'ReadUnit': + self.datatype = self.datatype.replace('Reader', '') - if self.ELEMENTNAME == "ProcUnit": - self.datatype = self.datatype.replace("Proc", "") + if self.ELEMENTNAME == 'ProcUnit': + self.datatype = self.datatype.replace('Proc', '') if self.inputId == 'None': self.inputId = '0' @@ -653,7 +650,7 @@ class ProcUnitConf(): def printattr(self): - print "%s[%s]: name = %s, datatype = %s, inputId = %s" %(self.ELEMENTNAME, + print '%s[%s]: name = %s, datatype = %s, inputId = %s' %(self.ELEMENTNAME, self.id, self.name, self.datatype, @@ -707,17 +704,9 @@ class ProcUnitConf(): kwargs[parmConfObj.name] = parmConfObj.getValue() - #ini = time.time() - - #print "\tRunning the '%s' operation with %s" %(opConfObj.name, opConfObj.id) sts = self.procUnitObj.call(opType = opConfObj.type, opName = opConfObj.name, opId = opConfObj.id) - - # total_time = time.time() - ini - # - # if total_time > 0.002: - # print "%s::%s took %f seconds" %(self.name, opConfObj.name, total_time) is_ok = is_ok or sts @@ -762,11 +751,12 @@ class ReadUnitConf(ProcUnitConf): return self.ELEMENTNAME - def setup(self, id, name, datatype, path='', startDate="", endDate="", startTime="", - endTime="", parentId=None, queue=None, server=None, **kwargs): + def setup(self, id, name, datatype, path='', startDate='', endDate='', + startTime='', endTime='', parentId=None, server=None, **kwargs): + #Compatible with old signal chain version if datatype==None and name==None: - raise ValueError, "datatype or name should be defined" + raise ValueError, 'datatype or name should be defined' if name==None: if 'Reader' in datatype: @@ -785,39 +775,28 @@ class ReadUnitConf(ProcUnitConf): self.endDate = endDate self.startTime = startTime self.endTime = endTime - self.inputId = '0' self.parentId = parentId - self.queue = queue self.server = server self.addRunOperation(**kwargs) - def update(self, datatype, path, startDate, endDate, startTime, endTime, parentId=None, name=None, **kwargs): + def update(self, **kwargs): - #Compatible with old signal chain version - if datatype==None and name==None: - raise ValueError, "datatype or name should be defined" - - if name==None: + if 'datatype' in kwargs: + datatype = kwargs.pop('datatype') if 'Reader' in datatype: - name = datatype + self.name = datatype else: - name = '%sReader' %(datatype) - - if datatype==None: - datatype = name.replace('Reader','') - - self.datatype = datatype - self.name = name - self.path = path - self.startDate = startDate - self.endDate = endDate - self.startTime = startTime - self.endTime = endTime + self.name = '%sReader' %(datatype) + self.datatype = self.name.replace('Reader', '') + attrs = ('path', 'startDate', 'endDate', 'startTime', 'endTime', 'parentId') + + for attr in attrs: + if attr in kwargs: + setattr(self, attr, kwargs.pop(attr)) + self.inputId = '0' - self.parentId = parentId - self.updateRunOperation(**kwargs) def removeOperations(self): @@ -832,13 +811,13 @@ class ReadUnitConf(ProcUnitConf): opObj = self.addOperation(name = 'run', optype = 'self') if self.server is None: - opObj.addParameter(name='datatype' , value=self.datatype, format='str') - opObj.addParameter(name='path' , value=self.path, format='str') - opObj.addParameter(name='startDate' , value=self.startDate, format='date') - opObj.addParameter(name='endDate' , value=self.endDate, format='date') - opObj.addParameter(name='startTime' , value=self.startTime, format='time') - opObj.addParameter(name='endTime' , value=self.endTime, format='time') - opObj.addParameter(name='queue' , value=self.queue, format='obj') + opObj.addParameter(name='datatype', value=self.datatype, format='str') + opObj.addParameter(name='path', value=self.path, format='str') + opObj.addParameter(name='startDate', value=self.startDate, format='date') + opObj.addParameter(name='endDate', value=self.endDate, format='date') + opObj.addParameter(name='startTime', value=self.startTime, format='time') + opObj.addParameter(name='endTime', value=self.endTime, format='time') + for key, value in kwargs.items(): opObj.addParameter(name=key, value=value, format=type(value).__name__) else: @@ -849,32 +828,21 @@ class ReadUnitConf(ProcUnitConf): def updateRunOperation(self, **kwargs): - opObj = self.getOperationObj(name = 'run') + opObj = self.getOperationObj(name='run') opObj.removeParameters() - opObj.addParameter(name='datatype' , value=self.datatype, format='str') - opObj.addParameter(name='path' , value=self.path, format='str') - opObj.addParameter(name='startDate' , value=self.startDate, format='date') - opObj.addParameter(name='endDate' , value=self.endDate, format='date') - opObj.addParameter(name='startTime' , value=self.startTime, format='time') - opObj.addParameter(name='endTime' , value=self.endTime, format='time') - + opObj.addParameter(name='datatype', value=self.datatype, format='str') + opObj.addParameter(name='path', value=self.path, format='str') + opObj.addParameter(name='startDate', value=self.startDate, format='date') + opObj.addParameter(name='endDate', value=self.endDate, format='date') + opObj.addParameter(name='startTime', value=self.startTime, format='time') + opObj.addParameter(name='endTime', value=self.endTime, format='time') + for key, value in kwargs.items(): opObj.addParameter(name=key, value=value, format=type(value).__name__) return opObj - # def makeXml(self, projectElement): - # - # procUnitElement = SubElement(projectElement, self.ELEMENTNAME) - # procUnitElement.set('id', str(self.id)) - # procUnitElement.set('name', self.name) - # procUnitElement.set('datatype', self.datatype) - # procUnitElement.set('inputId', str(self.inputId)) - # - # for opConfObj in self.opConfObjList: - # opConfObj.makeXml(procUnitElement) - def readXml(self, upElement): self.id = upElement.get('id') @@ -882,8 +850,8 @@ class ReadUnitConf(ProcUnitConf): self.datatype = upElement.get('datatype') self.inputId = upElement.get('inputId') - if self.ELEMENTNAME == "ReadUnit": - self.datatype = self.datatype.replace("Reader", "") + if self.ELEMENTNAME == 'ReadUnit': + self.datatype = self.datatype.replace('Reader', '') if self.inputId == 'None': self.inputId = '0' @@ -905,8 +873,9 @@ class ReadUnitConf(ProcUnitConf): self.endTime = opConfObj.getParameterValue('endTime') class Project(Process): + id = None - name = None + # name = None description = None filename = None @@ -916,17 +885,17 @@ class Project(Process): plotterQueue = None - def __init__(self, plotter_queue=None, logfile=None): + def __init__(self, plotter_queue=None): + Process.__init__(self) self.id = None - self.name = None + # self.name = None self.description = None - if logfile is not None: - logToFile(logfile) + self.plotterQueue = plotter_queue self.procUnitConfObjDict = {} - + def __getNewId(self): idList = self.procUnitConfObjDict.keys() @@ -972,18 +941,28 @@ class Project(Process): self.procUnitConfObjDict = newProcUnitConfObjDict - def setup(self, id, name, description): + def setup(self, id, name='', description=''): + print + print '*'*60 + print ' Starting SIGNAL CHAIN PROCESSING v%s ' % schainpy.__version__ + print '*'*60 + print self.id = str(id) - self.name = name self.description = description def update(self, name, description): - self.name = name self.description = description + def clone(self): + + p = Project() + p.procUnitConfObjDict = self.procUnitConfObjDict + return p + def addReadUnit(self, id=None, datatype=None, name=None, **kwargs): + if id is None: idReadUnit = self.__getNewId() else: @@ -1021,7 +1000,7 @@ class Project(Process): def getReadUnitObj(self): for obj in self.procUnitConfObjDict.values(): - if obj.getElementName() == "ReadUnit": + if obj.getElementName() == 'ReadUnit': return obj return None @@ -1066,20 +1045,20 @@ class Project(Process): if self.filename: filename = self.filename else: - filename = "schain.xml" + filename = 'schain.xml' if not filename: - print "filename has not been defined. Use setFilename(filename) for do it." + print 'filename has not been defined. Use setFilename(filename) for do it.' return 0 abs_file = os.path.abspath(filename) if not os.access(os.path.dirname(abs_file), os.W_OK): - print "No write permission on %s" %os.path.dirname(abs_file) + print 'No write permission on %s' %os.path.dirname(abs_file) return 0 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)): - print "File %s already exists and it could not be overwriten" %abs_file + print 'File %s already exists and it could not be overwriten' %abs_file return 0 self.makeXml() @@ -1093,13 +1072,13 @@ class Project(Process): def readXml(self, filename = None): if not filename: - print "filename is not defined" + print 'filename is not defined' return 0 abs_file = os.path.abspath(filename) if not os.path.isfile(abs_file): - print "%s file does not exist" %abs_file + print '%s file does not exist' %abs_file return 0 self.projectElement = None @@ -1108,7 +1087,7 @@ class Project(Process): try: self.projectElement = ElementTree().parse(abs_file) except: - print "Error reading %s, verify file format" %filename + print 'Error reading %s, verify file format' %filename return 0 self.project = self.projectElement.tag @@ -1145,10 +1124,10 @@ class Project(Process): def printattr(self): - print "Project[%s]: name = %s, description = %s" %(self.id, - self.name, - self.description) - + print 'Project[%s]: name = %s, description = %s' %(self.id, + self.name, + self.description) + for procUnitConfObj in self.procUnitConfObjDict.values(): procUnitConfObj.printattr() @@ -1179,7 +1158,7 @@ class Project(Process): self.__connect(puObjIN, thisPUObj) - def __handleError(self, procUnitConfObj, send_email=True): + def __handleError(self, procUnitConfObj, send_email=False): import socket @@ -1187,33 +1166,33 @@ class Project(Process): sys.exc_info()[1], sys.exc_info()[2]) - print "***** Error occurred in %s *****" %(procUnitConfObj.name) - print "***** %s" %err[-1] + print '***** Error occurred in %s *****' %(procUnitConfObj.name) + print '***** %s' %err[-1] - message = "".join(err) + message = ''.join(err) sys.stderr.write(message) if not send_email: return - subject = "SChain v%s: Error running %s\n" %(schainpy.__version__, procUnitConfObj.name) + subject = 'SChain v%s: Error running %s\n' %(schainpy.__version__, procUnitConfObj.name) - subtitle = "%s: %s\n" %(procUnitConfObj.getElementName() ,procUnitConfObj.name) - subtitle += "Hostname: %s\n" %socket.gethostbyname(socket.gethostname()) - subtitle += "Working directory: %s\n" %os.path.abspath("./") - subtitle += "Configuration file: %s\n" %self.filename - subtitle += "Time: %s\n" %str(datetime.datetime.now()) + subtitle = '%s: %s\n' %(procUnitConfObj.getElementName() ,procUnitConfObj.name) + subtitle += 'Hostname: %s\n' %socket.gethostbyname(socket.gethostname()) + subtitle += 'Working directory: %s\n' %os.path.abspath('./') + subtitle += 'Configuration file: %s\n' %self.filename + subtitle += 'Time: %s\n' %str(datetime.datetime.now()) readUnitConfObj = self.getReadUnitObj() if readUnitConfObj: - subtitle += "\nInput parameters:\n" - subtitle += "[Data path = %s]\n" %readUnitConfObj.path - subtitle += "[Data type = %s]\n" %readUnitConfObj.datatype - subtitle += "[Start date = %s]\n" %readUnitConfObj.startDate - subtitle += "[End date = %s]\n" %readUnitConfObj.endDate - subtitle += "[Start time = %s]\n" %readUnitConfObj.startTime - subtitle += "[End time = %s]\n" %readUnitConfObj.endTime + subtitle += '\nInput parameters:\n' + subtitle += '[Data path = %s]\n' %readUnitConfObj.path + subtitle += '[Data type = %s]\n' %readUnitConfObj.datatype + subtitle += '[Start date = %s]\n' %readUnitConfObj.startDate + subtitle += '[End date = %s]\n' %readUnitConfObj.endDate + subtitle += '[Start time = %s]\n' %readUnitConfObj.startTime + subtitle += '[End time = %s]\n' %readUnitConfObj.endTime adminObj = schainpy.admin.SchainNotify() adminObj.sendAlert(message=message, @@ -1228,15 +1207,15 @@ class Project(Process): return 0 def runController(self): - """ + ''' returns 0 when this process has been stopped, 1 otherwise - """ + ''' if self.isPaused(): - print "Process suspended" + print 'Process suspended' while True: - sleep(0.1) + time.sleep(0.1) if not self.isPaused(): break @@ -1244,10 +1223,10 @@ class Project(Process): if self.isStopped(): break - print "Process reinitialized" + print 'Process reinitialized' if self.isStopped(): - print "Process stopped" + print 'Process stopped' return 0 return 1 @@ -1258,29 +1237,23 @@ class Project(Process): def setPlotterQueue(self, plotter_queue): - raise NotImplementedError, "Use schainpy.controller_api.ControllerThread instead Project class" + raise NotImplementedError, 'Use schainpy.controller_api.ControllerThread instead Project class' def getPlotterQueue(self): - raise NotImplementedError, "Use schainpy.controller_api.ControllerThread instead Project class" + raise NotImplementedError, 'Use schainpy.controller_api.ControllerThread instead Project class' def useExternalPlotter(self): - raise NotImplementedError, "Use schainpy.controller_api.ControllerThread instead Project class" + raise NotImplementedError, 'Use schainpy.controller_api.ControllerThread instead Project class' + def run(self): - def run(self, filename=None): + log.success('Starting {}'.format(self.name)) - # self.writeXml(filename) self.createObjects() self.connectObjects() - print - print "*"*60 - print " Starting SIGNAL CHAIN PROCESSING v%s " %schainpy.__version__ - print "*"*60 - print - keyList = self.procUnitConfObjDict.keys() keyList.sort() @@ -1289,7 +1262,6 @@ class Project(Process): is_ok = False for procKey in keyList: -# print "Running the '%s' process with %s" %(procUnitConfObj.name, procUnitConfObj.id) procUnitConfObj = self.procUnitConfObjDict[procKey] @@ -1300,19 +1272,18 @@ class Project(Process): is_ok = False break except ValueError, e: - sleep(0.5) + time.sleep(0.5) self.__handleError(procUnitConfObj, send_email=True) is_ok = False break except: - sleep(0.5) + time.sleep(0.5) self.__handleError(procUnitConfObj) is_ok = False break #If every process unit finished so end process if not(is_ok): -# print "Every process unit have finished" break if not self.runController(): @@ -1322,3 +1293,5 @@ class Project(Process): for procKey in keyList: procUnitConfObj = self.procUnitConfObjDict[procKey] procUnitConfObj.close() + + log.success('{} finished'.format(self.name)) diff --git a/schainpy/gui/viewcontroller/basicwindow.py b/schainpy/gui/viewcontroller/basicwindow.py index caf1333..c2d8e75 100644 --- a/schainpy/gui/viewcontroller/basicwindow.py +++ b/schainpy/gui/viewcontroller/basicwindow.py @@ -6218,3 +6218,6 @@ class ShowMeConsole(QtCore.QObject): text = text[:-1] self.textWritten.emit(str(text)) + + def flush(self): + pass diff --git a/schainpy/model/io/jroIO_amisr.py b/schainpy/model/io/jroIO_amisr.py index adf4e9d..3be5aaa 100644 --- a/schainpy/model/io/jroIO_amisr.py +++ b/schainpy/model/io/jroIO_amisr.py @@ -267,7 +267,7 @@ class AMISRReader(ProcessingUnit): self.dirnameList = new_dirnameList return 1 - def __searchFilesOnline(self, + def searchFilesOnLine(self, path, walk=True): @@ -287,7 +287,7 @@ class AMISRReader(ProcessingUnit): return - def __searchFilesOffline(self, + def searchFilesOffLine(self, path, startDate, endDate, @@ -494,9 +494,9 @@ class AMISRReader(ProcessingUnit): self.online = online if not(online): #Busqueda de archivos offline - self.__searchFilesOffline(path, startDate, endDate, startTime, endTime, walk) + self.searchFilesOffLine(path, startDate, endDate, startTime, endTime, walk) else: - self.__searchFilesOnline(path, walk) + self.searchFilesOnLine(path, walk) if not(self.filenameList): print "There is no files into the folder: %s"%(path) diff --git a/schainpy/model/io/jroIO_base.py b/schainpy/model/io/jroIO_base.py index 4824af8..d2c079c 100644 --- a/schainpy/model/io/jroIO_base.py +++ b/schainpy/model/io/jroIO_base.py @@ -541,8 +541,7 @@ class JRODataIO: return inspect.getargspec(self.run).args class JRODataReader(JRODataIO): - - firstTime = True + online = 0 realtime = 0 @@ -578,8 +577,7 @@ class JRODataReader(JRODataIO): selBlocksize = None selBlocktime = None - - onlineWithDate = False + def __init__(self): """ @@ -603,19 +601,19 @@ class JRODataReader(JRODataIO): raise NotImplementedError - def __searchFilesOffLine(self, - path, - startDate=None, - endDate=None, - startTime=datetime.time(0,0,0), - endTime=datetime.time(23,59,59), - set=None, - expLabel='', - ext='.r', - queue=None, - cursor=None, - skip=None, - walk=True): + def searchFilesOffLine(self, + path, + startDate=None, + endDate=None, + startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59), + set=None, + expLabel='', + ext='.r', + cursor=None, + skip=None, + walk=True): + self.filenameList = [] self.datetimeList = [] @@ -624,8 +622,7 @@ class JRODataReader(JRODataIO): dateList, pathList = self.findDatafiles(path, startDate, endDate, expLabel, ext, walk, include_path=True) if dateList == []: - # print "[Reading] Date range selected invalid [%s - %s]: No *%s files in %s)" %(startDate, endDate, ext, path) - return None, None + return [], [] if len(dateList) > 1: print "[Reading] Data found for date range [%s - %s]: total days = %d" %(startDate, endDate, len(dateList)) @@ -636,18 +633,15 @@ class JRODataReader(JRODataIO): datetimeList = [] for thisPath in pathList: - # thisPath = pathList[pathDict[file]] - + fileList = glob.glob1(thisPath, "*%s" %ext) fileList.sort() skippedFileList = [] if cursor is not None and skip is not None: - # if cursor*skip > len(fileList): + if skip == 0: - if queue is not None: - queue.put(len(fileList)) skippedFileList = [] else: skippedFileList = fileList[cursor*skip: cursor*skip + skip] @@ -672,44 +666,43 @@ class JRODataReader(JRODataIO): if not(filenameList): print "[Reading] Time range selected invalid [%s - %s]: No *%s files in %s)" %(startTime, endTime, ext, path) - return None, None + return [], [] print "[Reading] %d file(s) was(were) found in time range: %s - %s" %(len(filenameList), startTime, endTime) print - for i in range(len(filenameList)): - print "[Reading] %s -> [%s]" %(filenameList[i], datetimeList[i].ctime()) + # for i in range(len(filenameList)): + # print "[Reading] %s -> [%s]" %(filenameList[i], datetimeList[i].ctime()) self.filenameList = filenameList - self.datetimeList = datetimeList + self.datetimeList = datetimeList + return pathList, filenameList - def __searchFilesOnLine(self, path, expLabel="", ext=None, walk=True, set=None, startDate=None, startTime=None): - + def __searchFilesOnLine(self, path, expLabel = "", ext = None, walk=True, set=None): + """ - Busca el ultimo archivo de la ultima carpeta (determinada o no por startDateTime) y - devuelve el archivo encontrado ademas de otros datos. - - Input: - path : carpeta donde estan contenidos los files que contiene data - - expLabel : Nombre del subexperimento (subfolder) - - ext : extension de los files - - walk : Si es habilitado no realiza busquedas dentro de los subdirectorios (doypath) - - Return: - directory : eL directorio donde esta el file encontrado - filename : el ultimo file de una determinada carpeta - year : el anho - doy : el numero de dia del anho - set : el set del archivo - - + Busca el ultimo archivo de la ultima carpeta (determinada o no por startDateTime) y + devuelve el archivo encontrado ademas de otros datos. + + Input: + path : carpeta donde estan contenidos los files que contiene data + + expLabel : Nombre del subexperimento (subfolder) + + ext : extension de los files + + walk : Si es habilitado no realiza busquedas dentro de los ubdirectorios (doypath) + + Return: + directory : eL directorio donde esta el file encontrado + filename : el ultimo file de una determinada carpeta + year : el anho + doy : el numero de dia del anho + set : el set del archivo + + """ - pathList = None - filenameList = None if not os.path.isdir(path): return None, None, None, None, None, None @@ -719,7 +712,7 @@ class JRODataReader(JRODataIO): fullpath = path foldercounter = 0 else: - # Filtra solo los directorios + #Filtra solo los directorios for thisPath in os.listdir(path): if not os.path.isdir(os.path.join(path,thisPath)): continue @@ -755,7 +748,7 @@ class JRODataReader(JRODataIO): year = int( filename[1:5] ) doy = int( filename[5:8] ) - set = int( filename[8:11] ) + set = int( filename[8:11] ) return fullpath, foldercounter, filename, year, doy, set @@ -767,7 +760,7 @@ class JRODataReader(JRODataIO): idFile += 1 if not(idFile < len(self.filenameList)): self.flagNoMoreFiles = 1 - # print "[Reading] No more Files" +# print "[Reading] No more Files" return 0 filename = self.filenameList[idFile] @@ -785,32 +778,31 @@ class JRODataReader(JRODataIO): self.fileSize = fileSize self.fp = fp - #print "[Reading] Setting the file: %s"%self.filename +# print "[Reading] Setting the file: %s"%self.filename return 1 def __setNextFileOnline(self): """ - Busca el siguiente file que tenga suficiente data para ser leida, dentro de un folder especifico, si - no encuentra un file valido espera un tiempo determinado y luego busca en los posibles n files - siguientes. - - Affected: - self.flagIsNewFile - self.filename - self.fileSize - self.fp - self.set - self.flagNoMoreFiles - - Return: - 0 : si luego de una busqueda del siguiente file valido este no pudo ser encontrado - 1 : si el file fue abierto con exito y esta listo a ser leido - - Excepciones: - Si un determinado file no puede ser abierto - """ - + Busca el siguiente file que tenga suficiente data para ser leida, dentro de un folder especifico, si + no encuentra un file valido espera un tiempo determinado y luego busca en los posibles n files + siguientes. + + Affected: + self.flagIsNewFile + self.filename + self.fileSize + self.fp + self.set + self.flagNoMoreFiles + + Return: + 0 : si luego de una busqueda del siguiente file valido este no pudo ser encontrado + 1 : si el file fue abierto con exito y esta listo a ser leido + + Excepciones: + Si un determinado file no puede ser abierto + """ nFiles = 0 fileOk_flag = False firstTime_flag = True @@ -869,48 +861,27 @@ class JRODataReader(JRODataIO): if self.fp != None: self.fp.close() self.fp = open(fullfilename, 'rb') self.flagNoMoreFiles = 0 - # print '[Reading] Setting the file: %s' % fullfilename +# print '[Reading] Setting the file: %s' % fullfilename else: self.fileSize = 0 self.filename = None self.flagIsNewFile = 0 self.fp = None self.flagNoMoreFiles = 1 - # print '[Reading] No more files to read' +# print '[Reading] No more files to read' return fileOk_flag def setNextFile(self): if self.fp != None: self.fp.close() + if self.online: newFile = self.__setNextFileOnline() else: newFile = self.__setNextFileOffline() + if not(newFile): - if self.onlineWithDate is True: - self.onlineWithDate=False - self.online = True - self.firstTime = False - self.setup( - path=self.path, - startDate=self.startDate, - endDate=self.endDate, - startTime=self.startTime , - endTime=self.endTime, - set=self.set, - expLabel=self.expLabel, - ext=self.ext, - online=self.online, - delay=self.delay, - walk=self.walk, - getblock=self.getblock, - nTxs=self.nTxs, - realtime=self.realtime, - blocksize=self.blocksize, - blocktime=self.blocktime - ) - return 1 print '[Reading] No more files to read' return 0 @@ -951,7 +922,7 @@ class JRODataReader(JRODataIO): return 1 if self.fileSize == self.fileSizeByHeader: - # self.flagEoF = True +# self.flagEoF = True return 0 print "[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries+1) @@ -1005,13 +976,13 @@ class JRODataReader(JRODataIO): else: self.fp.seek(self.fp.tell() - neededsize) break - - # csize = self.fileSize - self.fp.tell() - # neededsize = self.processingHeaderObj.blockSize + self.basicHeaderSize - # factor = int(csize/neededsize) - # if factor > 0: - # self.fp.seek(self.fp.tell() + factor*neededsize) - + +# csize = self.fileSize - self.fp.tell() +# neededsize = self.processingHeaderObj.blockSize + self.basicHeaderSize +# factor = int(csize/neededsize) +# if factor > 0: +# self.fp.seek(self.fp.tell() + factor*neededsize) + self.flagIsNewFile = 0 self.__isFirstTimeOnline = 0 @@ -1019,10 +990,10 @@ class JRODataReader(JRODataIO): #if self.server is None: if self.fp == None: return 0 - - # if self.online: - # self.__jumpToLastBlock() - + +# if self.online: +# self.__jumpToLastBlock() + if self.flagIsNewFile: self.lastUTTime = self.basicHeaderObj.utc return 1 @@ -1065,12 +1036,14 @@ class JRODataReader(JRODataIO): #Skip block out of startTime and endTime while True: - if not(self.__setNewBlock()): - print 'returning' + if not(self.__setNewBlock()): return 0 + if not(self.readBlock()): return 0 + self.getBasicHeader() + if not isTimeInRange(self.dataOut.datatime.time(), self.startTime, self.endTime): print "[Reading] Block No. %d/%d -> %s [Skipping]" %(self.nReadBlocks, @@ -1082,8 +1055,8 @@ class JRODataReader(JRODataIO): if self.verbose: print "[Reading] Block No. %d/%d -> %s" %(self.nReadBlocks, - self.processingHeaderObj.dataBlocksPerFile, - self.dataOut.datatime.ctime()) + self.processingHeaderObj.dataBlocksPerFile, + self.dataOut.datatime.ctime()) return 1 def __readFirstHeader(self): @@ -1114,8 +1087,8 @@ class JRODataReader(JRODataIO): self.dtype = datatype_str #self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + self.firstHeaderSize + self.basicHeaderSize*(self.processingHeaderObj.dataBlocksPerFile - 1) - # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels) - # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels) +# self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels) +# self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels) self.getBlockDimension() def __verifyFile(self, filename, msgFlag=True): @@ -1277,13 +1250,13 @@ class JRODataReader(JRODataIO): def setup(self, path=None, - startDate=None, - endDate=None, - startTime=datetime.time(0,0,0), - endTime=datetime.time(23,59,59), - set=None, - expLabel = "", - ext = None, + startDate=None, + endDate=None, + startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59), + set=None, + expLabel = "", + ext = None, online = False, delay = 60, walk = True, @@ -1292,139 +1265,108 @@ class JRODataReader(JRODataIO): realtime=False, blocksize=None, blocktime=None, + skip=None, + cursor=None, + warnings=True, verbose=True, - **kwargs): + server=None): + if server is not None: + if 'tcp://' in server: + address = server + else: + address = 'ipc:///tmp/%s' % server + self.server = address + self.context = zmq.Context() + self.receiver = self.context.socket(zmq.PULL) + self.receiver.connect(self.server) + time.sleep(0.5) + print '[Starting] ReceiverData from {}'.format(self.server) + else: + self.server = None + if path == None: + raise ValueError, "[Reading] The path is not valid" - if path == None: - raise ValueError, "[Reading] The path is not valid" - + if ext == None: + ext = self.ext - if ext == None: - ext = self.ext - - self.verbose=verbose - self.path = path - self.startDate = startDate - self.endDate = endDate - self.startTime = startTime - self.endTime = endTime - self.set = set - self.expLabel = expLabel - self.ext = ext - self.online = online - self.delay = delay - self.walk = walk - self.getblock = getblock - self.nTxs = nTxs - self.realtime = realtime - self.blocksize = blocksize - self.blocktime = blocktime - - - if self.firstTime is True: - pathList, filenameList = self.__searchFilesOffLine(path, startDate=startDate, endDate=endDate, + if online: + print "[Reading] Searching files in online mode..." + + for nTries in range( self.nTries ): + fullpath, foldercounter, file, year, doy, set = self.__searchFilesOnLine(path=path, expLabel=expLabel, ext=ext, walk=walk, set=set) + + if fullpath: + break + + print '[Reading] Waiting %0.2f sec for an valid file in %s: try %02d ...' % (self.delay, path, nTries+1) + sleep( self.delay ) + + if not(fullpath): + print "[Reading] There 'isn't any valid file in %s" % path + return + + self.year = year + self.doy = doy + self.set = set - 1 + self.path = path + self.foldercounter = foldercounter + last_set = None + else: + print "[Reading] Searching files in offline mode ..." + pathList, filenameList = self.searchFilesOffLine(path, startDate=startDate, endDate=endDate, startTime=startTime, endTime=endTime, set=set, expLabel=expLabel, ext=ext, - walk=walk) - if filenameList is not None: filenameList = filenameList[:-1] + walk=walk, cursor=cursor, + skip=skip) - if pathList is not None and filenameList is not None and online: - self.onlineWithDate = True - online = False + if not(pathList): self.fileIndex = -1 - self.pathList = pathList - self.filenameList = filenameList - file_name = os.path.basename(filenameList[-1]) - basename, ext = os.path.splitext(file_name) - last_set = int(basename[-3:]) - - if online: - print "[Reading] Searching files in online mode..." - - for nTries in range(self.nTries): - fullpath, foldercounter, file, year, doy, set = self.__searchFilesOnLine(path=path, - expLabel=expLabel, - ext=ext, - walk=walk, - startDate=startDate, - startTime=startTime, - set=set) - - if fullpath: - break - print '[Reading] Waiting %0.2f sec for an valid file in %s: try %02d ...' % (self.delay, path, nTries+1) - sleep( self.delay ) - - if not(fullpath): - print "[Reading] There 'isn't any valid file in %s" % path - return - - self.year = year - self.doy = doy - self.set = set - 1 - self.path = path - self.foldercounter = foldercounter - last_set = None - else: - print "[Reading] Searching files in offline mode ..." - pathList, filenameList = self.__searchFilesOffLine(path, startDate=startDate, endDate=endDate, - startTime=startTime, endTime=endTime, - set=set, expLabel=expLabel, ext=ext, - walk=walk) - - if not(pathList): - # print "[Reading] No *%s files in %s (%s - %s)"%(ext, path, - # datetime.datetime.combine(startDate,startTime).ctime(), - # datetime.datetime.combine(endDate,endTime).ctime()) - - # sys.exit(-1) - - self.fileIndex = -1 - self.pathList = [] - self.filenameList = [] - return - - self.fileIndex = -1 - self.pathList = pathList - self.filenameList = filenameList - file_name = os.path.basename(filenameList[-1]) - basename, ext = os.path.splitext(file_name) - last_set = int(basename[-3:]) - - - self.online = online - self.realtime = realtime - self.delay = delay - ext = ext.lower() - self.ext = ext - self.getByBlock = getblock - self.nTxs = nTxs - self.startTime = startTime - self.endTime = endTime - - - #Added----------------- - self.selBlocksize = blocksize - self.selBlocktime = blocktime - - - if not(self.setNextFile()): - if (startDate!=None) and (endDate!=None): - print "[Reading] No files in range: %s - %s" %(datetime.datetime.combine(startDate,startTime).ctime(), datetime.datetime.combine(endDate,endTime).ctime()) - elif startDate != None: - print "[Reading] No files in range: %s" %(datetime.datetime.combine(startDate,startTime).ctime()) - else: - print "[Reading] No files" - + self.pathList = [] + self.filenameList = [] + return + self.fileIndex = -1 - self.pathList = [] - self.filenameList = [] - return + self.pathList = pathList + self.filenameList = filenameList + file_name = os.path.basename(filenameList[-1]) + basename, ext = os.path.splitext(file_name) + last_set = int(basename[-3:]) + + self.online = online + self.realtime = realtime + self.delay = delay + ext = ext.lower() + self.ext = ext + self.getByBlock = getblock + self.nTxs = nTxs + self.startTime = startTime + self.endTime = endTime + + #Added----------------- + self.selBlocksize = blocksize + self.selBlocktime = blocktime + + # Verbose----------- + self.verbose = verbose + self.warnings = warnings + + if not(self.setNextFile()): + if (startDate!=None) and (endDate!=None): + print "[Reading] No files in range: %s - %s" %(datetime.datetime.combine(startDate,startTime).ctime(), datetime.datetime.combine(endDate,endTime).ctime()) + elif startDate != None: + print "[Reading] No files in range: %s" %(datetime.datetime.combine(startDate,startTime).ctime()) + else: + print "[Reading] No files" + + self.fileIndex = -1 + self.pathList = [] + self.filenameList = [] + return - # self.getBasicHeader() + # self.getBasicHeader() - if last_set != None: - self.dataOut.last_block = last_set * self.processingHeaderObj.dataBlocksPerFile + self.basicHeaderObj.dataBlock + if last_set != None: + self.dataOut.last_block = last_set * self.processingHeaderObj.dataBlocksPerFile + self.basicHeaderObj.dataBlock return def getBasicHeader(self): @@ -1442,10 +1384,10 @@ class JRODataReader(JRODataIO): self.dataOut.useLocalTime = self.basicHeaderObj.useLocalTime self.dataOut.ippSeconds = self.radarControllerHeaderObj.ippSeconds/self.nTxs - - # self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock*self.nTxs - - + +# self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock*self.nTxs + + def getFirstHeader(self): raise NotImplementedError @@ -1494,53 +1436,50 @@ class JRODataReader(JRODataIO): self.__printInfo = False def run(self, - path=None, - startDate=None, - endDate=None, - startTime=datetime.time(0,0,0), - endTime=datetime.time(23,59,59), - set=None, - expLabel = "", - ext = None, - online = False, - delay = 60, - walk = True, - getblock = False, - nTxs = 1, - realtime=False, - blocksize=None, - blocktime=None, - queue=None, - skip=None, - cursor=None, - warnings=True, - server=None, - verbose=True, **kwargs): + path=None, + startDate=None, + endDate=None, + startTime=datetime.time(0,0,0), + endTime=datetime.time(23,59,59), + set=None, + expLabel = "", + ext = None, + online = False, + delay = 60, + walk = True, + getblock = False, + nTxs = 1, + realtime=False, + blocksize=None, + blocktime=None, + skip=None, + cursor=None, + warnings=True, + server=None, + verbose=True, **kwargs): if not(self.isConfig): -# self.dataOut = dataOut - self.setup( path=path, - startDate=startDate, - endDate=endDate, - startTime=startTime, - endTime=endTime, - set=set, - expLabel=expLabel, - ext=ext, - online=online, - delay=delay, - walk=walk, - getblock=getblock, - nTxs=nTxs, - realtime=realtime, - blocksize=blocksize, - blocktime=blocktime, - queue=queue, - skip=skip, - cursor=cursor, - warnings=warnings, - server=server, - verbose=verbose, **kwargs) + self.setup(path=path, + startDate=startDate, + endDate=endDate, + startTime=startTime, + endTime=endTime, + set=set, + expLabel=expLabel, + ext=ext, + online=online, + delay=delay, + walk=walk, + getblock=getblock, + nTxs=nTxs, + realtime=realtime, + blocksize=blocksize, + blocktime=blocktime, + skip=skip, + cursor=cursor, + warnings=warnings, + server=server, + verbose=verbose) self.isConfig = True if server is None: self.getData() @@ -1663,9 +1602,9 @@ class JRODataWriter(JRODataIO): Return: None """ - - # CALCULAR PARAMETROS - + +# CALCULAR PARAMETROS + sizeLongHeader = self.systemHeaderObj.size + self.radarControllerHeaderObj.size + self.processingHeaderObj.size self.basicHeaderObj.size = self.basicHeaderSize + sizeLongHeader @@ -1792,7 +1731,7 @@ class JRODataWriter(JRODataIO): return 1 - def setup(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4, verbose=True): + def setup(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4): """ Setea el tipo de formato en la cual sera guardada la data y escribe el First Header diff --git a/schainpy/model/io/jroIO_heispectra.py b/schainpy/model/io/jroIO_heispectra.py index d6f37ca..ddbffab 100644 --- a/schainpy/model/io/jroIO_heispectra.py +++ b/schainpy/model/io/jroIO_heispectra.py @@ -453,7 +453,7 @@ class FitsReader(ProcessingUnit): # self.blockIndex = 1 return 1 - def __searchFilesOffLine(self, + def searchFilesOffLine(self, path, startDate, endDate, @@ -559,7 +559,7 @@ class FitsReader(ProcessingUnit): if not(online): print "Searching files in offline mode ..." - pathList, filenameList = self.__searchFilesOffLine(path, startDate=startDate, endDate=endDate, + pathList, filenameList = self.searchFilesOffLine(path, startDate=startDate, endDate=endDate, startTime=startTime, endTime=endTime, set=set, expLabel=expLabel, ext=ext, walk=walk) diff --git a/schainpy/model/io/jroIO_hf.py b/schainpy/model/io/jroIO_hf.py index 690492a..5ba1787 100644 --- a/schainpy/model/io/jroIO_hf.py +++ b/schainpy/model/io/jroIO_hf.py @@ -415,7 +415,7 @@ class HFReader(ProcessingUnit): - def __searchFilesOffline(self, + def searchFilesOffLine(self, path, startDate, endDate, @@ -438,7 +438,7 @@ class HFReader(ProcessingUnit): return - def __searchFilesOnline(self, + def searchFilesOnLine(self, path, expLabel= "", ext=None, @@ -636,10 +636,10 @@ class HFReader(ProcessingUnit): if not(online): print "Searching files in offline mode..." - self.__searchFilesOffline(path, startDate, endDate, ext, startTime, endTime, walk) + self.searchFilesOffLine(path, startDate, endDate, ext, startTime, endTime, walk) else: print "Searching files in online mode..." - self.__searchFilesOnline(path, walk,ext,set=set) + self.searchFilesOnLine(path, walk,ext,set=set) if set==None: pass else: @@ -647,7 +647,7 @@ class HFReader(ProcessingUnit): # for nTries in range(self.nTries): # -# fullpath,file,year,month,day,set = self.__searchFilesOnline(path=path,expLabel=expLabel,ext=ext, walk=walk,set=set) +# fullpath,file,year,month,day,set = self.searchFilesOnLine(path=path,expLabel=expLabel,ext=ext, walk=walk,set=set) # # if fullpath: # break diff --git a/schainpy/model/io/jroIO_kamisr.py b/schainpy/model/io/jroIO_kamisr.py index 9fcbf1c..7e4d14a 100644 --- a/schainpy/model/io/jroIO_kamisr.py +++ b/schainpy/model/io/jroIO_kamisr.py @@ -106,9 +106,9 @@ class AMISRReader(ProcessingUnit): #self.findFiles() if not(online): #Busqueda de archivos offline - self.__searchFilesOffline(path, startDate, endDate, startTime, endTime, walk) + self.searchFilesOffLine(path, startDate, endDate, startTime, endTime, walk) else: - self.__searchFilesOnline(path, startDate, endDate, startTime,endTime,walk) + self.searchFilesOnLine(path, startDate, endDate, startTime,endTime,walk) if not(self.filenameList): print "There is no files into the folder: %s"%(path) @@ -329,7 +329,7 @@ class AMISRReader(ProcessingUnit): self.dirnameList = new_dirnameList return 1 - def __searchFilesOnline(self, path, startDate, endDate, startTime=datetime.time(0,0,0), + def searchFilesOnLine(self, path, startDate, endDate, startTime=datetime.time(0,0,0), endTime=datetime.time(23,59,59),walk=True): if endDate ==None: @@ -349,7 +349,7 @@ class AMISRReader(ProcessingUnit): return - def __searchFilesOffline(self, + def searchFilesOffLine(self, path, startDate, endDate, diff --git a/schainpy/model/io/jroIO_param.py b/schainpy/model/io/jroIO_param.py index 604558f..50e7367 100644 --- a/schainpy/model/io/jroIO_param.py +++ b/schainpy/model/io/jroIO_param.py @@ -97,7 +97,7 @@ class ParamReader(ProcessingUnit): self.timezone = 'lt' print "[Reading] Searching files in offline mode ..." - pathList, filenameList = self.__searchFilesOffLine(path, startDate=startDate, endDate=endDate, + pathList, filenameList = self.searchFilesOffLine(path, startDate=startDate, endDate=endDate, startTime=startTime, endTime=endTime, ext=ext, walk=walk) @@ -115,7 +115,7 @@ class ParamReader(ProcessingUnit): return - def __searchFilesOffLine(self, + def searchFilesOffLine(self, path, startDate=None, endDate=None, diff --git a/schainpy/utils/.desktop b/schainpy/utils/.desktop deleted file mode 100644 index b1e940f..0000000 --- a/schainpy/utils/.desktop +++ /dev/null @@ -1,6 +0,0 @@ -[Desktop Entry] -Encoding=UTF-8 -Name=Link to -Type=Link -URL=file:///home/nanosat/schain/schainpy/utils/parameters.txt -Icon=text-plain