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