Skip to content
Snippets Groups Projects
PolyhedraEndcapCalorimeter2_geo.cpp 4.85 KiB
Newer Older
  • Learn to ignore specific revisions
  • Whitney Armstrong's avatar
    Whitney Armstrong committed
    //==========================================================================
    //  AIDA Detector description implementation
    //--------------------------------------------------------------------------
    // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
    // All rights reserved.
    //
    // For the licensing terms see $DD4hepINSTALL/LICENSE.
    // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
    //
    // Author     : M.Frank
    //
    //==========================================================================
    //
    // Modified for TOPSiDE detector
    //
    //==========================================================================
    #include "DD4hep/DetFactoryHelper.h"
    #include "XML/Layering.h"
    
    using namespace std;
    using namespace dd4hep;
    using namespace dd4hep::detail;
    
    static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens) {
        xml_det_t x_det = e;
        xml_dim_t dim = x_det.dimensions();
        int det_id = x_det.id();
        bool reflect = x_det.reflect(true);
        string det_name = x_det.nameStr();
        Material air = description.air();
        int numsides = dim.numsides();
        double rmin = dim.rmin();
        double rmax = dim.rmax() * std::cos(M_PI / numsides);
        double zmin = dim.zmin();
        Layering layering(x_det);
        double totalThickness = layering.totalThickness();
        Volume endcapVol("endcap", PolyhedraRegular(numsides, rmin, rmax, totalThickness), air);
        DetElement endcap("endcap", det_id);
    
        int l_num = 1;
        int layerType = 0;
        double layerZ = -totalThickness / 2;
    
        endcapVol.setAttributes(description, x_det.regionStr(), x_det.limitsStr(), x_det.visStr());
    
        for (xml_coll_t xc(x_det, _U(layer)); xc; ++xc) {
            xml_comp_t x_layer = xc;
            double l_thick = layering.layer(l_num - 1)->thickness();
            string l_name = _toString(layerType, "layer%d");
            int l_repeat = x_layer.repeat();
            Volume l_vol(l_name, PolyhedraRegular(numsides, rmin, rmax, l_thick), air);
            vector<PlacedVolume> sensitives;
    
            int s_num = 1;
            double sliceZ = -l_thick / 2;
            for (xml_coll_t xs(x_layer, _U(slice)); xs; ++xs) {
                xml_comp_t x_slice = xs;
                string s_name = _toString(s_num, "slice%d");
                double s_thick = x_slice.thickness();
                Material s_mat = description.material(x_slice.materialStr());
                Volume s_vol(s_name, PolyhedraRegular(numsides, rmin, rmax, s_thick), s_mat);
    
                s_vol.setVisAttributes(description.visAttributes(x_slice.visStr()));
                sliceZ += s_thick / 2;
                PlacedVolume s_phv = l_vol.placeVolume(s_vol, Position(0, 0, sliceZ));
                s_phv.addPhysVolID("slice", s_num);
                if (x_slice.isSensitive()) {
                    sens.setType("calorimeter");
                    s_vol.setSensitiveDetector(sens);
                    sensitives.push_back(s_phv);
                }
                sliceZ += s_thick / 2;
                s_num++;
            }
            l_vol.setVisAttributes(description.visAttributes(x_layer.visStr()));
            if (l_repeat <= 0) throw std::runtime_error(x_det.nameStr() + "> Invalid repeat value");
            for (int j = 0; j < l_repeat; ++j) {
                string phys_lay = _toString(l_num, "layer%d");
                layerZ += l_thick / 2;
                DetElement layer_elt(endcap, phys_lay, l_num);
                PlacedVolume pv = endcapVol.placeVolume(l_vol, Position(0, 0, layerZ));
                pv.addPhysVolID("layer", l_num);
                layer_elt.setPlacement(pv);
                for (size_t ic = 0; ic < sensitives.size(); ++ic) {
                    PlacedVolume sens_pv = sensitives[ic];
                    DetElement comp_elt(layer_elt, sens_pv.volume().name(), l_num);
                    comp_elt.setPlacement(sens_pv);
                }
                layerZ += l_thick / 2;
                ++l_num;
            }
            ++layerType;
        }
    
        double z_pos = zmin + totalThickness / 2;
        PlacedVolume pv;
        // Reflect it.
        Assembly assembly(det_name);
        DetElement endcapAssyDE(det_name, det_id);
        Volume motherVol = description.pickMotherVolume(endcapAssyDE);
        if (reflect) {
            pv = assembly.placeVolume(endcapVol,
                                      Transform3D(RotationZYX(M_PI / numsides, M_PI, 0), Position(0, 0, -z_pos)));
            pv.addPhysVolID("barrel", 2);
            Ref_t(endcap)->SetName((det_name + "_backward").c_str());
            endcap.setPlacement(pv);
        } else {
            pv = assembly.placeVolume(endcapVol,
                                      Transform3D(RotationZYX(M_PI / numsides, 0, 0), Position(0, 0, z_pos)));
            pv.addPhysVolID("barrel", 1);
            Ref_t(endcap)->SetName((det_name + "_forward").c_str());
            endcap.setPlacement(pv);
        }
        endcapAssyDE.add(endcap);
        pv = motherVol.placeVolume(assembly);
        pv.addPhysVolID("system", det_id);
        endcapAssyDE.setPlacement(pv);
        return endcapAssyDE;
    }
    
    // clang-format off
    DECLARE_DETELEMENT(refdet_PolyhedraEndcapCalorimeter2, create_detector)