From ece36ecbeddd0917e4327b6337435e1213e3c8cf Mon Sep 17 00:00:00 2001 From: mt82 Date: Mon, 20 Jan 2025 16:22:39 +0100 Subject: [PATCH] 18 implement detailed geometry for sand ecal endcaps (#40) * Implementation of detailed ECAL geometry * Wrong subbuilder name corrected * Corrected wrong Builder name * tab replaced with space at line 37 to avoid TabError: inconsistent use of tabs and spaces in indentation * alignment in config SAND_ECAL.cgf * just code alignment * aluminum palte put inside mother volume * ECAL ec module element construction moved to function * renaming ActiveMat to ScintMat, so that they have the same names in the SANDECALBARRELMOD and SANDECALENDCAP context * single values inherited from mother volume for several parameters * definition of a shape for ECAL endcap module * The endcap module volume now is filled with the ECAL active/passive layers * renaming of ec module volume name * number of barrel modules into config file * the whole endcap is now constructed and placed on both side of the barrel * Corrected Al_plate position. * Added dev option for the drift configuration. * Slab index starts at 0 at the outer radius. * Fixed horizontal section IDs and positioning * Updated but buggy geometry * Added develop configuration. * no overlaps; volume for yoke endcaps are removed from ecal endcap volumes. Size of yoke endcaps are decreased a bit * indentaion fixed * removed useless commented lines * tab removed, 4 spaces instead * removed useless comments * update of changelog --------- Co-authored-by: Paolo Gauzzi Co-authored-by: alrugger Co-authored-by: Alessandro Ruggeri <90973844+AlessandroRuggeri@users.noreply.github.com> --- CHANGELOG.md | 1 + duneggd/Component/SandECalBarrelMod.py | 46 +- duneggd/Component/SandECalEndcap.py | 874 ++++++++++++++++++++++--- duneggd/Config/SAND_ECAL.cfg | 34 +- duneggd/Config/SAND_MAGNET.cfg | 7 +- duneggd/SubDetector/SAND.py | 72 +- duneggd/SubDetector/SandECal.py | 163 +++-- setup.py | 2 +- 8 files changed, 995 insertions(+), 204 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f09c047..6af0274 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Geometry releases will be tagged as `Descriptive_tag_v_X.Y.Z`. - Bump gegede to version 0.8.0 - Define default geometries in Makefile instead of bash script +- Implementation of the C-shaped volumes of the SAND ECAL Endcaps ### Removed diff --git a/duneggd/Component/SandECalBarrelMod.py b/duneggd/Component/SandECalBarrelMod.py index b347340..cd8b0b9 100644 --- a/duneggd/Component/SandECalBarrelMod.py +++ b/duneggd/Component/SandECalBarrelMod.py @@ -9,44 +9,64 @@ class SandECalBarrelModBuilder(gegede.builder.Builder): #^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ def configure(self, - trapezoidDim=None, - ScintMat=None, - PasMat=None, - PasSlabThickness=None, - ActiveSlabThickness=None, - nSlabs=None, - **kwds): + trapezoidDim=None, + ScintMat=None, + PasMat=None, + PasSlabThickness=None, + ActiveSlabThickness=None, + nSlabs=None, + BackPlateThick=None, + **kwds): self.trapezoidDim = trapezoidDim self.ScintMat = ScintMat self.PasMat = PasMat self.PasSlabThickness = PasSlabThickness self.ActiveSlabThickness = ActiveSlabThickness self.nSlabs = nSlabs + self.BackPlateThick = BackPlateThick #^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ def construct(self, geom): + AlPlateThick = self.BackPlateThick + ECAL_shape = geom.shapes.Trapezoid('ECAL_shape', dx1=self.trapezoidDim[0], - dx2=self.trapezoidDim[1], + dx2=self.trapezoidDim[1]+Q('0.33cm'), dy1=self.trapezoidDim[2], dy2=self.trapezoidDim[2], - dz=self.trapezoidDim[3]) + dz=self.trapezoidDim[3]+AlPlateThick/2.) ECAL_lv = geom.structure.Volume('ECAL_lv', material='Air', shape=ECAL_shape) self.add_volume(ECAL_lv) -# ECAL_position = geom.structure.Position('ECAL_position', Position[0], Position[1], Position[2]) -# ECAL_place = geom.structure.Placement('ECAL_place', volume = ECAL_lv, pos=ECAL_position) + + ######## Aluminum back plate################## + + ECAL_Alplate_shape = geom.shapes.Box('ECAL_Alplate_shape', + dx = self.trapezoidDim[1], + dy = self.trapezoidDim[2], + dz = AlPlateThick/2.) + + ECAL_Alplate_lv = geom.structure.Volume('ECAL_Alplate_lv', material = 'Aluminum', + shape = ECAL_Alplate_shape) + + ECAL_Alplate_pos = geom.structure.Position('ECAL_Alplate_pos', Q('0cm'), Q('0cm'), + self.trapezoidDim[3]) + + ECAL_Alplate_place = geom.structure.Placement('ECAL_Alplate_place', + volume = ECAL_Alplate_lv, pos = ECAL_Alplate_pos) + + ECAL_lv.placements.append(ECAL_Alplate_place.name) for i in range(self.nSlabs): #nSlabs #tan = math.tan(math.pi/self.Segmentation) tan = 0.5*(self.trapezoidDim[1] - self.trapezoidDim[0])/self.trapezoidDim[3] xposSlab=Q('0cm') yposSlab=Q('0cm') - zposSlabActive = (-self.trapezoidDim[3] + + zposSlabActive = (-self.trapezoidDim[3]-AlPlateThick/2. + (i+0.5)*self.ActiveSlabThickness + i*self.PasSlabThickness) #print("active slab position= "+ str(zposSlabActive)) - zposSlabPassive = (-self.trapezoidDim[3] + + zposSlabPassive = (-self.trapezoidDim[3]-AlPlateThick/2. + (i+1.)*self.ActiveSlabThickness + (i+0.5)*self.PasSlabThickness) #print("passive slab position= "+ str(zposSlabPassive)) diff --git a/duneggd/Component/SandECalEndcap.py b/duneggd/Component/SandECalEndcap.py index 344b734..2707d39 100644 --- a/duneggd/Component/SandECalEndcap.py +++ b/duneggd/Component/SandECalEndcap.py @@ -7,99 +7,825 @@ class SandECalEndcapBuilder(gegede.builder.Builder): - #^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ - def configure(self, - EndcapSize=None, - ActiveMat=None, - PasMat=None, - PasSlabThickness=None, - ActiveSlabThickness=None, - nSlabs=None, - **kwds): - self.EndcapSize = EndcapSize - self.ActiveMat = ActiveMat + # ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ + def configure( + self, + EndcapDim=None, + EndcapModDim=None, + ScintMat=None, + PasMat=None, + PasSlabThickness=None, + ActiveSlabThickness=None, + nSlabs=None, + BackPlateThick=None, + **kwds + ): + self.EndcapDim = EndcapDim + self.EndcapModDim = EndcapModDim + self.ScintMat = ScintMat self.PasMat = PasMat self.PasSlabThickness = PasSlabThickness self.ActiveSlabThickness = ActiveSlabThickness self.nSlabs = nSlabs - #^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ + self.BackPlateThick = BackPlateThick + + ### Below values should be the same as the one in SANDBuilder + ### and will be used to construct subtraction boolean volume + ### to avoid overlap with yoke endcap elements (C,D) + + # part C is a TUBS, 2.15<|x|<2.58m, rmin=0.84m, rmax=1.34m + self.EndcapCZStart=Q("2.15m") + self.EndcapCZEnd=Q("2.58m") + self.EndcapCRmax=Q("1.34m") + self.EndcapCRmin=Q("0.84m") + + # part D is a TUBS, 1.96<|x|<2.15m, rmin=0.512m, rmax=1.73m + self.EndcapDZStart=Q("1.96m") + self.EndcapDZEnd=Q("2.15m") + + # Here we reduce the size of the D element of the yoke endcap + # to avoid overlap with the curved element of the ecal endcap module + self.EndcapDRmax=Q("1.66m") + self.EndcapDRmin=Q("0.62m") + + # ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ def construct(self, geom): + + rmax_ec = self.EndcapDim[0] + KLOEEndcapECALDepth = self.EndcapDim[2] + KLOEEndcapCurvRadius = self.EndcapDim[3] + KLOEEndcapStraight = self.EndcapDim[4] + KLOECellWidth = self.EndcapDim[5] + KLOEEndcapModDy = self.EndcapModDim + AlPlateThick = self.BackPlateThick + ColPerMod = 6 + XPosMod = -3 * KLOECellWidth + ECTubsSize = ( + KLOEEndcapECALDepth + KLOEEndcapCurvRadius + KLOEEndcapStraight + ) + + ##########creating main straight part of the ECAL endcap module########## + + ECAL_endcap_shape_base = geom.shapes.Tubs( + "ECAL_endcap_shape_base", rmin=Q("0m"), rmax=rmax_ec, dz=ECTubsSize / 2.0 + ) - KLOEEndcapECALRmin = self.EndcapSize[0] - KLOEEndcapECALRmax = self.EndcapSize[1] - KLOEEndcapECALDepth = self.EndcapSize[2] + # volume to be removed from MagIntVol_vol to make room for yoke endcap + yoke_endcap_shape = geom.shapes.Tubs("yoke_endcap_shape_ec", rmin=self.EndcapDRmin, rmax=self.EndcapDRmax, dz=0.5 * (self.EndcapCZEnd - self.EndcapDZStart)) - ECAL_end_shape = geom.shapes.Tubs('ECAL_end_shape', - rmin=Q('0m'), - rmax=KLOEEndcapECALRmax, - dz=KLOEEndcapECALDepth / 2.0) - - ECAL_end_lv = geom.structure.Volume('ECAL_end_lv', material='Air', shape=ECAL_end_shape) - self.add_volume(ECAL_end_lv) -# print(self.name) -# ECAL_position = geom.structure.Position('ECAL_position', Position[0], Position[1], Position[2]) -# ECAL_place = geom.structure.Placement('ECAL_place', volume = ECAL_lv, pos=ECAL_position) + yoke_ec_pos = geom.structure.Position("yoke_ec_pos_ec", Q('0m'), Q('0m'), 0.5 * (self.EndcapDZStart + self.EndcapCZEnd) - Q('1.955m')) + + ECAL_endcap_shape = geom.shapes.Boolean("ECAL_endcap_shape", + type='subtraction', + first=ECAL_endcap_shape_base, + second=yoke_endcap_shape, + pos=yoke_ec_pos) - for i in range(self.nSlabs): #nSlabs - - xposSlab=Q('0cm') - yposSlab=Q('0cm') - - zposSlabActive =( -KLOEEndcapECALDepth * 0.5 + - (i + 0.5) * self.ActiveSlabThickness + - i * self.PasSlabThickness ) - - zposSlabPassive = (zposSlabActive + - 0.5 * self.ActiveSlabThickness + - 0.5 * self.PasSlabThickness) - #print("BhalfPassive= "+ str(BhalfPassive)) - - ##########creating and appending active slabs to the ECAL endcap########## + ECAL_endcap_lv = geom.structure.Volume( + "ECAL_endcap_lv", material="Air", shape=ECAL_endcap_shape + ) + self.add_volume(ECAL_endcap_lv) + + ZPosMod = (-ECTubsSize + KLOEEndcapECALDepth) / 2.0 + + for mod in range(0, 16): + print(("Building ECAL Endcap Module " + str(mod))) + + # width of the module + if mod > 1 and mod < 12: + ColPerMod = 3 + elif mod > 11: + ColPerMod = 2 + + # y position of the module + if mod < 2: + YPosMod = Q("111.35cm") + else: + YPosMod = Q("0cm") + + # x position of the module + if mod == 2: + XPosMod += KLOECellWidth * 4.5 + elif mod == 12: + XPosMod += KLOECellWidth * 2.5 + elif mod > 0: + XPosMod += KLOECellWidth * ColPerMod + + ############################################################################### + ########## creating the volume of the ECAL endcap module ###################### + ############################################################################### + + # The endcap module shape is the union of 5 (4 for the central modules, i.e. mod == 0) + # shapes. Out of the 5 shapes, only 3 are different: + # - the vertical element : [A] + # - the curved element : [B] + # - the horizontal element: [C] + + ################################################################################ + # "DEFAULT MODULE" ## "CENTRAL MODULE" # + # (Y) ## (Y) # + # ^ /----------| ## ^ /----------| # + # | / | [C] | ## | / | [C] | # + # | / [B]/-------| ## | / [B]/-------| # + # | /----/ ## | /----/ # + # | | | ## | | | # + # | |[A] | ## | |[A] | # + # | | | ## | | | # + # | \----\ ## | \----\ # + # | \ [B]\-------| ## | \ [B]\ # + # | \ | [C] | ## | \ | # + # | \----------| ## | \---| # + # |---------------------------> (X) ## |---------------------------> (X) # + ################################################################################ + + # Here we create the basic shapes: vertical, curved, horizontal + ECAL_ec_mod_vert_shape = geom.shapes.Box( + "ECAL_mod_" + str(mod) + "_shape1", + dx=KLOECellWidth * ColPerMod / 2.0, + dy=KLOEEndcapModDy[mod], + dz=0.5 * (KLOEEndcapECALDepth + AlPlateThick), + ) + + ECAL_ec_mod_curv_shape = geom.shapes.Tubs( + "ECAL_ec_mod_curv_" + str(mod) + "_shape1", + rmin=KLOEEndcapCurvRadius - AlPlateThick, + rmax=KLOEEndcapCurvRadius + KLOEEndcapECALDepth, + dz=KLOECellWidth * ColPerMod / 2.0, + sphi=math.pi / 2.0, + dphi=math.pi / 2.0, + ) + + ECAL_ec_mod_hor_shape = geom.shapes.Box( + "ECAL_ec_mod_hor_" + str(mod) + "_shape1", + dx=KLOECellWidth * ColPerMod / 2.0, + dy=KLOEEndcapStraight / 2.0, + dz=0.5 * (KLOEEndcapECALDepth + AlPlateThick), + ) + + # These are the parameters of the ec module shape + Curv_y_pos = KLOEEndcapModDy[mod] + YPosMod + Curv_z_pos = ( + ZPosMod + KLOEEndcapECALDepth / 2.0 + KLOEEndcapCurvRadius + ) + Straight_y_pos = ( + Curv_y_pos + + KLOEEndcapCurvRadius + + 0.5 * (KLOEEndcapECALDepth - AlPlateThick) + ) + Straight_z_pos = Curv_z_pos + KLOEEndcapStraight / 2.0 + if mod < 2: + Curv_y_bottom = -KLOEEndcapModDy[mod] + YPosMod + else: + Curv_y_bottom = -Curv_y_pos + + # Here we define positions and rotation of each element with + # respect to the vertical one + ECAL_ec_mod_curv_top_pos1 = geom.structure.Position( + "ECAL_ec_mod_curv_" + str(mod) + "_top_pos1", + XPosMod - XPosMod, + Curv_y_pos - YPosMod, + Curv_z_pos - (ZPosMod + 0.5 * AlPlateThick), + ) + + ECAL_ec_mod_curv_top_rot1 = geom.structure.Rotation( + "ECAL_ec_mod_curv_" + str(mod) + "_top_rot1", + Q("0deg"), + Q("-90deg"), + Q("0deg"), + ) + + ECAL_ec_mod_curv_bot_pos1 = geom.structure.Position( + "ECAL_ec_mod_curv_" + str(mod) + "_bot_pos1", + XPosMod - XPosMod, + Curv_y_bottom - YPosMod, + Curv_z_pos - (ZPosMod + 0.5 * AlPlateThick), + ) + + ECAL_ec_mod_curv_bot_rot1 = geom.structure.Rotation( + "ECAL_ec_mod_curv_" + str(mod) + "_bot_rot1", + Q("0deg"), + Q("-90deg"), + Q("180deg"), + ) + + ECAL_ec_mod_hor_top_pos1 = geom.structure.Position( + "ECAL_ec_mod_hor_" + str(mod) + "_top_pos1", + XPosMod - XPosMod, + Straight_y_pos - YPosMod, + Straight_z_pos - (ZPosMod + 0.5 * AlPlateThick), + ) + + ECAL_ec_mod_hor_top_rot1 = geom.structure.Rotation( + "ECAL_ec_mod_hor_" + str(mod) + "_top_rot1", + Q("90deg"), + Q("0deg"), + Q("0deg"), + ) + + ECAL_ec_mod_hor_bot_pos1 = geom.structure.Position( + "ECAL_ec_mod_hor_" + str(mod) + "_bot_pos1", + XPosMod - XPosMod, + -Straight_y_pos - YPosMod, + Straight_z_pos - (ZPosMod + 0.5 * AlPlateThick), + ) + + ECAL_ec_mod_hor_bot_rot1 = geom.structure.Rotation( + "ECAL_ec_mod_hor_" + str(mod) + "_bot_rot1", + Q("-90deg"), + Q("0deg"), + Q("0deg"), + ) + + # Here we create the ec module shape + ECAL_ec_mod_step1 = geom.shapes.Boolean( + "ECAL_ec_mod_" + str(mod) + "_step1", + type="union", + first=ECAL_ec_mod_vert_shape, + second=ECAL_ec_mod_curv_shape, + pos=ECAL_ec_mod_curv_top_pos1, + rot=ECAL_ec_mod_curv_top_rot1, + ) + + ECAL_ec_mod_step2 = geom.shapes.Boolean( + "ECAL_ec_mod_" + str(mod) + "_step2", + type="union", + first=ECAL_ec_mod_step1, + second=ECAL_ec_mod_curv_shape, + pos=ECAL_ec_mod_curv_bot_pos1, + rot=ECAL_ec_mod_curv_bot_rot1, + ) + + ECAL_ec_mod_shape = geom.shapes.Boolean( + "ECAL_ec_mod_" + str(mod) + "_shape", + type="union", + first=ECAL_ec_mod_step2, + second=ECAL_ec_mod_hor_shape, + pos=ECAL_ec_mod_hor_top_pos1, + rot=ECAL_ec_mod_hor_top_rot1, + ) + + if mod > 1: + ECAL_ec_mod_shape = geom.shapes.Boolean( + "ECAL_ec_central_mod_" + str(mod) + "_shape", + type="union", + first=ECAL_ec_mod_shape, + second=ECAL_ec_mod_hor_shape, + pos=ECAL_ec_mod_hor_bot_pos1, + rot=ECAL_ec_mod_hor_bot_rot1, + ) + + ECAL_ec_mod_lv = geom.structure.Volume( + "ECAL_ec_mod_" + str(mod) + "_lv", + material="Air", + shape=ECAL_ec_mod_shape, + ) + + ############################################################################### + ########## creating and appending the vertical part to the ECAL endcap ######## + ############################################################################### + + ECAL_ec_mod_vert_lv = self.get_ec_module_vert(geom, mod, ColPerMod) + + ECAL_ec_mod_vert_pla = geom.structure.Placement( + "ECAL_ec_mod_vert_" + str(mod) + "_pla", + volume=ECAL_ec_mod_vert_lv, + ) + + ECAL_ec_mod_lv.placements.append(ECAL_ec_mod_vert_pla.name) + + ############################################################################### + ########## creating and appending the curved part to the ECAL endcap ########## + ############################################################################### + + ECAL_ec_mod_curv_lv = self.get_ec_module_curv(geom, mod, ColPerMod) + + # Using the same rotation used to contruct composite shape + # results in 16 overlaps. Why???? + ECAL_ec_mod_curv_top_rot2 = geom.structure.Rotation( + "ECAL_ec_mod_curv_" + str(mod) + "_top_rot2", + Q("0deg"), + Q("90deg"), + Q("0deg"), + ) + + ECAL_ec_mod_curv_top_pla = geom.structure.Placement( + "ECAL_ec_mod_curv_" + str(mod) + "_top_pla", + volume=ECAL_ec_mod_curv_lv, + pos=ECAL_ec_mod_curv_top_pos1, + rot=ECAL_ec_mod_curv_top_rot2, + ) + + ECAL_ec_mod_curv_bot_pla = geom.structure.Placement( + "ECAL_ec_mod_curv_" + str(mod) + "_bot_pla", + volume=ECAL_ec_mod_curv_lv, + pos=ECAL_ec_mod_curv_bot_pos1, + rot=ECAL_ec_mod_curv_bot_rot1, + ) + + ECAL_ec_mod_lv.placements.append(ECAL_ec_mod_curv_top_pla.name) + ECAL_ec_mod_lv.placements.append(ECAL_ec_mod_curv_bot_pla.name) + + ############################################################################### + ########## creating and appending the horizontal part to the ECAL endcap ###### + ############################################################################### + + ECAL_ec_mod_hor_lv = self.get_ec_module_hor(geom, mod, ColPerMod) + + ECAL_ec_mod_hor_top_pla = geom.structure.Placement( + "ECAL_ec_mod_hor_" + str(mod) + "_top_pla", + volume=ECAL_ec_mod_hor_lv, + pos=ECAL_ec_mod_hor_top_pos1, + rot=ECAL_ec_mod_hor_top_rot1, + ) + + ECAL_ec_mod_hor_bot_pla = geom.structure.Placement( + "ECAL_ec_mod_hor_" + str(mod) + "_bot_pla", + volume=ECAL_ec_mod_hor_lv, + pos=ECAL_ec_mod_hor_bot_pos1, + rot=ECAL_ec_mod_hor_bot_rot1, + ) + + ECAL_ec_mod_lv.placements.append(ECAL_ec_mod_hor_top_pla.name) + + if mod > 1: + ECAL_ec_mod_lv.placements.append(ECAL_ec_mod_hor_bot_pla.name) + + ############################################################################### + ########## positioning of endcap modules ###################################### + ############################################################################### + + # positioning of ec module + ECAL_ec_mod_pos = geom.structure.Position( + "ECAL_ec_mod_" + str(mod) + "_pos", + XPosMod, + YPosMod, + ZPosMod + 0.5 * AlPlateThick, + ) + + ECAL_ec_mod_rot = geom.structure.Rotation( + "ECAL_ec_mod_" + str(mod) + "_rot", + Q("0deg"), + Q("0deg"), + Q("0deg"), + ) + + ECAL_ec_mod_pla = geom.structure.Placement( + "ECAL_ec_mod_" + str(mod) + "_pla", + volume=ECAL_ec_mod_lv, + pos=ECAL_ec_mod_pos, + rot=ECAL_ec_mod_rot, + ) + + ECAL_endcap_lv.placements.append(ECAL_ec_mod_pla.name) + + mod += 16 + ECAL_ec_mod_pos = geom.structure.Position( + "ECAL_ec_mod_" + str(mod) + "_pos", + -XPosMod, + -YPosMod, + ZPosMod + 0.5 * AlPlateThick, + ) + + ECAL_ec_mod_rot = geom.structure.Rotation( + "ECAL_ec_mod_" + str(mod) + "_rot", + Q("0deg"), + Q("0deg"), + Q("180deg"), + ) + + ECAL_ec_mod_pla = geom.structure.Placement( + "ECAL_ec_mod_" + str(mod) + "_pla", + volume=ECAL_ec_mod_lv, + pos=ECAL_ec_mod_pos, + rot=ECAL_ec_mod_rot, + ) + + ECAL_endcap_lv.placements.append(ECAL_ec_mod_pla.name) + + # create the vertical part of the ECAL endcap module + def get_ec_module_vert(self, geom, mod, nCols): + + # params + KLOEEndcapECALDepth = self.EndcapDim[2] + KLOECellWidth = self.EndcapDim[5] + KLOEEndcapModDy = self.EndcapModDim + AlPlateThick = self.BackPlateThick + + # create endcap module vertical part volume + ECAL_ec_mod_vert_shape = geom.shapes.Box( + "ECAL_mod_" + str(mod) + "_shape", + dx=KLOECellWidth * nCols / 2.0, + dy=KLOEEndcapModDy[mod], + dz=0.5 * (KLOEEndcapECALDepth + AlPlateThick), + ) + + ECAL_ec_mod_vert_lv = geom.structure.Volume( + "ECAL_ec_mod_vert_" + str(mod) + "_lv", + material="Air", + shape=ECAL_ec_mod_vert_shape, + ) + + ########## creating the Aluminium plate for the endcap modules########## + + ECAL_end_Alplate_shape = geom.shapes.Box( + "endECALAlplate_" + str(mod), + dx=KLOECellWidth * nCols / 2.0, + dy=KLOEEndcapModDy[mod], + dz=AlPlateThick / 2.0, + ) + + ECAL_end_Alplate_lv = geom.structure.Volume( + "endvolECALAlplate_" + str(mod), + material="Aluminum", + shape=ECAL_end_Alplate_shape, + ) + + ECAL_end_Alplate_pos = geom.structure.Position( + "endECALAlplatepos_" + str(mod), + Q("0.0cm"), + Q("0.0cm"), + 0.5 * KLOEEndcapECALDepth, + ) + + ECAL_end_Alplate_pla = geom.structure.Placement( + "endECALAlplatepla_" + str(mod), + volume=ECAL_end_Alplate_lv, + pos=ECAL_end_Alplate_pos, + ) + + ECAL_ec_mod_vert_lv.placements.append(ECAL_end_Alplate_pla.name) + + ########## creating active slab volumes ########## + + endECALActiveSlab = geom.shapes.Box( + "endECALActiveSlab_" + str(mod), + dx=KLOECellWidth * nCols / 2.0, + dy=KLOEEndcapModDy[mod], + dz=0.5 * self.ActiveSlabThickness, + ) - endECALActiveSlab = geom.shapes.Tubs( - 'endECALActiveSlab'+ '_' + str(i), - rmin=KLOEEndcapECALRmin,# + FrameThickness, - rmax=KLOEEndcapECALRmax,# - FrameThickness, - dz=0.5 * self.ActiveSlabThickness) + endECALActiveSlab_lv = geom.structure.Volume( + "endvolECALActiveSlab_" + str(mod), + material=self.ScintMat, + shape=endECALActiveSlab, + ) + endECALActiveSlab_lv.params.append(("SensDet", "EMCalSci")) - endECALActiveSlab_lv = geom.structure.Volume( - 'endvolECALActiveSlab' + '_' + str(i), - material=self.ActiveMat, - shape=endECALActiveSlab) - endECALActiveSlab_lv.params.append(("SensDet","EMCalSci")) + ########## creating passive slab volumes ########## + + endECALPassiveSlab = geom.shapes.Box( + "endECALPassveSlab_" + str(mod), + dx=KLOECellWidth * nCols / 2.0, + dy=KLOEEndcapModDy[mod], + dz=0.5 * self.PasSlabThickness, + ) + + endECALPassiveSlab_lv = geom.structure.Volume( + "endvolECALPassiveSlab_" + str(mod), + material=self.PasMat, + shape=endECALPassiveSlab, + ) + + ########################################### + + for i in range(self.nSlabs): # nSlabs + + xposSlab = Q("0cm") + yposSlab = Q("0cm") + + zposSlabActive = ( + -(KLOEEndcapECALDepth + AlPlateThick) * 0.5 + + (i + 0.5) * self.ActiveSlabThickness + + i * self.PasSlabThickness + ) + + zposSlabPassive = ( + zposSlabActive + + 0.5 * self.ActiveSlabThickness + + 0.5 * self.PasSlabThickness + ) + + ########## appending active slabs to the ECAL endcap########## endECALActiveSlabPos = geom.structure.Position( - 'endecalactiveslabpos' + '_' + str(i), - xposSlab, yposSlab, zposSlabActive) + "endecalactiveslabpos_" + str(mod) + "_" + str(i), + xposSlab, + yposSlab, + zposSlabActive, + ) endECALActiveSlabPlace = geom.structure.Placement( - 'endecalactiveslabpla' + '_' + str(i), - volume=endECALActiveSlab_lv, - pos=endECALActiveSlabPos) - - ECAL_end_lv.placements.append( endECALActiveSlabPlace.name ) - - ##########creating and appending passive slabs to the ECAL endcap########## + "endecalactiveslabpla_" + str(mod) + "_" + str(i), + volume=endECALActiveSlab_lv, + pos=endECALActiveSlabPos, + ) - endECALPassiveSlab = geom.shapes.Tubs( - 'endECALPassveSlab' + '_' + str(i), - rmin=KLOEEndcapECALRmin,# + FrameThickness, - rmax=KLOEEndcapECALRmax,# - FrameThickness, - dz=0.5 * self.PasSlabThickness) + ECAL_ec_mod_vert_lv.placements.append(endECALActiveSlabPlace.name) - endECALPassiveSlab_lv = geom.structure.Volume( - 'endvolECALPassiveSlab' + '_' + str(i), - material=self.PasMat, - shape=endECALPassiveSlab) + ########## appending passive slabs to the ECAL endcap########## endECALPassiveSlabPos = geom.structure.Position( - 'endecalpassiveslabpos' + '_' + str(i), - xposSlab, yposSlab, zposSlabPassive) + "endecalpassiveslabpos_" + str(mod) + "_" + str(i), + xposSlab, + yposSlab, + zposSlabPassive, + ) endECALPassiveSlabPlace = geom.structure.Placement( - 'endecalpassiveslabpla' + '_' + str(i), - volume=endECALPassiveSlab_lv, - pos=endECALPassiveSlabPos) + "endecalpassiveslabpla_" + str(mod) + "_" + str(i), + volume=endECALPassiveSlab_lv, + pos=endECALPassiveSlabPos, + ) + + ECAL_ec_mod_vert_lv.placements.append(endECALPassiveSlabPlace.name) + + return ECAL_ec_mod_vert_lv + + # create the curved part of the ECAL endcap module + def get_ec_module_curv(self, geom, mod, nCols): + + KLOEEndcapECALDepth = self.EndcapDim[2] + KLOEEndcapCurvRadius = self.EndcapDim[3] + KLOECellWidth = self.EndcapDim[5] + AlPlateThick = self.BackPlateThick + + ECAL_ec_mod_curv_shape = geom.shapes.Tubs( + "ECAL_ec_mod_curv_" + str(mod) + "_shape", + rmin=KLOEEndcapCurvRadius - AlPlateThick, + rmax=KLOEEndcapCurvRadius + KLOEEndcapECALDepth, + dz=KLOECellWidth * nCols / 2.0, + sphi=math.pi / 2.0, + dphi=math.pi / 2.0, + ) + + ECAL_ec_mod_curv_lv = geom.structure.Volume( + "ECAL_ec_mod_curv_" + str(mod) + "_lv", + material="Air", + shape=ECAL_ec_mod_curv_shape, + ) + + ##########Aluminium plate for the endcap curved part########## + + ECAL_ec_mod_curv_Alplate_shape = geom.shapes.Tubs( + "ECAL_ec_mod_curv_Alplate_" + str(mod), + rmin=KLOEEndcapCurvRadius - AlPlateThick, + rmax=KLOEEndcapCurvRadius, + dz=KLOECellWidth * nCols / 2.0, + sphi=math.pi / 2.0, + dphi=math.pi / 2.0, + ) + + ECAL_ec_mod_curv_Alplate_lv = geom.structure.Volume( + "ECAL_ec_mod_curv_Alplate_" + str(mod) + "_lv", + material="Aluminum", + shape=ECAL_ec_mod_curv_Alplate_shape, + ) + + ECAL_ec_mod_curv_Alplate_pos = geom.structure.Position( + "ECAL_ec_mod_curv_Alplate_" + str(mod) + "_pos", + Q("0.0cm"), + Q("0.0cm"), + Q("0.0cm"), + ) + + ECAL_ec_mod_curv_Alplate_rot = geom.structure.Rotation( + "ECAL_ec_mod_curv_Alplate_" + str(mod) + "_rot", + Q("0deg"), + Q("0deg"), + Q("0deg"), + ) + + ECAL_ec_mod_curv_Alplate_pla = geom.structure.Placement( + "ECAL_ec_mod_curv_Alplate_" + str(mod) + "_pla", + volume=ECAL_ec_mod_curv_Alplate_lv, + pos=ECAL_ec_mod_curv_Alplate_pos, + rot=ECAL_ec_mod_curv_Alplate_rot, + ) + + ECAL_ec_mod_curv_lv.placements.append(ECAL_ec_mod_curv_Alplate_pla.name) + + ################ + + for i in range(self.nSlabs): # nSlabs + + xposSlab = Q("0cm") + yposSlab = Q("0cm") + zposSlab = Q("0cm") + + rmaxSlabActive = (KLOEEndcapCurvRadius + KLOEEndcapECALDepth) - ( + i * self.ActiveSlabThickness + i * self.PasSlabThickness + ) + + rmaxSlabPassive = rmaxSlabActive - self.ActiveSlabThickness + + ##########creating and appending active slabs to the ECAL endcap########## + + endECALcurvActiveSlab = geom.shapes.Tubs( + "endECALcurvActiveSlab_" + str(mod) + "_" + str(i), + rmax=rmaxSlabActive, + rmin=rmaxSlabActive - self.ActiveSlabThickness, + dz=KLOECellWidth * nCols / 2.0, + sphi=math.pi / 2.0, + dphi=math.pi / 2.0, + ) + + endECALcurvActiveSlab_lv = geom.structure.Volume( + "endvolECALcurvActiveSlab_" + str(mod) + "_" + str(i), + material=self.ScintMat, + shape=endECALcurvActiveSlab, + ) + endECALcurvActiveSlab_lv.params.append(("SensDet", "EMCalSci")) + + endECALcurvActiveSlabPos = geom.structure.Position( + "endecalcurvactiveslabpos_" + str(mod) + "_" + str(i), + xposSlab, + yposSlab, + zposSlab, + ) + + endECALcurvActiveSlabPlace = geom.structure.Placement( + "endecalcurvactiveslabpla_" + str(mod) + "_" + str(i), + volume=endECALcurvActiveSlab_lv, + pos=endECALcurvActiveSlabPos, + ) + + ECAL_ec_mod_curv_lv.placements.append( + endECALcurvActiveSlabPlace.name + ) + + ##########creating and appending passive slabs to the ECAL endcap########## + + endECALcurvPassiveSlab = geom.shapes.Tubs( + "endECALcurvPassiveSlab_" + str(mod) + "_" + str(i), + rmax=rmaxSlabPassive, + rmin=rmaxSlabPassive - self.PasSlabThickness, + dz=KLOECellWidth * nCols / 2.0, + sphi=math.pi / 2, + dphi=math.pi / 2.0, + ) + + endECALcurvPassiveSlab_lv = geom.structure.Volume( + "endvolECALcurvPassiveSlab_" + str(mod) + "_" + str(i), + material=self.PasMat, + shape=endECALcurvPassiveSlab, + ) + + endECALcurvPassiveSlabPos = geom.structure.Position( + "endecalcurvpassiveslabpos_" + str(mod) + "_" + str(i), + xposSlab, + yposSlab, + zposSlab, + ) + + endECALcurvPassiveSlabPlace = geom.structure.Placement( + "endecalcurvpassiveslabpla_" + str(mod) + "_" + str(i), + volume=endECALcurvPassiveSlab_lv, + pos=endECALcurvPassiveSlabPos, + ) + + ECAL_ec_mod_curv_lv.placements.append( + endECALcurvPassiveSlabPlace.name + ) + + return ECAL_ec_mod_curv_lv + + # create the horizontal part of the ECAL endcap module + def get_ec_module_hor(self, geom, mod, nCols): + + KLOEEndcapECALDepth = self.EndcapDim[2] + KLOEEndcapStraight = self.EndcapDim[4] + KLOECellWidth = self.EndcapDim[5] + AlPlateThick = self.BackPlateThick + + ECAL_ec_mod_hor_shape = geom.shapes.Box( + "ECAL_ec_mod_hor_" + str(mod) + "_shape", + dx=KLOECellWidth * nCols / 2.0, + dy=KLOEEndcapStraight / 2.0, + dz=0.5 * (KLOEEndcapECALDepth + AlPlateThick), + ) + + ECAL_ec_mod_hor_lv = geom.structure.Volume( + "ECAL_ec_mod_hor_" + str(mod) + "_lv", + material="Air", + shape=ECAL_ec_mod_hor_shape, + ) + + ##########Aluminium plate for the endcap short straight part########## + + ECAL_ec_mod_hor_Alplate_shape = geom.shapes.Box( + "ECAL_ec_mod_hor_Alplate_" + str(mod) + "_shape", + dx=KLOECellWidth * nCols / 2.0, + dy=KLOEEndcapStraight / 2.0, + dz=AlPlateThick / 2.0, + ) + + ECAL_ec_mod_hor_Alplate_lv = geom.structure.Volume( + "ECAL_ec_mod_hor_Alplate_" + str(mod) + "_lv", + material="Aluminum", + shape=ECAL_ec_mod_hor_Alplate_shape, + ) + + ECAL_ec_mod_hor_Alplate_pos = geom.structure.Position( + "ECAL_ec_mod_hor_Alplate_" + str(mod) + "_pos", + Q("0.0cm"), + Q("0.0cm"), + -0.5 * KLOEEndcapECALDepth, + ) + + ECAL_ec_mod_hor_Alplate_rot = geom.structure.Rotation( + "ECAL_ec_mod_hor_Alplate_" + str(mod) + "_rot", + Q("0deg"), + Q("0deg"), + Q("0deg"), + ) + + ECAL_ec_mod_hor_Alplate_pla = geom.structure.Placement( + "ECAL_ec_mod_hor_Alplate_" + str(mod) + "_pla", + volume=ECAL_ec_mod_hor_Alplate_lv, + pos=ECAL_ec_mod_hor_Alplate_pos, + rot=ECAL_ec_mod_hor_Alplate_rot, + ) + + ECAL_ec_mod_hor_lv.placements.append(ECAL_ec_mod_hor_Alplate_pla.name) + + ########### + endECALstraightActiveSlab = geom.shapes.Box( + "endECALstraightActiveSlab_" + str(mod), + dx=KLOECellWidth * nCols / 2.0, + dy=KLOEEndcapStraight / 2.0, + dz=0.5 * self.ActiveSlabThickness, + ) + + endECALstraightActiveSlab_lv = geom.structure.Volume( + "endvolECALstraightActiveSlab_" + str(mod), + material=self.ScintMat, + shape=endECALstraightActiveSlab, + ) + endECALstraightActiveSlab_lv.params.append(("SensDet", "EMCalSci")) + + endECALstraightPassiveSlab = geom.shapes.Box( + "endECALstraightPassveSlab_" + str(mod), + dx=KLOECellWidth * nCols / 2.0, + dy=KLOEEndcapStraight / 2.0, + dz=0.5 * self.PasSlabThickness, + ) + + endECALstraightPassiveSlab_lv = geom.structure.Volume( + "endvolECALstraightPassiveSlab_" + str(mod), + material=self.PasMat, + shape=endECALstraightPassiveSlab, + ) + + for i in range(self.nSlabs): # nSlabs + + xposSlab = Q("0cm") + yposSlab = Q("0cm") + + zposSlabActive =( (KLOEEndcapECALDepth+AlPlateThick) * 0.5 - + ((i + 0.5) * self.ActiveSlabThickness + + i * self.PasSlabThickness) ) + + zposSlabPassive = (zposSlabActive - + (0.5 * self.ActiveSlabThickness + + 0.5 * self.PasSlabThickness)) + + + ##########creating and appending active slabs to the ECAL endcap########## + + endECALstraightActiveSlabPos = geom.structure.Position( + "endecalstraightactiveslabpos_" + str(mod) + "_" + str(i), + xposSlab, + yposSlab, + zposSlabActive, + ) + + endECALstraightActiveSlabPlace = geom.structure.Placement( + "endecalstraightactiveslabpla_" + str(mod) + "_" + str(i), + volume=endECALstraightActiveSlab_lv, + pos=endECALstraightActiveSlabPos, + ) + + ECAL_ec_mod_hor_lv.placements.append( + endECALstraightActiveSlabPlace.name + ) + + ##########creating and appending passive slabs to the ECAL endcap########## + + endECALstraightPassiveSlabPos = geom.structure.Position( + "endecalstraightpassiveslabpos_" + str(mod) + "_" + str(i), + xposSlab, + yposSlab, + zposSlabPassive, + ) + + endECALstraightPassiveSlabPlace = geom.structure.Placement( + "endecalstraightpassiveslabpla_" + str(mod) + "_" + str(i), + volume=endECALstraightPassiveSlab_lv, + pos=endECALstraightPassiveSlabPos, + ) - ECAL_end_lv.placements.append( endECALPassiveSlabPlace.name ) + ECAL_ec_mod_hor_lv.placements.append( + endECALstraightPassiveSlabPlace.name + ) + return ECAL_ec_mod_hor_lv diff --git a/duneggd/Config/SAND_ECAL.cfg b/duneggd/Config/SAND_ECAL.cfg index 0629ec0..01882e5 100644 --- a/duneggd/Config/SAND_ECAL.cfg +++ b/duneggd/Config/SAND_ECAL.cfg @@ -1,21 +1,33 @@ [SANDECAL] class = duneggd.SubDetector.SandECal.SandECalBuilder -subbuilders = ['SANDECALBARRELMOD','SANDECALENDCAP'] - -[SANDECALBARRELMOD] -class = duneggd.Component.SandECalBarrelMod.SandECalBarrelModBuilder -trapezoidDim = [Q('26.255cm'), Q('29.285cm'), Q('215cm'), Q('11.5cm')] #b/2, B/2, L/2, D/2 ScintMat = 'Scintillator' PasMat = 'Lead' ActiveSlabThickness = Q('0.07cm') PasSlabThickness = Q('0.04cm') nSlabs = 209 +BackPlateThick = Q('2.5cm') +NCaloModBarrel = {SAND:NCaloModBarrel} +subbuilders = ['SANDECALBARRELMOD','SANDECALENDCAP'] + +[SANDECALBARRELMOD] +class = duneggd.Component.SandECalBarrelMod.SandECalBarrelModBuilder +trapezoidDim = [Q('26.255cm'), Q('29.285cm'), Q('215cm'), Q('11.5cm')] #b/2, B/2, L/2, D/2 +ScintMat = {SANDECAL:ScintMat} +PasMat = {SANDECAL:PasMat} +ActiveSlabThickness = {SANDECAL:ActiveSlabThickness} +PasSlabThickness = {SANDECAL:PasSlabThickness} +nSlabs = {SANDECAL:nSlabs} +BackPlateThick = {SANDECAL:BackPlateThick} [SANDECALENDCAP] class = duneggd.Component.SandECalEndcap.SandECalEndcapBuilder -EndcapSize = [Q('20.8cm'), Q('2.0m'),Q('0.23m')] #rmin, rmax, dz -ActiveMat = 'Scintillator' -PasMat = 'Lead' -ActiveSlabThickness = Q('0.07cm') -PasSlabThickness = Q('0.04cm') -nSlabs = 209 +EndcapDim = [Q('200cm'), Q('169cm'), Q('23cm'), Q('10cm'), Q('20cm'), Q('4.44cm')] #Max_radius, Z_position, Thickness, Curv_radius, Straight_part, Cell_dim +EndcapModDim = [Q('51cm'), Q('51cm'), Q('160.5cm'), Q('157.3cm'),Q('153.2cm'),Q('147.9cm'), + Q('141.5cm'),Q('133.8cm'),Q('124.6cm'),Q('113.7cm'),Q('100.7cm'),Q('84.5cm'), + Q('71.6cm'),Q('55.4cm'),Q('35.7cm'),Q('4.3cm')] +ScintMat = {SANDECAL:ScintMat} +PasMat = {SANDECAL:PasMat} +ActiveSlabThickness = {SANDECAL:ActiveSlabThickness} +PasSlabThickness = {SANDECAL:PasSlabThickness} +nSlabs = {SANDECAL:nSlabs} +BackPlateThick = {SANDECAL:BackPlateThick} \ No newline at end of file diff --git a/duneggd/Config/SAND_MAGNET.cfg b/duneggd/Config/SAND_MAGNET.cfg index 8d1a5b5..f7377dd 100644 --- a/duneggd/Config/SAND_MAGNET.cfg +++ b/duneggd/Config/SAND_MAGNET.cfg @@ -1,12 +1,13 @@ [SAND] class = duneggd.SubDetector.SAND.SANDBuilder -subbuilders = ['SANDINNERVOLUME', 'SANDECAL'] +subbuilders = ['SANDINNERVOLUME','SANDECAL'] halfDimension = {'dx':Q('360cm'),'dy':Q('360cm'),'dz':Q('400cm')} Material = 'Air' CentralBField = Q("0.6T") ExternalBField = Q("1.4T") BuildSTTFULL = False -Build3DSTwithSTT = False -Build3DST = False +Build3DSTwithSTT = False +Build3DST = False STTRotations = [Q('0deg'), Q('0deg'), Q('0deg')] +NCaloModBarrel = 24 diff --git a/duneggd/SubDetector/SAND.py b/duneggd/SubDetector/SAND.py index c5a29a6..3fcbe11 100644 --- a/duneggd/SubDetector/SAND.py +++ b/duneggd/SubDetector/SAND.py @@ -64,8 +64,11 @@ def configure(self, # part D is a TUBS, 1.96<|x|<2.15m, rmin=0.512m, rmax=1.73m self.EndcapDZStart=Q("1.96m") self.EndcapDZEnd=Q("2.15m") - self.EndcapDRmax=Q("1.73m") - self.EndcapDRmin=Q("0.51m") + + # Here we reduce the size of the D element of the yoke endcap + # to avoid overlap with the curved element of the ecal endcap module + self.EndcapDRmax=Q("1.66m") + self.EndcapDRmin=Q("0.62m") #^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ @@ -80,23 +83,46 @@ def construct(self, geom): # Magnetized internal volume MagIntVolRmax=Q("2.43m") MagIntVolRmin=Q("2.0m") - MagIntVolHLmin=Q("1.96m") + MagIntVolHLmin=Q("2.22m") MagIntVolHLmax=Q("2.15m") + + # Option below results in 1 overlap: MagIntVol_volume extruded by: MagIntVol_volume/kloe_calo_volume_0 + # MagIntVolHLmin=Q("1.96m") + # MagIntVolHLmax=Q("2.15m") vol1_shape = geom.shapes.Tubs("MagIntVol_vol1_shape", rmin=MagIntVolRmin, rmax=MagIntVolRmax, dz=MagIntVolHLmax) vol2_shape = geom.shapes.Tubs("MagIntVol_vol2_shape", rmin=Q('0.0m'), rmax=MagIntVolRmin, dz=MagIntVolHLmin) - pos = geom.structure.Position("MagIntVol_boolean_shape_pos", Q('0m'), Q('0m'), Q('0m')) + # volume to be removed from MagIntVol_vol to make room for yoke endcap + vol3_shape = geom.shapes.Tubs("MagIntVol_vol3_shape", rmin=self.EndcapDRmin, rmax=self.EndcapDRmax, dz=0.5 * (self.EndcapCZEnd - self.EndcapDZStart)) - MagIntVol_shape = geom.shapes.Boolean("MagIntVol_shape", type='union', + pos = geom.structure.Position("MagIntVol_boolean_shape_pos1", Q('0m'), Q('0m'), Q('0m')) + + MagIntVol_shape1 = geom.shapes.Boolean("MagIntVol_shape", type='union', first=vol1_shape, second=vol2_shape, rot='noRotate', pos=pos) + pos = geom.structure.Position("MagIntVol_boolean_shape_pos2", Q('0m'), Q('0m'), 0.5 * (self.EndcapDZStart + self.EndcapCZEnd)) + + MagIntVol_shape2 = geom.shapes.Boolean("MagIntVol_shape2", type='subtraction', + first=MagIntVol_shape1, + second=vol3_shape, + rot='noRotate', + pos=pos) + + pos = geom.structure.Position("MagIntVol_boolean_shape_pos3", Q('0m'), Q('0m'), -0.5 * (self.EndcapDZStart + self.EndcapCZEnd)) + + MagIntVol_shape3 = geom.shapes.Boolean("MagIntVol_shape3", type='subtraction', + first=MagIntVol_shape2, + second=vol3_shape, + rot='noRotate', + pos=pos) + MagIntVol_volume = geom.structure.Volume('MagIntVol_volume', material='Air', - shape=MagIntVol_shape) + shape=MagIntVol_shape3) pos = [Q('0m'),Q('0m'),Q('0m')] @@ -129,38 +155,6 @@ def construct(self, geom): print(("printing main_lv: " + str(main_lv))) - -# TranspV = [0,0,1] -# begingap = ltools.getBeginGap( self ) - - # initial position, based on the dimension projected on transportation vector - -# pos = [Q('0m'),Q('0m'),-main_hDim[2]] -# pos = [Q('0m'),Q('0m'),Q('0m')] -# rot = [Q('0deg'),Q('90deg'),Q('0deg')] -# main_lv = main_lv.get_Volume() -# main_pos = gemo.structure.Poition( main_lv.name_pos, Pos[0], Pos[1], Pos[2] ) -# main_rot = geom.structure.Rotation( main_lv.name_rot, Rot[0], Rot[1], Rot[2] ) -# main_pla = geom.structure.Placement (main_lv.name_pla, volume=main_lv, pos=main_pos, rot=main_rot ) -# main_lv.placements.append( main_pla.name ) - -# print( "KLOE subbuilders") -# for i,sb in enumerate(self.get_builders()): -# sb_lv = sb.get_volume() -# print( "Working on ", i, sb_lv.name) -# sb_dim = ltools.getShapeDimensions( sb_lv, geom ) - -# pos[2] = pos[2] + sb_dim[2] + self.InsideGap[i] - # defining position, placement, and finally insert into main logic volume. -# pos_name=self.name+sb_lv.name+'_pos_'+str(i) -# pla_name=self.name+sb_lv.name+'_pla_'+str(i) -# print( "Position name", pos_name) -# print( "Placement name", pla_name) -# sb_pos = geom.structure.Position(pos_name,pos[0], pos[1], pos[2]) -# sb_pla = geom.structure.Placement(pla_name,volume=sb_lv, pos=sb_pos) -# print( "Appending ",sb_pla.name," to main_lv=",main_lv.name) -# main_lv.placements.append(sb_pla.name) - def build_yoke(self,main_lv,geom): #build barrel @@ -186,7 +180,7 @@ def build_yoke(self,main_lv,geom): barrel_pla=geom.structure.Placement("KLOEYokeBarrel_pla", volume=barrel_lv, pos=barrel_pos) - print(("appending "+barrel_pla.name)) + print(("appending "+barrel_pla.name)) main_lv.placements.append(barrel_pla.name) # build endcap diff --git a/duneggd/SubDetector/SandECal.py b/duneggd/SubDetector/SandECal.py index a8d23ea..7a3148d 100644 --- a/duneggd/SubDetector/SandECal.py +++ b/duneggd/SubDetector/SandECal.py @@ -8,13 +8,35 @@ class SandECalBuilder(gegede.builder.Builder): #^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ - def configure(self, **kwds): - self.NCaloModBarrel = 24 + def configure(self, NCaloModBarrel=None, **kwds): + self.NCaloModBarrel = NCaloModBarrel self.caloThickness = Q('23cm') self.EndcapZ = Q('1.69m') self.EndcapRmin = Q('20.8cm') self.BarrelRmin = Q('2m') self.BarrelDZ = Q('2.15m') + self.ECCurvRad = Q('10cm') + self.ECStraight = Q('20cm') + self.AlPlateThick= Q('2.5cm') + + ### Below values should be the same as the one in SANDBuilder + ### and will be used to construct subtraction boolean volume + ### to avoid overlap with yoke endcap elements (C,D) + + # part C is a TUBS, 2.15<|x|<2.58m, rmin=0.84m, rmax=1.34m + self.EndcapCZStart=Q("2.15m") + self.EndcapCZEnd=Q("2.58m") + self.EndcapCRmax=Q("1.34m") + self.EndcapCRmin=Q("0.84m") + + # part D is a TUBS, 1.96<|x|<2.15m, rmin=0.512m, rmax=1.73m + self.EndcapDZStart=Q("1.96m") + self.EndcapDZEnd=Q("2.15m") + + # Here we reduce the size of the D element of the yoke endcap + # to avoid overlap with the curved element of the ecal endcap module + self.EndcapDRmax=Q("1.66m") + self.EndcapDRmin=Q("0.62m") #^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ def construct(self, geom): @@ -23,48 +45,70 @@ def construct(self, geom): # barrel rmax_barrel = (self.BarrelRmin + self.caloThickness) / math.cos(ang) # endcap - rmax_ec = rmax_barrel - dz_ec = 0.5 * self.caloThickness - zpos_ec = self.EndcapZ + 0.5 * self.caloThickness + rmin_ec = Q('0cm') + rmax_ec = self.BarrelRmin + dz_ec = (self.caloThickness+self.ECCurvRad+self.ECStraight)/2. + xpos_ec = Q('0cm') + ypos_ec = Q('0cm') + zpos_ec = self.EndcapZ + dz_ec - # barrel_shape = geom.shapes.Tubs("kloe_calo_barrel_shape", rmin=self.BarrelRmin, rmax=rmax_barrel, dz=self.BarrelDZ) barrel_shape = geom.shapes.PolyhedraRegular("kloe_calo_barrel_shape", numsides=24, rmin=self.BarrelRmin, - rmax=self.BarrelRmin + - self.caloThickness, + rmax=self.BarrelRmin + + self.caloThickness+self.AlPlateThick, dz=self.BarrelDZ, sphi=Q('7.5deg')) + endcap_shape = geom.shapes.Tubs("kloe_calo_endcap_shape", - rmin=Q('0m'), + rmin=rmin_ec, rmax=rmax_ec, dz=dz_ec) + + + # volume to be removed from MagIntVol_vol to make room for yoke endcap + yoke_endcap_shape = geom.shapes.Tubs("yoke_endcap_shape_cl", rmin=self.EndcapDRmin, rmax=self.EndcapDRmax, dz=0.5 * (self.EndcapCZEnd - self.EndcapDZStart)) - calo_ec_R_pos = geom.structure.Position("calo_ec_R_pos", Q('0m'), - Q('0m'), zpos_ec) + calo_eca_pos = geom.structure.Position("calo_eca_pos", xpos_ec, + ypos_ec, -zpos_ec) - calo_shape_tmp = geom.shapes.Boolean("kloe_calo_shape_tmp", - type='union', - first=barrel_shape, - second=endcap_shape, - rot='noRotate', - pos=calo_ec_R_pos) + calo_ecb_pos = geom.structure.Position("calo_ecb_pos", xpos_ec, + ypos_ec, zpos_ec) - calo_ec_L_pos = geom.structure.Position("calo_ec_L_pos", Q('0m'), - Q('0m'), -zpos_ec) + calo_tmp1 = geom.shapes.Boolean("kloe_calo_tmp1", + type='union', + first=barrel_shape, + second=endcap_shape, + pos=calo_eca_pos) - calo_shape = geom.shapes.Boolean("kloe_calo_shape", + calo_tmp2 = geom.shapes.Boolean("kloe_calo_tmp2", type='union', - first=calo_shape_tmp, + first=calo_tmp1, second=endcap_shape, - rot='r180aboutY', - pos=calo_ec_L_pos) + pos=calo_ecb_pos) + + yoke_ec_pos = geom.structure.Position("yoke_ec_pos_cl", Q('0m'), Q('0m'), 0.5 * (self.EndcapDZStart + self.EndcapCZEnd)) + + calo_tmp3 = geom.shapes.Boolean("kloe_calo_tmp3", + type='subtraction', + first=calo_tmp2, + second=yoke_endcap_shape, + pos=yoke_ec_pos) + + yoke_ec_pos = geom.structure.Position("yoke_ec_pos", Q('0m'), Q('0m'), -0.5 * (self.EndcapDZStart + self.EndcapCZEnd)) + + calo_shape = geom.shapes.Boolean("kloe_calo_tmp4", + type='subtraction', + first=calo_tmp3, + second=yoke_endcap_shape, + pos=yoke_ec_pos) calo_lv = geom.structure.Volume('kloe_calo_volume', material="Air", shape=calo_shape) self.add_volume(calo_lv) + self.buildECALBarrel(calo_lv, geom) self.buildECALEndCaps(calo_lv, geom) @@ -99,7 +143,7 @@ def buildECALBarrel(self, main_lv, geom): theta = j * ang ModPosition = [ Q('0mm'), - Q('0mm'), self.BarrelRmin + 0.5 * self.caloThickness + Q('0mm'), self.BarrelRmin + 0.5 * self.caloThickness + 0.5*self.AlPlateThick ] ModPositionNew = ltools.rotation( axisy, theta, ModPosition @@ -122,20 +166,13 @@ def buildECALBarrel(self, main_lv, geom): volume=emcalo_module_lv, pos=ECAL_position, rot=ECAL_rotation) + main_lv.placements.append(ECAL_place.name) - ################################################ - def buildECALEndCaps(self, main_lv, geom): - # ENDCAPs - # there are two endcaps which are 23 cm thick, roughly 2m outer radius, - # 0.208m inner radius and divided into 32 modules - # which run vertically, and curve 90degrees at the end to be read out - # this is nontrivial to model and will take some work and improvements - # to gegede - # just model as a disk with a hole - # segmentation is the same as for the barrel modules + # Real ENDCAP as 32 modules of different length and widht + # curved at both ends by 90 degrees if self.get_builder("SANDECALENDCAP") == None: print("SANDECALENDCAP builder not found") @@ -144,32 +181,32 @@ def buildECALEndCaps(self, main_lv, geom): emcalo_endcap_builder = self.get_builder("SANDECALENDCAP") emcalo_endcap_lv = emcalo_endcap_builder.get_volume() - for side in ['L', 'R']: - - pos = [Q('0m'), Q('0m'), Q('0m')] - pos[2] = self.EndcapZ + self.caloThickness / 2.0 - if side == 'L': - pos[2] = -pos[2] - ECAL_end_rotation = geom.structure.Rotation( - 'ECAL_end_rotation' + '_' + str(side), Q('0deg'), - Q('180deg'), Q('0deg')) - - else: - ECAL_end_rotation = geom.structure.Rotation( - 'ECAL_end_rotation' + '_' + str(side), Q('0deg'), - Q('0deg'), Q('0deg')) - - ECAL_end_position = geom.structure.Position( - 'ECAL_end_position' + '_' + str(side), pos[0], pos[1], pos[2]) - - print(("Building Kloe ECAL Endcap module " + str(side))) # keep compatibility with Python3 pylint: disable=superfluous-parens - - ######################################################################################## - ECAL_end_place = geom.structure.Placement("ECAL_end_pla" + '_' + - str(side), - volume=emcalo_endcap_lv, - pos=ECAL_end_position, - rot=ECAL_end_rotation) - - main_lv.placements.append(ECAL_end_place.name) - ######################################################################################## + pos = [Q('0m'), Q('0m'), Q('0m')] + pos[2] = -(self.EndcapZ + (self.caloThickness + self.ECCurvRad + self.ECStraight) / 2.0) + + ECAL_endA_rotation = geom.structure.Rotation( + 'ECAL_endA_rotation', Q('0deg'), Q('180deg'), Q('0deg')) + + ECAL_endA_position = geom.structure.Position( + 'ECAL_endA_position', pos[0], pos[1], pos[2]) + + ECAL_endB_rotation = geom.structure.Rotation( + 'ECAL_endB_rotation', Q('0deg'), Q('0deg'), Q('0deg')) + + ECAL_endB_position = geom.structure.Position( + 'ECAL_endB_position', pos[0], pos[1], -pos[2]) + + print(("Building Kloe ECAL Endcap")) # keep compatibility with Python3 pylint: disable=superfluous-parens + + ECAL_endA_place = geom.structure.Placement("ECAL_endA_pla", + volume=emcalo_endcap_lv, + pos=ECAL_endA_position, + rot=ECAL_endA_rotation) + + ECAL_endB_place = geom.structure.Placement("ECAL_endB_pla", + volume=emcalo_endcap_lv, + pos=ECAL_endB_position, + rot=ECAL_endB_rotation) + + main_lv.placements.append(ECAL_endA_place.name) + main_lv.placements.append(ECAL_endB_place.name) \ No newline at end of file diff --git a/setup.py b/setup.py index 26473d0..57e4c1a 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ install_requires = [ "gegede >= 0.8.0", "pint >= 0.5.1", # for units - "lxml >= 3.3.5", # for GDML export], + "lxml >= 3.3.5", # for GDML export ], )