finesse.py 62.1 KB
Newer Older
Daniel Brown's avatar
Daniel Brown committed
1001
1002
            err = ""
            
1003
            #if self.verbose: print "Finesse output:"            
1004
            for aline in iter(p.stderr.readline, b""):
1005
1006
1007
1008
                if six.PY2:
                    line = unicode(aline, "utf-8")
                else:
                    line = aline
1009
                if len(line) > 0:
1010
                    # remove any ANSI commands
1011
1012
                    #ansi = re.compile(r'\x1b[^m]*m')
                    #line = ansi.sub('', line)
1013
                    line = re.sub(br'\x1b[^m]*m', '', line, re.UNICODE)
1014

1015
1016
                    # warnings and errors start with an asterisk 
                    # so if verbose show them
1017
                    if line.lstrip().startswith(b'*PROG*'):
1018
                        line = line[8:-1]
1019
                        vals = line.split(b"-",1)
1020
1021
1022
1023
                        action = vals[0].strip()
                        prc = vals[1].strip()[:]
                    
                        if printerr == 1:
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
                            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(line) # todo fix this if needed        
                    elif line.rstrip().endswith(b'%'):
Daniel Brown's avatar
Daniel Brown committed
1035
1036
1037
1038
1039
                        vals = line.split("-")
                        action = vals[0].strip()
                        prc = vals[1].strip()[:]
                        
                        if printerr == 1:
1040
                            sys.stdout.write("\r{0} {1}".format(action, str(prc)))
1041
                            
1042
                    else:
1043
                        err += str(line)
1044

Daniel Brown's avatar
Daniel Brown committed
1045
            
Daniel Brown's avatar
Daniel Brown committed
1046
            [out,errpipe] = p.communicate()
1047
            
1048
            if printout == 1: 
1049
                print (out)
Andreas Freise's avatar
Andreas Freise committed
1050
            else:
1051
                if printerr == 1: print ("")
1052

Daniel Brown's avatar
Daniel Brown committed
1053
            # get the version number
1054
1055
            ix = out.find(b'build ') + 6
            ix2 = out.find(b')',ix)
Daniel Brown's avatar
Daniel Brown committed
1056
1057
            r.katVersion = out[ix:ix2]
            
1058
1059
            r.runDateTime = datetime.datetime.now()

1060
            # If Finesse returned an error, just print that and exit!
Daniel Brown's avatar
Daniel Brown committed
1061
            if p.returncode != 0:
1062
                print (err)
1063
                sys.exit(1) 
1064
            
1065
1066
            self.__prevrunfilename = katfile.name
            
Daniel Brown's avatar
Daniel Brown committed
1067
            root = os.path.splitext(katfile.name)
1068
            base = os.path.basename(root[0])            
Daniel Brown's avatar
Daniel Brown committed
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
            outfile = root[0] + ".out"
            
            if save_output:        
                newoutfile = "{0}.out".format(base)
                
                cwd = os.path.os.getcwd()
                newoutfile = os.path.join(cwd,newoutfile)
                
                if os.path.isfile(newoutfile):
                    os.remove(newoutfile)
                    
                os.rename(outfile, newoutfile)

1082
                if self.verbose: print ("\nOutput data saved to '{0}'".format(newoutfile))
Daniel Brown's avatar
Daniel Brown committed
1083
            
1084
1085
            if hasattr(self, "x2axis") and self.noxaxis == False:
                [r.x,r.y,r.z,hdr] = self.readOutFile(outfile)
Daniel Brown's avatar
Daniel Brown committed
1086
                
1087
1088
                r.xlabel = hdr[0]
                r.ylabel = hdr[1]
1089
                r.zlabels = [s.strip() for s in hdr[2:]]
1090
                #r.zlabels = map(str.strip, hdr[2:])
1091
1092
            else:
                [r.x,r.y,hdr] = self.readOutFile(outfile)
