#! /usr/bin/python

################################################################################
# Python script to generate OT Quarters geometry & structure
# Author: Jan Amoraal
################################################################################

# Some globals
author            = 'Jan Amoraal'
version           = '1.0'
otGeomPath        = '/dd/Geometry/AfterMagnetRegion/T/OT'
otStructPath      = '/dd/Structure/LHCb/AfterMagnetRegion/T/OT'
otChannelCondPath = '/dd/Conditions/ChannelInfo/OT'
otCalCondPath     = '/dd/Conditions/Calibration/OT'

# XML version and encoding
indent  = 3*' '
version  = '"1.0"'
encoding = '"ISO-8859-1"'
header   = '<?xml version=%s encoding=%s?>\n'%( version, encoding )
doctype  = '<!DOCTYPE DDDB SYSTEM "conddb:/DTD/geometry.dtd">\n' 
header   = header + doctype + '\n<DDDB>\n\n'
footer   = '</DDDB>\n'

# Station, Layers, and Quarters 
stations = [ 'T1', 'T2', 'T3' ]
layers   = [ 'X1', 'U', 'V', 'X2' ]
quarters = [ 'Q0', 'Q1', 'Q2', 'Q3' ] # (0,2) is C-Side and (1,3) is A-Side
# Modules 1 to 8 have 64 straws per monolayer
# Module 9 has either 64 or 32 per monolayer 
# depending on whether it's A- or C-side
qProperties = { 'Q0' : [ 'lvS3Module', '32' ], 
                'Q1' : [ 'lvS2Module', '64' ], 
                'Q2' : [ 'lvS3Module', '32' ], 
                'Q3' : [ 'lvS2Module', '64' ] }

# Stereo angle -> 0, 5, -5, 0
stereo   = [ 'X1StereoAngle', 'UStereoAngle' , 'VStereoAngle', 'X2StereoAngle' ]

# lv Module names
# Start with module 9 inner most module
lvModulesTopCSide    = [ 'lvS3Module', 'lvS1Module' ] + [ 'lvLModule' for i in range( 7 ) ]
lvModulesBottomCSide = [ 'lvS3Module', 'lvS1Module' ] + [ 'lvLModule' for i in range( 7 ) ]
lvModulesTopASide    = [ 'lvS2Module', 'lvS1Module' ] + [ 'lvLModule' for i in range( 7 ) ]
lvModulesBottomASide = [ 'lvS2Module', 'lvS1Module' ] + [ 'lvLModule' for i in range( 7 ) ]

# pv Module name
# Start with module 9 inner most module
modules = [ 'M' + str( 9 - i ) for i in range( 9 ) ]

# X Coordinates
# First C-Side
# Start with module 9 inner most module
xModulesCSide  = [ '( -0.5*S3ModXSize )' ]
xFModulesCSide = [ '( -0.5*S3ModXSize - S3ModXPitch - LModXPitch*' + str( float( i ) ) + ' )' for i in range( 8 ) ]
xModulesCSide  = xModulesCSide + xFModulesCSide

# Now A-Side
# NOTE: The pitch is the same for all modules in A-Side. Same Width.
xFModulesASide       = [ '( 0.5*LModXSize + LModXPitch*'+ str( float( i ) ) +' )' for i in range( 9 ) ]
xModulesASide        = xFModulesASide 

# Y Coordinates
yModulesTop    = [ '0.5*S2ModYSize + (0.5*LModYSize - S2ModYSize)' , '0.5*S1ModYSize + (0.5*LModYSize - S1ModYSize)'  ] + [ '0.25*LModYSize' for i in range( 7 ) ]
yModulesBottom = [ '-0.5*S2ModYSize - (0.5*LModYSize - S2ModYSize)', '-0.5*S1ModYSize - (0.5*LModYSize - S1ModYSize)'  ] + [ '-0.25*LModYSize' for i in range( 7 ) ]

