Na poprzedniej lekcji prawie skonstruowaliśmy nasz detektor. Ja teraz opisać jego geometrię? Można to zrobić na dwa sposoby:
- geometrią HADESową (geometria opisana plikami tekstowymi)
- geometrią ROOTową
- zaimplementować bezpośrednio w FairDetector::ConstructGeometry() (bardzo rzadko używane)
Pierwszy sposób jest zdecydowanie łatwiejszy ale zasadniczo ograniczony do najprostszych geometrii.
Geometria HADESowa
- Generalnie plik hadesowy oprócz tzw. cave (czyli "pokój" w którym jest cały detektor) wygląda następująco:
- Nazwa "bryły" detektora czyli "bryły z której jest złożony" mus mieć co najmniej 4 znaki (duże litery), w zasadzie tylko 4 pierwsze używane są przez Geanta. Jeśli mamy kilka kopii bryły to jej nazwa powinna mieć minimum 5 znaków. Dodatkowe znaki to cyfry od 1 do N elementów. Np. ToF zawiera 8 identycznych elementów/"podbrył" więc nazywa się T01S1... T01S8.
- Flaga inout (w zasadzie nie używana)
- Nazwa matki to nazwa "bryły" w której znajduje się nasza "podbryła". Jeśli mamy kilka takich "podbrył " to podajemy nazwę pierwszej np. T01S1
- Kształt opisuje kształt bryły
- Medium - czyli materiał z którego składa się bryła
- Punkty - charakterystyczne punkty opisujące bryłę
- Rozmieszczenie. Każda bryła posiada swój wewnętrzny system koordynatów. Jest to więc pozycja względem układu współrzędnych matki. Pozycja składa się z:
- trójwymiarowego wektora przesunięcia
- macierzy rotacji 3x3 (wymagana precyzja 10^-6)
- W przypadku brył które są kopiowane struktura jest nieco inna - najpierw jest nazwa, potem flaga inout, nazwa matki, wektor przesunięcia, a następnie macierz rotacji - nie ma np. medium czy rozmiarów bryły jako że kopiujemy bryłę.
Szczegółowy opis gometrii hadesowej można znaleźć tu https://www.hzdr.de/FWK/MITARB/sadovski/mdc/pslib/hadesgeom/Geometry.htm oraz https://fairroot.gsi.de/?q=node/33.
Przykładowy plik z geometrią to np. emc.geo z mpdroota który zawiera walec z powietrza:
//************************
// EMC
// basic mother volume of EMC
// version May-2010 litvin
//************************
emc1Chamber1
cave
TUBS
air
0.0 0.0 -2500.000
1450.0000 1950.
0.0 0.0 2500.000
0.0 360.0
0.000000 0.000000 0.000000
1. 0. 0. 0. 1. 0. 0. 0. 1.
//*************************************************
Ważne aby w przypadku geometrii hadesowej oprócz kształtu detektora zdefiniować materiały. Znajdują się one zwykle w pliku media.geo. Ich struktura wygląda następująco
- liczba pierwiastków w materiale, jeśli większa o 0 skład pierwiastkowy jest opisany wg masy jeśli mniejsza od 0 jest opisywany wg liczby atomów danego pierwiastka
- wagi atomowe pierwiastków
- liczby atomoœe pierwiastków
- gęstość w g/cm3
- wkład wagowy (tylko jeśli mamy więcej niż 1 pierwiastek w składzie)
- flaga czułości
- flaga pola (czy pole magnetyczne "wchodzi" w materiał)
- precyzja opliczeń
- liczba parametrów do zdefinioowana optycznych właściwości medium
przykład definicji powietrza:
air 3 14.01 16. 39.95 7. 8. 18. 1.205e-3 .78 .21 .01
0 1 20. .001
0
Więcej informacji można znaleźć na stronie: https://fairroot.gsi.de/?q=node/34.
Geometria ROOTowa
Jest to zalecany sposób dodawania geometrii bardziej złożonych detektorów. Ładowanie takich detektorów jest zdecydowanie szybsze, dodatkowo pliki geometryczne HADESa potrafią być upierdliwe (i czepiać się kolejności punktów czy pustych linii). Tutaj bazuję na pliku tutorialowym Fairroot/examples/simulation/Tutorial4/macros/Create_Tutorial4_Geometry.C:
/******************************************************************************** * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * * * * This software is distributed under the terms of the * * GNU Lesser General Public Licence (LGPL) version 3, * * copied verbatim in the file "LICENSE" * ********************************************************************************/ // in root all sizes are given in cm #include <TSystem.h> #include <TGeoManager.h> #include <TGeoVolume.h> #include <TGeoMaterial.h> #include <TGeoMedium.h> #include <TGeoPgon.h> #include <TGeoMatrix.h> #include <TGeoCompositeShape.h> #include <TFile.h> #include <TString.h> #include <TList.h> #include <TROOT.h> #include <iostream> // Name of geometry version and output file const TString geoVersion = "tutorial4"; const TString FileName = geoVersion + ".root"; const TString FileName1 = geoVersion + "_geomanager.root"; // Names of the different used materials which are used to build the modules // The materials are defined in the global media.geo file const TString KeepingVolumeMedium = "air"; const TString BoxVolumeMedium = "silicon"; // Distance of the center of the first detector layer [cm]; const Float_t First_Z_Position = 10; const Float_t Z_Distance = 10; // Silicon box for both module types const Float_t Module_Size_X = 80.; const Float_t Module_Size_Y = 80.; const Float_t Module_Size_Z = .04; // some global variables TGeoManager* gGeoMan = NULL; // Pointer to TGeoManager instance TGeoVolume* gModules; // Global storage for module types // Forward declarations void create_materials_from_media_file(); TGeoVolume* create_detector(); void position_detector(); void add_alignable_volumes(); void Create_Tutorial4_Geometry() { // Load the necessary FairRoot libraries // gROOT->LoadMacro("$VMCWORKDIR/gconfig/basiclibs.C"); // basiclibs(); // gSystem->Load("libGeoBase"); // gSystem->Load("libParBase"); // gSystem->Load("libBase"); // Load needed material definition from media.geo file create_materials_from_media_file(); // Get the GeoManager for later usage gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom"); gGeoMan->SetVisLevel(7); // Create the top volume TGeoVolume* top = new TGeoVolumeAssembly("TOP"); gGeoMan->SetTopVolume(top); TGeoVolume* tut4 = new TGeoVolumeAssembly(geoVersion); top->AddNode(tut4, 1); gModules = create_detector(); position_detector(); cout<"Voxelizing."<<endl; top->Voxelize(""); gGeoMan->CloseGeometry(); add_alignable_volumes(); gGeoMan->CheckOverlaps(0.001); gGeoMan->PrintOverlaps(); gGeoMan->Test(); TFile* outfile = TFile::Open(FileName,"RECREATE"); top->Write(); outfile->Close(); TFile* outfile1 = TFile::Open(FileName1,"RECREATE"); gGeoMan->Write(); outfile1->Close(); // ------------------------------------------------------------------------ } void create_materials_from_media_file() { // Use the FairRoot geometry interface to load the media which are already defined FairGeoLoader* geoLoad = new FairGeoLoader("TGeo", "FairGeoLoader"); FairGeoInterface* geoFace = geoLoad->getGeoInterface(); TString geoPath = gSystem->Getenv("VMCWORKDIR"); TString geoFile = geoPath + "/common/geometry/media.geo"; geoFace->setMediaFile(geoFile); geoFace->readMedia(); // Read the required media and create them in the GeoManager FairGeoMedia* geoMedia = geoFace->getMedia(); FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); FairGeoMedium* air = geoMedia->getMedium("air"); FairGeoMedium* silicon = geoMedia->getMedium("silicon"); // include check if all media are found geoBuild->createMedium(air); geoBuild->createMedium(silicon); } TGeoVolume* create_detector() { // needed materials TGeoMedium* SiliconVolMed = gGeoMan->GetMedium(BoxVolumeMedium); // Single detector_layer TGeoBBox* det_plane = new TGeoBBox("", Module_Size_X/2., Module_Size_Y/2., Module_Size_Z/2.); TGeoVolume* det_plane_vol = new TGeoVolume("tut4_det", det_plane, SiliconVolMed); det_plane_vol->SetLineColor(kBlue); // set line color det_plane_vol->SetTransparency(70); // set transparency TGeoTranslation* det_plane_trans = new TGeoTranslation("", 0., 0., 0.); return det_plane_vol; } void position_detector() { TGeoTranslation* det_trans=NULL; Int_t numDets=0; for (Int_t detectorPlanes = 0; detectorPlanes < 40; detectorPlanes++) { det_trans = new TGeoTranslation("", 0., 0., First_Z_Position+(numDets*Z_Distance)); gGeoMan->GetVolume(geoVersion)->AddNode(gModules, numDets, det_trans); numDets++; } } void add_alignable_volumes() { TString volPath; TString symName; TString detStr = "Tutorial4/det"; TString volStr = "/TOP_1/tutorial4_1/tut4_det_"; for (Int_t detectorPlanes = 0; detectorPlanes < 40; detectorPlanes++) { volPath = volStr; volPath += detectorPlanes; symName = detStr; symName += Form("%02d",detectorPlanes); cout<"Path: "<<volPath<<", "<<symName<<endl; // gGeoMan->cd(volPath); gGeoMan->SetAlignableEntry(symName.Data(),volPath.Data()); } cout<"Nr of alignable objects: "<<gGeoMan->GetNAlignable()<<endl; }
Kod jest w pewien sposób "samowyjaśniający" się choć wydaje się dosyć skomplikowany. Bazuje on na ROOTowej geometrii której pełne wyjaśnienie wymagałoby co najmniej kilku osobnych lekcji dlatego ograniczę się linku do ROOTowego manuala https://root.cern.ch/root/html534/guides/users-guide/Geometry.html#example-1-creating-the-world .
Dodawanie detektora
Jeśli już jakoś udało nam się przebrnąć przez wszystkie poprzednie etapy aby dodać detektory wystarczy coś takieg w makrze transportu:
FairModule *myDet = new MojDetektor("PIPE"); myDet->SetGeometryFileName("plikGeo.root"); fRun->AddModule(myDet);
Gdzie fRun jest instancją FairRunAna (lub innego manadżera tranportu). Oczywiście powyższy kod powinien być wywołany przed wywołaniem FairRun::Init().