Daniel Brown's avatar
Daniel Brown committed
1093
            
1094
                r.xlabel = hdr[0]
1095
                r.ylabels = [s.strip() for s in hdr[1:]]
1096
                #r.ylabels = map(str.strip, hdr[1:]) // replaced 090415 adf 
1097
                    
Daniel Brown's avatar
Daniel Brown committed
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
            if save_kat:
                if kat_name == None:
                    kat_name = "pykat_output"                
                
                cwd = os.path.os.getcwd()
                newkatfile = os.path.join(cwd, kat_name + ".kat")
                
                if os.path.isfile(newkatfile):
                    os.remove(newkatfile)
                  
                os.rename(katfile.name, newkatfile)         
                
1110
                if self.verbose: print ("Kat file saved to '{0}'".format(newkatfile))
Daniel Brown's avatar
Daniel Brown committed
1111
                
Sean Leavey's avatar
Sean Leavey committed
1112
            if self.trace != None and self.trace > 0:
1113
                #print ("{0}".format(out))
Sean Leavey's avatar
Sean Leavey committed
1114
1115
1116
                #if self.trace & 1:
                    #search = out.find(' --- highest order of TEM modes')
                    #if search > -1:
1117
                        #print ("Trace 1: {0}".format(out[search:]))
Sean Leavey's avatar
Sean Leavey committed
1118
1119

                # for now, just try to print the trace block in full
1120
                print (out[out.find(' ---') :])
Daniel Brown's avatar
Daniel Brown committed
1121
1122
1123
1124
1125
1126
1127
1128

            katfile.close()
            perfData = []
            
            if self.__time_code:
                perffile = open(root[0] + ".perf",'r')
                
                for l in perffile.readlines():
1129
                    vals = l.strip().split()
1130
                    perfData.append((vals[0], float(vals[1]), float(vals[2]), float(vals[3])))
Daniel Brown's avatar
Daniel Brown committed
1131
                    
1132
                return [r, perfData]
Daniel Brown's avatar
Daniel Brown committed
1133
            else:
1134
                return r
1135
1136
            
        except pkex.FinesseRunError as fe:
1137
            print (fe)
Daniel Brown's avatar
Daniel Brown committed
1138
        finally:
1139
1140
            if self.verbose: print ("")
            if self.verbose: print ("Finished in " + str(datetime.datetime.now()-start))
Daniel Brown's avatar
Daniel Brown committed
1141
            
1142
    def remove(self, obj):
Daniel Brown's avatar
Daniel Brown committed
1143
        if not isinstance(obj, pykat.finesse.Signals) and not (obj.name in self.__components  or obj.name in self.__detectors or obj.name in self.__commands or obj in self.signals.targets):
1144
            raise pkex.BasePyKatException("{0} is not currently in the simulation".format(obj.name))
Daniel Brown's avatar
Daniel Brown committed
1145
            
1146
1147
        if obj.removed:
            raise pkex.BasePyKatException("{0} has already been removed".format(obj.name))        
Daniel Brown's avatar
Daniel Brown committed
1148
1149

        nodes = None
1150
        
Daniel Brown's avatar
Daniel Brown committed
1151
1152
1153
1154
        # store nodes that this componet is attached to as a reference for gui
        if isinstance(obj, Component):
            nodes = self.nodes.getComponentNodes(obj)

1155
1156
1157
        if isinstance(obj, Component):    
            del self.__components[obj.name]
            self.__del_component(obj)
1158
            self.nodes._removeComponent(obj)
1159
1160
1161
1162
1163
1164
        elif isinstance(obj, Command):    
            del self.__commands[obj.name]
            self.__del_command(obj)
        elif isinstance(obj, Detector):    
            del self.__detectors[obj.name]
            self.__del_detector(obj)
Daniel Brown's avatar
Daniel Brown committed
1165
1166
1167
        elif isinstance(obj, pykat.finesse.Signals):
            obj.remove()
        elif isinstance(obj, pykat.finesse.Signals.fsig):
