23 #include <pybind11/pybind11.h>
24 #include <pybind11/stl.h>
25 #include <pybind11/numpy.h>
28 void add_dataClass ( pybind11::module& pyProSHADE )
31 pybind11::class_ < ProSHADE_internal_data::ProSHADE_data > ( pyProSHADE,
"ProSHADE_data" )
34 .def ( pybind11::init ( ) )
35 .def ( pybind11::init ( [] ( std::string strName, pybind11::array_t < float, pybind11::array::c_style | pybind11::array::forcecast > mapData, proshade_single xDmSz, proshade_single yDmSz, proshade_single zDmSz, proshade_unsign xDmInd, proshade_unsign yDmInd, proshade_unsign zDmInd, proshade_signed xFr, proshade_signed yFr, proshade_signed zFr, proshade_signed xT, proshade_signed yT, proshade_signed zT, proshade_unsign inputO )
38 pybind11::buffer_info buf = mapData.request();
39 proshade_unsign len =
static_cast< proshade_unsign
> ( buf.size );
42 double* npVals =
new double[
static_cast<proshade_unsign
> ( len )];
48 for ( proshade_unsign iter = 0; iter < len; iter++ ) { npVals[iter] =
static_cast < double > ( mapData.at(iter) ); }
50 else if ( buf.ndim == 3 )
52 float* dataPtr =
reinterpret_cast < float*
> ( buf.ptr );
53 for ( proshade_unsign xIt = 0; xIt < static_cast<proshade_unsign> ( buf.shape.at(0) ); xIt++ )
55 for ( proshade_unsign yIt = 0; yIt < static_cast<proshade_unsign> ( buf.shape.at(1) ); yIt++ )
57 for ( proshade_unsign zIt = 0; zIt < static_cast<proshade_unsign> ( buf.shape.at(2) ); zIt++ )
59 npVals[zIt +
static_cast< proshade_unsign
> ( buf.shape.at(2) ) * ( yIt +
static_cast< proshade_unsign
> ( buf.shape.at(1) ) * xIt )] =
static_cast < double > ( dataPtr[zIt +
static_cast< proshade_unsign
> ( buf.shape.at(2) ) * ( yIt +
static_cast< proshade_unsign
> ( buf.shape.at(1) ) * xIt )] );
66 std::cerr <<
"!!! ProSHADE PYTHON MODULE ERROR !!! The ProSHADE_data class constructor ( ProSHADE_settings, str, numpy.ndarray, float, float, float, ... ) only supports the third argument input array in the 1D or 3D numpy.ndarray format. The supplied array has " << buf.ndim <<
" dims. Terminating..." << std::endl;
67 exit ( EXIT_FAILURE );
73 static_cast<int> ( len ),
92 .def (
"readInStructure",
96 pybind11::buffer_info maskArr_buf = maskArr.request();
97 pybind11::buffer_info weightsArr_buf = weightsArr.request();
100 if ( ( maskArr_buf.shape.at(0) != 0 ) && ( maskArr_buf.shape.at(1) != 0 ) && ( maskArr_buf.shape.at(2) != 0 ) )
103 if ( maskArr_buf.ndim != 3 ) { std::cerr <<
"!!! ProSHADE PYTHON MODULE ERROR !!! The fourth argument to readInStructure() must be a 3D numpy array or empty and the dimensions must match!" << std::endl; exit ( EXIT_FAILURE ); }
106 proshade_double* mskArr =
new proshade_double[maskArr_buf.shape.at(0)*maskArr_buf.shape.at(1)*maskArr_buf.shape.at(2)];
110 proshade_double* arrStart =
static_cast< proshade_double*
> ( maskArr_buf.ptr );
111 for (
size_t iter = 0; iter < static_cast< size_t > ( maskArr_buf.shape.at(0)*maskArr_buf.shape.at(1)*maskArr_buf.shape.at(2) ); iter++ ) { mskArr[iter] = arrStart[iter]; }
114 if ( ( weightsArr_buf.shape.at(0) != 0 ) && ( weightsArr_buf.shape.at(1) != 0 ) && ( weightsArr_buf.shape.at(2) != 0 ) )
117 if ( weightsArr_buf.ndim != 3 ) { std::cerr <<
"!!! ProSHADE PYTHON MODULE ERROR !!! The fifth argument to readInStructure() must be a 3D numpy array or empty and the dimensions must match!" << std::endl; exit ( EXIT_FAILURE ); }
120 proshade_double* wghArr =
new proshade_double[weightsArr_buf.shape.at(0)*weightsArr_buf.shape.at(1)*weightsArr_buf.shape.at(2)];
124 proshade_double* arr2Start =
static_cast< proshade_double*
> ( weightsArr_buf.ptr );
125 for (
size_t iter = 0; iter < static_cast< size_t > ( weightsArr_buf.shape.at(0)*weightsArr_buf.shape.at(1)*weightsArr_buf.shape.at(2) ); iter++ ) { wghArr[iter] = arr2Start[iter]; }
128 self.readInStructure ( fName, inputO, settings, mskArr,
static_cast< proshade_unsign
> ( maskArr_buf.shape.at(0) ),
static_cast< proshade_unsign
> ( maskArr_buf.shape.at(1) ),
static_cast< proshade_unsign
> ( maskArr_buf.shape.at(2) ), wghArr,
static_cast< proshade_unsign
> ( weightsArr_buf.shape.at(0) ),
static_cast< proshade_unsign
> ( weightsArr_buf.shape.at(1) ),
static_cast< proshade_unsign
> ( weightsArr_buf.shape.at(2) ) );
136 self.readInStructure ( fName, inputO, settings, mskArr,
static_cast< proshade_unsign
> ( maskArr_buf.shape.at(0) ),
static_cast< proshade_unsign
> ( maskArr_buf.shape.at(1) ),
static_cast< proshade_unsign
> ( maskArr_buf.shape.at(2) ),
nullptr, 0, 0, 0 );
145 if ( ( weightsArr_buf.shape.at(0) != 0 ) && ( weightsArr_buf.shape.at(1) != 0 ) && ( weightsArr_buf.shape.at(2) != 0 ) )
148 if ( weightsArr_buf.ndim != 3 ) { std::cerr <<
"!!! ProSHADE PYTHON MODULE ERROR !!! The fifth argument to readInStructure() must be a 3D numpy array or empty and the dimensions must match!" << std::endl; exit ( EXIT_FAILURE ); }
151 proshade_double* wghArr =
new proshade_double[weightsArr_buf.shape.at(0)*weightsArr_buf.shape.at(1)*weightsArr_buf.shape.at(2)];
155 proshade_double* arr2Start =
static_cast< proshade_double*
> ( weightsArr_buf.ptr );
156 for (
size_t iter = 0; iter < static_cast< size_t > ( weightsArr_buf.shape.at(0)*weightsArr_buf.shape.at(1)*weightsArr_buf.shape.at(2) ); iter++ ) { wghArr[iter] = arr2Start[iter]; }
159 self.readInStructure ( fName, inputO, settings,
nullptr, 0, 0, 0, wghArr,
static_cast< proshade_unsign
> ( weightsArr_buf.shape.at(0) ),
static_cast< proshade_unsign
> ( weightsArr_buf.shape.at(1) ),
static_cast< proshade_unsign
> ( weightsArr_buf.shape.at(2) ) );
167 self.readInStructure ( fName, inputO, settings,
nullptr, 0, 0, 0,
nullptr, 0, 0, 0 );
173 },
"This function returns the group elements as rotation matrices of any point group described by the detected axes.", pybind11::arg (
"fName" ), pybind11::arg (
"inputO" ), pybind11::arg (
"settings" ), pybind11::arg(
"maskArr" ) = pybind11::array_t < proshade_double > (), pybind11::arg(
"weightsArr" ) = pybind11::array_t < proshade_double > () )
174 .def (
"writeMap", &
ProSHADE_internal_data::ProSHADE_data::writeMap,
"Function for writing out the internal structure representation in MRC MAP format.", pybind11::arg (
"fname" ), pybind11::arg (
"title" ) =
"Created by ProSHADE and written by GEMMI", pybind11::arg (
"mode" ) = 2 )
175 .def (
"writePdb", &
ProSHADE_internal_data::ProSHADE_data::writePdb,
"This function writes out the co-ordinates file with ProSHADE type rotation and translation applied.", pybind11::arg (
"fname" ), pybind11::arg (
"euA" ) = 0.0, pybind11::arg (
"euB" ) = 0.0, pybind11::arg (
"euG" ) = 0.0, pybind11::arg (
"trsX" ) = 0.0, pybind11::arg (
"trsY" ) = 0.0, pybind11::arg (
"trsZ" ) = 0.0, pybind11::arg (
"rotX" ) = 0.0, pybind11::arg (
"rotY" ) = 0.0, pybind11::arg (
"rotZ" ) = 0.0, pybind11::arg (
"firstModel" ) = true )
176 .def (
"writeGemmi", &
ProSHADE_internal_data::ProSHADE_data::writeGemmi,
"This function writes out the gemmi::Structure object with ProSHADE type rotation and translation applied.", pybind11::arg (
"fname" ), pybind11::arg (
"gemmiStruct" ), pybind11::arg (
"euA" ) = 0.0, pybind11::arg (
"euB" ) = 0.0, pybind11::arg (
"euG" ) = 0.0, pybind11::arg (
"trsX" ) = 0.0, pybind11::arg (
"trsY" ) = 0.0, pybind11::arg (
"trsZ" ) = 0.0, pybind11::arg (
"rotX" ) = 0.0, pybind11::arg (
"rotY" ) = 0.0, pybind11::arg (
"rotZ" ) = 0.0, pybind11::arg (
"firstModel" ) = true )
181 pybind11::array_t < proshade_double > retArr = pybind11::array_t < proshade_double > ( {
self.xDimIndices,
self.yDimIndices,
self.zDimIndices },
182 {
self.yDimIndices *
self.zDimIndices *
sizeof(proshade_double),
183 self.zDimIndices *
sizeof(proshade_double),
184 sizeof(proshade_double) },
192 .def (
"processInternalMap", &
ProSHADE_internal_data::ProSHADE_data::processInternalMap,
"This function simply clusters several map manipulating functions which should be called together. These include centering, phase removal, normalisation, adding extra space, etc.", pybind11::arg (
"settings" ) )
202 .def (
"getReBoxBoundaries",
206 proshade_signed* retVals =
new proshade_signed[6];
212 for ( proshade_unsign iter = 0; iter < 6; iter++ ) { retVals[iter] = settings->
forceBounds[iter]; }
219 static_cast< proshade_signed
> (
self.xDimIndices ),
220 static_cast< proshade_signed
> (
self.yDimIndices ),
221 static_cast< proshade_signed
> (
self.zDimIndices ),
226 self.xDimSize,
self.yDimSize,
self.zDimSize, retVals, settings->
boundsExtraSpace );
232 if ( settings->
useSameBounds && (
self.inputOrder == 0 ) ) {
for ( proshade_unsign iter = 0; iter < 6; iter++ ) { settings->
forceBounds[iter] = retVals[iter]; } }
236 pybind11::capsule pyCapsuleReBox2 ( retVals, [](
void *f ) { proshade_signed* foo =
reinterpret_cast< proshade_signed*
> ( f );
delete foo; } );
239 pybind11::array_t < proshade_signed > retArr = pybind11::array_t < proshade_signed > ( { 6 },
240 {
sizeof(proshade_signed) },
246 },
"This function finds the boundaries enclosing positive map values and adds some extra space." )
247 .def (
"createNewMapFromBounds",
251 proshade_signed* newBounds =
new proshade_signed[6];
255 for ( proshade_unsign iter = 0; iter < 6; iter++ ) { newBounds[iter] = bounds.at(iter); }
258 self.createNewMapFromBounds ( settings, newStr, newBounds );
262 },
"This function creates a new structure from the calling structure and new bounds values." )
279 .def (
"detectSymmetryInStructure",
284 },
"This function runs the symmetry detection algorithms on this structure and saves the results in the settings object.", pybind11::arg (
"settings" ) )
287 .def (
"getRecommendedSymmetryAxes",
291 float* npVals =
new float[
static_cast<unsigned int> ( settings->
detectedSymmetry.size() * 7 )];
295 for ( proshade_unsign iter = 0; iter < static_cast<proshade_unsign> ( settings->
detectedSymmetry.size() ); iter++ ) {
for ( proshade_unsign it = 0; it < 7; it++ ) { npVals[(iter*7)+it] =
static_cast< float > ( settings->
detectedSymmetry.at(iter)[it] ); } }
298 pybind11::capsule pyCapsuleStrRecSym ( npVals, [](
void *f ) {
float* foo =
reinterpret_cast< float*
> ( f );
delete foo; } );
301 pybind11::array_t < float > retArr = pybind11::array_t<float> ( {
static_cast<int> ( settings->
detectedSymmetry.size() ),
static_cast<int> ( 7 ) },
302 { 7 *
sizeof(float),
sizeof(
float) },
304 pyCapsuleStrRecSym );
308 },
"This function returns the recommended symmetry axes as a 2D numpy array." )
309 .def (
"getAllCSyms",
313 float* npVals =
new float[
static_cast<unsigned int> ( settings->
allDetectedCAxes.size() * 7 )];
317 for ( proshade_unsign iter = 0; iter < static_cast<proshade_unsign> ( settings->
allDetectedCAxes.size() ); iter++ ) {
for ( proshade_unsign it = 0; it < 7; it++ ) { npVals[(iter*7)+it] =
static_cast< float > ( settings->
allDetectedCAxes.at(iter).at(it) ); } }
320 pybind11::capsule pyCapsuleStrSymList ( npVals, [](
void *f ) {
float* foo =
reinterpret_cast< float*
> ( f );
delete foo; } );
323 pybind11::array_t < float > retArr = pybind11::array_t<float> ( {
static_cast<int> ( settings->
allDetectedCAxes.size() ), 7 },
324 { 7 *
sizeof(float),
sizeof(
float) },
326 pyCapsuleStrSymList );
330 },
"This function returns all symmetry axes as a 2D numpy array." )
331 .def (
"getNonCSymmetryAxesIndices",
335 pybind11::dict retDict;
336 pybind11::list dList, tList, oList, iList;
339 for ( proshade_unsign dIt = 0; dIt < static_cast<proshade_unsign> ( settings->
allDetectedDAxes.size() ); dIt++ )
341 pybind11::list memList;
342 for ( proshade_unsign memIt = 0; memIt < static_cast<proshade_unsign> ( settings->
allDetectedDAxes.at(dIt).size() ); memIt++ )
346 dList.append ( memList );
350 for ( proshade_unsign tIt = 0; tIt < static_cast<proshade_unsign> ( settings->
allDetectedTAxes.size() ); tIt++ )
356 for ( proshade_unsign oIt = 0; oIt < static_cast<proshade_unsign> ( settings->
allDetectedOAxes.size() ); oIt++ )
362 for ( proshade_unsign iIt = 0; iIt < static_cast<proshade_unsign> ( settings->
allDetectedIAxes.size() ); iIt++ )
368 retDict[ pybind11::handle ( pybind11::str (
"D" ).ptr ( ) ) ] = dList;
369 retDict[ pybind11::handle ( pybind11::str (
"T" ).ptr ( ) ) ] = tList;
370 retDict[ pybind11::handle ( pybind11::str (
"O" ).ptr ( ) ) ] = oList;
371 retDict[ pybind11::handle ( pybind11::str (
"I" ).ptr ( ) ) ] = iList;
375 },
"This function returns array of non-C axes indices." )
376 .def (
"getAllGroupElements",
380 pybind11::buffer_info buf = axList.request();
381 if ( buf.ndim != 1 ) { std::cerr <<
"!!! ProSHADE PYTHON MODULE ERROR !!! The second argument to getAllGroupElements() must be a 1D numpy array stating the indices of the axes forming the group!" << std::endl; exit ( EXIT_FAILURE ); }
384 std::vector< proshade_unsign > axesList;
385 for ( proshade_unsign iter = 0; iter < static_cast<proshade_unsign> ( axList.size() ); iter++ ) {
ProSHADE_internal_misc::addToUnsignVector ( &axesList,
static_cast< proshade_unsign
> ( axList.at(iter) ) ); }
388 std::vector < std::vector< proshade_double > > vals =
self.getAllGroupElements ( settings, axesList, groupType, matrixTolerance );
391 pybind11::list retList;
394 for ( proshade_unsign iter = 0; iter < static_cast<proshade_unsign> ( vals.size() ); iter++ )
397 float* npVals =
new float[
static_cast<unsigned int> ( 9 )];
401 for ( proshade_unsign it = 0; it < 9; it++ ) { npVals[it] =
static_cast< float > ( vals.at(iter).at(it) ); }
404 pybind11::capsule pyCapsuleGrpEl ( npVals, [](
void *f ) {
float* foo =
reinterpret_cast< float*
> ( f );
delete foo; } );
407 pybind11::array_t < float > retArr = pybind11::array_t<float> ( { 3, 3 },
408 { 3 *
sizeof(float),
sizeof(
float) },
413 retList.append ( retArr );
418 },
"This function returns the group elements as rotation matrices of any point group described by the detected axes.", pybind11::arg (
"settings" ), pybind11::arg (
"axList" ), pybind11::arg (
"groupType" ) =
"", pybind11::arg(
"matrixTolerance" ) = 0.05 )
420 .def (
"getMapCOMProcessChange",
424 std::vector< proshade_double > vals =
self.getMapCOMProcessChange ();
427 float* npVals =
new float[
static_cast<unsigned int> ( 3 )];
431 for ( proshade_unsign iter = 0; iter < 3; iter++ ) { npVals[iter] =
static_cast< float > ( vals.at(iter) ); }
434 pybind11::capsule pyCapsuleSymShiftDat ( npVals, [](
void *f ) {
float* foo =
reinterpret_cast< float*
> ( f );
delete foo; } );
437 pybind11::array_t < float > retArr = pybind11::array_t<float> ( {
static_cast<int> ( vals.size() ) },
440 pyCapsuleSymShiftDat );
444 },
"This function returns the shift in Angstrom applied to the internal map representation in order to align its COM with the centre of box." )
448 .def (
"getBestRotationMapPeaksEulerAngles",
452 std::vector< proshade_double > vals =
self.getBestRotationMapPeaksEulerAngles ( settings );
455 float* npVals =
new float[
static_cast<unsigned int> (vals.size())];
459 for ( proshade_unsign iter = 0; iter < static_cast<proshade_unsign> ( vals.size() ); iter++ ) { npVals[iter] =
static_cast< float > ( vals.at(iter) ); }
462 pybind11::capsule pyCapsuleEuPeak ( npVals, [](
void *f ) {
float* foo =
reinterpret_cast< float*
> ( f );
delete foo; } );
465 pybind11::array_t < float > retArr = pybind11::array_t<float> ( {
static_cast<unsigned int> (vals.size()) },
472 },
"This function returns a vector of three floats, the three Euler angles of the best peak in the rotation map.", pybind11::arg (
"settings" ) )
473 .def (
"getBestRotationMapPeaksRotationMatrix",
477 std::vector< proshade_double > vals =
self.getBestRotationMapPeaksEulerAngles ( settings );
480 proshade_double* retMat =
new proshade_double[9];
485 pybind11::capsule pyCapsuleRMPeak ( retMat, [](
void *f ) { proshade_double* foo =
reinterpret_cast< proshade_double*
> ( f );
delete foo; } );
488 pybind11::array_t < proshade_double > retArr = pybind11::array_t<proshade_double> ( { 3, 3 },
489 { 3 *
sizeof(proshade_double),
sizeof(proshade_double) },
495 },
"This function returns a rotation matrix representing the best peak in the rotation map.", pybind11::arg (
"settings" ) )
500 .def (
"getOverlayTranslations",
504 std::vector< proshade_double > vals =
self.getBestTranslationMapPeaksAngstrom ( staticStructure );
507 pybind11::dict retDict;
508 pybind11::list rotCen, toOverlay;
511 rotCen.append (
self.originalPdbRotCenX );
512 rotCen.append (
self.originalPdbRotCenY );
513 rotCen.append (
self.originalPdbRotCenZ );
515 toOverlay.append (
self.originalPdbTransX );
516 toOverlay.append (
self.originalPdbTransY );
517 toOverlay.append (
self.originalPdbTransZ );
520 retDict[ pybind11::handle ( pybind11::str (
"centreOfRotation" ).ptr ( ) ) ] = rotCen;
521 retDict[ pybind11::handle ( pybind11::str (
"rotCenToOverlay" ).ptr ( ) ) ] = toOverlay;
525 },
"This function returns the vector from optimal rotation centre to origin and the optimal overlay translation vector. These two vectors allow overlaying the inputs (see documentation for details on how the two vectors should be used).", pybind11::arg (
"staticStructure" ) )
526 .def (
"translateMap", &
ProSHADE_internal_data::ProSHADE_data::translateMap,
"This function translates the map by a given number of Angstroms along the three axes. Please note the translation happens firstly to the whole map box and only the translation remainder that cannot be achieved by moving the box will be corrected for using reciprocal space translation within the box.", pybind11::arg (
"trsX" ), pybind11::arg (
"trsY" ), pybind11::arg (
"trsZ" ) )
529 .def (
"findSHIndex",
533 proshade_signed index = seanindex (
static_cast< int > ( order ),
534 static_cast< int > ( band ),
535 static_cast< int > (
self.spheres[shell]->getLocalBandwidth() ) );
539 },
"This function finds the correct index for given shell, band and order in the spherical harmonics array. Please note that the order is expected in range -band <= 0 <- band and NOT from 0 to ( 2 * band ) + 1." )
540 .def (
"getSphericalHarmonics",
544 std::complex<proshade_double>* npVals =
new std::complex<proshade_double>[
static_cast<proshade_unsign
> (
self.noSpheres * pow(
self.maxShellBand, 2.0 ) )];
548 for ( proshade_unsign iter = 0; iter < static_cast<proshade_unsign> (
self.noSpheres * pow(
self.maxShellBand, 2.0 ) ); iter++ ) { npVals[iter].real ( 0.0 ); npVals[iter].imag ( 0.0 ); }
551 proshade_signed pyPosSH;
552 proshade_signed pyPos;
555 for ( proshade_signed shIt = 0; shIt < static_cast<proshade_signed> (
self.noSpheres ); shIt++ )
557 for ( proshade_signed bnd = 0; bnd < static_cast<proshade_signed> (
self.spheres[shIt]->getLocalBandwidth() ); bnd++ )
559 for ( proshade_signed order = -bnd; order <= bnd; order++ )
561 pyPosSH = (
static_cast< proshade_signed
> ( shIt ) *
static_cast< proshade_signed
> ( std::pow (
self.maxShellBand, 2 ) ) );
562 pyPos = seanindex (
static_cast< int > ( order ),
563 static_cast< int > ( bnd ),
564 static_cast< int > (
self.spheres[shIt]->getLocalBandwidth() ) );
565 npVals[pyPosSH+pyPos].real (
self.sphericalHarmonics[shIt][pyPos][0] );
566 npVals[pyPosSH+pyPos].imag (
self.sphericalHarmonics[shIt][pyPos][1] );
572 pybind11::capsule pyCapsuleSHs ( npVals, [](
void *f ) { std::complex<proshade_double>* foo =
reinterpret_cast< std::complex<proshade_double>*
> ( f );
delete foo; } );
575 pybind11::array_t < std::complex<proshade_double> > retArr = pybind11::array_t < std::complex<proshade_double > > (
576 {
static_cast<int> (
self.noSpheres ),
static_cast<int> ( pow (
self.maxShellBand, 2.0 ) ) },
577 {
sizeof ( std::complex < proshade_double > ) *
static_cast< proshade_unsign
> ( std::pow (
static_cast< proshade_unsign
> (
self.maxShellBand ), 2 ) ),
sizeof ( std::complex < proshade_double > ) },
583 },
"This function returns a 2D numpy array of complex numbers representing the spherical harmonics computed for the structure. The first dimension of the array is the spheres (i.e. each sphere has its own array) and the second dimension is the band and order combination as given by the findSHIndex() function. Please note that while each sphere can have different number of spherical harmonics coefficients (depending on the settings.progressiveSphereMapping value), this array uses maxShellBand**2 values to make sure the length are equal for all spheres. To avoid issues, please use the findSHIndex() to correctly find the index of a particular shell, band, order combination." )
588 std::complex<proshade_double>* npVals =
new std::complex < proshade_double >[
static_cast<proshade_unsign
> (
self.maxShellBand * ( (
self.maxShellBand * 2 ) + 1 ) * ( (
self.maxShellBand * 2 ) + 1 ) )];
592 proshade_signed index = 0;
595 for ( proshade_unsign iter = 0; iter < static_cast < proshade_unsign > (
self.maxShellBand * ( (
self.maxShellBand * 2 ) + 1 ) * ( (
self.maxShellBand * 2 ) + 1 ) ); iter++ ) { npVals[iter].real ( 0.0 ); npVals[iter].imag ( 0.0 ); }
598 proshade_double emReal, emImag;
599 for ( proshade_signed bandIter = 0; bandIter < static_cast< proshade_signed > (
self.maxShellBand ); bandIter++ )
601 for ( proshade_signed order1 = 0; order1 < ( ( bandIter * 2 ) + 1 ); order1++ )
603 for ( proshade_signed order2 = 0; order2 < ( ( bandIter * 2 ) + 1 ); order2++ )
605 index = order2 + ( (
static_cast< proshade_signed
> (
self.maxShellBand ) * 2 ) + 1 ) * ( order1 + ( (
static_cast< proshade_signed
> (
self.maxShellBand ) * 2 ) + 1 ) * bandIter );
606 self.getEMatrixValue(
static_cast< proshade_unsign
> ( bandIter ),
static_cast< proshade_unsign
> ( order1 ),
static_cast< proshade_unsign
> ( order2 ), &emReal, &emImag );
607 npVals[index].real ( emReal );
608 npVals[index].imag ( emImag );
614 pybind11::capsule pyCapsuleEMs ( npVals, [](
void *f ) { std::complex<proshade_double>* foo =
reinterpret_cast< std::complex<proshade_double>*
> ( f );
delete foo; } );
617 proshade_unsign orderSize = ( (
static_cast< proshade_unsign
> (
self.maxShellBand ) * 2 ) + 1 );
618 pybind11::array_t < std::complex<proshade_double> > retArr = pybind11::array_t < std::complex<proshade_double > > (
619 {
self.maxShellBand, orderSize, orderSize },
620 {
sizeof ( std::complex < proshade_double > ) * orderSize * orderSize,
621 sizeof ( std::complex < proshade_double > ) * orderSize,
622 sizeof ( std::complex < proshade_double > ) },
628 },
"This function returns the weighted E matrix values (these are the integral over all spheres of ( c1^(l,m) * c2^(l,m') ) values) obtained when rotation function or self-rotation function are computed. The returned array has three dimensions, first being the band, second being the order1 and third being the order2. Please note that as negative indexing does not work, the order indexing starts from 0 - i.e. array[1][0][0] means band 1 ; order1 = -1 and order2 = -1." )
629 .def (
"getSO3Coefficients",
633 std::complex<proshade_double>* npVals =
new std::complex < proshade_double >[
static_cast<proshade_unsign
> (
self.maxShellBand * ( (
self.maxShellBand * 2 ) + 1 ) * ( (
self.maxShellBand * 2 ) + 1 ) )];
637 proshade_signed index = 0;
640 for ( proshade_unsign iter = 0; iter < static_cast < proshade_unsign > (
self.maxShellBand * ( (
self.maxShellBand * 2 ) + 1 ) * ( (
self.maxShellBand * 2 ) + 1 ) ); iter++ ) { npVals[iter].real ( 0.0 ); npVals[iter].imag ( 0.0 ); }
643 for ( proshade_signed bandIter = 0; bandIter < static_cast< proshade_signed > (
self.maxShellBand ); bandIter++ )
645 for ( proshade_signed order1 = 0; order1 < ( ( bandIter * 2 ) + 1 ); order1++ )
647 for ( proshade_signed order2 = 0; order2 < ( ( bandIter * 2 ) + 1 ); order2++ )
649 index = order2 + ( (
static_cast< proshade_signed
> (
self.maxShellBand ) * 2 ) + 1 ) * ( order1 + ( (
static_cast< proshade_signed
> (
self.maxShellBand ) * 2 ) + 1 ) * bandIter );
650 npVals[index].real (
self.so3Coeffs[
self.so3CoeffsArrayIndex (
static_cast< proshade_signed
> ( order1 - bandIter ), order2 - bandIter, bandIter )][0] );
651 npVals[index].imag (
self.so3Coeffs[
self.so3CoeffsArrayIndex (
static_cast< proshade_signed
> ( order1 - bandIter ), order2 - bandIter, bandIter )][1] );
657 pybind11::capsule pyCapsuleSOCoeffs ( npVals, [](
void *f ) { std::complex<proshade_double>* foo =
reinterpret_cast< std::complex<proshade_double>*
> ( f );
delete foo; } );
660 proshade_unsign orderSize = ( (
static_cast< proshade_unsign
> (
self.maxShellBand ) * 2 ) + 1 );
661 pybind11::array_t < std::complex<proshade_double> > retArr = pybind11::array_t < std::complex<proshade_double > > (
662 {
self.maxShellBand, orderSize, orderSize },
663 {
sizeof ( std::complex < proshade_double > ) * orderSize * orderSize,
664 sizeof ( std::complex < proshade_double > ) * orderSize,
665 sizeof ( std::complex < proshade_double > ) },
671 },
"This function returns the SO(3) coefficient values (these are normalised E matrix values with sign modification) obtained when rotation function or self-rotation function are computed. The returned array has three dimensions, first being the band, second being the order1 and third being the order2. Please note that as negative indexing does not simply work, the order indexing starts from 0 - i.e. array[1][0][0] means band 1 ; order1 = -1 and order2 = -1." )
672 .def (
"getRotationFunctionMap",
676 std::complex<proshade_double>* npVals =
new std::complex < proshade_double >[
static_cast<proshade_unsign
> ( (
self.maxShellBand * 2 ) * (
self.maxShellBand * 2 ) * (
self.maxShellBand * 2 ) )];
680 for ( proshade_unsign iter = 0; iter < static_cast<proshade_unsign> ( (
self.maxShellBand * 2 ) * (
self.maxShellBand * 2 ) * (
self.maxShellBand * 2 ) ); iter++ ) { npVals[iter].real (
self.so3CoeffsInverse[iter][0] ); npVals[iter].imag (
self.so3CoeffsInverse[iter][1] ); }
683 pybind11::capsule pyCapsuleRotMap ( npVals, [](
void *f ) { std::complex<proshade_double>* foo =
reinterpret_cast< std::complex<proshade_double>*
> ( f );
delete foo; } );
686 pybind11::array_t < std::complex < proshade_double > > retArr = pybind11::array_t < std::complex < proshade_double > > (
687 { (
self.maxShellBand * 2 ), (
self.maxShellBand * 2 ), (
self.maxShellBand * 2 ) },
688 { (
self.maxShellBand * 2 ) * (
self.maxShellBand * 2 ) *
sizeof(std::complex < proshade_double >),
689 (
self.maxShellBand * 2 ) *
sizeof(std::complex < proshade_double >),
690 sizeof(std::complex < proshade_double >) },
696 },
"This function returns the (self) rotation function as a three-dimensional map of complex numbers." )
697 .def (
"getRotationMatrixFromSOFTCoordinates",
701 proshade_double* npVals =
new proshade_double[9];
705 proshade_double eulA, eulB, eulG;
714 pybind11::capsule pyCapsuleRMSoft ( npVals, [](
void *f ) { proshade_double* foo =
reinterpret_cast< proshade_double*
> ( f );
delete foo; } );
717 pybind11::array_t < proshade_double > retArr = pybind11::array_t < proshade_double > ( { 3, 3 },
718 { 3 *
sizeof(proshade_double),
sizeof(proshade_double) },
724 },
"This function converts a given rotation function map position onto the corresponding rotation matrix.", pybind11::arg (
"xPos" ), pybind11::arg (
"yPos" ), pybind11::arg (
"zPos" ) )
725 .def (
"getTranslationFunctionMap",
729 std::complex<proshade_double>* npVals =
new std::complex < proshade_double >[
static_cast<proshade_unsign
> (
self.getXDim() *
self.getYDim() *
self.getZDim() )];
733 for ( proshade_unsign iter = 0; iter < static_cast<proshade_unsign> (
self.getXDim() *
self.getYDim() *
self.getZDim() ); iter++ ) { npVals[iter].real (
self.translationMap[iter][0] ); npVals[iter].imag (
self.translationMap[iter][1] ); }
736 pybind11::capsule pyCapsuleTrsMap ( npVals, [](
void *f ) { std::complex<proshade_double>* foo =
reinterpret_cast< std::complex<proshade_double>*
> ( f );
delete foo; } );
739 pybind11::array_t < std::complex < proshade_double > > retArr = pybind11::array_t < std::complex < proshade_double > > (
740 {
self.getXDim(),
self.getYDim(),
self.getZDim() },
741 {
self.getYDim() *
self.getZDim() *
sizeof(std::complex < proshade_double >),
742 self.getZDim() *
sizeof(std::complex < proshade_double >),
743 sizeof(std::complex < proshade_double >) },
749 },
"This function returns the translation function as a three-dimensional map of complex numbers." )
787 .def (
"__repr__", [] ( ) {
return "<ProSHADE_data class object> (This class contains all information, results and available functionalities for a structure)"; } );
790 pyProSHADE.def (
"computeGroupElementsForGroup",
791 [] ( proshade_double x, proshade_double y, proshade_double z, proshade_unsign fold ) -> pybind11::array_t < proshade_double >
797 proshade_double* npVals =
new proshade_double[
static_cast<proshade_unsign
> ( retVec.size() ) * 9];
801 for ( proshade_unsign iter = 0; iter < static_cast<proshade_unsign> ( retVec.size() ); iter++ ) {
for ( proshade_unsign it = 0; it < 9; it++ ) { npVals[(iter*9)+it] = retVec.at(iter).at(it); } }
804 pybind11::capsule pyCapsuleGrEls ( npVals, [](
void *f ) { proshade_double* foo =
reinterpret_cast< proshade_double*
> ( f );
delete foo; } );
807 pybind11::array_t < proshade_double > retArr = pybind11::array_t < proshade_double > (
808 {
static_cast< int > ( retVec.size() ), 3, 3 },
809 { 9 *
sizeof(proshade_double), 3 *
sizeof(proshade_double),
sizeof(proshade_double) },
815 },
"This function takes the axis and fold and computes all resulting group elements (as rotation matrices), returning them in numpy.ndarray.", pybind11::arg (
"x" ), pybind11::arg (
"y" ), pybind11::arg (
"z" ), pybind11::arg (
"fold" ) );
816 pyProSHADE.def (
"joinElementsFromDifferentGroups",
817 [] ( pybind11::array_t < proshade_double, pybind11::array::c_style | pybind11::array::forcecast > first,
818 pybind11::array_t < proshade_double, pybind11::array::c_style | pybind11::array::forcecast > second,
819 proshade_double matrixTolerance,
820 bool combine ) -> pybind11::array_t < proshade_double >
823 pybind11::buffer_info buf1 = first.request();
824 pybind11::buffer_info buf2 = second.request();
827 if ( buf1.ndim != 3 || buf2.ndim != 3 )
829 std::cerr <<
"Function joinElementsFromDifferentGroups() arguments first and second should be numpy.ndarrays with 3 dimensions indexed as follos: first[elementNumber][elementRotationMatrixRow][elementRotationMatrixColumn] - the same format as returned by the computeGroupElementsForGroup() function." << std::endl;
830 return ( pybind11::array_t < proshade_double > () );
834 std::vector< std::vector< proshade_double > > fVec, sVec;
836 proshade_double* dataPtr1 =
reinterpret_cast < proshade_double*
> ( buf1.ptr );
837 for ( proshade_unsign elIt = 0; elIt < static_cast<proshade_unsign> ( buf1.shape.at(0) ); elIt++ )
839 std::vector< proshade_double > rotMat;
840 for ( proshade_unsign rowIt = 0; rowIt < static_cast<proshade_unsign> ( buf1.shape.at(1) ); rowIt++ )
842 for ( proshade_unsign colIt = 0; colIt < static_cast<proshade_unsign> ( buf1.shape.at(2) ); colIt++ )
850 proshade_double* dataPtr2 =
reinterpret_cast < proshade_double*
> ( buf2.ptr );
851 for ( proshade_unsign elIt = 0; elIt < static_cast<proshade_unsign> ( buf2.shape.at(0) ); elIt++ )
853 std::vector< proshade_double > rotMat;
854 for ( proshade_unsign rowIt = 0; rowIt < static_cast<proshade_unsign> ( buf2.shape.at(1) ); rowIt++ )
856 for ( proshade_unsign colIt = 0; colIt < static_cast<proshade_unsign> ( buf2.shape.at(2) ); colIt++ )
869 proshade_double* npVals =
new proshade_double[
static_cast<proshade_unsign
> ( retVec.size() ) * 9];
873 for ( proshade_unsign iter = 0; iter < static_cast<proshade_unsign> ( retVec.size() ); iter++ ) {
for ( proshade_unsign it = 0; it < 9; it++ ) { npVals[(iter*9)+it] = retVec.at(iter).at(it); } }
876 pybind11::capsule pyCapsuleGrElsCombo ( npVals, [](
void *f ) { proshade_double* foo =
reinterpret_cast< proshade_double*
> ( f );
delete foo; } );
879 pybind11::array_t < proshade_double > retArr = pybind11::array_t < proshade_double > (
880 {
static_cast< int > ( retVec.size() ), 3, 3 },
881 { 9 *
sizeof(proshade_double), 3 *
sizeof(proshade_double),
sizeof(proshade_double) },
883 pyCapsuleGrElsCombo );
887 },
"This function takes the axis and fold and computes all resulting group elements (as rotation matrices), returning them in numpy.ndarray.", pybind11::arg (
"first" ), pybind11::arg (
"second" ), pybind11::arg (
"matrixTolerance" ), pybind11::arg (
"combine" ) );
888 pyProSHADE.def (
"getRotationFunctionSpheres",
895 std::cerr <<
"Function getRotationFunctionSpheres() was called before rotation function was computed. Please compute the rotation function by calling the computeRotationFunction() function first. Returning empty array." << std::endl;
896 return ( pybind11::array_t < proshade_double > () );
902 std::cerr <<
"The fold for which the rotation function should be mapped is not in the allowed range (i.e. 2+). Returning empty array." << std::endl;
903 return ( pybind11::array_t < proshade_double > () );
907 std::vector<ProSHADE_internal_spheres::ProSHADE_rotFun_sphere*> sphereMappedRotFun;
910 proshade_double soughtAngle = 0.0;
911 for ( proshade_double angIt = 1.0; angIt < static_cast < proshade_double > ( fold ); angIt += 1.0 )
914 soughtAngle = angIt * ( 2.0 * M_PI /
static_cast<proshade_double
> ( fold ) );
918 M_PI /
static_cast< proshade_double
> ( dataObj->
getMaxBand() ),
921 static_cast<proshade_unsign
> ( angIt - 1.0 ) ) );
924 sphereMappedRotFun.at(
static_cast < size_t > ( angIt - 1.0 ))->interpolateSphereValues ( dataObj->
getInvSO3Coeffs ( ) );
928 proshade_double* npVals =
new proshade_double[(dataObj->
getMaxBand() * 2) * (dataObj->
getMaxBand() * 2) * (fold - 1)];
932 std::vector< std::vector < proshade_double > > vls;
934 for (
size_t sphIt = 0; sphIt < sphereMappedRotFun.size(); sphIt++ )
937 vls = sphereMappedRotFun.at(sphIt)->getCopyOfValues ();
939 for (
size_t lonIt = 0; lonIt < (dataObj->
getMaxBand() * 2); lonIt++ )
941 for (
size_t latIt = 0; latIt < (dataObj->
getMaxBand() * 2); latIt++ )
943 valIter = latIt +
static_cast< size_t > ( dataObj->
getMaxBand() * 2 ) * ( lonIt +
static_cast< size_t > ( dataObj->
getMaxBand() * 2 ) * sphIt );
944 npVals[valIter] = vls.at(lonIt).at(latIt);
950 pybind11::capsule pyCapsuleRFMapSph ( npVals, [](
void *f ) { proshade_double* foo =
reinterpret_cast< proshade_double*
> ( f );
delete foo; } );
953 pybind11::array_t < proshade_double > retArr = pybind11::array_t < proshade_double > (
954 {
static_cast< int > ( sphereMappedRotFun.size() ),
static_cast< int > (dataObj->
getMaxBand() * 2),
static_cast< int > (dataObj->
getMaxBand() * 2) },
955 { (dataObj->
getMaxBand() * 2) * (dataObj->
getMaxBand() * 2) *
sizeof(proshade_double), (dataObj->
getMaxBand() * 2) *
sizeof(proshade_double),
sizeof(proshade_double) },
961 },
"This function allows access to the (self-)rotation function mapping to spheres with the angle being the radius and the longitude/latitude angles being the axis of the rotation for a particular fold (i.e. for all angles required by the fold except for the angle 0)." );