141):
142 """
143 Create geometry configuration with specified parameters.
144
145 Args:
146 DecayVolumeMedium: Medium in decay volume ("helium" or "vacuums"), default: "helium"
147 Yheight: Height of vacuum tank in meters, default: 6.0
148 strawDesign: Straw tube design (4=aluminium frame, 10=steel frame), default: 10
149 muShieldGeo: Muon shield geometry file (for experts), default: None
150 shieldName: Name of shield configuration ("warm_opt" or "New_HA_Design"), default: "New_HA_Design"
151 nuTargetPassive: Target type (0=with active layers, 1=only passive), default: 1
152 SND: Enable SND detector, default: True
153 SND_design: SND design options (list of design numbers), default: [2]
154 TARGET_YAML: Path to target YAML configuration file, default: "$FAIRSHIP/geometry/target_config.yaml"
155
156 Returns:
157 Config: Geometry configuration object
158 """
159
160 if SND_design is None:
161 SND_design = [2]
162 if TARGET_YAML is None:
163 TARGET_YAML = os.path.expandvars("$FAIRSHIP/geometry/target_config.yaml")
164
165
166 c = Config()
167 c.DecayVolumeMedium = DecayVolumeMedium
168 c.SND = SND
169
170 if not isinstance(SND_design, list):
171 SND_design = [SND_design]
172 c.SND_design = SND_design
173 c.target_yaml = TARGET_YAML
174 print("Info: Target using configuration:", c.target_yaml)
175
176 if not shieldName:
177 raise ValueError("shieldName must not be empty!")
178
179 c.shieldName = shieldName
180 c.SC_mag = shield_db[shieldName]["hybrid"]
181
182
183 c.Yheight = Yheight * u.m
184 extraVesselLength = 10 * u.m
185 windowBulge = 25 * u.cm
186 c.strawDesign = strawDesign
187 c.magnetDesign = 4
188
189 c.cave = AttrDict()
190 c.cave.floorHeightMuonShield = 5 * u.m
191 c.cave.floorHeightTankA = 4.2 * u.m
192 if strawDesign == 10:
193 c.cave.floorHeightMuonShield = c.cave.floorHeightTankA
194 c.cave.floorHeightTankB = 2 * u.m
195
196 with open(c.target_yaml)
as file:
197 targetconfig = yaml.safe_load(file)
198 c.target = AttrDict(targetconfig["target"])
199
200 c.target.slices_length = []
201 c.target.slices_gap = []
202 c.target.slices_material = []
203
204 for i in range(c.target.Nplates):
205 for j in range(c.target.N[i]):
206 if len(c.target.L) == 1:
207 c.target.slices_length.append(c.target.L[0])
208 else:
209 c.target.slices_length.append(c.target.L[i])
210 if len(c.target.G) == 1:
211 c.target.slices_gap.append(c.target.G[0])
212 else:
213 c.target.slices_gap.append(c.target.G[i])
214 if len(c.target.M) == 1:
215 c.target.slices_material.append(c.target.M[0])
216 else:
217 c.target.slices_material.append(c.target.M[i])
218
219 c.target.slices_gap[c.target.nS - 1] = 0
220 print(c.target.slices_material, c.target.slices_length, c.target.slices_gap)
221
222 target_length = 0
223 for width, gap in zip(c.target.slices_length, c.target.slices_gap):
224 target_length += width + gap
225 c.target.length = target_length
226
227
228 c.target.z0 = 0
229 c.target.z = c.target.z0 + c.target.length / 2.0
230
231 c.hadronAbsorber = AttrDict()
232
233 c.hadronAbsorber.z = (
234 c.target.z0
235 + c.target.length
236 + 96.1 * u.mm
237 + 250 * u.mm
238 + 207.5 * u.mm
239 - 10 * u.cm
240 )
241
242
243 c.muShield = AttrDict()
244
245 c.muShield.z = c.hadronAbsorber.z
246
247 params = shield_db[shieldName]["params"]
248 c.muShield.params = params
249
250
251 c.muShield.length = sum(line[0] + line[1] * 2 for line in params)
252 c.muShield.nMagnets = len(params)
253
254 c.muShield.Zgap = []
255 c.muShield.half_length = []
256 c.muShield.Entrance = []
257
258 for line in params:
259 c.muShield.Zgap.append(line[0])
260 c.muShield.half_length.append(line[1])
261
262
263 for i in range(len(c.muShield.Zgap)):
264 if i == 0:
265
266 c.muShield.Entrance.append(c.muShield.z + c.muShield.Zgap[i])
267 else:
268
269 c.muShield.Entrance.append(
270 c.muShield.Entrance[i - 1] + c.muShield.half_length[i - 1] * 2 + c.muShield.Zgap[i]
271 )
272
273 c.muShield.params = [item for sublist in params for item in sublist]
274
275 c.decayVolume = AttrDict()
276
277
278 c.decayVolume.length = 50 * u.m
279
280
281
282 c.z = 89.57 * u.m
283 c.decayVolume.z = c.z - 31.450 * u.m
284 c.decayVolume.z0 = c.decayVolume.z - c.decayVolume.length / 2.0
285
286 c.chambers = AttrDict()
287 magnetIncrease = 100.0 * u.cm
288
289 if strawDesign != 4 and strawDesign != 10:
290 raise ValueError(f"straw design {strawDesign} is not supported, use strawDesign = 4 or 10")
291 else:
292 c.chambers.Tub1length = 2.5 * u.m
293 c.chambers.Tub2length = 17.68 * u.m + extraVesselLength / 2.0
294 c.chambers.Tub3length = 0.8 * u.m
295 c.chambers.Tub4length = 2.0 * u.m + magnetIncrease / 2.0
296 c.chambers.Tub5length = 0.8 * u.m
297 c.chambers.Tub6length = 0.1 * u.m + windowBulge / 2.0
298 c.chambers.Rmin = 245.0 * u.cm
299 c.chambers.Rmax = 250.0 * u.cm
300
301 c.xMax = 2 * u.m
302 TrGap = 2 * u.m
303 TrMagGap = 3.5 * u.m
304
305 z4 = c.z + TrMagGap + TrGap
306 c.TrackStation4 = AttrDict(z=z4)
307 z3 = c.z + TrMagGap
308 c.TrackStation3 = AttrDict(z=z3)
309 z2 = c.z - TrMagGap
310 c.TrackStation2 = AttrDict(z=z2)
311 z1 = c.z - TrMagGap - TrGap
312 c.TrackStation1 = AttrDict(z=z1)
313
314
315 c.Chamber1 = AttrDict(z=z4 - 4666.0 * u.cm - magnetIncrease - extraVesselLength)
316 c.Chamber6 = AttrDict(z=z4 + 30.0 * u.cm + windowBulge / 2.0)
317
318 c.Bfield = AttrDict()
319 c.Bfield.z = c.z
320 c.Bfield.max = 0
321 c.Bfield.y = c.Yheight
322 c.Bfield.x = 2.4 * u.m
323 c.Bfield.fieldMap = "files/MainSpectrometerField.root"
324 if c.magnetDesign > 3:
325 c.Bfield.YokeWidth = 0.8 * u.m
326 c.Bfield.YokeDepth = 1.4 * u.m
327 c.Bfield.CoilThick = 25.0 * u.cm
328 c.Bfield.x = 2.2 * u.m
329 c.Bfield.y = 3.5 * u.m
330
331
332 c.TimeDet = AttrDict()
333 c.TimeDet.dzBarRow = 1.2 * u.cm
334 c.TimeDet.dzBarCol = 2.4 * u.cm
335 c.TimeDet.zBar = 1 * u.cm
336 c.TimeDet.DZ = (c.TimeDet.dzBarRow + c.TimeDet.dzBarCol + c.TimeDet.zBar) / 2
337 c.TimeDet.DX = 225 * u.cm
338 c.TimeDet.DY = 325 * u.cm
339 c.TimeDet.z = (
340 37.800 * u.m - c.TimeDet.dzBarRow * 3 / 2 + c.decayVolume.z
341 )
342
343 c.HcalOption = -1
344 c.EcalOption = 2
345
346 c.SplitCal = AttrDict()
347 c.SplitCal.ZStart = 38.450 * u.m + c.decayVolume.z
348 c.SplitCal.XMax = 4 * u.m / 2
349 c.SplitCal.YMax = 6 * u.m / 2
350 c.SplitCal.Empty = 0 * u.cm
351 c.SplitCal.BigGap = 100 * u.cm
352 c.SplitCal.ActiveECALThickness = 0.56 * u.cm
353 c.SplitCal.FilterECALThickness = 0.28 * u.cm
354 c.SplitCal.FilterECALThickness_first = 0.28 * u.cm
355 c.SplitCal.ActiveHCALThickness = 90 * u.cm
356 c.SplitCal.FilterHCALThickness = 90 * u.cm
357 c.SplitCal.nECALSamplings = 50
358 c.SplitCal.nHCALSamplings = 0
359 c.SplitCal.ActiveHCAL = 0
360 c.SplitCal.FilterECALMaterial = 3
361 c.SplitCal.FilterHCALMaterial = 2
362 c.SplitCal.ActiveECALMaterial = 1
363 c.SplitCal.ActiveHCALMaterial = 1
364 c.SplitCal.ActiveECAL_gas_Thickness = 1.12 * u.cm
365 c.SplitCal.num_precision_layers = 1
366 c.SplitCal.first_precision_layer = 6
367 c.SplitCal.second_precision_layer = 10
368 c.SplitCal.third_precision_layer = 13
369 c.SplitCal.ActiveECAL_gas_gap = 10 * u.cm
370 c.SplitCal.NModulesInX = 2
371 c.SplitCal.NModulesInY = 3
372 c.SplitCal.NStripsPerModule = 50
373 c.SplitCal.StripHalfWidth = c.SplitCal.XMax / (c.SplitCal.NStripsPerModule * c.SplitCal.NModulesInX)
374 c.SplitCal.StripHalfLength = c.SplitCal.YMax / c.SplitCal.NModulesInY
375 c.SplitCal.SplitCalThickness = (
376 (c.SplitCal.FilterECALThickness_first - c.SplitCal.FilterECALThickness)
377 + (c.SplitCal.FilterECALThickness + c.SplitCal.ActiveECALThickness) * c.SplitCal.nECALSamplings
378 + c.SplitCal.BigGap
379 )
380
381 c.MuonStation0 = AttrDict(z=c.SplitCal.ZStart + 10 * u.cm + c.SplitCal.SplitCalThickness)
382
383 c.MuonStation1 = AttrDict(z=c.MuonStation0.z + 1 * u.m)
384 c.MuonStation2 = AttrDict(z=c.MuonStation0.z + 2 * u.m)
385 c.MuonStation3 = AttrDict(z=c.MuonStation0.z + 3 * u.m)
386
387 c.MuonFilter0 = AttrDict(z=c.MuonStation0.z + 50.0 * u.cm)
388 c.MuonFilter1 = AttrDict(z=c.MuonStation0.z + 150.0 * u.cm)
389 c.MuonFilter2 = AttrDict(z=c.MuonStation0.z + 250.0 * u.cm)
390
391 c.Muon = AttrDict()
392 c.Muon.XMax = 250.0 * u.cm
393 c.Muon.YMax = 325.0 * u.cm
394
395 c.Muon.ActiveThickness = 0.5 * u.cm
396 c.Muon.FilterThickness = 30.0 * u.cm
397
398 c.hadronAbsorber.WithConstField = shield_db[shieldName]["WithConstField"]
399 c.muShield.WithConstField = shield_db[shieldName]["WithConstField"]
400
401
402 c.strawtubesDigi = AttrDict()
403 c.strawtubesDigi.v_drift = 1.0 / (30 * u.ns / u.mm)
404 c.strawtubesDigi.sigma_spatial = 0.012 * u.cm
405
406
407 c.tauMudet = AttrDict()
408 c.tauMudet.Ztot = 3 * u.m
409 c.tauMudet.zMudetC = c.muShield.z + c.muShield.length / 2.0 - c.tauMudet.Ztot / 2.0 - 70 * u.cm
410
411
412
413
414
415 c.UpstreamTagger = AttrDict()
416 c.UpstreamTagger.BoxX = 4.4 * u.m
417 c.UpstreamTagger.BoxY = 6.4 * u.m
418 c.UpstreamTagger.BoxZ = 16.0 * u.cm
419 c.UpstreamTagger.Z_Position = -25.400 * u.m + c.decayVolume.z
420 c.UpstreamTagger.PositionResolution = 1.0 * u.cm
421 c.UpstreamTagger.TimeResolution = 0.3
422
423
424 c.muShieldGeo = muShieldGeo
425 c.nuTargetPassive = nuTargetPassive
426
427 return c
int open(const char *, int)
Opens a file descriptor.