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/README.md b/schaincli/README.md new file mode 100644 index 0000000..ced14bb --- /dev/null +++ b/schaincli/README.md @@ -0,0 +1,9 @@ +# schaing + +Command Line Interface for SIGNAL CHAIN - jro + +# Usage + +To use it: + + $ schain-cli --help diff --git a/schaincli/__init__.py b/schaincli/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/schaincli/__init__.py diff --git a/schaincli/asdasd.py b/schaincli/asdasd.py new file mode 100644 index 0000000..ca5629d --- /dev/null +++ b/schaincli/asdasd.py @@ -0,0 +1,34 @@ +from schainpy.controller import Project + +desc = "asdasddsad" + +controller = Project() +controller.setup(id='191', name="asdasd", description=desc) + +readUnitConf = controller.addReadUnit(datatype='VoltageReader', + path="/home/nanosat/schain/schain-cli", + 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/schain-cli/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/schaincli/cli.py b/schaincli/cli.py new file mode 100644 index 0000000..fdf7531 --- /dev/null +++ b/schaincli/cli.py @@ -0,0 +1,188 @@ +import click +import schainpy +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: + return + 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=str) +def main(command, nextcommand, version, xml): + """COMMAND LINE INTERFACE FOR SIGNAL CHAIN - JICAMARCA RADIO OBSERVATORY \n + Available commands.\n + --xml: runs a schain XML generated file\n + run: runs any python script starting 'experiment_'\n + generate: generates a template schain script\n + search: return avilable operations, procs or arguments of the give operation/proc\n""" + if xml is not None: + runFromXML(xml) + elif command == 'generate': + generate() + elif command == 'test': + test() + elif command == '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)) + args = module().getAllowedArgs() + log.warning('Use this feature with caution. It may not return all the allowed arguments') + try: + args.remove('self') + except Exception as e: + pass + try: + args.remove('dataOut') + except Exception as e: + pass + if len(args) == 0: + log.success('{} has no arguments'.format(nextcommand)) + else: + 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] + log.success('Searching {} instead'.format(similar)) + 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: + log.error('There is no file to run') + else: + try: + subprocess.call(['python ' + nextcommand], shell=True) + except Exception as e: + log.error("I cannot run the file. Does it exists?") + + +def basicInputs(): + inputs = {} + inputs['desc'] = click.prompt('Enter a description', default="A schain project", type=str) + inputs['name'] = click.prompt('Name of the project', default="project", type=str) + inputs['path'] = click.prompt('Data path', default=os.getcwd(), type=click.Path(exists=True, resolve_path=True)) + inputs['startDate'] = click.prompt('Start date', default='1970/01/01', type=str) + inputs['endDate'] = click.prompt('End date', default='2017/12/31', type=str) + inputs['startHour'] = click.prompt('Start hour', default='00:00:00', type=str) + inputs['endHour'] = click.prompt('End hour', default='23:59:59', type=str) + inputs['figpath'] = inputs['path'] + '/figs' + return inputs + + +def generate(): + inputs = basicInputs() + inputs['multiprocess'] = click.confirm('Is this a multiprocess script?') + if inputs['multiprocess']: + inputs['nProcess'] = click.prompt('How many process?', default=cpu_count(), type=int) + current = templates.multiprocess.format(**inputs) + else: + current = templates.basic.format(**inputs) + scriptname = '{}_{}.py'.format(PREFIX, inputs['name']) + script = open(scriptname, 'w') + try: + script.write(current) + log.success('Script {} generated'.format(scriptname)) + except Exception as e: + log.error('I cannot create the file. Do you have writing permissions?') + + +def test(): + log.warning('testing') + + +def runFromXML(filename): + controller = controller_api.ControllerThread() + if not controller.readXml(filename): + return + + plotterObj = controller.useExternalPlotter() + + controller.start() + plotterObj.start() + + cliLogger("Finishing all processes") + + controller.join(5) + + cliLogger("End of script") + return diff --git a/schaincli/templates.py b/schaincli/templates.py new file mode 100644 index 0000000..ce08f4c --- /dev/null +++ b/schaincli/templates.py @@ -0,0 +1,75 @@ +basic = '''from schainpy.controller import Project + +desc = "{desc}" + +controller = Project() +controller.setup(id='191', name="{name}", description=desc) + +readUnitConf = controller.addReadUnit(datatype='VoltageReader', + path="{path}", + startDate="{startDate}", + endDate="{endDate}", + startTime="{startHour}", + endTime="{endHour}", + 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="{figpath}", format='str') +opObj11.addParameter(name='wr_period', value='5', format='int') +opObj11.addParameter(name='exp_code', value='22', format='int') + + +controller.start() +''' + +multiprocess = '''from schainpy.controller import Project, multiSchain + +desc = "{desc}" + +def fiber(cursor, skip, q, day): + controller = Project() + controller.setup(id='191', name="{name}", description=desc) + + readUnitConf = controller.addReadUnit(datatype='SpectraReader', + path="{path}", + startDate=day, + endDate=day, + startTime="{startHour}", + endTime="{endHour}", + online=0, + queue=q, + cursor=cursor, + skip=skip, + verbose=1, + walk=1, + ) + + procUnitConf1 = controller.addProcUnit(datatype='Spectra', inputId=readUnitConf.getId()) + + procUnitConf2 = controller.addProcUnit(datatype='ParametersProc', inputId=readUnitConf.getId()) + opObj11 = procUnitConf2.addOperation(name='SpectralMoments', optype='other') + + opObj12 = procUnitConf2.addOperation(name='PublishData', optype='other') + opObj12.addParameter(name='zeromq', value=1, format='int') + opObj12.addParameter(name='verbose', value=0, format='bool') + + controller.start() + + +if __name__ == '__main__': + multiSchain(fiber, nProcess={nProcess}, startDate="{startDate}", endDate="{endDate}") + + +''' diff --git a/schaincli/tests/__init__.py b/schaincli/tests/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/schaincli/tests/__init__.py @@ -0,0 +1 @@ + diff --git a/schaincli/tests/test_cli.py b/schaincli/tests/test_cli.py new file mode 100644 index 0000000..62e4f30 --- /dev/null +++ b/schaincli/tests/test_cli.py @@ -0,0 +1,29 @@ +import pytest +from click.testing import CliRunner +from schaincli import cli + + +@pytest.fixture +def runner(): + return CliRunner() + + +def test_cli(runner): + result = runner.invoke(cli.main) + assert result.exit_code == 0 + assert not result.exception + assert result.output.strip() == 'Hello, world.' + + +def test_cli_with_option(runner): + result = runner.invoke(cli.main, ['--as-cowboy']) + assert not result.exception + assert result.exit_code == 0 + assert result.output.strip() == 'Howdy, world.' + + +def test_cli_with_arg(runner): + result = runner.invoke(cli.main, ['Jicamarca']) + assert result.exit_code == 0 + assert not result.exception + assert result.output.strip() == 'Hello, Jicamarca.' diff --git a/schainpy/controller.py b/schainpy/controller.py index 21bc640..c1d4836 100644 --- a/schainpy/controller.py +++ b/schainpy/controller.py @@ -61,7 +61,7 @@ def multiSchain(child, nProcess=cpu_count(), startDate=None, endDate=None, by_da process.terminate() process.join() print traceback.print_tb(trace) - + sys.excepthook = beforeExit for process in processes: @@ -1315,9 +1315,9 @@ class Project(): print "Process finished" - def start(self): + def start(self, filename=None): - self.writeXml() + self.writeXml(filename) self.createObjects() self.connectObjects() self.run() 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/data/jrodata.py b/schainpy/model/data/jrodata.py index c58715e..f7260e7 100644 --- a/schainpy/model/data/jrodata.py +++ b/schainpy/model/data/jrodata.py @@ -114,10 +114,6 @@ class GenericData(object): flagNoData = True - def __init__(self): - - raise NotImplementedError - def copy(self, inputObj=None): if inputObj == None: @@ -231,10 +227,6 @@ class JROData(GenericData): profileIndex = None - def __init__(self): - - raise NotImplementedError - def getNoise(self): raise NotImplementedError @@ -1216,7 +1208,10 @@ class Parameters(Spectra): def getTimeInterval(self): - return self.timeInterval1 + if hasattr(self, 'timeInterval1'): + return self.timeInterval1 + else: + return self.paramInterval def getNoise(self): diff --git a/schainpy/model/graphics/jroplot_data.py b/schainpy/model/graphics/jroplot_data.py index b01484e..01f20ce 100644 --- a/schainpy/model/graphics/jroplot_data.py +++ b/schainpy/model/graphics/jroplot_data.py @@ -14,7 +14,7 @@ from multiprocessing import Process from schainpy.model.proc.jroproc_base import Operation -plt.ioff() +plt.ion() func = lambda x, pos: ('%s') %(datetime.datetime.fromtimestamp(x).strftime('%H:%M')) @@ -58,6 +58,8 @@ class PlotData(Operation, Process): self.__MAXNUMY = kwargs.get('decimation', 80) self.throttle_value = 5 self.times = [] + #self.interactive = self.kwargs['parent'] + def fill_gaps(self, x_buffer, y_buffer, z_buffer): @@ -94,16 +96,22 @@ class PlotData(Operation, Process): print 'plotting...{}'.format(self.CODE) if self.show: - print 'showing' self.figure.show() self.figure2.show() self.plot() plt.tight_layout() - self.figure.canvas.manager.set_window_title('{} {} - Date:{}'.format(self.title, self.CODE.upper(), - datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S'))) - self.figure2.canvas.manager.set_window_title('{} {} - Date:{}'.format(self.title, self.CODE.upper(), - datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S'))) + +# self.figure.canvas.manager.set_window_title('{} {} - Date:{}'.format(self.title, self.CODE.upper(), +# datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S'))) +# self.figure2.canvas.manager.set_window_title('{} {} - Date:{}'.format(self.title, self.CODE.upper(), +# datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S'))) +# ======= + self.figure.canvas.manager.set_window_title('{} {} - {}'.format(self.title, self.CODE.upper(), + datetime.datetime.fromtimestamp(self.max_time).strftime('%Y/%m/%d'))) + self.figure2.canvas.manager.set_window_title('{} {} - {}'.format(self.title, self.CODE.upper(), + datetime.datetime.fromtimestamp(self.max_time).strftime('%Y/%m/%d'))) + if self.save: figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE, @@ -126,12 +134,19 @@ class PlotData(Operation, Process): def run(self): print '[Starting] {}'.format(self.name) + context = zmq.Context() receiver = context.socket(zmq.SUB) receiver.setsockopt(zmq.SUBSCRIBE, '') receiver.setsockopt(zmq.CONFLATE, self.CONFLATE) - receiver.connect("ipc:///tmp/zmq.plots") + + if 'server' in self.kwargs['parent']: + receiver.connect('ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server'])) + else: + receiver.connect("ipc:///tmp/zmq.plots") + seconds_passed = 0 + while True: try: self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)#flags=zmq.NOBLOCK @@ -637,6 +652,7 @@ class PlotNoiseData(PlotData): class PlotWindProfilerData(PlotRTIData): + CODE = 'wind' colormap = 'seismic' @@ -646,7 +662,7 @@ class PlotWindProfilerData(PlotRTIData): self.width = 10 self.height = 2.2*self.nrows self.ylabel = 'Height [Km]' - self.titles = ['Zonal' ,'Meridional', 'Vertical'] + self.titles = ['Zonal Wind' ,'Meridional Wind', 'Vertical Wind'] self.clabels = ['Velocity (m/s)','Velocity (m/s)','Velocity (cm/s)'] self.windFactor = [1, 1, 100] @@ -670,13 +686,13 @@ class PlotWindProfilerData(PlotRTIData): self.z = [] for ch in range(self.nrows): - self.z.append([self.data[self.CODE][t][ch] for t in self.times]) + self.z.append([self.data['output'][t][ch] for t in self.times]) self.z = np.array(self.z) self.z = numpy.ma.masked_invalid(self.z) cmap=plt.get_cmap(self.colormap) - cmap.set_bad('white', 1.) + cmap.set_bad('black', 1.) for n, ax in enumerate(self.axes): x, y, z = self.fill_gaps(*self.decimate()) @@ -695,9 +711,9 @@ class PlotWindProfilerData(PlotRTIData): ) divider = make_axes_locatable(ax) cax = divider.new_horizontal(size='2%', pad=0.05) - cax.set_ylabel(self.clabels[n]) self.figure.add_axes(cax) - plt.colorbar(plot, cax) + cb = plt.colorbar(plot, cax) + cb.set_label(self.clabels[n]) ax.set_ylim(self.ymin, self.ymax) ax.xaxis.set_major_formatter(FuncFormatter(func)) @@ -734,3 +750,62 @@ class PlotDOPData(PlotRTIData): class PlotPHASEData(PlotCOHData): CODE = 'phase' colormap = 'seismic' + + +class PlotSkyMapData(PlotData): + + CODE = 'met' + + def setup(self): + + self.ncols = 1 + self.nrows = 1 + self.width = 7.2 + self.height = 7.2 + + self.xlabel = 'Zonal Zenith Angle (deg)' + self.ylabel = 'Meridional Zenith Angle (deg)' + + if self.figure is None: + self.figure = plt.figure(figsize=(self.width, self.height), + edgecolor='k', + facecolor='w') + else: + self.figure.clf() + + self.ax = plt.subplot2grid((self.nrows, self.ncols), (0, 0), 1, 1, polar=True) + self.ax.firsttime = True + + + def plot(self): + + arrayParameters = np.concatenate([self.data['param'][t] for t in self.times]) + error = arrayParameters[:,-1] + indValid = numpy.where(error == 0)[0] + finalMeteor = arrayParameters[indValid,:] + finalAzimuth = finalMeteor[:,3] + finalZenith = finalMeteor[:,4] + + x = finalAzimuth*numpy.pi/180 + y = finalZenith + + if self.ax.firsttime: + self.ax.plot = self.ax.plot(x, y, 'bo', markersize=5)[0] + self.ax.set_ylim(0,90) + self.ax.set_yticks(numpy.arange(0,90,20)) + self.ax.set_xlabel(self.xlabel) + self.ax.set_ylabel(self.ylabel) + self.ax.yaxis.labelpad = 40 + self.ax.firsttime = False + else: + self.ax.plot.set_data(x, y) + + + dt1 = datetime.datetime.fromtimestamp(self.min_time).strftime('%y/%m/%d %H:%M:%S') + dt2 = datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S') + title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1, + dt2, + len(x)) + self.ax.set_title(title, size=8) + + self.saveTime = self.max_time diff --git a/schainpy/model/graphics/mpldriver.py b/schainpy/model/graphics/mpldriver.py index c09ec41..b84fb1c 100644 --- a/schainpy/model/graphics/mpldriver.py +++ b/schainpy/model/graphics/mpldriver.py @@ -204,7 +204,7 @@ def createPcolor(ax, x, y, z, xmin, xmax, ymin, ymax, zmin, zmax, z = numpy.ma.masked_invalid(z) cmap=matplotlib.pyplot.get_cmap(colormap) - cmap.set_bad('white', 1.) + cmap.set_bad('black', 1.) imesh = ax.pcolormesh(x,y,z.T, vmin=zmin, vmax=zmax, cmap=cmap) cb = matplotlib.pyplot.colorbar(imesh, cax=ax_cb) cb.set_label(cblabel) @@ -264,7 +264,7 @@ def addpcolorbuffer(ax, x, y, z, zmin, zmax, xlabel='', ylabel='', title='', col z = numpy.ma.masked_invalid(z) cmap=matplotlib.pyplot.get_cmap(colormap) - cmap.set_bad('white', 1.) + cmap.set_bad('black', 1.) ax.pcolormesh(x,y,z.T,vmin=zmin,vmax=zmax, cmap=cmap) 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/model/proc/jroproc_base.py b/schainpy/model/proc/jroproc_base.py index e52ceef..55f3afd 100644 --- a/schainpy/model/proc/jroproc_base.py +++ b/schainpy/model/proc/jroproc_base.py @@ -149,6 +149,7 @@ class ProcessingUnit(object): self.mp = True self.start() else: + self.operationKwargs[opId]['parent'] = self.kwargs methodToCall(**self.operationKwargs[opId]) else: if name=='run': @@ -187,6 +188,7 @@ class ProcessingUnit(object): if hasattr(externalProcObj, 'mp'): if externalProcObj.mp is False: + externalProcObj.kwargs['parent'] = self.kwargs self.operationKwargs[objId] = externalProcObj.kwargs externalProcObj.mp = True externalProcObj.start() @@ -194,6 +196,7 @@ class ProcessingUnit(object): externalProcObj.run(self.dataOut, **externalProcObj.kwargs) self.operationKwargs[objId] = externalProcObj.kwargs + return True def call(self, opType, opName=None, opId=None): diff --git a/schainpy/model/proc/jroproc_parameters.py b/schainpy/model/proc/jroproc_parameters.py index ee2b423..3111353 100644 --- a/schainpy/model/proc/jroproc_parameters.py +++ b/schainpy/model/proc/jroproc_parameters.py @@ -1038,7 +1038,7 @@ class WindProfiler(Operation): return data_output - def run(self, dataOut, technique, **kwargs): + def run(self, dataOut, technique, hmin=70, hmax=110, nHours=1, **kwargs): param = dataOut.data_param if dataOut.abscissaList != None: diff --git a/schainpy/model/utils/jroutils_publish.py b/schainpy/model/utils/jroutils_publish.py index 68a5907..e46c8c9 100644 --- a/schainpy/model/utils/jroutils_publish.py +++ b/schainpy/model/utils/jroutils_publish.py @@ -15,6 +15,7 @@ from threading import Thread from multiprocessing import Process from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit +from schainpy.model.data.jrodata import JROData MAXNUMX = 100 MAXNUMY = 100 @@ -257,7 +258,44 @@ class PublishData(Operation): self.client.loop_stop() self.client.disconnect() -class ReceiverData(ProcessingUnit, Process): + +class ReceiverData(ProcessingUnit): + + def __init__(self, **kwargs): + + ProcessingUnit.__init__(self, **kwargs) + + self.isConfig = False + server = kwargs.get('server', 'zmq.pipe') + if 'tcp://' in server: + address = server + else: + address = 'ipc:///tmp/%s' % server + + self.address = address + self.dataOut = JROData() + + def setup(self): + + self.context = zmq.Context() + self.receiver = self.context.socket(zmq.PULL) + self.receiver.bind(self.address) + time.sleep(0.5) + print '[Starting] ReceiverData from {}'.format(self.address) + + + def run(self): + + if not self.isConfig: + self.setup() + self.isConfig = True + + self.dataOut = self.receiver.recv_pyobj() + print '[Receiving] {} - {}'.format(self.dataOut.type, + self.dataOut.datatime.ctime()) + + +class PlotterReceiver(ProcessingUnit, Process): throttle_value = 5 @@ -268,7 +306,7 @@ class ReceiverData(ProcessingUnit, Process): self.mp = False self.isConfig = False self.isWebConfig = False - self.plottypes =[] + self.plottypes = [] self.connections = 0 server = kwargs.get('server', 'zmq.pipe') plot_server = kwargs.get('plot_server', 'zmq.web') @@ -373,8 +411,10 @@ class ReceiverData(ProcessingUnit, Process): self.data[plottype][t] = self.dataOut.getCoherence() if plottype == 'phase': self.data[plottype][t] = self.dataOut.getCoherence(phase=True) - if plottype == 'wind': + if plottype == 'output': self.data[plottype][t] = self.dataOut.data_output + if plottype == 'param': + self.data[plottype][t] = self.dataOut.data_param if self.realtime: self.data_web['timestamp'] = t if plottype == 'spc': @@ -402,8 +442,14 @@ class ReceiverData(ProcessingUnit, Process): self.sender_web = self.context.socket(zmq.PUB) self.sender_web.connect(self.plot_address) time.sleep(1) - self.sender.bind("ipc:///tmp/zmq.plots") + + if 'server' in self.kwargs: + self.sender.bind("ipc:///tmp/{}.plots".format(self.kwargs['server'])) + else: + self.sender.bind("ipc:///tmp/zmq.plots") + time.sleep(3) + t = Thread(target=self.event_monitor, args=(monitor,)) t.start() @@ -417,7 +463,6 @@ class ReceiverData(ProcessingUnit, Process): if self.dataOut.firstdata is True: self.data['STARTED'] = True - if self.dataOut.finished is True: self.send(self.data) self.connections -= 1 diff --git a/schainpy/project.py b/schainpy/project.py new file mode 100644 index 0000000..bdea4c3 --- /dev/null +++ b/schainpy/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/schainpy", + 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/schainpy/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/schainpy/scripts/project.py b/schainpy/scripts/project.py new file mode 100644 index 0000000..17237bd --- /dev/null +++ b/schainpy/scripts/project.py @@ -0,0 +1,33 @@ +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/schainpy/scripts", + startDate="1970/01/01", + endDate="2017/12/31", + startTime="00:00:00", + endTime="23:59:59", + online=0, + 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/schainpy/scripts/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/schainpy/scripts/receiver.py b/schainpy/scripts/receiver.py index c0a4bf6..73af1b8 100644 --- a/schainpy/scripts/receiver.py +++ b/schainpy/scripts/receiver.py @@ -14,14 +14,16 @@ if __name__ == '__main__': controllerObj = Project() controllerObj.setup(id='191', name='test01', description=desc) - proc1 = controllerObj.addProcUnit(name='ReceiverData') + proc1 = controllerObj.addProcUnit(name='PlotterReceiver') # proc1.addParameter(name='realtime', value='0', format='bool') #proc1.addParameter(name='plottypes', value='rti,coh,phase,snr,dop', format='str') #proc1.addParameter(name='plottypes', value='rti,coh,phase,snr', format='str') proc1.addParameter(name='plottypes', value='dop', format='str') - proc1.addParameter(name='throttle', value='10', format='int') - #proc1.addParameter(name='server', value='tcp://10.10.10.82:7000', format='str') + #proc1.addParameter(name='throttle', value='10', format='int') + + proc1.addParameter(name='interactive', value='0', format='bool') # ? PREGUNTAR + # proc1.addParameter(name='server', value='tcp://10.10.10.82:7000', format='str') ## TODO Agregar direccion de server de publicacion a graficos como variable """ diff --git a/schainpy/scripts/schain.xml b/schainpy/scripts/schain.xml index fe952f2..cf3e5c5 100644 --- a/schainpy/scripts/schain.xml +++ b/schainpy/scripts/schain.xml @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/schainpy/utils/__init__.py b/schainpy/utils/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/schainpy/utils/__init__.py diff --git a/schainpy/utils/log.py b/schainpy/utils/log.py new file mode 100644 index 0000000..85f1489 --- /dev/null +++ b/schainpy/utils/log.py @@ -0,0 +1,45 @@ +""". +SCHAINPY - LOG + Simple helper for log standarization + Usage: + from schainpy.utils import log + log.error('A kitten died beacuse of you') + log.warning('You are doing it wrong but what the heck, I'll allow it) + log.succes('YOU ROCK!') + To create your own logger inside your class do it like this: + from schainpy.utils import log + awesomeLogger = log.makelogger("never gonna", bg="red", fg="white") + awesomeLogger('give you up') + which will look like this: + [NEVER GONNA] - give you up + with color red as background and white as foreground. +""" + +import click + + +def warning(message): + click.echo(click.style('[WARNING] - ' + message, fg='yellow')) + pass + + +def error(message): + click.echo(click.style('[ERROR] - ' + message, fg='red')) + pass + + +def success(message): + click.echo(click.style(message, fg='green')) + pass + + +def log(message): + click.echo('[LOG] - ' + message) + pass + + +def makelogger(topic, bg='reset', fg='reset'): + def func(message): + click.echo(click.style('[{}] - '.format(topic.upper()) + message, + bg=bg, fg=fg)) + return func diff --git a/setup.py b/setup.py index 3fe773f..dcee0b2 100644 --- a/setup.py +++ b/setup.py @@ -1,49 +1,57 @@ -''' +""". + Created on Jul 16, 2014 @author: Miguel Urco -''' +""" from schainpy import __version__ from setuptools import setup, Extension setup(name="schainpy", - version=__version__, - description="Python tools to read, write and process Jicamarca data", - author="Miguel Urco", - author_email="miguel.urco@jro.igp.gob.pe", - url="http://jro.igp.gob.pe", - packages = {'schainpy', - 'schainpy.model', - 'schainpy.model.data', - 'schainpy.model.graphics', - 'schainpy.model.io', - 'schainpy.model.proc', - 'schainpy.model.serializer', - 'schainpy.model.utils', - 'schainpy.gui', - 'schainpy.gui.figures', - 'schainpy.gui.viewcontroller', - 'schainpy.gui.viewer', - 'schainpy.gui.viewer.windows'}, - ext_package='schainpy', - py_modules=[''], - package_data={'': ['schain.conf.template'], - 'schainpy.gui.figures': ['*.png','*.jpg'], - }, - include_package_data=False, - scripts =['schainpy/gui/schainGUI', - 'schainpy/scripts/schain'], - ext_modules=[Extension("cSchain", ["schainpy/model/proc/extensions.c"])], - install_requires=[ - "scipy >= 0.14.0", - "h5py >= 2.2.1", - "matplotlib >= 1.4.2", - "pyfits >= 3.4", - "numpy >= 1.11.2", - "paramiko >= 2.1.2", - "paho-mqtt >= 1.2", - "zmq", - "fuzzywuzzy" - ], + version=__version__, + description="Python tools to read, write and process Jicamarca data", + author="Miguel Urco", + author_email="miguel.urco@jro.igp.gob.pe", + url="http://jro.igp.gob.pe", + packages={'schainpy', + 'schainpy.model', + 'schainpy.model.data', + 'schainpy.model.graphics', + 'schainpy.model.io', + 'schainpy.model.proc', + 'schainpy.model.serializer', + 'schainpy.model.utils', + 'schainpy.gui', + 'schainpy.gui.figures', + 'schainpy.gui.viewcontroller', + 'schainpy.gui.viewer', + 'schainpy.gui.viewer.windows'}, + ext_package='schainpy', + py_modules=[''], + package_data={'': ['schain.conf.template'], + 'schainpy.gui.figures': ['*.png', '*.jpg'], + }, + include_package_data=False, + entry_points={ + 'console_scripts': [ + 'schain = schaincli.cli:main', + ], + }, + scripts=['schainpy/gui/schainGUI'], + ext_modules=[Extension("cSchain", ["schainpy/model/proc/extensions.c"])], + install_requires=[ + "scipy >= 0.14.0", + "h5py >= 2.2.1", + "matplotlib >= 1.4.2", + "pyfits >= 3.4", + "numpy >= 1.11.2", + "paramiko >= 2.1.2", + "paho-mqtt >= 1.2", + "zmq", + "fuzzywuzzy", + "click", + "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