#include "TDirectory.h"
#include "TSystem.h"
#include "TRandom.h"
#include "ACorsikaIACTFile.h"
#include "AOpticsManager.h"
ClassImp(ACorsikaIACTFile)
const Int_t ACorsikaIACTFile::kMaxArrays = 100;
const Int_t ACorsikaIACTFile::kMaxTelescopes = 1000;
ACorsikaIACTFile::ACorsikaIACTFile(Int_t bufferLength)
: fBunches(0), fEventHeader(0), fRunHeader(0)
{
fIOBuffer = allocate_io_buffer(0);
fIOBuffer->max_length = bufferLength;
fMaxPhotonBunches = 100000;
for(Int_t i = 0; i < 4; i++){
fTelescopePosition[i] = new Double_t[kMaxTelescopes];
}
fCorsikaInputs.text = 0;
fCorsikaInputs.next = 0;
}
ACorsikaIACTFile::~ACorsikaIACTFile()
{
Close();
for(Int_t i = 0; i < 4; i++){
delete [] fTelescopePosition[i];
fTelescopePosition[i] = 0;
}
}
void ACorsikaIACTFile::Close()
{
if(not IsOpen()){
return;
}
fclose(fIOBuffer->input_file);
fIOBuffer->input_file = 0;
struct linked_string *xl, *xln;
for(xl = &fCorsikaInputs; xl != 0; xl = xln){
free(xl->text);
xl->text = 0;
xln = xl->next;
xl->next = 0;
if(xl != &fCorsikaInputs){
free(xl);
}
}
fNumberOfTelescopes = 0;
for(Int_t j = 0; j < 4; j++){
for(Int_t i = 0; i < kMaxTelescopes; i++){
fTelescopePosition[j][i] = 0;
}
}
SafeDelete(fBunches);
SafeDelete(fEventHeader);
SafeDelete(fRunHeader);
fFileName = "";
}
ARayArray* ACorsikaIACTFile::GetRayArray(Int_t telNo, Int_t arrayNo,
Double_t z, Double_t refractiveIndex)
{
if(!fBunches){
return 0;
}
if(telNo < 0 or telNo >= fNumberOfTelescopes or
arrayNo < 0 or arrayNo >= kMaxArrays){
return 0;
}
ARayArray* array = new ARayArray;
Int_t telNo_, arrayNo_;
Float_t x, y, zem, time, cx, cy, cz, lambda, photons;
Double_t totalPhotons;
fBunches->SetBranchAddress("telNo", &telNo_);
fBunches->SetBranchAddress("arrayNo", &arrayNo_);
fBunches->SetBranchAddress("x", &x);
fBunches->SetBranchAddress("y", &y);
fBunches->SetBranchAddress("zem", &zem);
fBunches->SetBranchAddress("time", &time);
fBunches->SetBranchAddress("cx", &cx);
fBunches->SetBranchAddress("cy", &cy);
fBunches->SetBranchAddress("cz", &cz);
fBunches->SetBranchAddress("lambda", &lambda);
fBunches->SetBranchAddress("photons", &photons);
Double_t m = AOpticsManager::m();
Double_t cm = AOpticsManager::cm();
Double_t nm = AOpticsManager::nm();
Double_t ns = AOpticsManager::ns();
for(Int_t i = 0; i < fBunches->GetEntries(); i++){
fBunches->GetEntry(i);
if(telNo != telNo_ or arrayNo != arrayNo_){
continue;
}
Double_t airmass = -1./cz;
Double_t tel_dist = (z - GetTelescopeZ(telNo)*cm)*airmass;
Double_t speed = TMath::C()*m/refractiveIndex;
Double_t px = x*cm - tel_dist*cx;
Double_t py = y*cm - tel_dist*cy;
Double_t pt = time*ns - tel_dist/speed;
for(Int_t j = 0; j < photons; j++){
Double_t random_lambda = lambda == 0 ? 1./(1./fMinWavelength - gRandom->Uniform()*(1./fMinWavelength - 1./fMaxPhotonBunches)) : lambda;
ARay* ray = new ARay(0, random_lambda*nm, px, py, z, pt, cx, cy, cz);
array->Add(ray);
}
}
return array;
}
Double_t ACorsikaIACTFile::GetTelescopeR(Int_t i) const
{
if(0 <= i and i < fNumberOfTelescopes){
return fTelescopePosition[3][i];
} else {
return atof("NaN");
}
}
Double_t ACorsikaIACTFile::GetTelescopeX(Int_t i) const
{
if(0 <= i and i < fNumberOfTelescopes){
return fTelescopePosition[0][i];
} else {
return atof("NaN");
}
}
Double_t ACorsikaIACTFile::GetTelescopeY(Int_t i) const
{
if(0 <= i and i < fNumberOfTelescopes){
return fTelescopePosition[1][i];
} else {
return atof("NaN");
}
}
Double_t ACorsikaIACTFile::GetTelescopeZ(Int_t i) const
{
if(0 <= i and i < fNumberOfTelescopes){
return fTelescopePosition[2][i];
} else {
return atof("NaN");
}
}
Bool_t ACorsikaIACTFile::IsAllocated()
{
if(fIOBuffer){
return kTRUE;
} else {
return kFALSE;
}
}
Bool_t ACorsikaIACTFile::IsOpen()
{
if(IsAllocated()){
if(fIOBuffer->input_file){
return kTRUE;
}
}
return kFALSE;
}
void ACorsikaIACTFile::Open(const Char_t* fname)
{
if(IsOpen()){
fprintf(stderr, "Already open.\n");
Close();
}
if(IsAllocated()){
if((fIOBuffer->input_file = fileopen(gSystem->ExpandPathName(fname), "r")) == 0){
fprintf(stderr, "Cannot open the file.\n");
return;
}
}
fFileName = TString(fname);
if(ReadNextBlock() == IO_TYPE_MC_RUNH){
Float_t runh[273];
read_tel_block(fIOBuffer, IO_TYPE_MC_RUNH, runh, 273);
fRunHeader = new ACorsikaIACTRunHeader(runh);
} else {
fprintf(stderr, "The first header is not IO_TYPE_MC_RUNH.\n");
Close();
return;
}
if(ReadNextBlock() == IO_TYPE_MC_INPUTCFG){
read_input_lines(fIOBuffer, &fCorsikaInputs);
} else {
fprintf(stderr, "The second header is not IO_TYPE_MC_INPUTCFG.\n");
Close();
return;
}
if(ReadNextBlock() == IO_TYPE_MC_TELPOS){
read_tel_pos(fIOBuffer, kMaxTelescopes, &fNumberOfTelescopes,
fTelescopePosition[0], fTelescopePosition[1],
fTelescopePosition[2], fTelescopePosition[3]);
} else {
fprintf(stderr, "The third header is not IO_TYPE_MC_TELPOS.\n");
Close();
return;
}
}
void ACorsikaIACTFile::PrintInputCard() const
{
if(fCorsikaInputs.text!=0){
const struct linked_string *xl;
printf("CORSIKA was run with the following input lines:\n");
for(xl = &fCorsikaInputs; xl!=0; xl=xl->next){
printf(" %s\n", xl->text);
}
fflush(stdout);
}
}
#define SET_FLAG(flag, key) (flag |= (ULong64_t(0x1) << (key - IO_TYPE_MC_BASE)))
#define HAS_FLAG(flag, key) Bool_t(flag & (ULong64_t(0x1) << (key - IO_TYPE_MC_BASE)))
Int_t ACorsikaIACTFile::ReadEvent(Int_t num)
{
if(!IsOpen()){
fprintf(stderr, "File is not open.\n");
return -1;
}
if(fEventHeader){
if(fEventHeader->GetEventNumber() == num){
return num;
} else if(fEventHeader->GetEventNumber() > num){
return -1;
}
}
ULong64_t flag = 0x0;
while(1) {
Int_t numberOfArrays;
Double_t timeOffset;
Double_t xOffset[kMaxArrays];
Double_t yOffset[kMaxArrays];
Int_t telNo, arrayNo;
Float_t x, y, zem, time, cx, cy, cz, lambda, photons;
Double_t totalPhotons;
Int_t headerType = ReadNextBlock();
if(headerType == -1){
break;
}
switch(headerType) {
case IO_TYPE_MC_EVTH:
flag = 0x0;
Float_t evth[273];
read_tel_block(fIOBuffer, IO_TYPE_MC_EVTH, evth, 273);
if(evth[1] != num){
break;
}
fMaxWavelength = evth[96];
fMinWavelength = evth[95];
SafeDelete(fEventHeader);
fEventHeader = new ACorsikaIACTEventHeader(evth);
SET_FLAG(flag, IO_TYPE_MC_EVTH);
SafeDelete(fBunches);
fBunches = new TTree("tree", "Photon tree of CORSIKA IACT output.");
fBunches->Branch("telNo", &telNo, "telNo/I");
fBunches->Branch("arrayNo", &arrayNo, "arrayNo/I");
fBunches->Branch("x", &x, "x/F");
fBunches->Branch("y", &y, "y/F");
fBunches->Branch("zem", &zem, "zem/F");
fBunches->Branch("time", &time, "time/F");
fBunches->Branch("cx", &cx, "cx/F");
fBunches->Branch("cy", &cy, "cy/F");
fBunches->Branch("cz", &cz, "cz/F");
fBunches->Branch("lambda", &lambda, "lambda/F");
fBunches->Branch("photons", &photons, "photons/F");
break;
case IO_TYPE_MC_TELOFF:
if(HAS_FLAG(flag, IO_TYPE_MC_EVTH)){
read_tel_offset(fIOBuffer, kMaxArrays, &numberOfArrays, &timeOffset, xOffset, yOffset);
if(fEventHeader){
fEventHeader->SetMultipleUseHeader(numberOfArrays, timeOffset, xOffset, yOffset);
}
SET_FLAG(flag, IO_TYPE_MC_TELOFF);
}
break;
case IO_TYPE_MC_EXTRA_PARAM:
break;
case IO_TYPE_MC_LONGI:
break;
case IO_TYPE_MC_TELARRAY:
case IO_TYPE_MC_TELARRAY_HEAD:
{
if(headerType == IO_TYPE_MC_TELARRAY){
} else {
}
if(not (HAS_FLAG(flag, IO_TYPE_MC_EVTH) and HAS_FLAG(flag, IO_TYPE_MC_TELOFF))){
break;
}
Int_t instanceNumberOfArrays;
IO_ITEM_HEADER itemHeader;
Bool_t telIndividual;
if(headerType == IO_TYPE_MC_TELARRAY){
telIndividual = false;
begin_read_tel_array(fIOBuffer, &itemHeader, &instanceNumberOfArrays);
SET_FLAG(flag, IO_TYPE_MC_TELARRAY);
} else {
telIndividual = true;
read_tel_array_head(fIOBuffer, &itemHeader, &instanceNumberOfArrays);
SET_FLAG(flag, IO_TYPE_MC_TELARRAY_HEAD);
}
struct bunch* bunches = (struct bunch*)malloc(fMaxPhotonBunches*sizeof(struct bunch));
if(bunches == 0){
return -1;
}
for(Int_t i = 0; i < fNumberOfTelescopes; i++){
if(not telIndividual){
IO_ITEM_HEADER subItemHeader;
subItemHeader.type = IO_TYPE_MC_PHOTONS;
if(search_sub_item(fIOBuffer, &itemHeader, &subItemHeader) < 0){
break;
}
} else {
if(find_io_block(fIOBuffer, &fBlockHeader) != 0){
break;
}
if(read_io_block(fIOBuffer, &fBlockHeader) != 0){
break;
}
if(fBlockHeader.type == IO_TYPE_MC_TELARRAY_END){
telIndividual = false;
break;
}
if(fBlockHeader.type != IO_TYPE_MC_PHOTONS){
telIndividual = false;
break;
}
}
Int_t nbunches;
if(read_tel_photons(fIOBuffer, fMaxPhotonBunches, &arrayNo, &telNo,
&totalPhotons, bunches, &nbunches) < 0){
continue;
}
if(arrayNo != instanceNumberOfArrays){
}
if(i >= kMaxTelescopes or telNo < 0){
continue;
}
for(Int_t j = 0; j < nbunches; j++){
x = bunches[j].x;
y = bunches[j].y;
zem = bunches[j].zem;
time = bunches[j].ctime;
cx = bunches[j].cx;
cy = bunches[j].cy;
cz = -1.*sqrt(1. - cx*cx - cy*cy);
lambda = bunches[j].lambda;
photons = bunches[j].photons;
fBunches->Fill();
}
}
free(bunches);
if(fBlockHeader.type == IO_TYPE_MC_TELARRAY){
end_read_tel_array(fIOBuffer, &itemHeader);
}
break;
}
case IO_TYPE_MC_EVTE:
SET_FLAG(flag, IO_TYPE_MC_EVTE);
break;
case IO_TYPE_MC_RUNE:
SET_FLAG(flag, IO_TYPE_MC_RUNE);
break;
default:
fprintf(stderr, "Unknown type\n");
break;
}
if(HAS_FLAG(flag, IO_TYPE_MC_EVTH) and HAS_FLAG(flag, IO_TYPE_MC_TELOFF) and
(HAS_FLAG(flag, IO_TYPE_MC_TELARRAY) or HAS_FLAG(flag, IO_TYPE_MC_TELARRAY_HEAD)) and
HAS_FLAG(flag, IO_TYPE_MC_EVTE)){
return num;
}
}
return -1;
}
Int_t ACorsikaIACTFile::ReadNextBlock()
{
if(IsOpen()){
if(find_io_block(fIOBuffer, &fBlockHeader) != 0){
Close();
return -1;
}
if(read_io_block(fIOBuffer, &fBlockHeader) != 0){
Close();
return -1;
}
} else {
return -1;
}
return fBlockHeader.type;
}