#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __GNUC__ #define UNUSED __attribute__((unused)) #else #define UNUSED #endif using CLHEP::mm; using CLHEP::twopi; namespace RAT { void GeoAmBeSourceFactory::Construct( DBLinkPtr table, UNUSED const bool checkOverlaps ) { std::string prefix = table->GetS( "index" ); std::string motherName = table->GetS( "mother" ); // Load translations from the macro file std::pair< G4ThreeVector, G4RotationMatrix* > translation; try{ table->GetDArray("position"); translation = LoadTranslation( table ); } catch (DBNotFoundError& e ) { // If there is a translation or rotation missing check if there is AmBe information // loaded from ratdb LoadCalibCommon("MANIP"); if (fSourceType == "AMBE"){ translation.first.setX( fPosition.x() ); translation.first.setY( fPosition.y() ); translation.first.setZ( fPosition.z() ); // Now correct these by this volume's relative (if it exists) - see rat/src/geo/GeoFactory.cc try { const string relative = table->GetS( "relative" ); G4VPhysicalVolume* relativeVol = Detector::FindPhysicalVolume( relative ); if( relativeVol == NULL ) Log::Die( "GeoAmBeSourceFactory::Construct: No relative " + relative + " exists." ); translation.first -= relativeVol->GetFrameTranslation(); } catch( DBNotFoundError& e ) { } // This is not essential now but it may need to be (correctly) used in the future //G4ThreeVector colx = G4ThreeVector(fOrientationVector.x(), fOrientationVector.y(), 0.0); //G4ThreeVector coly = G4ThreeVector(-fOrientationVector.y(), fOrientationVector.x(), 0.); //G4ThreeVector colz = G4ThreeVector(0, 0, 0); //translation.second->set(colx, coly, colz); } else { Log::Die( "GeoAmBeSourceFactory::Construct: No position given and no run information exists."); } } // Read parameters from database // the actual AmBe source std::vector const &z_source = MultiplyVectorByUnit(table->GetDArray("z_source"),mm); std::vector const &r_inner_source = MultiplyVectorByUnit(table->GetDArray("r_inner_source"),mm); std::vector const &r_outer_source = MultiplyVectorByUnit(table->GetDArray("r_outer_source"),mm); G4Material * const material_source = G4Material::GetMaterial(table->GetS("material_source")); // bulk part of the new encapsulation std::vector const &z_bulk = MultiplyVectorByUnit(table->GetDArray("z_bulk"),mm); std::vector const &r_inner_bulk = MultiplyVectorByUnit(table->GetDArray("r_inner_bulk"),mm); std::vector const &r_outer_bulk = MultiplyVectorByUnit(table->GetDArray("r_outer_bulk"),mm); G4Material * const material_bulk = G4Material::GetMaterial(table->GetS("material_bulk")); // air pocket inside the can std::vector const &z_air = MultiplyVectorByUnit(table->GetDArray("z_air"),mm); std::vector const &r_inner_air = MultiplyVectorByUnit(table->GetDArray("r_inner_air"),mm); std::vector const &r_outer_air = MultiplyVectorByUnit(table->GetDArray("r_outer_air"),mm); G4Material * const material_air = G4Material::GetMaterial(table->GetS("material_air")); // side wall of the new encapsulation std::vector const &z_wall = MultiplyVectorByUnit(table->GetDArray("z_wall"),mm); std::vector const &r_inner_wall = MultiplyVectorByUnit(table->GetDArray("r_inner_wall"),mm); std::vector const &r_outer_wall = MultiplyVectorByUnit(table->GetDArray("r_outer_wall"),mm); G4Material * const material_wall = G4Material::GetMaterial(table->GetS("material_wall")); // Teflon holder std::vector const &z_holder = MultiplyVectorByUnit(table->GetDArray("z_holder"),mm); std::vector const &r_inner_holder = MultiplyVectorByUnit(table->GetDArray("r_inner_holder"),mm); std::vector const &r_outer_holder = MultiplyVectorByUnit(table->GetDArray("r_outer_holder"),mm); G4Material * const material_holder = G4Material::GetMaterial(table->GetS("material_holder")); //Build the geometry G4VSolid *sourceSolid = new G4Polycone(prefix + "_source", 0.0, twopi,z_source.size(), &z_source[0], &r_inner_source[0], &r_outer_source[0]); G4VSolid *bulkSolid = new G4Polycone(prefix + "_bulk", 0.0, twopi,z_bulk.size(), &z_bulk[0], &r_inner_bulk[0], &r_outer_bulk[0]); G4VSolid *airSolid = new G4Polycone(prefix + "_air", 0.0, twopi,z_air.size(), &z_air[0], &r_inner_air[0], &r_outer_air[0]); G4VSolid *wallSolid = new G4Polycone(prefix + "_wall", 0.0, twopi,z_wall.size(), &z_wall[0], &r_inner_wall[0], &r_outer_wall[0]); G4VSolid *holderSolid = new G4Polycone(prefix + "_holder", 0.0, twopi,z_holder.size(), &z_holder[0], &r_inner_holder[0], &r_outer_holder[0]); G4LogicalVolume *sourceLog = new G4LogicalVolume(sourceSolid, material_source, prefix + "_source_logical"); SetColor(table, "vis_color_source", sourceLog); G4LogicalVolume *bulkLog = new G4LogicalVolume(bulkSolid, material_bulk, prefix + "_bulk_logical"); SetColor(table, "vis_color_bulk", bulkLog); G4LogicalVolume *airLog = new G4LogicalVolume(airSolid, material_air, prefix + "_air_logical"); SetColor(table, "vis_color_air", airLog); G4LogicalVolume *wallLog = new G4LogicalVolume(wallSolid, material_wall, prefix + "_wall_logical"); SetColor(table, "vis_color_wall", wallLog); G4LogicalVolume *holderLog = new G4LogicalVolume(holderSolid, material_holder, prefix + "_holder_logical"); SetColor(table, "vis_color_holder", holderLog); new G4PVPlacement(0, G4ThreeVector(translation.first.x(), translation.first.y(), translation.first.z()), sourceLog->GetName(), sourceLog, Detector::FindPhysicalVolume(motherName), false, 0); new G4PVPlacement(0, G4ThreeVector(translation.first.x(), translation.first.y(), translation.first.z()), bulkLog->GetName(), bulkLog, Detector::FindPhysicalVolume(motherName), false, 0); new G4PVPlacement(0, G4ThreeVector(translation.first.x(), translation.first.y(), translation.first.z()), airLog->GetName(), airLog, Detector::FindPhysicalVolume(motherName), false, 0); new G4PVPlacement(0, G4ThreeVector(translation.first.x(), translation.first.y(), translation.first.z()), wallLog->GetName(), wallLog, Detector::FindPhysicalVolume(motherName), false, 0); new G4PVPlacement(0, G4ThreeVector(translation.first.x(), translation.first.y(), translation.first.z()), holderLog->GetName(), holderLog, Detector::FindPhysicalVolume(motherName), false, 0); } // Copied from N16 source factory void GeoAmBeSourceFactory::LoadCalibCommon(std::string fCalInfo) { if (fCalInfo != "MANIP" && fCalInfo != "CAMERA") Log::Die("GeoAmBeSourceFactory::LoadCalibCommon CalInfo "+ fCalInfo + " not recognized. Choose MANIP or CAMERA."); DBLinkPtr lCAL_SOURCE = DB::Get()->GetLink("CALIB_COMMON_RUN_LEVEL",fCalInfo); fSourceType = lCAL_SOURCE->GetS("source_type"); bool aPositionValid = lCAL_SOURCE->GetZ("position_valid"); if (!aPositionValid) { int aPositionBitmask = lCAL_SOURCE->GetI("position_bitmask"); Log::Die("GeoAmBeSourceFactory::LoadCalibCommon Position error: " + ::to_string(aPositionBitmask)); } std::vector aPosition = lCAL_SOURCE->GetFArrayFromD("position"); fPosition.SetXYZ(aPosition[0], aPosition[1], aPosition[2]); double aOrientation = lCAL_SOURCE->GetD("orientation"); // If info source is manip, orientation should be an integer (converted to float) // If info source is camera, orientation can be any value (but should match manip...) float or_x=0.0, or_y=0.0; if (fCalInfo == "MANIP"){ if (fabs(aOrientation) <0.01) { //East or_x = 1.0; or_y = 0.0; } else if (fabs(aOrientation - 1.0) <0.01) { //North or_x = 0.0; or_y = 1.0; } else if (fabs(aOrientation - 2.0) <0.01) { //West or_x = -1.0; or_y = 0.0; } else if (fabs(aOrientation - 3.0) <0.01) { //South or_x = 0.0; or_y = -1.0; } else { warn << "GeoAmBeSourceFactory::LoadCalibCommon MANIP option chosen but orientation read from ratdb is not close to an integer: "<< aOrientation << ". Using default orientation 0(East)." << newline; aOrientation = 0.0; or_x = 1.0; or_y = 0.0; } } else { or_x = cos(aOrientation*ROOT::Math::Pi()/2.0); or_y = sin(aOrientation*ROOT::Math::Pi()/2.0); } fOrientationVector = TVector3(or_x, -or_y,0.0); } //Copied from Sc48 source factory std::vector GeoAmBeSourceFactory::MultiplyVectorByUnit(std::vector v, const double unit) { transform(v.begin(), v.end(), v.begin(), bind2nd(std::multiplies(), unit)); return v; } //Copied from Sc48 source factory void GeoAmBeSourceFactory::SetColor(DBLinkPtr table, G4String colorName, G4LogicalVolume *logicalVolume) { G4VisAttributes *vis = new G4VisAttributes(); try { const std::vector &color = table->GetDArray(colorName); Log::Assert(color.size() == 3 || color.size() == 4, "GeoAmBeSourceFactory: Color entry " + colorName + " does not have 3 (RGB) or 4 (RGBA) components"); if (color.size() == 3) // RGB vis->SetColour(G4Colour(color[0], color[1], color[2])); else if (color.size() == 4) // RGBA vis->SetColour(G4Colour(color[0], color[1], color[2], color[3])); } catch (DBNotFoundError &e) { Log::Die("GeoAmBeSourceFactory: DBNotFoundError. Table " + e.table + ", index " + e.index + ", field " + e.field + "."); }; logicalVolume->SetVisAttributes(vis); } } // namespace RAT