diff --git a/compact/ce_ecal_crystal_glass.xml b/compact/ce_ecal_crystal_glass.xml
index 19156a0df841163a4bee35a1026641b73f62c195..45915ca42581036c8e3c14d4665893e4f5981a33 100644
--- a/compact/ce_ecal_crystal_glass.xml
+++ b/compact/ce_ecal_crystal_glass.xml
@@ -1,13 +1,13 @@
 <lccdd>
   <define>
-    <constant name="CrystalModule_sx" value="20.0*mm"/>
-    <constant name="CrystalModule_sy" value="20.0*mm"/>
-    <constant name="CrystalModule_sz" value="20.0*cm"/>
-    <constant name="CrystalModule_wrap" value="0.5*mm"/>
-    <constant name="GlassModule_sx" value="40.0*mm"/>
-    <constant name="GlassModule_sy" value="40.0*mm"/>
-    <constant name="GlassModule_sz" value="40.0*cm"/>
-    <constant name="GlassModule_wrap" value="1.0*mm"/>
+    <constant name="CrystalModule_sx" value="20.00*mm"/>
+    <constant name="CrystalModule_sy" value="20.00*mm"/>
+    <constant name="CrystalModule_sz" value="200.00*mm"/>
+    <constant name="CrystalModule_wrap" value="0.50*mm"/>
+    <constant name="GlassModule_sx" value="40.00*mm"/>
+    <constant name="GlassModule_sy" value="40.00*mm"/>
+    <constant name="GlassModule_sz" value="400.00*mm"/>
+    <constant name="GlassModule_wrap" value="1.00*mm"/>
     <constant name="CrystalModule_z0" value="10.*cm"/>
     <constant name="GlassModule_z0" value="0.0*cm"/>
     <constant name="EcalEndcapN_z0" value="-EcalEndcapN_zmin-max(CrystalModule_sz,GlassModule_sz)/2."/>