def QuarterGeometryTemplate( buffer, indent ) :
    # Module properties -> moduleID : [ lv, pv, nStraws ]
    modProperties = { '9' : [ 'lvLModule'  , '&pvM1;', '&yMod1;', '&xMod1;' ],
                      '8' : [ 'lvLModule'  , '&pvM2;', '&yMod2;', '&xMod2;' ],
                      '7' : [ 'lvLModule'  , '&pvM3;', '&yMod3;', '&xMod3;' ],
                      '6' : [ 'lvLModule'  , '&pvM4;', '&yMod4;', '&xMod4;' ],
                      '5' : [ 'lvLModule'  , '&pvM5;', '&yMod5;', '&xMod5;' ],
                      '4' : [ 'lvLModule'  , '&pvM6;', '&yMod6;', '&xMod6;' ],
                      '3' : [ 'lvLModule'  , '&pvM7;', '&yMod7;', '&xMod7;' ], 
                      '2' : [ 'lvS1Module' , '&pvM8;', '&yMod8;', '&xMod8;' ],
                      '1' : [ '&lvSModule;', '&pvM9;', '&yMod9;', '&xMod9;' ] }
    lvpath = otGeomPath + '/Modules/'
    buffer.write( '<?xml version=%s encoding=%s?>\n\n'%( version, encoding ) )
    buffer.write( indent + '<logvol name="lv&Station;&Layer;&Quarter;">\n' )
    # There are 9 modules per Quarter
    for m in range( 9 ) :
        buffer.write( indent + '  <physvol name="%s"\n'%( modProperties[ str( m + 1 ) ][ 1 ] ) )
        buffer.write( indent + '           logvol="%s">\n'%( lvpath + modProperties[ str( m + 1 ) ][ 0 ] ) )
        # Now we apply the transformation
        buffer.write( indent + '    <transformation>\n')
        # Rememeber though that the tags must be in the order pos rot
        # the transformation is the reverse, first the rotation then 
        # translation
        buffer.write( indent + '      <posXYZ y="%s" />\n'%( modProperties[ str( m + 1 ) ][ 2 ] ) )
        buffer.write( indent + '      <rotXYZ />\n' )
        buffer.write( indent + '      <posXYZ />\n' )
        buffer.write( indent + '      <posXYZ />\n' )
        buffer.write( indent + '      <rotXYZ rotZ="&StereoAngle;" />\n' )
        buffer.write( indent + '      <posXYZ />\n' )
        buffer.write( indent + '      <posXYZ x="%s/cos(&StereoAngle;)" />\n'%( modProperties[ str( m + 1 ) ][ 3 ] ) )
        buffer.write( indent + '      <rotXYZ />\n' )
        buffer.write( indent + '      <posXYZ />\n' )
        buffer.write( indent + '    </transformation>\n' )
        buffer.write( indent + '  </physvol>\n' )
    buffer.write( indent + '</logvol>\n' )
    buffer.write( '\n' )
    
def QuarterStructureTemplate( buffer, indent ) :
    # Module properties -> moduleID : [ lv, pv, nStraws ]
    modProperties = { '1' : [ 'lvLModule'    , '&pvM1;' , '64' ],
                      '2' : [ 'lvLModule'    , '&pvM2;' , '64' ],
                      '3' : [ 'lvLModule'    , '&pvM3;' , '64' ],
                      '4' : [ 'lvLModule'    , '&pvM4;' , '64' ],
                      '5' : [ 'lvLModule'    , '&pvM5;' , '64' ],
                      '6' : [ 'lvLModule'    , '&pvM6;' , '64' ],
                      '7' : [ 'lvLModule'    , '&pvM7;' , '64' ], 
                      '8' : [ 'lvS1Module'   , '&pvM8;' , '64' ],
                      '9' : [ '&lvSModule;'  , '&pvM9;' , '&SModuleNStraws;' ] }
    # %s is a python string substitute
    # &foo; are xml 'place holders'
    buffer.write( '<?xml version=%s encoding=%s?>\n\n'%( version, encoding ) )
    buffer.write( '<detelem classID="8104" name="&Quarter;">\n' )
    buffer.write( '  <author>%s</author>\n'%( author ) )
    buffer.write( '  <version>%s</version>\n'%( '1.0' ) )
    buffer.write( '  <geometryinfo lvname    = "%s/&Station;/&Station;&Layer;/&Station;&Layer;Quarters/lv&Station;&Layer;&Quarter;"\n'%( otGeomPath ) )
    buffer.write( '                condition = "/dd/Conditions/Alignment/OT/&Station;&Layer;&Quarter;"\n' )
    buffer.write( '                support   = "%s/&Station;/&Layer;"\n'%( otStructPath ) )
    buffer.write( '                npath     = "pv&Station;&Layer;&Quarter;" />\n' )
    buffer.write( '  <param name = "quarterID" type = "int">&QuarterID;</param>\n' )
    for m in range( 9 ) :
        buffer.write( '\n' )
        buffer.write( indent + '<detelem classID = "8105" name = "M%s">\n'%( str( m + 1 ) ) )
        buffer.write( indent + '  <author>%s</author>\n'%( author ) )
        buffer.write( indent + '  <version>%s</version>\n'%( version ) )
        # Long modules have different lv volumes from short modules 
        buffer.write( indent + '  <geometryinfo lvname    = "%s/Modules/%s"\n'%( otGeomPath, modProperties[ str( m + 1 ) ][0] ) )
        buffer.write( indent + '                condition = "/dd/Conditions/Alignment/OT/&Station;&Layer;&Quarter;M%s"\n'%( str( m + 1 ) ) )
        buffer.write( indent + '                support   = "%s/&Station;/&Layer;/&Quarter;"\n'%( otStructPath ) )
        buffer.write( indent + '                npath     = "%s" />\n'%( modProperties[ str( m + 1 ) ][ 1 ] ) )
        buffer.write( indent + '  <param name = "moduleID" type = "int">%s</param>\n'%( str( m + 1 ) ) )
        buffer.write( indent + '  <param name = "nStraws"  type = "int">%s</param>\n'%( modProperties[ str( m + 1 ) ][ 2 ] ) )
        calibration = '%s/CalibrationModules&Station;&Layer;&Quarter;/&Station;&Layer;&Quarter;M%s'%( otCalCondPath, str( m + 1 ) )
        readout     = '%s/ReadoutModules&Station;&Layer;&Quarter;/&Station;&Layer;&Quarter;M%s'%( otChannelCondPath, str( m + 1 ) )
        buffer.write( indent + '  <conditioninfo name = "Calibration" condition="%s" />\n'%( calibration ) )
        buffer.write( indent + '  <conditioninfo name = "Status"      condition="%s" />\n'%( readout ) )
        buffer.write( indent + '</detelem>\n' )
    buffer.write( '\n</detelem>\n' )

