00001
00002
00003
00004
00005 #include "GaudiKernel/ToolFactory.h"
00006 #include "GaudiKernel/SystemOfUnits.h"
00007
00008
00009 #include "MagFieldToolDC06.h"
00010
00011 #include <fstream>
00012 #include <cstring>
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 DECLARE_TOOL_FACTORY( MagFieldToolDC06 );
00023
00024
00025
00026
00027
00028 MagFieldToolDC06::MagFieldToolDC06( const std::string& type,
00029 const std::string& name,
00030 const IInterface* parent )
00031 : GaudiTool ( type, name , parent ),
00032 m_mapFileName(""),
00033 m_scaleFactor(0)
00034 {
00035 declareInterface<IMagFieldTool>(this);
00036 }
00037
00038
00039
00040 MagFieldToolDC06::~MagFieldToolDC06() {}
00041
00042
00043
00044
00045 StatusCode MagFieldToolDC06::updateMap( const std::vector<std::string>& theFiles,
00046 const double& scaleFactor )
00047 {
00048
00049 if( theFiles.size() != 1 )
00050 return Error( "DC06 field map requires one input file" );
00051
00052
00053 if( scaleFactor == m_scaleFactor &&
00054 theFiles[0] == m_mapFileName ) {
00055 debug() << "Update called but nothing has changed, returning..." << endmsg;
00056 return StatusCode::SUCCESS;
00057 }
00058
00059
00060
00061 if( theFiles[0] != m_mapFileName || fabs(m_scaleFactor) < 1.e-6 ) {
00062 StatusCode sc = readFile( theFiles[0], scaleFactor );
00063 if( sc.isFailure() ) return sc;
00064 m_mapFileName = theFiles[0];
00065 m_scaleFactor = scaleFactor;
00066 info() << "Map scaled by factor " << m_scaleFactor << endmsg;
00067 }
00068 else {
00069
00070 double rescaleFactor = scaleFactor / m_scaleFactor;
00071 rescale( rescaleFactor );
00072 m_scaleFactor = scaleFactor;
00073 info() << "Map scaled by factor " << m_scaleFactor << endmsg;
00074 }
00075 return StatusCode::SUCCESS;
00076 }
00077
00078
00079
00080
00081
00082 StatusCode MagFieldToolDC06::readFile( const std::string& theFile,
00083 const double& scaleFactor )
00084 {
00085 std::ifstream infile( theFile.c_str() );
00086 if ( infile ) {
00087 info() << "Opened magnetic field file : " << theFile << endmsg;
00088
00089
00090 m_Q.clear();
00091
00092
00093 char line[ 255 ];
00094 do{
00095 infile.getline( line, 255 );
00096 } while( line[0] != 'P' );
00097
00098
00099 std::string sPar[2];
00100 char* token = strtok( line, " " );
00101 int ip = 0;
00102 do{
00103 if ( token ) { sPar[ip] = token; token = strtok( NULL, " " );}
00104 else continue;
00105 ip++;
00106 } while ( token != NULL );
00107 long int npar = atoi( sPar[1].c_str() );
00108
00109
00110 do{
00111 infile.getline( line, 255 );
00112 } while( line[0] != 'G' );
00113
00114
00115 do{
00116 infile.getline( line, 255 );
00117 } while( line[0] != '#' );
00118
00119
00120 infile.getline( line, 255 );
00121 std::string sGeom[7];
00122 token = strtok( line, " " );
00123 int ig = 0;
00124 do{
00125 if ( token ) { sGeom[ig] = token; token = strtok( NULL, " " );}
00126 else continue;
00127 ig++;
00128 } while (token != NULL);
00129
00130
00131 m_Dxyz[0] = atof( sGeom[0].c_str() ) * Gaudi::Units::cm;
00132 m_Dxyz[1] = atof( sGeom[1].c_str() ) * Gaudi::Units::cm;
00133 m_Dxyz[2] = atof( sGeom[2].c_str() ) * Gaudi::Units::cm;
00134 m_Nxyz[0] = atoi( sGeom[3].c_str() );
00135 m_Nxyz[1] = atoi( sGeom[4].c_str() );
00136 m_Nxyz[2] = atoi( sGeom[5].c_str() );
00137 m_zOffSet = atof( sGeom[6].c_str() ) * Gaudi::Units::cm;
00138
00139 m_Q.clear();
00140 m_Q.reserve(npar - 7);
00141
00142 long int nlines = ( npar - 7 ) / 3;
00143
00144
00145 long int ncheck = 0;
00146
00147
00148
00149
00150 while( infile ) {
00151
00152
00153 infile.getline( line, 255 );
00154 if ( line[0] == '#' ) continue;
00155 std::string sFx, sFy, sFz;
00156 char* token = strtok( line, " " );
00157 if ( token ) { sFx = token; token = strtok( NULL, " " );} else continue;
00158 if ( token ) { sFy = token; token = strtok( NULL, " " );} else continue;
00159 if ( token ) { sFz = token; token = strtok( NULL, " " );} else continue;
00160 if ( token != NULL ) continue;
00161
00162
00163 double fx = atof( sFx.c_str() ) * Gaudi::Units::gauss * scaleFactor;
00164 double fy = atof( sFy.c_str() ) * Gaudi::Units::gauss * scaleFactor;
00165 double fz = atof( sFz.c_str() ) * Gaudi::Units::gauss * scaleFactor;
00166
00167
00168
00169 m_Q.push_back( fx );
00170 m_Q.push_back( fy );
00171 m_Q.push_back( fz );
00172
00173 ncheck++;
00174 }
00175 infile.close();
00176 if ( nlines != ncheck ) {
00177 return Error( " Number of points in field map does not match" );
00178 }
00179 }
00180 else {
00181 return Error( "Unable to open magnetic field file : " + theFile );
00182 }
00183
00184
00185 for (int iC = 0; iC< 3; ++iC ){
00186 m_min_FL[iC] = 0.0;
00187 m_max_FL[iC] = m_min_FL[iC]+( m_Nxyz[iC]-1 )* m_Dxyz[iC];
00188 }
00189
00190 return StatusCode::SUCCESS;
00191 }
00192
00193
00194
00195
00196 void MagFieldToolDC06::rescale( const double& rescaleFactor )
00197 {
00198 for ( std::vector<double>::iterator Q = m_Q.begin(); Q != m_Q.end(); ++Q ) {
00199 *Q = (*Q) * rescaleFactor;
00200 }
00201 }
00202
00203
00204
00205 void MagFieldToolDC06::fieldVector( const Gaudi::XYZPoint& r,
00206 Gaudi::XYZVector& bf ) const
00207 {
00208 bf.SetXYZ( 0.0, 0.0, 0.0 );
00209
00211 double z = r.z() - m_zOffSet;
00212 if( !(z >= m_min_FL[2] && z < m_max_FL[2]) ) return;
00213 double x = fabs( r.x() );
00214 if( !(x >= m_min_FL[0] && x < m_max_FL[0]) ) return;
00215 double y = fabs( r.y() );
00216 if( !(y >= m_min_FL[1] && y < m_max_FL[1]) ) return;
00217 int i = int( x/m_Dxyz[0]);
00218 int j = int( y/m_Dxyz[1] );
00219 int k = int( z/m_Dxyz[2] );
00220
00221 int ijk000 = 3*( m_Nxyz[0]*( m_Nxyz[1]*k + j ) + i );
00222 int ijk001 = 3*( m_Nxyz[0]*( m_Nxyz[1]*(k+1) + j ) + i );
00223 int ijk010 = 3*( m_Nxyz[0]*( m_Nxyz[1]*k + j + 1 ) + i );
00224 int ijk011 = 3*( m_Nxyz[0]*( m_Nxyz[1]*(k+1) + j + 1) + i );
00225 int ijk100 = 3*( m_Nxyz[0]*( m_Nxyz[1]*k + j) + i + 1 );
00226 int ijk101 = 3*( m_Nxyz[0]*( m_Nxyz[1]*(k+1) + j) + i + 1 );
00227 int ijk110 = 3*( m_Nxyz[0]*( m_Nxyz[1]*k + j + 1) + i + 1 );
00228 int ijk111 = 3*( m_Nxyz[0]*( m_Nxyz[1]*(k+1) + j + 1 ) + i + 1 );
00229
00230
00231
00232
00233 double cx000,cx001,cx010,cx011,cx100,cx101,cx110,cx111,
00234 cy000,cy001,cy010,cy011,cy100,cy101,cy110,cy111,
00235 cz000,cz001,cz010,cz011,cz100,cz101,cz110,cz111;
00236
00237 cx000 = m_Q[ ijk000 ];
00238 cx001 = m_Q[ ijk001 ];
00239 cx010 = m_Q[ ijk010 ];
00240 cx011 = m_Q[ ijk011 ];
00241 cx100 = m_Q[ ijk100 ];
00242 cx101 = m_Q[ ijk101 ];
00243 cx110 = m_Q[ ijk110 ];
00244 cx111 = m_Q[ ijk111 ];
00245 cy000 = m_Q[ ijk000+1 ];
00246 cy001 = m_Q[ ijk001+1 ];
00247 cy010 = m_Q[ ijk010+1 ];
00248 cy011 = m_Q[ ijk011+1 ];
00249 cy100 = m_Q[ ijk100+1 ];
00250 cy101 = m_Q[ ijk101+1 ];
00251 cy110 = m_Q[ ijk110+1 ];
00252 cy111 = m_Q[ ijk111+1 ];
00253 cz000 = m_Q[ ijk000+2 ];
00254 cz001 = m_Q[ ijk001+2 ];
00255 cz010 = m_Q[ ijk010+2 ];
00256 cz011 = m_Q[ ijk011+2 ];
00257 cz100 = m_Q[ ijk100+2 ];
00258 cz101 = m_Q[ ijk101+2 ];
00259 cz110 = m_Q[ ijk110+2 ];
00260 cz111 = m_Q[ ijk111+2 ];
00261
00262 double hx1 = ( x-i*m_Dxyz[0] )/m_Dxyz[0];
00263 double hy1 = ( y-j*m_Dxyz[1] )/m_Dxyz[1];
00264 double hz1 = ( z-k*m_Dxyz[2] )/m_Dxyz[2];
00265 double hx0 = 1.0-hx1;
00266 double hy0 = 1.0-hy1;
00267 double hz0 = 1.0-hz1;
00268
00269 double h000 = hx0*hy0*hz0;
00270 if( fabs(h000) > 0.0 &&
00271 cx000 > 9.0e5 && cy000 > 9.0e5 && cz000 > 9.0e5) return;
00272
00273 double h001 = hx0*hy0*hz1;
00274 if( fabs(h001) > 0.0 &&
00275 cx001 > 9.0e5 && cy001 > 9.0e5 && cz001 > 9.0e5) return;
00276
00277 double h010 = hx0*hy1*hz0;
00278 if( fabs(h010) > 0.0 &&
00279 cx010 > 9.0e5 && cy010 > 9.0e5 && cz010 > 9.0e5) return;
00280
00281 double h011 = hx0*hy1*hz1;
00282 if( fabs(h011) > 0.0 &&
00283 cx011 > 9.0e5 && cy011 > 9.0e5 && cz011 > 9.0e5) return;
00284
00285 double h100 = hx1*hy0*hz0;
00286 if( fabs(h100) > 0.0 &&
00287 cx100 > 9.0e5 && cy100 > 9.0e5 && cz100 > 9.0e5) return;
00288
00289 double h101 = hx1*hy0*hz1;
00290 if( fabs(h101) > 0.0 &&
00291 cx101 > 9.0e5 && cy101 > 9.0e5 && cz101 > 9.0e5) return;
00292
00293 double h110 = hx1*hy1*hz0;
00294 if( fabs(h110) > 0.0 &&
00295 cx110 > 9.0e5 && cy110 > 9.0e5 && cz110 > 9.0e5) return;
00296
00297 double h111 = hx1*hy1*hz1;
00298 if( fabs(h111) > 0.0 &&
00299 cx111 > 9.0e5 && cy111 > 9.0e5 && cz111 > 9.0e5) return;
00300
00301 bf.SetX ( cx000*h000 + cx001*h001 + cx010*h010 + cx011*h011 +
00302 cx100*h100 + cx101*h101 + cx110*h110 + cx111*h111);
00303 bf.SetY ( cy000*h000 + cy001*h001 + cy010*h010 + cy011*h011 +
00304 cy100*h100 + cy101*h101 + cy110*h110 + cy111*h111 );
00305 bf.SetZ ( cz000*h000 + cz001*h001 + cz010*h010 + cz011*h011 +
00306 cz100*h100 + cz101*h101 + cz110*h110 + cz111*h111 );
00307
00308 if( r.x() < 0. && r.y() >= 0. ){
00309 bf.SetX( -bf.x() );
00310 }
00311 else if( r.x() < 0. && r.y() < 0. ){
00312 bf.SetZ( -bf.z() );
00313 }
00314 else if( r.x() >= 0. && r.y() < 0. ){
00315 bf.SetX( -bf.x() );
00316 bf.SetZ( -bf.z() );
00317 }
00318
00319 return;
00320 }