/// @file ReadGeoDescription.cc /// @brief Implementation of the geometry reader class. #include "ReadGeoDescription.hh" #include "ReadGeoDescription_defs.hh" #include // ROOT include statements. #include #include #include #include #include // Standard include statements. #include using namespace std; // to be used as extern later ReadGeoDescription * g_GeoDsc; // // ReadGeoDescription constructor. // ReadGeoDescription::ReadGeoDescription(string xmlFile) { G4cout << "* INFO:" << G4endl << "* INFO:====================================================" << G4endl << "* INFO: [ReadGeoDescription] " << G4endl << "* INFO: | Reading the geometry descriptions." << G4endl << "* INFO:====================================================" << G4endl << "* INFO: " << G4endl; // Has the geometry already been read? If so, exit... if (g_GeoDsc) { G4cout << "* ERROR: [ReadGeoDescription::ReadGeoDescription] " << G4endl << "* ERROR: Can't instantiate this object twice!" << G4endl << "* ERROR:" << G4endl; exit(1); } // Initialize my vector //m_detsGeo = new map; // Units map // Initializing units from strings to map units from the XML file. m_unitsMap["nm"] = CLHEP::nm; m_unitsMap["um"] = CLHEP::um; m_unitsMap["mm"] = CLHEP::mm; m_unitsMap["cm"] = CLHEP::cm; m_unitsMap["m"] = CLHEP::m; // The list of expected tags TDOMParser *domParser = new TDOMParser(); m_firstIndx = -1; domParser->SetValidate(false); // do not validate with DTD for now domParser->ParseFile(xmlFile.c_str()); TXMLNode *node = domParser->GetXMLDocument()->GetRootNode(); // Parse the XML file. ParseContext(node); // Create any requested replicas. ReplicateDetectors(); G4cout << "* INFO:====================================================" << G4endl << "* INFO: Summary - read " << MyWid((int)m_detsGeo.size(),3,0) << " detectors from the XML database." << G4endl << "* INFO:====================================================" << G4endl << "* INFO: " << G4endl; // Loop over the detectors. map::iterator itr = m_detsGeo.begin(); for ( ; itr != m_detsGeo.end() ; itr++) { (*itr).second->Dump(); } // keep this pointer g_GeoDsc = this; }//end of ReadGeoDescription constructor. // // ReadGeoDescription::UseTheseDetectorsOnly method. // G4int ReadGeoDescription::UseTheseDetectorsOnly(vector useDetectors) { // Check for replicated sensors set checkIds; // First verify if all detectors are in the db vector::iterator itr = useDetectors.begin(); for( ; itr != useDetectors.end() ; itr++ ){ if(m_detsGeo.find(*itr) == m_detsGeo.end()){ // not found G4cout << "[OOPS] detector with Id " << *itr << " requested in the macro but not found in the db." << G4endl; G4cout << " Allpix can't recover ... so long, and thanks for all the fish ;)" << G4endl; exit(1); } if( checkIds.find(*itr) == checkIds.end()) { // not in the list all good checkIds.insert( *itr ); } else { G4cout << "[OOPS] detector with Id " << *itr << " duplicated in the macro ! please check your macro." << G4endl; G4cout << " Allpix can't recover ... so long, and thanks for all the fish ;)" << G4endl; exit(1); } } // now erase what's not needed G4int nErased = 0; map::iterator detItr = m_detsGeo.begin(); bool found = false; vector scheduledErase; for( ; detItr != m_detsGeo.end() ; detItr++){ G4int aDet = (*detItr).first; found = false; for( itr = useDetectors.begin() ; itr != useDetectors.end() ; itr++ ){ if(aDet == *itr){ found = true; break; } } if(!found){ G4cout << " ----> schedule for erasing " << aDet << G4endl; // don't erase right away, schedule and delete later, otherwise the // vector over which I am looping shrinks. scheduledErase.push_back(aDet); //m_detsGeo.erase(aDet); nErased++; } } // and finally erase vector::iterator eraseItr = scheduledErase.begin(); for( ; eraseItr != scheduledErase.end() ; eraseItr++ ) { m_detsGeo.erase(*eraseItr); } return nErased; }//end of ReadGeoDescription::UseTheseDetectorsOnly method. // // // void ReadGeoDescription::BuildListOfExpectedTags() { // Or don't, you know. } // // // ReadGeoDescription * ReadGeoDescription::GetInstance() { if(!g_GeoDsc){ std::cout << "This object has to be intantiated by DetectorConstruction first ... ReadGeoDescription::GetInstance()" << std::endl; exit(1); } return g_GeoDsc; } // // ReadGeoDescription::ParseContext method. // void ReadGeoDescription::ParseContext(TXMLNode *node) { string tempContent; string tempAtt1; for ( ; node ; node = node->GetNextNode()) { if (node->GetNodeType() == TXMLNode::kXMLElementNode) { // Element Node m_currentNodeName = string(node->GetNodeName()); //cout << m_currentNodeName << endl; /* if(m_currentNodeName == __pixeldet_node_S) { cout << "Creating configuration for device with id : "; //m_detsGeoIndx = 0; } */ // Catch properties first if any // This should be the right attribute each time // guaranteed by the dtd file if (node->HasAttributes()) { TList * attrList = node->GetAttributes(); TIter next(attrList); TXMLAttr *attr; while ((attr =(TXMLAttr*)next())) { // verifying attributes names tempContent = string(attr->GetName()); // att name if (tempContent == __pixeldet_node_ATT_id_S && m_currentNodeName == __pixeldet_node_S) { // check if this is the right attribute "id" tempAtt1 = string(attr->GetValue()); // fetch the value if (StringIsRelevant(tempAtt1)) { // Analyse the id string first // list of detector to create with this info vector indexes = ProcessIdString(tempAtt1.c_str()); // save first index m_firstIndx = indexes[__FIRST_DET_INDX]; // get rid of it indexes.erase(indexes.begin()); // Put the rest in the map. m_detsGeoIndx[m_firstIndx] = indexes; // Create the first detector. m_detsGeo[m_firstIndx] = new AllPixGeoDsc; m_detsGeo[m_firstIndx]->SetID(atoi(tempAtt1.c_str())); G4cout << "* INFO:" << G4endl << "* INFO: Creating configuration for device with ID : " << m_firstIndx << endl; //cout << m_detsGeoIndx[m_firstIndx].size() << " copies requested" << endl; } } else if (tempContent == __pixeldet_global_ATT_units_S) { tempAtt1 = string(attr->GetValue()); // fetch the value if (StringIsRelevant(tempAtt1)) { // use this units when processing the contents m_currentAtt = tempAtt1; } }//end of tempContent check. } } }//end of element node check. // Is the node a text node? if (node->GetNodeType() == TXMLNode::kXMLTextNode) { // Text node // get the other nodes into the GeoDsc for the current detector tempContent = string(node->GetContent()); //if(m_detsGeoIndx[__FIRST_DET_INDX] > -1 && StringIsRelevant(tempContent)){ if(StringIsRelevant(tempContent)){ if(m_currentNodeName == __npix_x_S) { int val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetNPixelsX(val); }else if(m_currentNodeName == __npix_y_S){ int val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetNPixelsY(val); }else if(m_currentNodeName == __npix_z_S){ int val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetNPixelsZ(val); } // The readout chip size. else if (m_currentNodeName == __chip_hx_S) { float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetChipHX(val*m_unitsMap[m_currentAtt]); } else if (m_currentNodeName == __chip_hy_S) { float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetChipHY(val*m_unitsMap[m_currentAtt]); } else if (m_currentNodeName == __chip_hz_S) { float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetChipHZ(val*m_unitsMap[m_currentAtt]); } //// The readout chip position. //else if(m_currentNodeName == __chip_posx_S) { // float val = atof(tempContent.c_str()); // m_detsGeo[m_firstIndx]->SetChipPosX(val*m_unitsMap[m_currentAtt]); //} //else if (m_currentNodeName == __chip_posy_S) { // float val = atof(tempContent.c_str()); // m_detsGeo[m_firstIndx]->SetChipPosY(val*m_unitsMap[m_currentAtt]); //} //else if (m_currentNodeName == __chip_posz_S) { // float val = atof(tempContent.c_str()); // m_detsGeo[m_firstIndx]->SetChipPosZ(val*m_unitsMap[m_currentAtt]); //} // The pixel size. else if (m_currentNodeName == __pixsize_x_S) { float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetPixSizeX(val*m_unitsMap[m_currentAtt]); } else if(m_currentNodeName == __pixsize_y_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetPixSizeY(val*m_unitsMap[m_currentAtt]); }else if(m_currentNodeName == __pixsize_z_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetPixSizeZ(val*m_unitsMap[m_currentAtt]); } else if (m_currentNodeName == __sensor_hx_S) { float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetSensorHX(val*m_unitsMap[m_currentAtt]); } else if (m_currentNodeName == __sensor_hy_S) { float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetSensorHY(val*m_unitsMap[m_currentAtt]); } else if (m_currentNodeName == __sensor_hz_S) { float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetSensorHZ(val*m_unitsMap[m_currentAtt]); } else if(m_currentNodeName == __sensor_posx_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetSensorPosX(val*m_unitsMap[m_currentAtt]); }else if(m_currentNodeName == __sensor_posy_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetSensorPosY(val*m_unitsMap[m_currentAtt]); }else if(m_currentNodeName == __sensor_posz_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetSensorPosZ(val*m_unitsMap[m_currentAtt]); } // PCB properties. else if (m_currentNodeName == __pcb_hx_S) { float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetPCBHX(val*m_unitsMap[m_currentAtt]); } else if (m_currentNodeName == __pcb_hy_S) { float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetPCBHY(val*m_unitsMap[m_currentAtt]); } else if (m_currentNodeName == __pcb_hz_S) { float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetPCBHZ(val*m_unitsMap[m_currentAtt]); } // Copper base properties. else if (m_currentNodeName == __Cu_base_Dx_S) { float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetCuBaseDX(val*m_unitsMap[m_currentAtt]); //if (dbg) G4cout<<"DEBUG: @ Set Copper base DX to "<GetCuBaseDX(), "Length")<SetCuBaseDY(val*m_unitsMap[m_currentAtt]); //if (dbg) G4cout<<"DEBUG: @ Set Copper base DY to "<GetCuBaseDY(), "Length")<SetCuBaseDZ(val*m_unitsMap[m_currentAtt]); //if (dbg) G4cout<<"DEBUG: @ Set Copper base DZ to "<GetCuBaseDZ(), "Length")<SetCuBaseOffsetX(val*m_unitsMap[m_currentAtt]); //if (dbg) G4cout<<"DEBUG: @ Set Copper base X offset to "<GetCuBaseOffsetX(), "Length")<SetCuBaseOffsetY(val*m_unitsMap[m_currentAtt]); //if (dbg) G4cout<<"DEBUG: @ Set Copper base Y offset to "<GetCuBaseOffsetY(), "Length")<SetAlFoilThickness(val*m_unitsMap[m_currentAtt]); } else if(m_currentNodeName == __sensor_gr_excess_htop_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetSensorExcessHTop(val*m_unitsMap[m_currentAtt]); }else if(m_currentNodeName == __sensor_gr_excess_hbottom_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetSensorExcessHBottom(val*m_unitsMap[m_currentAtt]); }else if(m_currentNodeName == __sensor_gr_excess_hright_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetSensorExcessHRight(val*m_unitsMap[m_currentAtt]); }else if(m_currentNodeName == __sensor_gr_excess_hleft_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetSensorExcessHLeft(val*m_unitsMap[m_currentAtt]); }else if(m_currentNodeName == __digitizer_S){ G4String valS(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetSensorDigitizer(valS); } else if(m_currentNodeName == __sensor_Resistivity){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetResistivity(val); } else if(m_currentNodeName == __MIP_Tot_S){ float val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetMIPTot(val); } else if(m_currentNodeName == __MIP_Charge_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetMIPCharge(val); } else if(m_currentNodeName == __Counter_Depth_S){ float val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetCounterDepth(val); } else if(m_currentNodeName == __Clock_Unit_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetClockUnit(val); } else if(m_currentNodeName == __Chip_Noise_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetChipNoise(val); } // // The chip threshold. else if(m_currentNodeName == __Chip_Threshold_S) { float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetThreshold(val); } // else if(m_currentNodeName == __Cross_Talk_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetCrossTalk(val); } else if(m_currentNodeName == __Saturation_Energy_S){ float val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetSaturationEnergy(val); } // Temporal information //---------------------- else if (m_currentNodeName == __AcqTime_S) { Double_t val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetAcqTime(val); } // Detector settings //------------------- // Polarity else if (m_currentNodeName == __Polarity_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetPolarity(val); } // Bias Voltage else if (m_currentNodeName == __HV_S) { Double_t val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetHV(val); } // DACS //------ // IKrum else if (m_currentNodeName == __DAC_IKrum_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacIkrum(val); } // Disc else if (m_currentNodeName == __DAC_Disc_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacDisc(val); } // Preamp else if (m_currentNodeName == __DAC_Preamp_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacPreamp(val); } // BuffAnalogA else if (m_currentNodeName == __DAC_BuffAnalogA_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacBuffAnalogA(val); } // BuffAnalogB else if (m_currentNodeName == __DAC_BuffAnalogB_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacBuffAnalogB(val); } // Hist else if (m_currentNodeName == __DAC_Hist_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacHist(val); } // THL else if (m_currentNodeName == __DAC_THL_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacThl(val); } // THL Coarse else if (m_currentNodeName == __DAC_THL_Coarse_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacThlCoarse(val); } // VCAS else if (m_currentNodeName == __DAC_VCAS_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacVcas(val); } // FBK else if (m_currentNodeName == __DAC_FBK_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacFbk(val); } // GND else if (m_currentNodeName == __DAC_GND_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacGnd(val); } // THS else if (m_currentNodeName == __DAC_THS_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacThs(val); } // Bias LVDS else if (m_currentNodeName == __DAC_BiasLVDS_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacBiasLvds(val); } // Ref LVDS else if (m_currentNodeName == __DAC_RefLVDS_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetDacRefLvds(val); } // Medipix Clock else if (m_currentNodeName == __Mpx_Clock_S) { Double_t val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetMpxClock(val); } // Timepix Clock else if (m_currentNodeName == __Tpx_Clock_S) { //Byte_t val; //if (tempContent == "0x00") val = 0x00; //else if (tempContent == "0x01") val = 0x01; //else if (tempContent == "0x02") val = 0x02; //else if (tempContent == "0x03") val = 0x03; //else val = 0x00; // // Changed to a double (MHz). Double_t val; if (tempContent == "0x00") val = 10.0; // MHz else if (tempContent == "0x01") val = 20.0; // MHz else if (tempContent == "0x02") val = 40.0; // MHz else if (tempContent == "0x03") val = 80.0; // MHz else val = atof(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetTpxClock(val); } // Back side preamp. enabled? else if (m_currentNodeName == __BS_Active_S) { Int_t val = atoi(tempContent.c_str()); Bool_t bval = (val == 1); m_detsGeo[m_firstIndx]->SetBsActive(bval); } // Calibration file name. else if (m_currentNodeName == __Calibration_File_S) { m_detsGeo[m_firstIndx]->SetCalibFile(tempContent); } //else if (m_currentNodeName == __) { // m_detsGeo[m_firstIndx]->(); //} // Detector information //---------------------- else if (m_currentNodeName == __Chip_ID_S) { m_detsGeo[m_firstIndx]->SetChipID(tempContent); } else if (m_currentNodeName == __Custom_Name_S) { m_detsGeo[m_firstIndx]->SetCustomName(tempContent); } else if (m_currentNodeName == __Firmware_S) { m_detsGeo[m_firstIndx]->SetFirmware(tempContent); } else if (m_currentNodeName == __Interface_S) { m_detsGeo[m_firstIndx]->SetInterface(tempContent); } else if (m_currentNodeName == __Mpx_Type_S) { Int_t val = atoi(tempContent.c_str()); m_detsGeo[m_firstIndx]->SetMpxType(val); } else if (m_currentNodeName == __Filter_File_S) { m_detsGeo[m_firstIndx]->SetAppFilterFile(tempContent); } else if (m_currentNodeName == __Applied_Filters_S) { m_detsGeo[m_firstIndx]->SetAppFilters(tempContent); } } /* if(StringIsRelevant(tempContent)) cout << "+" << tempContent << "-" << endl; */ } // A comment node? if (node->GetNodeType() == TXMLNode::kXMLCommentNode) { G4cout << "* INFO: Comment node: '" << node->GetContent() << "'" << G4endl; } // Parse the child nodes. ParseContext(node->GetChildren()); }//end of loop over the nodes. }//end of ReadGeoDescription::ParseContext method. // // ReadGeoDescription::ProcessIdString method. // vector ReadGeoDescription::ProcessIdString(const char * st) { TString idString(st); vector res; if (!idString.Contains(',',TString::kExact)) { res.push_back(atoi(st)); return res; } TString tempS; for (int i = 0 ; i < idString.Sizeof() ; i++) { if(idString[i] == ',' && tempS.Sizeof() != 0){ res.push_back( atoi(tempS.Data()) ); tempS.Clear(); }else{ tempS.Append(idString[i]); } } // last number if(tempS.Sizeof() != 0) res.push_back( atoi(tempS.Data()) ); /* for(int i = 0 ; i < (int)res.size() ; i++){ cout << res[i] << endl; } */ return res; }//end of ReadGeoDescription::ProcessIdString method. // // ReadGeoDescription::ReplicateDetectors method. // void ReadGeoDescription::ReplicateDetectors() { map >::iterator itr = m_detsGeoIndx.begin(); // step in the second instance vector replicas; vector::iterator repItr; // Loop over the detectors. for( ; itr != m_detsGeoIndx.end() ; itr++) { replicas = (*itr).second; for(repItr = replicas.begin() ; repItr != replicas.end() ; repItr++){ m_detsGeo[*repItr] = new AllPixGeoDsc; *(m_detsGeo[*repItr]) = *(m_detsGeo[(*itr).first]); // ! a copy of object contents ! cout << " --> Creating configuration replica with Id : " << *repItr << " (copy of " << (*itr).first << ")" << endl; m_detsGeo[*repItr]->SetID(*repItr); } } }//end of ReadGeoDescription::ReplicateDetectors method. // // ReadGeoDescription::StringIsRelevant method. // bool ReadGeoDescription::StringIsRelevant(string s){ // Convert to a TString. TString t(s); // Check for newlines or tabs. if(t.Contains('\n') || t.Contains('\t')) return false; return true; }//end of ReadGeoDescription::StringIsRelevant method.