#include #include #include #include #include #include #include #include #include namespace ccp4io_adaptbx { namespace boost_python { using namespace ssm; using namespace mmdb; class PySSMAlign : public Align { public: PySSMAlign() {} ~PySSMAlign() {} boost::python::tuple get_t_matrix() const { return boost::python::make_tuple( TMatrix[0][0], TMatrix[0][1], TMatrix[0][2], TMatrix[0][3], TMatrix[1][0], TMatrix[1][1], TMatrix[1][2], TMatrix[1][3], TMatrix[2][0], TMatrix[2][1], TMatrix[2][2], TMatrix[2][3] ); } boost::python::list get_q_values() const { boost::python::list l; realtype* pqvalues = GetQvalues(); for ( int i = 0; i < GetNMatches(); ++i ) { l.append( pqvalues[ i ] ); } return l; } }; class ResidueData { public: realtype hydropathy; boost::python::str chain_id, resname, inscode; int sse_type, resseq; ResidueData( const realtype& hydropathy_, const ChainID& chain_id_, const ResName& resname_, const InsCode& inscode_, int sse_type_, int resseq_ ) : hydropathy( hydropathy_ ), chain_id( chain_id_[0] == '\0' ? " " : boost::python::str( chain_id_, 1 ) ), resname( boost::python::str( resname_, 3 ) ), inscode( inscode_[0] == '\0' ? " " : boost::python::str( inscode_, 1 ) ), sse_type( sse_type_ ), resseq( resseq_ ) {} ~ResidueData() {} }; class PyXAlignText : public XAlignText { private: int length; public: PyXAlignText() : length( 0 ) {} ~PyXAlignText() {} void py_x_align(PManager m1, PManager m2, PySSMAlign& cssm) { PPAtom Calpha1,Calpha2; int nat1,nat2,nr; m1->GetSelIndex ( cssm.selHndCa1,Calpha1,nat1 ); m2->GetSelIndex ( cssm.selHndCa2,Calpha2,nat2 ); align( cssm.G1, Calpha1, cssm.Ca1, nat1, cssm.G2, Calpha2, cssm.Ca2, nat2, cssm.dist1, length ); } boost::python::list get_blocks() { boost::python::list l; PXTAlign XTA = GetTextRows(); for( int i = 0; i < length; ++i) { boost::python::tuple equivs; boost::python::tuple info; switch ( XTA[i].alignKey ) { case 0: // KEY_ALIGNED info = boost::python::make_tuple( XTA[i].dist, XTA[i].loopNo, XTA[i].simindex ); // no break! case 1: // KEY_NOT_ALIGNED equivs = boost::python::make_tuple( ResidueData( XTA[i].hydropathy1, XTA[i].chID1, XTA[i].resName1, XTA[i].insCode1, XTA[i].sseType1, XTA[i].seqNum1 ), ResidueData( XTA[i].hydropathy2, XTA[i].chID2, XTA[i].resName2, XTA[i].insCode2, XTA[i].sseType2, XTA[i].seqNum2 ) ); break; case 2: // KEY_FIRST_GAP equivs = boost::python::make_tuple( boost::python::object(), ResidueData( XTA[i].hydropathy2, XTA[i].chID2, XTA[i].resName2, XTA[i].insCode2, XTA[i].sseType2, XTA[i].seqNum2 ) ); break; case 3: // KEY_SECOND_GAP equivs = boost::python::make_tuple( ResidueData( XTA[i].hydropathy1, XTA[i].chID1, XTA[i].resName1, XTA[i].insCode1, XTA[i].sseType1, XTA[i].seqNum1 ), boost::python::object() ); break; } l.append( boost::python::make_tuple( equivs, info ) ); } return l; } }; struct MultAlignResidueData { public: bool aligned; boost::python::str chain_id, resname, inscode; int sse_type, resseq; MultAlignResidueData( const ChainID& chain_id_, const ResName& resname_, const InsCode& inscode_, int sse_type_, int resseq_, bool aligned_ ) : chain_id( chain_id_[0] == '\0' ? "" : boost::python::str( chain_id_, 1 ) ), resname( resname_[0] == '\0' ? "" : boost::python::str( resname_, 3 ) ), inscode( inscode_[0] == '\0' ? "" : boost::python::str( inscode_, 1 ) ), sse_type( sse_type_ ), resseq( resseq_ ), aligned( aligned_ ) {} ~MultAlignResidueData() {} }; class MultipleAlignment { public: typedef boost::scoped_ptr< Graph > graph_ptr_type; private: int rc_; boost::python::list result_; boost::python::list matrices_; int n_align_; int n_sses_; mmdb::realtype rmsd_; mmdb::realtype q_score_; public: MultipleAlignment( boost::python::object managers, boost::python::object selstrings ) : rc_( MALIGN_NoAlignment ), n_align_( 0 ), n_sses_( 0 ), rmsd_( 0 ), q_score_( 0 ) { using namespace boost::python; using namespace boost; std::size_t size = extract< std::size_t >( managers.attr( "__len__" )() ); assert ( size == extract< std::size_t >( selstrings.attr( "__len__" )() ) ); scoped_array< PManager > p_managers( new PManager[ size ] ); scoped_array< int > p_handles( new int[ size ] ); scoped_array< pstr > p_strs( new pstr[ size ] ); scoped_array< graph_ptr_type > p_graphs( new graph_ptr_type[ size ] ); scoped_array< PGraph > p_raw_pgraphs( new PGraph[ size ] ); for ( std::size_t i = 0; i < size; ++i ) { p_managers[ i ] = extract< Manager* >( managers[ i ] ); p_strs[ i ] = extract< char* >( selstrings[ i ] ); p_handles[ i ] = p_managers[ i ]->NewSelection(); p_managers[ i ]->Select( p_handles[ i ], STYPE_ATOM, p_strs[ i ], SKEY_NEW ); } rc_ = MALIGN_Ok; for ( std::size_t i = 0; i < size; ++i ) { graph_ptr_type graph_ptr( GetSSGraph( p_managers[ i ], p_handles[ i ], rc_ ) ); if ( rc_ != MALIGN_Ok ) { break; } p_graphs[ i ].swap( graph_ptr ); p_raw_pgraphs[ i ] = p_graphs[ i ].get(); } MultAlign malign; if ( rc_ == MALIGN_Ok ) { rc_ = malign.align( p_managers.get(), p_strs.get(), p_raw_pgraphs.get(), size ); } if ( rc_ == MALIGN_Ok ) { get_ma_output( malign ); get_ss_output( malign, size ); get_scores( malign ); } for ( std::size_t i = 0; i < size; ++i ) { p_managers[ i ]->DeleteSelection( p_handles[ i ] ); } } ~MultipleAlignment() {} public: int get_return_code() const { return rc_; } boost::python::list get_alignment() const { return result_; } boost::python::list get_matrices() const { return matrices_; } int get_n_align() const { return n_align_; } int get_n_sses() const { return n_sses_; } mmdb::realtype get_rmsd() const { return rmsd_; } mmdb::realtype get_q_score() const { return q_score_; } private: void get_ma_output(MultAlign& malign) { PPMAOutput MAOut = NULL; int nrows = 0; int ncols = 0; malign.GetMAOutput ( MAOut, nrows, ncols ); for ( int i = 0; i < nrows; ++i ) { boost::python::list row; for ( int j = 0; j < ncols; ++j ) { MAOutput const& ma = MAOut[i][j]; row.append( MultAlignResidueData( ma.chID, ma.name, ma.insCode, ma.sseType, ma.seqNum, ma.aligned ) ); } result_.append( row ); } FreeMSOutput ( MAOut, nrows ); } void get_ss_output(MultAlign& malign, int size) { mmdb::mat44 T; for ( int i=0; i< size; ++i ) { malign.getTMatrix( T, i ); matrices_.append( boost::python::make_tuple( T[0][0],T[0][1],T[0][2],T[0][3], T[1][0],T[1][1],T[1][2],T[1][3], T[2][0],T[2][1],T[2][2],T[2][3] ) ); } } void get_scores(MultAlign& malign) { malign.getAlignScores( n_align_, n_sses_, rmsd_, q_score_ ); } }; struct Manager_wrappers { typedef Manager wt; static boost::python::object GetSymOp_wrapper( wt& O, int Nop) { cpstr s = O.GetSymOp(Nop); if (s == 0) return boost::python::object(); return boost::python::str(s); } static void wrap() { using namespace boost::python; class_( "Manager", init<>() ) .def( "SetFlag", &wt::SetFlag, ( arg( "flag" ) ) ) .def("ReadPDBASCII", (ERROR_CODE (wt::*)(cpstr, io::GZ_MODE)) &wt::ReadPDBASCII, ( arg( "fileName" ), arg( "gzipMode" ))) .def( "PutPDBString", (ERROR_CODE (wt::*)(cpstr)) &wt::PutPDBString, ( arg( "pdbString" ))) .def( "WritePDBASCII", (ERROR_CODE (wt::*)(cpstr, io::GZ_MODE)) &wt::WritePDBASCII, ( arg( "fileName" ), arg( "gzipMode" ))) .def( "NewSelection", &wt::NewSelection ) .def("Select", (int (wt::*)(int, SELECTION_TYPE, cpstr, SELECTION_KEY)) &wt::Select, ( arg( "selHnd" ), arg( "selType" ), arg( "cid" ), arg( "selKey"))) .def( "GetSelLength", &wt::GetSelLength, ( arg( "selHnd" ) ) ) .def( "isSpaceGroup", &wt::isSpaceGroup ) .def( "GetNumberOfSymOps", &wt::GetNumberOfSymOps ) .def( "GetSymOp", GetSymOp_wrapper, ( arg( "Nop" ) ) ) ; } }; void init_module() { using namespace boost::python; object package = scope(); package.attr( "__path__" ) = "ccp4io_adaptbx"; object mmdb_module(( handle<>( borrowed( PyImport_AddModule( "ccp4io_adaptbx.mmdb" ) ) ) )); object ssm_module(( handle<>( borrowed( PyImport_AddModule( "ccp4io_adaptbx.ssm" ) ) ) )); scope().attr( "mmdb" ) = mmdb_module; scope().attr( "ssm" ) = ssm_module; scope mmdb_scope = mmdb_module; enum_("SELECTION_TYPE") .value("INVALID", STYPE_INVALID) .value("UNDEFINED", STYPE_UNDEFINED) .value("ATOM", STYPE_ATOM) .value("RESIDUE", STYPE_RESIDUE) .value("CHAIN", STYPE_CHAIN) .value("MODEL", STYPE_MODEL); enum_("SELECTION_KEY") .value("NEW", SKEY_NEW) .value("OR", SKEY_OR) .value("AND", SKEY_AND) .value("XOR", SKEY_XOR) .value("CLR", SKEY_CLR) .value("XAND", SKEY_XAND); enum_("ERROR_CODE") .value("EmptyCIF",Error_EmptyCIF) .value("NoError",Error_NoError) .value("Ok",Error_Ok); enum_("MMDB_READ_FLAG") .value("PrintCIFWarnings", MMDBF_PrintCIFWarnings ) .value("IgnoreDuplSeqNum", MMDBF_IgnoreDuplSeqNum) .value("IgnoreNonCoorPDBErrors", MMDBF_IgnoreNonCoorPDBErrors); enum_("IO_GZ_MODE") .value("NONE", io::GZM_NONE) .value("CHECK", io::GZM_CHECK) .value("ENFORCE", io::GZM_ENFORCE) .value("ENFORCE_GZIP", io::GZM_ENFORCE_GZIP) .value("ENFORCE_COMPRESS", io::GZM_ENFORCE_COMPRESS); enum_("IO_FILE_ERROR") .value("NoMemory", io::FileError_NoMemory) .value("ShortData", io::FileError_ShortData) .value("_NoDataFound", io::FileError_NoDataFound) .value("NoColumn", io::FileError_NoColumn) .value("BadData", io::FileError_BadData) .value("WrongMemoryAllocation", io::FileError_WrongMemoryAllocation); def( "GetErrorDescription", &GetErrorDescription ); InitMatType(); Manager_wrappers::wrap(); scope ssm_scope = ssm_module; enum_("SUPERPOSITION_RESULT") .value("Ok", SPOSE_Ok) .value("BadData", SPOSE_BadData) .value("NoCalphas1", SPOSE_NoCalphas1) .value("NoCalphas2", SPOSE_NoCalphas2) .value("RemoteStruct", SPOSE_RemoteStruct) .value("SVDFail", SPOSE_SVDFail); enum_("RETURN_CODE") .value("Ok", RC_Ok) .value("NoHits", RC_NoHits) .value("NoSuperposition", RC_NoSuperposition) .value("NoGraph", RC_NoGraph) .value("NoVertices", RC_NoVertices) .value("NoGraph2", RC_NoGraph2) .value("NoVertices2", RC_NoVertices2) .value("TooFewMatches", RC_TooFewMatches); enum_("PRECISION") .value("Highest", PREC_Highest) .value("High", PREC_High) .value("Normal", PREC_Normal) .value("Low", PREC_Low) .value("Lowest", PREC_Lowest); enum_("CONNECTIVITY") .value("Flexible", CONNECT_Flexible) .value("None_", CONNECT_None) .value("Strict", CONNECT_Strict); enum_("VERTEX_TYPE") .value("UNKNOWN", V_UNKNOWN) .value("HELIX", V_HELIX) .value("STRAND", V_STRAND); enum_("MALIGN") .value("Ok", MALIGN_Ok) .value("BadInput", MALIGN_BadInput) .value("NoStructure", MALIGN_NoStructure) .value("NoAlignment", MALIGN_NoAlignment) .value("NoGraph", MALIGN_NoGraph); InitGraph(); class_< PySSMAlign >( "SSMAlign", init<>() ) .def( "Align", &PySSMAlign::align, ( arg( "manager1" ), arg( "manager2" ), arg( "precision" ), arg( "connectivity" ), arg( "selHnd1" ), arg( "selHnd2" ) ) ) .def( "GetQvalues", &PySSMAlign::get_q_values ) .def( "AlignSelectedMatch", &PySSMAlign::AlignSelectedMatch, ( arg( "manager1" ), arg( "manager2" ), arg( "precision" ), arg( "connectivity" ), arg( "selHnd1" ), arg( "selHnd2" ), arg( "nselected" ) ) ) .def_readonly( "rmsd", &PySSMAlign::rmsd ) .def_readonly( "n_align", &PySSMAlign::nalgn ) .add_property( "t_matrix", &PySSMAlign::get_t_matrix ) ; class_< ResidueData >( "ResidueData", no_init ) .def_readonly( "hydropathy", &ResidueData::hydropathy ) .def_readonly( "chain_id", &ResidueData::chain_id ) .def_readonly( "resname", &ResidueData::resname ) .def_readonly( "inscode", &ResidueData::inscode ) .def_readonly( "sse_type", &ResidueData::sse_type ) .def_readonly( "resseq", &ResidueData::resseq ) ; class_< PyXAlignText >( "XAlignText", init<>() ) .def( "XAlign", &PyXAlignText::py_x_align, ( arg( "manager1" ), arg( "manager2" ), arg( "ssm_align" ) ) ) .def( "get_blocks", &PyXAlignText::get_blocks ) ; class_< MultAlignResidueData >( "MultAlignResidueData", no_init ) .def_readonly( "chain_id", &MultAlignResidueData::chain_id ) .def_readonly( "resname", &MultAlignResidueData::resname ) .def_readonly( "inscode", &MultAlignResidueData::inscode ) .def_readonly( "sse_type", &MultAlignResidueData::sse_type ) .def_readonly( "resseq", &MultAlignResidueData::resseq ) .def_readonly( "aligned", &MultAlignResidueData::aligned ) ; class_< MultipleAlignment >( "MultipleAlignment", no_init ) .def( init< object, object >( ( arg( "managers" ), arg( "selstrings" ) ) ) ) .def( "get_return_code", &MultipleAlignment::get_return_code ) .def( "get_alignment", &MultipleAlignment::get_alignment ) .def( "get_matrices", &MultipleAlignment::get_matrices ) .def( "get_n_align", &MultipleAlignment::get_n_align ) .def( "get_n_sses", &MultipleAlignment::get_n_sses ) .def( "get_rmsd", &MultipleAlignment::get_rmsd ) .def( "get_q_score", &MultipleAlignment::get_q_score ) ; } }} // namespace ccp4io_adaptbx::boost_python BOOST_PYTHON_MODULE( ccp4io_adaptbx_ext ) { ccp4io_adaptbx::boost_python::init_module(); }