1168
            obj._on_remove()
Daniel Brown's avatar
Daniel Brown committed
1169
            
1170
1171
1172
1173
        for b in self.__blocks:
            if obj in self.__blocks[b].contents:
                self.__blocks[b].contents.remove(obj)
        
Daniel Brown's avatar
Daniel Brown committed
1174
1175
1176
1177
1178
        if self.pykatgui != None:
            self.pykatgui._onComponentRemoved(obj, nodes)
    
        del nodes
        
1179
        #import gc
1180
        #print (gc.get_referrers(obj))
1181
    
1182
1183
1184
1185
1186
1187
1188
1189
1190
    def getMatrices(self):
        
        import scipy
        from scipy.sparse import coo_matrix
        
        prev = self.noxaxis
        
        self.noxaxis = True
        self.printmatrix = True
1191
        print ("".join(self.generateKatScript()))
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
        self.verbose = True
        self.run(printout=1)
        self.printmatrix = None
        self.noxaxis = prev        
        
        if self.__prevrunfilename == None:
            return None
        else:
            
            Mcarrier = None
            Msignal = None
            
            if os.path.exists("klu_full_matrix_car.dat"):
                M = np.loadtxt("klu_full_matrix_car.dat")
                
                if M.size > 0:
                    row = M[:,0]-1
                    col = M[:,1]-1
                    data = M[:,2] + 1j * M[:,3]
                    N = row.max()+1
                    Mcarrier = coo_matrix((data,(row,col)), shape=(N,N))
                
        
            if os.path.exists("klu_full_matrix_sig.dat"):
                M = np.loadtxt("klu_full_matrix_sig.dat")
                
                if M.size > 0:
                    row = M[:,0]-1
                    col = M[:,1]-1
                    data = M[:,2] + 1j * M[:,3]
                    N = row.max()+1
                    Msignal = coo_matrix((data,(row,col)), shape=(N,N))
        
            return (Mcarrier, Msignal)

1227
    
1228
1229
    def hasNamedObject(self, name):
        return name in self.__components or name in self.__detectors or name in self.__commands
Daniel Brown's avatar
Daniel Brown committed
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
        
    def add(self, obj):
        try:
            obj.tag = self.__currentTag
            self.__blocks[self.__currentTag].contents.append(obj)
            
            if isinstance(obj, Component):
                
                if obj.name in self.__components :
                    raise pkex.BasePyKatException("A component with name '{0}' has already been added".format([obj.name]))            
                            
                self.__components[obj.name] = obj
                self.__add_component(obj)
                
            elif isinstance(obj, Detector):
                
                if obj.name in self.__detectors :
                        raise pkex.BasePyKatException("A detector '{0}' has already been added".format(obj.name))
                        
                self.__detectors[obj.name] = obj
                self.__add_detector(obj)
                
            elif isinstance(obj, Command):
                
                self.__commands[obj.__class__.__name__] = obj
                self.__add_command(obj)
                
1257
            else:
Daniel Brown's avatar
Daniel Brown committed
1258
1259
1260
1261
1262
                raise pkex.BasePyKatException("Object {0} could not be added".format(obj))
                
            obj._on_kat_add(self)
            
        except pkex.BasePyKatException as ex:
1263
            print (ex)
Daniel Brown's avatar
Daniel Brown committed
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273

    def readOutFile(self, filename):
        
        with open(filename,'r') as outfile:
            # read first to lines to get to header line
            outfile.readline()
            outfile.readline()
            
            hdr = outfile.readline().replace('%','').replace('\n','').split(',')
        
1274
1275
1276
1277
1278
1279
        data = np.loadtxt(filename, comments='%',skiprows=4)

        # convert 1D arrays into 2D ones for simpler selection
        if len(data.shape) == 1:
            data = np.array([data])
                            
