diff --git a/experiment_project.py b/experiment_project.py new file mode 100644 index 0000000..5bb268a --- /dev/null +++ b/experiment_project.py @@ -0,0 +1,34 @@ +from schainpy.controller import Project + +desc = "A schain project" + +controller = Project() +controller.setup(id='191', name="project", description=desc) + +readUnitConf = controller.addReadUnit(datatype='VoltageReader', + path="/home/nanosat/schain", + startDate="1970/01/01", + endDate="2017/12/31", + startTime="00:00:00", + endTime="23:59:59", + online=0, + verbose=1, + walk=1, + ) + +procUnitConf1 = controller.addProcUnit(datatype='VoltageProc', inputId=readUnitConf.getId()) + +opObj11 = procUnitConf1.addOperation(name='ProfileSelector', optype='other') +opObj11.addParameter(name='profileRangeList', value='120,183', format='intlist') + +opObj11 = procUnitConf1.addOperation(name='RTIPlot', optype='other') +opObj11.addParameter(name='wintitle', value='Jicamarca Radio Observatory', format='str') +opObj11.addParameter(name='showprofile', value='0', format='int') +opObj11.addParameter(name='xmin', value='0', format='int') +opObj11.addParameter(name='xmax', value='24', format='int') +opObj11.addParameter(name='figpath', value="/home/nanosat/schain/figs", format='str') +opObj11.addParameter(name='wr_period', value='5', format='int') +opObj11.addParameter(name='exp_code', value='22', format='int') + + +controller.start() diff --git a/schain.xml b/schain.xml new file mode 100644 index 0000000..b67ac71 --- /dev/null +++ b/schain.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/schaincli/cli.py b/schaincli/cli.py index 5040ae8..53ba60a 100644 --- a/schaincli/cli.py +++ b/schaincli/cli.py @@ -4,10 +4,18 @@ import subprocess import os import sys import glob +save_stdout = sys.stdout +sys.stdout = open('trash', 'w') from multiprocessing import cpu_count from schaincli import templates from schainpy import controller_api +from schainpy.model import Operation, ProcessingUnit from schainpy.utils import log +from importlib import import_module +from pydoc import locate +from fuzzywuzzy import process +sys.stdout = save_stdout + def print_version(ctx, param, value): if not value or ctx.resilient_parsing: @@ -15,13 +23,16 @@ def print_version(ctx, param, value): click.echo(schainpy.__version__) ctx.exit() + cliLogger = log.makelogger('schain cli') +PREFIX = 'experiment' + @click.command() @click.option('--version', '-v', is_flag=True, callback=print_version, help='SChain version', type=str) @click.option('--xml', '-x', default=None, help='run an XML file', type=click.Path(exists=True, resolve_path=True)) @click.argument('command', default='run', required=True) -@click.argument('nextcommand', default=None, required=False, type=click.Path(exists=True, resolve_path=True)) +@click.argument('nextcommand', default=None, required=False, type=str) def main(command, nextcommand, version, xml): """COMMAND LINE INTERFACE FOR SIGNAL CHAIN - JICAMARCA RADIO OBSERVATORY""" if xml is not None: @@ -31,20 +42,90 @@ def main(command, nextcommand, version, xml): elif command == 'test': test() elif command == 'run': - if nextcommand is None: - currentfiles = glob.glob('./*.py') - numberfiles = len(currentfiles) - print currentfiles - if numberfiles > 1: - log.error('There is more than one file to run') - elif numberfiles == 1: - subprocess.call(['python ' + currentfiles[0]], shell=True) - else: - log.error('There is no file to run.') + runschain(nextcommand) + elif command == 'search': + search(nextcommand) + else: + log.error('Command {} is not defined'.format(command)) + +def check_module(possible, instance): + def check(x): + try: + instancia = locate('schainpy.model.{}'.format(x)) + return isinstance(instancia(), instance) + except Exception as e: + return False + clean = clean_modules(possible) + return [x for x in clean if check(x)] + + +def clean_modules(module): + noEndsUnder = [x for x in module if not x.endswith('__')] + noStartUnder = [x for x in noEndsUnder if not x.startswith('__')] + noFullUpper = [x for x in noStartUnder if not x.isupper()] + return noFullUpper + + +def search(nextcommand): + + if nextcommand is None: + log.error('There is no Operation/ProcessingUnit to search') + elif nextcommand == 'procs': + module = dir(import_module('schainpy.model')) + procs = check_module(module, ProcessingUnit) + try: + procs.remove('ProcessingUnit') + except Exception as e: + pass + log.success('Current ProcessingUnits are:\n\033[1m{}\033[0m'.format('\n'.join(procs))) + + elif nextcommand == 'operations': + module = dir(import_module('schainpy.model')) + noProcs = [x for x in module if not x.endswith('Proc')] + operations = check_module(noProcs, Operation) + try: + operations.remove('Operation') + except Exception as e: + pass + log.success('Current Operations are:\n\033[1m{}\033[0m'.format('\n'.join(operations))) + else: + try: + module = locate('schainpy.model.{}'.format(nextcommand)) + log.warning('Use this feature with caution. It may not return all the allowed arguments') + args = module().getAllowedArgs() + try: + args.remove('self') + except Exception as e: + pass + try: + args.remove('dataOut') + except Exception as e: + pass + log.success('Showing arguments of {} are:\n\033[1m{}\033[0m'.format(nextcommand, '\n'.join(args))) + except Exception as e: + log.error('Module {} does not exists'.format(nextcommand)) + allModules = dir(import_module('schainpy.model')) + module = check_module(allModules, Operation) + module.extend(check_module(allModules, ProcessingUnit)) + similar = process.extractOne(nextcommand, module)[0] + search(similar) + + +def runschain(nextcommand): + if nextcommand is None: + currentfiles = glob.glob('./{}_*.py'.format(PREFIX)) + numberfiles = len(currentfiles) + if numberfiles > 1: + log.error('There is more than one file to run') + elif numberfiles == 1: + subprocess.call(['python ' + currentfiles[0]], shell=True) else: - subprocess.call(['python ' + nextcommand], shell=True) + log.error('There is no file to run') else: - log.error('Command is not defined.') + try: + subprocess.call(['python ' + nextcommand], shell=True) + except Exception as e: + log.error("I cannot run the file. Does it exists?") def basicInputs(): @@ -68,11 +149,11 @@ def generate(): current = templates.multiprocess.format(**inputs) else: current = templates.basic.format(**inputs) - scriptname = inputs['name'] + ".py" + scriptname = '{}_{}.py'.format(PREFIX, inputs['name']) script = open(scriptname, 'w') try: script.write(current) - log.success('Script {file} generated'.format(file=scriptname)) + log.success('Script {} generated'.format(scriptname)) except Exception as e: log.error('I cannot create the file. Do you have writing permissions?') @@ -91,7 +172,7 @@ def runFromXML(filename): controller.start() plotterObj.start() - cliLogger("Finishing all processes ...") + cliLogger("Finishing all processes") controller.join(5) diff --git a/schainpy/controller_api.py b/schainpy/controller_api.py index 2c9efd1..d8d87b9 100644 --- a/schainpy/controller_api.py +++ b/schainpy/controller_api.py @@ -5,175 +5,175 @@ from schainpy.controller import Project from schainpy.model.graphics.jroplotter import PlotManager class ControllerThread(threading.Thread, Project): - + def __init__(self, plotter_queue=None): - + threading.Thread.__init__(self) Project.__init__(self, plotter_queue) - + self.setDaemon(True) - + self.lock = threading.Lock() self.control = {'stop':False, 'pause':False} - + def __del__(self): - + self.control['stop'] = True - + def stop(self): - + self.lock.acquire() - + self.control['stop'] = True - + self.lock.release() - + def pause(self): - + self.lock.acquire() - + self.control['pause'] = not(self.control['pause']) paused = self.control['pause'] - + self.lock.release() - + return paused - + def isPaused(self): - + self.lock.acquire() paused = self.control['pause'] self.lock.release() - + return paused - + def isStopped(self): - + self.lock.acquire() stopped = self.control['stop'] self.lock.release() - + return stopped - + def run(self): self.control['stop'] = False self.control['pause'] = False - + self.writeXml() - + self.createObjects() self.connectObjects() Project.run(self) - + def isRunning(self): - + return self.is_alive() - + def isFinished(self): - + return not self.is_alive() def setPlotters(self): - + plotterList = PlotManager.plotterList - + for thisPUConfObj in self.procUnitConfObjDict.values(): - + inputId = thisPUConfObj.getInputId() - + if int(inputId) == 0: continue - + for thisOpObj in thisPUConfObj.getOperationObjList(): - + if thisOpObj.type == "self": continue - + if thisOpObj.name in plotterList: thisOpObj.type = "plotter" def setPlotterQueue(self, plotter_queue): - + self.plotterQueue = plotter_queue - + def getPlotterQueue(self): - + return self.plotterQueue def useExternalPlotter(self): - + self.plotterQueue = Queue(10) self.setPlotters() - + plotManagerObj = PlotManager(self.plotterQueue) plotManagerObj.setController(self) - + return plotManagerObj - + # from PyQt4 import QtCore # from PyQt4.QtCore import SIGNAL -# +# # class ControllerQThread(QtCore.QThread, Project): -# +# # def __init__(self, filename): -# +# # QtCore.QThread.__init__(self) # Project.__init__(self) -# +# # self.filename = filename -# +# # self.lock = threading.Lock() # self.control = {'stop':False, 'pause':False} -# +# # def __del__(self): -# +# # self.control['stop'] = True # self.wait() -# +# # def stop(self): -# +# # self.lock.acquire() -# +# # self.control['stop'] = True -# +# # self.lock.release() -# +# # def pause(self): -# +# # self.lock.acquire() -# +# # self.control['pause'] = not(self.control['pause']) # paused = self.control['pause'] -# +# # self.lock.release() -# +# # return paused -# +# # def isPaused(self): -# +# # self.lock.acquire() # paused = self.control['pause'] # self.lock.release() -# +# # return paused -# +# # def isStopped(self): -# +# # self.lock.acquire() # stopped = self.control['stop'] # self.lock.release() -# +# # return stopped -# +# # def run(self): -# +# # self.control['stop'] = False # self.control['pause'] = False -# +# # self.readXml(self.filename) # self.createObjects() # self.connectObjects() # self.emit( SIGNAL( "jobStarted( PyQt_PyObject )" ), 1) # Project.run(self) # self.emit( SIGNAL( "jobFinished( PyQt_PyObject )" ), 1) -# \ No newline at end of file +# diff --git a/schainpy/model/io/jroIO_base.py b/schainpy/model/io/jroIO_base.py index a9b38a1..30a6f83 100644 --- a/schainpy/model/io/jroIO_base.py +++ b/schainpy/model/io/jroIO_base.py @@ -9,6 +9,7 @@ import glob import time import numpy import fnmatch +import inspect import time, datetime #import h5py import traceback @@ -536,6 +537,9 @@ class JRODataIO: return dtype_width + def getAllowedArgs(self): + return inspect.getargspec(self.run).args + class JRODataReader(JRODataIO): @@ -1432,12 +1436,52 @@ class JRODataReader(JRODataIO): self.__printInfo = False - def run(self, **kwargs): + 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, + verbose=True, **kwargs): if not(self.isConfig): - # self.dataOut = dataOut - self.setup(**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, + queue=queue, + skip=skip, + cursor=cursor, + warnings=warnings, + verbose=verbose) self.isConfig = True self.getData() @@ -1740,11 +1784,11 @@ class JRODataWriter(JRODataIO): return 1 - def run(self, dataOut, **kwargs): + def run(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4, **kwargs): if not(self.isConfig): - self.setup(dataOut, **kwargs) + self.setup(dataOut, path, blocksPerFile, profilesPerBlock=profilesPerBlock, set=set, ext=ext, datatype=datatype, **kwargs) self.isConfig = True self.putData() diff --git a/schainpy/utils/log.py b/schainpy/utils/log.py index 2544f8c..85f1489 100644 --- a/schainpy/utils/log.py +++ b/schainpy/utils/log.py @@ -1,5 +1,4 @@ """. - SCHAINPY - LOG Simple helper for log standarization Usage: @@ -25,12 +24,12 @@ def warning(message): def error(message): - click.echo(click.style('[ERROR] - ' + message, bg='red', fg='white')) + click.echo(click.style('[ERROR] - ' + message, fg='red')) pass def success(message): - click.echo(click.style('[SUCESS] - ' + message, bg='green', fg='white')) + click.echo(click.style(message, fg='green')) pass diff --git a/setup.py b/setup.py index 4dc60b8..dcee0b2 100644 --- a/setup.py +++ b/setup.py @@ -51,6 +51,7 @@ setup(name="schainpy", "zmq", "fuzzywuzzy", "click", - "colorama" + "colorama", + "python-Levenshtein" ], ) diff --git a/trash b/trash new file mode 100644 index 0000000..384299d --- /dev/null +++ b/trash @@ -0,0 +1 @@ +You should install "digital_rf_hdf5" module if you want to read USRP data