28 #include <basic/options/option.hh>
29 #include <basic/Tracer.hh>
31 #include <numeric/constants.hh>
32 #include <numeric/fourier/FFT.hh>
33 #include <numeric/xyzMatrix.hh>
34 #include <numeric/xyzVector.hh>
35 #include <numeric/xyz.functions.hh>
36 #include <numeric/xyzVector.io.hh>
37 #include <numeric/statistics.functions.hh>
42 #include <basic/options/keys/edensity.OptionKeys.gen.hh>
45 #include <utility/string_util.hh>
60 #define _USE_MATH_DEFINES
68 namespace electron_density_atomwise {
71 using namespace basic::options;
78 static basic::Tracer
TR (
"core.scoring.electron_density_atomwise.ElectronDensityAtomwise" );
84 is_map_loaded =
false;
85 is_score_precomputed =
false;
99 inline float d2r (
float d ) {
100 return ( d * M_PI / 180.0 );
102 inline double d2r (
double d ) {
103 return ( d * M_PI / 180.0 );
121 float r = std::fmod ( x, y );
127 inline double pos_mod (
double x,
double y ) {
128 double r = std::fmod ( x, y );
138 int *data = (
int * ) v;
142 for ( i = 0; i < ndata; i++ ) {
144 *N = ( ( ( *N >> 24 ) & 0xff ) | ( ( *N & 0xff ) << 24 ) | ( ( *N >> 8 ) & 0xff00 ) | ( ( *N & 0xff00 ) << 8 ) );
152 core::Real ca = cos (
d2r ( cell_angles[0] ) ), cb = cos (
d2r ( cell_angles[1] ) ), cg = cos (
d2r ( cell_angles[2] ) );
153 core::Real sa = sin (
d2r ( cell_angles[0] ) ), sb = sin (
d2r ( cell_angles[1] ) ), sg = sin (
d2r ( cell_angles[2] ) );
156 cell_dimensions[0] , cell_dimensions[1] * cg, cell_dimensions[2] * cb,
157 0.0, cell_dimensions[1] * sg, cell_dimensions[2] * ( ca - cb * cg ) / sg,
158 0.0, 0.0 , cell_dimensions[2] * sb * sqrt ( 1.0 -
square ( ( cb * cg - ca ) / ( sb * sg ) ) ) );
162 TR <<
"[ WARNING ] Invalid crystal cell dimensions." << std::endl;
168 ( f2c ( 2, 2 ) * f2c ( 3, 3 ) - f2c ( 2, 3 ) * f2c ( 3, 2 ) ) / D,
169 - ( f2c ( 1, 2 ) * f2c ( 3, 3 ) - f2c ( 1, 3 ) * f2c ( 3, 2 ) ) / D,
170 ( f2c ( 1, 2 ) * f2c ( 2, 3 ) - f2c ( 1, 3 ) * f2c ( 2, 2 ) ) / D,
171 - ( f2c ( 2, 1 ) * f2c ( 3, 3 ) - f2c ( 3, 1 ) * f2c ( 2, 3 ) ) / D,
172 ( f2c ( 1, 1 ) * f2c ( 3, 3 ) - f2c ( 1, 3 ) * f2c ( 3, 1 ) ) / D,
173 - ( f2c ( 1, 1 ) * f2c ( 2, 3 ) - f2c ( 1, 3 ) * f2c ( 2, 1 ) ) / D,
174 ( f2c ( 2, 1 ) * f2c ( 3, 2 ) - f2c ( 3, 1 ) * f2c ( 2, 2 ) ) / D,
175 - ( f2c ( 1, 1 ) * f2c ( 3, 2 ) - f2c ( 1, 2 ) * f2c ( 3, 1 ) ) / D,
176 ( f2c ( 1, 1 ) * f2c ( 2, 2 ) - f2c ( 1, 2 ) * f2c ( 2, 1 ) ) / D );
177 cell_volume = cell_dimensions[0] * cell_dimensions[1] * cell_dimensions[2] * sqrt ( 1 -
square ( ca ) -
square ( cb ) -
square ( cg ) + 2 * ca * cb * cg );
179 r_cell_dimensions[0] = cell_dimensions[1] * cell_dimensions[2] * sa / cell_volume;
180 r_cell_dimensions[1] = cell_dimensions[0] * cell_dimensions[2] * sb / cell_volume;
181 r_cell_dimensions[2] = cell_dimensions[0] * cell_dimensions[1] * sg / cell_volume;
182 cos_r_cell_angles[0] = cos ( asin ( std::min ( std::max ( cell_volume / ( cell_dimensions[0] * cell_dimensions[1] * cell_dimensions[2] * sb * sg ) , -1.0 ) , 1.0 ) ) );
183 cos_r_cell_angles[1] = cos ( asin ( std::min ( std::max ( cell_volume / ( cell_dimensions[0] * cell_dimensions[1] * cell_dimensions[2] * sa * sg ) , -1.0 ) , 1.0 ) ) );
184 cos_r_cell_angles[2] = cos ( asin ( std::min ( std::max ( cell_volume / ( cell_dimensions[0] * cell_dimensions[1] * cell_dimensions[2] * sa * sb ) , -1.0 ) , 1.0 ) ) );
185 r_cell_volume = 1.0 / cell_volume;
193 if ( symList.size() == 0 ) {
198 for (
int i = 1; i <= (
int ) symList.size(); ++i ) {
202 if ( rows.size() != 3 ) {
203 TR.Error <<
"[ ERROR ] invalid symmop in map file" << std::endl;
204 TR.Error << line << std::endl;
205 TR.Error <<
"Setting symmetry to P1 and continuing!" << line << std::endl;
218 for (
int j = 0; j < 3; ++j ) {
219 k = rows[j+1].find (
'/' );
221 if ( k != (
int ) std::string::npos ) {
223 int startNum = rows[j+1].find_last_not_of (
"0123456789", k - 1 ) + 1;
224 int startDenom = k + 1;
225 float denom = std::atof ( &rows[j+1][startDenom] );
227 trans[j] = std::atof ( &rows[j+1][startNum] ) / denom;
232 if ( rows[j+1].find (
"-X" ) != std::string::npos )
233 rot ( j + 1, 1 ) = -1;
234 else if ( rows[j+1].find (
"X" ) != std::string::npos )
235 rot ( j + 1, 1 ) = 1;
237 if ( rows[j+1].find (
"-Y" ) != std::string::npos )
238 rot ( j + 1, 2 ) = -1;
239 else if ( rows[j+1].find (
"Y" ) != std::string::npos )
240 rot ( j + 1, 2 ) = 1;
242 if ( rows[j+1].find (
"-Z" ) != std::string::npos )
243 rot ( j + 1, 3 ) = -1;
244 else if ( rows[j+1].find (
"Z" ) != std::string::npos )
245 rot ( j + 1, 3 ) = 1;
248 symmOps.push_back ( RT ( rot, trans ) );
262 if ( grid[0] == extent[0] && grid[1] == extent[1] && grid[2] == extent[2] )
265 ObjexxFCL::FArray3D< float > newDensity ( grid[0], grid[1], grid[2], 0.0 );
267 int limX = std::min ( extent[0], grid[0] ),
268 limY = std::min ( extent[1], grid[1] ),
269 limZ = std::min ( extent[2], grid[2] );
271 for (
int x = 1; x <= limX; ++x )
272 for (
int y = 1; y <= limY; ++y )
273 for (
int z = 1; z <= limZ; ++z ) {
274 newDensity ( x, y, z ) = density ( x, y, z );
279 for (
int x = grid[0]; x >= 1; --x )
280 for (
int y = grid[1]; y >= 1; --y )
281 for (
int z = grid[2]; z >= 1; --z ) {
282 if ( x <= limX && y <= limY && z <= limZ )
288 ( (
core::Real ) z + orig[2] - 1 ) / grid[2] );
290 for (
int symm_idx = 1; symm_idx <= (
int ) symmOps.size(); symm_idx++ ) {
292 symmOps[symm_idx].get_rotation() * fracX + symmOps[symm_idx].get_translation();
294 int Sx =
pos_mod ( (
int ) floor ( SfracX[0] * grid[0] + 0.5 - orig[0] ) , grid[0] ) + 1;
295 int Sy =
pos_mod ( (
int ) floor ( SfracX[1] * grid[1] + 0.5 - orig[1] ) , grid[1] ) + 1 ;
296 int Sz =
pos_mod ( (
int ) floor ( SfracX[2] * grid[2] + 0.5 - orig[2] ) , grid[2] ) + 1 ;
298 if ( Sx <= limX && Sy <= limY && Sz <= limZ ) {
299 newDensity ( x, y, z ) = density ( Sx, Sy, Sz );
305 density = newDensity;
312 if ( grid[0] != density.u1() || grid[1] != density.u2() || grid[2] != density.u3() ) {
313 TR <<
"[ ERROR ] resize() not supported for maps not covering the entire unit cell." << std::endl;
314 TR <<
" " << grid[0] <<
" != " << density.u1()
315 <<
" || " << grid[1] <<
" != " << density.u2()
316 <<
" || " << grid[2] <<
" != " << density.u3() << std::endl;
323 newDims[0] = (
int ) floor ( cell_dimensions[0] / approxGridSpacing + 0.5 );
324 newDims[1] = (
int ) floor ( cell_dimensions[1] / approxGridSpacing + 0.5 );
325 newDims[2] = (
int ) floor ( cell_dimensions[2] / approxGridSpacing + 0.5 );
326 newOri[0] = newDims[0] * orig[0] / ( (
core::Real ) grid[0] );
327 newOri[1] = newDims[1] * orig[1] / ( (
core::Real ) grid[1] );
328 newOri[2] = newDims[2] * orig[2] / ( (
core::Real ) grid[2] );
330 ObjexxFCL::FArray3D< std::complex<double> > newDensity;
331 newDensity.dimension ( newDims[0], newDims[1], newDims[2] );
332 TR <<
"Resizing " << density.u1() <<
"x" << density.u2() <<
"x" << density.u3() <<
" to "
333 << newDensity.u1() <<
"x" << newDensity.u2() <<
"x" << newDensity.u3() << std::endl;
335 ObjexxFCL::FArray3D< std::complex<double> > Foldmap, Fnewmap;
336 Fnewmap.dimension ( newDims[0], newDims[1], newDims[2] );
338 ObjexxFCL::FArray3D< std::complex<double> > cplx_density;
339 cplx_density.dimension ( density.u1() , density.u2() , density.u3() );
341 for (
int i = 0; i < density.u1() *density.u2() *density.u3(); ++i ) cplx_density[i] = (
double ) density[i];
343 numeric::fourier::fft3 ( cplx_density, Foldmap );
346 for (
int i = 0; i < Fnewmap.u1() *Fnewmap.u2() *Fnewmap.u3(); ++i ) Fnewmap[i] = std::complex<double> ( 0, 0 );
349 std::min ( Foldmap.u2(), Fnewmap.u2() ) / 2,
350 std::min ( Foldmap.u3(), Fnewmap.u3() ) / 2 );
351 numeric::xyzVector<int> nyqplus1_old ( std::max ( Foldmap.u1() - ( std::min ( Foldmap.u1(), Fnewmap.u1() ) - nyq[0] ) + 1 , nyq[0] + 1 ) ,
352 std::max ( Foldmap.u2() - ( std::min ( Foldmap.u2(), Fnewmap.u2() ) - nyq[1] ) + 1 , nyq[1] + 1 ) ,
353 std::max ( Foldmap.u3() - ( std::min ( Foldmap.u3(), Fnewmap.u3() ) - nyq[2] ) + 1 , nyq[2] + 1 ) );
354 numeric::xyzVector<int> nyqplus1_new ( std::max ( Fnewmap.u1() - ( std::min ( Foldmap.u1(), Fnewmap.u1() ) - nyq[0] ) + 1 , nyq[0] + 1 ) ,
355 std::max ( Fnewmap.u2() - ( std::min ( Foldmap.u2(), Fnewmap.u2() ) - nyq[1] ) + 1 , nyq[1] + 1 ) ,
356 std::max ( Fnewmap.u3() - ( std::min ( Foldmap.u3(), Fnewmap.u3() ) - nyq[2] ) + 1 , nyq[2] + 1 ) );
358 for (
int i = 1; i <= Fnewmap.u1(); i++ )
359 for (
int j = 1; j <= Fnewmap.u2(); j++ )
360 for (
int k = 1; k <= Fnewmap.u3(); k++ ) {
361 if ( i - 1 <= nyq[0] ) {
362 if ( j - 1 <= nyq[1] ) {
363 if ( k - 1 <= nyq[2] )
364 Fnewmap ( i, j, k ) = Foldmap ( i, j, k );
365 else if ( k - 1 >= nyqplus1_new[2] )
366 Fnewmap ( i, j, k ) = Foldmap ( i, j, k - nyqplus1_new[2] + nyqplus1_old[2] );
367 }
else if ( j - 1 >= nyqplus1_new[1] ) {
368 if ( k - 1 <= nyq[2] )
369 Fnewmap ( i, j, k ) = Foldmap ( i, j - nyqplus1_new[1] + nyqplus1_old[1], k );
370 else if ( k - 1 >= nyqplus1_new[2] )
371 Fnewmap ( i, j, k ) = Foldmap ( i, j - nyqplus1_new[1] + nyqplus1_old[1], k - nyqplus1_new[2] + nyqplus1_old[2] );
373 }
else if ( i - 1 >= nyqplus1_new[0] ) {
374 if ( j - 1 <= nyq[1] ) {
375 if ( k - 1 <= nyq[2] )
376 Fnewmap ( i, j, k ) = Foldmap ( i - nyqplus1_new[0] + nyqplus1_old[0], j, k );
377 else if ( k - 1 >= nyqplus1_new[2] )
378 Fnewmap ( i, j, k ) = Foldmap ( i - nyqplus1_new[0] + nyqplus1_old[0], j, k - nyqplus1_new[2] + nyqplus1_old[2] );
379 }
else if ( j - 1 >= nyqplus1_new[1] ) {
380 if ( k - 1 <= nyq[2] )
381 Fnewmap ( i, j, k ) = Foldmap ( i - nyqplus1_new[0] + nyqplus1_old[0], j - nyqplus1_new[1] + nyqplus1_old[1], k );
382 else if ( k - 1 >= nyqplus1_new[2] )
383 Fnewmap ( i, j, k ) = Foldmap ( i - nyqplus1_new[0] + nyqplus1_old[0],
384 j - nyqplus1_new[1] + nyqplus1_old[1],
385 k - nyqplus1_new[2] + nyqplus1_old[2] );
391 numeric::fourier::ifft3 ( Fnewmap, newDensity );
393 density.dimension ( newDims[0], newDims[1], newDims[2] );
395 for (
int i = 0; i < newDims[0]*newDims[1]*newDims[2] ; ++i )
396 density[i] = (
float ) newDensity[i].real();
400 TR <<
" new extent: " << density.u1() <<
" x " << density.u2() <<
" x " << density.u3() << std::endl;
401 TR <<
" new origin: " << orig[0] <<
" x " << orig[1] <<
" x " << orig[2] << std::endl;
402 TR <<
" new grid: " << grid[0] <<
" x " << grid[1] <<
" x " << grid[2] << std::endl;
409 TR <<
"Loading Density Map" << std::endl;
411 if ( !basic::options::option[ basic::options::OptionKeys::edensity::mapfile ].user() ) {
412 utility_exit_with_message (
"No density map specified for electron density scoring." );
415 std::string map_file = basic::options::option[ basic::options::OptionKeys::edensity::mapfile ]();
416 map_reso = basic::options::option[ basic::options::OptionKeys::edensity::mapreso ]();
417 grid_spacing = basic::options::option[ basic::options::OptionKeys::edensity::grid_spacing ]();
418 std::fstream mapin ( map_file.c_str() , std::ios::binary | std::ios::in );
419 char mapString[4], symData[81];
420 int crs2xyz[3], extent[3], mode, symBytes, origin_xyz[3];
421 int xyz2crs[3], vol_xsize, vol_ysize, vol_zsize;
422 int xIndex, yIndex, zIndex, vol_xySize, coord[3];
423 long dataOffset, filesize;
428 TR <<
"[ ERROR ] Error opening MRC map " << map_file <<
". Not loading map." << std::endl;
429 utility_exit_with_message (
"Fail to load the density map." );
432 if ( !mapin.read ( reinterpret_cast <char*> ( extent ), 3 * sizeof (
int ) )
433 || !mapin.read ( reinterpret_cast <char*> ( &mode ), 1 *
sizeof (
int ) )
434 || !mapin.read ( reinterpret_cast <char*> ( &origin_xyz[0] ), 3 *
sizeof (
int ) )
435 || !mapin.read ( reinterpret_cast <char*> ( &grid[0] ), 3 *
sizeof (
int ) )
436 || !mapin.read ( reinterpret_cast <char*> ( &cell_dimensions[0] ), 3 *
sizeof (
float ) )
437 || !mapin.read ( reinterpret_cast <char*> ( &cell_angles[0] ), 3 *
sizeof (
float ) )
438 || !mapin.read ( reinterpret_cast <char*> ( crs2xyz ), 3 *
sizeof (
int ) ) ) {
439 TR <<
"[ ERROR ] Improperly formatted line in MRC map. Not loading map." << std::endl;
440 utility_exit_with_message (
"Fail to load the density map." );
444 mapin.seekg ( 92, std::ios::beg );
446 if ( !mapin.read ( reinterpret_cast <char*> ( &symBytes ), 1 * sizeof (
int ) ) ) {
447 TR <<
"[ ERROR ] Failed reading symmetry bytes record. Not loading map." <<
"\n";
448 utility_exit_with_message (
"Fail to load the density map." );
454 mapin.seekg ( 196, std::ios::beg );
456 if ( !mapin.read ( reinterpret_cast <char*> ( altorigin ), 3 * sizeof (
float ) ) ) {
457 TR <<
"[ ERROR ] Improperly formatted line in MRC map. Not loading map." << std::endl;
458 utility_exit_with_message (
"Fail to load the density map." );
462 mapin.seekg ( 208, std::ios::beg );
465 if ( !mapin.read ( mapString, 3 ) || (
std::string ( mapString ) !=
"MAP" ) ) {
466 TR <<
"[ ERROR ] 'MAP' string missing, not a valid MRC map. Not loading map." << std::endl;
467 utility_exit_with_message (
"Fail to load the density map." );
475 TR <<
"[ ERROR ] Non-real (32-bit float) data types are unsupported. Not loading map." << std::endl;
476 utility_exit_with_message (
"Fail to load the density map." );
494 TR <<
" Setting resolution to " << map_reso <<
"A" << std::endl;
495 TR <<
" Read density map'" << map_file <<
"'" << std::endl;
496 TR <<
" extent: " << extent[0] <<
" x " << extent[1] <<
" x " << extent[2] << std::endl;
497 TR <<
" origin: " << origin_xyz[0] <<
" x " << origin_xyz[1] <<
" x" << origin_xyz[2] << std::endl;
498 TR <<
" altorigin: " << altorigin[0] <<
" x " << altorigin[1] <<
" x " << altorigin[2] << std::endl;
499 TR <<
" grid: " << grid[0] <<
" x " << grid[1] <<
" x " << grid[2] << std::endl;
500 TR <<
" celldim: " << cell_dimensions[0] <<
" x " << cell_dimensions[1] <<
" x " << cell_dimensions[2] << std::endl;
501 TR <<
" cellangles: " << cell_angles[0] <<
" x " << cell_angles[1] <<
" x " << cell_angles[2] << std::endl;
502 TR <<
" crs2xyz: " << crs2xyz[0] <<
" x " << crs2xyz[1] <<
" x " << crs2xyz[2] << std::endl;
503 TR <<
" symBytes: " << symBytes << std::endl;;
507 filesize = mapin.tellg();
508 dataOffset = filesize - 4 * ( extent[0] * extent[1] * extent[2] );
510 if ( dataOffset != (
CCP4HDSIZE + symBytes ) ) {
513 TR <<
"[ WARNING ] File contains bogus symmetry record. Continuing." << std::endl;
516 TR <<
"[ ERROR ] File appears truncated and doesn't match header. Not loading map." << std::endl;
517 utility_exit_with_message (
"Fail to load the density map." );
518 }
else if ( ( dataOffset >
CCP4HDSIZE ) && ( dataOffset < ( 1024 * 1024 ) ) ) {
522 TR <<
"[ WARNING ] File is larger than expected and doesn't match header. Reading anyway." << std::endl;
524 TR <<
"[ ERROR ] File is MUCH larger than expected and doesn't match header. Not loading map." << std::endl;
525 utility_exit_with_message (
"Fail to load the density map." );
533 if ( symBytes != 0 ) {
534 TR <<
"Symmetry records found:" << std::endl;
537 for (
int i = 0; i < symBytes / 80; i++ ) {
538 mapin.read ( symData, 80 );
539 symList.push_back ( symData );
540 TR << symData << std::endl;
544 symList.push_back (
"X, Y, Z" );
547 initializeSymmOps ( symList );
550 if ( grid[0] == 0 && extent[0] > 0 ) {
551 grid[0] = extent[0] - 1;
552 TR <<
"[ WARNING ] Fixed X interval count. Continuing." << std::endl;
555 if ( grid[1] == 0 && extent[1] > 0 ) {
556 grid[1] = extent[1] - 1;
557 TR <<
"[ WARNING ] Fixed Y interval count. Continuing." << std::endl;
560 if ( grid[2] == 0 && extent[2] > 0 ) {
561 grid[2] = extent[2] - 1;
562 TR <<
"[ WARNING ] Fixed Z interval count. Continuing." << std::endl;
566 if ( crs2xyz[0] == 0 && crs2xyz[1] == 0 && crs2xyz[2] == 0 ) {
567 TR <<
"[ WARNING ] All crs2xyz records are zero." << std::endl;
568 TR <<
"[ WARNING ] Setting crs2xyz to 1, 2, 3 and continuing." << std::endl;
574 xyz2crs[crs2xyz[0] - 1] = 0;
575 xyz2crs[crs2xyz[1] - 1] = 1;
576 xyz2crs[crs2xyz[2] - 1] = 2;
580 vol_xsize = extent[xIndex];
581 vol_ysize = extent[yIndex];
582 vol_zsize = extent[zIndex];
583 vol_xySize = vol_xsize * vol_ysize;
586 rowdata =
new float[extent[0]];
587 mapin.seekg ( dataOffset, std::ios::beg );
589 density.dimension ( vol_xsize, vol_ysize, vol_zsize );
591 for ( coord[2] = 1; coord[2] <= extent[2]; coord[2]++ ) {
592 for ( coord[1] = 1; coord[1] <= extent[1]; coord[1]++ ) {
596 TR <<
"[ ERROR ] Unexpected end-of-file. Not loading map." << std::endl;
597 utility_exit_with_message (
"Fail to load the density map." );
600 if ( mapin.fail() ) {
601 TR <<
"[ ERROR ] Problem reading the file. Not loading map." << std::endl;
602 utility_exit_with_message (
"Fail to load the density map." );
605 if ( !mapin.read ( reinterpret_cast< char* > ( rowdata ), sizeof (
float ) *extent[0] ) ) {
606 TR <<
"[ ERROR ] Error reading data row. Not loading map." << std::endl;
607 utility_exit_with_message (
"Fail to load the density map." );
610 for ( coord[0] = 1; coord[0] <= extent[0]; coord[0]++ ) {
611 density ( coord[xyz2crs[0]], coord[xyz2crs[1]], coord[xyz2crs[2]] ) = rowdata[coord[0] - 1];
621 orig[0] = origin_xyz[xyz2crs[0]];
622 orig[1] = origin_xyz[xyz2crs[1]];
623 orig[2] = origin_xyz[xyz2crs[2]];
628 computeCrystParams();
631 if ( altorigin[0] != 0 && altorigin[0] != 0 && altorigin[0] != 0 &&
632 ( altorigin[0] > -10000 && altorigin[0] < 10000 ) &&
633 ( altorigin[1] > -10000 && altorigin[1] < 10000 ) &&
634 ( altorigin[2] > -10000 && altorigin[2] < 10000 )
636 orig[0] = altorigin[xyz2crs[0]];
637 orig[1] = altorigin[xyz2crs[1]];
638 orig[2] = altorigin[xyz2crs[2]];
641 TR <<
"Using ALTERNATE origin\n";
642 TR <<
" origin =" << orig[0] <<
" x " << orig[1] <<
" x " << orig[2] << std::endl;
648 if ( grid_spacing > 0 ) resize ( grid_spacing );
651 max_del_grid = std::max ( cell_dimensions[0] / ( (
double ) grid[0] ) , cell_dimensions[1] / ( (
double ) grid[1] ) );
652 max_del_grid = std::max ( max_del_grid , cell_dimensions[2] / ( (
double ) grid[2] ) );
653 calculate_index2cart();
654 is_map_loaded =
true;
662 1 /
double ( grid[0] ), 0, 0,
663 0, 1 /
double ( grid[1] ), 0,
664 0, 0, 1 /
double ( grid[2] ) );
678 index_vector[0] = frac_vector[0] * grid[0];
679 index_vector[1] = frac_vector[1] * grid[1];
680 index_vector[2] = frac_vector[2] * grid[2];
688 frac_vector[0] = index_vector[0] / grid[0];
689 frac_vector[1] = index_vector[1] / grid[1];
690 frac_vector[2] = index_vector[2] / grid[2];
696 frac_vector[0] = ( double ) index_vector[0] / grid[0];
697 frac_vector[1] = ( double ) index_vector[1] / grid[1];
698 frac_vector[2] = ( double ) index_vector[2] / grid[2];
706 index_vector = c2i * xyz_vector;
707 index_vector[0] =
pos_mod ( index_vector[0] - orig[0], (
double ) grid[0] );
708 index_vector[1] =
pos_mod ( index_vector[1] - orig[1], (
double ) grid[1] );
709 index_vector[2] =
pos_mod ( index_vector[2] - orig[2], (
double ) grid[2] );
717 const Real PI = numeric::constants::f::pi;
719 gaussian_max_d = 4 * sigma;
721 Size gaussian_size =
Size( std::ceil ( gaussian_max_d / 0.01 ) );
723 for (
Size i = 0; i <= gaussian_size; ++i ) {
724 Real calc_value = exp ( - ( i * 0.01 ) * ( i * 0.01 ) / ( 2.0 * sigma * sigma ) ) / ( sqrt ( 2.0 * PI ) * sigma );
725 atom_gaussian_value.push_back ( calc_value );
732 if ( dist >= gaussian_max_d )
return 0.0;
734 return atom_gaussian_value[ (
int ) std::floor ( dist*100.0 + 0.5 ) +1];
740 if ( elt ==
"C" )
return 6;
742 if ( elt ==
"N" )
return 7;
744 if ( elt ==
"O" )
return 8;
746 if ( elt ==
"P" )
return 15;
748 if ( elt ==
"S" )
return 16;
750 if ( elt ==
"X" )
return 0;
753 TR.Warning <<
"[ WARNING ] Unknown atom " << elt << std::endl;
760 ObjexxFCL::FArray3D< double > & score,
762 int lower_bound[3], upper_bound[3];
766 for (
int i = 0; i < 3; ++i ) {
767 lower_bound[i] = (
int ) ( std::ceil ( index[i] ) );
768 upper_bound[i] = lower_bound[i] + 1;
770 if ( upper_bound[i] > grid[i] ) upper_bound[i] = 1;
772 residual[i] = index[i] + 1 - lower_bound[i];
775 double &c000 = score ( lower_bound[0], lower_bound[1], lower_bound[2] );
776 double &c100 = score ( upper_bound[0], lower_bound[1], lower_bound[2] );
777 double &c010 = score ( lower_bound[0], upper_bound[1], lower_bound[2] );
778 double &c001 = score ( lower_bound[0], lower_bound[1], upper_bound[2] );
779 double &c110 = score ( upper_bound[0], upper_bound[1], lower_bound[2] );
780 double &c101 = score ( upper_bound[0], lower_bound[1], upper_bound[2] );
781 double &c011 = score ( lower_bound[0], upper_bound[1], upper_bound[2] );
782 double &c111 = score ( upper_bound[0], upper_bound[1], upper_bound[2] );
784 Real cR00 = c000 + residual[0] * ( c100 - c000 );
785 Real cR10 = c010 + residual[0] * ( c110 - c010 );
786 Real cR01 = c001 + residual[0] * ( c101 - c001 );
787 Real cR11 = c011 + residual[0] * ( c111 - c011 );
789 Real cRR0 = cR00 + residual[1] * ( cR10 - cR00 );
790 Real cRR1 = cR01 + residual[1] * ( cR11 - cR01 );
792 Real cRRR = cRR0 + residual[2] * ( cRR1 - cRR0 );
798 ObjexxFCL::FArray3D< double > & score,
800 int lower_bound[3], upper_bound[3];
805 for (
int i = 0; i < 3; ++i ) {
806 lower_bound[i] = (
int ) ( floor ( index[i] + 1 ) );
807 upper_bound[i] = lower_bound[i] + 1;
809 if ( upper_bound[i] > grid[i] ) upper_bound[i] = 1;
811 residual[i] = index[i] + 1 - lower_bound[i];
814 double &c000 = score ( lower_bound[0], lower_bound[1], lower_bound[2] );
815 double &c100 = score ( upper_bound[0], lower_bound[1], lower_bound[2] );
816 double &c010 = score ( lower_bound[0], upper_bound[1], lower_bound[2] );
817 double &c001 = score ( lower_bound[0], lower_bound[1], upper_bound[2] );
818 double &c110 = score ( upper_bound[0], upper_bound[1], lower_bound[2] );
819 double &c101 = score ( upper_bound[0], lower_bound[1], upper_bound[2] );
820 double &c011 = score ( lower_bound[0], upper_bound[1], upper_bound[2] );
821 double &c111 = score ( upper_bound[0], upper_bound[1], upper_bound[2] );
823 Real cR00 = c000 + residual[0] * ( c100 - c000 );
824 Real cR10 = c010 + residual[0] * ( c110 - c010 );
825 Real cR01 = c001 + residual[0] * ( c101 - c001 );
826 Real cR11 = c011 + residual[0] * ( c111 - c011 );
828 Real cRR0 = cR00 + residual[1] * ( cR10 - cR00 );
829 Real cRR1 = cR01 + residual[1] * ( cR11 - cR01 );
831 grad[2] = cRR1 - cRR0;
833 Real cR0R = cR00 + residual[2] * ( cR01 - cR00 );
834 Real cR1R = cR10 + residual[2] * ( cR11 - cR10 );
836 grad[1] = cR1R - cR0R;
838 Real c0R0 = c000 + residual[1] * ( c010 - c000 );
839 Real c1R0 = c100 + residual[1] * ( c110 - c100 );
840 Real c0R1 = c001 + residual[1] * ( c011 - c001 );
841 Real c1R1 = c101 + residual[1] * ( c111 - c101 );
843 Real c0RR = c0R0 + residual[2] * ( c0R1 - c0R0 );
844 Real c1RR = c1R0 + residual[2] * ( c1R1 - c1R0 );
846 grad[0] = c1RR - c0RR;
854 ObjexxFCL::FArray3D< double > & coeffs ,
856 int dims[3] = { coeffs.u3(), coeffs.u2(), coeffs.u1() };
857 core::Real pt[3] = {idxX[2], idxX[1], idxX[0]};
864 ObjexxFCL::FArray3D< double > & coeffs ) {
865 int dims[3] = { data.u3(), data.u2(), data.u1() };
873 if ( is_score_precomputed )
return;
876 ObjexxFCL::FArray3D< double > rho_calc_array;
877 rho_calc_array.dimension ( density.u1() , density.u2() , density.u3() );
879 for (
int i = 0; i < density.u1() *density.u2() *density.u3(); ++i ) {
880 rho_calc_array[i] = 0.0;
884 Real map_reso = basic::options::option[ basic::options::OptionKeys::edensity::mapreso ]();
885 Real atom_gaussian_sigma = 0.30 + 0.18 * map_reso;
886 generate_gaussian_1d ( atom_gaussian_sigma );
891 for (
Size i = 1; i <= n_res; ++i ) {
898 atom_weight_stored.push_back ( weight_rsd );
902 for (
Size j = 1; j <= n_heavyatom_rsd; ++j ) {
905 std::string element = atom_type_set[rsd.atom_type_index ( j ) ].element();
906 Size weight = get_atom_weight ( element );
907 sum_weight += weight;
908 weight_rsd.push_back ( weight );
913 grid[1] * 0.5, grid[1] * 0.5 );
916 for (
int x = 1; x <= density.u1(); ++x ) {
918 dist_index[0] = coord_index[0] - ( x - 1 );
921 if ( dist_index[0] > grid_half[0] ) dist_index[0] -= grid[0];
923 if ( dist_index[0] <= - grid_half[0] ) dist_index[0] += grid[0];
928 if ( dist_x.length() > gaussian_max_d )
continue;
930 for (
int y = 1; y <= density.u2(); ++y ) {
932 dist_index[1] = coord_index[1] - ( y - 1 );
935 if ( dist_index[1] > grid_half[1] ) dist_index[1] -= grid[1];
937 if ( dist_index[1] <= - grid_half[1] ) dist_index[1] += grid[1];
942 if ( dist_xy.length() > gaussian_max_d )
continue;
944 for (
int z = 1; z <= density.u3(); ++z ) {
946 dist_index[2] = coord_index[2] - ( z - 1 );
949 if ( dist_index[2] > grid_half[2] ) dist_index[2] -= grid[2];
951 if ( dist_index[2] <= - grid_half[2] ) dist_index[2] += grid[2];
955 Real dist = dist_xyz.length();
957 if ( dist > gaussian_max_d )
continue;
959 rho_calc_array ( x, y, z ) += gaussian_1d ( dist ) * weight;
965 atom_weight_stored.push_back ( weight_rsd );
968 Real sum_rho_calc = 0.0;
969 Real sum_rho_calc_square = 0.0;
970 Real sum_rho_obs = 0.0;
971 Real sum_rho_obs_square = 0.0;
972 Real sum_rho_calc_times_rho_obs = 0.0;
973 Size n_grid_points = 0;
975 for (
int i = 0; i < density.u1() *density.u2() *density.u3(); ++i ) {
976 float rho_obs = density[i];
977 Real rho_calc = rho_calc_array[i];
979 if ( rho_calc < 1.0e-2 ) {
985 sum_rho_calc += rho_calc;
986 sum_rho_calc_square += rho_calc * rho_calc;
987 sum_rho_obs += rho_obs;
988 sum_rho_obs_square += rho_obs * rho_obs;
989 sum_rho_calc_times_rho_obs += rho_calc * rho_obs;
995 Real rscc = ( sum_rho_calc_times_rho_obs - sum_rho_calc * sum_rho_obs / n_grid_points ) / ( sqrt ( sum_rho_calc_square - sum_rho_calc * sum_rho_calc / n_grid_points ) * sqrt ( sum_rho_obs_square - sum_rho_obs * sum_rho_obs / n_grid_points ) );
998 normalization = - ( ( double ) sum_weight ) / ( sqrt ( sum_rho_calc_square - sum_rho_calc * sum_rho_calc / n_grid_points ) * sqrt ( sum_rho_obs_square - sum_rho_obs * sum_rho_obs / n_grid_points ) );
999 avg_rho_obs = sum_rho_obs / n_grid_points;
1000 TR <<
"RSCC of starting pose = " << rscc << std::endl;
1001 TR <<
"Score of starting pose = " << - ( rscc * sum_weight ) << std::endl;
1002 TR <<
"normalization factor = " << normalization << std::endl;
1003 TR <<
"avg_rho_obs = " << avg_rho_obs << std::endl;
1009 if ( is_score_precomputed )
return;
1011 ObjexxFCL::FArray3D< double > unweighted_score;
1012 ObjexxFCL::FArray3D< std::complex<double> > density_transformed,
1013 atom_dens_transformed, atom_dens, cplx_score, cplx_density;
1014 atom_dens.dimension ( density.u1() , density.u2() , density.u3() );
1016 for (
int i = 0; i < density.u1() *density.u2() *density.u3(); ++i ) {
1021 Real sum_rho_calc = 0.0;
1024 grid[1] * 0.5, grid[2] * 0.5 );
1026 for (
int x = 1; x <= atom_dens.u1(); ++x ) {
1028 dist_index[0] = x - 1;
1031 if ( dist_index[0] > grid_half[0] ) dist_index[0] -= grid[0];
1033 if ( dist_index[0] <= - grid_half[0] ) dist_index[0] += grid[0];
1038 if ( dist_x.length() > gaussian_max_d )
continue;
1040 for (
int y = 1; y <= atom_dens.u2(); ++y ) {
1042 dist_index[1] = y - 1;
1045 if ( dist_index[1] > grid_half[1] ) dist_index[1] -= grid[1];
1047 if ( dist_index[1] <= - grid_half[1] ) dist_index[1] += grid[1];
1052 if ( dist_xy.length() > gaussian_max_d )
continue;
1054 for (
int z = 1; z <= atom_dens.u3(); ++z ) {
1056 dist_index[2] = z - 1;
1059 if ( dist_index[2] > grid_half[2] ) dist_index[2] -= grid[2];
1061 if ( dist_index[2] <= - grid_half[2] ) dist_index[2] += grid[2];
1064 Real dist = dist_xyz.length();
1065 atom_dens ( x, y, z ) = gaussian_1d ( dist );
1066 sum_rho_calc += gaussian_1d ( dist );
1072 numeric::fourier::fft3_dynamic ( atom_dens, atom_dens_transformed );
1074 cplx_density.dimension ( density.u1() , density.u2() , density.u3() );
1076 for (
int i = 0; i < density.u1() *density.u2() *density.u3(); ++i ) {
1077 cplx_density[i] = ( double ) density[i];
1081 numeric::fourier::fft3_dynamic ( cplx_density, density_transformed );
1082 cplx_density.clear();
1084 for (
int i = 0; i < density_transformed.u1() *density_transformed.u2() *density_transformed.u3(); ++i ) {
1085 density_transformed[i] *= atom_dens_transformed[i];
1088 atom_dens_transformed.clear();
1089 numeric::fourier::ifft3_dynamic ( density_transformed, cplx_score );
1090 density_transformed.clear();
1091 unweighted_score.dimension ( cplx_score.u1() , cplx_score.u2() , cplx_score.u3() );
1093 for (
int i = 0; i < unweighted_score.u1() *unweighted_score.u2() *unweighted_score.u3(); ++i ) {
1094 unweighted_score[i] = cplx_score[i].real();
1095 unweighted_score[i] -= sum_rho_calc * avg_rho_obs;
1096 unweighted_score[i] *= normalization;
1102 unweighted_score.clear();
1103 is_score_precomputed =
true;
1116 for (
Size j = 1 ; j <= n_heavyatom_rsd; ++j ) {
1120 Size weight = atom_weight_stored[rsd_id][j];
1123 Real score = weight * spline_interpolation ( unweighted_score_coeff, coord_index );
1124 total_score += score;
1133 const & rsd_id,
core::Size const & atm_id ) {
1141 Size &weight = atom_weight_stored[rsd_id][atm_id];
1142 Real incre = 0.00000001;
1148 coord_index_dx[0] += incre;
1149 coord_index_dy[1] += incre;
1150 coord_index_dz[2] += incre;
1152 Real score_atom = spline_interpolation ( unweighted_score_coeff, coord_index );
1153 grad[0] = ( spline_interpolation ( unweighted_score_coeff, coord_index_dx ) -
1154 score_atom ) / incre;
1155 grad[1] = ( spline_interpolation ( unweighted_score_coeff, coord_index_dy ) -
1156 score_atom ) / incre;
1157 grad[2] = ( spline_interpolation ( unweighted_score_coeff, coord_index_dz ) -
1158 score_atom ) / incre;
1160 i2c_gradient.transpose();
1161 grad = weight * i2c_gradient * grad;
1174 return theDensityMap;