1280
        if hasattr(self, "x2axis") and self.noxaxis == False:
Daniel Brown's avatar
Daniel Brown committed
1281
1282
            # need to parse 2D outputs slightly different as they are effectively 2D matrices
            # written in linear form
1283
            x = data[0::(1+self.x2axis.steps),0]
1284
            y = data[0:(1+self.x2axis.steps),1]
Daniel Brown's avatar
Daniel Brown committed
1285
1286
            # get rows and columns lined up so that we can reshape a single column of all x/y data
            # into a matrix
1287
            z = data[:,2:].transpose().reshape(data.shape[1]-2, 1+self.xaxis.steps, 1+self.x2axis.steps)
Daniel Brown's avatar
Daniel Brown committed
1288
1289
1290
1291
1292
1293
            # once you do this the data for y and x axes need swapping
            z = z.swapaxes(1,2)
            return [x, y, z, hdr]
        else:
            shape_len = len(data.shape)
            
1294
            rows,cols = data.shape
Daniel Brown's avatar
Daniel Brown committed
1295
            
1296
            x = data[:,0]
1297
            y = data[:,1:cols]
1298
        
Daniel Brown's avatar
Daniel Brown committed
1299
            return [x, y, hdr]
1300
1301

    def removeLine(self, fragment) :
1302
        """
1303
1304
1305
1306
1307
        This will search all blocks by default and search for the string
        fragment specified and remove it. This will only remove non-parsed
        commands, it will not remove commands that have already been parsed
        into the pykat structure, such as mirrors and beamsplitters, use the
        kat.remove(...) function for that purpose.
1308
        """
1309
1310
1311
        for key in self.__blocks:
            objs = self.__blocks[key].contents
            for obj in objs:
1312
                if isinstance(obj,  six.string_types):
1313
                    if fragment in obj:
1314
                        print ("  ** removing line '{0}'".format(obj))
1315
                        objs.remove(obj)
1316

1317
1318
1319
1320
1321
1322
1323
    def addLine(self, line, block=NO_BLOCK) :
        """
        This will forcefully add a line of FINESSE code to a particular block
        if specfied. This command will not undergo any parsing so it will remain
        as just a string. This of course can create possible conflicts with other
        pykat object that create similar commands so becareful.
        """
Daniel Brown's avatar
Daniel Brown committed
1324
        self.__blocks[block].contents.append(line)
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
        
    def printExtraLines(self):
        """
        This prints all the Finesse commands that have not been parsed
        into pykat objects. This should be used for reference only. To
        add or remove extra lines use the addLine and removeLine methods.
        """
        found = False
        
        for key in self.__blocks:
            objs = self.__blocks[key].contents
            for obj in objs:
                if isinstance(obj, six.string_types):
                    print(obj)
                    found = True
        
        if not found:
            print("No extra lines were found")
        
1344
                        
Daniel Brown's avatar
Daniel Brown committed
1345
1346
    def generateKatScript(self) :
        """ Generates the kat file which can then be run """
1347

1348
        def writeBlock():
Daniel Brown's avatar
Daniel Brown committed
1349
            for obj in objs:
1350
                if isinstance(obj, six.string_types):
Daniel Brown's avatar
Daniel Brown committed
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
                    out.append(obj + '\n')
                    
                elif isinstance(obj, Component) or isinstance(obj, Detector) or isinstance(obj, Command):
                    txt = obj.getFinesseText() 
                    
                    if txt != None:
                        if isinstance(txt,list):
                            for t in txt:
                                out.append(t + "\n")
                        else:
                            out.append(txt + "\n")
1362

1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
        
        out = []    
        import datetime
        strtoday = datetime.datetime.now()
        out.append(strtoday.strftime("%% Generated by PyKat %d.%m.%Y %H:%M:%S\n") )

        # write the FTblocks
        for key in self.__blocks:
            objs = self.__blocks[key].contents

