# Read point sample data from disc file

 

import re, copy

 

def convert_data(s):

    for func in (int, float):

        try:

            n = func(s)

            return n

        except:

            pass

    return s

 

pattnum = re.compile(r'''

                      -\d+\.\d+E\+\d+|          # engineering notation -+

                      \d+\.\d+E\+\d+|           # engineering notation ++

                      -\d+\.\d+E-\d+|           # engineering notation --

                      \d+\.\d+E-\d+|            # engineering notation +-

                      -\d+\.\d+|                # negative float format

                      \d+\.\d+|                 # positive float format

                      -\d+\.|                   # negative float format

                      \d+\.|                    # positive float format

                      -\.\d+|                   # negative float format

                      \.\d+|                    # positive float format

                      \d{1,8}                   # positive integer

                      ''', re.X

                     )

 

pattinvalid = re.compile(r'''

                          \d+\.\d+\+\d+|           # invalid eng notation +

                          \d+\.\d+-\d+             # invalid eng notation -

                          ''', re.X

                         )                         

 

def parseData(fn, *kargs):

    fileList = [item.strip() for item in open(fn).readlines()\

                if not item.startswith('$')]

     

    pattkey = re.compile('|'.join([r'\b(%s)' % item for item in kargs]))

 

    # create dictionary with keys from kargs

    masterDict = dict(zip(kargs, [[] for _ in kargs]))

    inData = False

    for line in fileList:

 

        # check for invalid data

        if pattinvalid.search(line):

            for item in pattinvalid.findall(line):

                line = line.replace(item, item.replace('-', 'E-').replace('+', 'E+'))

       

        if inData and line.startswith('*'):

            data.extend(re.findall(pattnum, line))

        elif inData and not line.startswith('*'):

            masterDict[m.group(0)].append([convert_data(item)\

                                           for item in data])

            inData = False

            m = pattkey.match(line)

            if m:

                # m.group(0) is the current keyword

                if '*' in line:

                    inData = True

                    data = re.findall(pattnum, line)

                else:

                    data = re.findall(pattnum, line)

                    masterDict[m.group(0)].append([convert_data(item)\

                                                   for item in data])

        else:

            m = pattkey.match(line)

            if m:

                # m.group(0) is the current keyword

                if '*' in line:

                    inData = True

                    data = re.findall(pattnum, line)

                else:

                    data = re.findall(pattnum, line)

                    masterDict[m.group(0)].append([convert_data(item)\

                                                   for item in data])

    return masterDict

 

def replaceID(dataDict, idDict, *args):

    dd = copy.deepcopy(dataDict)

    for keyword in args:

        if keyword in dd:

            for item in dd[keyword]:

                if item[0] in idDict:

                    item[0] = idDict[item[0]]

    return dd

 

def replaceID1(dataDict, idDict, *args):

    for keyword in args:

        if keyword in dataDict:

            for item in dataDict[keyword]:

                if item[0] in idDict:

                    item[0] = idDict[item[0]]

    return dataDict

 

def replaceID2(fileList, idDict, *args):

    pattkey = re.compile('|'.join([r'\b(%s)' % item for item in args]))

    for i, line in enumerate(fileList):

        m = pattkey.match(line)

        if m:

            try:

                mnum = pattnum.search(line)

                id = int(mnum.group(0))

                if id in idDict:

                    s = str(idDict[id])

                    fileList[i] = '%s%s%s' % (line[:mnum.start()], s, \

                                              line[mnum.start()+len(s):])

            except:

                print 'No valid ID number found.'

    return fileList           

 