# Now let's write the geometry
import cStringIO, os
# Create dirs
quartersdir = 'Quarters'
geometrydir = 'Geometry'
try :
    os.mkdir( quartersdir )
    os.chdir( quartersdir )                     
except OSError :
    print quartersdir + ' Directory exits'
    os.chdir( quartersdir )

# First the templates
# Geometry template
geometryTemplate = cStringIO.StringIO()
QuarterGeometryTemplate( geometryTemplate, indent )
contents = geometryTemplate.getvalue()
geometryTemplate.close()
output = file( 'QuarterGeometryTemplate.xml', 'w' )
output.write( contents )
output.close()
# Structure template
structureTemplate = cStringIO.StringIO()
QuarterStructureTemplate( structureTemplate, indent )
contents = structureTemplate.getvalue()
structureTemplate.close()
output = file( 'QuarterStructureTemplate.xml', 'w' )
output.write( contents )
output.close()

# Now the geometry catalog
geometryCatalog = cStringIO.StringIO()
geometryCatalog.write( header )
for s in stations :
    for l in layers :
        geometryCatalog.write( '   <catalog name="%s" >\n'%( s + l + 'Quarters' ) )
        for q in quarters :
            quarter = s + l + q 
            geometryCatalog.write( '      <logvolref href="%s" />\n'%( 'Geometry/' + quarter + '@Geometry.xml#lv' + quarter ) )
        geometryCatalog.write( '   </catalog>\n\n')
geometryCatalog.write( footer )
contents = geometryCatalog.getvalue()
geometryCatalog.close()
output = file( 'QuarterGeometryCatalogs.xml', 'w' )
output.write( contents )
output.close()

# Geometry
try :
    os.mkdir( geometrydir )
    os.chdir( geometrydir )                     
except OSError :
    print geometrydir + ' Directory exits'
    os.chdir( geometrydir )