1373
            if key != NO_BLOCK:
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
                if np.size(objs)>0:
                    out.append("\n")
                    out.append("%%% FTblock " + key + "\n")
                    writeBlock()
                    out.append("%%% FTend " + key + "\n")

        # write the NO_BLOCK blocks
        for key in self.__blocks:
            objs = self.__blocks[key].contents


            if key == NO_BLOCK:
                if np.size(objs)>0:
                    out.append("\n")
                    writeBlock()
                
Daniel Brown's avatar
Daniel Brown committed
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
        # now loop through all the nodes and get any gauss commands
        for key in self.nodes.getNodes():
            txt = self.nodes.getNodes()[key].getFinesseText()
            
            if txt != None:
                if isinstance(txt,list):
                    for t in txt: out.append(t+ "\n")
                else:
                    out.append(txt + "\n")
        
1400

1401
1402
1403
1404
1405
1406
1407
1408
1409
        # now get any signal commands
        txt = self.signals.getFinesseText()
        
        if txt != None:
            if isinstance(txt,list):
                for t in txt: out.append(t+ "\n")
            else:
                out.append(txt + "\n")

1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
        if self.vacuum != None:
            
            if isinstance(self.vacuum, collections.Container):
                objs = []
                
                if len(self.vacuum) > 0:
                    for a in self.vacuum:
                        if hasattr(a, 'name'):
                            objs.append(a.name)
                        else:
                            objs.append(str(a))

                    out.append("vacuum {0}\n".format(" ".join(objs)))
                                        
1424
            elif isinstance(self.vacuum, six.string_types):
1425
1426
1427
1428
                out.append("vacuum {0}\n".format(self.vacuum))
            else:
                pkex.BasePyKatException("Couldn't understand vacuum input list")

1429
        if self.scale != None and self.scale !='': out.append("scale {0}\n".format(self.scale))
Daniel Brown's avatar
Daniel Brown committed
1430
        if self.phase != None: out.append("phase {0}\n".format(self.phase))
Sean Leavey's avatar
Sean Leavey committed
1431
        if self.trace != None: out.append("trace {0}\n".format(self.trace))
1432
1433
1434
1435
1436
        if self.maxtem != None:
                if self.maxtem == -1:
                        out.append("maxtem off\n")
                else:
                        out.append("maxtem {0}\n".format(self.maxtem))
Daniel Brown's avatar
Daniel Brown committed
1437

1438
1439
        if self.noxaxis == True:
            out.append("noxaxis\n")
1440
            
1441
1442
        if self.yaxis != None:
            out.append("yaxis {0}\n".format(self.yaxis))
1443
1444
1445
1446
         
        if self.printmatrix != None and self.printmatrix == True:
            out.append("printmatrix\n")
            
Daniel Brown's avatar
Daniel Brown committed
1447
1448
        if self.lambda0 != 1064e-9:
            out.append("lambda {0}\n".format(self.lambda0))
1449
            
Daniel Brown's avatar
Daniel Brown committed
1450
1451
        # ensure we don't do any plotting. That should be handled
        # by user themselves
1452
1453
        #out.append("gnuterm no\n")
        #out.append("pyterm no\n")
Daniel Brown's avatar
Daniel Brown committed
1454
1455
        
        return out
Daniel Brown's avatar
Daniel Brown committed
1456
        
Daniel Brown's avatar
Daniel Brown committed
1457
    def openGUI(self):
1458
1459
        if not USE_GUI:
            raise NoGUIException
Daniel Brown's avatar
Daniel Brown committed
1460
1461
1462
        else:
            self.app = QCoreApplication.instance() 
            created = False
1463
            
Daniel Brown's avatar
Daniel Brown committed
1464
1465
1466
            if self.app == None:
                created = True
                self.app = QApplication([""])
1467
                