if __name__ == '__main__':

    fn = 'H:\\TEMP\\temsys\\sample_points9.txt'

    keywords =  ['Point', 'Othr', 'Oth1', 'Rect', 'PRect', 'PLine', 'Line', 'Tria']  

    dd = parseData(fn, *keywords)

    for key in dd:

        print key

        for item in dd[key]:

            print '    %s' % item

 

    fn = 'H:\\TEMP\\temsys\\sample_points9.txt'

    pointID = {1:86010101,2:86010102,3:86010103,4:86010104,\

               5:86010106,6:96010104,7:86010110,8:86010201,\

               9:86010115,3280504:96010403}

    curveID = {1:10001101,2:10001102,3:10001103,4:10001104,\

               6:10001106}

    fileList = open(fn).readlines()

    replaceID2(fileList, curveID, *['Line', 'Rect', 'Tria'])

    replaceID2(fileList, pointID, *['Point',])

    f = open('H:\\TEMP\\temsys\\sample_points99.txt', 'w')

    f.write(''.join(fileList))

    f.close()

 

    print

    dd = parseData('H:\\TEMP\\temsys\\sample_points99.txt', *keywords)

    for key in dd:

        print key

        for item in dd[key]:

            print '    %s' % item   

 

    '''

    idDict = dict(zip(range(1,11), range(80000001, 80000011)))

    dd1 = replaceID(dd, idDict, *['Line', 'Rect'])

    print

    for key in dd1:

        print key

        for item in dd1[key]:

            print '    %s' % item

 

    idDict = dict(zip(range(1,11), range(90000001, 90000011)))

    dd2 = replaceID(dd, idDict, *['Point',])

    print

    for key in dd2:

        print key

        for item in dd2[key]:

            print '    %s' % item

 

    idDict1 = dict(zip(range(1,11), range(60000001, 60000023, 2)))

    idDict2 = dict(zip(range(1,11), range(60000002, 60000024, 2)))

    dd3 = replaceID(replaceID(dd, idDict2, *['Line', 'Rect']), idDict1, *['Point',])

    print

    for key in dd3:

        print key

        for item in dd3[key]:

            print '    %s' % item           

 

    idDict3 = dict(zip(range(60000001, 60000023, 2), range(101,111)))

    replaceID1(dd3, idDict3, *['Point',])

    print

    for key in dd3:

        print key

        for item in dd3[key]:

            print '    %s' % item

    '''

 

    '''   

    def pad_str(s, fw):

        return ''.join([s, ' '*(fw-len(s))])       

 

    pointID = {1:86010101,2:86010102,3:86010103,4:86010104,5:86010106,6:96010104,7:86010110,8:86010201,9:86010115,3280504:96010403}

    curveID = {1:10001101,2:10001102,3:10001103,4:10001104,6:10001106}

    fn = 'H:\\TEMP\\temsys\\data_new_IDs.txt'

    replaceID1(dd, pointID, *['Point',])

    outputList = []

    f = open(fn, 'w')

    for key in dd:

        outputList.append('\n'.join(['%-8s' % key + ''.join([pad_str('%8s' % str(item),[8, 16][key in ['Othr','Oth1','Line']]) \

                                                              for item in itemList]) for itemList in dd[key]]))   

    f.write('\n'.join(outputList))

    f.close()

    '''

   

    # Point: 'Point'

    # Curves: 'Line','Rect','Tria'

    # Others: 'Othr','Oth1'

    # Attributes: 'Pline','Prect'

 

''' Output

>>> Point

    [1, 0.0, 0.0, 0.0]

    [2, 1.0, 0.0, 0.0]

    [3, 2.0, 0.0, 0.0]

    [4, -3.0, 0.0, 0.0]

    [5, 0.0, 1.0, 0.0]

    [6, 1.0, 1.0, 0.0]

    [7, 2.0, 1.0, 0.0]

    [8, 4.0, 1.0, 0.0]

    [9, 0.0, -2.0, 0.0]

    [3280504, 0, 1282.8614500000001, 1282.8614500000001, -201.004501]

    [3280606, 0, 0.0069264000650000003, -1282.8614500000001, -10100.4501, -0.014385767359999999]

PLine

    [1, 6, 1.5, 9.375, 0.001, -0.001]

Tria

    [5, 1, 7, 2, 11]

PRect

    [4, 11, 15, 16, 10, 11, 0.29999999999999999]

Line

    [1, 1, 1, 2, 0.0029520000000000002, 0.99254699999999996, 0.121827]

Rect

    [2, 1, 2, 3, 7, 6]

    [3, 1, 3, 4, 8, 7]

    [4, 1, 5, 6, 10, 11, 0.0]

Othr

    [1, 1, 5, 6, 10, 11, 0.0, 0.0, 10, 11, 0.0, 1.0]

>>>

'''

 

''' Data File Contents

$$$$$

START

COLOR RED

LINETYPE SOLID

END

$$$$$$$

PLine    1        6      1.5     9.375   .001   -.001

$ Line Details

Line*    1               1                1              2

*        .002952         .992547         .121827

$

Rect     2        1       2       3       7       6

Rect     3        1       3       4       8       7

PRect*   4               11              15              16

*        10              11              0.3

Rect*    4               1               5               6

*        10              11              0.

Othr*    1               1               5               6

*        10              11              0.              0.

*        10              11              0.              1.0

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

Tria     5        1       7       2       11

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

Point    1               0.0     0.0     0.0

Point    2               1.0     0.0     0.0

Point    3               2.0     0.0     0.0

Point    4              -3.0     0.0     0.0

Point    5               0.0     1.0     0.0

Point    6               1.0     1.0     0.0

Point    7               2.0     1.0     0.0

Point    8               4.0     1.0     0.0

Point*   9                               0.0            -2.0

*          0.0

Point  *3280504         0               1.28286145E+03  1.28286145+03

*       -2.01004501E+02

#

Point  *3280606         0               6.926400065-03  -1.28286145+03

*       -1.01004501+04  -1.438576736-02

$

END

'''