#include #include #include #include #include #include #include #include #include #include namespace RAT { Co60SourceGen::Co60SourceGen() : fStateStr(""), fSourceName("TaggedSource_scintillator_phys") { // DecayChain_Gen::SetState("60CoChain:" + "fill:" + "poisson"); // Make sure that the tagged source geometry has actually been loaded. Log::Assert( Detector::FindPhysicalVolume(fSourceName) != NULL, "Co60SourceGen: Did not find physical volume '" + fSourceName + "'. Please load the TaggedSource geometry."); GLG4Gen_Combo::SetPosState(fSourceName); // Get all of the data required from the databases here DBLinkPtr sourceTable = DB::Get()->GetLink("GEO","TaggedSource"); DBLinkPtr isotopeTable = DB::Get()->GetLink("Decay0Backg","Co60"); // The geometry is built such that the position of the events should occur at // 'position', as set in TaggedSource.geo. Try to find it, and fail if not // found (geometry should not have been built without it, but it doesn't hurt // to check!). This position is the centre of the scintillator button. try{ fPos = sourceTable->GetDArray("position"); } catch(DBNotFoundError &e){ Log::Die("Co60SourceGen::SetState error: Could not find position in TaggedSource.geo.\n"); } try{ fLCN = sourceTable->GetI("lcn"); } catch(DBNotFoundError &e){ Log::Die("Co60SourceGen::SetState error: Could not find source LCN.\n"); } // Get the reference activity and date for the source (ie. the measured // activity on a particular date). If a date cannot be found, then default to // the date in DATE.ratdb. This implies the source activity will be equal to // that in TaggedSource.geo. try{ fRefActivity = sourceTable->GetD("ref_activity"); } catch(DBNotFoundError &e){ Log::Die("Co60SourceGen::SetEvRate error: Could not find the reference activity in TaggedSource.geo.\n"); } try{ fRefDate = sourceTable->GetS("ref_date"); } catch(DBNotFoundError &e){ warn << "Co60SourceGen::SetEvRate warning: Could not find the reference date for the source activity in TaggedSource.geo, so setting it equal to the run date in DATE.ratdb.\n"; // We'll do that setting below... fRefDate = ""; } // Get the 60Co half-life from the Decay0 database (value is in seconds). try{ fHalfLife = isotopeTable->GetDArray("Thnuc"); } catch(DBNotFoundError &e) { Log::Die("Co60SourceGen::SetEvRate error: Could not find the database information for 60Co in Decay0Backg.ratdb.\n"); } // Create a map that links month names to strings. BuildMonthMap(); // Decay0 generator for Co60 assuming a point source with poisson timing. fStateStr = "decay0:point:poisson"; GLG4Gen_Combo::SetState(fStateStr); fVertexStateStr = "backg Co60"; GLG4Gen_Combo::SetVertexState(fVertexStateStr); // Set the position state std::stringstream posStateStr; posStateStr << fPos.at(0) << " " << fPos.at(1) << " " << fPos.at(2); fPosStateStr = posStateStr.str(); GLG4Gen_Combo::SetPosState(fPosStateStr); // Calculate the event rate based on the run and reference dates and set the // activity for the generator. SetEvRate(); fTimeStateStr = GetEvRate(); GLG4Gen_Combo::SetTimeState(fTimeStateStr); } void Co60SourceGen::SetState(G4String state) { // This generator is completely specified internally, so the user has no need // to specify a state and we will ignore any attempts to do so. if(state != "") warn << "Co60SourceGen: Generator has a fixed state. Ignoring attempt to specify it.\n"; } void Co60SourceGen::SetEvRate() { // The event rate is determined using the reference date and activity in // TaggedSource.geo and the run start date set in DATE.ratdb. // Grab the date of the run from DATE.ratdb and set its universal time. Use // the EventTime class to handle the universal time conversion. fEvTime.LoadDB(); // Now take the string that represents the reference data for the calibration // source and separate out the day, month, year, hour, minute and second // (in that order). The string is in the form DD MMM/MM YYYY HH:MM:SS, where // MMM is a 3 character name for the month or MM is an integer for the month if(fRefDate.compare("") != 0){ // In this case, the date was defaulted. std::vector dateInfo; std::istringstream ssrefDate(fRefDate); std::string elem; while(!ssrefDate.eof()){ ssrefDate >> elem; std::istringstream sselem(elem); std::string el; while(getline(sselem,el,':')){ if(dateInfo.size() == 1){ int monthTemp = GetMonthInt(el); if(monthTemp <= 12 && monthTemp > 0) dateInfo.push_back(monthTemp); else Log::Die("Co60SourceGen::SetEvRate error: Month in reference date is incorrectly set.\n"); continue; } dateInfo.push_back(to_int(el)); } } Log::Assert(dateInfo.size() == 6, "Co60SourceGen::SetEvRate error: Reference date for the calibration source is not in the correct format. Should be YYYY MMM DD HH:MM:SS. MMM is the first 3 letters of the month name.\n"); // Convert the reference date into a Universal Time. int UTday, UTsec; double UTnsec; int seconds = 3600*dateInfo.at(3)+60*dateInfo.at(4)+dateInfo.at(5); UTday = fEvTime.GetUTDay(dateInfo.at(2),dateInfo.at(1),dateInfo.at(0), seconds,0.0,UTday,UTsec,UTnsec); fEvTime.SetUT(UTday,UTsec,UTnsec); } else // Set the reference date to the run date (either ref_date does not exist // in database, or it was set to "" in the macro). fEvTime.SetUT(fEvTime.GetStartUTDays(), fEvTime.GetStartUTSecs(), fEvTime.GetStartUTNsecs()); // Calculate the time difference, in seconds, between the reference date and // the run start date. If the start date is earlier than the reference, an // error is thrown. double timeDiff = 86400.*(fEvTime.GetStartUTDays()-fEvTime.GetUTDays())+ 1.*(fEvTime.GetStartUTSecs()-fEvTime.GetUTSecs()); Log::Assert(timeDiff >= 0., "Co60SourceGen::SetEvRate error: Reference date for the calibration source is later than the run date! Check the run date is set correctly in DATE.ratdb.\n"); // Calculate the activity of the source on the date of the run. Assume it is // constant over the run (which is a fair assumption, given the 5yr half-life). fActivity = fRefActivity*exp(-log(2.)*timeDiff/fHalfLife.at(0)); std::stringstream ssRate; ssRate << fActivity; G4String sRate = ssRate.str(); detail << "Co60SourceGen: Setting source activity to " << fActivity << " Bq based on a reference activity of " << fRefActivity << " Bq on " << fRefDate << ".\n"; fEvRate = sRate; std::cout<<"fEvRate = "<("Jan",1)); fMonth.insert(std::pair< std::string, int >("jan",1)); fMonth.insert(std::pair< std::string, int >("January",1)); fMonth.insert(std::pair< std::string, int >("january",1)); fMonth.insert(std::pair< std::string, int >("Feb",2)); fMonth.insert(std::pair< std::string, int >("feb",2)); fMonth.insert(std::pair< std::string, int >("February",2)); fMonth.insert(std::pair< std::string, int >("february",2)); fMonth.insert(std::pair< std::string, int >("Mar",3)); fMonth.insert(std::pair< std::string, int >("mar",3)); fMonth.insert(std::pair< std::string, int >("March",3)); fMonth.insert(std::pair< std::string, int >("march",3)); fMonth.insert(std::pair< std::string, int >("Apr",4)); fMonth.insert(std::pair< std::string, int >("apr",4)); fMonth.insert(std::pair< std::string, int >("April",4)); fMonth.insert(std::pair< std::string, int >("april",4)); fMonth.insert(std::pair< std::string, int >("May",5)); fMonth.insert(std::pair< std::string, int >("may",5)); fMonth.insert(std::pair< std::string, int >("Jun",6)); fMonth.insert(std::pair< std::string, int >("jun",6)); fMonth.insert(std::pair< std::string, int >("June",6)); fMonth.insert(std::pair< std::string, int >("june",6)); fMonth.insert(std::pair< std::string, int >("Jul",7)); fMonth.insert(std::pair< std::string, int >("jul",7)); fMonth.insert(std::pair< std::string, int >("July",7)); fMonth.insert(std::pair< std::string, int >("july",7)); fMonth.insert(std::pair< std::string, int >("Aug",8)); fMonth.insert(std::pair< std::string, int >("aug",8)); fMonth.insert(std::pair< std::string, int >("August",8)); fMonth.insert(std::pair< std::string, int >("august",8)); fMonth.insert(std::pair< std::string, int >("Sep",9)); fMonth.insert(std::pair< std::string, int >("sep",9)); fMonth.insert(std::pair< std::string, int >("September",9)); fMonth.insert(std::pair< std::string, int >("september",9)); fMonth.insert(std::pair< std::string, int >("Oct",10)); fMonth.insert(std::pair< std::string, int >("oct",10)); fMonth.insert(std::pair< std::string, int >("October",10)); fMonth.insert(std::pair< std::string, int >("october",10)); fMonth.insert(std::pair< std::string, int >("Nov",11)); fMonth.insert(std::pair< std::string, int >("nov",11)); fMonth.insert(std::pair< std::string, int >("November",11)); fMonth.insert(std::pair< std::string, int >("november",11)); fMonth.insert(std::pair< std::string, int >("Dec",12)); fMonth.insert(std::pair< std::string, int >("dec",12)); fMonth.insert(std::pair< std::string, int >("December",12)); fMonth.insert(std::pair< std::string, int >("december",12)); } int Co60SourceGen::GetMonthInt(std::string month) { // Find the month in the map and return the integer value for the month. If the // month is not found, then return the integer value of the argument passed, // as it could be that an integer value was set for the month in the database // rather than a name string if(fMonth.empty()) BuildMonthMap(); // This should never happen... std::map< std::string, int >::iterator itMonth; itMonth = fMonth.find(month); if(itMonth == fMonth.end()) return to_int(month); return (*itMonth).second; } void Co60SourceGen::SetVertexState(G4String /*state*/) { warn << "Co60SourceGen::SetVertexState error: /generator/vtx/set has no effect for the co60source generator. The vertex is generated using decay0.\n"; } void Co60SourceGen::SetPosState(G4String /*state*/) { warn << "Co60SourceGen::SetPosState error: /generator/set/pos has no effect for the co60source generator. The position is dictated by the position of the source geometry as set in TaggedSource.geo.\n"; } void Co60SourceGen::SetTimeState(G4String /*state*/) { warn << "Co60SourceGen::SetTimeState error: /generator/set/rate has no effect for the co60soure generator. The rate is calculated internally based on the start time set in DATE.ratdb and the reference date and rate set in TaggedSource.geo.\n"; } } // namespace RAT