Daniel Brown's avatar
Daniel Brown committed
1468
1469
1470
1471
1472
            if self.pykatgui == None:
                self.pykatgui = pyKatGUI(self)
                self.pykatgui.main()
            else:
                self.pykatgui.show()
1473
                
Daniel Brown's avatar
Daniel Brown committed
1474
            if created: self.app.exec_()
1475
    
Daniel Brown's avatar
Daniel Brown committed
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
    def getComponents(self):
        return self.__components.values()
    
    def hasComponent(self, name):
        return (name in self.__components)
    
    def _newName(self, container, prefix):
        n = 1
        name = "{0}{1}".format(prefix, n)
        
        while name in container:
            n += 1
            name = "{0}{1}".format(prefix,n)
        
        return name
    
    def getNewComponentName(self,prefix):
        '''
        Returns a name for a component which hasn't already been added.
        Returns [prefix] + number, where number is greater than 1. e.g.
        if m1 exists getNewName('m') will return 'm2'
        '''
        return self._newName(self.__components, prefix)
    
    def getNewDetectorName(self,prefix):
        '''
        Returns a name for a component which hasn't already been added.
        Returns [prefix] + number, where number is greater than 1. e.g.
        if m1 exists getNewName('m') will return 'm2'
        '''
        return self._newName(self.__detectors, prefix)
        
    def getNewNodeNames(self,prefix,N=1):
        '''
        Returns a list of names for N number of nodes which haven't already been added.
        Returns [prefix] + number, where number is greater than 1. e.g.
        if m1 exists getNewName('m') will return 'm2'
        '''
        rtn = []
        n = 1
        
        for M in range(1,N+1):
            name = "{0}{1}".format(prefix, n)
            
            while name in self.nodes.getNodes() or (name in rtn):
                n += 1
                name = "{0}{1}".format(prefix,n)
        
            rtn.append(name)
            
        return rtn
        
1528
1529
1530
1531
1532
1533
1534
    def lkat_trace(self, getCavities=True, getNodes=True, getSpaces=True):
        """
        Given the current state of the kat object a new FINESSE process is called and just
        the beam tracing routine is run. The object that is returned contains all the information
        from the beam tracing routine for each node and space components defined as well as cavity 
        commands.   
        """
Daniel Brown's avatar
Daniel Brown committed
1535
1536
1537
1538
        if lkat_location == None:
            raise RuntimeError("Could not find shared library 'libkat', please install to a system location or copy to the same directory as this script")
            
        trace_info = Manager().dict()
1539
1540
1541
1542
1543
        
        prev = self.maxtem
        self.maxtem = 0
        
        try:
1544
1545
            p = self.getProcess(f__lkat_trace_callback, trace_info=trace_info,
                                getCavities=getCavities, getNodes=getNodes, getSpaces=getSpaces)
1546
1547
            p.start()
            p.join()
1548
            p.terminate()
1549
            
1550
1551
1552
            # return a local copy of the trace information dictionary
            return dict(trace_info)
        finally: 
1553
            self.maxtem = prev
Daniel Brown's avatar
Daniel Brown committed
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
    
    def __add_detector(self, det):

        if not isinstance(det, Detector):
            raise exceptions.ValueError("Argument is not of type Detector")
        
        name = det.name
        fget = lambda self: self.__get_detector(name)
        
        setattr(self.__class__, name, property(fget))
1564
1565
1566
        setattr(self, '__det_' + name, det)                

    def __del_detector(self, det):
Daniel Brown's avatar
Daniel Brown committed
1567

1568
        if not isinstance(det, Detector):
1569
            raise pkex.BasePyKatException("Argument is not of type Detector")
1570
1571
1572
1573
1574
1575
        
        name = det.name
        
        delattr(self.__class__, name)
        delattr(self, '__det_' + name) 
        
Daniel Brown's avatar
Daniel Brown committed
1576
1577
1578
1579
1580
1581
    def __get_detector(self, name):
        return getattr(self, '__det_' + name) 
        
    def __add_command(self, com):

        if not isinstance(com, Command):
