GEANT4学习 第三节 B2中的SD 敏感探测器 1
SD探测器是G4里面比较常用的一个类,在我们领域还是非常重要的。
在之前,read-out的工作都是通过自己写step发生点的判断,然后计算event的能量沉积来输出沉积能量谱(实质上就是自己写的SD探测器)。
这一部分呢,我们尝试通过B2a这个例子,来使用SD探测器read-out。
1. B2 README固定靶实验
README中大概讲了这么几个事情:
1.1几何:
一个靶和六个电离室,都是圆柱体。
这个粒子包涵磁场(这一部分我不懂),通过交互命令可以来设置场强。
在B2中,使用了B2TrackerSD类,并注册了一个逻辑体作为探测器。
同样的,靶和电离室的材料也可以通过交互命令来更改。
1.2物理列表
和B1不同,B2使用的是FTFP_BERT。
1.3用户初始化
没啥可讲的
1.4初始粒子产生
还是G4ParticleGun这个类,这个和B1一样。这里提一句,我们组用的比较多的还是GPS来写源,更改更加方便。GPS在G4别的例子里面也有。
1.5探测器响应
使用 HIT 来记录能量的沉积
在这个例子中,电离室被定义成了SD,
那么,某一step中的一个 HIT 就是4个信息的集合:
1.track ID
2.电离室号
3.step内的能量沉积
4.能量沉积位置。
B2TrackSD::ProcessHits()会在粒子输运过程中的每一个step来实例化B2TrackHit的对象,即一个HIT。然后这个HIT会被收集到HitsCollection里面,
HitsCollection会在event结束时被打印在日志文件中。
2.main函数
和B1的区别只有一个物理列表是不同的。
运行还是一样,进入init_vis.mac,然后vis.mac,然后beamon
还是跟着代码的逻辑来,第一个类是B2aDetectorConstruction
3.B2aDetectorConstruction
我们先列一下这个类里面所有的参数和函数,这里我们稍微粗糙点,不管他们是公有还是私有的了。
序号 | 函数 | 备注 |
---|---|---|
1 | B2aDetectorConstruction | 构造函数 |
2 | ~B2aDetectorConstruction | 析构函数 |
3 | Construct | |
4 | ConstructSDandField | |
5 | SetTargetMaterial | |
6 | SetChamberMaterial | |
7 | SetMaxStep | |
8 | SetCheckOverlaps | |
9 | DefineMaterials | |
10 | DefineVolumes |
序号 | 参数 | 备注 |
---|---|---|
1 | fNbOfChambers | 电离室的个数 |
2 | fLogicTarget | 靶的逻辑体指针 |
3 | fLogicChamber | 电离室逻辑体指针 |
4 | fTargetMaterial | 靶材料指针 |
5 | fChamberMaterial | 电离室材料指针 |
6 | fStepLimit | step limits 的指针 |
7 | fMessenger | B2aDetectorMessenger的对象 |
8 | fMagFieldMessenger | 磁场Messenger对象 |
9 | fCheckOverlaps | overlap检查选项 |
构造函数和析构函数就不想说了。
B2a为了使用交互命令来修改探测器的几何结构,特意写了一个B2aDetectorMessenger,几何结构通过fMessenger来实现,这也让B2aDetectorConstruction显得有一点复杂,仔细梳理应该还是没问题的。
主要的还是 B2aDetectorConstruction::ConstructSDandField这个函数。首先,这个函数在G4VUserDetectorConstruction里面也有,猜测G4VUserDetectorConstruction的构造函数会首先检查并调用该函数。
我们把这个函数拿出来看一下:
void B2aDetectorConstruction::ConstructSDandField()
{
// Sensitive detectors
G4String trackerChamberSDname = "B2/TrackerChamberSD";
B2TrackerSD* aTrackerSD = new B2TrackerSD(trackerChamberSDname,
"TrackerHitsCollection"); //实例化了一个TrackSD对象
G4SDManager::GetSDMpointer()->AddNewDetector(aTrackerSD); //添加探测器
// Setting aTrackerSD to all logical volumes with the same name
// of "Chamber_LV".
SetSensitiveDetector("Chamber_LV", aTrackerSD, true); //设置探测器
// 这三个参数分别为 SD的逻辑体名字,一个G4VSensitiveDetector对象指针,以及是否多线程运行;最后一个参数可以省略
// Create global magnetic field messenger.
// Uniform magnetic field is then created automatically if
// the field value is not zero.
G4ThreeVector fieldValue = G4ThreeVector();
fMagFieldMessenger = new G4GlobalMagFieldMessenger(fieldValue);
fMagFieldMessenger->SetVerboseLevel(1);
// Register the field messenger for deleting
G4AutoDelete::Register(fMagFieldMessenger);
}
在这个类里面,需要将探测器设置一下,即
SetSensitiveDetector("Chamber_LV", aTrackerSD, true);
这一句话。而这一句话的aTrackerSD是B2TrackerSD的一个对象,我们需要去看这个类写了些什么。
4.B2TrackerSD
这个类里面的函数和参数如下:
序号 | 函数 | 备注 |
---|---|---|
1 | B2TrackerSD | 构造函数 |
2 | ~B2TrackerSD | 析构函数 |
3 | Initialize | |
4 | ProcessHits | 这个函数需要返回bool |
5 | EndOfEvent |
序号 | 参数 | 备注 |
---|---|---|
1 | fHitsCollection | B2TrackerHitsCollection类的指针 |
4.1 B2TrackerSD 构造函数
B2TrackerSD::B2TrackerSD(const G4String& name,
const G4String& hitsCollectionName)
: G4VSensitiveDetector(name),
fHitsCollection(NULL)
{
collectionName.insert(hitsCollectionName);
}
构造的时候插了一个hitsCollectionName到collectionName里面
但我没找到collectionName在哪里定义的。
4.2 Initialize()
void B2TrackerSD::Initialize(G4HCofThisEvent* hce)
{
// Create hits collection
fHitsCollection
= new B2TrackerHitsCollection(SensitiveDetectorName, collectionName[0]);
//这里实例化了B2TrackerHitsCollection
// Add this collection in hce
G4int hcID
= G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[0]);
hce->AddHitsCollection( hcID, fHitsCollection );
}
4.3 ProcessHits()
G4bool B2TrackerSD::ProcessHits(G4Step* aStep,
G4TouchableHistory*)
{
// energy deposit
G4double edep = aStep->GetTotalEnergyDeposit();
if (edep==0.) return false;
B2TrackerHit* newHit = new B2TrackerHit();
newHit->SetTrackID (aStep->GetTrack()->GetTrackID());
newHit->SetChamberNb(aStep->GetPreStepPoint()->GetTouchableHandle()
->GetCopyNumber());
newHit->SetEdep(edep);
newHit->SetPos (aStep->GetPostStepPoint()->GetPosition());
fHitsCollection->insert( newHit );
//newHit->Print();
return true;
}
4.4 EndOfEvent()
这个是输出信息了
void B2TrackerSD::EndOfEvent(G4HCofThisEvent*)
{
if ( verboseLevel>1 ) {
G4int nofHits = fHitsCollection->entries();
G4cout << G4endl
<< "-------->Hits Collection: in this event they are " << nofHits
<< " hits in the tracker chambers: " << G4endl;
for ( G4int i=0; i<nofHits; i++ ) (*fHitsCollection)[i]->Print();
}
}
在4.2Initialize()里面,即58-59行,实例化了B2TrackerHitsCollection,
另外在ProcessHits()里面,即78行,实例化了B2TrackerHit,
这两个类都在B2TrackerHit.hh文件里面,下面就看这个。
5. B2TrackerHit
序号 | 函数 | 备注 |
---|---|---|
1 | B2TrackerHit | 构造函数 |
2 | B2TrackerHit(const B2TrackerHit&) | |
3 | ~B2TrackerHit | 析构函数 |
4 | operator= | |
5 | operator== | |
6 | new | |
7 | delete | |
8 | Draw | |
9 | ||
10 | SetTrackID | |
11 | SetChamberNb | |
12 | SetEdep | |
13 | SetPos | |
10 | GetTrackID | |
11 | GetChamberNb | |
12 | GetEdep | |
13 | GetPos |
序号 | 参数 | 备注 |
---|---|---|
1 | fTrackID | TrackID |
1 | fChamberNb | |
1 | fEdep | |
1 | fPos |
其他的先不关注,大概和字面意思是差不多的
print这个函数里面,打印出了四个信息:
void B2TrackerHit::Print()
{
G4cout
<< " trackID: " << fTrackID << " chamberNb: " << fChamberNb
<< "Edep: "
<< std::setw(7) << G4BestUnit(fEdep,"Energy")
<< " Position: "
<< std::setw(7) << G4BestUnit( fPos,"Length")
<< G4endl;
}
6. B2ActionInitialization及B2PrimaryGeneratorAction
我们回到main函数中,注册完探测器几何形状后注册了物理列表,最后又注册了用户初始化。所以接下来看用户初始化,B2ActionInitialization。
在B2ActionInitialization中,和B1一样,还是实例化B2PrimaryGeneratorAction,调用粒子枪来产生粒子。
这两个类都比较简单,没什么可讲的。
值得注意的是,B2a的初始粒子是质子,能量为3.0GeV:
G4ParticleDefinition* particleDefinition
= G4ParticleTable::GetParticleTable()->FindParticle("proton");
fParticleGun->SetParticleDefinition(particleDefinition);
fParticleGun->SetParticleMomentumDirection(G4ThreeVector(0.,0.,1.));
fParticleGun->SetParticleEnergy(3.0*GeV);
这里讲完了运行的所有设置,后面呢就是输出信息的几个类了。