// $Id$ // // File: DGeometry.cc // Created: Thu Apr 3 08:43:06 EDT 2008 // Creator: davidl (on Darwin swire-d95.jlab.org 8.11.1 i386) // #include using namespace std; #include "DGeometry.h" #include #include "FDC/DFDCWire.h" #include "FDC/DFDCGeometry.h" #include using namespace std; #ifndef M_TWO_PI #define M_TWO_PI 6.28318530717958647692 #endif //--------------------------------- // DGeometry (Constructor) //--------------------------------- DGeometry::DGeometry(JGeometry *jgeom, DApplication *dapp, unsigned int runnumber) { this->jgeom = jgeom; this->dapp = dapp; this->bfield = NULL; // don't ask for B-field object before we're asked for it this->runnumber = runnumber; this->materialmaps_read = false; this->materials_read = false; pthread_mutex_init(&bfield_mutex, NULL); pthread_mutex_init(&materialmap_mutex, NULL); pthread_mutex_init(&materials_mutex, NULL); } //--------------------------------- // ~DGeometry (Destructor) //--------------------------------- DGeometry::~DGeometry() { pthread_mutex_lock(&materials_mutex); for(unsigned int i=0; iGetBfield(runnumber); pthread_mutex_unlock(&bfield_mutex); return bfield; } //--------------------------------- // GetLorentzDeflections //--------------------------------- DLorentzDeflections* DGeometry::GetLorentzDeflections(void) { return dapp->GetLorentzDeflections(runnumber); } //--------------------------------- // GetMaterialMapVector //--------------------------------- vector DGeometry::GetMaterialMapVector(void) const { ReadMaterialMaps(); return materialmaps; } //--------------------------------- // ReadMaterialMaps //--------------------------------- void DGeometry::ReadMaterialMaps(void) const { /// This gets called by several "FindMat" methods below. It /// will return immediately if the material maps have already /// been read in. If they have not been read in, then it reads /// them and sets a flag so that they are only read in once. /// /// Orginally, this code resided in the constructor, but was /// moved here so that programs not requiring the material /// maps could start up quicker and skip reading them in altogether. // Lock mutex so we can check flag to see if maps have already // been read in pthread_mutex_lock(&materialmap_mutex); if(materialmaps_read){ // Maps are already read. Unlock mutex and return now pthread_mutex_unlock(&materialmap_mutex); return; } JCalibration * jcalib = dapp->GetJCalibration(runnumber); if(!jcalib){ _DBG_<<"ERROR: Unable to get JCalibration object!"< material_maps; vector namepaths; jcalib->GetListOfNamepaths(namepaths); vector material_namepaths; for(unsigned int i=0; iGetNr()*mat->GetNz()); } //cout< &matched_xpaths) const { /// Find all nodes that match the specified xpath and return them as /// fully parsed lists of the nodes and attributes. /// /// The matched_xpaths variable has 4 levels of STL containers nested /// together! The node_t data type contains 2 of them and represents /// a single tag with the "first" member being the tag name /// and the "second" member being a map of all of the attributes /// of that tag along with their values. /// /// The xpathparsed_t data type is a STL vector of node_t objects /// that comprises a complete xpath. The data type of matched_xpaths /// is a STL vector if xpathparsed_t objects and so comprises a /// list of complete xpaths. /// We do this by calling the GetXPaths() method of JGeometry to get /// a list of all xpaths. Then we pass all of those in to /// JGeometryXML::ParseXPath() to get a parsed list for each. This /// is compared to the parsed values of the xpath passed to us /// (also parsed by JGeometryXML::ParseXPath()) to find matches. // Make sure matched_xpaths is empty matched_xpaths.clear(); // Cast JGeometry into a JGeometryXML JGeometryXML *jgeomxml = dynamic_cast(jgeom); // Parse our target xpath xpathparsed_t target; string unused_string; unsigned int unused_int; jgeomxml->ParseXPath(xpath, target, unused_string, unused_int); // Get all xpaths for current geometry source vector allxpaths; jgeom->GetXPaths(allxpaths, JGeometry::attr_level_all); // Loop over xpaths for(unsigned int i=0; iFindMatALT1(pos,KrhoZ_overA, rhoZ_overA,LnI,X0); if(err==NOERROR){ // We found the material map containing this point. If a non-NULL // pointer was passed in for s_to_boundary, then search through all // material maps above and including this one to find the estimated // distance to the nearest boundary the swimmer should step to. Maps // after this one would only be considered outside of this one so // there is no need to check them. if(s_to_boundary==NULL)return NOERROR; // User doesn't want distance to boundary *s_to_boundary = 1.0E6; for(unsigned int j=0; j<=i; j++){ double s = materialmaps[j]->EstimatedDistanceToBoundary(pos, mom); if(s<*s_to_boundary)*s_to_boundary = s; } return NOERROR; } } return RESOURCE_UNAVAILABLE; } //--------------------------------- // FindMatKalman - Kalman filter needs slightly different set of parms. //--------------------------------- jerror_t DGeometry::FindMatKalman(const DVector3 &pos,const DVector3 &mom, double &KrhoZ_overA, double &rhoZ_overA, double &LnI, double &chi2c_factor,double &chi2a_factor, double &chi2a_corr, unsigned int &last_index, double *s_to_boundary) const { ReadMaterialMaps(); //last_index=0; for(unsigned int i=last_index; iFindMatKalman(pos,KrhoZ_overA, rhoZ_overA,LnI,chi2c_factor, chi2a_factor,chi2a_corr); if(err==NOERROR){ if(i==materialmaps.size()-1) last_index=0; else last_index=i; if(s_to_boundary==NULL)return NOERROR; // User doesn't want distance to boundary *s_to_boundary = 1.0E6; // If we are in the main mother volume, search through all the maps for // the nearest boundary if(last_index==0){ for(unsigned int j=0; jEstimatedDistanceToBoundary(pos, mom); if(s<*s_to_boundary){ *s_to_boundary = s; } } } else{ // otherwise, we found the material map containing this point. double s = materialmaps[last_index]->EstimatedDistanceToBoundary(pos, mom); if(s<*s_to_boundary)*s_to_boundary = s; } return NOERROR; } } return RESOURCE_UNAVAILABLE; } //--------------------------------- jerror_t DGeometry::FindMatKalman(const DVector3 &pos, double &KrhoZ_overA, double &rhoZ_overA, double &LnI, double &chi2c_factor, double &chi2a_factor, double &chi2a_corr, unsigned int &last_index) const { ReadMaterialMaps(); //last_index=0; for(unsigned int i=last_index; iFindMatKalman(pos,KrhoZ_overA, rhoZ_overA,LnI, chi2c_factor,chi2a_factor, chi2a_corr); if(err==NOERROR){ if(i==materialmaps.size()-1) last_index=0; else last_index=i; return err; } } return RESOURCE_UNAVAILABLE; } //--------------------------------- // FindMat //--------------------------------- jerror_t DGeometry::FindMat(DVector3 &pos, double &rhoZ_overA, double &rhoZ_overA_logI, double &RadLen) const { ReadMaterialMaps(); for(unsigned int i=0; iFindMat(pos, rhoZ_overA, rhoZ_overA_logI, RadLen); if(err==NOERROR)return NOERROR; } return RESOURCE_UNAVAILABLE; } //--------------------------------- // FindMat //--------------------------------- jerror_t DGeometry::FindMat(DVector3 &pos, double &density, double &A, double &Z, double &RadLen) const { ReadMaterialMaps(); for(unsigned int i=0; iFindMat(pos, density, A, Z, RadLen); if(err==NOERROR)return NOERROR; } return RESOURCE_UNAVAILABLE; } //--------------------------------- // FindMatNode //--------------------------------- //const DMaterialMap::MaterialNode* DGeometry::FindMatNode(DVector3 &pos) const //{ // //} //--------------------------------- // FindDMaterialMap //--------------------------------- const DMaterialMap* DGeometry::FindDMaterialMap(DVector3 &pos) const { ReadMaterialMaps(); for(unsigned int i=0; iIsInMap(pos))return map; } return NULL; } //==================================================================== // Convenience Methods // // Below are defined some methods to make it easy to extract certain // key values about the GlueX detector geometry from the XML source. // Note that one can still use the generic Get(string xpath, ...) // methods. This just packages some of them up for convenience. // // The one real gotcha here is that these methods must be kept // in sync with the XML structure by hand. If volumes are renamed // or their location within the hierachy is modified, then these // routines will need to be modified as well. That, or course, is // also true if you are using the generic Get(...) methods. // // What these methods are useful for is when minor changes are made // to the XML (such as the locations of the FDC packages) they // are automatically reflected here. //==================================================================== //--------------------------------- // GetDMaterial //--------------------------------- const DMaterial* DGeometry::GetDMaterial(string name) const { /// Get a pointer to the DMaterial object with the specified name. // Only fill materials member when one is actually requested // and then, only fill it once. // Lock mutex so we can check flag to see if maps have already // been read in pthread_mutex_lock(&materials_mutex); if(!materials_read) GetMaterials(); pthread_mutex_unlock(&materials_mutex); for(unsigned int i=0; iGetName() == name)return materials[i]; } //_DBG_<<"No material \""< xpaths; jgeom->GetXPaths(xpaths, JGeometry::attr_level_all, filter); // Look for xpaths that have "/materials[" in them for(unsigned int i=0; itoString(); } //=========== composites =========== filter = "//materials/composite[@name]"; // Get list of all xpaths jgeom->GetXPaths(xpaths, JGeometry::attr_level_all, filter); // Look for xpaths that have "/materials[" in them for(unsigned int i=0; itoString(); } materials_read = true; } //--------------------------------- // GetCompositeMaterial //--------------------------------- bool DGeometry::GetCompositeMaterial(const string &name, double &density, double &radlen) const { // Get list of all xpaths with "addmaterial" and "fractionmass" char filter[512]; sprintf(filter,"//materials/composite[@name='%s']/addmaterial/fractionmass[@fraction]", name.c_str()); vector xpaths; jgeom->GetXPaths(xpaths, JGeometry::attr_level_all, filter); // Loop over components of this composite _DBG_<<"Components for compsite "<r_z; double phi0; vectorrot; // Extract data from the XML if(!Get(r_z_s.str(), r_z)) return false; if(!Get(phi0_s.str(), phi0)) return false; if(!Get(rot_s.str(), rot)) return false; // Angular quantities const double deg2rad=M_PI/180.; double dphi=2*M_PI/double(ncopy); phi0*=deg2rad; // Extract data from close-packed straws bool close_packed=false; double rotX=0.,rotY=0.,stereo=0.,stereo_sign=1.; vectordelta_xyz; stereo=deg2rad*rot[0]; if (stereo<0.) stereo_sign=-1.; // Loop over the number of straws for (unsigned int i=0;iring=ring; w->straw=i+1; // Find the nominal wire position and direction from the XML DVector3 origin,udir; if (close_packed){ origin.SetX(delta_xyz[0]); origin.SetY(delta_xyz[1]); origin.RotateZ(phi); } else{ origin.SetX(r_z[0]*cos(phi)); origin.SetY(r_z[0]*sin(phi)); } origin.SetZ(zcenter); // Here, we need to define a coordinate system for the wire // in which the wire runs along one axis. We call the directions // of the axes in this coordinate system s,t, and u with // the wire running in the "u" direction. The "s" direction // will be defined by the direction pointing from the beamline // to the midpoint of the wire. udir.SetXYZ(0.0, 0.0,1.0); if (close_packed){ udir.RotateX(rotX); udir.RotateY(rotY); udir.RotateZ(phi); //stereo = (rotX<0?-1.:1.)*w->udir.Angle(DVector3(0,0,1)); } else{ udir.RotateX(stereo); udir.RotateZ(phi); } // Apply offsets in x and y double half_dz=0.5*dz; double x0=origin.x(),y0=origin.y(); double ux=udir.x()/udir.z(); double uy=udir.y()/udir.z(); unsigned int ringid=ring-1; DVector3 downstream(x0+half_dz*ux+cdc_offsets[ringid][i].dx_d, y0+half_dz*uy+cdc_offsets[ringid][i].dy_d, zcenter+half_dz); DVector3 upstream(x0-half_dz*ux+cdc_offsets[ringid][i].dx_u, y0-half_dz*uy+cdc_offsets[ringid][i].dy_u, zcenter-half_dz); w->origin=0.5*(upstream+downstream); w->phi=w->origin.Phi(); // Wire direction w->udir=downstream-upstream; w->udir.SetMag(1.); w->stereo=stereo_sign*w->udir.Angle(DVector3(0.,0.,1.)); // other directions for our wire coordinate system w->sdir=w->origin; w->sdir.SetMag(1.); w->tdir = w->udir.Cross(w->sdir); stereowires.push_back(w); } return true; } //--------------------------------- // GetCDCAxialWires //--------------------------------- /// Extract the axial wire data from the XML bool DGeometry::GetCDCAxialWires(unsigned int ring,unsigned int ncopy, double zcenter,double dz, vector >&cdc_offsets, vector &axialwires) const{ stringstream phi0_s,r_z_s; // Create search strings for the number of straws and the straw geometrical properties phi0_s << "//mposPhi[@volume='CDCstrawShort']/@Phi0/ring[@value='" << ring << "']"; r_z_s << "//mposPhi[@volume='CDCstrawShort']/@R_Z/ring[@value='" << ring << "']"; double phi0; vectorr_z; // Extract the data from the XML if(!Get(phi0_s.str(), phi0)) return false; if(!Get(r_z_s.str(), r_z)) return false; // Angular quantities double dphi=2*M_PI/double(ncopy); phi0*=M_PI/180.; // Loop over the number of straws for (unsigned int i=0;iring=ring; w->straw=i+1; // Find the nominal wire position from the XML double x0=r_z[0]*cos(phi); double y0=r_z[0]*sin(phi); // Apply offsets in x and y double half_dz=0.5*dz; unsigned int ringid=ring-1; DVector3 downstream(x0+cdc_offsets[ringid][i].dx_d, y0+cdc_offsets[ringid][i].dy_d, zcenter+half_dz); DVector3 upstream(x0+cdc_offsets[ringid][i].dx_u, y0+cdc_offsets[ringid][i].dy_u, zcenter-half_dz); w->origin=0.5*(upstream+downstream); w->phi=w->origin.Phi(); // Here, we need to define a coordinate system for the wire // in which the wire runs along one axis. We call the directions // of the axes in this coordinate system s,t, and u with // the wire running in the "u" direction. The "s" direction // will be defined by the direction pointing from the beamline // to the midpoint of the wire. w->udir=downstream-upstream; w->udir.SetMag(1.); w->stereo=w->udir.Angle(DVector3(0.,0.,1.)); // other directions for our wire coordinate system w->sdir=w->origin; w->sdir.SetMag(1.); w->tdir = w->udir.Cross(w->sdir); axialwires.push_back(w); } return true; } //--------------------------------- // GetCDCWires //--------------------------------- bool DGeometry::GetCDCWires(vector >&cdcwires) const{ // Get nominal geometry from XML vectorcdc_origin; vectorcdc_length; Get("//posXYZ[@volume='CentralDC']/@X_Y_Z",cdc_origin); Get("//tubs[@name='STRW']/@Rio_Z",cdc_length); double zmin=cdc_origin[2]; double zmax=zmin+cdc_length[2]; double zcenter=0.5*(zmin+zmax); double L=zmax-zmin; // Get number of straws for each layer from the XML unsigned int numstraws[28]; stringstream ncopy_s; // Get number of straws for each ring for (unsigned int ring=1;ring<=28;ring++){ // Create search string for the number of straws ncopy_s << "//CentralDC_s/section/composition/mposPhi/@ncopy/ring[@value='" << ring << "']"; Get(ncopy_s.str(),numstraws[ring-1]); ncopy_s.str(""); ncopy_s.clear(); } // Get offsets tweaking nominal geometry from calibration database JCalibration * jcalib = dapp->GetJCalibration(runnumber); vector >vals; vectortempvec; vector >cdc_offsets; if (jcalib->Get("CDC/wire_alignment",vals)==false){ unsigned int straw_count=0,ring_count=0; for(unsigned int i=0; i &row = vals[i]; // put the vector of offsets for the current ring into the offsets vector if (straw_count==numstraws[ring_count]){ straw_count=0; ring_count++; cdc_offsets.push_back(tempvec); tempvec.clear(); } // Get the offsets from the calibration database cdc_offset_t temp; temp.dx_u=row["dxu"]; //temp.dx_u=0.; temp.dy_u=row["dyu"]; //temp.dy_u=0.; temp.dx_d=row["dxd"]; //temp.dx_d=0.; temp.dy_d=row["dyd"]; //temp.dy_d=0.; tempvec.push_back(temp); straw_count++; } cdc_offsets.push_back(tempvec); } else{ jerr<< "CDC wire alignment table not available... bailing... " <straws; if (!GetCDCAxialWires(ring,numstraws[ring-1],zcenter,L,cdc_offsets,straws)) return false; cdcwires.push_back(straws); } // First set of stereo layers for (unsigned int i=0;i<8;i++){ vectorstraws; if (!GetCDCStereoWires(i+5,numstraws[i+4],zcenter,L,cdc_offsets,straws)) return false; cdcwires.push_back(straws); } // Second axial layer for (unsigned int ring=13;ring<17;ring++){ vectorstraws; if (!GetCDCAxialWires(ring,numstraws[ring-1],zcenter,L,cdc_offsets,straws)) return false; cdcwires.push_back(straws); } // Second set of stereo layers for (unsigned int i=8;i<16;i++){ vectorstraws; if (!GetCDCStereoWires(i+9,numstraws[i+8],zcenter,L,cdc_offsets,straws)) return false; cdcwires.push_back(straws); } // Third axial layer for (unsigned int ring=25;ring<29;ring++){ vectorstraws; if (!GetCDCAxialWires(ring,numstraws[ring-1],zcenter,L,cdc_offsets,straws)) return false; cdcwires.push_back(straws); } // Calculate wire lengths and compute "s" and "t" direction vectors (orthogonal to "u") for (unsigned int i=0;iL=L/cos(w->stereo); // With the addition of close-packed stereo wires, the vector connecting // the center of the wire to the beamline ("s" direction) is not necessarily // perpendicular to the beamline. By definition, we want the "s" direction // to be perpendicular to the wire direction "u" and pointing at the beamline. // // NOTE: This extensive comment is here because the result, when implmented // below caused a WORSE residual distribution in the close-packed stereo // layers. Owing to lack of time currently to track the issue down (most // likely in DReferenceTrajectory) I'm commenting out the "correct" calculation // of s, but leaving this comment so the issue can be revisited later. This // error leads to around 100 micron errors in the C.P.S. wires, but they // are completely washed out when the position smearing of 150 microns is applied // making the error unnoticable except when position smearing is not applied. // // April 2, 2009 D.L. // // Here is how this is calculated -- We define a vector equation with 2 unknowns // Z and S: // // Zz + Ss = W // // where: z = unit vector in z direction // s = unit vector in "s" direction // W = vector pointing to center of wire in lab coordinates // // Rearranging, we get: // // s = (W - Zz)/S // // Since s must be perpendicular to u, we take a dot product of s and u // and set it equal to zero to determine Z: // // u.s = 0 = u.(W - Zz)/S => u.W = Zu.z // // or // // Z = u.W/u.z // // Thus, the s direction is just given by (W - (u.W/u.z)z) // //w->sdir=w->origin-DVector3(0,0,w->origin.Z()); w->sdir = w->origin - DVector3(0.0, 0.0, w->udir.Dot(w->origin)/w->udir.Z()); // see above comments w->sdir.SetMag(1.0); w->tdir = w->udir.Cross(w->sdir); w->tdir.SetMag(1.0); // This isn't really needed } } return true; } //--------------------------------- // GetFDCCathodes //--------------------------------- bool DGeometry::GetFDCCathodes(vector >&fdccathodes) const{ // Get offsets tweaking nominal geometry from calibration database JCalibration * jcalib = dapp->GetJCalibration(runnumber); vector >vals; vectorfdc_cathode_offsets; if (jcalib->Get("FDC/cathode_alignment",vals)==false){ for(unsigned int i=0; i &row = vals[i]; // Get the offsets from the calibration database fdc_cathode_offset_t temp; temp.du=row["dU"]; //temp.du=0.; temp.dphi=row["dPhiU"]; //temp.dphi=0.; fdc_cathode_offsets.push_back(temp); temp.du=row["dV"]; //temp.du=0.; temp.dphi=row["dPhiV"]; //temp.dphi=0.; fdc_cathode_offsets.push_back(temp); } } vectorfdc_cathode_pitches; if (jcalib->Get("FDC/strip_pitches",vals)==false){ for(unsigned int i=0; i &row = vals[i]; // Get the offsets from the calibration database fdc_cathode_pitches.push_back(row["strip_pitch_u"]); fdc_cathode_pitches.push_back(row["strip_pitch_d"]); } } else{ jerr << "Strip pitch calibration unavailable -- setting default..." <temp; for (int j=0; jlayer = i+1; c->strip = j+1; c->angle = angle; c->u=fdc_cathode_pitches[i]*((float)j+STRIP_ZERO_OFFSET)+fdc_cathode_offsets[i].du; temp.push_back(c); } fdccathodes.push_back(temp); } return true; } //--------------------------------- // GetFDCWires //--------------------------------- bool DGeometry::GetFDCWires(vector >&fdcwires) const{ // Get geometrical information from database vectorz_wires; vectorstereo_angles; if(!GetFDCZ(z_wires)) return false; if(!GetFDCStereo(stereo_angles)) return false; // Get offsets tweaking nominal geometry from calibration database JCalibration * jcalib = dapp->GetJCalibration(runnumber); vector >vals; vectorfdc_wire_offsets; if (jcalib->Get("FDC/wire_alignment",vals)==false){ for(unsigned int i=0; i &row = vals[i]; // Get the offsets from the calibration database fdc_wire_offset_t temp; temp.du=row["dU"]; //temp.du=0.; temp.dphi=row["dPhi"]; //temp.dphi=0.; temp.dz=row["dZ"]; // temp.dz=0.; fdc_wire_offsets.push_back(temp); } } // Generate the vector of wire plane parameters for(int i=0; itemp; for(int j=0; jlayer = i+1; w->wire = j+1; w->angle = angle; // find coordinates of center of wire in rotated system float u = U_OF_WIRE_ZERO + WIRE_SPACING*(float)(j); w->u=u+fdc_wire_offsets[i].du; // Rotate coordinates into lab system and set the wire's origin // Note that the FDC measures "angle" such that angle=0 // corresponds to the anode wire in the vertical direction // (i.e. at phi=90 degrees). float x = u*sin(angle + M_PI/2.0); float y = u*cos(angle + M_PI/2.0); w->origin.SetXYZ(x,y,z_wires[i]+fdc_wire_offsets[i].dz); // Length of wire is set by active radius w->L = 2.0*sqrt(pow(FDC_ACTIVE_RADIUS,2.0) - u*u); // Set directions of wire's coordinate system with "udir" // along wire. w->udir.SetXYZ(sin(angle),cos(angle),0.0); // "s" points in direction from beamline to midpoint of // wire. This happens to be the same direction as "origin" w->sdir = w->origin; w->sdir.SetMag(1.0); w->tdir = w->udir.Cross(w->sdir); w->tdir.SetMag(1.0); // This isn't really needed temp.push_back(w); } fdcwires.push_back(temp); } return true; } //--------------------------------- // GetFDCZ //--------------------------------- bool DGeometry::GetFDCZ(vector &z_wires) const { // The FDC geometry is defined as 4 packages, each containing 2 // "module"s and each of those containing 3 "chambers". The modules // are placed as multiple copies in Z using mposZ, but none of the // others are (???). // // This method is currently hardwired to assume 4 packages and // 3 chambers. (The number of modules is discovered via the // "ncopy" attribute of mposZ.) vector ForwardDC; vector forwardDC; vector forwardDC_package[4]; vector forwardDC_module[4]; vector forwardDC_chamber[4][6]; if(!Get("//section/composition/posXYZ[@volume='ForwardDC']/@X_Y_Z", ForwardDC)) return false; if(!Get("//composition[@name='ForwardDC']/posXYZ[@volume='forwardDC']/@X_Y_Z", forwardDC)) return false; if(!Get("//posXYZ[@volume='forwardDC_package_1']/@X_Y_Z", forwardDC_package[0])) return false; if(!Get("//posXYZ[@volume='forwardDC_package_2']/@X_Y_Z", forwardDC_package[1])) return false; if(!Get("//posXYZ[@volume='forwardDC_package_3']/@X_Y_Z", forwardDC_package[2])) return false; if(!Get("//posXYZ[@volume='forwardDC_package_4']/@X_Y_Z", forwardDC_package[3])) return false; if(!Get("//posXYZ[@volume='forwardDC_module_1']/@X_Y_Z", forwardDC_module[0])) return false; if(!Get("//posXYZ[@volume='forwardDC_module_2']/@X_Y_Z", forwardDC_module[1])) return false; if(!Get("//posXYZ[@volume='forwardDC_module_3']/@X_Y_Z", forwardDC_module[2])) return false; if(!Get("//posXYZ[@volume='forwardDC_module_4']/@X_Y_Z", forwardDC_module[3])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_1']/@X_Y_Z/layer[@value='1']", forwardDC_chamber[0][0])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_1']/@X_Y_Z/layer[@value='2']", forwardDC_chamber[0][1])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_1']/@X_Y_Z/layer[@value='3']", forwardDC_chamber[0][2])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_1']/@X_Y_Z/layer[@value='4']", forwardDC_chamber[0][3])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_1']/@X_Y_Z/layer[@value='5']", forwardDC_chamber[0][4])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_1']/@X_Y_Z/layer[@value='6']", forwardDC_chamber[0][5])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_2']/@X_Y_Z/layer[@value='1']", forwardDC_chamber[1][0])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_2']/@X_Y_Z/layer[@value='2']", forwardDC_chamber[1][1])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_2']/@X_Y_Z/layer[@value='3']", forwardDC_chamber[1][2])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_2']/@X_Y_Z/layer[@value='4']", forwardDC_chamber[1][3])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_2']/@X_Y_Z/layer[@value='5']", forwardDC_chamber[1][4])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_2']/@X_Y_Z/layer[@value='6']", forwardDC_chamber[1][5])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_3']/@X_Y_Z/layer[@value='1']", forwardDC_chamber[2][0])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_3']/@X_Y_Z/layer[@value='2']", forwardDC_chamber[2][1])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_3']/@X_Y_Z/layer[@value='3']", forwardDC_chamber[2][2])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_3']/@X_Y_Z/layer[@value='4']", forwardDC_chamber[2][3])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_3']/@X_Y_Z/layer[@value='5']", forwardDC_chamber[2][4])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_3']/@X_Y_Z/layer[@value='6']", forwardDC_chamber[2][5])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_4']/@X_Y_Z/layer[@value='1']", forwardDC_chamber[3][0])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_4']/@X_Y_Z/layer[@value='2']", forwardDC_chamber[3][1])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_4']/@X_Y_Z/layer[@value='3']", forwardDC_chamber[3][2])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_4']/@X_Y_Z/layer[@value='4']", forwardDC_chamber[3][3])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_4']/@X_Y_Z/layer[@value='5']", forwardDC_chamber[3][4])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_4']/@X_Y_Z/layer[@value='6']", forwardDC_chamber[3][5])) return false; // Offset due to global FDC envelopes double zfdc = ForwardDC[2] + forwardDC[2]; // Loop over packages for(int package=1; package<=4; package++){ double z_package = forwardDC_package[package-1][2]; // Each "package" has 1 "module" which is currently positioned at 0,0,0 but // that could in principle change so we add the module z-offset double z_module = forwardDC_module[package-1][2]; // Loop over chambers in this module for(int chamber=1; chamber<=6; chamber++){ double z_chamber = forwardDC_chamber[package-1][chamber-1][2]; double z = zfdc + z_package + z_module + z_chamber; z_wires.push_back(z); } } return true; } //--------------------------------- // GetFDCStereo //--------------------------------- bool DGeometry::GetFDCStereo(vector &stereo_angles) const { // The FDC geometry is defined as 4 packages, each containing 2 // "module"s and each of those containing 3 "chambers". The modules // are placed as multiple copies in Z using mposZ, but none of the // others are (???). // // This method is currently hardwired to assume 4 packages and // 3 chambers. (The number of modules is discovered via the // "ncopy" attribute of mposZ.) // // Stereo angles are assumed to be rotated purely about the z-axis // and the units are not specified, but the XML currently uses degrees. vector forwardDC_module[4]; vector forwardDC_chamber[4][6]; if(!Get("//posXYZ[@volume='forwardDC_module_1']/@X_Y_Z", forwardDC_module[0])) return false; if(!Get("//posXYZ[@volume='forwardDC_module_2']/@X_Y_Z", forwardDC_module[1])) return false; if(!Get("//posXYZ[@volume='forwardDC_module_3']/@X_Y_Z", forwardDC_module[2])) return false; if(!Get("//posXYZ[@volume='forwardDC_module_4']/@X_Y_Z", forwardDC_module[3])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_1']/@rot/layer[@value='1']", forwardDC_chamber[0][0])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_1']/@rot/layer[@value='2']", forwardDC_chamber[0][1])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_1']/@rot/layer[@value='3']", forwardDC_chamber[0][2])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_1']/@rot/layer[@value='4']", forwardDC_chamber[0][3])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_1']/@rot/layer[@value='5']", forwardDC_chamber[0][4])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_1']/@rot/layer[@value='6']", forwardDC_chamber[0][5])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_2']/@rot/layer[@value='1']", forwardDC_chamber[1][0])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_2']/@rot/layer[@value='2']", forwardDC_chamber[1][1])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_2']/@rot/layer[@value='3']", forwardDC_chamber[1][2])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_2']/@rot/layer[@value='4']", forwardDC_chamber[1][3])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_2']/@rot/layer[@value='5']", forwardDC_chamber[1][4])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_2']/@rot/layer[@value='6']", forwardDC_chamber[1][5])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_3']/@rot/layer[@value='1']", forwardDC_chamber[2][0])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_3']/@rot/layer[@value='2']", forwardDC_chamber[2][1])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_3']/@rot/layer[@value='3']", forwardDC_chamber[2][2])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_3']/@rot/layer[@value='4']", forwardDC_chamber[2][3])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_3']/@rot/layer[@value='5']", forwardDC_chamber[2][4])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_3']/@rot/layer[@value='6']", forwardDC_chamber[2][5])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_4']/@rot/layer[@value='1']", forwardDC_chamber[3][0])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_4']/@rot/layer[@value='2']", forwardDC_chamber[3][1])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_4']/@rot/layer[@value='3']", forwardDC_chamber[3][2])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_4']/@rot/layer[@value='4']", forwardDC_chamber[3][3])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_4']/@rot/layer[@value='5']", forwardDC_chamber[3][4])) return false; if(!Get("//posXYZ[@volume='forwardDC_chamber_4']/@rot/layer[@value='6']", forwardDC_chamber[3][5])) return false; // Loop over packages for(int package=1; package<=4; package++){ // Loop over chambers for(int chamber=1; chamber<=6; chamber++){ // if (chamber==4) forwardDC_chamber[package-1][chamber-1][2]+=15.0; stereo_angles.push_back(forwardDC_chamber[package-1][chamber-1][2]); } } return true; } //--------------------------------- // GetFDCRmin //--------------------------------- bool DGeometry::GetFDCRmin(vector &rmin_packages) const { vector FDA[4]; if(!Get("//section[@name='ForwardDC']/tubs[@name='FDA1']/@Rio_Z", FDA[0])) return false; if(!Get("//section[@name='ForwardDC']/tubs[@name='FDA2']/@Rio_Z", FDA[1])) return false; if(!Get("//section[@name='ForwardDC']/tubs[@name='FDA3']/@Rio_Z", FDA[2])) return false; if(!Get("//section[@name='ForwardDC']/tubs[@name='FDA4']/@Rio_Z", FDA[3])) return false; rmin_packages.push_back(FDA[0][0]); rmin_packages.push_back(FDA[1][0]); rmin_packages.push_back(FDA[2][0]); rmin_packages.push_back(FDA[3][0]); return true; } //--------------------------------- // GetFDCRmax //--------------------------------- bool DGeometry::GetFDCRmax(double &rmax_active_fdc) const { // We assume that all packages have the same outer radius of the // active area. vector FDA1; bool good = Get("//section[@name='ForwardDC']/tubs[@name='FDA1']/@Rio_Z", FDA1); if(!good){ _DBG_<<"Unable to retrieve FDC Rmax values."< Rio_Z; bool good = Get("//section[@name='CentralDC']/tubs[@name='STRW']/@Rio_Z", Rio_Z); cdc_axial_length = Rio_Z[2]; if(!good){ _DBG_<<"Unable to retrieve CDC axial wire length"< &cdc_stereo) const { return false; } //--------------------------------- // GetCDCRmid //--------------------------------- bool DGeometry::GetCDCRmid(vector &cdc_rmid) const { return false; } //--------------------------------- // GetCDCNwires //--------------------------------- bool DGeometry::GetCDCNwires(vector &cdc_nwires) const { return false; } //--------------------------------- // GetCDCEndplate //--------------------------------- bool DGeometry::GetCDCEndplate(double &z,double &dz,double &rmin,double &rmax) const{ vectorcdc_origin; vectorcdc_center; vectorcdc_endplate_pos; vectorcdc_endplate_dim; if(!Get("//posXYZ[@volume='CentralDC'/@X_Y_Z",cdc_origin)) return false; if(!Get("//posXYZ[@volume='centralDC']/@X_Y_Z",cdc_center)) return false; if(!Get("//posXYZ[@volume='CDPD']/@X_Y_Z",cdc_endplate_pos)) return false; if(!Get("//tubs[@name='CDPD']/@Rio_Z",cdc_endplate_dim)) return false; if(cdc_origin.size()<3){ _DBG_<<"cdc_origin.size()<3 !"< Phi0; bool good = Get("//BarrelEMcal_s/section/composition/mposPhi/@Phi0", Phi0); if(!good) return false; if(Phi0.size() == 1){ bcal_phi_shift = Phi0[0]; return true; }else{ bcal_phi_shift = 0.0; return false; } } //--------------------------------- // GetFCALZ //--------------------------------- bool DGeometry::GetFCALZ(double &z_fcal) const { vector ForwardEMcalpos; bool good = Get("//section/composition/posXYZ[@volume='ForwardEMcal']/@X_Y_Z", ForwardEMcalpos); if(!good){ _DBG_<<"Unable to retrieve ForwardEMcal position."< &z_tof) const { vector ForwardTOF; vector forwardTOF[2]; vector FTOC; if(!Get("//section/composition/posXYZ[@volume='ForwardTOF']/@X_Y_Z", ForwardTOF)) return false; if(!Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='0']", forwardTOF[0])) return false; if(!Get("//composition[@name='ForwardTOF']/posXYZ[@volume='forwardTOF']/@X_Y_Z/plane[@value='1']", forwardTOF[1])) return false; if(!Get("//box[@name='FTOC' and sensitive='true']/@X_Y_Z", FTOC)) return false; z_tof.push_back(ForwardTOF[2] + forwardTOF[0][2] - FTOC[2]/2.0); z_tof.push_back(ForwardTOF[2] + forwardTOF[1][2] - FTOC[2]/2.0); return true; } //--------------------------------- // GetTargetZ //--------------------------------- bool DGeometry::GetTargetZ(double &z_target) const { vector xyz_vessel; vector xyz_target; vector xyz_detector; z_target=65.; if(!Get("//composition[@name='targetVessel']/posXYZ[@volume='targetTube']/@X_Y_Z", xyz_vessel)) return false; if(!Get("//composition[@name='Target']/posXYZ[@volume='targetVessel']/@X_Y_Z", xyz_target)) return false; if(!Get("//composition[@name='GlueXdetector']/posXYZ[@volume='Target']/@X_Y_Z", xyz_detector)) return false; z_target = xyz_vessel[2] + xyz_target[2] + xyz_detector[2]; return true; } //--------------------------------- // GetTargetLength //--------------------------------- bool DGeometry::GetTargetLength(double &target_length) const { vector zLength; bool good = Get("//section[@name='Target']/pcon[@name='LIH2']/real[@name='length']/[@value]", zLength); target_length = good ? zLength[0]:0.0; return good; } // Get vectors of positions and norm vectors for start counter from XML bool DGeometry::GetStartCounterGeom(vector >&pos, vector >&norm ) const{ // Check if Start Counter geometry is present vector sc_origin; bool got_sc = Get("//posXYZ[@volume='StartCntr']/@X_Y_Z", sc_origin); if(got_sc){ // z-position at upstream face of scintillators. double z0=sc_origin[2]; // Get rotation angles vectorsc_rot_angles; Get("//posXYZ[@volume='StartCntr']/@rot", sc_rot_angles); double ThetaX=sc_rot_angles[0]*M_PI/180.; double ThetaY=sc_rot_angles[1]*M_PI/180.; double ThetaZ=sc_rot_angles[2]*M_PI/180.; double num_paddles; Get("//mposPhi[@volume='STRC']/@ncopy",num_paddles); double dSCdphi = M_TWO_PI/num_paddles; double Phi0; Get("///mposPhi[@volume='STRC']/@Phi0",Phi0); double dSCphi0 =Phi0*M_PI/180.; vector > sc_rioz; GetMultiple("//pgon[@name='STRC']/polyplane/@Rio_Z", sc_rioz); // Create vectors of positions and normal vectors for each paddle for (unsigned int i=0;i<30;i++){ double phi=dSCphi0+dSCdphi*double(i); double sinphi=sin(phi); double cosphi=cos(phi); double r=0.5*(sc_rioz[0][0]+sc_rioz[0][1]); DVector3 oldray; // Rotate by phi and take into account the tilt DVector3 ray(r*cosphi,r*sinphi,sc_rioz[0][2]); ray.RotateX(ThetaX); ray.RotateY(ThetaY); ray.RotateZ(ThetaZ); // Create stl-vectors to store positions and norm vectors vectorposvec; vectordirvec; // Loop over radial/z positions describing start counter geometry from xml for(unsigned int k = 1; k < sc_rioz.size(); ++k){ oldray=ray; r=0.5*(sc_rioz[k][0]+sc_rioz[k][1]); // Point in midplane of scintillator ray.SetXYZ(r*cosphi,r*sinphi,sc_rioz[k][2]); // Second point in the plane of the scintillator DVector3 ray2(r*cosphi-10.0*sinphi,r*sinphi+10.0*cosphi,sc_rioz[k][2]); // Take into account tilt ray.RotateX(ThetaX); ray.RotateY(ThetaY); ray.RotateZ(ThetaZ); ray2.RotateX(ThetaX); ray2.RotateY(ThetaY); ray2.RotateZ(ThetaZ); // Store one position on current plane posvec.push_back(DVector3(oldray.X(),oldray.Y(),oldray.Z()+z0)); // Compute normal vector to plane DVector3 dir=(ray-oldray).Cross(ray2-oldray); dir.SetMag(1.); dirvec.push_back(dir); } pos.push_back(posvec); norm.push_back(dirvec); posvec.clear(); dirvec.clear(); } } return got_sc; }