diff --git a/scripts/ce_ecal_placement.py b/scripts/ce_ecal_placement.py
index 83c1d20d7b11e354e8b9eab21cd99515ee86fd36..b06f2ee472dc64bee5e1351559fd0a1f925c90fb 100644
--- a/scripts/ce_ecal_placement.py
+++ b/scripts/ce_ecal_placement.py
@@ -5,31 +5,18 @@
     Date: 06/17/2021
 '''
 
+import os
 import numpy as np
 import argparse
+import DDG4
 from lxml import etree as ET
+from matplotlib import pyplot as plt
+from matplotlib.collections import PatchCollection
+from matplotlib.patches import Rectangle, Circle
 
 
-# constants: name, value
-CONSTANTS = [
-    ('CrystalModule_sx', '20.0*mm'),
-    ('CrystalModule_sy', '20.0*mm'),
-    ('CrystalModule_sz', '20.0*cm'),
-    ('CrystalModule_wrap', '0.5*mm'),
-    ('GlassModule_sx', '40.0*mm'),
-    ('GlassModule_sy', '40.0*mm'),
-    ('GlassModule_sz', '40.0*cm'),
-    ('GlassModule_wrap', '1.0*mm'),
-    ('CrystalModule_z0', '10.*cm'),
-    ('GlassModule_z0', '0.0*cm'),
-    ('EcalEndcapN_z0', '-EcalEndcapN_zmin-max(CrystalModule_sz,GlassModule_sz)/2.'),
-    ('CrystalModule_dx', 'CrystalModule_sx + CrystalModule_wrap'),
-    ('CrystalModule_dy', 'CrystalModule_sy + CrystalModule_wrap'),
-    ('GlassModule_dx', 'GlassModule_sx + GlassModule_wrap'),
-    ('GlassModule_dy', 'GlassModule_sy + GlassModule_wrap'),
-]
-
-# line-by-line alignment start pos, total number of blocks
+CRYSTAL_SIZE = (20., 20., 200.) # mm
+CRYSTAL_GAP = 0.5 # mm
 CRYSTAL_ALIGNMENT = [
     (7, 17), (7, 17), (7, 17), (6, 18),
     (6, 18), (5, 19), (3, 19), (0, 22),
@@ -39,6 +26,8 @@ CRYSTAL_ALIGNMENT = [
     (0, 12), (0, 12), (0, 6),  (0, 6),
 ]
 
+GLASS_SIZE = (40., 40., 400.) # mm
+GLASS_GAP = 1.0 # mm
 GLASS_ALIGNMENT = [
     (12, 11), (12, 11), (12, 11), (11, 12),
     (11, 12), (11, 12), (10, 12), (9, 13),
@@ -49,11 +38,11 @@ GLASS_ALIGNMENT = [
 ]
 
 # calculate positions of modules with a quad-alignment and module size
-def individual_placement(alignment, module_x=20.5, module_y=20.5):
+def individual_placement(alignment, module_x, module_y, gap=0.):
     placements = []
     for row, (start, num) in enumerate(alignment):
         for col in np.arange(start, start + num):
-            placements.append(((col + 0.5)*module_y, (row + 0.5)*module_x))
+            placements.append(((col + 0.5)*(module_y + gap), (row + 0.5)*(module_x + gap)))
     placements = np.asarray(placements)
     return np.vstack((placements,
             np.vstack((placements.T[0]*-1., placements.T[1])).T,
@@ -61,11 +50,50 @@ def individual_placement(alignment, module_x=20.5, module_y=20.5):
             np.vstack((placements.T[0]*-1., placements.T[1]*-1.)).T))
 
 
+def draw_placement(axis, colors=('teal'), module_alignment=((CRYSTAL_SIZE, CRYSTAL_GAP, CRYSTAL_ALIGNMENT))):
+    xmin, ymin, xmax, ymax = 0., 0., 0., 0.
+    for color, (mod_size, mod_gap, alignment) in zip(colors, module_alignment):
+        placements = individual_placement(alignment, *mod_size[:2], mod_gap)
+        boxes = [Rectangle((x - (mod_size[0] + mod_gap)/2., y - (mod_size[1] + mod_gap)/2.), mod_size[0], mod_size[1])
+                 for x, y in placements]
+        pc = PatchCollection(boxes, facecolor=color, alpha=0.5, edgecolor='k')
+
+        xmin = min(xmin, placements.T[0].min() - 3.*(mod_size[0] + mod_gap))
+        ymin = min(ymin, placements.T[1].min() - 3.*(mod_size[1] + mod_gap))
+        xmax = max(xmax, placements.T[0].max() + 3.*(mod_size[0] + mod_gap))
+        ymax = max(ymax, placements.T[1].max() + 3.*(mod_size[1] + mod_gap))
+
+        # Add collection to axes
+        axis.add_collection(pc)
+    axis.set_xlim(xmin, xmax)
+    axis.set_ylim(ymin, ymax)
+    return axis
+
+
+def compact_constants(path, names):
+    if not os.path.exists(path):
+        print('Cannot find compact file \"{}\".'.format(path))
+        return []
+    kernel = DDG4.Kernel()
+    description = kernel.detectorDescription()
+    kernel.loadGeometry("file:{}".format(path))
+    try:
+        vals = [description.constantAsDouble(n) for n in names]
+    except:
+        print('Fail to extract values from {}, return empty.'.format(names))
+        vals = []
+    kernel.terminate()
+    return vals
+
 
 if __name__ == '__main__':
     parser = argparse.ArgumentParser()
     parser.add_argument('-s', '--save', default='compact/ce_ecal_crystal_glass.xml',
             help='path to save compact file.')
+    parser.add_argument('-c', '--compact', default='',
+            help='compact file to get contant to plot')
+    parser.add_argument('--radii-constants', dest='radii', default='EcalBarrel_rmin',
+            help='constant names in compact file to plot, seprate by \",\"')
     parser.add_argument('--individual', dest='indiv', action='store_true',
             help='individual block placements instead of line placements')
     args = parser.parse_args()
@@ -73,6 +101,29 @@ if __name__ == '__main__':
     data = ET.Element('lccdd')
     defines = ET.SubElement(data, 'define')
 
+    # constants: name, value
+    CONSTANTS = [
+        ('CrystalModule_sx', '{:.2f}*mm'.format(CRYSTAL_SIZE[0])),
+        ('CrystalModule_sy', '{:.2f}*mm'.format(CRYSTAL_SIZE[1])),
+        ('CrystalModule_sz', '{:.2f}*mm'.format(CRYSTAL_SIZE[2])),
+        ('CrystalModule_wrap', '{:.2f}*mm'.format(CRYSTAL_GAP)),
+
+        ('GlassModule_sx', '{:.2f}*mm'.format(GLASS_SIZE[0])),
+        ('GlassModule_sy', '{:.2f}*mm'.format(GLASS_SIZE[1])),
+        ('GlassModule_sz', '{:.2f}*mm'.format(GLASS_SIZE[2])),
+        ('GlassModule_wrap', '{:.2f}*mm'.format(GLASS_GAP)),
+
+        ('CrystalModule_z0', '10.*cm'),
+        ('GlassModule_z0', '0.0*cm'),
+        ('EcalEndcapN_z0', '-EcalEndcapN_zmin-max(CrystalModule_sz,GlassModule_sz)/2.'),
+
+        ('CrystalModule_dx', 'CrystalModule_sx + CrystalModule_wrap'),
+        ('CrystalModule_dy', 'CrystalModule_sy + CrystalModule_wrap'),
+        ('GlassModule_dx', 'GlassModule_sx + GlassModule_wrap'),
+        ('GlassModule_dy', 'GlassModule_sy + GlassModule_wrap'),
+    ]
+
+# line-by-line alignment start pos, total number of blocks
     for name, value in CONSTANTS:
         constant = ET.SubElement(defines, 'constant')
         constant.set('name', name)
@@ -121,7 +172,7 @@ if __name__ == '__main__':
     crystal_wrap.set('vis', 'WhiteVis')
     # crystal placements (for individuals)
     if args.indiv:
-        for m, (x, y) in enumerate(individual_placement(CRYSTAL_ALIGNMENT)):
+        for m, (x, y) in enumerate(individual_placement(CRYSTAL_ALIGNMENT, *CRYSTAL_SIZE[:2], CRYSTAL_GAP)):
             module = ET.SubElement(crystal, 'placement')
             module.set('x', '{:.3f}*mm'.format(x))
             module.set('y', '{:.3f}*mm'.format(y))
@@ -157,7 +208,7 @@ if __name__ == '__main__':
     glass_wrap.set('vis', 'WhiteVis')
     # crystal placements (for individuals)
     if args.indiv:
-        for m, (x, y) in enumerate(individual_placement(GLASS_ALIGNMENT, 41.0, 41.0)):
+        for m, (x, y) in enumerate(individual_placement(GLASS_ALIGNMENT, *GLASS_SIZE[:2], GLASS_GAP)):
             module = ET.SubElement(glass, 'placement')
             module.set('x', '{:.3f}*mm'.format(x))
             module.set('y', '{:.3f}*mm'.format(y))
@@ -208,3 +259,21 @@ if __name__ == '__main__':
     with open(args.save, 'wb') as f:
         f.write(text)
 
+
+    fig, ax = plt.subplots(figsize=(12, 12), dpi=160)
+    ax = draw_placement(ax, ['teal', 'royalblue'], [(CRYSTAL_SIZE, CRYSTAL_GAP, CRYSTAL_ALIGNMENT),
+                                                    (GLASS_SIZE, GLASS_GAP, GLASS_ALIGNMENT)])
+    ax.set_xlabel('x (mm)', fontsize=24)
+    ax.set_ylabel('y (mm)', fontsize=24)
+    ax.tick_params(direction='in', labelsize=22, which='both')
+    ax.set_axisbelow(True)
+    ax.grid(linestyle=':', which='both')
+
+    if args.compact and args.radii:
+        names = [c.strip() for c in args.radii.split(',')]
+        radii = compact_constants(args.compact, names)
+        for name, radius in zip(names, radii):
+            ax.add_patch(Circle((0, 0), radius*10., facecolor='none', edgecolor='k', linewidth=2))
+            ax.annotate(name, xy=(radius*10/1.4, radius*10/1.4), fontsize=22)
+    fig.savefig('ce_ecal_placement.png')
+