1582
            raise pkex.BasePyKatException("Argument is not of type Command")
Daniel Brown's avatar
Daniel Brown committed
1583
1584
1585
1586
1587
1588
1589
        
        name = com.__class__.__name__
        fget = lambda self: self.__get_command(name)
        
        setattr(self.__class__, name, property(fget))
        setattr(self, '__com_' + name, com)                   

1590
1591
1592
1593
1594
1595
    def __del_command(self, com):

        if not isinstance(com, Command):
            raise exceptions.ValueError("Argument is not of type Command")
        
        name = com.__class__.__name__
1596
        
1597
        print (getattr(self.__class__, name))
1598
        
1599
1600
1601
        delattr(self.__class__, name)
        delattr(self, '__com_' + name)
        
Daniel Brown's avatar
Daniel Brown committed
1602
1603
1604
1605
1606
1607
    def __get_command(self, name):
        return getattr(self, '__com_' + name)            
    
    def __add_component(self, comp):

        if not isinstance(comp, Component):
1608
            raise pkex.BasePyKatException("Argument is not of type Component")
Daniel Brown's avatar
Daniel Brown committed
1609
1610
1611
1612
1613
            
        fget = lambda self: self.__get_component(comp.name)
        
        setattr(self.__class__, comp.name, property(fget))
        setattr(self, '__comp_' + comp.name, comp)                   
1614
1615
        
    def __del_component(self, comp):
Daniel Brown's avatar
Daniel Brown committed
1616

1617
        if not isinstance(comp, Component):
1618
            raise pkex.BasePyKatException("Argument is not of type Component")
1619
1620
1621
1622
        
        delattr(self.__class__, comp.name)
        delattr(self, '__comp_' + comp.name)
        
Daniel Brown's avatar
Daniel Brown committed
1623
1624
1625
1626
    def __get_component(self, name):
        return getattr(self, '__comp_' + name)        

    def remove_comments(self, string):
1627
1628
1629
        """
        This takes a raw Finesse code string and removes any comments
        It returns a list of lines however, not a multiline string.
1630
        Also removes any extrawhite space in command lines.
1631
        """
Daniel Brown's avatar
Daniel Brown committed
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
        pattern = r"(\".*?\"|\'.*?\'|%{3}[^\r\n]*$)|(/\*.*?\*/|%[^\r\n]*$|#[^\r\n]*$|//[^\r\n]*$)"
        # first group captures quoted strings (double or single)
        # second group captures comments (//single-line or /* multi-line */)
        regex = re.compile(pattern, re.MULTILINE|re.DOTALL)
        def _replacer(match):
            # if the 2nd group (capturing comments) is not None,
            # it means we have captured a non-quoted (real) comment string.
            if match.group(2) is not None:
                return "" # so we will return empty to remove the comment
            else: # otherwise, we will return the 1st group
                return match.group(1) # captured quoted-string
1643
1644
1645
1646
1647
1648
1649
        
        # remove any inline comments
        string = regex.sub(_replacer, string)
        
        commands = []
        
        for line in string.split('\n'):
1650
1651
1652
1653
1654
1655
            line = line.replace('\r','')
            if len(line) > 0:
                # remove any mutliple whitespace
                line = " ".join(line.split())
                # add to a list all the positions of any inline comment markers
                i = [line.find('#'), line.find('\\')]
1656
1657
1658
                #i = filter(lambda a: a != -1, i)
                i = [a for a in i if a != -1]    

1659
1660
1661
1662
1663
1664
1665
1666
                if len(i) == 0:
                    commands.append(line)
                else:
                    line = line[0:min(i)]
                    if len(line):
                        commands.append(line)
        
        
1667
        return commands
1668
1669
1670

# printing pykat logo on first input
kat.logo()
For faster browsing, not all history is shown. View entire blame