Create a parameter object from gearbox.
482 {
483 TOPGeometry* geo = new TOPGeometry("TOPGeometry");
484
485
486
487 GearDir pmtParams(content, "PMTs/PMT");
488 TOPGeoPMT pmt(pmtParams.getLength("ModuleXSize"),
489 pmtParams.getLength("ModuleYSize"),
490 pmtParams.getLength("ModuleZSize") +
491 pmtParams.getLength("WindowThickness") +
492 pmtParams.getLength("BottomThickness"));
493 pmt.setWallThickness(pmtParams.getLength("ModuleWall"));
494 pmt.setWallMaterial(pmtParams.getString("wallMaterial"));
495 pmt.setFillMaterial(pmtParams.getString("fillMaterial"));
496 pmt.setSensVolume(pmtParams.getLength("SensXSize"),
497 pmtParams.getLength("SensYSize"),
498 pmtParams.getLength("SensThickness"),
499 pmtParams.getString("sensMaterial"));
500 pmt.setNumPixels(pmtParams.getInt("PadXNum"),
501 pmtParams.getInt("PadYNum"));
502 pmt.setWindow(pmtParams.getLength("WindowThickness"),
503 pmtParams.getString("winMaterial"));
504 pmt.setBottom(pmtParams.getLength("BottomThickness"),
505 pmtParams.getString("botMaterial"));
506
507 auto& materials = geometry::Materials::getInstance();
508 GearDir reflEdgeSurfParams(pmtParams, "reflectiveEdge/Surface");
509 pmt.setReflEdge(pmtParams.getLength("reflectiveEdge/width"),
510 pmtParams.getLength("reflectiveEdge/thickness"),
511 materials.createOpticalSurfaceConfig(reflEdgeSurfParams));
512
513 GearDir arrayParams(content, "PMTs");
514 TOPGeoPMTArray pmtArray(arrayParams.getInt("nPMTx"),
515 arrayParams.getInt("nPMTy"),
516 arrayParams.getLength("Xgap"),
517 arrayParams.getLength("Ygap"),
518 arrayParams.getString("stackMaterial"),
519 pmt);
520 pmtArray.setSiliconeCookie(arrayParams.getLength("siliconeCookie/thickness"),
521 arrayParams.getString("siliconeCookie/material"));
522 pmtArray.setWavelengthFilter(arrayParams.getLength("wavelengthFilter/thickness"),
523 arrayParams.getString("wavelengthFilter/material"));
524 pmtArray.setAirGap(arrayParams.getLength("airGap", 0));
525 double decoupledFraction = arrayParams.getDouble("decoupledFraction", 0);
526
527
528
529 GearDir moduleParams(content, "Modules");
530 GearDir glueParams(moduleParams, "Glue");
531 int numModules = moduleParams.getNumberNodes("Module");
532 for (int slotID = 1; slotID <= numModules; slotID++) {
533 std::string gearName = "Module[@slotID='" + std::to_string(slotID) + "']";
534 GearDir slotParams(moduleParams, gearName);
535 TOPGeoModule module(slotID,
536 slotParams.getLength("Radius"),
537 slotParams.getAngle("Phi"),
538 slotParams.getLength("BackwardZ"));
539 int cNumber = slotParams.getInt("ConstructionNumber");
540 module.setModuleCNumber(cNumber);
541 module.setName(addNumber(module.getName(), cNumber));
542
543 auto prism = createPrism(content, slotParams.getString("Prism"));
544 prism.setName(addNumber(prism.getName(), cNumber));
545 module.setPrism(prism);
546
547 auto barSegment2 = createBarSegment(content, slotParams.getString("BarSegment2"));
548 barSegment2.setName(addNumber(barSegment2.getName() + "2-", cNumber));
549 barSegment2.setGlue(glueParams.getLength("Thicknes1"),
550 glueParams.getString("GlueMaterial"));
551 module.setBarSegment2(barSegment2);
552
553 auto barSegment1 = createBarSegment(content, slotParams.getString("BarSegment1"));
554 barSegment1.setName(addNumber(barSegment1.getName() + "1-", cNumber));
555 barSegment1.setGlue(glueParams.getLength("Thicknes2"),
556 glueParams.getString("GlueMaterial"));
557 module.setBarSegment1(barSegment1);
558
559 auto mirror = createMirrorSegment(content, slotParams.getString("Mirror"));
560 mirror.setName(addNumber(mirror.getName(), cNumber));
561 mirror.setGlue(glueParams.getLength("Thicknes3"),
562 glueParams.getString("GlueMaterial"));
563 module.setMirrorSegment(mirror);
564
565 module.setPMTArray(pmtArray);
566 if (decoupledFraction > 0) module.generateDecoupledPMTs(decoupledFraction);
567
568 geo->appendModule(module);
569 }
570
571
572
573 GearDir displacedGeometry(content, "DisplacedGeometry");
574 if (displacedGeometry) {
575 if (displacedGeometry.getInt("SwitchON") != 0) {
576 B2WARNING("TOP: displaced geometry is activated");
577 for (const GearDir& slot : displacedGeometry.getNodes("Slot")) {
578 int moduleID = slot.getInt("@ID");
579 if (!geo->isModuleIDValid(moduleID)) {
580 B2WARNING("TOPGeometryPar: DisplacedGeometry.xml: invalid moduleID."
581 << LogVar("moduleID", moduleID));
582 continue;
583 }
584 TOPGeoModuleDisplacement moduleDispl(slot.getLength("x"),
585 slot.getLength("y"),
586 slot.getLength("z"),
587 slot.getAngle("alpha"),
588 slot.getAngle("beta"),
589 slot.getAngle("gamma"));
590 auto& module = const_cast<TOPGeoModule&>(geo->getModule(moduleID));
591 module.setModuleDisplacement(moduleDispl);
592 }
593 }
594 }
595
596
597
598 GearDir displacedPMTArrays(content, "DisplacedPMTArrays");
599 if (displacedPMTArrays) {
600 if (displacedPMTArrays.getInt("SwitchON") != 0) {
601 B2WARNING("TOP: displaced PMT arrays are activated");
602 for (const GearDir& slot : displacedPMTArrays.getNodes("Slot")) {
603 int moduleID = slot.getInt("@ID");
604 if (!geo->isModuleIDValid(moduleID)) {
605 B2WARNING("TOPGeometryPar: DisplacedPMTArrays.xml: invalid moduleID."
606 << LogVar("moduleID", moduleID));
607 continue;
608 }
609 TOPGeoPMTArrayDisplacement arrayDispl(slot.getLength("x"),
610 slot.getLength("y"),
611 slot.getAngle("alpha"));
612 auto& module = const_cast<TOPGeoModule&>(geo->getModule(moduleID));
613 module.setPMTArrayDisplacement(arrayDispl);
614 }
615 }
616 }
617
618
619
620 GearDir brokenGlues(content, "BrokenGlues");
621 if (brokenGlues) {
622 if (brokenGlues.getInt("SwitchON") != 0) {
623 auto material = brokenGlues.getString("material");
624 for (const GearDir& slot : brokenGlues.getNodes("Slot")) {
625 int moduleID = slot.getInt("@ID");
626 if (!geo->isModuleIDValid(moduleID)) {
627 B2WARNING("TOPGeometryPar: BrokenGlues.xml: invalid moduleID."
628 << LogVar("moduleID", moduleID));
629 continue;
630 }
631 auto& module = const_cast<TOPGeoModule&>(geo->getModule(moduleID));
632 for (const GearDir& glue : slot.getNodes("Glue")) {
633 int glueID = glue.getInt("@ID");
634 double fraction = glue.getDouble("fraction");
635 if (fraction <= 0) continue;
636 double angle = glue.getAngle("angle");
637 module.setBrokenGlue(glueID, fraction, angle, material);
638 }
639 }
640 }
641 }
642
643
644
645 GearDir peelOff(content, "PeelOffCookies");
646 if (peelOff) {
647 if (peelOff.getInt("SwitchON") != 0) {
648 auto material = peelOff.getString("material");
649 double thickness = peelOff.getLength("thickness");
650 for (const GearDir& slot : peelOff.getNodes("Slot")) {
651 int moduleID = slot.getInt("@ID");
652 if (!geo->isModuleIDValid(moduleID)) {
653 B2WARNING("TOPGeometryPar: PeelOffCookiess.xml: invalid moduleID."
654 << LogVar("moduleID", moduleID));
655 continue;
656 }
657 auto& module = const_cast<TOPGeoModule&>(geo->getModule(moduleID));
658 module.setPeelOffRegions(thickness, material);
659 for (const GearDir& region : slot.getNodes("Region")) {
660 int regionID = region.getInt("@ID");
661 double fraction = region.getDouble("fraction");
662 if (fraction <= 0) continue;
663 double angle = region.getAngle("angle");
664 module.appendPeelOffRegion(regionID, fraction, angle);
665 }
666 }
667 }
668 }
669
670
671
672 GearDir feParams(content, "FrontEndGeo");
673 GearDir fbParams(feParams, "FrontBoard");
674 TOPGeoFrontEnd frontEnd;
675 frontEnd.setFrontBoard(fbParams.getLength("width"),
676 fbParams.getLength("height"),
677 fbParams.getLength("thickness"),
678 fbParams.getLength("gap"),
679 fbParams.getLength("y"),
680 fbParams.getString("material"));
681 GearDir hvParams(feParams, "HVBoard");
682 frontEnd.setHVBoard(hvParams.getLength("width"),
683 hvParams.getLength("length"),
684 hvParams.getLength("thickness"),
685 hvParams.getLength("gap"),
686 hvParams.getLength("y"),
687 hvParams.getString("material"));
688 GearDir bsParams(feParams, "BoardStack");
689 frontEnd.setBoardStack(bsParams.getLength("width"),
690 bsParams.getLength("height"),
691 bsParams.getLength("length"),
692 bsParams.getLength("gap"),
693 bsParams.getLength("y"),
694 bsParams.getString("material"),
695 bsParams.getLength("spacerWidth"),
696 bsParams.getString("spacerMaterial"));
697 geo->setFrontEnd(frontEnd, feParams.getInt("numBoardStacks"));
698
699
700
701 GearDir qbbParams(content, "QBB");
702 TOPGeoQBB qbb(qbbParams.getLength("width"),
703 qbbParams.getLength("length"),
704 qbbParams.getLength("prismPosition"),
705 qbbParams.getString("material"));
706
707 GearDir outerPanelParams(qbbParams, "outerPanel");
708 TOPGeoHoneycombPanel outerPanel(outerPanelParams.getLength("width"),
709 outerPanelParams.getLength("length"),
710 outerPanelParams.getLength("minThickness"),
711 outerPanelParams.getLength("maxThickness"),
712 outerPanelParams.getLength("radius"),
713 outerPanelParams.getLength("edgeWidth"),
714 outerPanelParams.getLength("y"),
715 outerPanelParams.getInt("N"),
716 outerPanelParams.getString("material"),
717 outerPanelParams.getString("edgeMaterial"),
718 "TOPOuterHoneycombPanel");
719 qbb.setOuterPanel(outerPanel);
720
721 GearDir innerPanelParams(qbbParams, "innerPanel");
722 TOPGeoHoneycombPanel innerPanel(innerPanelParams.getLength("width"),
723 innerPanelParams.getLength("length"),
724 innerPanelParams.getLength("minThickness"),
725 innerPanelParams.getLength("maxThickness"),
726 innerPanelParams.getLength("radius"),
727 innerPanelParams.getLength("edgeWidth"),
728 innerPanelParams.getLength("y"),
729 innerPanelParams.getInt("N"),
730 innerPanelParams.getString("material"),
731 innerPanelParams.getString("edgeMaterial"),
732 "TOPInnerHoneycombPanel");
733 qbb.setInnerPanel(innerPanel);
734
735 GearDir sideRailsParams(qbbParams, "sideRails");
736 TOPGeoSideRails sideRails(sideRailsParams.getLength("thickness"),
737 sideRailsParams.getLength("reducedThickness"),
738 sideRailsParams.getLength("height"),
739 sideRailsParams.getString("material"));
740 qbb.setSideRails(sideRails);
741
742 GearDir prismEnclParams(qbbParams, "prismEnclosure");
743 TOPGeoPrismEnclosure prismEncl(prismEnclParams.getLength("length"),
744 prismEnclParams.getLength("height"),
745 prismEnclParams.getAngle("angle"),
746 prismEnclParams.getLength("bottomThickness"),
747 prismEnclParams.getLength("sideThickness"),
748 prismEnclParams.getLength("backThickness"),
749 prismEnclParams.getLength("frontThickness"),
750 prismEnclParams.getLength("extensionThickness"),
751 prismEnclParams.getString("material"));
752 qbb.setPrismEnclosure(prismEncl);
753
754 GearDir endPlateParams(qbbParams, "forwardEndPlate");
755 TOPGeoEndPlate endPlate(endPlateParams.getLength("thickness"),
756 endPlateParams.getLength("height"),
757 endPlateParams.getString("material"),
758 "TOPForwardEndPlate");
759 qbb.setEndPlate(endPlate);
760
761 GearDir coldPlateParams(qbbParams, "coldPlate");
762 TOPGeoColdPlate coldPlate(coldPlateParams.getLength("baseThickness"),
763 coldPlateParams.getString("baseMaterial"),
764 coldPlateParams.getLength("coolThickness"),
765 coldPlateParams.getLength("coolWidth"),
766 coldPlateParams.getString("coolMaterial"));
767 qbb.setColdPlate(coldPlate);
768
769 geo->setQBB(qbb);
770
771
772
773 GearDir qeParams(content, "QE");
774 std::vector<float> qeData;
775 for (const GearDir& Qeffi : qeParams.getNodes("Qeffi")) {
776 qeData.push_back(Qeffi.getDouble(""));
777 }
778 TOPNominalQE nominalQE(qeParams.getLength("LambdaFirst") / Unit::nm,
779 qeParams.getLength("LambdaStep") / Unit::nm,
780 qeParams.getDouble("ColEffi"),
781 qeData);
782 geo->setNominalQE(nominalQE);
783
784
785
786 GearDir ttsParams(content, "PMTs/TTS");
787 TOPNominalTTS nominalTTS("TOPNominalTTS");
788 for (const GearDir& Gauss : ttsParams.getNodes("Gauss")) {
789 nominalTTS.appendGaussian(Gauss.getDouble("fraction"),
790 Gauss.getTime("mean"),
791 Gauss.getTime("sigma"));
792 }
793 nominalTTS.normalize();
794 geo->setNominalTTS(nominalTTS);
795
796
797
798 GearDir pmtTTSParams(content, "TTSofPMTs");
799 for (const GearDir& ttsPar : pmtTTSParams.getNodes("TTSpar")) {
800 int type = ttsPar.getInt("type");
801 double tuneFactor = ttsPar.getDouble("PDEtuneFactor");
802 TOPNominalTTS tts("TTS of " + ttsPar.getString("@name") + " PMT");
803 tts.setPMTType(type);
804 for (const GearDir& Gauss : ttsPar.getNodes("Gauss")) {
805 tts.appendGaussian(Gauss.getDouble("fraction"),
806 Gauss.getTime("mean"),
807 Gauss.getTime("sigma"));
808 }
809 tts.normalize();
810 geo->appendTTS(tts);
811 geo->appendPDETuningFactor(type, tuneFactor);
812 }
813
814
815
816 GearDir tdcParams(content, "TDC");
817 if (tdcParams) {
818 TOPNominalTDC nominalTDC(tdcParams.getInt("numWindows"),
819 tdcParams.getInt("subBits"),
820 tdcParams.getTime("syncTimeBase"),
821 tdcParams.getInt("numofBunches"),
822 tdcParams.getTime("offset"),
823 tdcParams.getTime("pileupTime"),
824 tdcParams.getTime("doubleHitResolution"),
825 tdcParams.getTime("timeJitter"),
826 tdcParams.getDouble("efficiency"));
827 nominalTDC.setADCBits(tdcParams.getInt("adcBits"));
828 nominalTDC.setAveragePedestal(tdcParams.getInt("averagePedestal"));
829 geo->setNominalTDC(nominalTDC);
830 } else {
831 TOPNominalTDC nominalTDC(pmtParams.getInt("TDCbits"),
832 pmtParams.getTime("TDCbitwidth"),
833 pmtParams.getTime("TDCoffset", 0),
834 pmtParams.getTime("TDCpileupTime", 0),
835 pmtParams.getTime("TDCdoubleHitResolution", 0),
836 pmtParams.getTime("TDCtimeJitter", 50e-3),
837 pmtParams.getDouble("TDCefficiency", 1));
838 geo->setNominalTDC(nominalTDC);
839 }
840
841
842
843 GearDir shapeParams(content, "SignalShape");
844 if (shapeParams) {
845 GearDir noiseBandwidth(shapeParams, "noiseBandwidth");
846 TOPSignalShape signalShape(shapeParams.getArray("sampleValues"),
847 geo->getNominalTDC().getSampleWidth(),
848 shapeParams.getTime("tailTimeConstant"),
849 noiseBandwidth.getDouble("pole1") / 1000,
850 noiseBandwidth.getDouble("pole2") / 1000);
851 geo->setSignalShape(signalShape);
852 }
853
854
855
856 GearDir calpulseParams(content, "CalPulseShape");
857 if (calpulseParams) {
858 GearDir noiseBandwidth(calpulseParams, "noiseBandwidth");
859 TOPSignalShape shape(calpulseParams.getArray("sampleValues"),
860 geo->getNominalTDC().getSampleWidth(),
861 calpulseParams.getTime("tailTimeConstant"),
862 noiseBandwidth.getDouble("pole1") / 1000,
863 noiseBandwidth.getDouble("pole2") / 1000);
864 geo->setCalPulseShape(shape);
865 }
866
867
868
869 std::string materialNode = "Materials/Material[@name='TOPWavelengthFilterIHU340']";
870 GearDir filterMaterial(content, materialNode);
871 if (!filterMaterial) {
872 B2FATAL("TOPGeometry: " << materialNode << " not found");
873 }
874 GearDir property(filterMaterial, "Property[@name='ABSLENGTH']");
875 if (!property) {
876 B2FATAL("TOPGeometry: " << materialNode << ", Property ABSLENGTH not found");
877 }
878 int numNodes = property.getNumberNodes("value");
879 if (numNodes > 1) {
880 double conversion = Unit::convertValue(1, property.getString("@unit", "GeV"));
881 std::vector<double> energies;
882 std::vector<double> absLengths;
883 for (int i = 0; i < numNodes; i++) {
884 GearDir value(property, "value", i + 1);
885 energies.push_back(value.getDouble("@energy") * conversion / Unit::eV);
886 absLengths.push_back(value.getDouble() * Unit::mm);
887 }
888 TSpline3 spline("absLen", energies.data(), absLengths.data(), energies.size());
889 double lambdaFirst = c_hc / energies.back();
890 double lambdaLast = c_hc / energies[0];
891 double lambdaStep = 5;
892 int numSteps = (lambdaLast - lambdaFirst) / lambdaStep + 1;
893 const double filterThickness = arrayParams.getLength("wavelengthFilter/thickness");
894 std::vector<float> bulkTransmittances;
895 for (int i = 0; i < numSteps; i++) {
896 double wavelength = lambdaFirst + lambdaStep * i;
897 double energy = c_hc / wavelength;
898 double absLen = spline.Eval(energy);
899 bulkTransmittances.push_back(exp(-filterThickness / absLen));
900 }
901 TOPWavelengthFilter filter(lambdaFirst, lambdaStep, bulkTransmittances);
902 geo->setWavelengthFilter(filter);
903 } else {
904 B2FATAL("TOPGeometry: " << materialNode
905 << ", Property ABSLENGTH has less than 2 nodes");
906 }
907
908 return geo;
909 }