# Start with inner most module
# Q3
T1XUQ3deltaY = [-0.500, -0.363, -0.225, -0.088, +0.050, +0.188, +0.325, +0.463, +0.600]
T1XUQ3deltaY.reverse()
T1VXQ3deltaY = [-1.300, -1.138, -0.975, -0.813, -0.650, -0.488, -0.325, -0.163, +0.000]
T1VXQ3deltaY.reverse()
T2XUQ3deltaY = [-0.500, -0.363, -0.225, -0.088, +0.050, +0.188, +0.325, +0.463, +0.600]
T2XUQ3deltaY.reverse()
T2VXQ3deltaY = [-1.700, -1.488, -1.275, -1.063, -0.850, -0.638, -0.425, -0.213, +0.000]
T2VXQ3deltaY.reverse()
T3XUQ3deltaY = [-2.000, -1.813, -1.625, -1.438, -1.250, -1.063, -0.875, -0.688, -0.500]
T3XUQ3deltaY.reverse()
T3VXQ3deltaY = [-1.800, -1.680, -1.550, -1.430, -1.300, -1.180, -1.100, -0.930, -0.800]
T3VXQ3deltaY.reverse()

# Q2
T1XUQ2deltaY = [+0.500, +0.393, +0.251, +0.110, -0.0330, -0.174, -0.316, -0.458, -0.600]
T1VXQ2deltaY = [-1.00, -1.100, -1.226, -1.355, -1.484, -1.613, -1.742, -1.871, -2.00]
T2XUQ2deltaY = [+0.000, -0.136, -0.317, -0.497, -0.700, -0.859, -1.040, -1.220, -1.4]
T2VXQ2deltaY = [-1.00, -1.136, -1.317, -1.497, -1.700, -1.858, -2.040, -2.220, -2.400]
T3XUQ2deltaY = [-0.5, -0.600, -0.730, -0.900, -1.00, -1.113, -1.242, -1.371, -1.500]
T3VXQ2deltaY = [-1.200, -1.300, -1.426, -1.600, -1.684, -1.813, -1.942, -2.071, -2.200]

M9Offsets = [ '(-7.0*mm)', '(0.0*mm)', '(+7.0*mm)' ]
for m, s in enumerate( stations ) :
    yM9Bottom = yModulesBottom[ 0 ] + ' - 1.0*' + M9Offsets[ m ] 
    yM9Top    = yModulesTop[ 0 ]    + ' + 1.0*' + M9Offsets[ m ]
    for n, l in enumerate( layers ) :
        for q in quarters :
            pv = 'pv'+ s + l + q
            pvModules = []
            xModules  = []
            yModules  = []
            if q == 'Q0' or q == 'Q2' :
                pvModules = [ pv + i for i in modules ]
                xModules  = xModulesCSide
            elif q == 'Q1' or q == 'Q3' :
                pvModules = [ pv + i for i in modules ]
                xModules  = xModulesASide
            if q == 'Q0' or q == 'Q1' :
                yModules = [yM9Bottom] + yModulesBottom[1:]
                yS1Coupling = '-0.5*(0.5*LModYSize - S1ModYSize)'
            elif q == 'Q2' or q == 'Q3' :
                yModules = [yM9Top] + yModulesTop[1:]
                yS1Coupling = '+0.5*(0.5*LModYSize - S1ModYSize)'
#             if s == 'T1' and ( l == 'X1'or l == 'U') and ( q == 'Q0' or q == 'Q2' ) :
#                 yModules = [ i + '+ (' + str( j ) + '*mm)' for i,j in zip( yModules, T1XUQ2deltaY ) ]
#             if s == 'T2' and ( l == 'X1'or l == 'U') and ( q == 'Q0' or q == 'Q2' ) :
#                 yModules = [ i + '+ (' + str( j ) + '*mm)' for i,j in zip( yModules, T2XUQ2deltaY ) ]
#             if s == 'T3' and ( l == 'X1'or l == 'U') and ( q == 'Q0' or q == 'Q2' ) :
#                 yModules = [ i + '+ (' + str( j ) + '*mm)' for i,j in zip( yModules, T3XUQ2deltaY ) ]
#             if s == 'T1' and ( l == 'X2'or l == 'V') and ( q == 'Q0' or q == 'Q2' ) :
#                 yModules = [ i + '+ (' + str( j ) + '*mm)' for i,j in zip( yModules, T1VXQ2deltaY ) ]
#             if s == 'T2' and ( l == 'X2'or l == 'V') and ( q == 'Q0' or q == 'Q2' ) :
#                 yModules = [ i + '+ (' + str( j ) + '*mm)' for i,j in zip( yModules, T2VXQ2deltaY ) ]
#             if s == 'T3' and ( l == 'X2'or l == 'V') and ( q == 'Q0' or q == 'Q2' ) :
#                 yModules = [ i + '+ (' + str( j ) + '*mm)' for i,j in zip( yModules, T3VXQ2deltaY ) ]
            
