diff --git a/pykat/__init__.py b/pykat/__init__.py index 7a8eb2ab89b44ecca17ec101d10ccaa7576d94a8..bbcc325973d0cf54df565209418b5e1087fddd3f 100644 --- a/pykat/__init__.py +++ b/pykat/__init__.py @@ -3,7 +3,7 @@ from __future__ import division from __future__ import print_function from __future__ import unicode_literals -__version__ = "0.8.10" +__version__ = "1.0.0" # This flag is used to switch on the gui features in pkat at import time USE_GUI = False diff --git a/pykat/finesse.py b/pykat/finesse.py index fd4bf9f03e613b08d22d05ba01aaaca40a52ffde..f0cd57108ead3bf2a2a8901728bf4044e0bb28de 100644 --- a/pykat/finesse.py +++ b/pykat/finesse.py @@ -28,6 +28,7 @@ from __future__ import division from __future__ import print_function from __future__ import unicode_literals +import uuid import sys import os import subprocess @@ -47,6 +48,8 @@ import collections import re import copy +from subprocess import Popen, PIPE + try: # Python 2 from itertools import izip_longest @@ -73,6 +76,7 @@ from pykat.components import Component from pykat.commands import Command, xaxis from pykat.SIfloat import * from pykat.param import Param, AttrParam +from pykat.external import progressbar import pykat.external.six as six @@ -206,7 +210,7 @@ class KatBatch(object): if "cmd_args" in kwargs: kw["cmd_args"] = kwargs["cmd_args"] - return kat.run(printerr=1, **kw) + return kat.run(**kw) def addKat(self, kat, **kwargs): import os @@ -492,6 +496,8 @@ class katRun2D(object): self.zlabels = None self.katScript = None self.katVersion = None + self.stderr = None + self.stdout = None def saveKatRun(self, filename): with open(filename,'w') as outfile: @@ -1326,13 +1332,11 @@ class kat(object): except pkex.BasePyKatException as ex: print (ex) - def run(self, printout=0, printerr=0, plot=None, save_output=False, save_kat=False, kat_name=None, cmd_args=None, getTraceData=False, rethrowExceptions=False): + def run(self, plot=None, save_output=False, save_kat=False, kat_name=None, cmd_args=None, getTraceData=False, rethrowExceptions=False): """ Runs the current simulation setup that has been built thus far. It returns a katRun or katRun2D object which is populated with the various data from the simulation run. - printout=1 prints the Finesse banner - printerr shows the Finesse progress (set kat.verbose=1 to see warnings and errors) plot (string) - Sets gnuterm for plotting save_output (bool) - if true does not delete out file save_kat (bool) - if true does not delete kat file @@ -1404,13 +1408,12 @@ class kat(object): katfile = open( filepath, 'w' ) katfile.writelines(r.katScript) - #katfile.writelines(bytes(r.katScript, 'UTF-8')) + katfile.flush() - if printout == 1 or plot != None: - cmd=[kat_exec] - else: - cmd=[kat_exec, '--perl1'] + pipe_name = katfile.name + str(uuid.uuid4()) + + cmd=[kat_exec, "--pykat=" + pipe_name] if self.__time_code: cmd.append('--perf-timing') @@ -1427,85 +1430,68 @@ class kat(object): cmd.append('-format=%.15g') cmd.append(katfile.name) - - p=subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - err = "" - #if self.verbose: print "Finesse output:" - for aline in iter(p.stderr.readline, b""): - if six.PY2: - line = unicode(aline, "utf-8") - else: - line = aline - - if len(line) > 0: - # remove any ANSI commands - line = re.sub(br'\x1b[^m]*m',b'', line, re.UNICODE) - - # warnings and errors start with an asterisk - # so if verbose show them - if line.lstrip().startswith(b'*PROG*'): - line = line[8:-1] - vals = line.split(b"-",1) - action = vals[0].strip() - prc = vals[1].strip()[:] + if sys.platform == "win32" or sys.platform == "cygwin": + # Pipes in windows need to be prefixed with a hidden location. + pipe_name = "\\\\.\\pipe\\" + pipe_name + + p = Popen(cmd, stderr=PIPE, stdout=PIPE) + + if self.verbose: + pb = progressbar.ProgressBar() + + fifo = None + + start = time.time() + duration = 5 # Duration for searching for open pipe + + try: + while fifo is None: + try: + if time.time() < start + duration: + time.sleep(0.1) + fifo = open(pipe_name, "r") + else: + raise Exception("Could not connect to pykat pipe in {0} seconds.".format(duration)) + except FileNotFoundError as ex: + if self.verbose: + print("Looking for pipe...") + + for line in fifo: + v = line.split(":", 1) - if printerr == 1: - if six.PY2: - sys.stdout.write("\r{0} {1}".format(action, prc)) - else: - sys.stdout.write("\r{0} {1}".format(str(action, 'utf-8'), str(prc, 'utf-8'))) - - elif line.lstrip().startswith(b'*'): - if self.verbose: - if six.PY2: - sys.stdout.write(line) - else: - sys.stdout.write(str(line,'utf-8')) - - elif line.rstrip().endswith(b'%'): - vals = line.split(b'-') - action = vals[0].strip() - prc = vals[1].strip()[:] + if len(v) != 2: + continue - if printerr == 1: - if six.PY2: - sys.stdout.write("\r{0} {1}".format(action, prc)) - else: - sys.stdout.write("\r{0} {1}".format(str(action, 'utf-8'), str(prc, 'utf-8'))) - - else: - if six.PY2: - err="".join((err,line)) - else: - err="".join((err,str(line, 'utf-8'))) - - - [out, errpipe] = p.communicate() + (tag, line) = v + + if tag == "version": + r.katVersion = line + elif tag == "progress": + var = line.split("\t") + + if len(var) == 3 and self.verbose: + pb.currval = int(var[1]) + pb.update() + finally: + if fifo is not None: + fifo.close() + + (stdout, stderr) = p.communicate() + + r.stdout = stdout.decode('unicode_escape') + r.stderr = stderr.decode('unicode_escape') - if six.PY2: - _out = str(out).split("\n") - else: - _out = str(out).split("\\n") + if p.returncode != 0: + print(r.stderr) - for line in _out[::-1]: + for line in r.stdout[::-1]: if line.lstrip().startswith('computation time:'): try: r.runtime = float(line.split(":")[1].replace("s","")) except: r.runtime = 0.0 - if printout == 1: - print (out) - else: - if printerr == 1: print ("") - - # get the version number - ix = out.find(b'build ') + 6 - ix2 = out.find(b')',ix) - - r.katVersion = out[ix:ix2] - r.runDateTime = datetime.datetime.now() # If Finesse returned an error, just print that and exit! @@ -1614,20 +1600,6 @@ class kat(object): if self.verbose: print ("Kat file saved to '{0}'".format(newkatfile)) - if self.trace != None and self.trace > 0: - #print ("{0}".format(out)) - #if self.trace & 1: - #search = out.find(' --- highest order of TEM modes') - #if search > -1: - #print ("Trace 1: {0}".format(out[search:])) - - # For now, just try to print the trace block in full. - # Converting to unicode so it works in python 3. - tmpOut = out.decode('unicode_escape') - print (tmpOut[tmpOut.find(' ---') :]) - # print (out[out.find(' ---') :]) - - katfile.close() perfData = [] @@ -1667,8 +1639,9 @@ class kat(object): else: pkex.PrintError("Error from pykat:", ex) finally: - if self.verbose: print ("") - if self.verbose: print ("Finished in " + str(datetime.datetime.now()-start)) + if self.verbose: + print ("") + print ("Finished in " + str(time.time() + start)) def remove(self, obj): try: @@ -1758,7 +1731,7 @@ class kat(object): self.printmatrix = True print ("".join(self.generateKatScript())) self.verbose = True - self.run(printout=1) + self.run() self.printmatrix = None self.noxaxis = prev diff --git a/setup.py b/setup.py index 3b048cef0f7cb3d4e146d42616546c734845597e..deda7ff6355b81fae499e4a38e35e906e7a8447b 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ setup( version=version, author='Daniel Brown', author_email='ddb@star.sr.bham.ac.uk', - packages=['pykat','pykat.testing','pykat.testing.web','pykat.maths','pykat.optics', 'pykat.external', 'pykat.tools'], + packages=[x[0].replace("/",".") for x in os.walk("pykat") if "__" not in x[0]], url='http://pypi.python.org/pypi/PyKat/', license='GPL v2', description='Python interface and tools for FINESSE',