#             if s == 'T1' and ( l == 'X1'or l == 'U') and ( q == 'Q1' or q == 'Q3' ) :
#                 yModules = [ i + '+ (' + str( j ) + '*mm)' for i,j in zip( yModules, T1XUQ3deltaY ) ]
#             if s == 'T2' and ( l == 'X1'or l == 'U') and ( q == 'Q1' or q == 'Q3' ) :
#                 yModules = [ i + '+ (' + str( j ) + '*mm)' for i,j in zip( yModules, T2XUQ3deltaY ) ]
#             if s == 'T3' and ( l == 'X1'or l == 'U') and ( q == 'Q1' or q == 'Q3' ) :
#                 yModules = [ i + '+ (' + str( j ) + '*mm)' for i,j in zip( yModules, T3XUQ3deltaY ) ]
#             if s == 'T1' and ( l == 'X2'or l == 'V') and ( q == 'Q1' or q == 'Q3' ) :
#                 yModules = [ i + '+ (' + str( j ) + '*mm)' for i,j in zip( yModules, T1VXQ3deltaY ) ]
#             if s == 'T2' and ( l == 'X2'or l == 'V') and ( q == 'Q1' or q == 'Q3' ) :
#                 yModules = [ i + '+ (' + str( j ) + '*mm)' for i,j in zip( yModules, T2VXQ3deltaY ) ]
#             if s == 'T3' and ( l == 'X2'or l == 'V') and ( q == 'Q1' or q == 'Q3' ) :
#                 yModules = [ i + '+ (' + str( j ) + '*mm)' for i,j in zip( yModules, T3VXQ3deltaY ) ]
            geometry = cStringIO.StringIO()
            geometry.write( '<!DOCTYPE DDDB SYSTEM "conddb:/DTD/geometry.dtd"\n' )
            geometry.write( ' [<!ENTITY Station         "%s">\n'%( s ) )
            geometry.write( '  <!ENTITY Layer           "%s">\n'%( l ) )
            geometry.write( '  <!ENTITY Quarter         "%s">\n'%( q ) )
            geometry.write( '  <!ENTITY StereoAngle     "%s">\n'%( stereo[ n ] ) )
            geometry.write( '  <!ENTITY pvM1            "%s">\n'%( pvModules[ 8 ] ) )
            geometry.write( '  <!ENTITY yMod1           "%s">\n'%( yModules[ 8 ]  ) )
            geometry.write( '  <!ENTITY xMod1           "%s">\n'%( xModules[ 8 ]  ) )
            geometry.write( '  <!ENTITY pvM2            "%s">\n'%( pvModules[ 7 ] ) )
            geometry.write( '  <!ENTITY yMod2           "%s">\n'%( yModules[ 7 ]  ) )
            geometry.write( '  <!ENTITY xMod2           "%s">\n'%( xModules[ 7 ]  ) )
            geometry.write( '  <!ENTITY pvM3            "%s">\n'%( pvModules[ 6 ] ) )
            geometry.write( '  <!ENTITY yMod3           "%s">\n'%( yModules[ 6 ]  ) )
            geometry.write( '  <!ENTITY xMod3           "%s">\n'%( xModules[ 6 ]  ) )
            geometry.write( '  <!ENTITY pvM4            "%s">\n'%( pvModules[ 5 ] ) )
            geometry.write( '  <!ENTITY yMod4           "%s">\n'%( yModules[ 5 ]  ) )
            geometry.write( '  <!ENTITY xMod4           "%s">\n'%( xModules[ 5 ]  ) )
            geometry.write( '  <!ENTITY pvM5            "%s">\n'%( pvModules[ 4 ] ) )
            geometry.write( '  <!ENTITY yMod5           "%s">\n'%( yModules[ 4 ]  ) )
            geometry.write( '  <!ENTITY xMod5           "%s">\n'%( xModules[ 4 ]  ) )
            geometry.write( '  <!ENTITY pvM6            "%s">\n'%( pvModules[ 3 ] ) )
            geometry.write( '  <!ENTITY yMod6           "%s">\n'%( yModules[ 3 ]  ) )
            geometry.write( '  <!ENTITY xMod6           "%s">\n'%( xModules[ 3 ]  ) )
            geometry.write( '  <!ENTITY pvM7            "%s">\n'%( pvModules[ 2 ] ) )
            geometry.write( '  <!ENTITY yMod7           "%s">\n'%( yModules[ 2 ]  ) )
            geometry.write( '  <!ENTITY xMod7           "%s">\n'%( xModules[ 2 ]  ) )
            geometry.write( '  <!ENTITY pvM8            "%s">\n'%( pvModules[ 1 ] ) )
            geometry.write( '  <!ENTITY yMod8           "%s">\n'%( yModules[ 1 ]  ) )
            geometry.write( '  <!ENTITY xMod8           "%s">\n'%( xModules[ 1 ]  ) )
            geometry.write( '  <!ENTITY pvM9            "%s">\n'%( pvModules[ 0 ] ) )
            geometry.write( '  <!ENTITY lvSModule       "%s">\n'%( qProperties[ q ][ 0 ] ) )
            geometry.write( '  <!ENTITY yMod9           "%s">\n'%( yModules[ 0 ]  ) )
            geometry.write( '  <!ENTITY xMod9           "%s">\n'%( xModules[ 0 ]  ) )
            geometry.write( '  <!ENTITY %s%s%sGeometry SYSTEM "../QuarterGeometryTemplate.xml">]>\n'%( s, l, q ) )
            geometry.write( '\n' )
            geometry.write( '<DDDB>\n' )
            geometry.write( '  &%s%s%sGeometry;\n'%( s, l, q ) )
            geometry.write( '</DDDB>\n' )
            contents = geometry.getvalue()
            geometry.close()
            fname = '%s%s%s@Geometry.xml'%( s, l, q )
            output = file( fname, 'w' )
            output.write( contents )
            output.close()

# # Now generate the accompanying structure
structdir = 'Structure'
try :
    os.chdir( '..' )
    os.mkdir( structdir )
    os.chdir( structdir )
except OSError :
    print structdir + ' Directory exits'
    os.chdir( structdir )

for s in stations :
    for l in layers :
        for q in quarters :
            pv = 'pv'+ s + l + q
            pvModules = []
            if q == 'Q0' or q == 'Q2' :
                pvModules = [ pv + i for i in modules ]
            elif q == 'Q1' or q == 'Q3' :
                pvModules = [ pv + i for i in modules ]
            structure = cStringIO.StringIO()
            structure.write( '<!DOCTYPE DDDB SYSTEM "conddb:/DTD/structure.dtd"\n' )
            structure.write( ' [<!ENTITY Station         "%s">\n'%( s ) )
            structure.write( '  <!ENTITY Layer           "%s">\n'%( l ) )
            structure.write( '  <!ENTITY Quarter         "%s">\n'%( q ) )
            structure.write( '  <!ENTITY QuarterID       "%s">\n'%( q[1] ) )
            structure.write( '  <!ENTITY pvM1            "%s">\n'%( pvModules[ 8 ] ) )
            structure.write( '  <!ENTITY pvM2            "%s">\n'%( pvModules[ 7 ] ) )
            structure.write( '  <!ENTITY pvM3            "%s">\n'%( pvModules[ 6 ] ) )
            structure.write( '  <!ENTITY pvM4            "%s">\n'%( pvModules[ 5 ] ) )
            structure.write( '  <!ENTITY pvM5            "%s">\n'%( pvModules[ 4 ] ) )
            structure.write( '  <!ENTITY pvM6            "%s">\n'%( pvModules[ 3 ] ) )
            structure.write( '  <!ENTITY pvM7            "%s">\n'%( pvModules[ 2 ] ) )
            structure.write( '  <!ENTITY pvM8            "%s">\n'%( pvModules[ 1 ] ) )
            structure.write( '  <!ENTITY pvM9            "%s">\n'%( pvModules[ 0 ] ) )
            structure.write( '  <!ENTITY lvSModule       "%s">\n'%( qProperties[ q ][ 0 ] ) )
            structure.write( '  <!ENTITY SModuleNStraws  "%s">\n'%( qProperties[ q ][ 1 ] ) )
            structure.write( '  <!ENTITY %s%s%sStructure SYSTEM "../QuarterStructureTemplate.xml">]>\n'%( s, l, q ) )
            structure.write( '\n' )
            structure.write( '<DDDB>\n' )
            structure.write( '  &%s%s%sStructure;\n'%( s, l, q ) )
            structure.write( '</DDDB>\n' )
            contents = structure.getvalue()
            structure.close()
            fname = '%s%s%s@Structure.xml'%( s, l, q )
            output = file( fname, 'w' )
            output.write( contents )
            output.close()
