mmdb2-2.0.5/0000775000175000017500000000000012604270557007532 500000000000000mmdb2-2.0.5/mmdb2/0000775000175000017500000000000012604270557010533 500000000000000mmdb2-2.0.5/mmdb2/mmdb_math_rand.cpp0000664000175000017500000001344312401105774014111 00000000000000// $Id: mmdb_math_rand.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : Rand // ~~~~~~~~~ // **** Classes : RandomNumber ( random number generator ) // ~~~~~~~~~ // // (C) E. Krissinel 1997-2013 // // ================================================================= // #include #include "mmdb_math_rand.h" namespace mmdb { namespace math { // =================== RandomNumber ========================== RandomNumber::RandomNumber ( long IJ, long KL ) { Init ( IJ,KL ); } void RandomNumber::Init ( long IJ, long KL ) { long i,j,k,l,m, ii,jj; realtype s,t; iset = 0; gset = 0.0; if ((IJ<0) || (IJ>_RN_MAX_IJ) || (KL<0) || (KL>_RN_MAX_KL)) return; i = mod(IJ/177,177) + 2; j = mod(IJ,177) + 2; k = mod(KL/169,178) + 1; l = mod(KL,169); for (ii=0;ii<97;ii++) { s = 0.0; t = 0.5; for (jj=1;jj<=24;jj++) { m = mod(mod(i*j,179)*k,179); i = j; j = k; k = m; l = mod(53*l+1,169); if (mod(l*m,64)>=32) s += t; t *= 0.5; } U[ii] = s; } C = 362436.0 / 16777216.0; CD = 7654321.0 / 16777216.0; CM = 16777213.0 / 16777216.0; I97 = 96; J97 = 32; } // uniform [0..1] random number generator realtype RandomNumber::random() { realtype uni; uni = U[I97] - U[J97]; if (uni<0.0) uni += 1.0; U[I97] = uni; I97--; if (I97<0) I97 = 96; J97--; if (J97<0) J97 = 96; C -= CD; if (C<0.0) C += CM; uni -= C; if (uni<0.0) uni += 1.0; return uni; } // uniform [-1..1] random number generator realtype RandomNumber::srandom() { realtype uni; uni = U[I97] - U[J97]; if (uni<0.0) uni += 1.0; U[I97] = uni; I97--; if (I97<0) I97 = 96; J97--; if (J97<0) J97 = 96; C -= CD; if (C<0.0) C += CM; uni -= C; if (uni<0.0) uni += 1.0; return 2.0*uni - 1.0; } // gaussian random numbers realtype RandomNumber::gauss_rnd() { realtype v1,v2,r,fac; if (iset==0) { do { v1 = srandom(); v2 = srandom(); r = v1*v1 + v2*v2; } while ((r>=1.0) || (r==0.0)); fac = sqrt(-2.0*log(r)/r); gset = v1*fac; iset = 1; return v2*fac; } else { iset = 0; return gset; } } void RandomNumber::write ( io::RFile f ) { int Version=1; f.WriteFile ( &Version,sizeof(Version) ); f.WriteFile ( &I97 ,sizeof(I97) ); f.WriteFile ( &J97 ,sizeof(J97) ); f.WriteFile ( U ,sizeof(U) ); f.WriteFile ( &C ,sizeof(C) ); f.WriteFile ( &CD ,sizeof(CD) ); f.WriteFile ( &CM ,sizeof(CM) ); f.WriteFile ( &gset ,sizeof(gset) ); f.WriteFile ( &iset ,sizeof(iset) ); } void RandomNumber::read ( io::RFile f ) { int Version; f.ReadFile ( &Version,sizeof(Version) ); f.ReadFile ( &I97 ,sizeof(I97) ); f.ReadFile ( &J97 ,sizeof(J97) ); f.ReadFile ( U ,sizeof(U) ); f.ReadFile ( &C ,sizeof(C) ); f.ReadFile ( &CD ,sizeof(CD) ); f.ReadFile ( &CM ,sizeof(CM) ); f.ReadFile ( &gset ,sizeof(gset) ); f.ReadFile ( &iset ,sizeof(iset) ); } } // namespace math } // namespace mmdb /* static int m1 = 259200; static int ia1 = 7141; static int ic1 = 54773; static realtype rm1 = 1.0/259200.0; static int m2 = 134456; static int ia2 = 8121; static int ic2 = 28411; static realtype rm2 = 1.0/134456.0; static int m3 = 243000; static int ia3 = 4561; static int ic3 = 51349; static int ix1 = 0; static int ix2 = 0; static int ix3 = 0; static realtype R[97]; void randomize ( int iseed ) { int j; RndInit = True; ix1 = mod(ic1-iseed,m1); ix1 = mod(ia1*ix1+ic1,m1); ix2 = mod(ix1,m2); ix1 = mod(ia1*ix1+ic1,m1); ix3 = mod(ix1,m3); for (j=0;j<97;j++) { ix1 = mod(ia1*ix1+ic1,m1); ix2 = mod(ia2*ix2+ic2,m2); R[j] = (ix1+ix2*rm2)*rm1; } } realtype rand() { int j; realtype rnd; if (!RndInit) randomize(); ix1 = mod(ia1*ix1+ic1,m1); ix2 = mod(ia2*ix2+ic2,m2); ix3 = mod(ia3*ix3+ic3,m3); j = 1 + (97*ix3)/m3; j = IMax(j,1); j = IMin(j,97); rnd = R[j-1]; R[j] = (ix1+ix2*rm2)*rm1; return rnd; } */ // =========================================================== // End of Random_N mmdb2-2.0.5/mmdb2/mmdb_seqsuperpose.cpp0000775000175000017500000002345512401105774014721 00000000000000// $Id: mmdb_seqsuperpose.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 19.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : SeqSuperpose // ~~~~~~~~~ // **** Classes : mmdb::SeqSuperpose // ~~~~~~~~~ // // (C) E.Krissinel 2005-2013 // // ================================================================= // #include #include #include "mmdb_tables.h" #include "mmdb_seqsuperpose.h" namespace mmdb { // ================================================================= SeqSuperpose::SeqSuperpose() { SeqSuperposeInit(); } SeqSuperpose::~SeqSuperpose() { FreeMemory(); } void SeqSuperpose::SeqSuperposeInit() { Align = NULL; Mat4Init ( TMatrix ); // superposes Ca1 over Ca2: |T*Ca1 - Ca2|->min Q = -0.5; // Q-score rmsd = MaxReal; // rmsd seqId = MaxReal; // sequence identity _seqId = 0.0; // sequence identity in sequence alignment Nalign = 0; // alignment length c1 = NULL; // sup-n vector: Ca1[i]->Ca2[c1[i]] if c1[i]>=0 c2 = NULL; // sup-n vector: Ca2[i]->Ca1[c2[i]] if c2[i]>=0 cn1 = NULL; // temporary contact array #1 cn2 = NULL; // temporary contact array #2 Rmsd0 = 3.0; // quality optimization parameter maxContact = 15.0; // maximal Calpha-pair contact parameter contact = NULL; ncontacts = 0; } void SeqSuperpose::FreeMemory() { if (Align) { delete Align; Align = NULL; } FreeVectorMemory ( c1 ,0 ); FreeVectorMemory ( c2 ,0 ); FreeVectorMemory ( cn1,0 ); FreeVectorMemory ( cn2,0 ); if (contact) { delete[] contact; contact = NULL; } ncontacts = 0; } void makeAAString ( pstr & S, PPAtom C, int nat ) { pstr rname; ResName r1; int i,j; S = new char[nat+1]; j = 0; for (i=0;iGetResName(); if (rname) { Get1LetterCode ( rname,r1 ); S[j++] = r1[0]; } } S[j] = char(0); } realtype SeqSuperpose::MatchQuality ( int Nalign, realtype Rmsd, int nres1, int nres2 ) { if (Nalign==0) return 0.0; return MatchQuality2 ( Nalign,Rmsd*Rmsd*Nalign,nres1,nres2 ); } realtype SeqSuperpose::MatchQuality2 ( int Nalign, realtype dist2, int nres1, int nres2 ) { realtype NormN,Na2,NormR; NormN = nres1*nres2; if (NormN<=0.0) return 0.0; Na2 = Nalign*Nalign; NormR = dist2/(Nalign*Rmsd0*Rmsd0); return Na2/((1.0+NormR)*NormN); } void SeqSuperpose::MakeContacts ( mat44 & TM, realtype cont_est ) { // Find the closest contacts atoms and makes the correspondence // vectors cn1 and cn2 int i,j,i1,i2; // 1. Find all contacts in the range of 0.0 - cont_est if (contact) { delete[] contact; contact = NULL; } ncontacts = 0; M->SeekContacts ( Ca2,nCa2,Ca1,nCa1,0.0,cont_est,0, contact,ncontacts,0,&TM,0, BRICK_ON_1 | BRICK_READY ); // 2. Leave only unique shortest contacts, that is, if Ca1[i]-Ca2[j] // is the shortest contact for atom Ca1[i], it has also to be // the shortest contact for atom Ca2[j]. if (ncontacts>0) { SortContacts ( contact,ncontacts,CNSORT_DINC ); for (i=0;iGetAlignedS(); T = Align->GetAlignedT(); GetVectorMemory ( cn1,nCa1,0 ); GetVectorMemory ( c1 ,nCa1,0 ); for (i=0;iGetSpace(); while (S[i] && (i1areBricks())) M->MakeBricks ( Ca2,nCa2,1.25*maxContact ); Q = -1.0; Q0 = -1.0; iter = 0; iter1 = 0; do { Q = RMax ( Q,Q0 ); iter++; rc = SuperposeAtoms ( TM,Ca1,nCa1,Ca2,cn1 ); if (rc==SPOSEAT_Ok) { MakeContacts ( TM,maxContact ); dist2 = 0.0; for (i=0;i0) { i = ncontacts; while (i>3) { i--; dist2 -= contact[i].dist; if (dist2<=i*maxRMSD2) { // rmsd must be within the limits Q1 = MatchQuality2 ( i,dist2,nCa1,nCa2 ); if (Q1>Q0) { Q0 = Q1; nal = i; dist20 = dist2; } } } for (i=nal+1;iQ) { for (i=0;i100)) rc = SEQSP_IterLimit; } while ((rc==SPOSEAT_Ok) && ((Q=2))); if (Nalign>0) { SuperposeAtoms ( TMatrix,Ca1,nCa1,Ca2,c1 ); rmsd = sqrt(rmsd/Nalign); // rmsd seqId = 0.0; for (i=0;i=0) { if (!strcasecmp(Ca1[i]->GetResName(),Ca2[c1[i]]->GetResName())) seqId += 1.0; } seqId = seqId/Nalign; } else { rmsd = MaxReal; seqId = 0.0; } FreeVectorMemory ( cn1,0 ); FreeVectorMemory ( cn2,0 ); if (!keepBricks) M->RemoveBricks(); return rc; } int SeqSuperpose::Superpose ( PManager MMDB, PPAtom Calpha1, int nCalpha1, PPAtom Calpha2, int nCalpha2, realtype seqThreshold, bool keepBricks ) { pstr S,T; Mat4Init ( TMatrix ); // superposes Ca1 over Ca2: |T*Ca1 - Ca2|->min Q = 0.0; // Q-score rmsd = MaxReal; // rmsd seqId = MaxReal; // sequence identity in structure alignment Nalign = 0; // alignment length in structure alignment FreeVectorMemory ( c1,0 ); FreeVectorMemory ( c2,0 ); _seqId = IMin(nCalpha1,nCalpha2); _seqId /= IMax(nCalpha1,nCalpha2); if (_seqIdAlign ( S,T,math::ALIGN_FREEENDS ); if (S) delete[] S; if (T) delete[] T; return makeStructAlignment ( seqThreshold,keepBricks ); } } // namespace mmdb mmdb2-2.0.5/mmdb2/mmdb_manager.cpp0000664000175000017500000002517712401105774013575 00000000000000// $Id: mmdb_manager.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 15.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : mmdb_manager // ~~~~~~~~~ // Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::Manager ( MMDB file manager ) // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include "mmdb_manager.h" namespace mmdb { // ===================== Manager ======================= Manager::Manager() : BondManager() { } Manager::Manager ( io::RPStream Object ) : BondManager(Object) { } Manager::~Manager() {} void Manager::Copy ( PManager MMDB, COPY_MASK CopyMask ) { PModel mdl; PPChain chain; PChain ch; ChainID chID; int i,j, nchains; if (CopyMask & MMDBFCM_Flags) Flags = MMDB->Flags; if (CopyMask & MMDBFCM_Title) title.Copy ( &(MMDB->title) ); if (CopyMask & MMDBFCM_Cryst) cryst.Copy ( &(MMDB->cryst) ); if (CopyMask & MMDBFCM_Coord) { FreeCoordMemory (); DeleteAllSelections(); nAtoms = MMDB->nAtoms; atmLen = nAtoms; if (nAtoms>0) { atom = new PAtom[atmLen]; for (i=0;iatom[i]) { atom[i] = newAtom(); atom[i]->Copy ( MMDB->atom[i] ); // the internal atom references are installed // by residue classes when they are read in // model->chain below atom[i]->SetAtomIndex ( i+1 ); } else atom[i] = NULL; } } nModels = MMDB->nModels; if (nModels>0) { model = new PModel[nModels]; for (i=0;imodel[i]) { model[i] = newModel(); model[i]->SetMMDBManager ( this,0 ); model[i]->_copy ( MMDB->model[i] ); } else model[i] = NULL; } } crModel = NULL; crChain = NULL; crRes = NULL; if (MMDB->crModel) { for (i=0;iserNum==MMDB->crModel->serNum) { crModel = model[i]; break; } } if (crModel && crModel->chain && MMDB->crChain) for (i=0;inChains;i++) if (crModel->chain[i]) { if (!strcmp(crModel->chain[i]->chainID, MMDB->crModel->chain[i]->chainID)) { crChain = crModel->chain[i]; break; } } if (crChain && crChain->residue && MMDB->crRes) for (i=0;inResidues;i++) if (crChain->residue[i]) { if ((!strcmp(crChain->residue[i]->name, MMDB->crRes->name)) && (crChain->residue[i]->seqNum==MMDB->crRes->seqNum) && (!strcmp(crChain->residue[i]->insCode, MMDB->crRes->insCode))) { crRes = crChain->residue[i]; break; } } } /* if ((MMDB->nSelections>0) && MMDB->Mask) { nSelections = MMDB->nSelections; if (nSelections>0) { Mask = new PCMask [nSelections]; SelAtom = new PPAtom[nSelections]; nSelAtoms = new int [nSelections]; for (i=0;iCopyMask ( MMDB->Mask[i] ); nSelAtoms[i] = MMDB->nSelAtoms[i]; if (nSelAtoms[i]>0) { SelAtom[i] = new PAtom[nSelAtoms[i]]; for (j=0;jSelAtom[i][j]->index]; } else SelAtom[i] = NULL; } } } */ } else if (CopyMask & (MMDBFCM_HetInfo | MMDBFCM_SecStruct | MMDBFCM_Links | MMDBFCM_CisPeps | MMDBFCM_ChainAnnot)) { for (i=0;inModels;i++) if (MMDB->model[i]) { mdl = GetModel ( i+1 ); if (!mdl) { mdl = new Model( NULL,i+1 ); AddModel ( mdl ); } if (CopyMask & MMDBFCM_HetInfo) mdl->CopyHets ( MMDB->model[i] ); if (CopyMask & MMDBFCM_SecStruct) mdl->CopySecStructure ( MMDB->model[i] ); if (CopyMask & MMDBFCM_Links) { mdl->CopyLinks ( MMDB->model[i] ); mdl->CopyLinkRs ( MMDB->model[i] ); } if (CopyMask & MMDBFCM_CisPeps) mdl->CopyCisPeps ( MMDB->model[i] ); if (CopyMask & MMDBFCM_ChainAnnot) { MMDB->GetChainTable ( i+1,chain,nchains ); for (j=0;jGetChainID ( chID ); ch = mdl->GetChain ( chID ); if (!ch) { ch = new Chain(); ch->SetChainID ( chID ); mdl->AddChain ( ch ); } ch->CopyAnnotations ( chain[j] ); } } } } if (CopyMask & MMDBFCM_SA) SA.Copy ( &(MMDB->SA) ); if (CopyMask & MMDBFCM_SB) SB.Copy ( &(MMDB->SB) ); if (CopyMask & MMDBFCM_SC) SC.Copy ( &(MMDB->SC) ); if (CopyMask & MMDBFCM_Footnotes) Footnote.Copy ( &(MMDB->Footnote) ); if (CopyMask & MMDBFCM_Buffer) { lcount = MMDB->lcount; strncpy ( S,MMDB->S,sizeof(S) ); } } void Manager::Delete ( word DelMask ) { PPModel model; PPChain chain; int i,j,nm, nchains; if (DelMask & MMDBFCM_Flags) Flags = 0; if (DelMask & MMDBFCM_Title) title.Copy ( NULL ); if (DelMask & MMDBFCM_TitleKeepBM) title.FreeMemory ( true ); if (DelMask & MMDBFCM_Cryst) cryst.Copy ( NULL ); if (DelMask & MMDBFCM_Coord) { FreeCoordMemory (); DeleteAllSelections(); } if (DelMask & MMDBFCM_SecStruct) { GetModelTable ( model,nm ); if (model) for (i=0;iRemoveSecStructure(); } if (DelMask & MMDBFCM_HetInfo) { GetModelTable ( model,nm ); if (model) for (i=0;iRemoveHetInfo(); } if (DelMask & MMDBFCM_Links) { GetModelTable ( model,nm ); if (model) for (i=0;iRemoveLinks (); model[i]->RemoveLinkRs(); } } if (DelMask & MMDBFCM_CisPeps) { GetModelTable ( model,nm ); if (model) for (i=0;iRemoveCisPeps(); } if (DelMask & MMDBFCM_ChainAnnot) { nm = GetNumberOfModels(); for (i=1;i<=nm;i++) { GetChainTable ( i,chain,nchains ); if (chain) for (j=0;jFreeAnnotations(); } } if (DelMask & MMDBFCM_SA) SA.FreeContainer(); if (DelMask & MMDBFCM_SB) SB.FreeContainer(); if (DelMask & MMDBFCM_SC) SC.FreeContainer(); if (DelMask & MMDBFCM_Footnotes) Footnote.FreeContainer(); if (DelMask & MMDBFCM_Buffer) { lcount = 0; S[0] = char(0); } } PTitleContainer Manager::GetRemarks() { return title.GetRemarks(); } PTitleContainer Manager::GetJournal() { return title.GetJournal(); } realtype Manager::GetResolution() { return title.GetResolution(); } int Manager::ParseBiomolecules() { return title.ParseBiomolecules(); } int Manager::GetNofBiomolecules() { return title.GetNofBiomolecules(); } void Manager::GetBiomolecules ( PPBiomolecule & BM, int & nBMs ) { title.GetBiomolecules ( BM,nBMs ); } PBiomolecule Manager::GetBiomolecule ( int bmNo ) { return title.GetBiomolecule ( bmNo ); } PManager Manager::MakeBiomolecule ( int bmNo, int modelNo ) { PManager M; PPChain ch; PChain chain; PModel model; PBiomolecule BM; int i,j,k,n,n0,nChains; BM = title.GetBiomolecule ( bmNo ); if (!BM) return NULL; GetChainTable ( modelNo,ch,nChains ); if ((!ch) || (nChains<=0)) return NULL; n0 = 0; model = new Model(); for (i=0;(inBMAs) && (n0>=0);i++) if (BM->bmApply[i]) { for (j=0;(jbmApply[i]->nMatrices) && (n0>=0);j++) for (k=0;(kbmApply[i]->nChains) && (n0>=0);k++) { n0 = -1; for (n=0;(nGetChainID(),BM->bmApply[i]->chain[k])) n0 = n; if (n0>=0) { chain = new Chain(); chain->Copy ( ch[n0] ); chain->ApplyTransform ( BM->bmApply[i]->tm[j] ); model->AddChain ( chain ); } } } if (n0>=0) { M = new Manager(); M->AddModel ( model ); M->PDBCleanup ( PDBCLEAN_SERIAL | PDBCLEAN_INDEX ); } else { delete model; M = NULL; } return M; } // ------------------- Stream functions ---------------------- void Manager::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); BondManager::write ( f ); } void Manager::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); BondManager::read ( f ); } MakeStreamFunctions(Manager) } // namespace mmdb mmdb2-2.0.5/mmdb2/mmdb_io_file.cpp0000664000175000017500000014162512601171753013570 00000000000000// $Id: file_.cpp,v 1.29 2012/01/26 17:52:19 ekr Exp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2008. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 29.01.10 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : mmdb_io_file // ~~~~~~~~~ // **** Classes : mmdb::io::File - file I/O Support. // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include #include #ifdef _WIN32 # include # define sleep Sleep #else # ifndef __UNISTD_H # include # endif #endif #include "mmdb_io_file.h" // _WIN32_NEWLINE should be raised when compilinig on Windows in // order to enforce Windows' line endings when writing text in // files opened for *binary* output. Otherwise, writing text lines // in binary files will results in UNIX line endings. Line endings // in files, opened for output in text mode, will be always // platform-specific. #ifdef _WIN32_NEWLINE // for DOS/WINDOWS machines: #define NEWLINE "\r\n" #else // for UNIX machines: #define NEWLINE "\n" #endif namespace mmdb { namespace io { #ifdef _WIN32 const char _dir_sep_c = '\\'; cpstr _dir_sep = "\\"; #else const char _dir_sep_c = '/'; cpstr _dir_sep = "/"; #endif // =================== Auxilary Functions ========================= cpstr GetFPath ( pstr FilePath, SYSKEY syskey ) { pstr P; if (syskey==syskey_unix) P = strrchr(FilePath,'/'); else if (syskey==syskey_win) P = strrchr(FilePath,'\\'); else if (syskey==syskey_all) { P = strrchr(FilePath,'/'); if (!P) P = strrchr(FilePath,'\\'); } else P = NULL; if (P) { P = P + 1; *P = char(0); } else FilePath[0] = char(0); return FilePath; } cpstr GetFName ( cpstr FilePath, SYSKEY syskey ) { pstr P; if (syskey==syskey_unix) P = strrchr(FilePath,'/'); else if (syskey==syskey_win) P = strrchr(FilePath,'\\'); else if (syskey==syskey_all) { P = strrchr(FilePath,'/'); if (!P) P = strrchr(FilePath,'\\'); } else P = NULL; if (!P) return FilePath; else return P + 1; } cpstr GetFExt ( cpstr FilePath ) { pstr P; P = strchr ( GetFName(FilePath),'.'); if (!P) return &(FilePath[strlen(FilePath)]); else return P; } cpstr ChangeExt ( pstr FilePath, cpstr newExt, SYSKEY syskey ) { int i; i = strlen(FilePath)-1; if (syskey==syskey_unix) while ((i>0) && (FilePath[i]!='.') && (FilePath[i]!='/')) i--; else if (syskey==syskey_win) while ((i>0) && (FilePath[i]!='.') && (FilePath[i]!='\\')) i--; else if (syskey==syskey_all) while ((i>0) && (FilePath[i]!='.') && (FilePath[i]!='/') && (FilePath[i]!='\\')) i--; if (FilePath[i]=='.') { FilePath[i+1] = char(0); strcat ( FilePath,newExt ); } else { strcat ( FilePath,"." ); strcat ( FilePath,newExt ); } return FilePath; } bool FileExists ( cpstr FileName, PFile f ) { PFile g; bool B; if (FileName) { if (!f) g = new File(); else g = f; g->assign ( FileName ); B = g->exists(); if (!f) delete g; return B; } else return false; } // ======================== File Class ======================== #define ARCH_NONE 0 #define ARCH_GZIP 1 #define ARCH_COMPRESS 2 #define ARCH_ENFORCE 3 File::File ( word BufSize ) { Buf_Size = BufSize; BufLen = 0; BufInc = 1; EofFile = false; hFile = NULL; FName = NULL; BufCnt = 0; IOBuf = NULL; IOSuccess = true; TextMode = false; UniBin = false; StdIO = false; gzipIO = ARCH_NONE; memIO = false; } File::~File() { shut (); FreeBuffer(); } void File::FreeBuffer () { if (IOBuf) { if (!memIO) delete[] IOBuf; IOBuf = NULL; } if (FName) { delete[] FName; FName = NULL; } } void File::assign ( cpstr FileName, bool Text, bool UniB, GZ_MODE gzMode ) { pstr p; shut(); FreeBuffer(); CreateCopy ( FName,FileName ); StdIO = (!strcmp(FName,"stdin" )) || (!strcmp(FName,"stdout")) || (!strcmp(FName,"stderr")); if (StdIO) TextMode = true; else TextMode = Text; UniBin = UniB; gzipMode = gzMode; gzipIO = ARCH_NONE; if ((gzipMode==GZM_ENFORCE) || (gzipMode==GZM_ENFORCE_GZIP)) gzipIO = ARCH_GZIP; else if (gzipMode==GZM_ENFORCE_COMPRESS) gzipIO = ARCH_COMPRESS; else if (gzipMode==GZM_CHECK) { p = strrchr ( FName,'.' ); if (p) { if (!strcmp(p,".gz")) gzipIO = ARCH_GZIP; else if (!strcmp(p,".Z")) gzipIO = ARCH_COMPRESS; } } memIO = false; } void File::assign ( word poolSize, word sizeInc, pstr filePool ) { shut (); FreeBuffer(); IOBuf = (pstr)filePool; BufLen = poolSize; FLength = poolSize; BufInc = sizeInc; BufCnt = 0; memIO = true; gzipMode = GZM_NONE; gzipIO = ARCH_NONE; } void File::GetFilePool ( pstr & filePool, word & fileSize ) { if (memIO) { filePool = IOBuf; fileSize = FLength; IOBuf = NULL; BufLen = 0; BufCnt = 0; FLength = 0; } else { filePool = NULL; fileSize = 0; } } static pstr gzip_path = pstr("gzip "); static pstr ungzip_path = pstr("gzip -dc "); static pstr compress_path = pstr("compress "); static pstr uncompress_path = pstr("uncompress -c "); void SetGZIPPath ( pstr gzipPath, pstr ungzipPath ) { if (!gzipPath) gzip_path = pstr("gzip "); else gzip_path = gzipPath; if (!ungzipPath) ungzip_path = pstr("gzip -d "); else ungzip_path = ungzipPath; } void SetCompressPath ( pstr compressPath, pstr uncompressPath ) { if (!compressPath) compress_path = pstr("compress "); else compress_path = compressPath; if (!uncompressPath) uncompress_path = pstr("uncompress -c "); else uncompress_path = uncompressPath; } bool File::reset ( bool ReadOnly, int retry ) { #ifndef _MSC_VER pstr p; int i; #endif if (memIO) { shut(); if (!IOBuf) return false; BufCnt = 0; IOSuccess = true; } else { if (!FName) return false; shut(); BufLen = 0; BufCnt = 0; if (!strcmp(FName,"stdin")) { hFile = stdin; StdIO = true; TextMode = true; FLength = 1; EofFile = false; IOSuccess = true; } else { StdIO = false; if (gzipIO==ARCH_GZIP) { #ifndef _MSC_VER p = NULL; CreateConcat ( p,ungzip_path,FName ); for (i=0;(i<=retry) && (!hFile);i++) { if (i>0) sleep ( 1 ); hFile = popen ( p,"r" ); } if (p) delete[] p; #endif } else if (gzipIO==ARCH_COMPRESS) { #ifndef _MSC_VER p = NULL; CreateConcat ( p,uncompress_path,FName ); for (i=0;(i<=retry) && (!hFile);i++) { if (i>0) sleep ( 1 ); hFile = popen ( p,"r" ); } if (p) delete[] p; #endif } else { #ifndef _MSC_VER for (i=0;(i<=retry) && (!hFile);i++) { if (i>0) sleep ( 1 ); if (TextMode) { if (ReadOnly) hFile = fopen ( FName,"rt" ); else hFile = fopen ( FName,"r+t" ); } else { if (ReadOnly) hFile = fopen ( FName,"rb" ); else hFile = fopen ( FName,"r+b" ); } } #endif } if (hFile) { if (gzipIO==ARCH_NONE) { fseek ( hFile,0L,SEEK_END ); FLength = ftell ( hFile ); fseek ( hFile,0L,SEEK_SET ); EofFile = (FLength<=0); } else { FLength = 1; EofFile = false; } IOSuccess = true; } else { EofFile = true; IOSuccess = false; } } } return IOSuccess; } bool File::rewrite() { #ifndef _MSC_VER pstr p; #endif if (memIO) { shut(); FreeBuffer(); IOBuf = new char[BufLen]; BufCnt = 0; FLength = 0; IOSuccess = true;; } else { if (!FName) return false; shut(); BufLen = 0; BufCnt = 0; if (gzipIO==ARCH_GZIP) { #ifndef _MSC_VER p = NULL; CreateConcat ( p,gzip_path,pstr(" > "),FName ); hFile = popen ( p,"w" ); if (p) delete[] p; #else hFile = NULL; #endif StdIO = false; } else if (gzipIO==ARCH_COMPRESS) { #ifndef _MSC_VER p = NULL; CreateConcat ( p,compress_path,pstr(" > "),FName ); hFile = popen ( p,"w" ); if (p) delete[] p; #else hFile = NULL; #endif StdIO = false; } else if (!TextMode) { hFile = fopen ( FName,"w+b" ); StdIO = false; } else if (!strcmp(FName,"stdout")) { hFile = stdout; StdIO = true; } else if (!strcmp(FName,"stderr")) { hFile = stderr; StdIO = true; } else { hFile = fopen ( FName,"w+t" ); StdIO = false; } FLength = 0; IOSuccess = (hFile!=NULL); } return IOSuccess; } bool File::append() { #ifndef _MSC_VER pstr p; #endif if (memIO) { if (!IOBuf) { IOBuf = new char[BufLen]; BufCnt = 0; } FLength = BufCnt; IOSuccess = true; } else { if (!FName) return false; shut(); BufLen = 0; BufCnt = 0; if (gzipIO==ARCH_GZIP) { #ifndef _MSC_VER p = NULL; CreateConcat ( p,gzip_path,pstr(" >> "),FName ); hFile = popen ( p,"w" ); if (p) delete[] p; #else hFile = NULL; #endif StdIO = false; } else if (gzipIO==ARCH_COMPRESS) { #ifndef _MSC_VER p = NULL; CreateConcat ( p,compress_path,pstr(" >> "),FName ); hFile = popen ( p,"w" ); if (p) delete[] p; #else hFile = NULL; #endif StdIO = false; } else if (!TextMode) { hFile = fopen ( FName,"ab" ); StdIO = false; } else if (!strcmp(FName,"stdout")) { hFile = stdout; StdIO = true; } else if (!strcmp(FName,"stderr")) { hFile = stderr; StdIO = true; } else { hFile = fopen ( FName,"at" ); StdIO = false; } FLength = 0; IOSuccess = hFile!=NULL; } return IOSuccess; } bool File::erase() { if (!FName) return false; shut(); if (!StdIO) { BufLen = 0; BufCnt = 0; if (FName) IOSuccess = (remove(FName)==0); FLength = 0; } else IOSuccess = true; return IOSuccess; } bool File::exists() { if (memIO) { IOSuccess = (IOBuf!=NULL); } else { if (!FName) return false; shut(); if (!StdIO) { hFile = fopen ( FName,"r" ); IOSuccess = (hFile!=NULL); BufLen = 0; BufCnt = 0; FLength = 0; if (hFile) fclose ( hFile ); } else IOSuccess = true; hFile = NULL; } return IOSuccess; } bool File::parse ( cpstr FileName ) { UNUSED_ARGUMENT(FileName); return true; } bool File::rename ( cpstr NewFileName ) { if (!FName) return false; shut(); if (!StdIO) IOSuccess = (::rename(FName,NewFileName)==0); if (IOSuccess) assign ( NewFileName,TextMode,UniBin,gzipMode ); return IOSuccess; } long File::Position() { // do not use on text files if (memIO) return BufCnt; if (hFile==NULL) return 0L; return ftell ( hFile ); } bool File::seek ( long Position ) { // do not use on text files if (memIO) { if (Position<=(long)BufLen) { BufCnt = Position; IOSuccess = true; } else IOSuccess = false; return IOSuccess; } else if (hFile==NULL) return false; else if (!StdIO) { IOSuccess = fseek(hFile,Position,SEEK_SET)==0; return IOSuccess; } else return true; } bool File::FileEnd() { if (memIO) return ((long)BufCnt>=FLength); if (TextMode) { if (EofFile || ((!hFile) && (!StdIO))) return true; if (feof(hFile)==0) return false; return true; } return EofFile && (BufLen==0); } void File::flush () { if (hFile!=NULL) { if (!StdIO) { #ifndef _MSC_VER if (gzipIO==ARCH_NONE) fflush ( hFile ); #else fflush ( hFile ); #endif } } } void File::shut () { if (hFile!=NULL) { if (!StdIO) { #ifndef _MSC_VER if (gzipIO!=ARCH_NONE) pclose ( hFile ); else fclose ( hFile ); #else fclose ( hFile ); #endif } hFile = NULL; } } bool File::isOpen() { if (memIO) return (IOBuf!=NULL); return (hFile!=NULL); } word File::ReadLine ( pstr Line, word MaxLen ) { word LCnt; int Done; bool HSuccess = IOSuccess; if (memIO) { LCnt = 0; while (((long)BufCnt0) { if ((Line[LCnt-1]!='\n') && (Line[LCnt-1]!='\r')) break; Line[LCnt-1] = char(0); LCnt--; } } else LCnt = 0; return LCnt; } else { if (IOBuf==NULL) { IOBuf = new char[Buf_Size]; BufLen = ReadFile ( IOBuf,Buf_Size ); IOSuccess = HSuccess; BufCnt = 0; } LCnt = 0; do { while ((BufCnt=BufLen) { HSuccess = IOSuccess; BufLen = ReadFile ( IOBuf,Buf_Size ); IOSuccess = HSuccess; BufCnt = 0; } if (IOBuf[BufCnt]=='\r') Done = 1; else if (IOBuf[BufCnt]=='\n') Done = 2; else Done = 0; if (Done) BufCnt++; if (BufCnt>=BufLen) { HSuccess = IOSuccess; BufLen = ReadFile ( IOBuf,Buf_Size ); IOSuccess = HSuccess; BufCnt = 0; } if (BufLen>0) { if (((Done==2) && (IOBuf[BufCnt]=='\r')) || ((Done==1) && (IOBuf[BufCnt]=='\n'))) BufCnt++; } } while ((!Done) && (LCnt0)); Line[LCnt] = char(0); return LCnt; } } } word File::ReadNonBlankLine ( pstr S, word MaxLen ) { word i,j; do { j = ReadLine ( S,MaxLen ); i = 0; while ((i=j) && (!FileEnd())); if (i>=j) { S[0] = char(0); j = 0; } return j; } bool File::WriteLine ( cpstr Line ) { if ((!memIO) && TextMode) { if (hFile==NULL) return false; fputs ( Line,hFile ); // return (fputs(NEWLINE,hFile)>=0); return (fputs("\n",hFile)>=0); } else { if (WriteFile(Line,strlen(Line))) return WriteFile ( (void *)NEWLINE,strlen(NEWLINE) ); else return false; } } bool File::Write ( cpstr Line ) { if ((!memIO) && TextMode) { if (hFile==NULL) return false; return (fputs(Line,hFile)>=0); } else return WriteFile(Line,strlen(Line)); } bool File::Write ( realtype V, int length ) { char N[50]; sprintf ( N,"%-.*g",length,V ); if ((!memIO) && TextMode) { if (hFile==NULL) return false; return (fputs(N,hFile)>=0); } else return WriteFile(N,strlen(N)); } bool File::Write ( int iV, int length ) { char N[50]; sprintf ( N,"%*i",length,iV ); if ((!memIO) && TextMode) { if (hFile==NULL) return false; return (fputs(N,hFile)>=0); } else return WriteFile(N,strlen(N)); } bool File::LF() { if ((!memIO) && TextMode) { if (hFile==NULL) return false; // return (fputs(NEWLINE,hFile)>=0); return (fputs("\n",hFile)>=0); } else return WriteFile ( (void *)NEWLINE,strlen(NEWLINE) ); } bool File::WriteDataLine ( realtype X, realtype Y, int length ) { Write ( pstr(" ") ); Write ( X,length ); Write ( pstr(" ") ); Write ( Y,length ); return LF(); } bool File::WriteParameter ( cpstr S, realtype X, int ParColumn, int length ) { int l=strlen(S); if ((!memIO) && TextMode) { fputs ( S,hFile ); while (lParColumn) { // X = atof ( &(S[ParColumn]) ); X = GetNumber ( &(S[ParColumn]) ); return true; } else { X = 0.0; return false; } } bool File::ReadParameters ( pstr S, int & n_X, rvector X, int MaxLen, int ParColumn ) { pstr S1,S2; ReadLine ( S,MaxLen ); if ((int)strlen(S)>ParColumn) { n_X = 0; S2 = &(S[ParColumn]); S1 = S2; while (*S1!=char(0)) { if (*S1==',') *S1 = ' '; S1++; } while (*S2!=char(0)) { S1 = S2; X[n_X] = strtod ( S1,&S2 ); n_X++; while ((*S2!=char(0)) && (*S2==' ')) S2++; } return true; } else { n_X = 0; X[0] = 0.0; return false; } } bool File::ReadParameter ( pstr S, int & X, int ParColumn ) { realtype V; if (ReadParameter(S,V,ParColumn)) { X = mround(V); return true; } else { X = 0; return false; } } bool File::CreateWrite ( cpstr Line ) { wordUniBin wUB; word i; if (UniBin) { if (Line) { i = strlen(Line)+1; word2UniBin ( i,wUB ); if (WriteFile(wUB,sizeof(wordUniBin))) return WriteFile ( Line,i ); else return false; } else { i = 0; word2UniBin ( i,wUB ); return WriteFile ( wUB,sizeof(wordUniBin) ); } } else { if (Line) { i = strlen(Line)+1; if (WriteFile(&i,sizeof(i))) return WriteFile ( Line,i ); else return false; } else { i = 0; return WriteFile ( &i,sizeof(i) ); } } } #define _max_dyn_string_len 1073741824 word File::CreateRead ( pstr & Line ) { wordUniBin wUB; word i; //unsigned short int i; if (Line) { delete[] Line; Line = NULL; } if (UniBin) { ReadFile ( wUB,sizeof(wordUniBin) ); UniBin2word ( wUB,i ); } else ReadFile ( &i,sizeof(i) ); if ((i>0) && (i<_max_dyn_string_len)) { Line = new char[i]; ReadFile ( Line,i ); } return i; } bool File::WriteTerLine ( cpstr Line, bool longLine ) { wordUniBin wUB; word ll; byte sl; bool B; if (Line) ll = strlen(Line); else ll = 0; if (!longLine) { sl = byte(ll); B = WriteFile ( &sl,sizeof(sl) ); } else if (UniBin) { word2UniBin ( ll,wUB ); B = WriteFile ( wUB,sizeof(wordUniBin) ); } else B = WriteFile ( &ll,sizeof(ll) ); if (B && (ll>0)) B = WriteFile ( Line,ll ); return B; } word File::ReadTerLine ( pstr Line, bool longLine ) { wordUniBin wUB; word ll; byte sl; if (!longLine) { ReadFile ( &sl,sizeof(sl) ); ll = sl; } else if (UniBin) { ReadFile ( wUB,sizeof(wordUniBin) ); UniBin2word ( wUB,ll ); } else ReadFile ( &ll,sizeof(ll) ); if (ll>0) ReadFile ( Line,ll ); Line[ll] = char(0); return ll+1; } word File::ReadFile ( void * Buffer, word Count ) { word Cnt; if (memIO) { Cnt = WMin(Count,FLength-BufCnt); if (Cnt>0) { memcpy ( Buffer,&(IOBuf[BufCnt]),Cnt ); BufCnt += Cnt; } IOSuccess = (Cnt==Count); EofFile = ((Cnt=FLength)); return Cnt; } else if (hFile) { Cnt = (word)fread ( Buffer,1,Count,hFile ); EofFile = (CntBufLen) { Cnt += BufInc; IOB = new char[Cnt]; if (IOBuf) { memcpy ( IOB,IOBuf,BufCnt ); delete[] IOBuf; } IOBuf = IOB; BufLen = Cnt; } memcpy ( &(IOBuf[BufCnt]),Buffer,Count ); BufCnt += Count; FLength = BufCnt; IOSuccess = true; } else { if (hFile==NULL) return false; Cnt = (word)fwrite ( Buffer,1,Count,hFile ); Pos = Position(); if (Pos>FLength) FLength = Pos; IOSuccess = Cnt==Count; } return IOSuccess; } bool File::WriteReal ( realtype * V ) { realUniBin rUB; if (UniBin) { real2UniBin ( *V,rUB ); return WriteFile ( rUB,sizeof(realUniBin) ); } else return WriteFile ( V,sizeof(realtype) ); } bool File::WriteFloat ( realtype * V ) { floatUniBin fUB; float fV; if (UniBin) { float2UniBin ( *V,fUB ); return WriteFile ( fUB,sizeof(floatUniBin) ); } else { fV = (float)*V; return WriteFile ( &fV,sizeof(float) ); } } bool File::WriteInt ( int * I ) { intUniBin iUB; if (UniBin) { int2UniBin ( *I,iUB ); return WriteFile ( iUB,sizeof(intUniBin) ); } else return WriteFile ( I,sizeof(int) ); } bool File::WriteShort ( short * S ) { shortUniBin sUB; if (UniBin) { short2UniBin ( *S,sUB ); return WriteFile ( sUB,sizeof(shortUniBin) ); } else return WriteFile ( S,sizeof(short) ); } bool File::WriteLong ( long * L ) { longUniBin lUB; if (UniBin) { long2UniBin ( *L,lUB ); return WriteFile ( lUB,sizeof(longUniBin) ); } else return WriteFile ( L,sizeof(long) ); } bool File::WriteBool ( bool * B ) { intUniBin iUB; int k; if (UniBin) { if (*B) k = 1; else k = 0; int2UniBin ( k,iUB ); return WriteFile ( iUB,sizeof(intUniBin) ); } else return WriteFile ( B,sizeof(bool) ); } bool File::WriteByte ( byte * B ) { return WriteFile ( B,sizeof(byte) ); } bool File::WriteWord ( word * W ) { wordUniBin wUB; if (UniBin) { word2UniBin ( *W,wUB ); return WriteFile ( wUB,sizeof(wordUniBin) ); } else return WriteFile ( W,sizeof(word) ); } bool File::ReadReal ( realtype * V ) { realUniBin rUB; if (UniBin) { if (ReadFile(rUB,sizeof(realUniBin))==sizeof(realUniBin)) { UniBin2real ( rUB,*V ); return true; } else return false; } else return ( ReadFile(V,sizeof(realtype))==sizeof(realtype) ); } bool File::ReadFloat ( realtype * V ) { floatUniBin fUB; float fV; if (UniBin) { if (ReadFile(fUB,sizeof(floatUniBin))==sizeof(floatUniBin)) { UniBin2float ( fUB,*V ); return true; } } else if (ReadFile(&fV,sizeof(float))==sizeof(float)) { *V = fV; return true; } return false; } bool File::ReadInt ( int * I ) { intUniBin iUB; if (UniBin) { if (ReadFile(iUB,sizeof(intUniBin))==sizeof(intUniBin)) { UniBin2int ( iUB,*I ); return true; } else return false; } else return ( ReadFile(I,sizeof(int))==sizeof(int) ); } bool File::ReadShort ( short * S ) { shortUniBin sUB; if (UniBin) { if (ReadFile(sUB,sizeof(shortUniBin))==sizeof(shortUniBin)) { UniBin2short ( sUB,*S ); return true; } else return false; } else return ( ReadFile(S,sizeof(short))==sizeof(short) ); } bool File::ReadLong ( long * L ) { longUniBin lUB; if (UniBin) { if (ReadFile(lUB,sizeof(longUniBin))==sizeof(longUniBin)) { UniBin2long ( lUB,*L ); return true; } else return false; } else return ( ReadFile(L,sizeof(long))==sizeof(long) ); } bool File::ReadBool ( bool * B ) { intUniBin iUB; int k; if (UniBin) { if (ReadFile(iUB,sizeof(intUniBin))==sizeof(intUniBin)) { UniBin2int ( iUB,k ); *B = (k!=0); return true; } else return false; } else return ( ReadFile(B,sizeof(bool))==sizeof(bool) ); } bool File::ReadByte ( byte * B ) { return ( ReadFile(B,sizeof(byte))==sizeof(byte) ); } bool File::ReadWord ( word * W ) { wordUniBin wUB; if (UniBin) { if (ReadFile(wUB,sizeof(wordUniBin))==sizeof(wordUniBin)) { UniBin2word ( wUB,*W ); return true; } else return false; } else return ( ReadFile(W,sizeof(word))==sizeof(word) ); } bool File::AddReal ( realtype * V ) { realtype x; if (ReadReal(&x)) { *V += x; return true; } return false; } bool File::AddFloat ( realtype * V ) { realtype x; if (ReadFloat(&x)) { *V += x; return true; } return false; } bool File::AddInt ( int * I ) { int k; if (ReadInt(&k)) { *I += k; return true; } return false; } bool File::AddShort ( short * S ) { short k; if (ReadShort(&k)) { *S += k; return true; } return false; } bool File::AddLong ( long * L ) { long k; if (ReadLong(&k)) { *L += k; return true; } return false; } bool File::AddByte ( byte * B ) { byte k; if (ReadByte(&k)) { *B += k; return true; } return false; } bool File::AddWord ( word * W ) { word k; if (ReadWord(&k)) { *W += k; return true; } return false; } bool File::WriteVector ( rvector V, int len, int Shift ) { intUniBin iUB; realUniBin rUB; int i; int l = len; if (V==NULL) l = 0; if (UniBin) { int2UniBin ( l,iUB ); WriteFile ( iUB,sizeof(intUniBin) ); for (i=0;i0) WriteFile ( &(V[Shift]),sizeof(realtype)*l ); } return IOSuccess; } bool File::WriteVector ( ivector iV, int len, int Shift ) { intUniBin iUB; int i; int l = len; if (iV==NULL) l = 0; if (UniBin) { int2UniBin ( l,iUB ); WriteFile ( iUB,sizeof(intUniBin) ); for (i=0;i0) WriteFile ( &(iV[Shift]),sizeof(int)*l ); } return IOSuccess; } bool File::WriteVector ( lvector lV, int len, int Shift ) { intUniBin iUB; longUniBin lUB; int i; int l = len; if (lV==NULL) l = 0; if (UniBin) { int2UniBin ( l,iUB ); WriteFile ( iUB,sizeof(intUniBin) ); for (i=0;i0) WriteFile ( &(lV[Shift]),sizeof(long)*l ); } return IOSuccess; } bool File::WriteVector ( bvector B, int len, int Shift ) { intUniBin iUB; int l = len; if (B==NULL) l = 0; if (UniBin) { int2UniBin ( l,iUB ); WriteFile ( iUB,sizeof(intUniBin) ); } else WriteFile ( &l,sizeof(l) ); if (l>0) WriteFile ( &(B[Shift]),sizeof(byte)*l ); return IOSuccess; } bool File::ReadVector ( rvector V, int maxlen, int Shift ) { intUniBin iUB; realUniBin rUB; int i,l,ll; realtype B; if (UniBin) { ReadFile ( iUB,sizeof(intUniBin) ); UniBin2int ( iUB,l ); if (IOSuccess && (l>0)) { ll = IMin(l,maxlen); if (V) for (i=0;i<=ll;i++) { ReadFile ( rUB,sizeof(realUniBin) ); UniBin2real ( rUB,V[Shift+i] ); } for (i=ll+1;i<=l;i++) ReadFile ( rUB,sizeof(realUniBin) ); } } else { ReadFile ( &l,sizeof(l) ); if (IOSuccess && (l>0)) { ll = IMin(l,maxlen); if (V) ReadFile ( &(V[Shift]),sizeof(realtype)*ll ); for (i=ll+1;i<=l;i++) ReadFile ( &B,sizeof(B) ); } } return IOSuccess; } bool File::ReadVector ( ivector iV, int maxlen, int Shift ) { intUniBin iUB; int i,l,ll,iB; if (UniBin) { ReadFile ( iUB,sizeof(intUniBin) ); UniBin2int ( iUB,l ); if (IOSuccess && (l>0)) { ll = IMin(l,maxlen); if (iV) for (i=0;i<=ll;i++) { ReadFile ( iUB,sizeof(intUniBin) ); UniBin2int ( iUB,iV[Shift+i] ); } for (i=ll+1;i<=l;i++) ReadFile ( iUB,sizeof(intUniBin) ); } } else { ReadFile ( &l,sizeof(l) ); if (IOSuccess && (l>0)) { ll = IMin(l,maxlen); if (iV) ReadFile ( &(iV[Shift]),sizeof(int)*ll ); for (i=ll+1;i<=l;i++) ReadFile ( &iB,sizeof(iB) ); } } return IOSuccess; } bool File::ReadVector ( lvector lV, int maxlen, int Shift ) { intUniBin iUB; longUniBin lUB; int i,l,ll; long lB; if (UniBin) { ReadFile ( iUB,sizeof(intUniBin) ); UniBin2int ( iUB,l ); if (IOSuccess && (l>0)) { ll = IMin(l,maxlen); if (lV) for (i=0;i<=ll;i++) { ReadFile ( lUB,sizeof(longUniBin) ); UniBin2long ( lUB,lV[Shift+i] ); } for (i=ll+1;i<=l;i++) ReadFile ( lUB,sizeof(longUniBin) ); } } else { ReadFile ( &l,sizeof(l) ); if (IOSuccess && (l>0)) { ll = IMin(l,maxlen); if (lV) ReadFile ( &(lV[Shift]),sizeof(long)*ll ); for (i=ll+1;i<=l;i++) ReadFile ( &lB,sizeof(lB) ); } } return IOSuccess; } bool File::ReadVector ( bvector B, int maxlen, int Shift ) { intUniBin iUB; int i,l,ll; byte t; if (UniBin) { ReadFile ( iUB,sizeof(intUniBin) ); UniBin2int ( iUB,l ); } else ReadFile ( &l,sizeof(l) ); if (IOSuccess && (l>0)) { ll = IMin(l,maxlen); if (B) ReadFile ( &(B[Shift]),sizeof(byte)*ll ); for (i=ll+1;i<=l;i++) ReadFile ( &t,sizeof(t) ); } return IOSuccess; } bool File::CreateReadVector ( rvector & V, int & len, int Shift ) { intUniBin iUB; realUniBin rUB; int i; realtype B; FreeVectorMemory ( V,Shift ); if (UniBin) { ReadFile ( iUB,sizeof(intUniBin) ); UniBin2int ( iUB,len ); if (IOSuccess && (len>0)) { GetVectorMemory ( V,len,Shift ); if (V) for (i=0;i0)) { GetVectorMemory ( V,len,Shift ); if (V) ReadFile ( &(V[Shift]),sizeof(realtype)*len ); else for (i=0;i0)) { GetVectorMemory ( iV,len,Shift ); if (iV) for (i=0;i0)) { GetVectorMemory ( iV,len,Shift ); if (iV) ReadFile ( &(iV[Shift]),sizeof(int)*len ); else for (i=0;i0)) { GetVectorMemory ( lV,len,Shift ); if (lV) for (i=0;i0)) { GetVectorMemory ( lV,len,Shift ); if (lV) ReadFile ( &(lV[Shift]),sizeof(long)*len ); else for (i=0;i0)) { GetVectorMemory ( B,len,Shift ); if (B) ReadFile ( &(B[Shift]),sizeof(byte)*len ); else for (i=0;i0)) { ReadFile ( iUB,sizeof(intUniBin) ); UniBin2int ( iUB,M ); if (IOSuccess && (M>0)) { GetMatrixMemory ( A,N,M,ShiftN,ShiftM ); for (i=0;i0) { ReadFile ( &M,sizeof(M) ); if (M>0) { GetMatrixMemory ( A,N,M,ShiftN,ShiftM ); for (i=0;i=j) DataLen--; if (DataLen>0) { Ok = GetVectorMemory(X,DataLen,Shift); if (Ok && (yCol>=0)) Ok = Ok && GetVectorMemory(Y,DataLen,Shift); if (Ok && (zCol>=0)) Ok = Ok && GetVectorMemory(Z,DataLen,Shift); if (Ok) { reset(); _ReadColumns ( DataLen,S,sizeof(S),X,Y,Z,xCol,yCol, zCol,Shift ); } else ErrCode = FileError_NoMemory; } else ErrCode = FileError_NoDataFound; } else ErrCode = FileError_NoDataFound; return DataLen; } int File::CreateReadColumns ( rvector & X, rvector & Y, int xCol, int yCol, int Shift ) { return CreateReadColumns ( X,Y,X,xCol,yCol,-1,Shift ); } void File::_ReadColumns ( int & DLen, pstr S, int SLen, rvector X, rvector Y, rvector Z, int xCol, int yCol, int zCol, int Shift ) { int i,is,j,k,m,n,cmax; char SV[256]; realtype Res; ErrCode = 0; i = 0; cmax = IMax(zCol,IMax(xCol,yCol)); while ((i=k)) { DLen = i; return; } m++; } while ((m!=xCol) && (m!=yCol) && (m!=zCol)); if (SV[0]==char(0)) { if (n>0) ErrCode = FileError_NoColumn; else ErrCode = FileError_ShortData; } else { Res = GetNumber ( SV ); if (ErrCode==0) { is = i+Shift; if (m==xCol) X[is] = Res; else if (m==yCol) Y[is] = Res; else Z[is] = Res; n++; } } } if ((ErrCode==0) && (n<2)) ErrCode = FileError_NoColumn; i++; } if ((ErrCode==FileError_ShortData) && (i>1)) { ErrCode = 0; DLen = i-1; } if (ErrCode!=0) ErrCode = FileError_BadData; } void RemoveDelimiters ( pstr S, int SLen ) { int j; for (j=0;j // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::CrystContainer ( container for cryst. data ) // ~~~~~~~~~ mmdb::NCSMatrix ( non-cryst. symm. matrix class ) // mmdb::TVect ( translation vector class ) // mmdb::Cryst ( MMDB cryst. section class ) // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_Cryst__ #define __MMDB_Cryst__ #include "mmdb_io_stream.h" #include "mmdb_symop.h" #include "mmdb_defs.h" #include "mmdb_utils.h" namespace mmdb { // ==================== CrystContainer ====================== DefineClass(CrystContainer); DefineStreamFunctions(CrystContainer); class CrystContainer : public ClassContainer { public : CrystContainer () : ClassContainer() {} CrystContainer ( io::RPStream Object ) : ClassContainer ( Object ) {} ~CrystContainer() {} PContainerClass MakeContainerClass ( int ClassID ); ERROR_CODE AddMTRIXLine ( cpstr S ); }; // ================== NCSMatrix ======================== enum NCSM_SET { NCSMSET_Matrix1 = 0x00000001, NCSMSET_Matrix2 = 0x00000002, NCSMSET_Matrix3 = 0x00000004, NCSMSET_All = 0x00000007 }; DefineClass(NCSMatrix); DefineStreamFunctions(NCSMatrix); class NCSMatrix : public ContainerClass { friend class Cryst; public : int serNum; // serial number mat33 m; // non-crystallographic symmetry matrix vect3 v; // translational part of ncs matrix int iGiven; // iGiven flag (see PDB format) NCSMatrix (); NCSMatrix ( cpstr S ); NCSMatrix ( io::RPStream Object ); ~NCSMatrix(); bool PDBASCIIDump1 ( io::RFile f ); ERROR_CODE ConvertPDBASCII ( cpstr S ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_NCSMatrix; } void SetNCSMatrix ( int serialNum, mat33 & ncs_m, vect3 & ncs_v, int i_Given ); void Copy ( PContainerClass NCSMatrix ); void write ( io::RFile f ); void read ( io::RFile f ); protected : word WhatIsSet; // mask field // 0x0001 MTRIX1 was converted // 0x0002 MTRIX2 was converted // 0x0004 MTRIX3 was converted void Init(); }; // ================== TVect ======================== DefineClass(TVect); DefineStreamFunctions(TVect); class TVect : public ContainerClass { public : int serNum; // serial number vect3 t; // translation vector pstr comment; // comment TVect (); TVect ( cpstr S ); TVect ( io::RPStream Object ); ~TVect(); void PDBASCIIDump ( pstr S, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_TVect; } void Copy ( PContainerClass TVect ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void Init(); }; // ================= Cryst ======================= DefineClass(Cryst); DefineStreamFunctions(Cryst); // constants for the CellCheck field enum CELL_CHECK { CCHK_Ok = 0x00000000, CCHK_NoCell = 0x00000001, CCHK_Error = 0x00000002, CCHK_Disagreement = 0x00000004, CCHK_NoOrthCode = 0x00000008, CCHK_Translations = 0x00000010, CCHK_Unchecked = 0x00001000 }; // constants for the WhatIsSet field enum CELL_SET { CSET_CellParams1 = 0x00000001, CSET_CellParams2 = 0x00000002, CSET_CellParams = 0x00000003, CSET_SpaceGroup = 0x00000004, CSET_ZValue = 0x00000008, CSET_CrystCard = 0x0000000F, CSET_OrigMatrix1 = 0x00000010, CSET_OrigMatrix2 = 0x00000020, CSET_OrigMatrix3 = 0x00000040, CSET_OrigMatrix = 0x00000070, CSET_ScaleMatrix1 = 0x00000080, CSET_ScaleMatrix2 = 0x00000100, CSET_ScaleMatrix3 = 0x00000200, CSET_ScaleMatrix = 0x00000380, CSET_Transforms = 0x00000400, CSET_DummyCell = 0x00001000 }; extern cpstr OrthCode[6]; class Cryst : public io::Stream { friend class Channel; public : realtype a,b,c; // cell parameters realtype alpha,beta,gamma; // cell parameters mat44 RO,RF; // orthogonal-fractional recalculation // matrices mat44 ROU,RFU; // ort-frac recalc matrices for // anisotr. t-fac mat633 RR; // standard orthogonalizations realtype Vol; // cell volume int NCode; // code of orthogonalization matrix SymGroup spaceGroup; // group of space symmetry as read // from file SymGroup spaceGroupFix; // actually used space group int Z; // Z-value mat33 o; // orthogonal transformation matrix vect3 t; // translation orthogonal vector mat33 s; // scale matrix vect3 u; // translation part of the scale matrix word CellCheck; // 0x0000 - Ok // 0x0001 - no cell stored // 0x0002 - some error in cell volume // 0x0004 - disagreement between // cell and PDB // 0x0008 - no orth code derived // 0x0010 - translations also specified // 0x1000 - the check was not done word WhatIsSet; // indicator of the fields set bool ignoreScalei; // flag to ignore SCALEi cards bool processSG; // flag to process space group at file // read bool fixSpaceGroup; // flag to fix space group at file read Cryst (); Cryst ( io::RPStream Object ); ~Cryst(); void FreeMemory(); void Reset (); // ConvertPDBString(..) interprets an ASCII PDB line and fills // the corresponding data fields. It returns zero if the line was // successfully converted, otherwise returns a non-negative value // of Error_XXXX. // PDBString must be not shorter than 81 characters. ERROR_CODE ConvertPDBString ( pstr PDBString ); // RWBROOKReadPrintout() may be invoked after reading PDB file // for simulating the old RWBROOK messages and warnings void RWBROOKReadPrintout(); void SetCell ( realtype cell_a, realtype cell_b, realtype cell_c, realtype cell_alpha, realtype cell_beta, realtype cell_gamma, int OrthCode ); void PutCell ( realtype cell_a, realtype cell_b, realtype cell_c, realtype cell_alpha, realtype cell_beta, realtype cell_gamma, int OrthCode ); void GetCell ( realtype & cell_a, realtype & cell_b, realtype & cell_c, realtype & cell_alpha, realtype & cell_beta, realtype & cell_gamma, realtype & vol ); void GetRCell ( realtype & cell_as, realtype & cell_bs, realtype & cell_cs, realtype & cell_alphas, realtype & cell_betas, realtype & cell_gammas, realtype & vols ); void SetSyminfoLib ( cpstr syminfoLib ); pstr GetSyminfoLib (); int SetSpaceGroup ( cpstr spGroup ); pstr GetSpaceGroup (); pstr GetSpaceGroupFix(); // CalcCoordTransforms() should be called once after all data // relevant to the crystallographic information, are read and // converted. Field CellCheck will then have bits set if there // are errors, e.g. bit CCHK_NoCell means that the coordinate // transformations cannot be performed. void CalcCoordTransforms(); // A PDB ASCII dump void PDBASCIIDump ( io::RFile f ); ERROR_CODE GetCIF ( mmcif::PData CIF ); void MakeCIF ( mmcif::PData CIF ); bool areMatrices(); // returns True if the orthogonal-to- // fractional and fractional-to-orthogonal // matrices are defined // Frac2Orth(..) and Orth2Frac(..) transform between fractional // and orthogonal coordinates, if areMatrices() returns True. // If the transformation matrices were not set, the functions just // copy the coordinates. Returns True if the transformation was // done; False return means that transformation matrices were not // calculated bool Frac2Orth ( realtype x, realtype y, realtype z, realtype & xx, realtype & yy, realtype & zz ); bool Orth2Frac ( realtype x, realtype y, realtype z, realtype & xx, realtype & yy, realtype & zz ); // Below, F and T are transformation matrices in fractional and // orthogonal coordinates, respectively. bool Frac2Orth ( mat44 & F, mat44 & T ); bool Orth2Frac ( mat44 & T, mat44 & F ); // Cryst2Orth(..) and Orth2Cryst(..) transform between fractional // and orthogonal anisotropic temperature factors, if areMatrices() // returns True. If the transformation matrices were not set, the // functions leave the factors unchanged. // Vector U is composed as follows: // U[0]=u11 U[1]=u22 U[2]=u33 // U[3]=u12 U[4]=u13 U[5]=u23 // Returns True if the transformation was done; False retuen // means that transformation matrices were not calculated bool Cryst2Orth ( rvector U ); bool Orth2Cryst ( rvector U ); void CalcOrthMatrices(); // calculates RR, AC, cella's and Vol bool isNCSMatrix (); bool isScaleMatrix (); bool isCellParameters(); int GetNumberOfSymOps(); pstr GetSymOp ( int Nop ); int GetNumberOfNCSMatrices(); int GetNumberOfNCSMates (); // Returns the number of // NCS mates not given in // the file (iGiven==0) bool GetNCSMatrix ( int NCSMatrixNo, mat33 & ncs_m, vect3 & ncs_v ); bool GetNCSMatrix ( int NCSMatrixNo, mat44 & ncs_m, int & iGiven ); // no=0..N-1 int AddNCSMatrix ( mat33 & ncs_m, vect3 & ncs_v, int iGiven ); // GetTMatrix(..) calculates and returns the coordinate // transformation matrix, which converts orthogonal coordinates // according to the symmetry operation number Nop and places // them into unit cell shifted by cellshift_a a's, cellshift_b // b's and cellshift_c c's. // // Return 0 means everything's fine, // 1 there's no symmetry operation Nop defined // 2 fractionalizing/orthogonalizing matrices were not // calculated // 3 cell parameters were not set up. int GetTMatrix ( mat44 & TMatrix, int Nop, int cellshift_a, int cellshift_b, int cellshift_c, PSymOps symOpers=NULL ); // GetUCTMatrix(..) calculates and returns the coordinate // transformation matrix, which converts orthogonal coordinates // according to the symmetry operation Nop. Translation part // of the matrix is being chosen such that point (x,y,z) has // least distance to the center of primary (333) unit cell, // and then it is shifted by cellshift_a a's, cellshift_b b's // and cellshift_c c's. // // Return 0 means everything's fine, // 1 there's no symmetry operation Nop defined // 2 fractionalizing/orthogonalizing matrices were not // calculated // 3 cell parameters were not set up. // int GetUCTMatrix ( mat44 & TMatrix, int Nop, realtype x, realtype y, realtype z, int cellshift_a, int cellshift_b, int cellshift_c, PSymOps symOpers=NULL ); // GetFractMatrix(..) calculates and returns the coordinate // transformation matrix, which converts fractional coordinates // according to the symmetry operation number Nop and places them // into unit cell shifted by cellshift_a a's, cellshift_b b's and // cellshift_c c's. // // Return 0 means everything's fine, // 1 there's no symmetry operation Nop defined // 2 fractionalizing/orthogonalizing matrices were not // calculated // 3 cell parameters were not set up. int GetFractMatrix ( mat44 & TMatrix, int Nop, int cellshift_a, int cellshift_b, int cellshift_c, PSymOps symOpers=NULL ); // GetSymOpMatrix(..) returns the transformation matrix for // Nop-th symmetry operator in the space group // // Return 0 means everything's fine, // 1 there's no symmetry operation Nop defined // 2 fractionalizing/orthogonalizing matrices were not // calculated // 3 cell parameters were not set up. // int GetSymOpMatrix ( mat44 & TMatrix, int Nop ); void Copy ( PCryst Cryst ); void write ( io::RFile f ); // writes header to PDB binary file void read ( io::RFile f ); // reads header from PDB binary file protected : CrystContainer ncsMatrix; // non-cryst. symm. matrices CrystContainer tVect; // translation vectors realtype as,bs,cs; // calculated 'cell parameters' realtype alphas,betas,gammas; // calculated 'cell parameters' realtype AC[6]; realtype VolChk,VolErr; pstr syminfo_lib; // path to syminfo.lib SymOps symOps; // symmetry operations void Init ( bool fullInit ); int FixSpaceGroup(); }; extern cpstr getOrthCodeName ( int NCode ); } // namespace mmdb /* extern void TestCryst(); // reads from 'in.cryst', writes into // 'out.cryst' and 'abin.cryst' */ #endif mmdb2-2.0.5/mmdb2/mmdb_mattype.cpp0000664000175000017500000014615512401105774013646 00000000000000// $Id: mmdb_mattype.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2008. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 10.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MatType_ // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include #include #include #include #include "mmdb_mattype.h" namespace mmdb { // ------------------------------------------------------- realtype MachEps; realtype floatMachEps; realtype LnMaxReal; realtype LnMinReal; static realtype LnMaxRealExp; static realtype LnMinRealExp; // Initialization. Some C++ enviroments do not do the // following statements automatically, therefore it is // always advisable to call InitMatType() explicitely // from the top of main(). See body of InitMatType() // in the very end of this file. It is completely // harmless and cheap to call InitMatType() multiple // times. static bool MatTypeInit = InitMatType(); // ------------------------------------------------------- #ifdef _WIN32 pstr strcasestr ( pstr s1, cpstr s2 ) { pstr l1,l2,l; l1 = NULL; l2 = NULL; CreateCopy ( l1,s1 ); CreateCopy ( l2,s2 ); LowerCase ( l1 ); LowerCase ( l2 ); l = strstr ( l1,l2 ); if (l) l = s1 + (l-l1); delete[] l1; delete[] l2; return l; } #endif // ------------------------------------------------------- bool GetVectorMemory ( rvector & V, word N, word Shift ) { V = new realtype[N]; if (V!=NULL) V = V - Shift; // shift for abovementioned enumeration return (V!=NULL); } bool GetVectorMemory ( ivector & I, word N, word Shift ) { I = new int[N]; if (I!=NULL) I = I - Shift; // shift for abovementioned enumeration return (I!=NULL); } bool GetVectorMemory ( wvector & W, word N, word Shift ) { W = new word[N]; if (W!=NULL) W = W - Shift; // shift for abovementioned enumeration return (W!=NULL); } bool GetVectorMemory ( bvector & B, word N, word Shift ) { B = new byte[N]; if (B!=NULL) B = B - Shift; // shift for abovementioned enumeration return (B!=NULL); } bool GetVectorMemory ( ovector & O, word N, word Shift ) { O = new bool[N]; if (O!=NULL) O = O - Shift; // shift for abovementioned enumeration return (O!=NULL); } bool GetVectorMemory ( lvector & L, word N, word Shift ) { L = new long[N]; if (L!=NULL) L = L - Shift; // shift for abovementioned enumeration return (L!=NULL); } bool GetVectorMemory ( lwvector & L, word N, word Shift ) { L = new lword[N]; if (L!=NULL) L = L - Shift; // shift for abovementioned enumeration return (L!=NULL); } bool GetVectorMemory ( psvector & P, word N, word Shift ) { P = new pstr[N]; if (P!=NULL) P = P - Shift; // shift for abovementioned enumeration return (P!=NULL); } void FreeVectorMemory ( rvector & V, word Shift ) { if (V!=NULL) { V = V + Shift; // back shift for the work of heap system delete[] V; V = NULL; } } void FreeVectorMemory ( ivector & I, word Shift ) { if (I!=NULL) { I = I + Shift; // back shift for the work of heap system delete[] I; I = NULL; } } void FreeVectorMemory ( wvector & W, word Shift ) { if (W!=NULL) { W = W + Shift; // back shift for the work of heap system delete[] W; W = NULL; } } void FreeVectorMemory ( bvector & B, word Shift ) { if (B!=NULL) { B = B + Shift; // back shift for the work of heap system delete[] B; B = NULL; } } void FreeVectorMemory ( ovector & O, word Shift ) { if (O!=NULL) { O = O + Shift; // back shift for the work of heap system delete[] O; O = NULL; } } void FreeVectorMemory ( lvector & L, word Shift ) { if (L!=NULL) { L = L + Shift; // back shift for the work of heap system delete[] L; L = NULL; } } void FreeVectorMemory ( lwvector & L, word Shift ) { if (L!=NULL) { L = L + Shift; // back shift for the work of heap system delete[] L; L = NULL; } } void FreeVectorMemory ( psvector & P, word Shift ) { if (P!=NULL) { P = P + Shift; // back shift for the work of heap system delete[] P; P = NULL; } } bool GetMatrixMemory ( rmatrix & A, word N, word M, word ShiftN, word ShiftM ) { A = new rvector[N]; if (A!=NULL) { for (word i=0;i::epsilon(); } realtype floatMachinEps() { // A1.3.1 : Calculation of the machine's epsilon /* float fMachEps = 1.0; do fMachEps /= 2.0; while (float(1.0+fMachEps)!=1.0); return 2.0*fMachEps; */ return std::numeric_limits::epsilon(); } realtype frac ( realtype R ) { realtype i; return modf ( R,&i ); } long mod ( long x, long y ) { long k=x/y; long f=x-k*y; while (f<0) f += y; return f; } realtype Pow ( realtype X, int y ) { int m,l; realtype B; if (y==0) return 1.0; else if (X!=0.0) { B = X; m = 1; if (y>=0) l = y; else l = -y; while (m++=0) return B; else return 1.0/B; } else return 0.0; } realtype Pow1 ( realtype X, realtype Y ) { int k = mround(Y); if (fabs(k-Y)<=100.0*MachEps) return Pow(X,k); if (X==0.0) return 0.0; else return pow(X,Y); } realtype Exp ( realtype X ) { //realtype X1 = X; //realtype B = 1.0; if (X>=LnMaxRealExp) return MaxReal; else if (X<=LnMinRealExp) return 0.0; else { return exp(X); /* while (X1>LnMaxReal) { X1 -= LnMaxReal; B *= MaxExponent; } while (X1<-LnMaxReal) { X1 += LnMaxReal; B /= MaxExponent; } return B*exp(X1); */ } } bool Odd ( int i ) { return (i & 1); } // ---------------------------------------------------- long HexValL ( cpstr S ) { char C; int i; long z=0; for (i=0;S[i];i++) { z <<= 4; C = (char)toupper(S[i]); if (isdigit(C)) z += S[i]-'0'; else z += C-'A'+10; } return z; } // ---------------------------------------------------- long OctValL ( cpstr S ) { int i; long z=0; for (i=0;S[i];i++) { z <<= 3; z += S[i]-'0'; } return z; } // ---------------------------------------------------- long BinValL ( cpstr S ) { int i; long z=0; for (i=0;S[i];i++) { z <<= 1; z += S[i]-'0'; } return z; } pstr BinValS ( long L, pstr S ) { int i; long z; z = long(1) << (8*sizeof(long)-1); for (i=0;i<8*(int)sizeof(long);i++) { if (L & z) S[i] = '1'; else S[i] = '0'; z >>= 1; } S[8*sizeof(long)] = char(0); return S; } // ---------------------------------------------------- pstr ParamStr ( pstr D, cpstr S, realtype V, int M, cpstr S1 ) { char VS[30]; strcat ( D,S ); sprintf ( VS,"%-.*g",M,V ); strcat ( D,VS ); return strcat(D,S1); } pstr ParamStr ( pstr D, cpstr S, realtype V, int M, cpstr S1, realtype V2, int M2, cpstr S2 ) { char VS[30]; ParamStr ( D,S,V,M,S1 ); sprintf ( VS,"%-.*g",M2,V2 ); strcat ( D,VS ); return strcat(D,S2); } pstr CreateCopy ( pstr & Dest, cpstr Source ) { if (Dest) delete[] Dest; if (Source) { Dest = new char[strlen(Source)+1]; strcpy ( Dest,Source ); } else Dest = NULL; return Dest; } pstr CreateCopy_n ( pstr & Dest, cpstr Source, int n ) { int l; if (Dest) delete[] Dest; if (Source) { l = IMin ( strlen(Source),n ); Dest = new char[l+1]; strncpy ( Dest,Source,l ); Dest[l] = char(0); } else Dest = NULL; return Dest; } pstr CreateCopCat ( pstr & Dest, cpstr Source1, cpstr Source2, cpstr Source3, cpstr Source4, cpstr Source5 ) { if (Dest) { delete[] Dest; Dest = NULL; } return CreateConcat ( Dest,Source1,Source2,Source3,Source4,Source5 ); } pstr CreateCopCat ( pstr & Dest, cpstr Source1, cpstr Source2, cpstr Source3, cpstr Source4 ) { if (Dest) { delete[] Dest; Dest = NULL; } return CreateConcat ( Dest,Source1,Source2,Source3,Source4 ); } pstr CreateCopCat ( pstr & Dest, cpstr Source1, cpstr Source2, cpstr Source3 ) { if (Dest) { delete[] Dest; Dest = NULL; } return CreateConcat ( Dest,Source1,Source2,Source3 ); } pstr CreateCopCat ( pstr & Dest, cpstr Source1, cpstr Source2 ) { if (Dest) { delete[] Dest; Dest = NULL; } return CreateConcat ( Dest,Source1,Source2 ); } pstr CreateConcat ( pstr & Dest, cpstr Source1, cpstr Source2, cpstr Source3, cpstr Source4, cpstr Source5 ) { pstr S; int ld,ls; if (Dest) ld = strlen(Dest); else ld = 0; ls = 0; if (Source1) ls += strlen(Source1); if (Source2) ls += strlen(Source2); if (Source3) ls += strlen(Source3); if (Source4) ls += strlen(Source4); if (Source5) ls += strlen(Source5); if (ls>0) { S = new char[ls+ld+1]; if (Dest) { strcpy ( S,Dest ); delete[] Dest; } else S[0] = char(0); if (Source1) strcat ( S,Source1 ); if (Source2) strcat ( S,Source2 ); if (Source3) strcat ( S,Source3 ); if (Source4) strcat ( S,Source4 ); if (Source5) strcat ( S,Source5 ); Dest = S; } return Dest; } pstr CreateConcat ( pstr & Dest, cpstr Source1, cpstr Source2, cpstr Source3, cpstr Source4 ) { pstr S; int ld,ls; if (Dest) ld = strlen(Dest); else ld = 0; ls = 0; if (Source1) ls += strlen(Source1); if (Source2) ls += strlen(Source2); if (Source3) ls += strlen(Source3); if (Source4) ls += strlen(Source4); if (ls>0) { S = new char[ls+ld+1]; if (Dest) { strcpy ( S,Dest ); delete[] Dest; } else S[0] = char(0); if (Source1) strcat ( S,Source1 ); if (Source2) strcat ( S,Source2 ); if (Source3) strcat ( S,Source3 ); if (Source4) strcat ( S,Source4 ); Dest = S; } return Dest; } pstr CreateConcat ( pstr & Dest, cpstr Source1, cpstr Source2, cpstr Source3 ) { pstr S; int ld,ls; if (Dest) ld = strlen(Dest); else ld = 0; ls = 0; if (Source1) ls += strlen(Source1); if (Source2) ls += strlen(Source2); if (Source3) ls += strlen(Source3); if (ls>0) { S = new char[ls+ld+1]; if (Dest) { strcpy ( S,Dest ); delete[] Dest; } else S[0] = char(0); if (Source1) strcat ( S,Source1 ); if (Source2) strcat ( S,Source2 ); if (Source3) strcat ( S,Source3 ); Dest = S; } return Dest; } pstr CreateConcat ( pstr & Dest, cpstr Source1, cpstr Source2 ) { pstr S; int ld,ls; if (Dest) ld = strlen(Dest); else ld = 0; ls = 0; if (Source1) ls += strlen(Source1); if (Source2) ls += strlen(Source2); if (ls>0) { S = new char[ls+ld+1]; if (Dest) { strcpy ( S,Dest ); delete[] Dest; } else S[0] = char(0); if (Source1) strcat ( S,Source1 ); if (Source2) strcat ( S,Source2 ); Dest = S; } return Dest; } pstr CreateConcat ( pstr & Dest, cpstr Source ) { pstr S; int ld,ls; if (Dest) ld = strlen(Dest); else ld = 0; if (Source) ls = strlen(Source); else ls = 0; if (ls>0) { S = new char[ls+ld+1]; if (Dest) { strcpy ( S,Dest ); delete[] Dest; } else S[0] = char(0); strcat ( S,Source ); Dest = S; } return Dest; } pstr LastOccurence ( cpstr S, char c ) { pstr P=(pstr)S; pstr R=NULL; while (*P) { if (*P==c) R = P; P++; } return R; } pstr FirstOccurence ( cpstr S, char c ) { pstr P=(pstr)S; while (*P) { if (*P==c) return P; P++; } return NULL; } int indexOf ( cpstr S, char c ) { int i=0; while (S[i]) { if (S[i]==c) return i; i++; } return -1; } pstr FirstOccurence ( cpstr S, int Slen, cpstr Q, int Qlen ) { int i,j,k,l; l = Slen-Qlen; for (i=0;i<=l;i++) { j = 0; k = i; while (j=Qlen) return pstr(&(S[i])); } return NULL; } int indexOf ( cpstr S, int Slen, cpstr Q, int Qlen ) { int i,j,k,l; l = Slen-Qlen; for (i=0;i<=l;i++) { j = 0; k = i; while (j=Qlen) return i; } return -1; } pstr LowerCase ( pstr s ) { pstr p=s; while (*p) { *p = char(tolower(int(*p))); p++; } return s; } pstr UpperCase ( pstr s ) { pstr p=s; while (*p) { *p = char(toupper(int(*p))); p++; } return s; } void GetString ( pstr L, cpstr S, int M ) { // Copies first M characters of string S into string L, // appending the terminating null. If S contains less // then M characters, L will be padded with spaces. int i,j; i = 0; j = 0; while (S[i] && (i=SMax) || (!S[k])) { lm1 = IMin(n,lm1); while (k=SMax)) { lm1 = IMin(n,lm1); while (k=0) && (k>=0)) d[i--] = s[k--]; while (i>=0) d[i--] = ' '; } void strcpy_nr ( pstr d, cpstr s, int n ) { // Copies at most n symbols from string s to d, but // no more than strlen(s) (s must contain a terminating null). // The string in d is aligned to the right and added with // spaces at the left, if necessary. The terminating null // IS NEITHER appended NOR copied to d. int i,k; i = n-1; k = IMin(i,strlen(s)-1); while ((i>=0) && (k>=0)) d[i--] = s[k--]; while (i>=0) d[i--] = ' '; } void strcpy_ns ( pstr d, cpstr s, int n ) { // Copies at most n symbols from string s to d, but // no more than strlen(s) (s must contain a terminating // null). The terminating null IS NEITHER appended NOR // copied to d; rather, d is padded with spaces if // strlen(s)0) && (d[i]==' ')) i--; if (d[i]==' ') d[i] = char(0); else d[i+1] = char(0); return d; } pstr strcpy_ncs ( pstr d, cpstr s, int n ) { // Copies at most n characters from string s to string d // cutting all spaces at at the end. Thus, " abcde " will // be copied like " abc" at n=4 and like " abcde" at n>5 // (terminating null appended). // The function returns d. int i; i = 0; while (s[i] && (i0) && (d[i]==' ')) i--; if (d[i]==' ') d[i] = char(0); else d[i+1] = char(0); return d; } pstr strcpy_css ( pstr d, cpstr s ) { // Copies string s to string d cutting all spaces at // at the begining and at the end. Thus, " ab c de " // will be copied like "ab c de" (terminating null // appended). // The function returns d. int i,k; i = 0; while (s[i]==' ') i++; k = 0; while (s[i]) d[k++] = s[i++]; if (k>0) { k--; while ((k>0) && (d[k]==' ')) k--; if (d[k]==' ') d[k] = char(0); else d[k+1] = char(0); } else d[k] = char(0); return d; } pstr strcpy_ncss ( pstr d, cpstr s, int n ) { // Copies at most n characters from string s to string d cutting // all spaces at the begining and at the end. Thus, " ab c de " // will be copied like "ab" at n=3 (terminating null appended). // The function returns d. int i,k; i = 0; while ((s[i]==' ') && (i0) { k--; while ((k>0) && (d[k]==' ')) k--; if (d[k]==' ') d[k] = char(0); else d[k+1] = char(0); } else d[k] = char(0); return d; } pstr strcpy_n0 ( pstr d, cpstr s, int n ) { // Copies at most n symbols from string s to d, but // no more than strlen(s) (s must contain a terminating // null). The terminating null IS appended to d. // The function returns d. int i; i = 0; while ((i0)) { k--; while ((k>0) && (S[k]==' ')) k--; if (S[k]!=' ') k++; } S[k] = char(0); return S; } pstr DelSpaces ( pstr S, char c ) { // Removes all spaces (or other symbols as specified by 'c') // from the string. The string is then shrinked by the number // of removed characters. Thus, " as ttt " becomes "asttt". int i,j; j = 0; for (i=0;S[i];i++) if (S[i]!=c) { if (j>= 8; } } void short2UniBin ( short S, shortUniBin sUB ) { int j,sh; short n; sh = 8*(sizeof(shortUniBin)-1); for (j=sizeof(shortUniBin)-1;j>=0;j--) { n = (S >> sh) & 0xFF; sUB[j] = byte(n); sh -= 8; } } void long2UniBin ( long L, longUniBin lUB ) { int j,sh; long n; sh = 8*(sizeof(longUniBin)-1); for (j=sizeof(longUniBin)-1;j>=0;j--) { n = (L >> sh) & 0xFF; lUB[j] = byte(n); sh -= 8; } } void word2UniBin ( word W, wordUniBin wUB ) { int j,sh; word n; sh = 8*(sizeof(wordUniBin)-1); for (j=sizeof(wordUniBin)-1;j>=0;j--) { n = (W >> sh) & 0xFF; wUB[j] = byte(n); sh -= 8; } } void real2UniBin ( realtype R, realUniBin rUB ) { int k1,k2,k; realtype Q,L; if (R>=0) Q = R; else Q = -R; k1 = 0; k2 = _nfPowers; do { k = (k1+k2)/2; if (Q>=_fpower[k]) k1 = k; else k2 = k; } while (k2>k1+1); if (Q<=_fpower[0]) k2 = 0; Q = (Q/_fpower[k2])*_fpower8; rUB[0] = byte(k2); for (k=sizeof(realUniBin)-1;k>0;k--) { L = floor(Q/_rfbase); rUB[k] = byte(int(Q-L*_rfbase)); Q = L; } if (R<0) rUB[1] |= _fsign; } void shortreal2UniBin ( shortreal R, shortrealUniBin srUB ) { int k1,k2,k; realtype Q,L; if (R>=0) Q = R; else Q = -R; k1 = 0; k2 = _nfPowers; do { k = (k1+k2)/2; if (Q>=_fpower[k]) k1 = k; else k2 = k; } while (k2>k1+1); if (Q<=_fpower[0]) k2 = 0; Q = (Q/_fpower[k2])*_fpower4; srUB[0] = byte(k2); for (k=sizeof(shortrealUniBin)-1;k>0;k--) { L = floor(Q/_rfbase); srUB[k] = byte(int(Q-L*_rfbase)); Q = L; } if (R<0) srUB[1] |= _fsign; } /* #undef _new_float_unibin #ifdef _new_float_unibin void float2UniBin ( realtype R, floatUniBin fUB ) { int k1,k2,k; realtype Q,L; if (R>=0) Q = R; else Q = -R; k1 = 0; k2 = _nfPowers; do { k = (k1+k2)/2; if (Q>=_fpower[k]) k1 = k; else k2 = k; } while (k2>k1+1); if (Q<=_fpower[0]) k2 = 0; Q = (Q/_fpower[k2])*_fpower4; fUB[0] = byte(k2); for (k=sizeof(floatUniBin)-1;k>0;k--) { L = floor(Q/_rfbase); fUB[k] = byte(int(Q-L*_rfbase)); Q = L; } if (R<0) fUB[1] |= _fsign; } #else void float2UniBin ( realtype R, floatUniBin fUB ) { int k1,k2,k; realtype Q,L; if (R>=0) Q = R; else Q = -R; k1 = 0; k2 = _nfPowers; do { k = (k1+k2)/2; if (Q>=_fpower[k]) k1 = k; else k2 = k; } while (k2>k1+1); if (Q<=_fpower[0]) k2 = 0; Q = (Q/_fpower[k2])*_fpower8; fUB[0] = byte(k2); for (k=sizeof(realUniBin)-1;k>0;k--) { L = floor(Q/_rfbase); if (k<=sizeof(floatUniBin)) fUB[k] = byte(int(Q-L*_rfbase)); Q = L; } if (R<0) fUB[1] |= _fsign; } #endif */ void float2UniBin ( realtype R, floatUniBin fUB ) { int k1,k2,k; realtype Q,L; if (R>=0) Q = R; else Q = -R; k1 = 0; k2 = _nfPowers; do { k = (k1+k2)/2; if (Q>=_fpower[k]) k1 = k; else k2 = k; } while (k2>k1+1); if (Q<=_fpower[0]) k2 = 0; fUB[0] = byte(k2); if (_old_float_unibin) { // this is wrong but compatible with already existing files :( // in the result, it gives errors in 6th digit at back conversion Q = (Q/_fpower[k2])*_fpower8; for (k=sizeof(realUniBin)-1;k>0;k--) { L = floor(Q/_rfbase); if (k<=(int)sizeof(floatUniBin)) fUB[k] = byte(int(Q-L*_rfbase)); Q = L; } } else { // this is correct Q = (Q/_fpower[k2])*_fpower4; for (k=sizeof(floatUniBin)-1;k>0;k--) { L = floor(Q/_rfbase); fUB[k] = byte(int(Q-L*_rfbase)); Q = L; } } //if (fUB[1] & _fsign) printf ( " error!\n" ); if (R<0) fUB[1] |= _fsign; } void UniBin2float ( floatUniBin fUB, realtype & R ) { int j,s; if (fUB[1] & _fsign) { s = 1; fUB[1] &= _fsign1; } else s = 0; R = int(fUB[1]); if (_old_float_unibin) { // this is wrong and gives a conversion error in 6th digit :( // we have to keep this for compatibility with already existing // files for (j=2;j<(int)sizeof(floatUniBin);j++) R = R*_rfbase + int(fUB[j]); for (j=sizeof(floatUniBin);j<(int)sizeof(realUniBin);j++) R *= _rfbase; R = (R/_fpower8)*_fpower[int(fUB[0])]; } else { // this is correct for (j=2;j<(int)sizeof(floatUniBin);j++) R = R*_rfbase + int(fUB[j]); R = (R/_fpower4)*_fpower[int(fUB[0])]; } if (s) R = -R; } /* ------------------------------------------------------- This piece of code shows that float2Unibin - Unbin2float pair does same-quality job as the native float - double conversion: InitMatType(); set_new_float_unibin(); floatUniBin fUB; realUniBin rUB; realtype maxsh = MaxShortReal/2.0; // max manageable /2! float maxshf = maxsh; realtype maxshr = maxshf; realtype maxsh1; float2UniBin ( maxsh,fUB ); UniBin2float ( fUB,maxsh1 ); printf ( " float\n %10.3f\n %10.3f\n %10.3f\n %10.3f\n", maxsh,maxsh1,maxshf,maxshr ); maxsh = MaxShortReal; real2UniBin ( maxsh,rUB ); UniBin2real ( rUB,maxsh1 ); printf ( " real\n %10.3f\n %10.3f\n",maxsh,maxsh1 ); ---- RESULTS: float 170099999999999990938343446679146987520.000 170099999948540854500627141228603899904.000 170100000027769017014891478822147850240.000 170100000027769017014891478822147850240.000 real 340199999999999981876686893358293975040.000 340199999999999981876686893358293975040.000 -------------------------------------------------------------- */ /* void shortreal2UniBin ( shortreal R, shortrealUniBin srUB ) { int k1,k2,k; realtype Q,L; if (R>=0) Q = R; else Q = -R; k1 = 0; k2 = _nfPowers; do { k = (k1+k2)/2; if (Q>=_fpower[k]) k1 = k; else k2 = k; } while (k2>k1+1); if (Q<=_fpower[0]) k2 = 0; Q = (Q/_fpower[k2])*_fpower8; srUB[0] = byte(k2); for (k=sizeof(realUniBin)-1;k>0;k--) { L = floor(Q/_rfbase); if (k<=(int)sizeof(shortrealUniBin)) srUB[k] = byte(int(Q-L*_rfbase)); Q = L; } if (R<0) srUB[1] |= _fsign; } void float2UniBin ( realtype R, floatUniBin fUB ) { int k1,k2,k; realtype Q,L; if (R>=0) Q = R; else Q = -R; k1 = 0; k2 = _nfPowers; do { k = (k1+k2)/2; if (Q>=_fpower[k]) k1 = k; else k2 = k; } while (k2>k1+1); if (Q<=_fpower[0]) k2 = 0; Q = (Q/_fpower[k2])*_fpower8; fUB[0] = byte(k2); for (k=sizeof(realUniBin)-1;k>0;k--) { L = floor(Q/_rfbase); if (k<=(int)sizeof(floatUniBin)) fUB[k] = byte(int(Q-L*_rfbase)); Q = L; } if (R<0) fUB[1] |= _fsign; } */ /* void UniBin2int ( intUniBin iUB, int & I ) { int j,n,sh; sh = 8*sizeof(intUniBin); I = 0x00; for (j=sizeof(intUniBin)-1;j>=0;j--) { sh -= 8; n = byte(iUB[j]); I = I | (n << sh); } } */ void UniBin2int ( intUniBin iUB, int & I ) { int j; I = 0x00; for (j=sizeof(intUniBin)-1;j>=0;j--) { I <<= 8; I |= int(iUB[j]); } } void UniBin2short ( shortUniBin sUB, short & S ) { int j,sh; short n; sh = 8*sizeof(shortUniBin); S = 0x00; for (j=sizeof(shortUniBin)-1;j>=0;j--) { sh -= 8; n = byte(sUB[j]); S = S | (n << sh); } } void UniBin2long ( longUniBin lUB, long & L ) { int j,sh; long n; sh = 8*sizeof(longUniBin); L = 0x00; for (j=sizeof(longUniBin)-1;j>=0;j--) { sh -= 8; n = byte(lUB[j]); L = L | (n << sh); } } void UniBin2word ( wordUniBin wUB, word & W ) { int j,sh; word n; sh = 8*sizeof(wordUniBin); W = 0x00; for (j=sizeof(wordUniBin)-1;j>=0;j--) { sh -= 8; n = byte(wUB[j]); W = W | (n << sh); } } void UniBin2real ( realUniBin rUB, realtype & R ) { int j,s; if (rUB[1] & _fsign) { s = 1; rUB[1] &= _fsign1; } else s = 0; R = int(rUB[1]); for (j=2;j<(int)sizeof(realUniBin);j++) R = R*_rfbase + int(rUB[j]); R = (R/_fpower8)*_fpower[int(rUB[0])]; if (s) R = -R; } void UniBin2shortreal ( shortrealUniBin srUB, shortreal & R ) { int j,s; if (srUB[1] & _fsign) { s = 1; srUB[1] &= _fsign1; } else s = 0; R = int(srUB[1]); for (j=2;j<(int)sizeof(shortrealUniBin);j++) R = R*_rfbase + int(srUB[j]); R = (R/_fpower4)*_fpower[int(srUB[0])]; if (s) R = -R; } /* #ifdef _new_float_unibin void UniBin2float ( floatUniBin fUB, realtype & R ) { int j,s; if (fUB[1] & _fsign) { s = 1; fUB[1] &= _fsign1; } else s = 0; R = int(fUB[1]); for (j=2;j<(int)sizeof(floatUniBin);j++) R = R*_rfbase + int(fUB[j]); R = (R/_fpower4)*_fpower[int(fUB[0])]; if (s) R = -R; } #else void UniBin2float ( floatUniBin fUB, realtype & R ) { int j,s; if (fUB[1] & _fsign) { s = 1; fUB[1] &= _fsign1; } else s = 0; R = int(fUB[1]); for (j=2;j0) { memcpy ( &(S[l]),L,len ); l += len; S[l] = char(0); } } void mem_write ( bool B, pstr S, int & l ) { if (B) S[l++] = 'Y'; else S[l++] = 'N'; S[l] = char(0); } void mem_write_byte ( byte B, pstr S, int & l ) { S[l++] = char(B); S[l] = char(0); } void mem_read ( int & I, cpstr S, int & l ) { intUniBin iUB; memcpy ( iUB,&(S[l]),sizeof(intUniBin) ); l += sizeof(intUniBin); UniBin2int ( iUB,I ); } void mem_read ( short & I, cpstr S, int & l ) { shortUniBin sUB; memcpy ( sUB,&(S[l]),sizeof(shortUniBin) ); l += sizeof(shortUniBin); UniBin2short ( sUB,I ); } void mem_read ( long & I, cpstr S, int & l ) { longUniBin lUB; memcpy ( lUB,&(S[l]),sizeof(longUniBin) ); l += sizeof(longUniBin); UniBin2long ( lUB,I ); } void mem_read ( word & W, cpstr S, int & l ) { wordUniBin wUB; memcpy ( wUB,&(S[l]),sizeof(wordUniBin) ); l += sizeof(wordUniBin); UniBin2word ( wUB,W ); } void mem_read ( realtype & R, cpstr S, int & l ) { realUniBin rUB; memcpy ( rUB,&(S[l]),sizeof(realUniBin) ); l += sizeof(realUniBin); UniBin2real ( rUB,R ); } void mem_read ( shortreal & R, cpstr S, int & l ) { shortrealUniBin srUB; memcpy ( srUB,&(S[l]),sizeof(shortrealUniBin) ); l += sizeof(shortrealUniBin); UniBin2shortreal ( srUB,R ); } void mem_read ( pstr L, int len, cpstr S, int & l ) { memcpy ( L,&(S[l]),len ); l += len; } void mem_read ( pstr & L, cpstr S, int & l ) { int len; if (L) { delete[] L; L = NULL; } mem_read ( len,S,l ); if (len>0) { L = new char[len+1]; memcpy ( L,&(S[l]),len ); L[len] = char(0); l += len; } } void mem_read ( bool & B, cpstr S, int & l ) { B = (S[l++]=='Y'); } void mem_read_byte ( byte & B, cpstr S, int & l ) { B = byte(S[l++]); } // ------------------------------------------------------- bool InitMatType() { MachEps = MachinEps(); floatMachEps = floatMachinEps(); LnMaxReal = log(fMaxReal); LnMinReal = log(fMinReal); LnMaxRealExp = LnMaxReal; LnMinRealExp = LnMinReal; InitFPowers(); return true; } } /* =================================================== */ // *** end of mmdb2-2.0.5/mmdb2/mmdb_io_file.h0000664000175000017500000003031012601171753013221 00000000000000// $Id: mmdb_io_file.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2008. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 11.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : file_ // ~~~~~~~~~ // **** Classes : mmdb::io::File - file I/O Support. // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_IO_File__ #define __MMDB_IO_File__ #include #include "mmdb_mattype.h" namespace mmdb { namespace io { // ======================== File Class ======================== enum GZ_MODE { GZM_NONE = 0, GZM_CHECK = 1, GZM_ENFORCE = 2, GZM_ENFORCE_GZIP = 2, GZM_ENFORCE_COMPRESS = 3 }; enum FILE_ERROR { FileError_NoMemory = 110, FileError_ShortData = 111, FileError_NoDataFound = 112, FileError_NoColumn = 113, FileError_BadData = 114, FileError_WrongMemoryAllocation = 115 }; enum SYSKEY { syskey_unix = 1, syskey_win = 2, syskey_all = 3 }; extern const char _dir_sep_c; extern cpstr _dir_sep; // =================== Auxilary Functions ======================== extern cpstr GetFPath ( pstr FilePath, SYSKEY syskey=syskey_unix ); extern cpstr GetFName ( cpstr FilePath, SYSKEY syskey=syskey_unix ); extern cpstr GetFExt ( cpstr FilePath ); extern cpstr ChangeExt ( pstr FilePath, cpstr newExt, SYSKEY syskey=syskey_unix ); extern cpstr FileError ( int ErrCode ); extern void RemoveDelimiters ( pstr S, int SLen ); extern void PickOutNumber ( cpstr S, pstr SV, int SLen, int & j ); // ========================== File =============================== DefineClass(File); class File { public : File ( word BufSize=4096 ); virtual ~File(); // ---- control functions // FileName allows for "stdin", "stdout" and "stderr" as // for standard UNIX streams. void assign ( cpstr FileName, bool Text=false, bool UniB=false, GZ_MODE gzMode=GZM_NONE ); // assign for memory IO void assign ( word poolSize, word sizeInc, pstr filePool ); void GetFilePool ( pstr & filePool, word & fileSize ); inline cpstr FileName() { return FName; } bool reset ( bool ReadOnly=false, int retry=0 ); // = true if opened, each retry 1 sec sleep bool erase (); // = true if erased bool exists (); // = true if exists bool parse ( cpstr FileName ); // true if filled bool rename ( cpstr NewFileName ); // true if renamed bool rewrite (); // = true if opened bool append (); // = true if opened bool isOpen (); long Position (); inline long FileLength () { return FLength; } bool seek ( long Position ); bool FileEnd (); inline bool Success () { return IOSuccess; } inline void SetSuccess() { IOSuccess = true; } void flush (); void shut (); // ---- binary I/O word ReadFile ( void * Buffer, word Count ); word CreateRead ( pstr & Line ); word ReadTerLine ( pstr Line, bool longLine=false ); word ReadShortLine ( pstr Line, bool longLine=false ); bool WriteFile ( const void * Buffer, word Count ); bool CreateWrite ( cpstr Line ); bool WriteTerLine ( cpstr Line, bool longLine=false ); // machine-independent binary I/O bool WriteReal ( realtype * V ); bool WriteFloat ( realtype * V ); bool WriteInt ( int * I ); bool WriteShort ( short * S ); bool WriteLong ( long * L ); bool WriteBool ( bool * B ); bool WriteByte ( byte * B ); bool WriteWord ( word * W ); bool ReadReal ( realtype * V ); bool ReadFloat ( realtype * V ); bool ReadInt ( int * I ); bool ReadShort ( short * S ); bool ReadLong ( long * L ); bool ReadBool ( bool * B ); bool ReadByte ( byte * B ); bool ReadWord ( word * B ); bool AddReal ( realtype * V ); bool AddFloat ( realtype * V ); bool AddInt ( int * I ); bool AddShort ( short * S ); bool AddLong ( long * L ); bool AddByte ( byte * B ); bool AddWord ( word * B ); // complex data binary I/O bool WriteVector ( rvector V, int len, int Shift ); bool WriteVector ( ivector iV, int len, int Shift ); bool WriteVector ( lvector lV, int len, int Shift ); bool WriteVector ( bvector B, int len, int Shift ); bool ReadVector ( rvector V, int maxlen, int Shift ); bool ReadVector ( ivector iV, int maxlen, int Shift ); bool ReadVector ( lvector lV, int maxlen, int Shift ); bool ReadVector ( bvector B, int maxlen, int Shift ); bool CreateReadVector ( rvector & V, int & len, int Shift ); bool CreateReadVector ( ivector & iV, int & len, int Shift ); bool CreateReadVector ( lvector & lV, int & len, int Shift ); bool CreateReadVector ( bvector & B, int & len, int Shift ); bool CreateReadVector ( rvector & V, int Shift ); bool CreateReadVector ( ivector & iV, int Shift ); bool CreateReadVector ( lvector & lV, int Shift ); bool CreateReadVector ( bvector & B, int Shift ); bool WriteMatrix ( rmatrix & A, int N, int M, int ShiftN, int ShiftM ); bool CreateReadMatrix ( rmatrix & A, int ShiftN, int ShiftM ); bool CreateReadMatrix ( rmatrix & A, int & N, int & M, int ShiftN, int ShiftM ); /// ---- text I/O bool Write ( cpstr Line ); //!< writes without LF bool Write ( realtype V, int length=10 ); //!< w/o LF bool Write ( int iV, int length=5 ); //!< w/o LF bool WriteLine ( cpstr Line ); //!< writes and adds LF bool LF (); //!< just adds LF word ReadLine ( pstr Line, word MaxLen=255 ); word ReadNonBlankLine ( pstr S, word MaxLen=255 ); /// complex data text I/O // writes with spaces and adds LF bool WriteDataLine ( realtype X, realtype Y, int length=10 ); bool WriteParameter ( cpstr S, realtype X, // writes parameter int ParColumn=40, // name S and value X int length=10 ); // at column ParColumn // and adds LF. bool WriteParameters ( cpstr S, int n_X, // writes parameter rvector X, // name S and n_X values int ParColumn=40, // X[0..n_X-1] at col int length=10 ); // ParColumn, ads LF. bool ReadParameter ( pstr S, realtype & X, // reads parameter int ParColumn=40 ); // name S and val X bool ReadParameter ( pstr S, int & X, int ParColumn=40 ); bool ReadParameters ( pstr S, int & n_X, // reads parameter rvector X, // name S, counts the int MaxLen=255, // of values n_X and int ParColumn=40 ); // reads X[0..n_X-1]. // MaxLen gives sizeof(S) // WriteColumns writes data stored in X, Y and Z in the form // of columns, adding a blank line in the end. If Z (or Z and Y) // are set to NULL, then only X and Y (or only X) are written. // Shift corresponds to the begining of arrays' enumeration // X[Shift..Shift+len-1]. bool WriteColumns ( rvector X, rvector Y, rvector Z, int len, int Shift, int MLength ); bool WriteColumns ( rvector X, rvector Y, int len, int Shift, int MLength ); // ReadColumns reads data stored by WriteColumns. X, Y, and Z // must be allocated prior to call. // xCol, yCol and zCol specify the order number of columns // (starting from 0) to be read into X, Y and Z, correspondingly. // If zCol (or zCol and yCol) < 0 then Z (or Z and Y) are not read. // Shift corresponds to the begining of arrays' enumeration // X[Shift..Shift+len-1]. // Returns number of lines read. int ReadColumns ( int maxlen, rvector X, rvector Y, rvector Z, int xCol, int yCol, int zCol, int Shift ); int ReadColumns ( int maxlen, rvector X, rvector Y, int xCol, int yCol, int Shift ); // CreateReadColumns reads data stored by WriteColumns. X, Y, // and Z must be set to NULL prior to call. They will be allocated // within the procedure. // xCol, yCol and zCol specify the order number of columns // (starting from 0) to be read into X, Y and Z, correspondingly. // If zCol (or zCol and yCol) < 0 then Z (or Z and Y) are not read. // Shift corresponds to the begining of arrays' enumeration // X[Shift..Shift+len-1]. // Returns number of lines read, errors are reported by // ErrorCode(). int CreateReadColumns ( rvector & X, rvector & Y, rvector & Z, int xCol, int yCol, int zCol, int Shift ); int CreateReadColumns ( rvector & X, rvector & Y, int xCol, int yCol, int Shift ); // ---- miscellaneous realtype GetNumber ( cpstr S ); FILE * GetHandle () { return hFile; } protected : word Buf_Size; bool TextMode,UniBin; GZ_MODE gzipMode; pstr IOBuf; word BufCnt,BufLen,BufInc; FILE * hFile; bool EofFile; pstr FName; long FLength; bool IOSuccess; int ErrCode; void FreeBuffer (); void _ReadColumns ( int & DLen, pstr S, int SLen, rvector X, rvector Y, rvector Z, int xCol, int yCol, int zCol, int Shift ); private : int gzipIO; bool StdIO,memIO; }; extern void SetGZIPPath ( pstr gzipPath, pstr ungzipPath ); extern void SetCompressPath ( pstr compressPath, pstr uncompressPath ); extern bool FileExists ( cpstr FileName, PFile f=NULL ); } } #endif mmdb2-2.0.5/mmdb2/mmdb_ficif.h0000664000175000017500000003032612401105774012700 00000000000000// $Id: mmdb_ficif.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2008. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_FICIF // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_FICIF__ #define __MMDB_FICIF__ #include "mmdb_machine_.h" using namespace mmdb; using namespace mmdb::machine; // ==================== FORTRAN INTERFACE ======================== FORTRAN_SUBR ( MMDB_FCIF_INIT, mmdb_fcif_init,(),(),() ); FORTRAN_SUBR ( MMDB_FCIF_QUIT, mmdb_fcif_quit,(),(),() ); FORTRAN_SUBR ( MMDB_FCIF_CREATE, mmdb_fcif_create, ( // lengths-at-end list fpstr DataName, // file name int DataName_len // fortran-hidden length of DataName ), ( // lengths-in-structure list fpstr DataName ), ( // lengths-follow list fpstr DataName, int DataName_len ) ); FORTRAN_SUBR ( MMDB_FCIF_WRITE, mmdb_fcif_write, ( // lengths-at-end list fpstr FileName, // file name int * iRet, // return code int FileName_len // fortran-hidden length of FileName ), ( // lengths-in-structure list fpstr FileName, int *iRet ), ( // lengths-follow list fpstr FileName, int FileName_len, int * iRet ) ); FORTRAN_SUBR ( MMDB_FCIF_PUTDATE, mmdb_fcif_putdate, ( // lengths-at-end list fpstr CatName, // category name fpstr Tag, // tag int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr CatName, fpstr Tag, int * iRet ), ( // lengths-follow list fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * iRet ) ); FORTRAN_SUBR ( MMDB_FCIF_PUTDOT, mmdb_fcif_putdot, ( // lengths-at-end list fpstr CatName, // category name fpstr Tag, // tag int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr CatName, fpstr Tag, int * iRet ), ( // lengths-follow list fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * iRet ) ); FORTRAN_SUBR ( MMDB_FCIF_PUTQUESTION, mmdb_fcif_putquestion, ( // lengths-at-end list fpstr CatName, // category name fpstr Tag, // tag int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr CatName, fpstr Tag, int * iRet ), ( // lengths-follow list fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * iRet ) ); FORTRAN_SUBR ( MMDB_FCIF_PUTSTRING, mmdb_fcif_putstring, ( // lengths-at-end list fpstr Data, // data string to store fpstr CatName, // category name fpstr Tag, // tag int * iRet, // return code int Data_len, // fortran-hidden length of Data int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr Data, fpstr CatName, fpstr Tag, int * iRet ), ( // lengths-follow list fpstr Data, int Data_len, fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * iRet ) ); FORTRAN_SUBR ( MMDB_FCIF_PUTREAL, mmdb_fcif_putreal, ( // lengths-at-end list apireal * V, // real value to store fpstr CatName, // category name fpstr Tag, // tag int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list apireal * V, fpstr CatName, fpstr Tag, int * iRet ), ( // lengths-follow list apireal * V, fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * iRet ) ); FORTRAN_SUBR ( MMDB_FCIF_PUTINTEGER, mmdb_fcif_putinteger, ( // lengths-at-end list int * I, // integer value to store fpstr CatName, // category name fpstr Tag, // tag int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list int * I, fpstr CatName, fpstr Tag, int * iRet ), ( // lengths-follow list int * I, fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * iRet ) ); FORTRAN_SUBR ( MMDB_FCIF_PUTLOOPDOT, mmdb_fcif_putloopdot, ( // lengths-at-end list fpstr CatName, // category name fpstr Tag, // tag int * nrow, // row number int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr CatName, fpstr Tag, int * nrow, int * iRet ), ( // lengths-follow list fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * nrow, int * iRet ) ); FORTRAN_SUBR ( MMDB_FCIF_PUTLOOPQUESTION, mmdb_fcif_putloopquestion, ( // lengths-at-end list fpstr CatName, // category name fpstr Tag, // tag int * nrow, // row number int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr CatName, fpstr Tag, int * nrow, int * iRet ), ( // lengths-follow list fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * nrow, int * iRet ) ); FORTRAN_SUBR ( MMDB_FCIF_PUTLOOPSTRING, mmdb_fcif_putloopstring, ( // lengths-at-end list fpstr Data, // data string to store fpstr CatName, // category name fpstr Tag, // tag int * nrow, // row number int * iRet, // return code int Data_len, // fortran-hidden length of Data int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr Data, fpstr CatName, fpstr Tag, int * nrow, int * iRet ), ( // lengths-follow list fpstr Data, int Data_len, fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * nrow, int * iRet ) ); FORTRAN_SUBR ( MMDB_FCIF_PUTLOOPREAL, mmdb_fcif_putloopreal, ( // lengths-at-end list apireal * V, // real value to store fpstr CatName, // category name fpstr Tag, // tag int * nrow, // row number int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list apireal * V, fpstr CatName, fpstr Tag, int * nrow, int * iRet ), ( // lengths-follow list apireal * V, fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * nrow, int * iRet ) ); FORTRAN_SUBR ( MMDB_FCIF_PUTLOOPINTEGER, mmdb_fcif_putloopinteger, ( // lengths-at-end list int * I, // integer value to store fpstr CatName, // category name fpstr Tag, // tag int * nrow, // row number int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list int * I, fpstr CatName, fpstr Tag, int * nrow, int * iRet ), ( // lengths-follow list int * I, fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * nrow, int * iRet ) ); // ==================== C INTERFACE ======================== extern "C" void MMDB_CCIF_Init(); extern "C" void MMDB_CCIF_Quit(); extern "C" void MMDB_CCIF_Create ( pstr DataName ); extern "C" int MMDB_CCIF_Write ( pstr FileName ); extern "C" int MMDB_CCIF_PutDate ( pstr CatName, pstr Tag ); extern "C" int MMDB_CCIF_PutDot ( pstr CatName, pstr Tag ); extern "C" int MMDB_CCIF_PutQuestion ( pstr CatName, pstr Tag ); extern "C" int MMDB_CCIF_PutString ( pstr Data, pstr CatName, pstr Tag ); extern "C" int MMDB_CCIF_PutReal ( realtype V, pstr CatName, pstr Tag ); extern "C" int MMDB_CCIF_PutInteger ( int I, pstr CatName, pstr Tag ); extern "C" int MMDB_CCIF_PutLoopDot ( pstr CatName, pstr Tag, int nrow ); extern "C" int MMDB_CCIF_PutLoopQuestion ( pstr CatName, pstr Tag, int nrow ); extern "C" int MMDB_CCIF_PutLoopString ( pstr Data, pstr CatName, pstr Tag, int nrow ); extern "C" int MMDB_CCIF_PutLoopReal ( realtype V, pstr CatName, pstr Tag, int nrow ); extern "C" int MMDB_CCIF_PutLoopInteger ( int I, pstr CatName, pstr Tag, int nrow ); #endif mmdb2-2.0.5/mmdb2/mmdb_io_stream.h0000664000175000017500000001777712401105774013621 00000000000000// $Id: mmdb_io_stream.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2008. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 11.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : Stream // ~~~~~~~~~ // **** Classes : mmdb::io::Stream ( Basic Stream Class ) // ~~~~~~~~~ // // (C) E. Krissinel 1995-2013 // // ================================================================= // #ifndef __MMDB_IO_Stream__ #define __MMDB_IO_Stream__ #include "mmdb_io_file.h" // ******************************************************************* #ifndef __ClassMacros # define __ClassMacros // A Class definition macros # define DefineClass(ClassName) \ class ClassName; \ typedef ClassName * P##ClassName; \ typedef ClassName & R##ClassName; \ typedef P##ClassName * PP##ClassName; \ typedef P##ClassName & RP##ClassName; // A Structure definition macros # define DefineStructure(StructureName) \ struct StructureName; \ typedef StructureName * P##StructureName; \ typedef StructureName & R##StructureName; \ typedef P##StructureName * PP##StructureName; \ typedef P##StructureName & RP##StructureName; #endif #define DefineStreamFunctions(ClassName) \ extern void StreamWrite ( mmdb::io::RFile f, RP##ClassName Object ); \ extern void StreamRead ( mmdb::io::RFile f, RP##ClassName Object ); #define MakeStreamFunctions(ClassName) \ void StreamWrite ( mmdb::io::RFile f, RP##ClassName Object ) { \ StreamWrite_ ( f,(mmdb::io::RPStream)Object ); \ } \ mmdb::io::PStream StreamInit##ClassName ( mmdb::io::RPStream Object ) { \ return (mmdb::io::PStream)(new ClassName(Object)); \ } \ void StreamRead ( mmdb::io::RFile f, RP##ClassName Object ) { \ StreamRead_ ( f,(mmdb::io::RPStream)Object,StreamInit##ClassName );\ } #define DefineFactoryFunctions(ClassName) \ typedef P##ClassName Make##ClassName(); \ typedef Make##ClassName * PMake##ClassName; \ typedef P##ClassName StreamMake##ClassName ( mmdb::io::RPStream Object ); \ P##ClassName new##ClassName (); \ P##ClassName streamNew##ClassName ( mmdb::io::RPStream Object ); \ typedef StreamMake##ClassName * PStreamMake##ClassName; \ extern void SetMakers##ClassName ( void * defMk, void * streamMk ); \ extern void StreamWrite ( mmdb::io::RFile f, RP##ClassName Object ); \ extern void StreamRead ( mmdb::io::RFile f, RP##ClassName Object ); #define MakeFactoryFunctions(ClassName) \ static PMake##ClassName make##ClassName = NULL; \ static PStreamMake##ClassName streamMake##ClassName = NULL; \ P##ClassName new##ClassName() { \ if (make##ClassName) return (*make##ClassName)(); \ else return new ClassName(); \ } \ P##ClassName streamNew##ClassName ( mmdb::io::RPStream Object ) { \ if (streamMake##ClassName) \ return (*streamMake##ClassName)(Object); \ else return new ClassName(Object); \ } \ void SetMakers##ClassName ( void * defMk, void * streamMk ) { \ make##ClassName = PMake##ClassName(defMk); \ streamMake##ClassName = PStreamMake##ClassName(streamMk); \ } \ void StreamWrite ( mmdb::io::RFile f, RP##ClassName Object ) { \ StreamWrite_ ( f,(mmdb::io::RPStream)Object ); \ } \ mmdb::io::PStream StreamInit##ClassName ( mmdb::io::RPStream Object ) { \ return (mmdb::io::PStream)(streamNew##ClassName(Object)); \ } \ void StreamRead ( mmdb::io::RFile f, RP##ClassName Object ) { \ StreamRead_ ( f,(mmdb::io::RPStream)Object,StreamInit##ClassName ); \ } namespace mmdb { namespace io { // ========================== Stream =========================== // Each streamable class should be derived from Stream // and have constructor Class(PStream & Object), which should // initialize all memory of the class, and virtual functions // read(..) and write(..) (see below). Constructor Class(PStream&) // must not touch the Object variable. This constructor is used // only once just before the read(..) function. It is assumed that // read(..)/write(..) functions of the Class provide storage/reading // of all vital data. Function read(..) must read data in exactly // the same way as function write(..) stores it. // For using Class in streams, three following functions should // be supplied: // // 1. // void StreamWrite ( File & f, PClass & Object ) { // StreamWrite ( f,(PStream)Object ); // } // // 2. // PStream ClassInit ( PStream & Object ) { // return (PStream)(new Class(Object)); // } // // 3. // void StreamRead ( File & f, PClass & Object ) { // StreamRead_ ( f,(PStream)Object,ClassInit ); // } // // All these functions are automatically generated by macros // DefineStreamFunctions(Class) -- in the header -- and // MakeStreamFunctions(Class) -- in the implementation body. Note // that macro DefineClass(Class) should always be issued for // streamable classes prior to the stream-making macros. Then // Class may be streamed using functions #1 and #3. // StreamRead will return NULL for Object if it was not in // the stream. If Object existed before calling StreamRead(..) // but was not found in the stream, it will be disposed (NULL // assigned). DefineClass(Stream); DefineStreamFunctions(Stream); class Stream { public : Stream () {} Stream ( RPStream ) {} virtual ~Stream () {} virtual void read ( RFile ) {} virtual void write ( RFile ) {} }; typedef PStream InitStreamObject(RPStream Object); extern void StreamRead_ ( RFile f, RPStream Object, InitStreamObject Init ); extern void StreamWrite_ ( RFile f, RPStream Object ); } } #endif mmdb2-2.0.5/mmdb2/mmdb_math_linalg.h0000664000175000017500000002123112401105774014072 00000000000000// $Id: mmdb_math_linalg.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : LinAlg // ~~~~~~~~~ // **** Project : MMDB ( MacroMolecular Data Base ) // ~~~~~~~~~ // // (C) E.Krissinel 2000-2013 // // ================================================================= // // #ifndef __MMDB_MATH_LinAlg__ #define __MMDB_MATH_LinAlg__ #include "mmdb_mattype.h" namespace mmdb { namespace math { // ========================== Jacobi ============================= /// Diagonalization of symmetric matrices A[1..N][1..N] /// by the method of Jacobi. extern void Jacobi ( int N, //!< dimension of the matrix rmatrix A, //!< matrix to diagonalize; the /// lower triangle, except the /// diagonal, will remain unchanged rmatrix T, //!< eigenvectors placed as columns rvector Eigen, //!< vector of eigenvalues, orderd /// by increasing rvector Aik, //!< working array int & Signal //!< 0 <=> Ok, ItMax <=> iteration /// limit exchausted. ); // A5.5.2 : Perturbed Cholesky Decomposition extern void PbCholDecomp ( int N, rvector HDiag, realtype MaxOff, realtype MachEps, rmatrix L, realtype & MaxAdd ); // A3.2.3a : Cholesky's L - Solution of // L*Y = B ( given B ) extern void LSolve ( int N, rmatrix L, rvector B, rvector Y ); // A3.2.3b : Cholesky's LT - Solution of // LT*X = Y ( given Y ) extern void LTSolve ( int N, rmatrix L, rvector Y, rvector X ); // A3.2.3 : Solution of the equation L*LT*S = G // by the Cholesky's method extern void ChSolve ( int N, rmatrix L, rvector G, rvector S ); // ---------------------------------------------------- extern void FastInverse ( int N, rmatrix A, ivector J0, //#D realtype & Det, int & Signal ); // // 13.09.90 <-- Last Modification Date // ------------------------ // // ================================================ // // Fast Inversion of the matrix A // by the method of GAUSS - JORDAN . // // ------------------------------------------------ // // Input parameters are : // // N - dimension of the matrix // A - the matrix [1..N][1..N] to be inverted. // ------------------------------------------------ // // J0 - integer vector [1..N] for temporal storage // // ------------------------------------------------ // // Output parameters are : // // A - the inverted matrix // Signal - the error key : // = 0 <=> O'K // else // degeneration was found, and // the rang of matrix is Signal-1. // // Variable Det may return the determinant // of matrix A. To obtain it, remove all comments // of form //#D. // // ================================================ // ---------------------------------------------------- extern void SVD ( int NA, int M, int N, rmatrix A, rmatrix U, rmatrix V, rvector W, rvector RV1, bool MatU, bool MatV, int & RetCode ); // // 13.12.01 <-- Last Modification Date // ------------------------ // // ================================================ // // The Singular Value Decomposition // of the matrix A by the algorithm from // G.Forsait, M.Malkolm, K.Mouler. Numerical // methods of mathematical calculations // // M., Mir, 1980. // // Matrix A is represented as // // A = U * W * VT // // ------------------------------------------------ // // All dimensions are indexed from 1 on. // // ------------------------------------------------ // // Input parameters: // // NA - number of lines in A. NA may be // equal to M or N only. If NA=M // then usual SVD will be made. If MA=N // then matrix A is transposed before // the decomposition, and the meaning of // output parameters U and V is // swapped (U accepts VT and VT accepts U). // In other words, matrix A has physical // dimension of M x N , same as U and V; // however the logical dimension of it // remains that of N x M . // M - number of lines in U // N - number of columns in U,V and length // of W,RV1 . Always provide M >= N ! // A - matrix [1..M][1..N] or [1..N][1..M] // to be decomposed. The matrix does not // change, and it may coincide with U or // V, if NA=M (in which case A does change) // MatU - compute U , if set True // MatV - compute V , if set True // RV1 - temporary array [1..N]. // U - should be always supplied as an array of // [1..M][1..N], M>=N . // V - should be suuplied as an array of // [1..N][1..N] if MatV is True . // // ------------------------------------------------ // // Output parameters are : // // W - N non-ordered singular values, // if RetCode=0. If RetCode<>0, the // RetCode+1 ... N -th values are still // valid // U - matrix of right singular vectors // (arranged in columns), corresponding // to the singular values in W, if // RetCode=0 and MatU is True. If MatU // is False, U is still used as a // temporary array. If RetCode<>0 then // the RetCode+1 ... N -th vectors // are valid // V - matrix of left singular vectors // (arranged in columns), corresponding // to the singular values in W, if // RetCode=0 and MatV is True. If MatV // is False, V is not used and may be set // to NULL. If RetCode<>0 then the // RetCode+1 ... N -th vectors are valid // RetCode - the error key : // = 0 <=> O'K // else // = k, if the k-th singular value // was not computed after 30 iterations. // // ------------------------------------------------ // // Key Variables are : // // ItnLimit - the limit for iterations // // This routine does not use any machine-dependent // constants. // // ================================================ // // extern void OrderSVD ( int M, int N, rmatrix U, rmatrix V, rvector W, bool MatU, bool MatV ); } } #endif mmdb2-2.0.5/mmdb2/mmdb_atom.h0000664000175000017500000007236312601171753012571 00000000000000// $Id: mmdb_atom.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2015. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 07.09.15 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_Atom // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::Atom ( atom class ) // ~~~~~~~~~ mmdb::Residue ( residue class ) // **** Functions: mmdb::BondAngle // ~~~~~~~~~~ // // Copyright (C) E. Krissinel 2000-2015 // // ================================================================= // #ifndef __MMDB_Atom__ #define __MMDB_Atom__ #include "mmdb_io_stream.h" #include "mmdb_uddata.h" #include "mmdb_utils.h" #include "mmdb_defs.h" namespace mmdb { // ====================== Atom ========================== // constants for the WhatIsSet field enum ASET_FLAG { ASET_Coordinates = 0x00000001, ASET_Occupancy = 0x00000002, ASET_tempFactor = 0x00000004, ASET_CoordSigma = 0x00000010, ASET_OccSigma = 0x00000020, ASET_tFacSigma = 0x00000040, ASET_Anis_tFac = 0x00000100, ASET_Anis_tFSigma = 0x00001000, ASET_Charge = 0x00000080, ASET_All = 0x000FFFFF }; const int ATOM_NoSeqNum = MinInt4; extern bool ignoreSegID; extern bool ignoreElement; extern bool ignoreCharge; extern bool ignoreNonCoorPDBErrors; extern bool ignoreUnmatch; DefineStructure(AtomStat); struct AtomStat { public : int nAtoms; // number of atoms in statistics realtype xmin,ymin,zmin; // minimums of coordinates realtype xmax,ymax,zmax; // maximums of coordinates realtype xm ,ym ,zm; // mediums of coordinates realtype xm2 ,ym2 ,zm2; // square mediums of coordinates realtype occ_min,occ_max; // minimum/maximum occupancy realtype occ_m ,occ_m2; // medium and square medium occupancy realtype tFmin,tFmax; // minimum/maximum temperature factor realtype tFm ,tFm2; // medium and sq. med. temp. factor realtype u11_min,u11_max; // minimums and realtype u22_min,u22_max; // maximums of realtype u33_min,u33_max; // anisotropic realtype u12_min,u12_max; // temperature realtype u13_min,u13_max; // factors realtype u23_min,u23_max; realtype u11_m,u11_m2; // mediums and realtype u22_m,u22_m2; // square mediums of realtype u33_m,u33_m2; // anisotropic realtype u12_m,u12_m2; // temperature realtype u13_m,u13_m2; // factors realtype u23_m,u23_m2; word WhatIsSet; // mask field void Init (); void Finish(); realtype GetMaxSize(); private : bool finished; }; DefineStructure(AtomBondI); struct AtomBondI { int index; //!< bonded atom index byte order; //!< bond order }; DefineStructure(AtomBond); struct AtomBond { PAtom atom; //!< bonded atom pointer byte order; //!< bond order }; DefineFactoryFunctions(Atom); class Atom : public UDData { friend class Residue; friend class Model; friend class Root; friend class CoorManager; friend class SelManager; public : int serNum; //!< serial number AtomName name; //!< atom name (ALIGNED) AtomName label_atom_id; //!< assigned atom name (not aligned) AltLoc altLoc; //!< alternative location indicator ("" for none) SegID segID; //!< segment identifier Element element; //!< element symbol (ALIGNED TO RIGHT) EnergyType energyType; //!< energy type (without spaces) PResidue residue; //!< reference to residue realtype x,y,z; //!< orthogonal coordinates in angstroms realtype occupancy; //!< occupancy realtype tempFactor; //!< temperature factor realtype charge; //!< charge on the atom realtype sigX,sigY,sigZ; //!< standard deviations of the coords realtype sigOcc; //!< standard deviation of occupancy realtype sigTemp; //!< standard deviation of temp. factor realtype u11,u22,u33; //!< anisotropic temperature realtype u12,u13,u23; /// factors realtype su11,su22,su33; //!< standard deviations of realtype su12,su13,su23; /// anisotropic temperature factors bool Het; //!< indicator of het atom bool Ter; //!< chain terminator word WhatIsSet; //!< mask field /// 0x0001 atomic coordinates /// 0x0002 occupancy /// 0x0004 temperature factor /// 0x0010 coordinate standard deviations /// 0x0020 deviation of occupancy /// 0x0040 deviation of temperature factor /// 0x0100 anisotropic temperature factors /// 0x1000 anis. temp. fact-s st-d deviations Atom (); Atom ( PResidue res ); Atom ( io::RPStream Object ); ~Atom(); void SetResidue ( PResidue res ); void PDBASCIIDump ( io::RFile f ); void MakeCIF ( mmcif::PData CIF ); // AddBond(...) adds a bond to the atom, that is a pointer // to the bonded atom and the bond order. nAdd_bonds allows // one to minimize the memory reallocations, if number of // bonds is known apriori: Atom adds space for nAdd_bonds // if currently allocated space is exchausted. // Return: <=0 - error: bond_atom is already "bonded" // >0 - Ok, returns current number of bonds int AddBond ( PAtom bond_atom, int bond_order, int nAdd_bonds=1 ); int GetNBonds(); // This GetBonds(..) returns pointer to the Atom's // internal Bond structure, IT MUST NOT BE DISPOSED. void GetBonds ( RPAtomBond atomBond, int & nAtomBonds ); void FreeBonds(); // This GetBonds(..) disposes AtomBondI, if it was not set // to NULL, allocates AtomBondI[nAtomBonds] and returns its // pointer. AtomBondI MUST BE DISPOSED BY APPLICATION. void GetBonds ( RPAtomBondI atomBondI, int & nAtomBonds ); // This GetBonds(..) does not dispose or allocate AtomBondI. // It is assumed that length of AtomBondI is sufficient to // accomodate all bonded atoms. void GetBonds ( PAtomBondI atomBondI, int & nAtomBonds, int maxlength ); // ConvertPDBxxxxxx() gets data from the PDB ASCII xxxxxx // record (xxxxxx stands for ATOM, SIGATM, ANISOU, SIGUIJ, // TER or HETATM). // These functions DO NOT check the xxxxxx keyword and // do not decode the chain and residue parameters! These // must be treated by the calling process, see // CMMDBFile::ReadPDBAtom(). // The atom reference is updated in the corresponding // residue. ERROR_CODE ConvertPDBATOM ( int ix, cpstr S ); ERROR_CODE ConvertPDBSIGATM ( int ix, cpstr S ); ERROR_CODE ConvertPDBANISOU ( int ix, cpstr S ); ERROR_CODE ConvertPDBSIGUIJ ( int ix, cpstr S ); ERROR_CODE ConvertPDBTER ( int ix, cpstr S ); ERROR_CODE ConvertPDBHETATM ( int ix, cpstr S ); ERROR_CODE GetCIF ( int ix, mmcif::PLoop Loop, mmcif::PLoop LoopAnis ); bool RestoreElementName(); bool MakePDBAtomName(); void SetAtomName ( int ix, // index int sN, // serial number const AtomName aName, // atom name const AltLoc aLoc, // alternative location const SegID sID, // segment ID const Element eName ); // element name // This only renames the atom void SetAtomName ( const AtomName atomName ); void SetElementName ( const Element elName ); void SetCharge ( cpstr chrg ); void SetCharge ( realtype chrg ); void SetAtomIndex ( int ix ); // don't use in your applications! void MakeTer(); // converts atom into 'ter' void SetCoordinates ( realtype xx, realtype yy, realtype zz, realtype occ, realtype tFac ); int GetModelNum (); pstr GetChainID (); pstr GetLabelAsymID (); pstr GetResName (); pstr GetLabelCompID (); int GetAASimilarity ( const ResName resName ); int GetAASimilarity ( PAtom A ); realtype GetAAHydropathy(); realtype GetOccupancy (); int GetSeqNum (); int GetLabelSeqID (); int GetLabelEntityID (); pstr GetInsCode (); int GetSSEType (); // works only after SSE calculations pstr GetAtomName () { return name; } pstr GetElementName () { return element; } pstr GetAtomCharge ( pstr chrg ); // GetChainCalphas(...) is a specialized function for quick // access to C-alphas of chain which includes given atom. // This function works faster than an equivalent implementation // through MMDB's selection procedures. // Parameters: // Calphas - array to accept pointers on C-alpha atoms // If Calphas!=NULL, then the function will // delete and re-allocate it. When the array // is no longer needed, the application MUST // delete it: delete[] Calphas; Deleting // Calphas does not delete atoms from MMDB. // nCalphas - integer to accept number of C-alpha atoms // and the length of Calphas array. // altLoc - alternative location indicator. By default // (""), maximum-occupancy locations are taken. void GetChainCalphas ( PPAtom & Calphas, int & nCalphas, cpstr altLoc = "" ); bool isTer () { return Ter; } bool isMetal (); bool isSolvent (); // works only for atom in a residue! bool isInSelection ( int selHnd ); bool isNTerminus (); bool isCTerminus (); void CalAtomStatistics ( RAtomStat AS ); realtype GetDist2 ( PAtom a ); realtype GetDist2 ( PAtom a, mat44 & tm ); // tm applies to A realtype GetDist2 ( PAtom a, mat33 & r, vect3 & t );// tm applies to A realtype GetDist2 ( realtype ax, realtype ay, realtype az ); realtype GetDist2 ( vect3 & xyz ); // GetCosine(a1,a2) calculates cosine of angle a1-this-a2, // i.e. that between vectors [a1,this] and [this,a2]. realtype GetCosine ( PAtom a1, PAtom a2 ); PResidue GetResidue (); PChain GetChain (); PModel GetModel (); int GetResidueNo(); void * GetCoordHierarchy(); // PRoot // GetAtomID(..) generates atom ID in the form // /m/c/r(rn).i/n[e]:a // where m - model number // c - chain ID // r - residue sequence number // rn - residue name // i - insertion code // n - atom name // e - chemical element specification // a - alternate location indicator // If any of the fields is undefined, it is replaced by // hyphen '-'. // No checks on the sufficiency of string buffer AtomID // is made. // GetAtomID returns AtomID. pstr GetAtomID ( pstr AtomID ); pstr GetAtomIDfmt ( pstr AtomID ); // ------- checking atom ID // CheckID(..) returns 1 if atom is identified, and 0 otherwise. // Parameters: // aname - atom name. It may or may not be aligned (as in // a PDB file), only first word of the name will // be taken ("CA", " CA" and " CA B" are all // considered as "CA"). aname may be set to NULL // or '*', then this parameter is ignored. // elname - element code. It will work only if element code // is supplied (which might not be the case if // the atom was created in a tricky way). elname // should be used to distinguih between, e.g. // "Ca" and "C_alpha"). elname may be set to NULL, // or '*', then this parameter is ignored. // aloc - the alternate location code. aloc may be set to // NULL or '*', then this parameter is ignored. // IMPORTANT: comparison is case-sensitive. // The atom is considered as identified, if all non-NULL // parameters do match. If all parameters are set NULL, any atom // is identified. // DEFAULT values correspond to 'any element' and // 'no alternate location code' // NOTE that " " is not an empty item. int CheckID ( const AtomName aname, const Element elname=NULL, const AltLoc aloc=pstr("") ); // CheckIDS(..) works exactly like CheckID(..), but it takes // the only parameter, the atom ID, which is of the form: // {name} {[element]} {:altcode} // Here {} means that the item may be omitted. Any item may be // represented by a wildcard '*', which means 'any value'. Just // absence of an item means 'empty', which makes sense only for // alternate location code. Missing name or element therefore // mean 'any name' or 'any element', correspondingly (same as a // wildcard). There should be no spaces in ID except for leading // spaces; any following space will terminate parsing. // The followings are perfectly valid IDs: // CA[C]:A (carbon C_alpha in location A) // CA[*]:A (either C_alpha or Ca in location A) // CA:A (same as above) // CA (either C_alpha or Ca with no location indicator) // CA[] (same as above) // CA[C]: (C_alpha with no location indicator) // [C] (any carbon with no location indicator) // [C]:* (any carbon with any location indicator) // *[C]:* (same as above) // :A (any atom in location A) // *[*]:A (same as above) // *[*]:* (any atom) // * (any atom with no alternate location indicator) int CheckIDS ( cpstr ID ); // ------- transform coordinates: x := m*x + v void Transform ( mat33 & tm, vect3 & v ); void Transform ( mat44 & tm ); void TransformCopy ( mat44 & tm, realtype & xx, realtype & yy, realtype & zz ); void TransformCopy ( mat44 & tm, vect3 & xyz ); void TransformSet ( mat44 & tm, realtype xx, realtype yy, realtype zz ); // ------- user-defined data handlers int PutUDData ( int UDDhandle, int iudd ); int PutUDData ( int UDDhandle, realtype rudd ); int PutUDData ( int UDDhandle, cpstr sudd ); int GetUDData ( int UDDhandle, int & iudd ); int GetUDData ( int UDDhandle, realtype & rudd ); int GetUDData ( int UDDhandle, pstr sudd, int maxLen ); int GetUDData ( int UDDhandle, pstr & sudd ); int GetIndex() { return index; } virtual void Copy ( PAtom atom ); // without references in // residues void SetCompactBinary(); // leaves only coordinates in binary files void write ( io::RFile f ); void read ( io::RFile f ); protected : int index; // index in the file int nBonds; // number of bonds in the lowest byte (!) PAtomBond Bond; // atom bonds void InitAtom (); void FreeMemory (); void StandardPDBOut ( cpstr Record, pstr S ); void GetData ( cpstr S ); ERROR_CODE CheckData ( cpstr S ); void GetStat ( realtype v, realtype & v_min, realtype & v_max, realtype & v_m, realtype & v_m2 ); void _setBonds ( PPAtom A ); // used only in Residue }; // ====================== Residue ========================== enum ALTLOC_FLAG { ALF_NoAltCodes = 0x00000000, ALF_EmptyAltLoc = 0x00000001, ALF_NoEmptyAltLoc = 0x00000002, ALF_Mess = 0x00000004, ALF_Occupancy = 0x00000008 }; enum SSE_FLAG { SSE_None = 0, SSE_Strand = 1, SSE_Bulge = 2, SSE_3Turn = 3, SSE_4Turn = 4, SSE_5Turn = 5, SSE_Helix = 6 }; DefineFactoryFunctions(Residue); class Residue : public UDData { friend class Atom; friend class Chain; friend class Root; public : ResName name; //!< residue name - all spaces cut ResName label_comp_id; //!< assigned residue name ChainID label_asym_id; //!< assigned chain Id InsCode insCode; //!< residue insertion code PChain chain; //!< reference to chain PPAtom atom; //!< array of atoms int seqNum; //!< residue sequence number int label_seq_id; //!< assigned residue sequence number int label_entity_id; //!< assigned entity id int index; //!< index in the chain int nAtoms; //!< number of atoms in the residue byte SSE; //!< SSE type Residue (); Residue ( PChain Chain_Owner ); Residue ( PChain Chain_Owner, const ResName resName, int sqNum, const InsCode ins ); Residue ( io::RPStream Object ); ~Residue(); void SetChain ( PChain Chain_Owner ); void SetResID ( const ResName resName, int sqNum, const InsCode ins ); void SetChainID ( const ChainID chID ); void PDBASCIIAtomDump ( io::RFile f ); void MakeAtomCIF ( mmcif::PData CIF ); PChain GetChain(); PModel GetModel(); int GetModelNum (); pstr GetChainID (); pstr GetLabelAsymID(); pstr GetResName (); pstr GetLabelCompID(); int GetAASimilarity ( const ResName resName ); int GetAASimilarity ( PResidue res ); realtype GetAAHydropathy(); void SetResName ( const ResName resName ); int GetSeqNum (); int GetLabelSeqID (); int GetLabelEntityID(); pstr GetInsCode (); int GetResidueNo (); int GetCenter ( realtype & x, realtype & y, realtype & z ); void * GetCoordHierarchy(); // PCMMDBFile void GetAtomStatistics ( RAtomStat AS ); void CalAtomStatistics ( RAtomStat AS ); pstr GetResidueID ( pstr ResidueID ); // GetAltLocations(..) returns the number of different // alternative locations in nAltLocs, the locations themselves // - in aLoc and the corresponding occupancies - in occupancy. // aLoc and occupancy are allocated dynamically; it is // responsibility of the application to deallocate aLoc prior // calling GetAltLocations(..) if they were previously allocated. // Either, the application is responsible for deallocating aLoc and // occupancy after use. // occupancy[i] may return -1.0 if occupancies were not read // from coordinate file. // alflag returns ALF_NoAltCodes if no alt codes was found, // otherwise the output is decoded according to bits: // ALF_EmptyAltLoc alternative locations include the // "no alt loc indicator" ("" for // Atom::altLoc). // This means that each atom that has alt locs // different of "", also includes one marked as // "". // ALF_NoEmptyAltLoc alternative locations do not include the // "no alt loc indicator" ("" for // Atom::altLoc). // This means that each atom has either "" // alt loc or at least two alt locs different // of "". // ALF_Mess incorrect residue: it mixes both // ""-including and not-""-including schemes // ALF_Occupancy warning that sum of occupancies for alt // located atoms differ from 1.0 by more // than 0.01. void GetAltLocations ( int & nAltLocs, PAltLoc & aLoc, rvector & occupancy, int & alflag ); int GetNofAltLocations(); bool isAminoacid (); bool isNucleotide (); int isDNARNA (); // 0(neither),1(DNA),2(RNA) bool isSugar (); bool isSolvent (); bool isModRes (); bool isInSelection ( int selHnd ); bool isNTerminus (); bool isCTerminus (); // ------- checking residue ID // CheckID(..) returns 1 if residue is identified, and 0 otherwise. // Parameters: // sname - pointer to sequence number; if NULL then ignored. // inscode - insertion code; if NULL or '*' then ignored. // resname - residue name; if NULL or '*' then ignored. // IMPORTANT: comparison is case-sensitive. // The residue is considered as identified, if all non-NULL // parameters do match. If all parameters are set NULL, any // residue is identified. // DEFAULT values correspond to 'any residue name' and // 'no insertion code' // NOTE that " " is not an empty item. int CheckID ( int * snum, const InsCode inscode=pstr(""), const ResName resname=NULL ); // CheckIDS(..) works exactly like CheckID(..), but it takes // the only parameter, the residue ID, which is of the form: // {seqnum} {(name)} {.inscode} // Here {} means that the item may be omitted. Any item may be // represented by a wildcard '*', which means 'any value'. Just // absence of a value means 'empty', which is meaningful only for // the insertion code. Missing sequence number or residue name // therefore mean 'any sequence number' or 'any residue name', // correspondingly (same as a wildcard). There should be no // spaces in ID except for leading spaces; any following space will // terminate parsing. The followings are perfectly valid IDs: // 27(ALA).A (residue 27A ALA) // 27().A (residue 27A) // 27(*).A (same as above) // 27.A (same as above) // 27 (residue 27) // 27(). (same as above) // (ALA) (any ALA without insertion code) // (ALA). (same as above) // (ALA).* (any ALA) // *(ALA).* (any ALA) // .A (any residue with insertion code A) // *(*).A (same as above) // *(*).* (any residue) // * (any residue with no insertion code) int CheckIDS ( cpstr ID ); // -------------------- Extracting atoms ---------------------- int GetNumberOfAtoms (); int GetNumberOfAtoms ( bool countTers ); PAtom GetAtom ( const AtomName aname, const Element elname=NULL, const AltLoc aloc=cpstr("") ); PAtom GetAtom ( int atomNo ); void GetAtomTable ( PPAtom & atomTable, int & NumberOfAtoms ); // GetAtomTable1(..) returns atom table without TER atoms and // without NULL atom pointers. NumberOfAtoms returns the actual // number of atom pointers in atomTable. // atomTable is allocated withing the function. If it was // not set to NULL before calling the function, the latter will // attempt to deallocate it first. // The application is responsible for deleting atomTable, // however it must not touch atom pointers, i.e. use simply // "delete[] atomTable;". Never pass atomTable from GetAtomTable() // into this function, unless you set it to NULL before doing that. void GetAtomTable1 ( PPAtom & atomTable, int & NumberOfAtoms ); // --------------------- Deleting atoms ----------------------- int DeleteAtom ( const AtomName aname, const Element elname=NULL, const AltLoc aloc=cpstr("") ); int DeleteAtom ( int atomNo ); int DeleteAllAtoms(); // DeleteAltLocs() leaves only alternative location with maximal // occupancy, if those are equal or unspecified, the one with // "least" alternative location indicator. // The function returns the number of deleted atoms. The atom // table remains untrimmed, so that nAtoms are wrong until that // is done. Tables are trimmed by FinishStructEdit() or // explicitely. int DeleteAltLocs (); void TrimAtomTable (); // ---------------------- Adding atoms ------------------------ // AddAtom(..) adds atom to the residue. If residue is associated // with a coordinate hierarchy, and atom 'atm' is not, the latter // is checked in automatically. If atom 'atm' belongs to any // coordinate hierarchy (even though that of the residue), it is // *copied* rather than simply taken over, and is checked in. // If residue is not associated with a coordinate hierarchy, all // added atoms will be checked in automatically once the residue // is checked in. int AddAtom ( PAtom atm ); // InsertAtom(..) inserts atom into the specified position of // the residue. If residue is associated with a coordinate // hierarchy, and atom 'atm' is not, the latter is checked in // automatically. If atom 'atm' belongs to any coordinate // hierarchy (even though that of the residue), it is *copied* // rather than simply taken over, and is checked in. // If residue is not associated with a coordinate hierarchy, all // added atoms will be checked in automatically once the residue // is checked in. int InsertAtom ( PAtom atm, int position ); // This version inserts before the atom with given name. If such // name is not found, the atom is appended to the end. int InsertAtom ( PAtom atm, const AtomName aname ); // -------------------------------------------------------------- void ApplyTransform ( mat44 & TMatrix ); // transforms all // coordinates by // multiplying with // matrix TMatrix void MaskAtoms ( PMask Mask ); void UnmaskAtoms ( PMask Mask ); // ------- user-defined data handlers int PutUDData ( int UDDhandle, int iudd ); int PutUDData ( int UDDhandle, realtype rudd ); int PutUDData ( int UDDhandle, cpstr sudd ); int GetUDData ( int UDDhandle, int & iudd ); int GetUDData ( int UDDhandle, realtype & rudd ); int GetUDData ( int UDDhandle, pstr sudd, int maxLen ); int GetUDData ( int UDDhandle, pstr & sudd ); bool isMainchainHBond ( PResidue res ); void Copy ( PResidue res ); void write ( io::RFile f ); void read ( io::RFile f ); protected : int AtmLen; // length of atom array bool Exclude; // used internally void InitResidue (); void FreeMemory (); int _AddAtom ( PAtom atm ); int _ExcludeAtom ( int kndex ); // 1: residue gets empty, // 0 otherwise void _copy ( PResidue res ); void _copy ( PResidue res, PPAtom atm, int & atom_index ); void ExpandAtomArray ( int nAdd ); void CheckInAtoms (); }; extern realtype BondAngle ( PAtom A, PAtom B, PAtom C ); } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_io_stream.cpp0000664000175000017500000000741412401105774014137 00000000000000// $Id: mmdb_io_stream.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 11.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : Stream_ // ~~~~~~~~~ // **** Classes : mmdb::io::Stream ( Basic Stream Class ) // ~~~~~~~~~ // // (C) E. Krissinel 1995-2013 // // ================================================================= // #include "mmdb_io_stream.h" namespace mmdb { namespace io { // ========================== CStream =========================== // Each streamable class should be derived from Stream // and have constructor Class(PStream & Object), which should // initialize all memory of the class, and virtual functions // read(..) and write(..) (see below). Constructor Class(PStream&) // must not touch the Object variable. This constructor is used // only once just before read(..) function. It is assumed that // read/write functions of Class provide storage/reading of // all vital data. Function read(..) must read data in exactly // the same way as function write(..) stores it. // For using Class in streams, three following functions should // be supplied: // // 1. // void StreamWrite ( RFile f, RPClass Object ) { // StreamWrite ( f,(PStream)PClass ); // } // // 2. // PCStream ClassInit ( RPStream Object ) { // return (PStream)(new Class(Object)); // } // // 3. // void StreamRead ( RFile f, RPClass Object ) { // StreamRead_ ( f,(PStream)Object,ClassInit ); // } // // All these functions are automatically generated by macros // DefineStreamFunctions(CClass) -- in the header -- and // MakeStreamFunctions(CClass) -- in the implementation body. // Then CClass may be streamed in/out using functions #1 and #3. // StreamRead will return NULL for Object if it was not // in the stream. If Object existed before StreamRead(..) but // was not found in the stream, it will be disposed. void StreamRead_ ( RFile f, RPStream Object, InitStreamObject Init ) { int i; f.ReadInt ( &i ); if (i) { if (!Object) Object = Init(Object); //Object = new CStream ( Object ); Object->read ( f ); } else { if (Object) delete Object; Object = NULL; } } void StreamWrite_ ( RFile f, RPStream Object ) { int i; if (Object) { i = 1; f.WriteInt ( &i ); Object->write ( f ); } else { i = 0; f.WriteInt ( &i ); } } MakeStreamFunctions(Stream) } } mmdb2-2.0.5/mmdb2/mmdb_model.h0000664000175000017500000011371312571573314012731 00000000000000// $Id: mmdb_model.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 10.05.15 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_Model // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::HetCompound ( description of het compounds ) // ~~~~~~~~~ mmdb::HetCompounds (HETNAM, HETSYN, FORMULA records) // mmdb::SSContainer (container for helixes and turns) // mmdb::Helix ( helix info ) // mmdb::Strand ( strand info ) // mmdb::Sheet ( sheet info ) // mmdb::Sheets ( container for sheets ) // mmdb::Turn ( turn info ) // mmdb::LinkContainer ( container for link data ) // mmdb::Link ( link data ) // mmdb::LinkRContainer ( container for refmac link ) // mmdb::LinkR ( link data ) // mmdb::CisPepContainer ( container for CisPep data ) // mmdb::CisPep ( CisPep data ) // mmdb::Model ( PDB model ) // // Copyright (C) E. Krissinel 2000-2015 // // ================================================================= // #ifndef __MMDB_Model__ #define __MMDB_Model__ #include "mmdb_io_stream.h" #include "mmdb_utils.h" #include "mmdb_chain.h" #include "mmdb_defs.h" namespace mmdb { // ==================== HetCompound ======================= DefineClass(HetCompound); DefineStreamFunctions(HetCompound); class HetCompound : public io::Stream { public : ResName hetID; // Het identifiers, right-justified pstr comment; int nSynonyms; psvector hetSynonym; // synonyms int compNum; // component number char wc; // '*' for water, otherwise space pstr Formula; // formulas HetCompound ( cpstr HetName ); HetCompound ( io::RPStream Object ); ~HetCompound(); void AddKeyWord ( cpstr W, bool Closed ); void HETNAM_PDBDump ( io::RFile f ); void HETSYN_PDBDump ( io::RFile f ); void FORMUL_PDBDump ( io::RFile f ); void FormComString ( pstr & F ); void FormSynString ( pstr & F ); void FormForString ( pstr & F ); void Copy ( PHetCompound hetCompound ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitHetCompound ( cpstr HetName ); void FreeMemory (); }; // ==================== SSContainer ====================== DefineClass(SSContainer); DefineStreamFunctions(SSContainer); class SSContainer : public ClassContainer { public : SSContainer () : ClassContainer() {} SSContainer ( io::RPStream Object ) : ClassContainer ( Object ) {} ~SSContainer () {} PContainerClass MakeContainerClass ( int ClassID ); }; // ==================== Helix ============================ DefineClass(Helix); DefineStreamFunctions(Helix); class Helix : public ContainerClass { public : int serNum; // serial number HelixID helixID; // helix ID ResName initResName; // name of the helix's initial residue ChainID initChainID; // chain ID for the chain containing the helix int initSeqNum; // sequence number of the initial residue InsCode initICode; // insertion code of the initial residue ResName endResName; // name of the helix's terminal residue ChainID endChainID; // chain ID for the chain containing the helix int endSeqNum; // sequence number of the terminal residue InsCode endICode; // insertion code of the terminal residue int helixClass; // helix class pstr comment; // comment about the helix int length; // length of the helix Helix (); Helix ( cpstr S ); Helix ( io::RPStream Object ); ~Helix(); void PDBASCIIDump ( pstr S, int N ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_Helix; } void Copy ( PContainerClass Helix ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitHelix(); }; // ==================== Strand ============================ DefineClass(Strand); DefineStreamFunctions(Strand); class Strand : public io::Stream { public : StrandID sheetID; // sheet ID int strandNo; // strand number ResName initResName; // name of the strand's initial residue ChainID initChainID; // chain ID of initial residue in the strand int initSeqNum; // sequence number of the initial residue InsCode initICode; // insertion code of the initial residue ResName endResName; // name of the strand's terminal residue ChainID endChainID; // chain ID of terminal residue in the strand int endSeqNum; // sequence number of the terminal residue InsCode endICode; // insertion code of the terminal residue int sense; // sense of strand with respect to previous // strand AtomName curAtom; // registration; atom name in current strand ResName curResName; // registration; residue name in current // strand ChainID curChainID; // registration; chain ID in current strand int curResSeq; // registration; res-e seq numb in current // strand InsCode curICode; // registration; ins code in current strand AtomName prevAtom; // registration; atom name in previous strand ResName prevResName; // registration; residue name in previous // strand ChainID prevChainID; // registration; chain ID in previous strand int prevResSeq; // registration; res-e seq numb in previous // strand InsCode prevICode; // registration; ins code in previous strand Strand (); Strand ( io::RPStream Object ); ~Strand(); void PDBASCIIDump ( pstr S ); void MakeCIF ( mmcif::PData CIF ); ERROR_CODE ConvertPDBASCII ( cpstr S ); int GetCIF ( mmcif::PData CIF, cpstr sheet_id ); void Copy ( PStrand Strand ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitStrand(); }; // ==================== Sheet ============================ DefineClass(Sheet); DefineStreamFunctions(Sheet); class Sheet : public io::Stream { public : SheetID sheetID; // sheet ID int nStrands; // number of strands in the sheet PPStrand strand; // array of strands Sheet (); Sheet ( io::RPStream Object ); ~Sheet(); void FreeMemory(); void OrderSheet(); void PDBASCIIDump ( io::RFile f ); void MakeCIF ( mmcif::PData CIF ); ERROR_CODE ConvertPDBASCII ( cpstr S ); int GetCIF ( mmcif::PData CIF ); void Copy ( PSheet sheet ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitSheet (); void CIFFindStrands ( mmcif::PData CIF, cpstr Category ); void TryStrand ( int strand_no ); int GetStrand ( int strand_no ); }; // ==================== Sheets ============================ DefineClass(Sheets); DefineStreamFunctions(Sheets); class Sheets : public io::Stream { public : int nSheets; PPSheet sheet; Sheets (); Sheets ( io::RPStream Object ); ~Sheets(); void FreeMemory(); void PDBASCIIDump ( io::RFile f ); void MakeCIF ( mmcif::PData CIF ); ERROR_CODE ConvertPDBASCII ( cpstr S ); int GetCIF ( mmcif::PData CIF ); void Copy ( PSheets Sheets ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitSheets (); void CIFFindSheets ( mmcif::PData CIF, cpstr Category ); }; // ==================== Turn ============================ DefineClass(Turn); DefineStreamFunctions(Turn); class Turn : public ContainerClass { public : int serNum; // serial number TurnID turnID; // turn ID ResName initResName; // name of the turn's initial residue ChainID initChainID; // chain ID for the chain containing the turn int initSeqNum; // sequence number of the initial residue InsCode initICode; // insertion code of the initial residue ResName endResName; // name of the turn's terminal residue ChainID endChainID; // chain ID for the chain containing the turn int endSeqNum; // sequence number of the terminal residue InsCode endICode; // insertion code of the terminal residue pstr comment; // comment about the helix Turn (); Turn ( cpstr S ); Turn ( io::RPStream Object ); ~Turn(); void PDBASCIIDump ( pstr S, int N ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_Turn; } void Copy ( PContainerClass turn ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitTurn(); }; // ==================== HetCompounds ======================= DefineClass(HetCompounds); DefineStreamFunctions(HetCompounds); class HetCompounds : public io::Stream { public : int nHets; PPHetCompound hetCompound; HetCompounds (); HetCompounds ( io::RPStream Object ); ~HetCompounds(); void FreeMemory (); void PDBASCIIDump ( io::RFile f ); void ConvertHETNAM ( cpstr S ); void ConvertHETSYN ( cpstr S ); void ConvertFORMUL ( cpstr S ); void MakeCIF ( mmcif::PData CIF ); ERROR_CODE GetCIF ( mmcif::PData CIF ); void Copy ( PHetCompounds hetCompounds ); void write ( io::RFile f ); void read ( io::RFile f ); protected : bool Closed; void InitHetCompounds(); int AddHetName ( cpstr H ); }; // =================== LinkContainer ===================== DefineClass(LinkContainer); DefineStreamFunctions(LinkContainer); class LinkContainer : public ClassContainer { public : LinkContainer () : ClassContainer() {} LinkContainer ( io::RPStream Object ) : ClassContainer ( Object ) {} ~LinkContainer () {} PContainerClass MakeContainerClass ( int ClassID ); }; // ==================== Link ============================ DefineClass(Link); DefineStreamFunctions(Link); class Link : public ContainerClass { public : AtomName atName1; // name of 1st linked atom AltLoc aloc1; // alternative location of 1st linked atom ResName resName1; // residue name of 1st linked atom ChainID chainID1; // chain ID of 1st linked atom int seqNum1; // sequence number of 1st linked atom InsCode insCode1; // insertion code of 1st linked atom AtomName atName2; // name of 2nd linked atom AltLoc aloc2; // alternative location of 2nd linked atom ResName resName2; // residue name of 2nd linked atom ChainID chainID2; // chain ID of 2nd linked atom int seqNum2; // sequence number of 2nd linked atom InsCode insCode2; // insertion code of 2nd linked atom int s1,i1,j1,k1; // sym id of 1st atom int s2,i2,j2,k2; // sym id of 2nd atom realtype dist; // link distance Link (); Link ( cpstr S ); Link ( io::RPStream Object ); ~Link(); void PDBASCIIDump ( pstr S, int N ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_Link; } void Copy ( PContainerClass link ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitLink(); }; // =================== LinkRContainer ==================== DefineClass(LinkRContainer); DefineStreamFunctions(LinkRContainer); class LinkRContainer : public ClassContainer { public : LinkRContainer () : ClassContainer() {} LinkRContainer ( io::RPStream Object ) : ClassContainer ( Object ) {} ~LinkRContainer () {} PContainerClass MakeContainerClass ( int ClassID ); }; // ==================== LinkR ============================ DefineClass(LinkR); DefineStreamFunctions(LinkR); /* Garib's LINK LYS A 27 PLP A 255 PLPLYS LINK MAN S 3 MAN S 4 BETA1-4 LINK C6 BBEN B 1 O1 BMAF S 2 BEN-MAF LINK OE2 AGLU A 320 C1 AMAF S 2 GLU-MAF LINK OE2 GLU A 67 1.895 ZN ZN R 5 GLU-ZN LINK NE2 HIS A 71 2.055 ZN ZN R 5 HIS-ZN LINK O ARG A 69 2.240 NA NA R 9 ARG-NA Coot's LINKR O VAL C 103 NA NA C 401 VAL-NA LINKR OD1 ASP D 58 NA NA D 401 ASP-NA LINKR O ALA D 97 NA NA D 401 ALA-NA LINKR OG1 THR D 99 NA NA D 401 THR-NA LINKR O SER D 101 NA NA D 401 SER-NA LINKR O VAL D 103 NA NA D 401 VAL-NA PDB's LINK O GLY A 49 NA NA A6001 1555 1555 2.98 LINK OG1 THR A 51 NA NA A6001 1555 1555 2.72 LINK OD2 ASP A 66 NA NA A6001 1555 1555 2.72 LINK NE ARG A 68 NA NA A6001 1555 1555 2.93 LINK NE ARG A 68 NA NA A6001 1555 1555 2.93 LINK C21 2EG A 7 C22 2EG B 19 1555 1555 1.56 */ class LinkR : public ContainerClass { public : LinkRID linkRID; // link name AtomName atName1; // name of 1st linked atom AltLoc aloc1; // alternative location of 1st linked atom ResName resName1; // residue name of 1st linked atom ChainID chainID1; // chain ID of 1st linked atom int seqNum1; // sequence number of 1st linked atom InsCode insCode1; // insertion code of 1st linked atom AtomName atName2; // name of 2nd linked atom AltLoc aloc2; // alternative location of 2nd linked atom ResName resName2; // residue name of 2nd linked atom ChainID chainID2; // chain ID of 2nd linked atom int seqNum2; // sequence number of 2nd linked atom InsCode insCode2; // insertion code of 2nd linked atom realtype dist; // link distance LinkR (); LinkR ( cpstr S ); LinkR ( io::RPStream Object ); ~LinkR(); void PDBASCIIDump ( pstr S, int N ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_LinkR; } void Copy ( PContainerClass LinkR ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitLinkR(); }; // =================== CisPepContainer ===================== DefineClass(CisPepContainer); DefineStreamFunctions(CisPepContainer); class CisPepContainer : public ClassContainer { public : CisPepContainer () : ClassContainer() {} CisPepContainer ( io::RPStream Object ) : ClassContainer ( Object ) {} ~CisPepContainer () {} PContainerClass MakeContainerClass ( int ClassID ); }; // ===================== CisPep =========================== DefineClass(CisPep); DefineStreamFunctions(CisPep); class CisPep : public ContainerClass { public : int serNum; // record serial number ResName pep1; // residue name ChainID chainID1; // chain identifier 1 int seqNum1; // residue sequence number 1 InsCode icode1; // insertion code 1 ResName pep2; // residue name 2 ChainID chainID2; // chain identifier 2 int seqNum2; // residue sequence number 2 InsCode icode2; // insertion code 2 int modNum; // model number realtype measure; // measure of the angle in degrees. CisPep (); CisPep ( cpstr S ); CisPep ( io::RPStream Object ); ~CisPep(); void PDBASCIIDump ( pstr S, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); CLASS_ID GetClassID () { return ClassID_CisPep; } void Copy ( PContainerClass cisPep ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitCisPep(); }; // ==================== Model =============================== enum SSE_RC { SSERC_Ok = 0, SSERC_noResidues = 1, SSERC_noAminoacids = 2, SSERC_noSSE = 3 }; enum SORT_CHAIN_DIR { SORT_CHAIN_ChainID_Asc = 0, SORT_CHAIN_ChainID_Desc = 1 }; DefineFactoryFunctions(Model); class Model : public ProModel { friend class Manager; friend class BondManager; friend class SelManager; friend class CoorManager; friend class Root; friend class Chain; friend class Residue; friend class Atom; public : Model (); // SetMMDBFile() MUST be used after this constructor! Model ( PManager MMDBF, int serialNum ); Model ( io::RPStream Object ); ~Model(); void SetMMDBManager ( PManager MMDBM, int serialNum ); PManager GetCoordHierarchy() { return manager; } // GetChainCreate() returns pointer on chain, whose identifier // is given in chID. If such a chain is absent in the model, // it is created. If enforceUniqueChainID is true and chain with // the same first letter in chain ID already exists in the model, // then the new chain ID will be appended with a serial number // in order to keep it unique. The model will contain chains like // A, A0, A1, A2, ... in such cases. PChain GetChainCreate ( const ChainID chID, bool enforceUniqueChainID ); // CreateChain() creates a new chain with chain ID regardless // the presence of same-ID chains in the model. This function // was introduced only for compatibility with older CCP4 // applications and using it in any new developments should be // strictly discouraged. PChain CreateChain ( const ChainID chID ); cpstr GetEntryID (); void SetEntryID ( const IDCode idCode ); int GetSerNum (); // returns the model's serial number cpstr GetModelID ( pstr modelID ); // returns "/mdl" int GetNumberOfModels (); // returns TOTAL number of models int GetNumberOfAtoms ( bool countTers ); // returns number // of atoms in the model int GetNumberOfResidues(); // returns number of residues in // the model // ---------------- Extracting chains -------------------------- int GetNumberOfChains(); // returns number of chains in the model bool GetNewChainID ( ChainID chID, int length=1 ); // GetChain() returns pointer on chain, whose identifier // is given in chID. If such a chain is absent in the model, // returns NULL. PChain GetChain ( const ChainID chID ); PChain GetChain ( int chainNo ); // returns chainNo-th chain // in the model; // 0<=chainNoindex-1; atom[]->index // is assigned automatically. void MoveChain ( PChain & m_chain, PPAtom m_atom, PPAtom atom, int & atom_index, int chain_ext ); void GetAIndexRange ( int & i1, int & i2 ); void MaskAtoms ( PMask mask ); void MaskResidues ( PMask mask ); void MaskChains ( PMask mask ); void UnmaskAtoms ( PMask mask ); void UnmaskResidues ( PMask mask ); void UnmaskChains ( PMask mask ); // ---- Getting Secondary Structure Elements int GetNumberOfHelices (); int GetNumberOfSheets (); PHelix GetHelix ( int serialNum ); // 1<=serNum<=NofHelices void GetSheetID ( int serialNum, SheetID sheetID ); // '\0' for none PSheet GetSheet ( int serialNum ); //1<=serNum<=NofSheets PSheet GetSheet ( const SheetID sheetID ); // NULL for none int GetNumberOfStrands ( int sheetSerNum ); int GetNumberOfStrands ( const SheetID sheetID ); PStrand GetStrand ( int sheetSerNum, int strandSerNum ); PStrand GetStrand ( const SheetID sheetID, int strandSerNum ); inline PSSContainer GetHelices() { return &helices; } inline PSheets GetSheets () { return &sheets; } void RemoveSecStructure(); int CalcSecStructure ( bool flagBulge=true, int aminoSelHnd=-1 ); // int CalcSecStructure ( bool flagBulge=true ); PHetCompounds GetHetInfo() { return &hetCompounds; } void RemoveHetInfo (); // ---- Working Links int GetNumberOfLinks (); PLink GetLink ( int serialNum ); // 1<=serNum<=NofLinks PLinkContainer GetLinks() { return &links; } void RemoveLinks(); void AddLink ( PLink link ); // ---- Working Refmac Links int GetNumberOfLinkRs (); PLinkR GetLinkR ( int serialNum ); // 1<=serNum<=NofLinks PLinkRContainer GetLinkRs() { return &linkRs; } void RemoveLinkRs(); void AddLinkR ( PLinkR linkR ); // ---- Working CisPeps int GetNumberOfCisPeps(); PCisPep GetCisPep ( int CisPepNum ); PCisPepContainer GetCisPeps() { return &cisPeps; } void RemoveCisPeps(); void AddCisPep ( PCisPep cisPep ); void ApplyTransform ( mat44 & TMatrix ); // transforms all // coordinates by multiplying // with matrix TMatrix bool isInSelection ( int selHnd ); // ------- user-defined data handlers int PutUDData ( int UDDhandle, int iudd ); int PutUDData ( int UDDhandle, realtype rudd ); int PutUDData ( int UDDhandle, cpstr sudd ); int GetUDData ( int UDDhandle, int & iudd ); int GetUDData ( int UDDhandle, realtype & rudd ); int GetUDData ( int UDDhandle, pstr sudd, int maxLen ); int GetUDData ( int UDDhandle, pstr & sudd ); void Copy ( PModel model ); void CopyHets ( PModel model ); void CopySecStructure ( PModel model ); void CopyLinks ( PModel model ); void CopyLinkRs ( PModel model ); void CopyCisPeps ( PModel model ); void write ( io::RFile f ); void read ( io::RFile f ); protected : int serNum; // the model serial number PManager manager; // pointer to mmdbmanager class HetCompounds hetCompounds; // information on heterocompounds SSContainer helices; // information on helices Sheets sheets; // information on sheets SSContainer turns; // information on turns LinkContainer links; // information on links LinkRContainer linkRs; // information on refmac links CisPepContainer cisPeps; // information on cispeps int nChains; // number of chains int nChainsAlloc; // actual length of Chain[] PPChain chain; // array of chains bool Exclude; // used internally void InitModel (); void FreeMemory (); void ExpandChainArray ( int nOfChains ); ERROR_CODE GetCIFPSClass ( mmcif::PData CIF, int ClassID ); // _ExcludeChain(..) excludes (but does not dispose!) a chain // from the model. Returns 1 if the chain gets empty and 0 // otherwise. int _ExcludeChain ( const ChainID chainID ); // _copy(PModel) does not copy atoms! -- not for use in // applications void _copy ( PModel Model ); // _copy(PModel,PPAtom,int&) does copy atoms into array 'atom' // starting from position atom_index. 'atom' should be able to // accept all new atoms - no checks on the length of 'atom' // is being made. This function should not be used in applications. void _copy ( PModel Model, PPAtom atom, int & atom_index ); void CheckInAtoms (); }; } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_selmngr.cpp0000664000175000017500000034453112601171753013632 00000000000000// $Id: mmdb_selmngr.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 15.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : mmdb_selmngr // ~~~~~~~~~ // Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::Manager ( MMDB atom selection manager ) // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include #include #include "mmdb_selmngr.h" namespace mmdb { const int ANY_RES = MinInt4; // ==================== SelManager ===================== SelManager::SelManager() : CoorManager() { InitSelManager(); } SelManager::SelManager ( io::RPStream Object ) : CoorManager(Object) { InitSelManager(); } SelManager::~SelManager() { DeleteAllSelections(); } void SelManager::ResetManager() { CoorManager::ResetManager(); DeleteAllSelections(); InitSelManager (); } void SelManager::InitSelManager() { nSelections = 0; // number of selections mask = NULL; // vector of selections selType = NULL; // vector of selection types nSelItems = NULL; // numbers of selected items selection = NULL; // vector of selected items } // ------------------------ Selection ----------------------------- int SelManager::NewSelection() { PMask M; PPMask Mask1; PPMask * Selection1; ivector nSelItems1; SELECTION_TYPE * SelType1; int i,l; M = new Mask(); M->NewMask ( mask,nSelections ); i = 0; while (i=nSelections) { l = nSelections+10; Mask1 = new PMask [l]; Selection1 = new PPMask[l]; nSelItems1 = new int[l]; SelType1 = new SELECTION_TYPE[l]; for (i=0;i0) && (selHnd<=nSelections)) { k = selHnd-1; if (mask[k]) return selType[k]; } return STYPE_INVALID; } void SelManager::DeleteSelection ( int selHnd ) { int i,k; if ((selHnd>0) && (selHnd<=nSelections)) { k = selHnd-1; if (mask[k]) { for (i=0;iRemoveMask ( mask[k] ); // for (i=0;iRemoveMask ( mask[k] ); delete mask[k]; } mask[k] = NULL; if (selection[k]) delete[] selection[k]; selection[k] = NULL; nSelItems[k] = 0; selType [k] = STYPE_UNDEFINED; } } PMask SelManager::GetSelMask ( int selHnd ) { if ((selHnd>0) && (selHnd<=nSelections)) return mask[selHnd-1]; else return NULL; } void SelManager::DeleteAllSelections() { PResidue res ,res1; PChain chain,chain1; PModel model,model1; int i; if (mask) { res = NULL; chain = NULL; model = NULL; if (atom) for (i=0;iClearMask(); res1 = atom[i]->GetResidue(); if (res1!=res) { res = res1; res->ClearMask(); chain1 = res->GetChain(); if (chain1!=chain) { chain = chain1; chain->ClearMask(); model1 = chain->GetModel(); if (model1!=model) { model = model1; model->ClearMask(); } } } } for (i=0;inSelections) || (nAtoms<=0)) return; k = selHnd-1; sk = sKey; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = STYPE_ATOM; else if (selType[k]!=STYPE_ATOM) return; switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; if (nsel<=0) return; break; case SKEY_XAND: nsel = 0; break; } if ((iSer1==0) && (iSer2==0)) { for (i=0;iTer) SelectAtom ( atom[i],k,sk,nsel ); } } else { if (iSer1<=iSer2) { s1 = iSer1; s2 = iSer2; } else { s1 = iSer2; s2 = iSer1; } // for a very general use, we allow the serial number // to differ from the atom's index, although this is // against PDB format. Therefore we apply here the most // primitive and less efficient way of selection for (i=0;iTer) { if ((s1<=atom[i]->serNum) && (atom[i]->serNum<=s2)) SelectAtom ( atom[i],k,sk,nsel ); else if (sk==SKEY_AND) atom[i]->RemoveMask ( mask[k] ); } } } MakeSelIndex ( selHnd,STYPE_ATOM,nsel ); } void SelManager::SelectAtoms ( int selHnd, ivector asn, int nsn, SELECTION_KEY selKey ) { // SelectAtoms(..) selects atoms with serial numbers given in // vector asn[0..nsn-1]. QuickSort QS; ivector asn1; int i,k,nsn1,j,j1,j2, sn,nsel; SELECTION_KEY sk; if ((selHnd<=0) || (selHnd>nSelections) || (nAtoms<=0)) return; k = selHnd-1; sk = selKey; if ((selType[k]==STYPE_UNDEFINED) || (selKey==SKEY_NEW)) selType[k] = STYPE_ATOM; else if (selType[k]!=STYPE_ATOM) return; switch (selKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; if (nsel<=0) return; break; case SKEY_XAND: nsel = 0; break; } GetVectorMemory ( asn1,nsn,0 ); for (i=0;iTer) { sn = atom[i]->serNum; if ((asn1[0]<=sn) && (sn<=asn1[nsn1])) { // binary search j1 = 0; j2 = nsn1; do { j = (j1+j2)/2; if (snasn1[j]) j1 = j; else j1 = j2; } while (j1RemoveMask ( mask[k] ); } else if (sk==SKEY_AND) atom[i]->RemoveMask ( mask[k] ); } } FreeVectorMemory ( asn1,0 ); MakeSelIndex ( selHnd,STYPE_ATOM,nsel ); } void SelManager::UnselectAtoms ( int selHnd, int iSer1, int iSer2 ) { // UnselectAtoms(..) clears the specified mask for atoms in // the serial number range of iSer1 to iSer2. If iSer1=iSer2=0 // then all atoms are cleared of the specified mask. If selHnd // is set to 0, then the atoms are cleared of any mask. int i,s1,s2,k; if ((selHnd<=nSelections) && (nAtoms>0)) { k = selHnd-1; if (selType[k]==STYPE_UNDEFINED) selType[k] = STYPE_ATOM; else if (selType[k]!=STYPE_ATOM) return; if ((iSer1==0) && (iSer2==0)) { if (k<0) { for (i=0;iClearMask(); } else { for (i=0;iRemoveMask ( mask[k] ); } } else { if (iSer1<=iSer2) { s1 = iSer1; s2 = iSer2; } else { s1 = iSer2; s2 = iSer1; } // for a very general use, we allow the serial number // to differ from the atom's index, although this is // against PDB format. Therefore we apply here the most // primitive and less efficient way of selection if (k<0) { for (i=0;iserNum) && (atom[i]->serNum<=s2)) atom[i]->ClearMask(); } } else { for (i=0;iserNum) && (atom[i]->serNum<=s2)) atom[i]->RemoveMask ( mask[k] ); } } } MakeSelIndex ( selHnd,STYPE_ATOM,-1 ); } } pstr MakeList ( cpstr S ) { // makes the list of selecting items: // 1st character - special use, // then each item from S embraced by commas pstr L; int i,j; i = 0; while (S[i]==' ') i++; if (S[i]!='*') { // compile a searchable list L = new char[strlen(S)+5]; if (S[i]=='!') { L[0] = '!'; i++; } else L[0] = ' '; if (strchr(S,'[')) L[1] = '"'; else L[1] = ' '; L[2] = ','; j = 3; while (S[i]) { while (S[i]==' ') i++; if (S[i]=='[') { while (S[i] && (S[i]!=']')) L[j++] = S[i++]; L[j++] = ']'; if (S[i]==']') i++; } else while (S[i] && (S[i]!=' ') && (S[i]!=',')) L[j++] = S[i++]; while (S[i]==' ') i++; L[j++] = ','; if (S[i]==',') { i++; if (!S[i]) L[j++] = ','; // blank chain ID at the end assumed } } if (j==3) L[j++] = ','; L[j] = char(0); } else L = NULL; return L; } bool MatchName ( pstr L, pstr N ) { char M[sizeof(maxMMDBName)+5]; int i,j; if (L) { i = 0; M[0] = ','; j = 1; while (N[i]) if (N[i]==' ') i++; else M[j++] = N[i++]; M[j++] = ','; M[j] = char(0); if (strstr(&(L[2]),M)) return (L[0]!='!'); else if (L[1]!='"') return (L[0]=='!'); else { strcpy ( M,",[" ); strcat ( M,N ); strcat ( M,"]," ); if (strstr(&(L[2]),M)) return (L[0]!='!'); else return (L[0]=='!'); } } else return true; } bool MatchCharge ( pstr L, PAtom atom ) { char N[100]; if (L) { if (atom->WhatIsSet & ASET_Charge) { sprintf ( N,"%+2i",mround(atom->charge) ); return MatchName ( L,N ); } else return false; } else return true; } void SelManager::SelectAtom ( int selHnd, PAtom A, SELECTION_KEY selKey, bool makeIndex ) { int i, k, nsel; SELECTION_KEY sk; if ((selHnd<=0) || (selHnd>nSelections)) return; k = selHnd-1; sk = selKey; if ((selType[k]==STYPE_UNDEFINED) || (selKey==SKEY_NEW)) selType[k] = STYPE_ATOM; else if (selType[k]!=STYPE_ATOM) return; switch (selKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : if (nSelItems[k]==0) return; nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; if (nsel<=0) return; break; case SKEY_XAND: nsel = 0; break; } SelectAtom ( A,k,sk,nsel); if (makeIndex) MakeSelIndex ( selHnd,STYPE_ATOM,nsel ); } void SelManager::SelectResidue ( int selHnd, PResidue Res, SELECTION_TYPE sType, SELECTION_KEY sKey, bool makeIndex ) { // Selects residue Res or all its atoms depending on selType PPAtom A; int i, k, nsel, nat; SELECTION_KEY sk; if ((selHnd<=0) || (selHnd>nSelections)) return; k = selHnd-1; sk = sKey; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = sType; else if (selType[k]!=sType) return; switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : if (nSelItems[k]==0) return; nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; if (nsel<=0) return; break; case SKEY_XAND: nsel = 0; break; } switch (sType) { case STYPE_ATOM : Res->GetAtomTable ( A,nat ); for (i=0;iTer) SelectAtom ( A[i],k,sk,nsel); } break ; case STYPE_RESIDUE : SelectObject ( Res,k,sk,nsel ); break ; default : ; } if (makeIndex) MakeSelIndex ( selHnd,sType,nsel ); } void SelManager::SelectChain ( int selHnd, PChain Chain, SELECTION_TYPE sType, SELECTION_KEY sKey, bool makeIndex ) { // Selects chain Chain or all its residues or atoms depending on selType PPAtom A; PPResidue Res; int i,j, k, nsel, nat,nres; SELECTION_KEY sk; if ((selHnd<=0) || (selHnd>nSelections)) return; k = selHnd-1; sk = sKey; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = sType; else if (selType[k]!=sType) return; switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : if (nSelItems[k]==0) return; nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; if (nsel<=0) return; break; case SKEY_XAND: nsel = 0; break; } switch (sType) { case STYPE_ATOM : Chain->GetResidueTable ( Res,nres ); for (i=0;iGetAtomTable ( A,nat ); for (j=0;jTer) SelectAtom ( A[j],k,sk,nsel); } } break ; case STYPE_RESIDUE : Chain->GetResidueTable ( Res,nres ); for (i=0;inSelections)) return; k = selHnd-1; sk = sKey; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = sType; else if (selType[k]!=sType) return; switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : if (nSelItems[k]==0) return; nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; if (nsel<=0) return; break; case SKEY_XAND: nsel = 0; break; } switch (sType) { case STYPE_ATOM : model->GetChainTable ( Chain,nch ); for (i=0;iGetResidueTable ( Res,nres ); for (j=0;jGetAtomTable ( A,nat ); for (n=0;nTer) SelectAtom ( A[n],k,sk,nsel); } } } break ; case STYPE_RESIDUE : model->GetChainTable ( Chain,nch ); for (i=0;iGetResidueTable ( Res,nres ); for (j=0;jGetChainTable ( Chain,nch ); for (i=0;inSelections)) return 0; k = selHnd-1; if (selType[k]==STYPE_UNDEFINED) return 0; MakeSelIndex ( selHnd,selType[k],-1 ); return nSelItems[k]; } void SelManager::MakeAllSelIndexes() { int k; for (k=0;knSelections) || (nAtoms<=0)) return; modelSel = false; k = selHnd-1; sk = sKey; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = sType; else if (selType[k]!=sType) return; // if something goes wrong, sk should be assigned SKEY_OR if // selKey is set to SKEY_NEW or SKEY_OR below switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; if (nsel<=0) return; break; default : return; } selAND = (sKey==SKEY_AND); altLocs1 = NULL; if (altLocs) { if (strchr(altLocs,hetIndicator)) { CreateCopy ( altLocs1,altLocs ); DelSpaces ( altLocs1 ); aloc_l = strchr ( altLocs1,hetIndicator ); aloc_l[0] = ' '; if (aloc_l[1]) aloc_l[1] = ' '; // instead of comma else if (aloc_l!=altLocs1) { aloc_l--; aloc_l[0] = ' '; } DelSpaces ( altLocs1 ); aloc_l = MakeList ( altLocs1 ); } else aloc_l = MakeList ( altLocs ); } else aloc_l = MakeList ( altLocs ); chain_l = MakeList ( Chains ); res_l = MakeList ( RNames ); atom_l = MakeList ( ANames ); elem_l = MakeList ( Elements ); segm_l = MakeList ( Segments ); charge_l = MakeList ( Charges ); // noRes==true means no residue restrictions noRes = (ResNo1==ResNo2) && (ResNo1==ANY_RES) && (Ins1[0]==Ins2[0]) && (Ins1[0]=='*'); Occ = (occ1>=0.0) || (occ2>=0.0); Dist = (d0>0.0); d02 = d0*d0; m1 = iModel-1; if (m1>=0) m2 = m1+1; // will take only this model else { m1 = 0; // will take m2 = nModels; // all models } if (m1>=nModels) return; for (n=0;nnChains;c++) { chain = mdl->chain[c]; if (chain) { // again check for safety if (MatchName(chain_l,chain->chainID)) { // the chain has to be taken i = 0; if (!noRes) while (inResidues) { res = chain->residue[i]; if (res) { if ((res->seqNum==ResNo1) && MatchName(res_l,res->name) && ((Ins1[0]=='*') || (!strcmp(res->insCode,Ins1)))) break; else if (selAND) { if (sType==STYPE_ATOM) res->UnmaskAtoms ( mask[k] ); else if (sType==STYPE_RESIDUE) res->RemoveMask ( mask[k] ); } } i++; } while (inResidues) { res = chain->residue[i]; if (res) { resSel = false; // will be true on 1st sel-n in the res-e if (MatchName(res_l,res->name)) { for (j=0;jnAtoms;j++) { atom = res->atom[j]; if (atom) { if ((!atom->Ter) && MatchName(atom_l ,atom->name ) && MatchName(elem_l ,atom->element) && MatchName(aloc_l ,atom->altLoc ) && MatchName(segm_l ,atom->segID ) && MatchCharge(charge_l,atom ) && ((!altLocs1) || atom->Het)) { Sel = true; if (Occ) Sel = ((occ1<=atom->occupancy) && (atom->occupancy<=occ2)); if (Dist) { dx = atom->x - x0; dy = atom->y - y0; dz = atom->z - z0; Sel = Sel && ((dx*dx+dy*dy+dz*dz)<=d02); } } else Sel = false; if (Sel) { SelectObject ( sType,atom,k,sk,nsel ); resSel = true; chainSel = true; modelSel = true; } else if (selAND && (sType==STYPE_ATOM)) atom->RemoveMask ( mask[k] ); } if (resSel && (sType!=STYPE_ATOM)) break; } } else if (selAND && (sType==STYPE_ATOM)) res->UnmaskAtoms ( mask[k] ); if ((!resSel) && selAND && (sType==STYPE_RESIDUE)) res->RemoveMask ( mask[k] ); if (chainSel && (sType>STYPE_RESIDUE)) break; if (!noRes) { if ((res->seqNum==ResNo2) && ((Ins2[0]=='*') || (!strcmp(res->insCode,Ins2))) ) break; } } i++; } if (selAND) { if (sType==STYPE_ATOM) while (inResidues) { res = chain->residue[i]; if (res) res->UnmaskAtoms ( mask[k] ); i++; } if (sType==STYPE_RESIDUE) while (inResidues) { res = chain->residue[i]; if (res) res->RemoveMask ( mask[k] ); i++; } } } else if (selAND) switch (sType) { case STYPE_ATOM : chain->UnmaskAtoms ( mask[k] ); break; case STYPE_RESIDUE : chain->UnmaskResidues ( mask[k] ); break; case STYPE_CHAIN : chain->RemoveMask ( mask[k] ); break; default : ; } if ((!chainSel) && selAND && (sType==STYPE_CHAIN)) chain->RemoveMask ( mask[k] ); if (modelSel && (sType>STYPE_CHAIN)) break; } } } else if (selAND) switch (sType) { case STYPE_ATOM : mdl->UnmaskAtoms ( mask[k] ); break; case STYPE_RESIDUE : mdl->UnmaskResidues ( mask[k] ); break; case STYPE_CHAIN : mdl->UnmaskChains ( mask[k] ); break; default : ; } if ((!modelSel) && selAND && (sType==STYPE_MODEL)) mdl->RemoveMask ( mask[k] ); } } // release dynamic memory if (chain_l) delete[] chain_l; if (res_l) delete[] res_l; if (atom_l) delete[] atom_l; if (elem_l) delete[] elem_l; if (altLocs1) delete[] altLocs1; if (aloc_l) delete[] aloc_l; if (segm_l) delete[] segm_l; if (charge_l) delete[] charge_l; MakeSelIndex ( selHnd,STYPE_ATOM,nsel ); } void SelManager::SelectAtoms ( int selHnd, // must be obtained from NewSelection() int iModel, // model number; iModel=0 means // 'any models' cpstr Chains, // may be several chains "A,B,W"; // "*" means 'any chain' (in model) int ResNo1, // starting residue number cpstr Ins1, // starting residue insertion code; // "*" means 'any code' int ResNo2, // ending residue number. // ResNo1=ResNo2=ANY_RES means 'any // residue number' (in chain) cpstr Ins2, // ending residue insertion code // "*" means 'any code' cpstr RNames, // may be several residue names // "ALA,GLU,CIS"; "*" means 'any // residue name' cpstr ANames, // may be several names "CA,CB"; "*" // means 'any atom' (in residue) cpstr Elements, // may be several element types like // "H,C,O,CU"; "*" means 'any // element' cpstr altLocs, // may be several alternative // locations 'A,B'; "*" means 'any // alternative location' SELECTION_KEY sKey // selection key ) { Select ( selHnd,STYPE_ATOM,iModel,Chains,ResNo1,Ins1,ResNo2,Ins2, RNames,ANames,Elements,altLocs,sKey ); } int SelManager::Select ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX cpstr CID, // coordinate ID SELECTION_KEY sKey // selection key ) { InsCode insCode1,insCode2; pstr RNames; pstr ANames; pstr Elements; pstr altLocs; pstr Chains; int seqNum1 ,seqNum2; int iModel,l,RC; l = IMax(10,strlen(CID))+1; Chains = new char[l]; RNames = new char[l]; ANames = new char[l]; Elements = new char[l]; altLocs = new char[l]; if (strcmp(CID,"-all")) { RC = ParseSelectionPath ( CID,iModel,Chains,seqNum1,insCode1, seqNum2,insCode2,RNames,ANames, Elements,altLocs ); } else { iModel = 0; strcpy ( Chains,"*" ); seqNum1 = ANY_RES; seqNum2 = ANY_RES; strcpy ( insCode1,"*" ); strcpy ( insCode2,"*" ); strcpy ( RNames ,"*" ); strcpy ( ANames ,"*" ); strcpy ( Elements,"*" ); strcpy ( altLocs ,"" ); // only main conformation by default RC = 0; } if (!RC) { Select ( selHnd,sType,iModel,Chains,seqNum1,insCode1, seqNum2,insCode2,RNames,ANames,Elements,altLocs,sKey ); RC = 0; } delete[] Chains; delete[] RNames; delete[] ANames; delete[] Elements; delete[] altLocs; return RC; } void SelManager::Select ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX int iModel, // model number; iModel=0 means // 'any model' cpstr Chains, // may be several chains "A,B,W"; // "*" means 'any chain' (in model) int ResNo1, // starting residue number cpstr Ins1, // starting residue insertion code; // "*" means 'any code' int ResNo2, // ending residue number. // ResNo1=ResNo2=ANY_RES means 'any // residue number' (in chain) cpstr Ins2, // ending residue insertion code // "*" means 'any code' cpstr RNames, // may be several residue names // "ALA,GLU,CIS"; "*" means 'any // residue name' cpstr ANames, // may be several names "CA,CB"; "*" // means 'any atom' (in residue) cpstr Elements, // may be several element types like // "H,C,O,CU"; "*" means 'any element' cpstr altLocs, // may be several alternative // locations 'A,B'; "*" means 'any // alternative location' SELECTION_KEY sKey // selection key ) { PModel mdl; PChain chain; PResidue res; PAtom atom; pstr chain_l; pstr res_l; pstr atom_l; pstr elem_l; pstr altLocs1; pstr aloc_l; int i,j,k,n,m1,m2,c, nsel; bool noRes,modelSel,chainSel,resSel,selAND; SELECTION_KEY sk; if ((selHnd<=0) || (selHnd>nSelections) || (nAtoms<=0)) return; modelSel = false; k = selHnd-1; sk = sKey; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = sType; else if (selType[k]!=sType) return; // if something goes wrong, sk should be assigned SKEY_OR if // selKey is set to SKEY_NEW or SKEY_OR below switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; if (nsel<=0) return; break; default : return; } selAND = (sKey==SKEY_AND); altLocs1 = NULL; if (altLocs) { if (strchr(altLocs,hetIndicator)) { CreateCopy ( altLocs1,altLocs ); DelSpaces ( altLocs1 ); aloc_l = strchr ( altLocs1,hetIndicator ); aloc_l[0] = ' '; if (aloc_l[1]) aloc_l[1] = ' '; // instead of comma else if (aloc_l!=altLocs1) { aloc_l--; aloc_l[0] = ' '; } DelSpaces ( altLocs1 ); aloc_l = MakeList ( altLocs1 ); } else aloc_l = MakeList ( altLocs ); } else aloc_l = MakeList ( altLocs ); chain_l = MakeList ( Chains ); res_l = MakeList ( RNames ); atom_l = MakeList ( ANames ); elem_l = MakeList ( Elements ); // noRes==true means no residue restrictions noRes = (ResNo1==ResNo2) && (ResNo1==ANY_RES) && (Ins1[0]=='*') && (Ins2[0]=='*'); m1 = iModel-1; if (m1>=0) m2 = m1+1; // will take only this model else { m1 = 0; // will take m2 = nModels; // all models } if (m1>=nModels) return; for (n=0;nnChains;c++) { chain = mdl->chain[c]; if (chain) { // again check for safety chainSel = false; // will be true on 1st sel-n in the chain if (MatchName(chain_l,chain->chainID)) { // the chain is to be taken i = 0; if (!noRes) // skip "leading" residues while (inResidues) { res = chain->residue[i]; if (res) { if ((res->seqNum==ResNo1) && MatchName(res_l,res->name) && ((Ins1[0]=='*') || (!strcmp(res->insCode,Ins1)))) break; else if (selAND) { if (sType==STYPE_ATOM) res->UnmaskAtoms ( mask[k] ); else if (sType==STYPE_RESIDUE) res->RemoveMask ( mask[k] ); } } i++; } while (inResidues) { res = chain->residue[i]; i++; if (res) { resSel = false; // will be true on 1st selection // in the residue if (MatchName(res_l,res->name)) { for (j=0;jnAtoms;j++) { atom = res->atom[j]; if (atom) { if ((!atom->Ter) && MatchName(atom_l,atom->name ) && MatchName(elem_l,atom->element) && MatchName(aloc_l,atom->altLoc ) && ((!altLocs1) || atom->Het)) { SelectObject ( sType,atom,k,sk,nsel ); resSel = true; chainSel = true; modelSel = true; } else if (selAND && (sType==STYPE_ATOM)) atom->RemoveMask ( mask[k] ); } if (resSel && (sType!=STYPE_ATOM)) break; } } else if (selAND && (sType==STYPE_ATOM)) res->UnmaskAtoms ( mask[k] ); if ((!resSel) && selAND && (sType==STYPE_RESIDUE)) res->RemoveMask ( mask[k] ); if (chainSel && (sType>STYPE_RESIDUE)) break; if (!noRes) { if ((res->seqNum==ResNo2) && ((Ins2[0]=='*') || (!strcmp(res->insCode,Ins2))) ) break; } } } if (selAND) { if (sType==STYPE_ATOM) while (inResidues) { res = chain->residue[i]; if (res) res->UnmaskAtoms ( mask[k] ); i++; } if (sType==STYPE_RESIDUE) while (inResidues) { res = chain->residue[i]; if (res) res->RemoveMask ( mask[k] ); i++; } } } else if (selAND) switch (sType) { case STYPE_ATOM : chain->UnmaskAtoms ( mask[k] ); break; case STYPE_RESIDUE : chain->UnmaskResidues ( mask[k] ); break; default : ; } if ((!chainSel) && selAND && (sType==STYPE_CHAIN)) chain->RemoveMask ( mask[k] ); if (modelSel && (sType>STYPE_CHAIN)) break; } } } else if (selAND) switch (sType) { case STYPE_ATOM : mdl->UnmaskAtoms ( mask[k] ); break; case STYPE_RESIDUE : mdl->UnmaskResidues ( mask[k] ); break; case STYPE_CHAIN : mdl->UnmaskChains ( mask[k] ); break; default : ; } if ((!modelSel) && selAND && (sType==STYPE_MODEL)) mdl->RemoveMask ( mask[k] ); } } // release dynamic memory if (chain_l) delete[] chain_l; if (res_l) delete[] res_l; if (atom_l) delete[] atom_l; if (elem_l) delete[] elem_l; if (altLocs1) delete[] altLocs1; if (aloc_l) delete[] aloc_l; MakeSelIndex ( selHnd,sType,nsel ); } void SelManager::Select ( int selHnd1, // destination, must be obtained // from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX int selHnd2, // source, must be obtained from // NewSelection() and have been // used for selection SELECTION_KEY sKey // selection key ) { // SKEY_XOR works only downward the hierarchy! PAtom atom; PResidue res; PChain chain; PModel model; int k1,k2,i,j,l,n,nsel; SELECTION_KEY sk; if ((selHnd1<=0) || (selHnd1>nSelections) || (selHnd2<=0) || (selHnd2>nSelections) || (nAtoms<=0)) return; k1 = selHnd1-1; k2 = selHnd2-1; sk = sKey; if ((selType[k1]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k1] = sType; else if (selType[k1]!=sType) return; if (selType[k2]==STYPE_UNDEFINED) return; switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k1] ); nSelItems[k1] = 0; sk = SKEY_OR; nsel = 0; break; case SKEY_OR : if (nSelItems[k1]==0) sk = SKEY_NEW; nsel = nSelItems[k1]; break; case SKEY_AND : if (nSelItems[k1]==0) return; sk = SKEY_XAND; nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k1]; break; case SKEY_CLR : nsel = nSelItems[k1]; if (nsel<=0) return; break; default : return; } switch (selType[k2]) { case STYPE_ATOM : for (i=0;iTer) SelectObject ( sType,atom,k1,sk,nsel ); } } break; case STYPE_RESIDUE : for (i=0;inAtoms;j++) { atom = res->atom[j]; if (atom) { if (!atom->Ter) SelectObject (atom,k1,sk,nsel); } } break; case STYPE_RESIDUE : //if (res->chain) SelectObject ( res,k1,sk,nsel ); break; case STYPE_CHAIN : if (res->chain) SelectObject ( res->chain,k1, sk,nsel ); break; case STYPE_MODEL : if (res->chain) { if (res->chain->model) SelectObject ( res->chain->model, k1,sk,nsel ); } default : ; } } break; case STYPE_CHAIN : for (i=0;inResidues;j++) { res = chain->residue[j]; if (res) for (l=0;lnAtoms;l++) { atom = res->atom[l]; if (atom) { if (!atom->Ter) SelectObject ( atom,k1, sk,nsel ); } } } break; case STYPE_RESIDUE : for (j=0;jnResidues;j++) { res = chain->residue[j]; if (res) SelectObject ( res,k1,sk,nsel ); } break; case STYPE_CHAIN : //if (chain->model) SelectObject ( chain,k1,sk,nsel ); break; case STYPE_MODEL : if (chain->model) SelectObject ( chain->model,k1, sk,nsel ); default : ; } } break; case STYPE_MODEL : for (i=0;inChains;j++) { chain = model->chain[j]; if (chain) for (l=0;lnResidues;l++) { res = chain->residue[l]; if (res) for (n=0;nnAtoms;n++) { atom = res->atom[n]; if (atom) { if (!atom->Ter) SelectObject ( atom,k1,sk,nsel ); } } } } break; case STYPE_RESIDUE : for (j=0;jnChains;j++) { chain = model->chain[j]; if (chain) for (l=0;lnResidues;l++) { res = chain->residue[j]; if (res) SelectObject ( res,k1,sk,nsel ); } } break; case STYPE_CHAIN : for (j=0;jnChains;j++) { chain = model->chain[j]; if (chain) SelectObject (chain,k1,sk,nsel); } break; case STYPE_MODEL : SelectObject ( model,k1,sk,nsel ); default : ; } } break; default : ; } if (sKey==SKEY_AND) for (i=0;iXadMask ( mask[k1] ); MakeSelIndex ( selHnd1,sType,nsel ); } void SelManager::SelectProperty ( int selHnd, // must be obtained from NewSelection() SELECTION_PROPERTY propKey, // property key SELECTION_TYPE sType, // selection type STYPE_XXXXX SELECTION_KEY sKey // selection key ) { PModel mdl; PChain chain; PResidue res; int i,k,selHnd1,nsel, m,c,r; bool doSelect; SELECTION_KEY sk; if ((selHnd<=0) || (selHnd>nSelections) || (nAtoms<=0)) return; k = selHnd-1; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = sType; else if (selType[k]!=sType) return; if (sType!=STYPE_RESIDUE) { selHnd1 = NewSelection(); if ((sKey==SKEY_AND) || (sKey==SKEY_CLR)) Select ( selHnd1,STYPE_RESIDUE,selHnd,SKEY_NEW ); } else selHnd1 = selHnd; k = selHnd1-1; selType[k] = STYPE_RESIDUE; sk = sKey; switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; sk = SKEY_OR; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : if (nSelItems[k]==0) return; sk = SKEY_XAND; nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; if (nsel<=0) return; break; default : return; } if ((sKey==SKEY_AND) || (sKey==SKEY_CLR)) { for (i=0;iisSolvent(); break; case SELPROP_Aminoacid : doSelect = res->isAminoacid(); break; case SELPROP_Nucleotide : doSelect = res->isNucleotide(); break; case SELPROP_Sugar : doSelect = res->isSugar(); break; case SELPROP_ModRes : doSelect = res->isModRes(); break; default : doSelect = false; } if (doSelect) SelectObject ( res,k,sk,nsel ); } } if (sKey==SKEY_AND) for (i=0;iXadMask ( mask[k] ); } else { for (m=0;mnChains;c++) { chain = mdl->chain[c]; if (chain) { for (r=0;rnResidues;r++) { res = chain->residue[r]; if (res) { switch (propKey) { case SELPROP_Solvent : doSelect = res->isSolvent(); break; case SELPROP_Aminoacid : doSelect = res->isAminoacid(); break; case SELPROP_Nucleotide : doSelect = res->isNucleotide(); break; case SELPROP_Sugar : doSelect = res->isSugar(); break; case SELPROP_ModRes : doSelect = res->isModRes(); break; default : doSelect = false; } if (doSelect) SelectObject ( res,k,sk,nsel ); } } } } } } } MakeSelIndex ( selHnd1,STYPE_RESIDUE,nsel ); if (sType!=STYPE_RESIDUE) { Select ( selHnd,sType,selHnd1,SKEY_NEW ); DeleteSelection ( selHnd1 ); } } void SelManager::SelectUDD ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX int UDDhandle, // UDD handle int selMin, // lower selection boundary int selMax, // upper selection boundary SELECTION_KEY sKey // selection key ) { PModel mdl; PChain chain; PResidue res; PAtom atom; int i,k,nsel,iudd, n,c,r,a; bool selAND; SELECTION_KEY sk; k = selHnd-1; sk = sKey; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = sType; else if (selType[k]!=sType) return; if ((selHnd<=0) || (selHnd>nSelections)) return; switch (sType) { case STYPE_ATOM : if ((UDDhandle & UDRF_ATOM)==0) return; break; case STYPE_RESIDUE : if ((UDDhandle & UDRF_RESIDUE)==0) return; break; case STYPE_CHAIN : if ((UDDhandle & UDRF_CHAIN)==0) return; break; case STYPE_MODEL : if ((UDDhandle & UDRF_MODEL)==0) return; break; default : return; } // if something goes wrong, sk should be assigned SKEY_OR if // selKey is set to SKEY_NEW or SKEY_OR below switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : if (nSelItems[k]==0) return; nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; if (nsel<=0) return; break; default : return; } selAND = (sKey==SKEY_AND); for (n=0;ngetUDData ( UDDhandle,iudd ); if ((selMin<=iudd) && (iudd<=selMax)) SelectObject ( mdl,k,sk,nsel ); else if (selAND) mdl->RemoveMask ( mask[k] ); } else { for (c=0;cnChains;c++) { chain = mdl->chain[c]; if (chain) { // again check for safety if (sType==STYPE_CHAIN) { chain->getUDData ( UDDhandle,iudd ); if ((selMin<=iudd) && (iudd<=selMax)) SelectObject ( chain,k,sk,nsel ); else if (selAND) chain->RemoveMask ( mask[k] ); } else { for (r=0;rnResidues;r++) { res = chain->residue[r]; if (res) { if (sType==STYPE_RESIDUE) { res->getUDData ( UDDhandle,iudd ); if ((selMin<=iudd) && (iudd<=selMax)) SelectObject ( res,k,sk,nsel ); else if (selAND) res->RemoveMask ( mask[k] ); } else { for (a=0;anAtoms;a++) { atom = res->atom[a]; if (atom) { if (!atom->Ter) { atom->getUDData ( UDDhandle,iudd ); if ((selMin<=iudd) && (iudd<=selMax)) SelectObject ( atom,k,sk,nsel ); else if (selAND) atom->RemoveMask ( mask[k] ); } } } } } } } } } } } } MakeSelIndex ( selHnd,sType,nsel ); } void SelManager::SelectUDD ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX int UDDhandle, // UDD handle realtype selMin, // lower selection boundary realtype selMax, // upper selection boundary SELECTION_KEY sKey // selection key ) { PModel mdl; PChain chain; PResidue res; PAtom atom; realtype rudd; int i,k,nsel, n,c,r,a; bool selAND; SELECTION_KEY sk; k = selHnd-1; sk = sKey; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = sType; else if (selType[k]!=sType) return; if ((selHnd<=0) || (selHnd>nSelections)) return; switch (sType) { case STYPE_ATOM : if ((UDDhandle & UDRF_ATOM)==0) return; break; case STYPE_RESIDUE : if ((UDDhandle & UDRF_RESIDUE)==0) return; break; case STYPE_CHAIN : if ((UDDhandle & UDRF_CHAIN)==0) return; break; case STYPE_MODEL : if ((UDDhandle & UDRF_MODEL)==0) return; break; default : return; } // if something goes wrong, sk should be assigned SKEY_OR if // selKey is set to SKEY_NEW or SKEY_OR below switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : if (nSelItems[k]==0) return; nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; if (nsel<=0) return; break; default : return; } selAND = (sKey==SKEY_AND); for (n=0;ngetUDData ( UDDhandle,rudd ); if ((selMin<=rudd) && (rudd<=selMax)) SelectObject ( mdl,k,sk,nsel ); else if (selAND) mdl->RemoveMask ( mask[k] ); } else { for (c=0;cnChains;c++) { chain = mdl->chain[c]; if (chain) { // again check for safety if (sType==STYPE_CHAIN) { chain->getUDData ( UDDhandle,rudd ); if ((selMin<=rudd) && (rudd<=selMax)) SelectObject ( chain,k,sk,nsel ); else if (selAND) chain->RemoveMask ( mask[k] ); } else { for (r=0;rnResidues;r++) { res = chain->residue[r]; if (res) { if (sType==STYPE_RESIDUE) { res->getUDData ( UDDhandle,rudd ); if ((selMin<=rudd) && (rudd<=selMax)) SelectObject ( res,k,sk,nsel ); else if (selAND) res->RemoveMask ( mask[k] ); } else { for (a=0;anAtoms;a++) { atom = res->atom[a]; if (atom) { if (!atom->Ter) { atom->getUDData ( UDDhandle,rudd ); if ((selMin<=rudd) && (rudd<=selMax)) SelectObject ( atom,k,sk,nsel ); else if (selAND) atom->RemoveMask ( mask[k] ); } } } } } } } } } } } } MakeSelIndex ( selHnd,sType,nsel ); } bool selSUDD ( cpstr sudd, cpstr selStr, int cmpRule, int ssLen ) { if (!sudd) return false; switch (cmpRule) { case UDSCR_LT : return (strcmp(sudd,selStr)<0); case UDSCR_LE : return (strcmp(sudd,selStr)<=0); case UDSCR_EQ : return (strcmp(sudd,selStr)==0); case UDSCR_NE : return (strcmp(sudd,selStr)!=0); case UDSCR_GE : return (strcmp(sudd,selStr)>=0); case UDSCR_GT : return (strcmp(sudd,selStr)>=0); case UDSCR_LTcase : return (strcasecmp(sudd,selStr)<0); case UDSCR_LEcase : return (strcasecmp(sudd,selStr)<=0); case UDSCR_EQcase : return (strcasecmp(sudd,selStr)==0); case UDSCR_NEcase : return (strcasecmp(sudd,selStr)!=0); case UDSCR_GEcase : return (strcasecmp(sudd,selStr)>=0); case UDSCR_GTcase : return (strcasecmp(sudd,selStr)>=0); case UDSCR_LTn : return (strncmp(sudd,selStr,ssLen)<0); case UDSCR_LEn : return (strncmp(sudd,selStr,ssLen)<=0); case UDSCR_EQn : return (strncmp(sudd,selStr,ssLen)==0); case UDSCR_NEn : return (strncmp(sudd,selStr,ssLen)!=0); case UDSCR_GEn : return (strncmp(sudd,selStr,ssLen)>=0); case UDSCR_GTn : return (strncmp(sudd,selStr,ssLen)>=0); case UDSCR_LTncase : return (strncasecmp(sudd,selStr,ssLen)<0); case UDSCR_LEncase : return (strncasecmp(sudd,selStr,ssLen)<=0); case UDSCR_EQncase : return (strncasecmp(sudd,selStr,ssLen)==0); case UDSCR_NEncase : return (strncasecmp(sudd,selStr,ssLen)!=0); case UDSCR_GEncase : return (strncasecmp(sudd,selStr,ssLen)>=0); case UDSCR_GTncase : return (strncasecmp(sudd,selStr,ssLen)>=0); case UDSCR_Substr : return (strstr(sudd,selStr)!=NULL); case UDSCR_NoSubstr : return (strstr(sudd,selStr)==NULL); case UDSCR_Substr1 : return (strstr(selStr,sudd)!=NULL); case UDSCR_NoSubstr1 : return (strstr(selStr,sudd)==NULL); default : return false; } } void SelManager::SelectUDD ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX int UDDhandle, // UDD handle cpstr selStr, // selection string int cmpRule, // comparison rule SELECTION_KEY sKey // selection key ) { PModel mdl; PChain chain; PResidue res; PAtom atom; int i,k,nsel,ssLen, n,c,r,a; bool selAND; SELECTION_KEY sk; k = selHnd-1; sk = sKey; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = sType; else if (selType[k]!=sType) return; if ((selHnd<=0) || (selHnd>nSelections)) return; switch (sType) { case STYPE_ATOM : if ((UDDhandle & UDRF_ATOM)==0) return; break; case STYPE_RESIDUE : if ((UDDhandle & UDRF_RESIDUE)==0) return; break; case STYPE_CHAIN : if ((UDDhandle & UDRF_CHAIN)==0) return; break; case STYPE_MODEL : if ((UDDhandle & UDRF_MODEL)==0) return; break; default : return; } // if something goes wrong, sk should be assigned SKEY_OR if // selKey is set to SKEY_NEW or SKEY_OR below switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : if (nSelItems[k]==0) return; nsel = 0; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; if (nsel<=0) return; break; default : return; } selAND = (sKey==SKEY_AND); ssLen = strlen ( selStr ); for (n=0;ngetUDData(UDDhandle),selStr, cmpRule,ssLen)) SelectObject ( mdl,k,sk,nsel ); else if (selAND) mdl->RemoveMask ( mask[k] ); } else { for (c=0;cnChains;c++) { chain = mdl->chain[c]; if (chain) { // again check for safety if (sType==STYPE_CHAIN) { if (selSUDD(chain->getUDData(UDDhandle),selStr, cmpRule,ssLen)) SelectObject ( chain,k,sk,nsel ); else if (selAND) chain->RemoveMask ( mask[k] ); } else { for (r=0;rnResidues;r++) { res = chain->residue[r]; if (res) { if (sType==STYPE_RESIDUE) { if (selSUDD(res->getUDData(UDDhandle),selStr, cmpRule,ssLen)) SelectObject ( res,k,sk,nsel ); else if (selAND) res->RemoveMask ( mask[k] ); } else { for (a=0;anAtoms;a++) { atom = res->atom[a]; if (atom) { if (!atom->Ter) { if (selSUDD(atom->getUDData(UDDhandle),selStr, cmpRule,ssLen)) SelectObject ( atom,k,sk,nsel ); else if (selAND) atom->RemoveMask ( mask[k] ); } } } } } } } } } } } } MakeSelIndex ( selHnd,sType,nsel ); } void SelManager::SelectSphere ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX realtype x, // x-coordinate of the sphere's center realtype y, // y-coordinate of the sphere's center realtype z, // z-coordinate of the sphere's center realtype r, // radius of the sphere SELECTION_KEY sKey // selection key ) { // Selecting a sphere PPAtom A; PAtom atm; PResidue res; PChain chain; PModel mdl; realtype dx,dy,dz, r2; int i,k, nat,nsel, im,ic,ir; bool ASel, resSel,chainSel,modelSel,selAND; SELECTION_KEY sk; if ((selHnd<=0) || (selHnd>nSelections) || (r<=0.0)) return; k = selHnd-1; sk = sKey; A = atom; nat = nAtoms; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = sType; else if (selType[k]!=sType) return; // if something goes wrong, sk should be assigned SKEY_OR if // selKey is set to SKEY_NEW or SKEY_OR below switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : nsel = 0; nat = nSelItems[k]; A = (PPAtom)selection[k]; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; nat = nSelItems[k]; A = (PPAtom)selection[k]; break; default : return; } selAND = (sKey==SKEY_AND); if ((nat<=0) || (!A)) return; r2 = r*r; if (sType==STYPE_ATOM) { for (i=0;iTer) && (A[i]->WhatIsSet & ASET_Coordinates)) { dx = fabs(A[i]->x-x); if (dx<=r) { dy = fabs(A[i]->y-y); if (dy<=r) { dz = fabs(A[i]->z-z); if (dz<=r) { if (dx*dx+dy*dy+dz*dz<=r2) { ASel = true; SelectAtom ( A[i],k,sk,nsel ); } } } } } if (!ASel) A[i]->RemoveMask ( mask[k] ); } } else { for (im=0;imnChains;ic++) { chain = mdl->chain[ic]; if (chain) { chainSel = false; for (ir=0;irnResidues;ir++) { res = chain->residue[ir]; if (res) { resSel = false; for (i=0;inAtoms;i++) { atm = res->atom[i]; if (atm) { ASel = false; if ((!atm->Ter) && (atm->WhatIsSet & ASET_Coordinates)) { dx = fabs(atm->x-x); if (dx<=r) { dy = fabs(atm->y-y); if (dy<=r) { dz = fabs(atm->z-z); if (dz<=r) { if (dx*dx+dy*dy+dz*dz<=r2) { SelectObject ( sType,atm,k,sk,nsel ); ASel = true; resSel = true; chainSel = true; modelSel = true; } } } } } if (ASel) break; // selType>=STYPE_RESIDUE } } if ((!resSel) && selAND && (sType==STYPE_RESIDUE)) res->RemoveMask ( mask[k] ); if (chainSel && (sType>STYPE_RESIDUE)) break; } } if ((!chainSel) && selAND && (sType==STYPE_CHAIN)) chain->RemoveMask ( mask[k] ); if (modelSel && (sType>STYPE_CHAIN)) break; } } if ((!modelSel) && selAND && (sType==STYPE_MODEL)) mdl->RemoveMask ( mask[k] ); } } } MakeSelIndex ( selHnd,sType,nsel ); } void SelManager::SelectCylinder ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX realtype x1, // x-coordinate of the cylinder axis' 1st end realtype y1, // y-coordinate of the cylinder axis' 1st end realtype z1, // z-coordinate of the cylinder axis' 1st end realtype x2, // x-coordinate of the cylinder axis' 2nd end realtype y2, // y-coordinate of the cylinder axis' 2nd end realtype z2, // z-coordinate of the cylinder axis' 2nd end realtype r, // radius of the cylinder SELECTION_KEY sKey // selection key ) { // // Selecting a cylinder // // Method : given a line running through (x1,y1,z1) to (x2,y2,z2) on, // a point (x,y,z) is then projected on it at distance // // c1 = (c^2-a^2+b^2)/(2c), // // from (x1,y1,z1), where // 'a' is the distance between (x,y,z) and (x2,y2,z2) // 'b' is the distance between (x,y,z) and (x1,y1,z1) // 'c' is the distance between (x1,y1,z1) and (x2,y2,z2). // The distance between point (x,y,z) and line is determined as // // h^2 = b^2 - c1^2 // // If c1>=0 and c1<=c and h^2<=r^2 then point (x,y,z) is inside // a cylinder of radius 'r' with axis running from point // (x1,y1,z1) to (x2,y2,z2). // PPAtom A; PAtom atm; PResidue res; PChain chain; PModel mdl; realtype dx,dy,dz, c,dc,c1,c2, a2,b2, r2; int i,k, nat,nsel, im,ic,ir; bool resSel,chainSel,modelSel,selAND; SELECTION_KEY sk; if ((selHnd<=0) || (selHnd>nSelections) || (r<=0.0)) return; dx = x1-x2; dy = y1-y2; dz = z1-z2; c2 = dx*dx + dy*dy + dz*dz; if (c2<=0.0) return; c = sqrt(c2); dc = 2.0*c; r2 = r*r; k = selHnd-1; sk = sKey; A = atom; nat = nAtoms; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = sType; else if (selType[k]!=sType) return; // if something goes wrong, sk should be assigned SKEY_OR if // selKey is set to SKEY_NEW or SKEY_OR below switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : nsel = 0; nat = nSelItems[k]; A = (PPAtom)selection[k]; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; nat = nSelItems[k]; A = (PPAtom)selection[k]; break; default : return; } selAND = (sKey==SKEY_AND); if ((nat<=0) || (!A)) return; if (sType==STYPE_ATOM) { for (i=0;iTer) && (A[i]->WhatIsSet & ASET_Coordinates)) { dx = fabs(A[i]->x-x1); dy = fabs(A[i]->y-y1); dz = fabs(A[i]->z-z1); a2 = dx*dx + dy*dy + dz*dz; dx = fabs(A[i]->x-x2); dy = fabs(A[i]->y-y2); dz = fabs(A[i]->z-z2); b2 = dx*dx + dy*dy + dz*dz; c1 = (c2-a2+b2)/dc; if ((0.0<=c1) && (c1<=c) && (b2-c1*c1<=r2)) SelectAtom ( A[i],k,sk,nsel ); else if (sk==SKEY_AND) A[i]->RemoveMask ( mask[k] ); } } } else { for (im=0;imnChains;ic++) { chain = mdl->chain[ic]; if (chain) { chainSel = false; for (ir=0;irnResidues;ir++) { res = chain->residue[ir]; if (res) { resSel = false; for (i=0;inAtoms;i++) { atm = res->atom[i]; if (atm) { if ((!atm->Ter) && (atm->WhatIsSet & ASET_Coordinates)) { dx = fabs(atm->x-x1); dy = fabs(atm->y-y1); dz = fabs(atm->z-z1); a2 = dx*dx + dy*dy + dz*dz; dx = fabs(atm->x-x2); dy = fabs(atm->y-y2); dz = fabs(atm->z-z2); b2 = dx*dx + dy*dy + dz*dz; c1 = (c2-a2+b2)/dc; if ((0.0<=c1) && (c1<=c) && (b2-c1*c1<=r2)) { SelectObject ( sType,atm,k,sk,nsel ); resSel = true; chainSel = true; modelSel = true; break; // selType>=STYPE_RESIDUE } } } } if ((!resSel) && selAND && (sType==STYPE_RESIDUE)) res->RemoveMask ( mask[k] ); if (chainSel && (sType>STYPE_RESIDUE)) break; } } if ((!chainSel) && selAND && (sType==STYPE_CHAIN)) chain->RemoveMask ( mask[k] ); if (modelSel && (sType>STYPE_CHAIN)) break; } } if ((!modelSel) && selAND && (sType==STYPE_MODEL)) mdl->RemoveMask ( mask[k] ); } } } MakeSelIndex ( selHnd,sType,nsel ); } void SelManager::SelectSlab ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX realtype a, // a-parameter of the plane ax+by+cz=d realtype b, // b-parameter of the plane ax+by+cz=d realtype c, // c-parameter of the plane ax+by+cz=d realtype d, // d-parameter of the plane ax+by+cz=d realtype r, // distance to the plane SELECTION_KEY sKey // selection key ) { // // Selecting all atoms on a given distance from a plane // // Method : the distance between a point (x0,y0,z0) and a plane // defined by equation // // a*x + b*y + c*z = d // // is found as // // h = (d-a*x0-b*y0-c*z0)/sqrt(a^2+b^2+c^2) // // If |h|nSelections) || (r<=0.0)) return; v = sqrt(a*a + b*b + c*c); if (v<=0.0) return; k = selHnd-1; sk = sKey; A = atom; nat = nAtoms; if ((selType[k]==STYPE_UNDEFINED) || (sKey==SKEY_NEW)) selType[k] = sType; else if (selType[k]!=sType) return; // if something goes wrong, sk should be assigned SKEY_OR if // selKey is set to SKEY_NEW or SKEY_OR below switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : nsel = 0; nat = nSelItems[k]; A = (PPAtom)selection[k]; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; nat = nSelItems[k]; A = (PPAtom)selection[k]; break; default : return; } selAND = (sKey==SKEY_AND); if ((nat<=0) || (!A)) return; if (sType==STYPE_ATOM) { for (i=0;iTer) && (A[i]->WhatIsSet & ASET_Coordinates)) { h = fabs(d-a*A[i]->x-b*A[i]->y-c*A[i]->z)/v; if (h<=r) SelectAtom ( A[i],k,sk,nsel ); else if (sk==SKEY_AND) A[i]->RemoveMask ( mask[k] ); } } } else { for (im=0;imnChains;ic++) { chain = mdl->chain[ic]; if (chain) { chainSel = false; for (ir=0;irnResidues;ir++) { res = chain->residue[ir]; if (res) { resSel = false; for (i=0;inAtoms;i++) { atm = res->atom[i]; if (atm) { if ((!atm->Ter) && (atm->WhatIsSet & ASET_Coordinates)) { h = fabs(d-a*A[i]->x-b*A[i]->y-c*A[i]->z)/v; if (h<=r) { SelectObject ( sType,atm,k,sk,nsel ); resSel = true; chainSel = true; modelSel = true; break; // selType>=STYPE_RESIDUE } } } } if ((!resSel) && selAND && (sType==STYPE_RESIDUE)) res->RemoveMask ( mask[k] ); if (chainSel && (sType>STYPE_RESIDUE)) break; } } if ((!chainSel) && selAND && (sType==STYPE_CHAIN)) chain->RemoveMask ( mask[k] ); if (modelSel && (sType>STYPE_CHAIN)) break; } } if ((!modelSel) && selAND && (sType==STYPE_MODEL)) mdl->RemoveMask ( mask[k] ); } } } MakeSelIndex ( selHnd,sType,nsel ); } void SelManager::SelectNeighbours ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX PPAtom sA, // array of already selected atoms int alen, // length of A realtype d1, // minimal distance to already selected atoms realtype d2, // maximal distance to already selected atoms SELECTION_KEY sKey // selection key ) { // Selecting all atoms on a given distance from already selected PPAtom A; PBrick B; PAtom atm; PResidue res; PChain chain; PModel mdl; realtype x,y,z, dx,dy,dz, dst, d12,d22; int i,j,k, dn, nx,ny,nz, nat,nsel, im,ic,ir; int ix1,ix2,ix, iy1,iy2,iy, iz1,iz2,iz; bool ASel,resSel,chainSel,modelSel,selAND; SELECTION_KEY sk; if ((selHnd<=0) || (selHnd>nSelections) || (d2<=0.0) || (d2RemoveMask ( mask[k] ); nSelItems[k] = 0; } return; } // if something goes wrong, sk should be assigned SKEY_OR if // selKey is set to SKEY_NEW or SKEY_OR below switch (sKey) { case SKEY_NEW : for (i=0;iRemoveMask ( mask[k] ); nSelItems[k] = 0; nsel = 0; break; case SKEY_OR : if (nSelItems[k]==0) sk = SKEY_NEW; nsel = nSelItems[k]; break; case SKEY_AND : nsel = 0; nat = nSelItems[k]; A = (PPAtom)selection[k]; break; case SKEY_XOR : nsel = nSelItems[k]; break; case SKEY_CLR : nsel = nSelItems[k]; nat = nSelItems[k]; A = (PPAtom)selection[k]; break; default : return; } selAND = (sk==SKEY_AND); if ((nat<=0) || (!A)) return; MakeBricks ( sA,alen,d2*1.5 ); dn = mround(d2/brick_size)+1; if (brick && (sType==STYPE_ATOM)) { for (i=0;iTer) { ASel = false; GetBrickCoor ( A[i],nx,ny,nz ); if (nx<0) nx++; ix1 = IMax ( 0,nx-dn ); iy1 = IMax ( 0,ny-dn ); iz1 = IMax ( 0,nz-dn ); ix2 = IMin ( nbrick_x,nx+dn+1 ); iy2 = IMin ( nbrick_y,ny+dn+1 ); iz2 = IMin ( nbrick_z,nz+dn+1 ); x = A[i]->x; y = A[i]->y; z = A[i]->z; for (ix=ix1;(ixnAtoms) && (!ASel);j++) if (B->atom[j]!=A[i]) { dx = fabs(x-B->atom[j]->x); if (dx<=d2) { dy = fabs(y-B->atom[j]->y); if (dy<=d2) { dz = fabs(z-B->atom[j]->z); if (dz<=d2) { dst = dx*dx+dy*dy+dz*dz; if ((dst>=d12) && (dst<=d22)) { ASel = true; SelectAtom ( A[i],k,sk,nsel ); } } } } } } if ((!ASel) && selAND) A[i]->RemoveMask ( mask[k] ); } } } else if (brick) { for (im=0;imnChains;ic++) { chain = mdl->chain[ic]; if (chain) { chainSel = false; for (ir=0;irnResidues;ir++) { res = chain->residue[ir]; if (res) { resSel = false; for (i=0;(inAtoms) && (!resSel);i++) { atm = res->atom[i]; if (atm) { if ((!atm->Ter) && (atm->WhatIsSet & ASET_Coordinates)) { GetBrickCoor ( atm,nx,ny,nz ); if (nx<0) nx++; ix1 = IMax ( 0,nx-dn ); iy1 = IMax ( 0,ny-dn ); iz1 = IMax ( 0,nz-dn ); ix2 = IMin ( nbrick_x,nx+dn+1 ); iy2 = IMin ( nbrick_y,ny+dn+1 ); iz2 = IMin ( nbrick_z,nz+dn+1 ); x = atm->x; y = atm->y; z = atm->z; for (ix=ix1;(ixnAtoms) && (!resSel);j++) if (B->atom[j]!=atm) { dx = fabs(x-B->atom[j]->x); if (dx<=d2) { dy = fabs(y-B->atom[j]->y); if (dy<=d2) { dz = fabs(z-B->atom[j]->z); if (dz<=d2) { dst = dx*dx+dy*dy+dz*dz; if ((dst>=d12) && (dst<=d22)) { SelectObject ( sType, atm,k,sk,nsel ); resSel = true; chainSel = true; modelSel = true; } } } } } } } } } if ((!resSel) && selAND && (sType==STYPE_RESIDUE)) res->RemoveMask ( mask[k] ); if (chainSel && (sType>STYPE_RESIDUE)) break; } } if ((!chainSel) && selAND && (sType==STYPE_CHAIN)) chain->RemoveMask ( mask[k] ); if (modelSel && (sType>STYPE_CHAIN)) break; } } if ((!modelSel) && selAND && (sType==STYPE_MODEL)) mdl->RemoveMask ( mask[k] ); } } } MakeSelIndex ( selHnd,sType,nsel ); } int TakeChainID ( pstr & p, pstr chainID ) { int RC,k; chainID[0] = char(0); if (*p) { RC = 0; if (*p==':') { // starts with colon <=> empty chain ID chainID[0] = char(0); p++; // advance to residue number } else if (p[1]==':') { // second symbol is colon <=> regular chain ID chainID[0] = *p; chainID[1] = char(0); p++; p++; // advance to residue number } else if (*p=='\'') { // starts with a strip <=> assume empty chain ID chainID[0] = char(0); p++; if (*p=='\'') { // closing strip must be followed by colon p++; if (*p!=':') RC = -1; } else { // no concluding strip <=> could be a strip chain ID, // although this must be captured by 2nd "if" chainID[0] = '\''; chainID[1] = char(0); // assume that residue number is following the strip } } else if ((int(*p)>=int('0')) && (int(*p)<=int('9'))) { // a digit without following semicolon looks very much // like residue number with unspecified empty chain ID chainID[0] = char(0); // assume that p already points on residue number } else { // assume a long chain ID k = 0; while (*p && (*p!=':') && (k<(int)sizeof(ChainID)-1)) { chainID[k++] = *p; p++; } if (*p==':') { chainID[k] = char(0); } else { // a mistake chainID[0] = char(0); RC = -1; } } while (*p==' ') p++; } else RC = 1; return RC; } int TakeResID( pstr & p, int & seqNum, pstr inscode ) { char N[100]; int i,RC; pstr endptr; RC = 1; inscode[0] = '*'; inscode[1] = char(0); seqNum = ANY_RES; if (((*p) && (int(*p)>=int('0')) && (int(*p)<=int('9'))) || (*p=='-')) { N[0] = *p; p++; i = 1; while ((*p) && (int(*p)>=int('0')) && (int(*p)<=int('9'))) { N[i++] = *p; p++; } N[i] = char(0); seqNum = mround(strtod(N,&endptr)); if ((seqNum==0) && (endptr==N)) RC = -1; else { RC = 0; if ((*p) && (*p!='-') && (*p!=',') && (*p!=' ')) { inscode[0] = *p; inscode[1] = char(0); p++; } else inscode[0] = char(0); if ((*p=='-') || (*p==',')) p++; } while (*p==' ') p++; } return RC; } int SelManager::SelectDomain ( int selHnd , cpstr domainRange, SELECTION_TYPE sType, SELECTION_KEY sKey, int modelNo ) { // domainRange is of the following format: // "*", "(all)" - take all file // "-" - take chain without chain ID // "a:Ni-Mj,b:Kp-Lq,..." - take chain a residue number N // insertion code i to residue number M // insertion code j plus chain b // residue number K insertion code p to // residue number L insertion code q and // so on. // "a:,b:..." - take whole chains a and b and so on // "a:,b:Kp-Lq,..." - any combination of the above. ChainID chainID; InsCode insCode1,insCode2; pstr S,p; int seqNum1,seqNum2,rc; SELECTION_KEY selKey1; if ((selHnd<=0) || (selHnd>nSelections)) return 1; // leave only required residues rc = 1; if (!domainRange) rc = 0; else if ((!domainRange[0]) || (domainRange[0]=='*')) rc = 0; else if (!strcasecmp(domainRange,"(all)")) rc = 0; if (!rc) { // select all Select ( selHnd,sType,modelNo,"*",ANY_RES,"*",ANY_RES,"*", "*","*","*","*",sKey ); return 0; } if (!strcasecmp(domainRange,"-")) { // select chain without chain ID Select ( selHnd,sType,modelNo,"",ANY_RES,"*",ANY_RES,"*", "*","*","*","*",sKey ); return 0; } S = new char[strlen(domainRange)+10]; strcpy ( S,domainRange ); DelSpaces ( S ); // UpperCase ( S ); p = S; rc = 0; selKey1 = sKey; while ((*p) && (!rc)) { if (TakeChainID(p,chainID)<0) rc = -1; else if (TakeResID(p,seqNum1,insCode1)<0) rc = -2; else if (TakeResID(p,seqNum2,insCode2)<0) rc = -3; else { Select ( selHnd,sType,modelNo,chainID, seqNum1,insCode1,seqNum2,insCode2, "*","*","*","*",selKey1 ); if (*p==',') p++; if (selKey1==SKEY_NEW) selKey1 = SKEY_OR; } } delete[] S; return rc; } int SelManager::GetSelLength ( int selHnd ) { if ((selHnd>0) && (selHnd<=nSelections)) return nSelItems[selHnd-1]; else return 0; } void SelManager::GetSelIndex ( int selHnd, PPAtom & SelAtom, int & nSelAtoms ) { if ((selHnd>0) && (selHnd<=nSelections)) { if (selType[selHnd-1]!=STYPE_ATOM) { SelAtom = NULL; nSelAtoms = 0; } else { SelAtom = (PPAtom)selection[selHnd-1]; nSelAtoms = nSelItems[selHnd-1]; } } else { SelAtom = NULL; nSelAtoms = 0; } } void SelManager::GetSelIndex ( int selHnd, PPResidue & SelResidue, int & nSelResidues ) { if ((selHnd>0) && (selHnd<=nSelections)) { if (selType[selHnd-1]!=STYPE_RESIDUE) { SelResidue = NULL; nSelResidues = 0; } else { SelResidue = (PPResidue)selection[selHnd-1]; nSelResidues = nSelItems[selHnd-1]; } } else { SelResidue = NULL; nSelResidues = 0; } } void SelManager::GetSelIndex ( int selHnd, PPChain & SelChain, int & nSelChains ) { if ((selHnd>0) && (selHnd<=nSelections)) { if (selType[selHnd-1]!=STYPE_CHAIN) { SelChain = NULL; nSelChains = 0; } else { SelChain = (PPChain)selection[selHnd-1]; nSelChains = nSelItems[selHnd-1]; } } else { SelChain = NULL; nSelChains = 0; } } void SelManager::GetSelIndex ( int selHnd, PPModel & SelModel, int & nSelModels ) { if ((selHnd>0) && (selHnd<=nSelections)) { if (selType[selHnd-1]!=STYPE_MODEL) { SelModel = NULL; nSelModels = 0; } else { SelModel = (PPModel)selection[selHnd-1]; nSelModels = nSelItems[selHnd-1]; } } else { SelModel = NULL; nSelModels = 0; } } void SelManager::GetAtomStatistics ( int selHnd, RAtomStat AS ) { int i,k; AS.Init(); if ((selHnd>0) && (selHnd<=nSelections)) { k = selHnd-1; switch (selType[k]) { case STYPE_MODEL : if (selection[k]) for (i=0;i CalAtomStatistics ( AS ); break; case STYPE_CHAIN : if (selection[k]) for (i=0;i CalAtomStatistics ( AS ); break; case STYPE_RESIDUE : if (selection[k]) for (i=0;i CalAtomStatistics ( AS ); break; case STYPE_ATOM : if (selection[k]) for (i=0;i CalAtomStatistics ( AS ); break; default : break; } } AS.Finish(); } void SelManager::SelectAtom ( PAtom atom, int maskNo, SELECTION_KEY sKey, int & nsel ) { bool ASel; ASel = atom->CheckMask ( mask[maskNo] ); switch (sKey) { default : case SKEY_NEW : case SKEY_OR : if (!ASel) { atom->SetMask ( mask[maskNo] ); nsel++; } break; case SKEY_AND : if (ASel) nsel++; break; case SKEY_XOR : if (ASel) { atom->RemoveMask ( mask[maskNo] ); nsel--; } else { atom->SetMask ( mask[maskNo] ); nsel++; } break; case SKEY_CLR : if (ASel) { atom->RemoveMask ( mask[maskNo] ); nsel--; } } } void SelManager::SelectObject ( SELECTION_TYPE sType, PAtom atm, int maskNo, SELECTION_KEY sKey, int & nsel ) { PMask object; switch (sType) { default : case STYPE_UNDEFINED : return; case STYPE_ATOM : object = atm; break; case STYPE_RESIDUE : object = atm->GetResidue(); break; case STYPE_CHAIN : object = atm->GetChain (); break; case STYPE_MODEL : object = atm->GetModel (); break; } if (!object) return; SelectObject ( object,maskNo,sKey,nsel ); } void SelManager::SelectObject ( PMask object, int maskNo, SELECTION_KEY sKey, int & nsel ) { bool ASel; ASel = object->CheckMask ( mask[maskNo] ); switch (sKey) { default : case SKEY_NEW : case SKEY_OR : if (!ASel) { object->SetMask ( mask[maskNo] ); nsel++; } break; case SKEY_AND : if (ASel) nsel++; break; case SKEY_XOR : if (ASel) { object->RemoveMask ( mask[maskNo] ); nsel--; } else { object->SetMask ( mask[maskNo] ); nsel++; } break; case SKEY_CLR : if (ASel) { object->RemoveMask ( mask[maskNo] ); nsel--; } break; case SKEY_XAND : if (ASel) { object->RemoveMask ( mask[maskNo] ); nsel++; } } } void SelManager::DeleteSelObjects ( int selHnd ) { PPModel model; PPChain chain; PPResidue res; PPAtom atom; int i,k,nSel; if ((selHnd>0) && (selHnd<=nSelections)) { k = selHnd-1; nSel = nSelItems[k]; switch (selType[k]) { case STYPE_MODEL : model = (PPModel)selection[k]; for (i=0;i0) && (selHnd<=nSelections)) { k1 = selHnd-1; k2 = k1+1; } else { k1 = 0; k2 = nSelections; } for (k=k1;kCheckMask(mask[k])) ns++; break; case STYPE_RESIDUE : for (n=0;nnChains;i++) { chain = mdl->chain[i]; if (chain) for (j=0;jnResidues;j++) { res = chain->residue[j]; if (res) if (res->CheckMask(mask[k])) ns++; } } } break; case STYPE_CHAIN : for (i=0;inChains;j++) { chain = mdl->chain[j]; if (chain) if (chain->CheckMask(mask[k])) ns++; } } break; case STYPE_MODEL : for (i=0;iCheckMask(mask[k])) ns++; break; default : ; } } else ns = nsel; if (selection[k]) delete[] selection[k]; if (ns>0) { selection[k] = new PMask[ns]; nns = 0; switch (sType) { case STYPE_ATOM : for (i=0;iCheckMask(mask[k])) { selection[k][nns++] = atom[i]; if (nns>=ns) nns = ns-1; } } break; case STYPE_RESIDUE : for (n=0;nnChains;i++) { chain = mdl->chain[i]; if (chain) for (j=0;jnResidues;j++) { res = chain->residue[j]; if (res) if (res->CheckMask(mask[k])) { selection[k][nns++] = res; if (nns>=ns) nns = ns-1; } } } } break; case STYPE_CHAIN : for (i=0;inChains;j++) { chain = mdl->chain[j]; if (chain) if (chain->CheckMask(mask[k])) { selection[k][nns++] = chain; if (nns>=ns) nns = ns-1; } } } break; case STYPE_MODEL : for (i=0;iCheckMask(mask[k])) { selection[k][nns++] = model[i]; if (nns>=ns) nns = ns-1; } break; default : ; } } else selection[k] = NULL; nSelItems[k] = ns; } } // ------------------- Stream functions ---------------------- void SelManager::write ( io::RFile f ) { int i,sType; byte Version=1; f.WriteByte ( &Version ); CoorManager::write ( f ); if (!isCompactBinary()) { f.WriteInt ( &nSelections ); for (i=0;i0) { mask = new PMask [nSelections]; selection = new PPMask[nSelections]; nSelItems = new int [nSelections]; selType = new SELECTION_TYPE[nSelections]; for (i=0;i // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::ProModel ( a virtue of Model ) // ~~~~~~~~~ mmdb::DBReference ( DBREF records ) // mmdb::ChainContainer ( container of in-chain classes ) // mmdb::ContainerChain ( chain containered class template) // mmdb::SeqAdv ( SEQADV records ) // mmdb::SeqRes ( SEQRES records ) // mmdb::ModRes ( MODRES records ) // mmdb::HetRec ( HET records ) // mmdb::Chain ( chain class ) // // Copyright (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_Chain__ #define __MMDB_Chain__ #include "mmdb_io_stream.h" #include "mmdb_utils.h" #include "mmdb_atom.h" #include "mmdb_defs.h" namespace mmdb { // ==================== ProModel ====================== // This class is a virtue needed only for defining certain // functions of Model, which are used by Chain and // Residue DefineClass(ProModel); DefineStreamFunctions(ProModel); DefineClass(Manager); class ProModel : public UDData { friend class Chain; public : ProModel () : UDData () {} ProModel ( io::RPStream Object ) : UDData ( Object ) {} ~ProModel () {} virtual cpstr GetEntryID () { return ""; } virtual void SetEntryID ( const IDCode ) {} virtual int AddChain ( PChain ) { return 0; } // returns pointer to Root virtual PManager GetCoordHierarchy() { return NULL; } // GetNumberOfModels() returns TOTAL number of models virtual int GetNumberOfModels() { return 0; } // GetNumberOfAllAtoms() returns TOTAL number of atoms in // all models virtual int GetNumberOfAllAtoms() { return 0; } // returns pointer to the general Atom array virtual PPAtom GetAllAtoms() { return NULL; } virtual int GetSerNum () { return 0; } virtual void ExpandAtomArray ( int ) {} virtual void AddAtomArray ( int ) {} protected : virtual int _ExcludeChain ( const ChainID ) { return 0; } }; // ==================== ChainContainer ====================== DefineClass(ChainContainer); DefineStreamFunctions(ChainContainer); class ChainContainer : public ClassContainer { public : ChainContainer () : ClassContainer () {} ChainContainer ( io::RPStream Object ) : ClassContainer ( Object ) {} ~ChainContainer () {} PContainerClass MakeContainerClass ( int ClassID ); void SetChain ( PChain Chain_Owner ); // must be set before using // the Container // special functions used in Model::GetCIF(..) cpstr Get1stChainID (); void MoveByChainID ( const ChainID chainID, PChainContainer chainContainer ); protected : PChain chain; }; // ================== ContainerChain ===================== DefineClass(ContainerChain); DefineStreamFunctions(ContainerChain); class ContainerChain : public ContainerClass { friend class ChainContainer; public : ContainerChain (); ContainerChain ( PChain Chain_Owner ); ContainerChain ( io::RPStream Object ) : ContainerClass(Object) {} void SetChain ( PChain Chain_Owner ); protected : PChain chain; ChainID chainID; // just a copy of Chain->chainID }; // ================== DBReference ======================== DefineClass(DBReference); DefineStreamFunctions(DBReference); class DBReference : public ContainerChain { public : int seqBeg; // initial seq num of the PDB seq-ce segment InsCode insBeg; // initial ins code of the PDB seq-ce segm-t int seqEnd; // ending seq number of the PDB seq-ce segm-t InsCode insEnd; // ending ins code of the PDB seq-ce segment DBName database; // sequence database name DBAcCode dbAccession; // sequence database accession code DBIdCode dbIdCode; // sequence database identification code int dbseqBeg; // initial seq number of the database segment InsCode dbinsBeg; // ins code of initial residue of the segment int dbseqEnd; // ending seq number of the database segment InsCode dbinsEnd; // ins code of the ending residue of the seg-t DBReference (); DBReference ( PChain Chain_Owner ); DBReference ( PChain Chain_Owner, cpstr S ); DBReference ( io::RPStream Object ); ~DBReference(); void PDBASCIIDump ( pstr S, int N ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_DBReference; } void Copy ( PContainerClass DBRef ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitDBReference(); }; // ==================== SeqAdv =========================== DefineClass(SeqAdv); DefineStreamFunctions(SeqAdv); class SeqAdv : public ContainerChain { public : ResName resName; // residue name in conflict int seqNum; // residue sequence number InsCode insCode; // residue insertion code DBName database; // sequence database name DBAcCode dbAccession; // sequence database accession code ResName dbRes; // sequence database residue name int dbSeq; // sequence database sequence number pstr conflict; // conflict comment SeqAdv (); SeqAdv ( PChain Chain_Owner ); SeqAdv ( PChain Chain_Owner, cpstr S ); SeqAdv ( io::RPStream Object ); ~SeqAdv(); void PDBASCIIDump ( pstr S, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_SeqAdv; } void Copy ( PContainerClass seqAdv ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitSeqAdv(); }; // ================== SeqRes ======================== DefineClass(SeqRes); DefineStreamFunctions(SeqRes); class SeqRes : public io::Stream { friend class Model; friend class Chain; public : int numRes; // number of residues in the chain PResName resName; // residue names SeqRes (); SeqRes ( io::RPStream Object ); ~SeqRes(); void SetChain ( PChain Chain_Owner ); void PDBASCIIDump ( io::RFile f ); ERROR_CODE ConvertPDBASCII ( cpstr S ); void MakeCIF ( mmcif::PData CIF ); ERROR_CODE GetCIF ( mmcif::PData CIF ); void Copy ( PSeqRes seqRes ); void write ( io::RFile f ); void read ( io::RFile f ); protected : PChain chain; ChainID chainID; int serNum; void InitSeqRes(); void FreeMemory(); }; // ================== ModRes ======================== DefineClass(ModRes); DefineStreamFunctions(ModRes); class ModRes : public ContainerChain { public : ResName resName; // residue name used int seqNum; // residue sequence number InsCode insCode; // residue insertion code ResName stdRes; // standard residue name pstr comment; // description of the residue modification ModRes (); ModRes ( PChain Chain_Owner ); ModRes ( PChain Chain_Owner, cpstr S ); ModRes ( io::RPStream Object ); ~ModRes(); void PDBASCIIDump ( pstr S, int N ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_ModRes; } void Copy ( PContainerClass modRes ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitModRes(); }; // ================== HetRec =========================== DefineClass(HetRec); DefineStreamFunctions(HetRec); class HetRec : public ContainerChain { public : ResName hetID; // Het identifier (right-justified) int seqNum; // sequence number InsCode insCode; // insertion code int numHetAtoms; // number of HETATM records for the // group present in the entry pstr comment; // text describing Het group HetRec (); HetRec ( PChain Chain_Owner ); HetRec ( PChain Chain_Owner, cpstr S ); HetRec ( io::RPStream Object ); ~HetRec(); void PDBASCIIDump ( pstr S, int N ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_Het; } void Copy ( PContainerClass Het ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitHetRec(); }; // ================= Chain ======================= DefineFactoryFunctions(Chain); class Chain : public UDData { friend class DBReference; friend class SeqAdv; friend class SeqRes; friend class ModRes; friend class HetRec; friend class Residue; friend class Atom; friend class Model; friend class Root; friend class SelManager; friend class BondManager; friend class CoorManager; friend class Manager; public : ChainContainer DBRef; // database reference ChainContainer seqAdv; // SEQADV records SeqRes seqRes; // Sequence residues, SEQRES records ChainContainer modRes; // modification descriptions ChainContainer Het; // non-standard residues descriptions Chain (); // SetModel() MUST be used after this constructor! Chain ( PProModel model, const ChainID chID ); Chain ( io::RPStream Object ); ~Chain(); void FreeAnnotations(); void SetModel ( PProModel model ); void SetChain ( const ChainID chID ); PManager GetCoordHierarchy(); // PRoot // ConvertXXXXX(..) functions do not check for record name // and assume that PDBString is at least 81 symbols long // (including the terminating null). ERROR_CODE ConvertDBREF ( cpstr PDBString ); ERROR_CODE ConvertSEQADV ( cpstr PDBString ); ERROR_CODE ConvertSEQRES ( cpstr PDBString ); ERROR_CODE ConvertMODRES ( cpstr PDBString ); ERROR_CODE ConvertHET ( cpstr PDBString ); // This function should be used for testing purposes only. // A full PDB ASCII dump for all models and chains involved // is done by Root class. void PDBASCIIDump ( io::RFile f ); void PDBASCIIAtomDump ( io::RFile f ); void MakeAtomCIF ( mmcif::PData CIF ); // ----------------- Extracting residues ------------------------- int GetNumberOfResidues(); // returns number of res-s in the chain PResidue GetResidue ( int resNo ); // returns resNo-th residue // in the chain; // 0<=resNo // ~~~~~~~~~ // **** Project : MMDB ( MacroMolecular Data Base ) // ~~~~~~~~~ // // (C) E.Krissinel 2000-2013 // // ================================================================= // // #include #include #include "mmdb_math_linalg.h" namespace mmdb { namespace math { // ========================== Jacobi ============================= void Jacobi ( int N, // dimension of the matrix rmatrix A, // matrix to diagonalize; the lower // triangle, except the diagonal, // will remain unchanged rmatrix T, // eigenvectors placed as columns rvector Eigen, // vector of eigenvalues, orderd // by increasing rvector Aik, // working array int & Signal // 0 <=> Ok, ItMax <=> iteration limit // exchausted. ) { // Diagonalization of symmetric matrices by the method of Jacobi. // Key variables: // ItMax - the maximum available number of iterations // Eps1 - is used in SNA and CSA calculations // Eps2 - is the level of the elimination of the // non-diagonal matrix elements // Eps3 - the criterion to stop the iterations. // The iterations stop if (1-Sigma1/Sigma2)<=Eps3 // where Sigma1 is the dekart norm of the eigenvalues // at the preceding iteration and Sigma2 is // the same for the current iteration. realtype Eps1,Eps2,Eps3; realtype Sigma1,Sigma2,OffDsq, SPQ,CSA,SNA,Q,P, HoldIK,HoldKI; int ItMax; int i,j,k,Iter; Eps1 = 6.0e-9; Eps2 = 9.0e-12; Eps3 = 1.0e-8; ItMax = 9999; Signal = 0; if (N<=1) { T[1][1] = 1.0; Eigen[1] = A[1][1]; return; } for (i=1;i<=N;i++) { for (j=1;j<=N;j++) T[i][j] = 0.0; T[i][i] = 1.0; Eigen[i] = A[i][i]; } Sigma1 = 0.0; OffDsq = 0.0; // Sigma1 is the Dekart measure of the diagonal elements // OffDsq is the Dekart measure of the non-diagonal elements for (i=1;i<=N;i++) { Sigma1 += A[i][i]*A[i][i]; if (iEps3)) { for (i=1;iEps2)) { if (Q>Eps1) { P = 2.0*A[i][j]*(Q/(A[i][i]-A[j][j])); SPQ = sqrt(P*P+Q*Q); CSA = sqrt((1.0+Q/SPQ)/2.0); SNA = P/(SPQ*CSA*2.0); } else { CSA = sqrt(0.5); SNA = CSA; } for (k=1;k<=N;k++) { HoldKI = T[k][i]; T[k][i] = HoldKI*CSA + T[k][j]*SNA; T[k][j] = HoldKI*SNA - T[k][j]*CSA; } for (k=i;k<=N;k++) if (k<=j) { Aik[k] = A[i][k]; A[i][k] = CSA*Aik[k] + SNA*A[k][j]; if (k==j) { A[j][k] = SNA*Aik[k] - CSA*A[j][k]; Aik[j] = SNA*Aik[i] - CSA*Aik[j]; } } else { HoldIK = A[i][k]; A[i][k] = CSA*HoldIK + SNA*A[j][k]; A[j][k] = SNA*HoldIK - CSA*A[j][k]; } for (k=1;k<=j;k++) if (k>i) A[k][j] = SNA*Aik[k] - CSA*A[k][j]; else { HoldKI = A[k][i]; A[k][i] = CSA*HoldKI + SNA*A[k][j]; A[k][j] = SNA*HoldKI - CSA*A[k][j]; } } } Sigma2 = 0.0; for (i=1;i<=N;i++) { Eigen[i] = A[i][i]; Sigma2 += Eigen[i]*Eigen[i]; } HoldIK = fabs(1.0-Sigma1/Sigma2); Sigma1 = Sigma2; Iter++; } if (Iter>ItMax) Signal = ItMax; for (i=1;i<=N;i++) { k = i; for (j=i;j<=N;j++) if (Eigen[j]MaxOffl) MaxOffl = BB; } MaxOffl = sqrt(MaxOffl); } MinL2 = sqrt(MachEps)*MaxOffl; MaxAdd = 0.0; for (j=1;j<=N;j++) { S = 0.0; if (j>1) for (i=1;i1) for (k=1;kMinLjj) MinLjj = BB; } BB = MinLjj/MaxOffl; if (BB>MinL) MinLjj = BB; else MinLjj = MinL; if (L[j][j]>MinLjj*MinLjj) L[j][j] = sqrt(L[j][j]); else { if (MinL2>MinLjj) MinLjj = MinL2; BB = MinLjj*MinLjj-L[j][j]; if (BB>MaxAdd) MaxAdd = BB; L[j][j] = MinLjj; } if (j1) for (i=2;i<=N;i++) { Y[i] = B[i]; for (j=1;j1) for (i=N-1;i>=1;i--) { X[i] = Y[i]; for (j=i+1;j<=N;j++) X[i] -= L[j][i]*X[j]; X[i] /= L[i][i]; } } // ----------------------------------------------------- void ChSolve ( int N, rmatrix L, rvector G, rvector S ) { // A3.2.3 : Solution of the equation L*LT*S = G // by the Cholesky's method //int i; LSolve ( N,L,G,S ); LTSolve ( N,L,S,S ); // for (i=1;i<=N;i++) // S[i] = -S[i]; } // ---------------------------------------------------- void FastInverse ( int N, rmatrix A, ivector J0, //#D realtype & Det, int & Signal ) { // // 17.01.91 <-- Last Date of Modification. // ---------------------------- // // ================================================ // // Fast Inversion of the matrix A // by the method of GAUSS - JOIRDAN . // // ------------------------------------------------ // // Input parameters are : // // N - dimension of the matrix // A - the matrix [1..N][1..N] to be inverted. // // ------------------------------------------------ // // J0 - integer vector [1..N] for temporal storage // // // ------------------------------------------------ // // Output parameters are : // // A - the inverted matrix // Signal - the error key : // = 0 <=> O'K // else // degeneration was found, and // the rang of matrix is Signal-1. // // Variable Det may return the determinant // of matrix A. To obtain it, remove all comments // of form //#D . // // ------------------------------------------------ // // Key Variables are : // // Eps - is the level for the degeneration // detection. Keep in mind, that // this routine does not norm the // matrix given, and thus Eps1 // is the ABSOLUTE value. // // ================================================ // realtype Eps = 1.0e-16; int i,j,k,i0; realtype A0,B; rvector Ai,Ai0; Signal = 0; if (N<=1) { if (fabs(A[1][1])A0) { A0 = fabs(A[j][i]); i0 = j; } } if (A0=1;i--) { j = J0[i]; if (j!=i) { //#D Det = -Det; for (k=1;k<=N;k++) { B = A[k][i]; A[k][i] = A[k][j]; A[k][j] = B; } } } return; } // End of the procedure FastInverse // ---------------------------------------------------- realtype Sign ( realtype A, realtype B ) { if (B>=0.0) return A; else return -A; } realtype SrX2Y2 ( realtype X, realtype Y ) { realtype Ax,Ay; Ax = fabs(X); Ay = fabs(Y); if (Ay>Ax) return Ay*sqrt((X*X)/(Y*Y)+1.0); if (Ay==Ax) return Ax*sqrt(2.0); return Ax*sqrt((Y*Y)/(X*X)+1.0); } // ---------------------------------------------------- void SVD ( int NA, int M, int N, rmatrix A, rmatrix U, rmatrix V, rvector W, rvector RV1, bool MatU, bool MatV, int & RetCode ) { // // 13.12.01 <-- Last Modification Date // ------------------------ // // ================================================ // // The Singular Value Decomposition // of the matrix A by the algorithm from // G.Forsait, M.Malkolm, K.Mouler. Numerical // methods of mathematical calculations // M., Mir, 1980. // // Matrix A is represented as // // A = U * W * VT // // ------------------------------------------------ // // All dimensions are indexed from 1 on. // // ------------------------------------------------ // // Input parameters: // // NA - number of lines in A. NA may be // equal to M or N only. If NA=M // then usual SVD will be made. If MA=N // then matrix A is transposed before // the decomposition, and the meaning of // output parameters U and V is // swapped (U accepts VT and VT accepts U). // In other words, matrix A has physical // dimension of M x N , same as U and V; // however the logical dimension of it // remains that of N x M . // M - number of lines in U // N - number of columns in U,V and length // of W,RV1 . Always provide M >= N ! // A - matrix [1..M][1..N] or [1..N][1..M] // to be decomposed. The matrix does not // change, and it may coincide with U or // V, if NA=M (in which case A does change) // MatU - compute U , if set True // MatV - compute V , if set True // RV1 - temporary array [1..N]. // U - should be always supplied as an array of // [1..M][1..N], M>=N . // V - should be suuplied as an array of // [1..N][1..N] if MatV is True . // // ------------------------------------------------ // // Output parameters are : // // W - N non-ordered singular values, // if RetCode=0. If RetCode<>0, the // RetCode+1 ... N -th values are still // valid // U - matrix of right singular vectors // (arranged in columns), corresponding // to the singular values in W, if // RetCode=0 and MatU is True. If MatU // is False, U is still used as a // temporary array. If RetCode<>0 then // the RetCode+1 ... N -th vectors // are valid // V - matrix of left singular vectors // (arranged in columns), corresponding // to the singular values in W, if // RetCode=0 and MatV is True. If MatV // is False, V is not used and may be set // to NULL. If RetCode<>0 then the // RetCode+1 ... N -th vectors are valid // RetCode - the error key : // = 0 <=> O'K // else // = k, if the k-th singular value // was not computed after 30 iterations. // // ------------------------------------------------ // // Key Variables are : // // ItnLimit - the limit for iterations // // This routine does not use any machine-dependent // constants. // // ================================================ // // int ItnLimit=300; int i,j,k,l,i1,k1,l1,its,mn,ExitKey; realtype C,G,F,X,S,H,Y,Z,Scale,ANorm,GG; l1 = 0; // this is to keep compiler happy RetCode = 0; if (U!=A) { if (NA==M) for (i=1;i<=M;i++) for (j=1;j<=N;j++) U[i][j] = A[i][j]; else for (i=1;i<=M;i++) for (j=1;j<=N;j++) U[i][j] = A[j][i]; } G = 0.0; Scale = 0.0; ANorm = 0.0; for (i=1;i<=N;i++) { l = i+1; RV1[i] = Scale*G; G = 0.0; S = 0.0; Scale = 0.0; if (i<=M) { for (k=i;k<=M;k++) Scale += fabs(U[k][i]); if (Scale!=0.0) { for (k=i;k<=M;k++) { U[k][i] /= Scale; S += U[k][i]*U[k][i]; } F = U[i][i]; G = -Sign(sqrt(S),F); H = F*G-S; U[i][i] = F-G; if (i!=N) for (j=l;j<=N;j++) { S = 0.0; for (k=i;k<=M;k++) S += U[k][i]*U[k][j]; F = S/H; for (k=i;k<=M;k++) U[k][j] += F*U[k][i]; } for (k=i;k<=M;k++) U[k][i] *= Scale; } } W[i] = Scale*G; G = 0.0; S = 0.0; Scale = 0.0; if ((i<=M) && (i!=N)) { for (k=l;k<=N;k++) Scale += fabs(U[i][k]); if (Scale!=0.0) { for (k=l;k<=N;k++) { U[i][k] /= Scale; S += U[i][k]*U[i][k]; } F = U[i][l]; G = -Sign(sqrt(S),F); H = F*G-S; U[i][l] = F-G; for (k=l;k<=N;k++) RV1[k] = U[i][k]/H; if (i!=M) for (j=l;j<=M;j++) { S = 0.0; for (k=l;k<=N;k++) S += U[j][k]*U[i][k]; for (k=l;k<=N;k++) U[j][k] += S*RV1[k]; } for (k=l;k<=N;k++) U[i][k] *= Scale; } } ANorm = RMax( ANorm,fabs(W[i])+fabs(RV1[i]) ); } // Accumulation of the right-hand transformations if (MatV) for (i=N;i>=1;i--) { if (i!=N) { if (G!=0.0) { for (j=l;j<=N;j++) V[j][i] = (U[i][j]/U[i][l]) / G; for (j=l;j<=N;j++) { S = 0.0; for (k=l;k<=N;k++) S += U[i][k]*V[k][j]; for (k=l;k<=N;k++) V[k][j] += S*V[k][i]; } } for (j=l;j<=N;j++) { V[i][j] = 0.0; V[j][i] = 0.0; } } V[i][i] = 1.0; G = RV1[i]; l = i; } // Accumulation of the left-hand transformations if (MatU) { mn = N; if (M=1;i--) { l = i+1; G = W[i]; if (i!=N) for (j=l;j<=N;j++) U[i][j] = 0.0; if (G!=0.0) { if (i!=mn) for (j=l;j<=N;j++) { S = 0.0; for (k=l;k<=M;k++) S += U[k][i]*U[k][j]; F = (S/U[i][i]) / G; for (k=i;k<=M;k++) U[k][j] += F*U[k][i]; } for (j=i;j<=M;j++) U[j][i] /= G; } else for (j=i;j<=M;j++) U[j][i] = 0.0; U[i][i] += 1.0; } } // Diagonalization of the two-diagonal form. for (k=N;k>=1;k--) { k1 = k-1; its = 0; do { ExitKey = 0; l = k+1; while ((ExitKey==0) && (l>1)) { l--; l1 = l-1; if (fabs(RV1[l])+ANorm==ANorm) ExitKey=1; else if (l1>0) { if (fabs(W[l1])+ANorm==ANorm) ExitKey=2; } } // if (ExitKey!=1) { <-- this is original statement if (ExitKey>1) { // <-- prevents from corruption due to l1<1. // This is a rare case as RV1[1] should be // always 0.0 . Apparently this logics is // on the edge of float-point arithmetic, // therefore extra precaution for the case // of l1<1 was found necessary. C = 0.0; S = 1.0; ExitKey = 0; i = l; while ((ExitKey==0) && (i<=k)) { F = S*RV1[i]; RV1[i] = C*RV1[i]; if (fabs(F)+ANorm==ANorm) ExitKey = 1; else { G = W[i]; H = SrX2Y2(F,G); W[i] = H; C = G/H; S = -F/H; if (MatU) for (j=1;j<=M;j++) { Y = U[j][l1]; Z = U[j][i]; U[j][l1] = Y*C+Z*S; U[j][i] = -Y*S+Z*C; } i++; } } } // Convergence Checking Z = W[k]; if (l!=k) { if (its>=ItnLimit) { RetCode = k; return; } its++; X = W[l]; Y = W[k1]; G = RV1[k1]; H = RV1[k]; F = ((Y-Z)*(Y+Z) + (G-H)*(G+H)) / ( 2.0*H*Y ); if (fabs(F)<=1.0) GG = Sign(sqrt(F*F+1.0),F); else GG = F*sqrt(1.0+1.0/F/F); F = ((X-Z)*(X+Z) + H*(Y/(F+GG)-H)) / X; // Next QR - Transformation C = 1.0; S = 1.0; for (i1=l;i1<=k1;i1++) { i = i1+1; G = RV1[i]; Y = W[i]; H = S*G; G = C*G; Z = SrX2Y2(F,H); RV1[i1] = Z; C = F/Z; S = H/Z; F = X*C+G*S; G = -X*S+G*C; H = Y*S; Y = Y*C; if (MatV) for (j=1;j<=N;j++) { X = V[j][i1]; Z = V[j][i]; V[j][i1] = X*C+Z*S; V[j][i] = -X*S+Z*C; } Z = SrX2Y2(F,H); W[i1] = Z; if (Z!=0.0) { C = F/Z; S = H/Z; } F = C*G+S*Y; X = -S*G+C*Y; if (MatU) for (j=1;j<=M;j++) { Y = U[j][i1]; Z = U[j][i]; U[j][i1] = Y*C+Z*S; U[j][i] = -Y*S+Z*C; } } RV1[l] = 0.0; RV1[k] = F; W[k] = X; } else if (Z<0.0) { W[k] = -Z; if (MatV) for (j=1;j<=N;j++) V[j][k] = -V[j][k]; } } while (l!=k); } } // ----------------------------------------------------- void OrderSVD ( int M, int N, rmatrix U, rmatrix V, rvector W, bool MatU, bool MatV ) { int i,k,j; realtype P; // External loop of the re-ordering for (i=1;iP) { k = j; P = W[j]; } if (k!=i) { // Swapping the singular value W[k] = W[i]; W[i] = P; // Swapping the U's columns ( if needed ) if (MatU) for (j=1;j<=M;j++) { P = U[j][i]; U[j][i] = U[j][k]; U[j][k] = P; } // Swapping the V's columns ( if needed ) if (MatV) for (j=1;j<=N;j++) { P = V[j][i]; V[j][i] = V[j][k]; V[j][k] = P; } } } } /* #ifndef __STDIO_H #include #endif int main ( int argc, char ** argv, char ** env ) { // Test Jacobi matrix A,T,A1; vector Eigen,Aik; realtype SR; int N,i,j,k,Signal; N = 4; GetMatrixMemory ( A,N,N,1,1 ); GetMatrixMemory ( T,N,N,1,1 ); GetMatrixMemory ( A1,N,N,1,1 ); GetVectorMemory ( Eigen,N,1 ); GetVectorMemory ( Aik ,N,1 ); k = 1; for (i=1;i<=N;i++) for (j=i;j<=N;j++) { A[i][j] = k++; A[i][j] *= 1000.0; A[j][i] = A[i][j]; } printf ( " INITIAL MATRIX:\n" ); for (i=1;i<=N;i++) { for (j=1;j<=N;j++) printf ( " %10.4f",A[i][j] ); printf ( "\n" ); } Jacobi ( N,A,T,Eigen,Aik,Signal ); printf ( "\n EIGEN VALUES AND EIGEN VECTORS:\n" ); for (i=1;i<=N;i++) { printf ( " %10.4f ",Eigen[i] ); for (j=1;j<=N;j++) printf ( " %10.4f",T[j][i] ); printf ( "\n" ); } printf ( "\n measure: " ); for (i=1;i<=N;i++) { SR = 0.0; for (j=1;j<=N;j++) SR += T[j][i]*T[j][i]; printf ( " %10.4f",sqrt(SR) ); } printf ( "\n" ); for (i=1;i<=N;i++) for (j=1;j<=N;j++) { A1[i][j] = 0.0; for (k=1;k<=N;k++) A1[i][j] += T[i][k]*Eigen[k]*T[j][k]; } printf ( "\n RESTORED INITIAL MATRIX:\n" ); for (i=1;i<=N;i++) { for (j=1;j<=N;j++) printf ( " %10.4f",A1[j][i] ); printf ( "\n" ); } FreeMatrixMemory ( A,N,1,1 ); FreeMatrixMemory ( T,N,1,1 ); FreeMatrixMemory ( A1,N,1,1 ); FreeVectorMemory ( Eigen,1 ); FreeVectorMemory ( Aik ,1 ); } */ } } mmdb2-2.0.5/mmdb2/mmdb_mattype.h0000664000175000017500000006434412461512315013311 00000000000000// $Id: mmdb_mattype.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2008. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 10.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MatType_ // ~~~~~~~~~ // **** Functions : // ~~~~~~~~~~~ // GetString ( reads substring from a string ) // GetStrTer ( reads substring and put term-ing null ) // strcpy_n ( copies not more than n characters ) // strcpy_ns ( like strcpy_ns and pads with spaces ) // strcpy_n0 ( like strcpy_n and adds terminating 0 ) // PadSpaces ( pads a string with spaces ) // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_MatType__ #define __MMDB_MatType__ #include #define UseDoubleFloat #ifndef __ClassMacros # define __ClassMacros // A Class definition macros # define DefineClass(ClassName) \ class ClassName; \ typedef ClassName * P##ClassName; \ typedef ClassName & R##ClassName; \ typedef P##ClassName * PP##ClassName; \ typedef P##ClassName & RP##ClassName; // A Structure definition macros # define DefineStructure(StructureName) \ struct StructureName; \ typedef StructureName * P##StructureName; \ typedef StructureName & R##StructureName; \ typedef P##StructureName * PP##StructureName; \ typedef P##StructureName & RP##StructureName; #endif #define UNUSED_ARGUMENT(x) (void)x // ----------------------------------------------------- namespace mmdb { #ifdef UseDoubleFloat typedef double realtype; const realtype MinReal = 2.2250e-307; const realtype MaxReal = 1.7976e+308; const realtype fMinReal = 2.2250e-307; const realtype fMaxReal = 1.7976e+308; #else typedef float realtype; const realtype MinReal = 1.1755e-38; const realtype MaxReal = 3.4020e+38; const realtype fMinReal = 1.1755e-38; const realtype fMaxReal = 3.4020e+38; #endif typedef float shortreal; const shortreal MinShortReal = 1.1755e-38; const shortreal MaxShortReal = 3.4020e+38; #define strrchr LastOccurence #define fstrrchr LastOccurence #define strchr FirstOccurence #define fstrchr FirstOccurence typedef char * pstr; typedef const char * cpstr; typedef unsigned int word; typedef unsigned char byte; typedef signed char short_int; // typedef byte Boolean; typedef unsigned int word2; typedef byte * byteptr; typedef unsigned long lword; typedef byte intUniBin [4]; typedef byte shortUniBin [2]; typedef byte longUniBin [4]; typedef byte wordUniBin [4]; typedef byte realUniBin [10]; typedef byte floatUniBin [5]; typedef byte shortrealUniBin[5]; #ifdef _WIN32 pstr strcasestr ( pstr s1, cpstr s2 ); #endif #ifdef _MSC_VER #define strncasecmp _strnicmp #define strcasecmp _stricmp #endif const int MaxInt = 32767; const int MinInt = -32768; const word MaxWord = 65535L; const long int MaxInt4 = 2147483647L; // MinInt4 would have to be defined as -2147483648, // however some compilers do not like that. To be on safe, // we define it as -2147483647: const long int MinInt4 = -2147483647; const lword MaxWord4 = 4294967295UL; const realtype Pi = 3.141592653589793238462643; const realtype Eu = 2.718281828459045235360287; const realtype ln10 = 2.3025850929940456840179915; // *** vectors X[1..N] : typedef realtype * rvector; typedef int * ivector; typedef word * wvector; typedef byte * bvector; typedef bool * ovector; typedef long * lvector; typedef lword * lwvector; typedef pstr * psvector; // *** matrices X[1..N][1..M] : typedef rvector * rmatrix; typedef ivector * imatrix; typedef wvector * wmatrix; typedef bvector * bmatrix; typedef ovector * omatrix; typedef lvector * lmatrix; typedef lwvector * lwmatrix; typedef psvector * psmatrix; // *** matrices X[1..N][1..M][1..K] : typedef rmatrix * rmatrix3; typedef imatrix * imatrix3; typedef wmatrix * wmatrix3; typedef bmatrix * bmatrix3; typedef omatrix * omatrix3; typedef lmatrix * lmatrix3; typedef lwmatrix * lwmatrix3; typedef psmatrix * psmatrix3; // ------------------------------------------------------------ // Initialization. Some C++ enviroments do not do call // InitMatType() automatically, therefore it is always // advisable to call InitMatType() explicitely from the top of // main(). It is completely harmless and cheap (although // unnecessary) to call InitMatType() multiple times. extern bool InitMatType(); // ------------------------------------------------------------ inline int mround ( realtype X ) { return (int)floor(X+0.5); } inline int ifloor ( realtype X ) { return (int)floor(X); } inline int Abs ( int x ) { return ( x >= 0 ? x : -x ); } inline void ISwap ( int & x, int & y ) { int b = x; x = y; y = b; } inline void WSwap ( word & x, word & y ) { word b = x; x = y; y = b; } inline void BSwap ( byte & x, byte & y ) { byte b = x; x = y; y = b; } inline void OSwap ( bool & x, bool & y ) { bool b = x; x = y; y = b; } inline void LSwap ( long & x, long & y ) { long b = x; x = y; y = b; } inline void RSwap ( realtype & x, realtype & y ) { realtype b = x; x = y; y = b; } inline realtype RMax ( const realtype x1, const realtype x2 ) { return ( x1 > x2 ? x1 : x2 ); } inline long LMax ( const long x1, const long x2 ) { return ( x1 > x2 ? x1 : x2 ); } inline word WMax ( const word x1, const word x2 ) { return ( x1 > x2 ? x1 : x2 ); } inline int IMax ( const int x1, const int x2 ) { return ( x1 > x2 ? x1 : x2 ); } inline realtype RMin ( const realtype x1, const realtype x2 ) { return ( x1 < x2 ? x1 : x2 ); } inline long LMin ( const long x1, const long x2 ) { return ( x1 < x2 ? x1 : x2 ); } inline word WMin ( const word x1, const word x2 ) { return ( x1 < x2 ? x1 : x2 ); } inline int IMin ( const int x1, const int x2 ) { return ( x1 < x2 ? x1 : x2 ); } inline realtype fsign ( const realtype x1, const realtype x2 ) { realtype ax; if (x1>=0.0) ax = x1; else ax = -x1; return ( x2 >= 0.0 ? ax : -ax ); } // ------------------------------------------------------------ // Allocated vectors are enumerated as [Shift..Shift+N-1] // rather than [0..N-1] ! // Get-functions return if memory was allocated; // if allocation attemt fails, vector is assigned with NULL extern bool GetVectorMemory ( rvector & V, word N, word Shift=1 ); extern bool GetVectorMemory ( ivector & I, word N, word Shift=1 ); extern bool GetVectorMemory ( wvector & W, word N, word Shift=1 ); extern bool GetVectorMemory ( bvector & B, word N, word Shift=1 ); extern bool GetVectorMemory ( ovector & O, word N, word Shift=1 ); extern bool GetVectorMemory ( lvector & L, word N, word Shift=1 ); extern bool GetVectorMemory ( lwvector & L, word N, word Shift=1 ); extern bool GetVectorMemory ( psvector & P, word N, word Shift=1 ); // Shift at deallocation MUST be the same as that at allocation ! // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Free-functions do nothing if vector has value NULL (e.g. // after unsuccessful allocation). extern void FreeVectorMemory ( rvector & V, word Shift=1 ); extern void FreeVectorMemory ( ivector & I, word Shift=1 ); extern void FreeVectorMemory ( wvector & W, word Shift=1 ); extern void FreeVectorMemory ( bvector & B, word Shift=1 ); extern void FreeVectorMemory ( ovector & O, word Shift=1 ); extern void FreeVectorMemory ( lvector & L, word Shift=1 ); extern void FreeVectorMemory ( lwvector & L, word Shift=1 ); extern void FreeVectorMemory ( psvector & P, word Shift=1 ); // ------------------------------------------------------------- // Allocated matrices are enumerated as // [ShiftN..ShiftN+N-1, ShiftM..ShiftM+M-1] // rather than [0..N-1,0..M-1] ! // Get-functions return if memory was allocated; // if allocation attemt fails, matrix is assigned with NULL // Free-functions do nothing if matrix has value NULL (e.g. // after unsuccessful allocation). extern bool GetMatrixMemory ( rmatrix & A, word N, word M, word ShiftN=1, word ShiftM=1 ); extern bool GetMatrixMemory ( imatrix & A, word N, word M, word ShiftN=1, word ShiftM=1 ); extern bool GetMatrixMemory ( wmatrix & W, word N, word M, word ShiftN=1, word ShiftM=1 ); extern bool GetMatrixMemory ( bmatrix & B, word N, word M, word ShiftN=1, word ShiftM=1 ); extern bool GetMatrixMemory ( omatrix & O, word N, word M, word ShiftN=1, word ShiftM=1 ); extern bool GetMatrixMemory ( lmatrix & L, word N, word M, word ShiftN=1, word ShiftM=1 ); extern bool GetMatrixMemory ( lwmatrix & L, word N, word M, word ShiftN=1, word ShiftM=1 ); extern bool GetMatrixMemory ( psmatrix & P, word N, word M, word ShiftN=1, word ShiftM=1 ); // ShiftN and ShiftM at deallocation MUST be the same as those at // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // allocation ! // ~~~~~~~~~~~~~ extern void FreeMatrixMemory ( rmatrix & A, word N, word ShiftN=1, word ShiftM=1 ); extern void FreeMatrixMemory ( imatrix & A, word N, word ShiftN=1, word ShiftM=1 ); extern void FreeMatrixMemory ( wmatrix & W, word N, word ShiftN=1, word ShiftM=1 ); extern void FreeMatrixMemory ( bmatrix & B, word N, word ShiftN=1, word ShiftM=1 ); extern void FreeMatrixMemory ( omatrix & O, word N, word ShiftN=1, word ShiftM=1 ); extern void FreeMatrixMemory ( lmatrix & L, word N, word ShiftN=1, word ShiftM=1 ); extern void FreeMatrixMemory ( lwmatrix & L, word N, word ShiftN=1, word ShiftM=1 ); extern void FreeMatrixMemory ( psmatrix & P, word N, word ShiftN=1, word ShiftM=1 ); // ------------------------------------------------------------- // 3D matrices extern bool GetMatrix3Memory ( rmatrix3 & A, word N, word M, word K, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern bool GetMatrix3Memory ( imatrix3 & A, word N, word M, word K, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern bool GetMatrix3Memory ( wmatrix3 & A, word N, word M, word K, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern bool GetMatrix3Memory ( bmatrix3 & A, word N, word M, word K, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern bool GetMatrix3Memory ( omatrix3 & A, word N, word M, word K, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern bool GetMatrix3Memory ( lmatrix3 & A, word N, word M, word K, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern bool GetMatrix3Memory ( lwmatrix3 & A, word N, word M, word K, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern bool GetMatrix3Memory ( psmatrix3 & A, word N, word M, word K, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); // // ShiftN, ShiftM and ShiftK at deallocation MUST be // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // the same as those at allocation ! // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ extern void FreeMatrix3Memory ( rmatrix3 & A, word N, word M, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern void FreeMatrix3Memory ( imatrix3 & A, word N, word M, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern void FreeMatrix3Memory ( wmatrix3 & A, word N, word M, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern void FreeMatrix3Memory ( bmatrix3 & A, word N, word M, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern void FreeMatrix3Memory ( omatrix3 & A, word N, word M, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern void FreeMatrix3Memory ( lmatrix3 & A, word N, word M, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern void FreeMatrix3Memory ( lwmatrix3 & A, word N, word M, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); extern void FreeMatrix3Memory ( psmatrix3 & A, word N, word M, word ShiftN=1, word ShiftM=1, word ShiftK=1 ); // ------------------------------------------------------------- extern realtype MachEps; extern realtype floatMachEps; extern realtype LnMaxReal; extern realtype LnMinReal; extern realtype MachinEps (); extern realtype floatMachinEps(); extern realtype frac ( realtype R ); extern long mod ( long x, long y ); extern realtype Pow ( realtype X, int y ); extern realtype Pow1 ( realtype X, realtype Y ); extern realtype Exp ( realtype X ); // use to avoid catastrophies extern bool Odd ( int i ); extern long HexValL ( cpstr S ); extern long OctValL ( cpstr S ); extern long BinValL ( cpstr S ); extern pstr BinValS ( long L, pstr S ); // S[sizeof(long)+1] at least extern pstr ParamStr ( pstr D, cpstr S, realtype V, int M=5, cpstr S1=(pstr)"" ); extern pstr ParamStr ( pstr D, cpstr S, realtype V, int M, cpstr S1, realtype V2, int M2=5, cpstr S2=(pstr)"" ); // ---------- Strings // CreateCopy(..) allocates Dest string and copies the contents of // Source into it. If Dest is not NULL prior calling the function, // it is attempted to deallocate first. extern pstr CreateCopy ( pstr & Dest, cpstr Source ); extern pstr CreateCopy_n ( pstr & Dest, cpstr Source, int n ); extern pstr CreateConcat ( pstr & Dest, cpstr Source ); extern pstr CreateConcat ( pstr & Dest, cpstr Source1, cpstr Source2 ); extern pstr CreateConcat ( pstr & Dest, cpstr Source1, cpstr Source2, cpstr Source3 ); extern pstr CreateConcat ( pstr & Dest, cpstr Source1, cpstr Source2, cpstr Source3, cpstr Source4 ); extern pstr CreateConcat ( pstr & Dest, cpstr Source1, cpstr Source2, cpstr Source3, cpstr Source4, cpstr Source5 ); extern pstr CreateCopCat ( pstr & Dest, cpstr Source1, cpstr Source2, cpstr Source3, cpstr Source4, cpstr Source5 ); extern pstr CreateCopCat ( pstr & Dest, cpstr Source1, cpstr Source2, cpstr Source3, cpstr Source4 ); extern pstr CreateCopCat ( pstr & Dest, cpstr Source1, cpstr Source2, cpstr Source3 ); extern pstr CreateCopCat ( pstr & Dest, cpstr Source1, cpstr Source2 ); extern pstr LastOccurence ( cpstr S , char c ); extern pstr FirstOccurence ( cpstr S , char c ); extern int indexOf ( cpstr S , char c ); extern pstr FirstOccurence ( cpstr S, int Slen, cpstr Q, int Qlen ); extern int indexOf ( cpstr S, int Slen, cpstr Q, int Qlen ); extern pstr LowerCase ( pstr s ); extern pstr UpperCase ( pstr s ); // GetString(..) copies first M characters of string S into string // L, appending the terminating null. If S contains less then M // characters, L will be padded with spaces. extern void GetString ( pstr L, cpstr S, int M ); // GetStrTer(..) copies at least n (or LMax if LMax5 // (terminating null appended). // The function returns d. extern pstr strcpy_ncs ( pstr d, cpstr s, int n ); // strcpy_css(..) copies string s to string d cutting all // spaces at the begining and at the end. Thus, " ab c de " // will be copied like "ab c de" (terminating null appended). // The function returns d. extern pstr strcpy_css ( pstr d, cpstr s ); // strcpy_ncss(..) copies at most n characters from string s // to string d cutting all spaces at the begining and at the end. // Thus, " ab c de " will be copied like "ab" at n=3 (terminating // null appended). // The function returns d. extern pstr strcpy_ncss ( pstr d, cpstr s, int n ); // strcpy_n0(..) copies at most n symbols from string s to d, // but no more than strlen(s) (s must contain a terminating // null). The terminating null IS appended to d. // The function returns d. extern pstr strcpy_n0 ( pstr d, cpstr s, int n ); // strlen_des returns the length of a string as if all extra // spaces from the latter have been deleted. Extra spaces // include all leading and tracing spaces and any sequential // spaces when more than one. The string does not change. extern int strlen_des ( cpstr s ); // strcpy_des copies string s into string d removing all extra // spaces from the latter. Extra spaces include all leading and // tracing spaces and any sequential spaces when more than one. extern pstr strcpy_des ( pstr d, cpstr s ); // strcat_des appends string s to string d removing all extra // spaces from the latter. Extra spaces include all leading and // tracing spaces and any sequential spaces when more than one. extern pstr strcat_des ( pstr d, cpstr s ); // PadSpaces(..) pads string S with spaces making its length // equal to len. The terminating zero is added, so that S should // reserve space of a minimum len+1 characters. extern void PadSpaces ( pstr S, int len ); enum SCUTKEY { SCUTKEY_BEGIN = 0x00000001, SCUTKEY_END = 0x00000002, SCUTKEY_BEGEND = 0x00000003 }; // CutSpaces(..) cuts spaces at the begining or end of // string S according to the value of CutKey. The function // returns S. extern pstr CutSpaces ( pstr S, int CutKey ); // DelSpaces(..) removes all spaces (or other symbols as // specified by 'c') from the string. The string is then // shrinked by the number of removed characters. Thus, // " as ttt " becomes "asttt". extern pstr DelSpaces ( pstr S, char c=' ' ); // EnforceSpaces(..) replaces all unprintable characters, // except , , and some others, for spaces extern pstr EnforceSpaces ( pstr S ); // ------------------------------------------------------------- /// This call will produce correct floats in universal binaries but /// make them incompatible with old files. Without this call, float /// read/write will result in error after 6th digit. /// UniBin read/write of other types (realtype, shortreal, int etc) /// is not affected by this call, and to the best of knowledge is /// correct (no loss of precision). extern void set_new_float_unibin(); extern bool is_new_float_unibin(); extern void set_old_float_unibin(); extern void __modify4(); extern void int2UniBin ( int I, intUniBin iUB ); extern void short2UniBin ( short S, shortUniBin sUB ); extern void long2UniBin ( long L, longUniBin lUB ); extern void word2UniBin ( word W, wordUniBin wUB ); extern void real2UniBin ( realtype R, realUniBin rUB ); extern void float2UniBin ( realtype R, floatUniBin fUB ); extern void shortreal2UniBin ( shortreal R, shortrealUniBin srUB ); extern void UniBin2int ( intUniBin iUB, int & I ); extern void UniBin2short ( shortUniBin sUB, short & S ); extern void UniBin2long ( longUniBin lUB, long & L ); extern void UniBin2word ( wordUniBin wUB, word & W ); extern void UniBin2real ( realUniBin rUB, realtype & R ); extern void UniBin2shortreal ( shortrealUniBin srUB, shortreal & R ); extern void UniBin2float ( floatUniBin fUB, realtype & R ); extern void mem_write ( int I, pstr S, int & l ); extern void mem_write ( short I, pstr S, int & l ); extern void mem_write ( long I, pstr S, int & l ); extern void mem_write ( word W, pstr S, int & l ); extern void mem_write ( realtype R, pstr S, int & l ); extern void mem_write ( shortreal R, pstr S, int & l ); extern void mem_write ( pstr L, int len, pstr S, int & l ); extern void mem_write ( pstr L, pstr S, int & l ); extern void mem_write ( bool B, pstr S, int & l ); extern void mem_write_byte ( byte B, pstr S, int & l ); extern void mem_read ( int & I, cpstr S, int & l ); extern void mem_read ( short & I, cpstr S, int & l ); extern void mem_read ( long & I, cpstr S, int & l ); extern void mem_read ( word & W, cpstr S, int & l ); extern void mem_read ( realtype & R, cpstr S, int & l ); extern void mem_read ( shortreal & R, cpstr S, int & l ); extern void mem_read ( pstr L, int len, cpstr S, int & l ); extern void mem_read ( pstr & L, cpstr S, int & l ); extern void mem_read ( bool & B, cpstr S, int & l ); extern void mem_read_byte ( byte & B, cpstr S, int & l ); } #endif /* =================================================== */ mmdb2-2.0.5/mmdb2/mmdb_utils.h0000664000175000017500000006130512461512315012760 00000000000000// $Id: mmdb_utils.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2008. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDBF_Utils // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // // **** Classes : mmdb::ContainerClass ( containered class template ) // ~~~~~~~~~ mmdb::ContString ( containered string ) // mmdb::ClassContainer ( container of classes ) // mmdb::AtomPath ( atom path ID ) // mmdb::QuickSort ( quick sort of integers ) // // **** Functions : Date9to11 ( DD-MMM-YY -> DD-MMM-YYYY ) // ~~~~~~~~~~~ Date11to9 ( DD-MMM-YYYY -> DD-MMM-YY ) // Date9toCIF ( DD-MMM-YY -> YYYY-MM-DD ) // Date11toCIF( DD-MMM-YYYY -> YYYY-MM-DD ) // DateCIFto9 ( YYYY-MM-DD -> DD-MMM-YY ) // DateCIFto11( YYYY-MM-DD -> DD-MMM-YYYY ) // GetInteger ( reads integer from a string ) // GetReal ( reads real from a string ) // GetIntIns ( reads integer and insert code ) // PutInteger ( writes integer into a string ) // PutRealF ( writes real in F-form into a string ) // PutIntIns ( writes integer and insert code ) // CIFGetInteger ( reads and deletes int from CIF ) // CIFGetReal ( reads and deletes real from CIF ) // CIFGetString ( reads and deletes string from CIF) // CIFGetInteger1 (reads and del-s int from CIF loop) // CIFGetReal1 (reads and del-s int from CIF loop) // Mat4Inverse ( inversion of 4x4 matrices ) // GetErrorDescription (ascii line to an Error_XXXXX) // ParseAtomID ( parses atom ID line ) // ParseResID ( parses residue ID line ) // ParseAtomPath ( parses full atom path ) // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_Utils__ #define __MMDB_Utils__ #include "mmdb_io_stream.h" #include "mmdb_mmcif_.h" #include "mmdb_defs.h" namespace mmdb { // ================== Date functions =================== // converts DD-MMM-YY to DD-MMM-YYYY; appends terminating zero extern void Date9to11 ( cpstr Date9, pstr Date11 ); // converts DD-MMM-YYYY to DD-MMM-YY; does not append terminating zero extern void Date11to9 ( cpstr Date11, pstr Date9 ); // converts DD-MMM-YY to YYYY-MM-DD; appends terminating zero extern void Date9toCIF ( cpstr Date9, pstr DateCIF ); // converts DD-MMM-YYYY to YYYY-MM-DD; appends terminating zero extern void Date11toCIF ( cpstr Date11, pstr DateCIF ); // converts YYYY-MM-DD to DD-MMM-YY; appends terminating zero extern void DateCIFto9 ( cpstr DateCIF, pstr Date9 ); // converts YYYY-MM-DD to DD-MMM-YYYY; appends terminating zero extern void DateCIFto11 ( cpstr DateCIF, pstr Date11 ); // ================= Format functions ================== // Returns true if S contains an integer number in its // first M characters. This number is returned in N. // The return is false if no integer number may be // recognized. In this case, N is assigned MinInt4 value. extern bool GetInteger ( int & N, cpstr S, int M ); // Returns true if S contains a real number in its // first M characters. This number is returned in R. // The return is false if no real number may be // recognized. In this case, R is assigned -MaxReal value. extern bool GetReal ( realtype & R, cpstr S, int M ); // Returns true if S contains an integer number in its // first M characters. This number is returned in N. In addition // to that, GetIntIns() retrieves the insertion code which may // follow the integer and returns it in "ins" (1 character + // terminating 0). // The return is false if no integer number may be // recognized. In this case, N is assigned MinInt4 value, // "ins" just returns (M+1)th symbol of S (+terminating 0). extern bool GetIntIns ( int & N, pstr ins, cpstr S, int M ); // Integer N is converted into ASCII string of length M // and pasted onto first M characters of string S. No // terminating zero is added. // If N is set to MinInt4, then first M characters of // string S are set to space. extern void PutInteger ( pstr S, int N, int M ); // Real R is converted into ASCII string of length M // and pasted onto first M characters of string S. No // terminating zero is added. The conversion is done // according to fixed format FM.L // If R is set to -MaxReal, then first M characters of // string S are set to the space character. extern void PutRealF ( pstr S, realtype R, int M, int L ); // Integer N is converted into ASCII string of length M // and pasted onto first M characters of string S. No // terminating zero is added. The insert code ins is put // immediately after the integer. // If N is set to MinInt4, then first M+1 characters of // string S are set to space, and no insert code are // appended. extern void PutIntIns ( pstr S, int N, int M, cpstr ins ); // CIFInteger(..), CIFReal(..) and CIFGetString(..) automate // extraction and analysis of data from CIF file. If the data // is erroneous or absent, they store an error message in // CIFErrorLocation string (below) and return non-zero. extern ERROR_CODE CIFGetInteger ( int & I, mmcif::PStruct Struct, cpstr Tag, bool Remove=true ); extern ERROR_CODE CIFGetReal ( realtype & R, mmcif::PStruct Struct, cpstr Tag, bool Remove=true ); extern ERROR_CODE CIFGetString ( pstr S, mmcif::PStruct Struct, cpstr Tag, int SLen, cpstr DefS, bool Remove=true ); extern ERROR_CODE CIFGetInteger ( int & I, mmcif::PLoop Loop, cpstr Tag, int & Signal ); extern ERROR_CODE CIFGetIntegerD ( int & I, mmcif::PLoop Loop, cpstr Tag, int defValue=MinInt4 ); extern ERROR_CODE CIFGetInteger1 ( int & I, mmcif::PLoop Loop, cpstr Tag, int nrow ); extern ERROR_CODE CIFGetReal ( realtype & R, mmcif::PLoop Loop, cpstr Tag, int & Signal ); extern ERROR_CODE CIFGetReal1 ( realtype & R, mmcif::PLoop Loop, cpstr Tag, int nrow ); extern ERROR_CODE CIFGetString ( pstr S, mmcif::PLoop Loop, cpstr Tag, int row, int SLen, cpstr DefS ); // Calculates AI=A^{-1} extern void Mat4Inverse ( mat44 & A, mat44 & AI ); // Calculates A=B*C extern void Mat4Mult ( mat44 & A, mat44 & B, mat44 & C ); // Calculates A=B^{-1}*C extern void Mat4Div1 ( mat44 & A, mat44 & B, mat44 & C ); // Calculates A=B*C^{-1} extern void Mat4Div2 ( mat44 & A, mat44 & B, mat44 & C ); // Calculates determinant of the rotation part extern realtype Mat4RotDet ( mat44 & T ); // Sets up a unit matrix extern void Mat4Init ( mat44 & A ); extern void Mat3Init ( mat33 & A ); // Calculates AI=A^{-1}, returns determinant extern realtype Mat3Inverse ( mat33 & A, mat33 & AI ); extern bool isMat4Unit ( mat44 & A, realtype eps, bool rotOnly ); // Copies A into AC extern void Mat4Copy ( mat44 & A, mat44 & ACopy ); extern void Mat3Copy ( mat33 & A, mat33 & ACopy ); extern bool isMat4Eq ( mat44 & A, mat44 & B, realtype eps, bool rotOnly ); extern void TransformXYZ ( mat44 & T, realtype & X, realtype & Y, realtype & Z ); extern realtype TransformX ( mat44 & T, realtype X, realtype Y, realtype Z ); extern realtype TransformY ( mat44 & T, realtype X, realtype Y, realtype Z ); extern realtype TransformZ ( mat44 & T, realtype X, realtype Y, realtype Z ); extern char CIFErrorLocation[200]; // Returns ASCII string explaining the nature of // Error_xxxx error code. extern cpstr GetErrorDescription ( ERROR_CODE ErrorCode ); // ================ ContainerClass ==================== DefineClass(ContainerClass); DefineStreamFunctions(ContainerClass); class ContainerClass : public io::Stream { friend class ClassContainer; public : ContainerClass (); ContainerClass ( io::RPStream Object ); ~ContainerClass() {} // ConvertPDBASCII(..) will return one of the Error_XXXXX // constants, see virtual ERROR_CODE ConvertPDBASCII ( cpstr ) { return Error_NoError; } virtual void PDBASCIIDump ( pstr, int ) {} virtual bool PDBASCIIDump1 ( io::RFile ) { return false; } virtual void MakeCIF ( mmcif::PData, int ) {} // Append(..) should return true if CC is appended to this class. // If this is not the case, CC is merely put on the top of // container. // Note: Append(..) detects the necessity to append CC and // performs all the necessary actions for that. The rest of CC // will be disposed by Class Container. // Note: Class Container checks every new class, which is // being added to it (see CClassContainer::AddData(..)), only // against the top of container. virtual bool Append ( PContainerClass CC ); // GetCIF(..) extracts any necessary information from CIF and // returns in Signal: // Error_noError : the information was successfully extracted, // this instance of container class should be // stored, and unchanged value of Signal should // be passed to the next (newly created) instance // of this container class. // Error_EmptyCIF : there is no information for this type of // containers to extract. This instance of // container class should be deleted and input // for this type of container class terminated. // Other : the corresponding error. This instance of // container class should be deleted and the // whole input stopped. virtual ERROR_CODE GetCIF ( mmcif::PData, int & n ) { n = -1; return Error_EmptyCIF; } virtual CLASS_ID GetClassID () { return ClassID_Template; } virtual void Copy ( PContainerClass ) {} void write ( io::RFile ) {} void read ( io::RFile ) {} protected : int ContinuationNo; }; // ======================== ContString ========================= DefineClass(ContString); DefineStreamFunctions(ContString); class ContString : public ContainerClass { public : pstr Line; // a string ContString (); ContString ( cpstr S ); ContString ( io::RPStream Object ); ~ContString(); ERROR_CODE ConvertPDBASCII ( cpstr S ); void PDBASCIIDump ( pstr S, int N ); bool PDBASCIIDump1 ( io::RFile f ); void MakeCIF ( mmcif::PData CIF, int N ); // void GetCIF1 ( mmcif::PData CIF, ERROR_CODE & Signal, // int & pos ); bool Append ( PContainerClass ContString ); CLASS_ID GetClassID () { return ClassID_String; } void Copy ( PContainerClass CString ); void write ( io::RFile f ); void read ( io::RFile f ); protected : pstr CIFCategory,CIFTag; void InitString(); }; // ============== ClassContainer ==================== DefineClass(ClassContainer); DefineStreamFunctions(ClassContainer); class ClassContainer : public io::Stream { public : ClassContainer (); ClassContainer ( io::RPStream Object ); ~ClassContainer (); void FreeContainer (); void AddData ( PContainerClass Data ); virtual void PDBASCIIDump ( io::RFile f ); virtual void MakeCIF ( mmcif::PData CIF ); // GetCIF(..) will return one of the Error_XXXXX constants, // see virtual ERROR_CODE GetCIF ( mmcif::PData CIF, int ClassID ); virtual PContainerClass MakeContainerClass ( int ClassID ); // Copy will empty the class if parameter is set to NULL virtual void Copy ( PClassContainer CContainer ); inline int Length() { return length; } PContainerClass GetContainerClass ( int ContClassNo ); void write ( io::RFile f ); void read ( io::RFile f ); protected : int length; PPContainerClass Container; void Init(); }; // ====================== ID parsers ========================== DefineClass(AtomPath); DefineStreamFunctions(AtomPath); enum APATH_FLAG { APATH_ModelNo = 0x00000001, APATH_ChainID = 0x00000002, APATH_SeqNum = 0x00000004, APATH_InsCode = 0x00000008, APATH_ResName = 0x00000010, APATH_AtomName = 0x00000020, APATH_Element = 0x00000040, APATH_AltLoc = 0x00000080, APATH_Incomplete = 0x00000100, APATH_WC_ModelNo = 0x00001000, APATH_WC_ChainID = 0x00002000, APATH_WC_SeqNum = 0x00004000, APATH_WC_InsCode = 0x00008000, APATH_WC_ResName = 0x00010000, APATH_WC_AtomName = 0x00020000, APATH_WC_Element = 0x00040000, APATH_WC_AltLoc = 0x00080000 }; class AtomPath : public io::Stream { public : int modelNo; ChainID chainID; int seqNum; InsCode insCode; ResName resName; AtomName atomName; Element element; AltLoc altLoc; int isSet; AtomPath (); AtomPath ( cpstr ID ); AtomPath ( io::RPStream Object ); ~AtomPath (); // SetPath(..) parses the Atom Path ID string, which // may be incomplete. Below {..} means blocks that // may be omitted; any elements within such blocks // may be omitted as well. // // 1. If ID starts with '/' then the ID must be of // the following form: // /mdl{/chn{/seq(res).i{/atm[elm]:a}}} // // 2. If ID starts with a letter: // chn{/seq(res).i{/atm[elm]:a}} // // 3. If ID starts with a number or '(': // seq(res).i{/atm[elm]:a} // // 4. If ID contains colon ':' or '[' then // it may be just // atm[elm]:a // // The following are valid samples of IDs: // // /1 model number 1 // /1/A/23(GLU).A/CA[C]:A model number 1, chain A, // residue 23 GLU insertion code A, C-alpha // atom in alternative location A // A/23 residue 23 of chain A // CA[C]: atom C-alpha // [C] a carbon // *[C]:* same as above // :A an atom with insertion code A // 5 residue number 5 // (GLU) residue GLU // // All spaces are ignored. SetPath(..) sets bit of isSet // for each element present. Any element may be a wildcard // '*'. Wildcard for model will set modelNo=0, for sequence // number will set seqNum=MinInt4. // // Returns: // 0 <-> Ok // -1 <-> wrong numerical format for model // -2 <-> wrong numerical format for sequence number int SetPath ( cpstr ID ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitAtomPath(); }; // -------------------------------------------------------------- DefineClass(QuickSort); class QuickSort : public io::Stream { public : QuickSort (); QuickSort ( io::RPStream Object ); ~QuickSort() {} virtual int Compare ( int i, int j ); virtual void Swap ( int i, int j ); void Sort ( void * sortdata, int data_len ); protected : int selSortLimit,dlen; void * data; void SelectionSort ( int left, int right ); int Partition ( int left, int right ); void Quicksort ( int left, int right ); }; // -------------------------------------------------------------- extern void takeWord ( pstr & p, pstr wrd, cpstr ter, int l ); // ParseAtomID(..) reads the atom ID of the following form: // {name} {[element]} {:altcode} // (here {} means that the item may be omitted; any field may have // value of wildcard '*'), and returns the atom name in aname, // element name - in elname, and alternate location code - in aloc. // Except for the alternate location code, missing items are // replaced by wildcards. Missing alternate location code is // returned as empty string "". // Leading spaces are allowed; any other space will terminate // the parsing. // The followings are perfectly valid atom IDs: // CA[C]:A (carbon C_alpha in location A) // CA[*]:A (either C_alpha or Ca in location A) // CA:A (same as above) // CA (either C_alpha or Ca with no location indicator) // CA[] (same as above) // CA[C]: (C_alpha with no location indicator) // [C] (any carbon with no location indicator) // [C]:* (any carbon with any location indicator) // *[C]:* (same as above) // :A (any atom in location A) // *[*]:A (same as above) // *[*]:* (any atom) // * (any atom with no alternate location indicator) extern void ParseAtomID ( cpstr ID, AtomName aname, Element elname, AltLoc aloc ); // ParseResID(..) reads the residue ID of the following form: // {seqnum} {(name)} {.inscode} // (here {} means that the item may be omitted; any field may have // value of wildcard '*'), and returns the sequence number in sn, // insertion code - in inscode, and residue name - in resname. // If a wildcard was specified for the sequence number, then // ParseResID(..) returns 1. Missing residue name is replaced by // the wildcard '*', and misisng insertion code is returned as empty // string "". // Leading spaces are allowed; any other space will terminate // the parsing. // Return 0 means Ok, 1 - wildcard for the sequence number, // 2 - an error in numerical format of the sequence number // (other items are parsed). // The followings are perfectly valid residue IDs: // 27(ALA).A (residue 27A ALA) // 27().A (residue 27A) // 27(*).A (same as above) // 27.A (same as above) // 27 (residue 27) // 27(). (same as above) // (ALA) (any ALA without insertion code) // (ALA). (same as above) // (ALA).* (any ALA) // *(ALA).* (any ALA) // .A (any residue with insertion code A) // *(*).A (same as above) // *(*).* (any residue) // * (any residue with no insertion code) extern int ParseResID ( cpstr ID, int & sn, InsCode inscode, ResName resname ); // ParseAtomPath(..) parses an atom path string of the following // structure: // /mdl/chn/seq(res).i/atm[elm]:a // where all items may be represented by a wildcard '*' and // mdl - model number (mandatory); at least model #1 is always // present; returned in mdl; on a wildcard mdl is set to 0 // chn - chain identifier ( mandatory); returned in chn; on a // wildcard chn is set to '*' // seq - residue sequence number (mandatory); returned in sn; // on a wild card ParseAtomPath(..) returns 1 // (res) - residue name in round brackets (may be omitted); // returnded in res; on a wildcard res is set to '*' // .i - insert code after a dot; if '.i' or 'i' is missing // then a residue without an insertion code is looked for; // returned in ic; on a wildcard (any insertion code would // do) ic is set to '*' // atm - atom name (mandatory); returned in atm; on a wildcard // atm is set to '*' // [elm] - chemical element code in square brackets; it may // be omitted but could be helpful for e.g. // distinguishing C_alpha and CA; returned in elm; // in a wildcard elm is set to '*' // :a - alternate location indicator after colon; if // ':a' or 'a' is missing then an atom without // alternate location indicator is looked for; returned // in aloc; on a wildcard (any alternate code would do) // aloc is set to '*'. // All spaces are ignored, all identifiers should be in capital // letters (comparisons are case-sensitive). // The atom path string may be incomplete. If DefPath is supplied, // the function will try to get missing elements from there. If // missing items may not be found in DefPath, they are replaced by // wildcards. // ParseAtomPath(..) returns the following bits: // 0 - Ok // APATH_Incomplete - if path contains wildcards. Wildcards for // residue name and chemical element will be // ignored here if sequence number and // atom name, correspondingly, are provided. // APATH_WC_XXXXX - wildcard for different elements // -1 - wrong numerical format for model (fatal) // -2 - wrong numerical format for seqNum (fatal) extern int ParseAtomPath ( cpstr ID, int & mdl, ChainID chn, int & sn, InsCode ic, ResName res, AtomName atm, Element elm, AltLoc aloc, PAtomPath DefPath=NULL ); extern int ParseSelectionPath ( cpstr CID, int & iModel, pstr Chains, int & sNum1, InsCode ic1, int & sNum2, InsCode ic2, pstr RNames, pstr ANames, pstr Elements, pstr altLocs ); extern void MakeSelectionPath ( pstr CID, int iModel, cpstr Chains, int sNum1, const InsCode ic1, int sNum2, const InsCode ic2, cpstr RNames, cpstr ANames, cpstr Elements, cpstr altLocs ); } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_xml_.h0000664000175000017500000001332212401105774012554 00000000000000// $Id: mmdb_xml_.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 06.12.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_XML // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::xml::XMLObject // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_XML__ #define __MMDB_XML__ #include "mmdb_mmcif_.h" namespace mmdb { namespace xml { // ====================== XMLObject ========================== enum XML_RC { XMLRC_Ok = 0, XMLRC_NoFile = 1, XMLRC_CantOpenFile = 2, XMLRC_NoTag = 3, XMLRC_BrokenTag = 4, XMLRC_UnclosedTag = 5, XMLRC_RFormatError = 6, XMLRC_IFormatError = 7, XMLRC_OFormatError = 8 }; DefineClass(XMLObject); DefineStreamFunctions(XMLObject); class XMLObject : public io::Stream { public : XMLObject (); XMLObject ( cpstr Tag ); XMLObject ( cpstr Tag, cpstr Data ); XMLObject ( cpstr Tag, realtype V, int length=11 ); XMLObject ( cpstr Tag, int iV, int length=0 ); XMLObject ( cpstr Tag, bool bV ); XMLObject ( cpstr Tag, PXMLObject XMLObject ); XMLObject ( io::RPStream Object ); ~XMLObject(); void SetTag ( cpstr Tag ); void AddAttribute ( cpstr name, cpstr value ); void AddAttribute ( cpstr name, const int iV ); void AddAttribute ( cpstr name, const bool bV ); void SetData ( cpstr Data ); void AddData ( cpstr Data ); void SetData ( const realtype V, const int length=11 ); void SetData ( const int iV, const int length=0 ); void SetData ( const bool bV ); int AddMMCIFCategory ( mmcif::PCategory mmCIFCat ); int AddMMCIFStruct ( mmcif::PStruct mmCIFStruct ); int AddMMCIFLoop ( mmcif::PLoop mmCIFLoop ); int AddMMCIFData ( mmcif::PData mmCIFData ); inline pstr GetTag() { return objTag; } // Here and below the functions allow for "tag1>tag2>tag3>..." // as a composite multi-level tag, e.g. the above may stand for // data. NULL tag // corresponds to "this" object. // objNo counts same-tag objects of the *highest* level used // (e.g. level tag3 for composite tag tag1>tag2>tag3 ). // GetData ( pstr& ... ) only copies a pointer to data. pstr GetData ( cpstr Tag=NULL, int objNo=1 ); XML_RC GetData ( pstr & Data, cpstr Tag=NULL, int objNo=1 ); XML_RC GetData ( realtype & V, cpstr Tag=NULL, int objNo=1 ); XML_RC GetData ( int & iV, cpstr Tag=NULL, int objNo=1 ); XML_RC GetData ( bool & bV, cpstr Tag=NULL, int objNo=1 ); PXMLObject GetObject ( cpstr Tag, int objNo=1 ); PXMLObject GetFirstObject(); PXMLObject GetLastObject (); inline int GetNumberOfObjects() { return nObjects; } PXMLObject GetObject ( int objectNo ); // 0,1,... inline PXMLObject GetParent() { return parent; } void AddObject ( PXMLObject XMLObject, int lenInc=10 ); void InsertObject ( PXMLObject XMLObject, int pos, int lenInc=10 ); XML_RC WriteObject ( cpstr FName, int pos=0, int ident=2 ); void WriteObject ( io::RFile f, int pos=0, int ident=2 ); XML_RC ReadObject ( cpstr FName ); XML_RC ReadObject ( io::RFile f, pstr S, int & pos, int slen ); virtual void Copy ( PXMLObject xmlObject ); void write ( io::RFile f ); void read ( io::RFile f ); protected: PXMLObject parent; pstr objTag; pstr objData; int nObjects,nAlloc; PPXMLObject object; int nAttributes,nAttrAlloc; psvector attr_name,attr_value; void InitXMLObject(); virtual void FreeMemory (); inline void SetParent ( PXMLObject p ) { parent = p; } }; extern PXMLObject mmCIF2XML ( mmcif::PData mmCIFData, int * rc=NULL ); extern PXMLObject mmCIF2XML ( cpstr XMLName, mmcif::PFile mmCIFFile, int * rc=NULL ); } // namespace xml } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/hybrid_36.h0000664000175000017500000000300112461512315012377 00000000000000// $Id: hybrid_36.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // /* If you change the include guards, please be sure to also rename the functions below. Otherwise your project will clash with the original iotbx declarations and definitions. */ #ifndef IOTBX_PDB_HYBRID_36_C_H #define IOTBX_PDB_HYBRID_36_C_H #ifdef __cplusplus extern "C" { #endif const char* hy36encode(unsigned width, int value, char* result); const char* hy36decode(unsigned width, const char* s, unsigned s_size, int* result); #ifdef __cplusplus } #endif #endif /* IOTBX_PDB_HYBRID_36_C_H */ mmdb2-2.0.5/mmdb2/mmdb_selmngr.h0000664000175000017500000007061512601171753013276 00000000000000// $Id: mmdb_selmngr.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 15.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : mmdb_selmngr // ~~~~~~~~~ // Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::Manager ( MMDB atom selection manager ) // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_SelMngr__ #define __MMDB_SelMngr__ #include "mmdb_coormngr.h" #include "mmdb_mask.h" namespace mmdb { // ======================= SelManager ========================== // Selection keys. These specify how the requested selection // operation applies to the existing selection for the given mask: // SKEY_NEW previous selection is wiped out // SKEY_OR new selection is added to the already selected set; // if no selection preexists, SKEY_NEW and SKEY_OR // are equivalent. This key is the default one in // all selection functions. // SKEY_AND new selection is made on the already selected set; // this corresponds to logical 'and' of former and // current selections. If no selection preexists, // no selection will be made. // SKEY_XOR only those atoms will be left which are found // in either former or newly selected sets, but not // in both of them; this corresponds to logical // 'exclusive or' of previous and current selections. // If no selection preexists, it is equivalent to // SKEY_OR. enum SELECTION_KEY { SKEY_NEW = 0, SKEY_OR = 1, SKEY_AND = 2, SKEY_XOR = 3, SKEY_CLR = 4, SKEY_XAND = 100 // used internally }; // Selection types enum SELECTION_TYPE { STYPE_INVALID = -1, STYPE_UNDEFINED = 0, STYPE_ATOM = 1, STYPE_RESIDUE = 2, STYPE_CHAIN = 3, STYPE_MODEL = 4 }; // Residue properties for SelectProperties() enum SELECTION_PROPERTY { SELPROP_Solvent = 0, SELPROP_Aminoacid = 1, SELPROP_Nucleotide = 2, SELPROP_Sugar = 3, SELPROP_ModRes = 4 }; // comparison rules for SelectUDD function enum UDD_CMP_RULE { UDSCR_LT = 1, UDSCR_LE = 2, UDSCR_EQ = 3, UDSCR_NE = 4, UDSCR_GE = 5, UDSCR_GT = 6, UDSCR_LTcase = 7, UDSCR_LEcase = 8, UDSCR_EQcase = 9, UDSCR_NEcase = 10, UDSCR_GEcase = 11, UDSCR_GTcase = 12, UDSCR_LTn = 13, UDSCR_LEn = 14, UDSCR_EQn = 15, UDSCR_NEn = 16, UDSCR_GEn = 17, UDSCR_GTn = 18, UDSCR_LTncase = 19, UDSCR_LEncase = 20, UDSCR_EQncase = 21, UDSCR_NEncase = 22, UDSCR_GEncase = 23, UDSCR_GTncase = 24, UDSCR_Substr = 25, UDSCR_NoSubstr = 26, UDSCR_Substr1 = 27, UDSCR_NoSubstr1 = 28 }; DefineClass(SelManager); DefineStreamFunctions(SelManager); class SelManager : public CoorManager { public : SelManager (); SelManager ( io::RPStream Object ); ~SelManager(); // ==================== Selecting atoms ======================= // NewSelection() creates a new selection mask and returns its // handle. A handle is always a positive (non-zero) integer. // Calling NewSelection() is the only way to create a new // selection mask. Notice however that masks will be automatically // copied from another MMDB (see Copy(..) in CMMDBManager) if // coordinates are copied; if this is the case, the mask handles // will be inherited from the source MMDB as well. The masks will // also be automatically deleted (see Delete(..) in CMMDBManager()) // if coordinates are deleted. int NewSelection (); int GetSelType ( int selHnd ); // returns STYPE_XXXX // DeleteSelection(..) deletes the specified selection mask // and removes the corresponding selection attributes from // all atoms, which were selected with this mask. If an atom // was selected also with other mask(s), the other selection(s) // will remain, provided that the corresponding masks are valid. // After DeleteSelection() returns, the corresponding mask // becomes invalid. void DeleteSelection ( int selHnd ); // DeleteAllSelections() deletes all selection masks and // unselects all atoms in the file. All mask handles become // invalid. void DeleteAllSelections(); // SelectAtoms(..) selects atoms in the serial number range // of iSer1 to iSer2 by adding them to the set of atoms // marked by the given mask. If iSer1=iSer2=0 then all atoms // are selected. Each atom may be selected by a number of masks // simultaneously. void SelectAtoms ( int selHnd, int iSer1, int iSer2, SELECTION_KEY selKey=SKEY_OR // selection key ); // SelectAtoms(..) selects atoms with serial numbers given in // vector asn[0..nsn-1]. void SelectAtoms ( int selHnd, ivector asn, int nsn, SELECTION_KEY selKey=SKEY_OR // selection key ); // UnselectAtoms(..) clears the specified mask for atoms in // the serial number range of iSer1 to iSer2. If iSer1=iSer2=0 // then all atoms are cleared of the specified mask. If selHnd // is set to 0, then the atoms are cleared of any mask. void UnselectAtoms ( int selHnd, int iSer1, int iSer2 ); // SelectAtom(..) selects a single atom according to the value // of selection key. If makeIndex is false, then the routine // does not update the selection index. This saves time, but // prevents GetSelIndex(..) from accessing all selected atoms. // In order to update the index after all single-atom selections // are done, use MakeSelIndex(selHnd) found next. void SelectAtom ( int selHnd, PAtom A, SELECTION_KEY selKey=SKEY_OR, bool makeIndex=true ); // SelectResidue(..), SelectChain(..) and SelectModel(..) // select a single residue, chain or model, or all their // hierarchical descendants depending on the value of sType // (i.e. atoms, residues (in chain and model) and chains // (in model only). Ascending hierarchical objects should be // selected explicitely, e.g. atom->GetResidue()->SelectResidue(..) void SelectResidue ( int selHnd, PResidue Res, SELECTION_TYPE sType, SELECTION_KEY sKey, bool makeIndex ); void SelectChain ( int selHnd, PChain chain, SELECTION_TYPE sType, SELECTION_KEY sKey, bool makeIndex ); void SelectModel ( int selHnd, PModel mdl, SELECTION_TYPE sType, SELECTION_KEY sKey, bool makeIndex ); // MakeSelIndex(.) calculates selection index for selection // adressed by selHnd. All selection functions except the // SelectAtom(..) above, update selection index automatically. // This function is for use after a series of calls to // SelectAtom(..) with makeIndex parameter set false. This // combination of SelectAtom - MakeSelIndex considerably saves CPU // at extensive selections. // MakeSelIndex(.) returns the number of selected objects. int MakeSelIndex ( int selHnd ); void MakeAllSelIndexes(); // Selecting by atom ID, space condition (a sphere) and some // other bits. void SelectAtoms ( int selHnd, // must be obtained from NewSelection() int iModel, // model number; iModel=0 means // 'any model' cpstr Chains, // may be several chains "A,B,W"; "*" // means 'any chain' (in selected // model(s)) int ResNo1, // starting residue sequence number cpstr Ins1, // starting residue insertion code; "*" // means 'any code' int ResNo2, // ending residue sequence number. cpstr Ins2, // ending residue insertion code; "*" // means 'any code'. Combination of // ResNo1=ResNo2=ANY_RES and // Ins1=Ins2="*" means 'any residue' // (in selected chain(s)) cpstr RNames, // may be several residue names // "ALA,GLU,CIS"; "*" means 'any // residue name' cpstr ANames, // may be several names "CA,CB"; "*" // means 'any atom' (in selected // residue(s)) cpstr Elements, // may be several element types // 'H,C,O,CU'; "*" means 'any element' cpstr altLocs, // may be several alternative // locations 'A,B'; "*" means // 'any alternative location' cpstr Segments, // may be several segment IDs // like "S1,S2,A234"; "*" means // 'any segment' cpstr Charges, // may be several charges like // "+1,-2, "; "*" means 'any charge' realtype occ1, // lowest occupancy realtype occ2, // highest occupancy; occ1=occ2<0.0 // means "any occupancy" realtype x0, // reference x-point realtype y0, // reference y-point realtype z0, // reference z-point realtype d0, // selection distance from the // reference point; d0<=0.0 // means "any distance" and values // of x0, y0 and z0 are ignored SELECTION_KEY selKey=SKEY_OR // selection key ); // Selecting by just atom ID, no other conditions void SelectAtoms ( int selHnd, // must be obtained from NewSelection() int iModel, // model number; iModel=0 means // 'any model' cpstr Chains, // may be several chains "A,B,W"; "*" // means 'any chain' (in selected // model(s)) int ResNo1, // starting residue sequence number cpstr Ins1, // starting residue insertion code; "*" // means 'any code' int ResNo2, // ending residue sequence number. cpstr Ins2, // ending residue insertion code; "*" // means 'any code'. Combination of // ResNo1=ResNo2=ANY_RES and // Ins1=Ins2="*" means 'any residue // number' (in selected chain(s)) cpstr RNames, // may be several residue names // "ALA,GLU,CIS"; "*" means 'any // residue name' cpstr ANames, // may be several names "CA,CB"; "*" // means 'any atom' (in selected // residue(s)) cpstr Elements, // may be several element types // "H,C,O,CU"; "*" means 'any element' cpstr altLocs, // may be several alternative // locations 'A,B'; "*" means // 'any alternative location' SELECTION_KEY selKey=SKEY_OR // selection key ); // Selecting by integer User-Defined Data void SelectUDD ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX int UDDhandle, // UDD handle int selMin, // lower selection boundary int selMax, // upper selection boundary SELECTION_KEY sKey // selection key ); void SelectUDD ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX int UDDhandle, // UDD handle realtype selMin, // lower selection boundary realtype selMax, // upper selection boundary SELECTION_KEY sKey // selection key ); void SelectUDD ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX int UDDhandle, // UDD handle cpstr selStr, // selection string int cmpRule, // comparison rule SELECTION_KEY sKey // selection key ); // Selecting a sphere void SelectSphere ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX realtype x, // x-coordinate of the sphere's center realtype y, // y-coordinate of the sphere's center realtype z, // z-coordinate of the sphere's center realtype r, // radius of the sphere SELECTION_KEY sKey=SKEY_OR // selection key ); // Selecting a cylinder void SelectCylinder ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX realtype x1, // x-coordinate of the cylinder axis' 1st end realtype y1, // y-coordinate of the cylinder axis' 1st end realtype z1, // z-coordinate of the cylinder axis' 1st end realtype x2, // x-coordinate of the cylinder axis' 2nd end realtype y2, // y-coordinate of the cylinder axis' 2nd end realtype z2, // z-coordinate of the cylinder axis' 2nd end realtype r, // radius of the cylinder SELECTION_KEY sKey=SKEY_OR // selection key ); // Selecting all atoms on a given distance from a plane void SelectSlab ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX realtype a, // a-parameter of the plane ax+by+cz=d realtype b, // b-parameter of the plane ax+by+cz=d realtype c, // c-parameter of the plane ax+by+cz=d realtype d, // d-parameter of the plane ax+by+cz=d realtype r, // distance to the plane SELECTION_KEY sKey=SKEY_OR // selection key ); // Selecting all atoms on a given distance from already selected void SelectNeighbours ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX PPAtom sA, // array of already selected atoms int alen, // length of A realtype d1, // minimal distance to already selected atoms realtype d2, // maximal distance to already selected atoms SELECTION_KEY sKey=SKEY_OR // selection key ); int GetSelLength ( int selHnd ); // Getting an array of atoms selected for a certain mask void GetSelIndex ( int selHnd, // selection mask PPAtom & SelAtom, // continuous index of selected // atoms; application must not // dispose either index or atoms int & nSelAtoms // length of index // [0..nSelectedAtoms-1] ); // Getting an array of residues selected for a certain mask void GetSelIndex ( int selHnd, // selection mask PPResidue & SelResidues, // continuous index of selected // residues; application must // not dispose either index or // residues int & nSelResidues // length of index // [0..nSelResidues-1] ); // Getting an array of chains selected for a certain mask void GetSelIndex ( int selHnd, // selection mask PPChain & SelChains, // continuous index of selected // chains; application must not // dispose either index or chains int & nSelChains // length of index // [0..nSelChains-1] ); // Getting an array of models selected for a certain mask void GetSelIndex ( int selHnd, // selection mask PPModel & SelModels, // continuous index of selected // models; application must not // dispose either index or models int & nSelModels // length of index // [0..nSelModels-1] ); void GetAtomStatistics ( int selHnd, RAtomStat AS ); // =============== General selection functions ================ // Selecting by atom ID, space condition (a sphere) and some // other bits. void Select ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX int iModel, // model number; iModel=0 means // 'any model' cpstr Chains, // may be several chains "A,B,W"; "*" // means 'any chain' (in selected // model(s)) int ResNo1, // starting residue sequence number cpstr Ins1, // starting residue insertion code; "*" // means 'any code' int ResNo2, // ending residue sequence number. cpstr Ins2, // ending residue insertion code; "*" // means 'any code'. Combination of // ResNo1=ResNo2=ANY_RES and // Ins1=Ins2="*" means 'any residue' // (in selected chain(s)) cpstr RNames, // may be several residue names // "ALA,GLU,CIS"; "*" means // 'any residue name' cpstr ANames, // may be several names "CA,CB"; "*" // means 'any atom' (in selected // residue(s)) cpstr Elements, // may be several element types // 'H,C,O,CU'; "*" means 'any element' cpstr altLocs, // may be several alternative // locations 'A,B'; "*" means // 'any alternative location' cpstr Segments, // may be several segment IDs like // "S1,S2,A234"; "*" means // 'any segment' cpstr Charges, // may be several charges like // "+1,-2, "; "*" means 'any charge' realtype occ1, // lowest occupancy realtype occ2, // highest occupancy; occ1=occ2<0.0 // means "any occupancy" realtype x0, // reference x-point realtype y0, // reference y-point realtype z0, // reference z-point realtype d0, // selection distance from the // reference point; d0<=0.0 // means "any distance" and values // of x0, y0 and z0 are ignored SELECTION_KEY sKey=SKEY_OR // selection key ); // Selecting by just atom ID, no other conditions void Select ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX int iModel, // model number; iModel=0 means // 'any model' cpstr Chains, // may be several chains "A,B,W"; "*" // means 'any chain' (in selected // model(s)) int ResNo1, // starting residue sequence number cpstr Ins1, // starting residue insertion code; "*" // means 'any code' int ResNo2, // ending residue sequence number. cpstr Ins2, // ending residue insertion code; "*" // means 'any code'. Combination of // ResNo1=ResNo2=ANY_RES and // Ins1=Ins2="*" means 'any residue // number' (in selected chain(s)) cpstr RNames, // may be several residue names // "ALA,GLU,CIS"; "*" means // 'any residue name' cpstr ANames, // may be several names "CA,CB"; "*" // means 'any atom' (in selected // residue(s)) cpstr Elements, // may be several element types // "H,C,O,CU"; "*" means 'any element' cpstr altLocs, // may be several alternative // locations 'A,B'; "*" means // 'any alternative location' SELECTION_KEY sKey=SKEY_OR // selection key ); // Selecting by coordinate ID. // Examples: // // 1. /mdl/chn/s1.i1-s2.i2/at[el]:aloc // 2. /mdl/chn/*(res).ic /at[el]:aloc // 3. chn/*(res).ic /at[el]:aloc // 4. s1.i1-s2.i2/at[el]:aloc // 5. s1.i1 /at[el]:aloc // 6. /mdl // 7. chn // 8. s1.i1-s2.i2 // 9. (res) // 10. at[el]:aloc // 11. chn//[el] // // mdl - the model's serial number or 0 or '*' for any model // (default). // chn - the chain ID or list of chains 'A,B,C' or '*' for // any chain (default). // s1,s2 - the starting and ending residue sequence numbers // or '*' for any sequence number (default). // i1,i2 - the residues insertion codes or '*' for any // insertion code. If the sequence number other than // '*' is specified, then insertion code defaults to "" // (no insertion code), otherwise the default is '*'. // at - atom name or list of atom names 'CA,N1,O' or '*' // for any atom name (default) // el - chemical element name or list of chemical element // names 'C,N,O' or '*' for any chemical element name // (default) // aloc - the alternative location indicator or '*' for any // alternate location. If the atom name and chemical // element name is specified (both may be '*'), then // the alternative location indicator defaults to "" // (no alternate location), otherwise the default is // '*'. // // All spaces are ignored. // // Returns -1 if numerical format of model is wrong, -2 if // numerical format for sequence number is wrong, and 0 // otherwise. int Select ( int selHnd, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX cpstr CID, // coordinate ID SELECTION_KEY sKey // selection key ); // Propagating the selection up and down coordinate hierarchy void Select ( int selHnd1, // must be obtained from NewSelection() SELECTION_TYPE sType, // selection type STYPE_XXXXX int selHnd2, // must be obtained from NewSelection() // and have been used for selection SELECTION_KEY sKey=SKEY_OR // selection key ); void SelectProperty ( int selHnd, // must be obtained from NewSelection() SELECTION_PROPERTY propKey, // property key SELPROP_XXXXXXX SELECTION_TYPE sType, // selection type STYPE_XXXXX SELECTION_KEY sKey // selection key ); // In SelectDomain, domainRange is of the following format: // "*", "(all)" - take all file // "-" - take chain without chain ID // "a:Ni-Mj,b:Kp-Lq,..." - take chain a residue number N // insertion code i to residue numberM // insertion code j plus chain b // residue number K insertion code p to // residue number L insertion code q // and so on. // "a:,b:..." - take whole chains a and b and so on // "a:,b:Kp-Lq,..." - any combination of the above. int SelectDomain ( int selHnd , cpstr domainRange, SELECTION_TYPE sType, SELECTION_KEY sKey, int modelNo=1 ); void DeleteSelObjects ( int selHnd ); protected : // --- SELECTION DATA NOT FOR PUBLIC ACCESS int nSelections; // number of selections PPMask mask; // vector of selections SELECTION_TYPE *selType; // vector of selection types ivector nSelItems; // numbers of selected items PPMask * selection; // vector of selected items // --------------- Stream I/O ----------------------------- void write ( io::RFile f ); void read ( io::RFile f ); void InitSelManager(); void SelectAtom ( PAtom atm, int maskNo, SELECTION_KEY sKey, int & nsel ); void SelectObject ( SELECTION_TYPE sType, PAtom atm, int maskNo, SELECTION_KEY sKey, int & nsel ); void SelectObject ( PMask object, int maskNo, SELECTION_KEY sKey, int & nsel ); void MakeSelIndex ( int selHnd, SELECTION_TYPE sType, int nsel ); void ResetManager(); PMask GetSelMask ( int selHnd ); }; } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_xml_.cpp0000664000175000017500000006234212401105774013115 00000000000000// $Id: mmdb_xml_.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 06.12.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_XML // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::xml::XMLObject // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include #include "mmdb_xml_.h" namespace mmdb { namespace xml { // ====================== XMLObject ========================== XMLObject::XMLObject() : io::Stream() { InitXMLObject(); } XMLObject::XMLObject ( cpstr Tag ) : io::Stream() { InitXMLObject(); SetTag ( Tag ); } XMLObject::XMLObject ( cpstr Tag, cpstr Data ) : io::Stream() { InitXMLObject(); SetTag ( Tag ); SetData ( Data ); } XMLObject::XMLObject ( cpstr Tag, realtype V, int length ) : io::Stream() { InitXMLObject(); SetTag ( Tag ); SetData ( V,length ); } XMLObject::XMLObject ( cpstr Tag, int iV, int length ) : io::Stream() { InitXMLObject(); SetTag ( Tag ); SetData ( iV,length ); } XMLObject::XMLObject ( cpstr Tag, bool bV ) : io::Stream() { InitXMLObject(); SetTag ( Tag ); SetData ( bV ); } XMLObject::XMLObject ( cpstr Tag, PXMLObject XMLObject ) : io::Stream() { InitXMLObject(); SetTag ( Tag ); AddObject ( XMLObject ); } XMLObject::XMLObject ( io::RPStream Object ) : io::Stream(Object) { InitXMLObject(); } XMLObject::~XMLObject() { FreeMemory(); } void XMLObject::InitXMLObject() { parent = NULL; objTag = NULL; objData = NULL; nObjects = 0; nAlloc = 0; object = NULL; nAttributes = 0; nAttrAlloc = 0; attr_name = NULL; attr_value = NULL; } void XMLObject::FreeMemory() { int i; if (objTag) delete[] objTag; if (objData) delete[] objData; objTag = NULL; objData = NULL; if (object) { for (i=0;i=nAttrAlloc) { nAttrAlloc = nAttributes + 10; GetVectorMemory ( an,nAttrAlloc,0 ); GetVectorMemory ( av,nAttrAlloc,0 ); for (i=0;iGetCategoryID()==mmcif::MMCIF_Loop) return AddMMCIFLoop ( mmcif::PLoop(mmCIFCat) ); if (mmCIFCat->GetCategoryID()==mmcif::MMCIF_Struct) return AddMMCIFStruct ( mmcif::PStruct(mmCIFCat) ); return -1; } pstr getCCIFTag ( pstr & ccifTag, cpstr Tag ) { if (Tag[0]=='_') return CreateCopCat ( ccifTag,pstr("ccif") ,Tag ); else return CreateCopCat ( ccifTag,pstr("ccif_"),Tag ); } int XMLObject::AddMMCIFStruct ( mmcif::PStruct mmCIFStruct ) { PXMLObject XMLObject1,XMLObject2; pstr SName,Tag,Field, ccifTag; int nTags,i,k; XMLObject1 = this; ccifTag = NULL; SName = mmCIFStruct->GetCategoryName(); if (SName) { if (SName[0]!=char(1)) XMLObject1 = new XMLObject ( getCCIFTag(ccifTag,SName) ); } k = 0; nTags = mmCIFStruct->GetNofTags(); for (i=0;iGetTag ( i ); if (Tag) { XMLObject2 = new XMLObject ( getCCIFTag(ccifTag,Tag) ); Field = mmCIFStruct->GetField ( i ); if (Field) { if (Field[0]!=char(2)) XMLObject2->SetData ( Field ); else XMLObject2->SetData ( &(Field[1]) ); } XMLObject1->AddObject ( XMLObject2 ); k++; } } if (SName) { if (SName[0]!=char(1)) AddObject ( XMLObject1 ); } if (ccifTag) delete[] ccifTag; return k; } int XMLObject::AddMMCIFLoop ( mmcif::PLoop mmCIFLoop ) { PXMLObject XMLObject1,XMLObject2,XMLObject3; pstr SName,Tag,Field,ccifTag; int nTags,nRows,i,j,k; XMLObject1 = this; ccifTag = NULL; SName = mmCIFLoop->GetCategoryName(); if (SName) { if (SName[0]!=char(1)) XMLObject1 = new XMLObject ( getCCIFTag(ccifTag,SName) ); } k = 0; nTags = mmCIFLoop->GetNofTags (); nRows = mmCIFLoop->GetLoopLength(); for (i=0;iGetTag ( j ); if (Tag) { XMLObject3 = new XMLObject ( getCCIFTag(ccifTag,Tag) ); Field = mmCIFLoop->GetField ( i,j ); if (Field) { if (Field[0]!=char(2)) XMLObject3->SetData ( Field ); else XMLObject3->SetData ( &(Field[1]) ); } XMLObject2->AddObject ( XMLObject3 ); k++; } } XMLObject1->AddObject ( XMLObject2 ); } if (SName) { if (SName[0]!=char(1)) AddObject ( XMLObject1 ); } if (ccifTag) delete[] ccifTag; return k; } int XMLObject::AddMMCIFData ( mmcif::PData mmCIFData ) { mmcif::PCategory mmCIFCat; int nCats,i,k,n; nCats = mmCIFData->GetNumberOfCategories(); k = 0; n = 0; for (i=0;(i=0);i++) { mmCIFCat = mmCIFData->GetCategory ( i ); if (mmCIFCat) { if (mmCIFCat->GetCategoryID()==mmcif::MMCIF_Loop) n = AddMMCIFLoop ( mmcif::PLoop(mmCIFCat) ); else if (mmCIFCat->GetCategoryID()==mmcif::MMCIF_Struct) n = AddMMCIFStruct ( mmcif::PStruct(mmCIFCat) ); else n = -1; if (n>=0) k += n; } } if (n<0) return -(k+1); return k; } pstr XMLObject::GetData ( cpstr Tag, int objNo ) { PXMLObject XMLObject; XMLObject = GetObject ( Tag,objNo ); if (XMLObject) return XMLObject->objData; return NULL; } XML_RC XMLObject::GetData ( pstr & Data, cpstr Tag, int objNo ) { PXMLObject XMLObject; XMLObject = GetObject ( Tag,objNo ); if (XMLObject) { Data = XMLObject->objData; return XMLRC_Ok; } else { Data = NULL; return XMLRC_NoTag; } } XML_RC XMLObject::GetData ( realtype & V, cpstr Tag, int objNo ) { pstr d,p; XML_RC rc; rc = GetData ( d,Tag,objNo ); if (d) { V = strtod(d,&p); if ((V==0.0) && (p==d)) rc = XMLRC_RFormatError; else rc = XMLRC_Ok; } else if (!rc) rc = XMLRC_NoTag; return rc; } XML_RC XMLObject::GetData ( int & iV, cpstr Tag, int objNo ) { pstr d,p; XML_RC rc; rc = GetData ( d,Tag,objNo ); if (d) { iV = mround(strtod(d,&p)); if ((iV==0) && (p==d)) rc = XMLRC_IFormatError; else rc = XMLRC_Ok; } else if (!rc) rc = XMLRC_NoTag; return rc; } XML_RC XMLObject::GetData ( bool & bV, cpstr Tag, int objNo ) { pstr d; XML_RC rc; rc = GetData ( d,Tag,objNo ); if (d) { if (!strcasecmp(d,"Yes")) bV = true; else { bV = false; if (strcasecmp(d,"No")) rc = XMLRC_OFormatError; } } else if (rc==XMLRC_Ok) rc = XMLRC_NoTag; return rc; } PXMLObject XMLObject::GetObject ( cpstr Tag, int objNo ) { // allow for "tag1>tag2>tag3>..." PXMLObject XMLObject; pstr p,p1; int i,j,k,l; XMLObject = this; if (Tag) { p = pstr(Tag); do { p1 = p; l = 0; while (*p1 && (*p1!='>')) { p1++; l++; } if (l>0) { k = -1; j = 0; for (i=0;(inObjects) && (k<0);i++) if (XMLObject->object[i]) { if (!strncmp(XMLObject->object[i]->objTag,p,l)) { j++; if (j==objNo) k = i; } } if (k<0) { XMLObject = NULL; l = 0; } else { XMLObject = XMLObject->object[k]; if (*p1) p = p1 + 1; else l = 0; } } } while (l>0); } return XMLObject; } PXMLObject XMLObject::GetFirstObject() { if (nObjects>0) return object[0]; return NULL; } PXMLObject XMLObject::GetLastObject() { if (nObjects>0) return object[nObjects-1]; return NULL; } PXMLObject XMLObject::GetObject ( int objectNo ) { if ((0<=objectNo) && (objectNo=nAlloc) { nAlloc += lenInc; obj1 = new PXMLObject[nAlloc]; for (i=0;iSetParent ( this ); nObjects++; } void XMLObject::InsertObject ( PXMLObject XMLObject, int pos, int lenInc ) { PPXMLObject obj1; int i; if (!XMLObject) return; if (pos>=nObjects) { AddObject ( XMLObject,lenInc ); return; } if (nObjects>=nAlloc) { nAlloc += lenInc; obj1 = new PXMLObject[nAlloc]; for (i=0;ipos;i--) object[i] = object[i-1]; object[pos] = XMLObject; XMLObject->SetParent ( this ); nObjects++; } XML_RC XMLObject::WriteObject ( cpstr FName, int pos, int indent ) { io::File f; f.assign ( FName,true ); if (f.rewrite()) { WriteObject ( f,pos,indent ); f.shut(); return XMLRC_Ok; } return XMLRC_CantOpenFile; } void XMLObject::WriteObject ( io::RFile f, int pos, int indent ) { int i,pos1,lm,rm,tl; pstr indstr,p,p1,q; bool sngline; if (objTag) { pos1 = pos + indent; indstr = new char[pos1+1]; for (i=0;i") ); delete[] indstr; return; } f.Write ( pstr(">") ); sngline = false; if (objData) { rm = 72; // right margin lm = IMin ( pos1,36 ); // left margin tl = strlen(objTag); if ((pos+tl+2+(int)strlen(objData)WriteObject ( f,pos+indent,indent ); if (!sngline) f.Write ( indstr ); f.Write ( pstr("") ); delete[] indstr; } } XML_RC XMLObject::ReadObject ( cpstr FName ) { io::File f; char S[500]; int i; XML_RC rc; f.assign ( FName,true ); if (f.reset(true)) { S[0] = char(0); i = 0; rc = ReadObject ( f,S,i,sizeof(S) ); f.shut(); } else rc = XMLRC_NoFile; if (rc!=XMLRC_Ok) FreeMemory(); return rc; } XML_RC XMLObject::ReadObject ( io::RFile f, pstr S, int & pos, int slen ) { PXMLObject xmlObject; pstr S1; int k,k1,k2; XML_RC rc; bool Done; FreeMemory(); rc = XMLRC_Ok; k1 = -1; k2 = -1; while ((!f.FileEnd()) && (k1<0)) { k = strlen(S); while ((pos // constructions pos++; else if (S[pos+1]!='<') k1 = pos; else pos += 2; } else pos++; if (k1>=0) { k2 = -1; while ((pos') { if (S[pos+1]!='>') k2 = pos; else pos += 2; } else pos++; if (k2<0) rc = XMLRC_BrokenTag; } if (k1<0) { f.ReadLine ( S,slen ); pos = 0; } } if (k1<0) return XMLRC_NoTag; if (rc!=XMLRC_Ok) return rc; pos++; if (S[k2-1]=='/') { // S[k2-1] = char(0); CreateCopy ( objTag,&(S[k1+1]) ); return XMLRC_Ok; } S[k2] = char(0); CreateCopy ( objTag,&(S[k1+1]) ); S[k2] = '>'; S1 = new char[slen+1]; Done = false; while ((!f.FileEnd()) && (!Done)) { k = strlen(S); while ((pos=0) S[k2] = char(0); strcpy_des ( S1,&(S[k1]) ); if (S1[0]) { if (objData) CreateConcat ( objData,pstr(" "),S1 ); else CreateConcat ( objData,S1 ); } if (k2>=0) { S[k2] = '<'; if (S[k2+1]!='/') { xmlObject = new XMLObject(); AddObject ( xmlObject ); rc = xmlObject->ReadObject ( f,S,pos,slen ); Done = (rc!=XMLRC_Ok); } else { Done = true; k1 = k2+2; k2 = -1; while ((pos') { if (S[pos+1]!='>') k2 = pos; else pos += 2; } else pos++; if (k2<0) rc = XMLRC_BrokenTag; else { S[k2] = char(0); if (strcmp(objTag,&(S[k1]))) rc = XMLRC_UnclosedTag; else pos++; } } } } if (!Done) { f.ReadLine ( S,slen ); pos = 0; } } delete[] S1; // this keeps pairs instead of replacing them for // on output if ((!objData) && (nObjects<=0)) CreateCopy ( objData,pstr("") ); if (rc!=XMLRC_Ok) FreeMemory(); return rc; } void XMLObject::Copy ( PXMLObject xmlObject ) { int i; FreeMemory(); CreateCopy ( objTag ,xmlObject->objTag ); CreateCopy ( objData,xmlObject->objData ); nObjects = xmlObject->nObjects; nAlloc = nObjects; if (nObjects>0) { object = new PXMLObject[nObjects]; for (i=0;iobject[i]) { object[i] = new XMLObject(); object[i]->Copy ( xmlObject->object[i] ); } else object[i] = NULL; } nAttributes = xmlObject->nAttributes; nAttrAlloc = nAttributes; if (nAttributes>0) { GetVectorMemory ( attr_name ,nAttrAlloc,0 ); GetVectorMemory ( attr_value,nAttrAlloc,0 ); for (i=0;iattr_name [i] ); CreateCopy ( attr_value[i],xmlObject->attr_value[i] ); } } } void XMLObject::write ( io::RFile f ) { int i; f.CreateWrite ( objTag ); f.CreateWrite ( objData ); f.WriteInt ( &nObjects ); for (i=0;i0) { object = new PXMLObject[nObjects]; for (i=0;i0) { GetVectorMemory ( attr_name ,nAttrAlloc,0 ); GetVectorMemory ( attr_value,nAttrAlloc,0 ); for (i=0;iGetDataName(); if (dataName) { if (dataName[0]) xmlObject = new XMLObject ( dataName ); } if (!xmlObject) xmlObject = new XMLObject ( pstr("no_data_name") ); k = xmlObject->AddMMCIFData ( mmCIFData ); if (rc) *rc = k; } return xmlObject; } PXMLObject mmCIF2XML ( cpstr XMLName, mmcif::PFile mmCIFFile, int * rc ) { PXMLObject xmlObject1,xmlObject2; mmcif::PData mmCIFData; int nData,i,k,rc1; xmlObject1 = new XMLObject ( XMLName ); if (rc) *rc = -1; if (mmCIFFile) { nData = mmCIFFile->GetNofData(); k = 0; rc1 = 0; for (i=0;(i=0);i++) { mmCIFData = mmCIFFile->GetCIFData ( i ); if (mmCIFData) { xmlObject2 = mmCIF2XML ( mmCIFData,&rc1 ); if (xmlObject2) { if (rc1>=0) { xmlObject1->AddObject ( xmlObject2 ); k += rc1; } else delete xmlObject2; } } } if (rc1<0) { delete xmlObject1; if (rc) *rc = -2; } else if (rc) *rc = k; } return xmlObject1; } } // namespace xml } // namespace mmdb mmdb2-2.0.5/mmdb2/mmdb_coormngr.cpp0000664000175000017500000037121712601171753014012 00000000000000// $Id: mmdb_coormngr.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 07.09.15 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : mmdb_coormngr // ~~~~~~~~~ // Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::Brick ( space brick ) // ~~~~~~~~~ mmdb::CoorManager ( MMDB atom coordinate manager ) // // (C) E. Krissinel 2000-2015 // // ================================================================= // #include #include #include "mmdb_coormngr.h" #include "mmdb_math_linalg.h" #include "mmdb_tables.h" namespace mmdb { // ========================== Brick ============================= Brick::Brick() { InitBrick(); } Brick::~Brick() { Clear(); } void Brick::InitBrick() { atom = NULL; id = NULL; nAtoms = 0; nAllocAtoms = 0; } void Brick::Clear() { if (atom) delete[] atom; FreeVectorMemory ( id,0 ); atom = NULL; nAtoms = 0; nAllocAtoms = 0; } void Brick::AddAtom ( PAtom A, int atomid ) { int i; PPAtom atom1; ivector id1; if (nAtoms>=nAllocAtoms) { nAllocAtoms = nAtoms+10; atom1 = new PAtom[nAllocAtoms]; GetVectorMemory ( id1,nAllocAtoms,0 ); for (i=0;i=nalloc) { nalloc = natoms+10; atom1 = new PAtom[nalloc]; GetVectorMemory ( id1,nalloc,0 ); for (i=0;inOpAlloc) { ch1ID = new PChainID[Nops]; ch2ID = new PChainID[Nops]; GetVectorMemory ( nChains1,Nops,0 ); for (i=0;i0) { nOpAlloc = Nops; chID1 = new PChainID[Nops]; chID2 = new PChainID[Nops]; GetVectorMemory ( nChains,Nops,0 ); for (i=0;inChains[i]; if (nChains[i]<=0) { chID1[i] = NULL; chID2[i] = NULL; } else { chID1[i] = new ChainID[nChains[i]]; chID2[i] = new ChainID[nChains[i]]; for (j=0;jchID1[i][j] ); strcpy ( chID2[i][j],PGenSym(GenSym)->chID2[i][j] ); } } } } } void GenSym::write ( io::RFile f ) { int i,j; byte Version=1; f.WriteByte ( &Version ); SymOps::write ( f ); f.WriteInt ( &nOpAlloc ); for (i=0;i0) { chID1 = new PChainID[nOpAlloc]; chID2 = new PChainID[nOpAlloc]; GetVectorMemory ( nChains,nOpAlloc,0 ); for (i=0;i0) { chID1[i] = new ChainID[nChains[i]]; chID2[i] = new ChainID[nChains[i]]; for (j=0;j0) { if (n_contacts=alloc_index) { alloc_index = n_contacts+IMax(alloc_index/4+10,10); if ((alloc_max>0) && (alloc_index>alloc_max)) alloc_index = alloc_max; cont1 = new Contact[alloc_index]; for (i=0;i0) { atom = new PPAtom[nStruct]; id = new ivector[nStruct]; GetVectorMemory ( nAtoms,nStruct,0 ); GetVectorMemory ( nAlloc,nStruct,0 ); for (i=0;i=nal) { nal = nat+10; A2 = new PAtom[nal]; GetVectorMemory ( id2,nal,0 ); for (i=0;iGetSerNum(); return 1; } PModel CoorManager::GetModel ( int modelNo ) { if ((modelNo>=1) && (modelNo<=nModels)) return model[modelNo-1]; else return NULL; } PModel CoorManager::GetModel ( cpstr CID ) { int modno,sn,rc; ChainID chname; InsCode ic; ResName resname; AtomName aname; Element elname; AltLoc aloc; CoorIDCode = CID_Ok; rc = ParseAtomPath ( CID,modno,chname,sn,ic,resname, aname,elname,aloc,&DefPath ); if ((rc<0) || (rc & APATH_WC_ModelNo)) { CoorIDCode = CID_WrongPath; return NULL; } if ((modno>=1) && (modno<=nModels)) return model[modno-1]; else return NULL; } void CoorManager::GetModelTable ( PPModel & modelTable, int & NumberOfModels ) { NumberOfModels = nModels; modelTable = model; } int CoorManager::DeleteModel ( int modelNo ) { if ((modelNo>=1) && (modelNo<=nModels)) { if (model[modelNo-1]) { Exclude = false; delete model[modelNo-1]; model[modelNo-1] = NULL; Exclude = true; return 1; } } return 0; } int CoorManager::DeleteModel ( cpstr CID ) { int modno,sn,rc; ChainID chname; InsCode ic; ResName resname; AtomName aname; Element elname; AltLoc aloc; CoorIDCode = CID_Ok; rc = ParseAtomPath ( CID,modno,chname,sn,ic,resname, aname,elname,aloc,&DefPath ); if ((rc<0) || (rc & APATH_WC_ModelNo)) { CoorIDCode = CID_WrongPath; return 0; } if ((modno>=1) && (modno<=nModels)) { if (model[modno-1]) { Exclude = false; delete model[modno-1]; model[modno-1] = NULL; Exclude = true; return 1; } } return 0; } int CoorManager::DeleteSolvent() { int i,k; Exclude = false; k = 0; for (i=0;iDeleteSolvent(); model[i]->TrimChainTable(); if (model[i]->nChains<=0) { delete model[i]; model[i] = NULL; } } Exclude = true; return k; } // ---------------- Adding/Inserting models --------------- int CoorManager::AddModel ( PModel mdl ) { PPModel model1; int i,nnat,nat1; for (i=0;iGetNumberOfAtoms ( true ); AddAtomArray ( nnat ); // get space for new atoms if (mdl->GetCoordHierarchy()) { SwitchModel ( nModels+1 ); // get one more model at the end nat1 = nAtoms; model[nModels-1]->_copy ( mdl,atom,nat1 ); model[nModels-1]->serNum = nModels; nAtoms = nat1; } else { model1 = new PModel[nModels+1]; for (i=0;iSetMMDBManager ( PManager(this),nModels+1 ); model[nModels]->CheckInAtoms(); nModels++; } return nModels; } int CoorManager::InsModel ( PModel mdl, int modelNo ) { AddModel ( mdl ); RotateModels ( modelNo,nModels,1 ); return nModels; } void CoorManager::RotateModels ( int modelNo1, int modelNo2, int rotdir ) { PModel mdl; PPAtom A; int m1,m2,i11,i12,i21,i22,nat,i,k; m1 = IMax ( 0,modelNo1-1 ); m2 = IMin ( nModels,modelNo2) - 1; if (m1>m2) ISwap ( m1,m2 ); if (m1!=m2) { if (model[m1] && model[m2]) { model[m1]->GetAIndexRange ( i11,i12 ); model[m2]->GetAIndexRange ( i21,i22 ); if ((i11index = k+1; k++; } for (i=0;iindex = k+1; k++; } } else { // rotate anticlockwise nat = i22-i21+1; A = new PAtom[nat]; k = 0; for (i=i21;i<=i22;i++) A[k++] = atom[i]; k = i22; for (i=i21-1;i>=i11;i--) { atom[k] = atom[i]; if (atom[k]) atom[k]->index = k+1; k--; } for (i=nat-1;i>=0;i--) { atom[k] = A[i]; if (atom[k]) atom[k]->index = k+1; k--; } } delete[] A; } } if (rotdir<0) { // rotate anticlockwise mdl = model[m1]; for (i=m1;iserNum = i+1; } model[m2] = mdl; model[m2]->serNum = m2+1; } else { // rotate clockwise mdl = model[m2]; for (i=m2;i>m1;i--) { model[i] = model[i-1]; model[i]->serNum = i+1; } model[m1] = mdl; model[m1]->serNum = m1+1; } } } void CoorManager::SwapModels ( int modelNo1, int modelNo2 ) { PModel mdl; PPAtom A; int m1,m2,i11,i12,i21,i22,i,k,n; n = 0; // tp depress "uninitialized" warning m1 = IMax ( 0,modelNo1-1 ); m2 = IMin ( nModels,modelNo2) - 1; if (m1>m2) ISwap ( m1,m2 ); if (m1!=m2) { if (model[m1]) model[m1]->GetAIndexRange ( i11,i12 ); else { n = m1; while ((!model[n]) && (nGetAIndexRange ( i11,i12 ); i12 = i11-1; } else n = -1; } if (n>=0) { if (model[m2]) model[m2]->GetAIndexRange ( i21,i22 ); else { n = m2; while ((!model[n]) && (m1GetAIndexRange ( i21,i22 ); i22 = i21-1; } else n = -1; } } if (n>=0) { i11--; i12--; i21--; i22--; A = new PAtom[atmLen]; k = 0; for (i=0 ;iindex = i+1; for (i=nAtoms;iserNum = m1+1; model[m2]->serNum = m2+1; } } PChain CoorManager::GetChain ( int modelNo, const ChainID chainID ) { if ((0GetChain ( chainID ); } return NULL; } PChain CoorManager::GetChain ( int modelNo, int chainNo ) { if ((0GetChain ( chainNo ); } return NULL; } PChain CoorManager::GetChain ( cpstr CID ) { int modno,sn,rc; ChainID chname; InsCode ic; ResName resname; AtomName aname; Element elname; AltLoc aloc; CoorIDCode = CID_Ok; rc = ParseAtomPath ( CID,modno,chname,sn,ic,resname, aname,elname,aloc,&DefPath ); if ((rc<0) || (rc & (APATH_WC_ModelNo | APATH_WC_ChainID))) { CoorIDCode = CID_WrongPath; return NULL; } return GetChain ( modno,chname ); } void CoorManager::GetChainTable ( int modelNo, PPChain & chainTable, int & NumberOfChains ) { chainTable = NULL; NumberOfChains = 0; if ((0chain; NumberOfChains = model[modelNo-1]->nChains; } } } void CoorManager::GetChainTable ( cpstr CID, PPChain & chainTable, int & NumberOfChains ) { int modno,sn,rc; ChainID chname; InsCode ic; ResName resname; AtomName aname; Element elname; AltLoc aloc; chainTable = NULL; NumberOfChains = 0; CoorIDCode = CID_Ok; rc = ParseAtomPath ( CID,modno,chname,sn,ic,resname, aname,elname,aloc,&DefPath ); if ((rc<0) || (rc & APATH_WC_ModelNo)) { CoorIDCode = CID_WrongPath; return; } if ((0chain; NumberOfChains = model[modno-1]->nChains; } } } int CoorManager::DeleteChain ( int modelNo, const ChainID chID ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteChain ( chID ); } return 0; } int CoorManager::DeleteChain ( int modelNo, int chainNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteChain ( chainNo ); } return 0; } int CoorManager::DeleteAllChains ( int modelNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAllChains(); } return 0; } int CoorManager::DeleteAllChains() { int i,k; k = 0; for (i=0;iDeleteAllChains(); return k; } int CoorManager::AddChain ( int modelNo, PChain chain ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->AddChain ( chain ); } return 0; } PResidue CoorManager::GetResidue ( int modelNo, const ChainID chainID, int seqNo, const InsCode insCode ) { if ((0GetResidue ( chainID,seqNo,insCode ); } return NULL; } PResidue CoorManager::GetResidue ( int modelNo, int chainNo, int seqNo, const InsCode insCode ) { if ((0GetResidue ( chainNo,seqNo,insCode ); } return NULL; } PResidue CoorManager::GetResidue ( int modelNo, const ChainID chainID, int resNo ) { if ((0GetResidue ( chainID,resNo ); } return NULL; } PResidue CoorManager::GetResidue ( int modelNo, int chainNo, int resNo ) { if ((0GetResidue ( chainNo,resNo ); } return NULL; } PResidue CoorManager::GetResidue ( cpstr CID ) { int modno,sn,rc; ChainID chname; InsCode ic; ResName resname; AtomName aname; Element elname; AltLoc aloc; CoorIDCode = CID_Ok; rc = ParseAtomPath ( CID,modno,chname,sn,ic,resname, aname,elname,aloc,&DefPath ); if ((rc<0) || (rc & (APATH_WC_ModelNo | APATH_WC_ChainID | APATH_WC_SeqNum | APATH_WC_InsCode))) { CoorIDCode = CID_WrongPath; return NULL; } return GetResidue ( modno,chname,sn,ic ); } int CoorManager::GetResidueNo ( int modelNo, const ChainID chainID, int seqNo, const InsCode insCode ) { if ((0GetResidueNo ( chainID,seqNo,insCode ); } return -3; } int CoorManager::GetResidueNo ( int modelNo, int chainNo, int seqNo, const InsCode insCode ) { if ((0GetResidueNo ( chainNo,seqNo,insCode ); } return -3; } void CoorManager::GetResidueTable ( PPResidue & resTable, int & NumberOfResidues ) { // resTable has to be NULL or it will be reallocated. The // application is responsible for deallocating the resTable (but not // of its residues!). This does not apply to other GetResidueTable // functions. PPChain chain; PPResidue res; int i,j,k,n,nChains,nResidues; if (resTable) { delete[] resTable; resTable = NULL; } NumberOfResidues = 0; for (i=0;iGetChainTable ( chain,nChains ); for (j=0;jnChains;j++) if (chain[j]) { chain[j]->GetResidueTable ( res,nResidues ); NumberOfResidues += nResidues; } } if (NumberOfResidues>0) { resTable = new PResidue[NumberOfResidues]; k = 0; for (i=0;iGetChainTable ( chain,nChains ); for (j=0;jnChains;j++) if (chain[j]) { chain[j]->GetResidueTable ( res,nResidues ); for (n=0;nGetChain ( chainID ); if (chain) { resTable = chain->residue; NumberOfResidues = chain->nResidues; } } } } void CoorManager::GetResidueTable ( int modelNo, int chainNo, PPResidue & resTable, int & NumberOfResidues ) { PChain chain; resTable = NULL; NumberOfResidues = 0; if ((0GetChain ( chainNo ); if (chain) { resTable = chain->residue; NumberOfResidues = chain->nResidues; } } } } void CoorManager::GetResidueTable ( cpstr CID, PPResidue & resTable, int & NumberOfResidues ) { int modno,sn,rc; ChainID chname; InsCode ic; ResName resname; AtomName aname; Element elname; AltLoc aloc; PChain chain; resTable = NULL; NumberOfResidues = 0; CoorIDCode = CID_Ok; rc = ParseAtomPath ( CID,modno,chname,sn,ic,resname, aname,elname,aloc,&DefPath ); if ((rc<0) || (rc & (APATH_WC_ModelNo | APATH_WC_ChainID))) { CoorIDCode = CID_WrongPath; return; } if ((0GetChain ( chname ); if (chain) { resTable = chain->residue; NumberOfResidues = chain->nResidues; } } } } int CoorManager::DeleteResidue ( int modelNo, const ChainID chainID, int seqNo, const InsCode insCode ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteResidue ( chainID,seqNo,insCode ); } return 0; } int CoorManager::DeleteResidue ( int modelNo, const ChainID chainID, int resNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteResidue ( chainID,resNo ); } return 0; } int CoorManager::DeleteResidue ( int modelNo, int chainNo, int seqNo, const InsCode insCode ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteResidue ( chainNo,seqNo,insCode ); } return 0; } int CoorManager::DeleteResidue ( int modelNo, int chainNo, int resNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteResidue ( chainNo,resNo ); } return 0; } int CoorManager::DeleteAllResidues ( int modelNo, const ChainID chainID ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAllResidues ( chainID ); } return 0; } int CoorManager::DeleteAllResidues ( int modelNo, int chainNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAllResidues ( chainNo ); } return 0; } int CoorManager::DeleteAllResidues ( int modelNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAllResidues(); } return 0; } int CoorManager::DeleteAllResidues() { int i,k; k = 0; for (i=0;iDeleteAllResidues(); return k; } int CoorManager::AddResidue ( int modelNo, const ChainID chainID, PResidue res ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->AddResidue ( chainID,res ); } return 0; } int CoorManager::AddResidue ( int modelNo, int chainNo, PResidue res ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->AddResidue ( chainNo,res ); } return 0; } int CoorManager::GetNumberOfChains ( int modelNo ) { if ((0nChains; } return 0; } int CoorManager::GetNumberOfChains ( cpstr CID ) { int modno,sn,rc; ChainID chname; InsCode ic; ResName resname; AtomName aname; Element elname; AltLoc aloc; CoorIDCode = CID_Ok; rc = ParseAtomPath ( CID,modno,chname,sn,ic,resname, aname,elname,aloc,&DefPath ); if ((rc<0) || (rc & APATH_WC_ModelNo)) { CoorIDCode = CID_WrongPath; return 0; } if ((0nChains; } return 0; } int CoorManager::GetNumberOfResidues ( int modelNo, const ChainID chainID ) { PChain chain; if ((0GetChain ( chainID ); if (chain) return chain->nResidues; } } return 0; } int CoorManager::GetNumberOfResidues ( int modelNo, int chainNo ) { PChain chain; if ((0nChains)) { chain = model[modelNo-1]->chain[chainNo]; if (chain) return chain->nResidues; } } } return 0; } int CoorManager::GetNumberOfResidues ( cpstr CID ) { int modno,sn,rc; ChainID chname; InsCode ic; ResName resname; AtomName aname; Element elname; AltLoc aloc; PChain chain; CoorIDCode = CID_Ok; rc = ParseAtomPath ( CID,modno,chname,sn,ic,resname, aname,elname,aloc,&DefPath ); if ((rc<0) || (rc & (APATH_WC_ModelNo | APATH_WC_ChainID))) { CoorIDCode = CID_WrongPath; return 0; } if ((0GetChain ( chname ); if (chain) return chain->nResidues; } } return 0; } int CoorManager::GetNumberOfAtoms ( int modelNo, const ChainID chainID, int seqNo, const InsCode insCode ) { PChain chain; PResidue res; if ((0GetChain ( chainID ); if (chain) { res = chain->GetResidue ( seqNo,insCode ); if (res) return res->nAtoms; } } } return 0; } int CoorManager::GetNumberOfAtoms ( int modelNo, int chainNo, int seqNo, const InsCode insCode ) { PChain chain; PResidue res; if ((0nChains)) { chain = model[modelNo-1]->chain[chainNo]; if (chain) { res = chain->GetResidue ( seqNo,insCode ); if (res) return res->nAtoms; } } } } return 0; } int CoorManager::GetNumberOfAtoms ( int modelNo, const ChainID chainID, int resNo ) { PChain chain; PResidue res; if ((0GetChain ( chainID ); if (chain) { if ((0<=resNo) && (resNonResidues)) { res = chain->residue[resNo]; if (res) return res->nAtoms; } } } } return 0; } int CoorManager::GetNumberOfAtoms ( int modelNo, int chainNo, int resNo ) { PChain chain; PResidue res; if ((0nChains)) { chain = model[modelNo-1]->chain[chainNo]; if (chain) { if ((0<=resNo) && (resNonResidues)) { res = chain->residue[resNo]; if (res) return res->nAtoms; } } } } } return 0; } int CoorManager::GetNumberOfAtoms ( cpstr CID ) { // returns number of atoms in residues identified by CID int modno,sn,rc; ChainID chname; InsCode ic; ResName resname; AtomName aname; Element elname; AltLoc aloc; PChain chain; PResidue res; CoorIDCode = CID_Ok; rc = ParseAtomPath ( CID,modno,chname,sn,ic,resname, aname,elname,aloc,&DefPath ); if ((rc<0) || (rc & (APATH_WC_ModelNo | APATH_WC_ChainID | APATH_WC_SeqNum | APATH_WC_InsCode))) { CoorIDCode = CID_WrongPath; return 0; } if ((0GetChain ( chname ); if (chain) { res = chain->GetResidue ( sn,ic ); if (res) return res->nAtoms; } } } return 0; } // -------------------- Extracting atoms ----------------------- PAtom CoorManager::GetAtom ( int modelNo, // model serial number 1... const ChainID chID, // chain ID int seqNo, // residue sequence number const InsCode insCode, // residue insertion code const AtomName aname, // atom name const Element elmnt, // chemical element code or '*' const AltLoc aloc // alternate location indicator ) { PModel mdl; PChain chn; PResidue res; PAtom atm; if ((1<=modelNo) && (modelNo<=nModels)) mdl = model[modelNo-1]; else mdl = NULL; if (!mdl) { CoorIDCode = CID_NoModel; return NULL; } chn = mdl->GetChain ( chID ); if (!chn) { CoorIDCode = CID_NoChain; return NULL; } res = chn->GetResidue ( seqNo,insCode ); if (!res) { CoorIDCode = CID_NoResidue; return NULL; } atm = res->GetAtom ( aname,elmnt,aloc ); if (!atm) CoorIDCode = CID_NoAtom; else CoorIDCode = CID_Ok; return atm; } PAtom CoorManager::GetAtom ( int modelNo, // model serial number 1... const ChainID chID, // chain ID int seqNo, // residue sequence number const InsCode insCode, // residue insertion code int atomNo // atom number 0.. ) { PModel mdl; PChain chn; PResidue res; PAtom atm; if ((1<=modelNo) && (modelNo<=nModels)) mdl = model[modelNo-1]; else mdl = NULL; if (!mdl) { CoorIDCode = CID_NoModel; return NULL; } chn = mdl->GetChain ( chID ); if (!chn) { CoorIDCode = CID_NoChain; return NULL; } res = chn->GetResidue ( seqNo,insCode ); if (!res) { CoorIDCode = CID_NoResidue; return NULL; } if ((0<=atomNo) && (atomNonAtoms)) atm = res->atom[atomNo]; else atm = NULL; if (!atm) CoorIDCode = CID_NoAtom; else CoorIDCode = CID_Ok; return atm; } PAtom CoorManager::GetAtom ( int modelNo, // model serial number 1... const ChainID chID, // chain ID int resNo, // residue number 0.. const AtomName aname, // atom name const Element elmnt, // chemical element code or '*' const AltLoc aloc // alternate location indicator ) { PModel mdl; PChain chn; PResidue res; PAtom atm; if ((1<=modelNo) && (modelNo<=nModels)) mdl = model[modelNo-1]; else mdl = NULL; if (!mdl) { CoorIDCode = CID_NoModel; return NULL; } chn = mdl->GetChain ( chID ); if (!chn) { CoorIDCode = CID_NoChain; return NULL; } if ((0<=resNo) && (resNonResidues)) res = chn->residue[resNo]; else res = NULL; if (!res) { CoorIDCode = CID_NoResidue; return NULL; } atm = res->GetAtom ( aname,elmnt,aloc ); if (!atm) CoorIDCode = CID_NoAtom; else CoorIDCode = CID_Ok; return atm; } PAtom CoorManager::GetAtom ( int modelNo, // model serial number 1... const ChainID chID, // chain ID int resNo, // residue number 0.. int atomNo // atom number 0.. ) { PModel mdl; PChain chn; PResidue res; PAtom atm; if ((1<=modelNo) && (modelNo<=nModels)) mdl = model[modelNo-1]; else mdl = NULL; if (!mdl) { CoorIDCode = CID_NoModel; return NULL; } chn = mdl->GetChain ( chID ); if (!chn) { CoorIDCode = CID_NoChain; return NULL; } if ((0<=resNo) && (resNonResidues)) res = chn->residue[resNo]; else res = NULL; if (!res) { CoorIDCode = CID_NoResidue; return NULL; } if ((0<=atomNo) && (atomNonAtoms)) atm = res->atom[atomNo]; else atm = NULL; if (!atm) CoorIDCode = CID_NoAtom; else CoorIDCode = CID_Ok; return atm; } PAtom CoorManager::GetAtom ( int modelNo, // model serial number 1... int chNo, // chain number 0.. int seqNo, // residue sequence number const InsCode insCode, // residue insertion code const AtomName aname, // atom name const Element elmnt, // chemical element code or '*' const AltLoc aloc // alternate location indicator ) { PModel mdl; PChain chn; PResidue res; PAtom atm; if ((1<=modelNo) && (modelNo<=nModels)) mdl = model[modelNo-1]; else mdl = NULL; if (!mdl) { CoorIDCode = CID_NoModel; return NULL; } if ((0<=chNo) && (chNonChains)) chn = mdl->chain[chNo]; else chn = NULL; if (!chn) { CoorIDCode = CID_NoChain; return NULL; } res = chn->GetResidue ( seqNo,insCode ); if (!res) { CoorIDCode = CID_NoResidue; return NULL; } atm = res->GetAtom ( aname,elmnt,aloc ); if (!atm) CoorIDCode = CID_NoAtom; else CoorIDCode = CID_Ok; return atm; } PAtom CoorManager::GetAtom ( int modelNo, // model serial number 1... int chNo, // chain number 0... int seqNo, // residue sequence number const InsCode insCode, // residue insertion code int atomNo // atom number 0... ) { PModel mdl; PChain chn; PResidue res; PAtom atm; if ((1<=modelNo) && (modelNo<=nModels)) mdl = model[modelNo-1]; else mdl = NULL; if (!mdl) { CoorIDCode = CID_NoModel; return NULL; } if ((0<=chNo) && (chNonChains)) chn = mdl->chain[chNo]; else chn = NULL; if (!chn) { CoorIDCode = CID_NoChain; return NULL; } res = chn->GetResidue ( seqNo,insCode ); if (!res) { CoorIDCode = CID_NoResidue; return NULL; } if ((0<=atomNo) && (atomNonAtoms)) atm = res->atom[atomNo]; else atm = NULL; if (!atm) CoorIDCode = CID_NoAtom; else CoorIDCode = CID_Ok; return atm; } PAtom CoorManager::GetAtom ( int modelNo, // model serial number 1... int chNo, // chain number 0... int resNo, // residue number 0... const AtomName aname, // atom name const Element elmnt, // chemical element code or '*' const AltLoc aloc // alternate location indicator ) { PModel mdl; PChain chn; PResidue res; PAtom atm; if ((1<=modelNo) && (modelNo<=nModels)) mdl = model[modelNo-1]; else mdl = NULL; if (!mdl) { CoorIDCode = CID_NoModel; return NULL; } if ((0<=chNo) && (chNonChains)) chn = mdl->chain[chNo]; else chn = NULL; if (!chn) { CoorIDCode = CID_NoChain; return NULL; } if ((0<=resNo) && (resNonResidues)) res = chn->residue[resNo]; else res = NULL; if (!res) { CoorIDCode = CID_NoResidue; return NULL; } atm = res->GetAtom ( aname,elmnt,aloc ); if (!atm) CoorIDCode = CID_NoAtom; else CoorIDCode = CID_Ok; return atm; } PAtom CoorManager::GetAtom ( int modelNo, // model serial number 1... int chNo, // chain number 0... int resNo, // residue number 0... int atomNo // atom number 0... ) { PModel mdl; PChain chn; PResidue res; PAtom atm; if ((1<=modelNo) && (modelNo<=nModels)) mdl = model[modelNo-1]; else mdl = NULL; if (!mdl) { CoorIDCode = CID_NoModel; return NULL; } if ((0<=chNo) && (chNonChains)) chn = mdl->chain[chNo]; else chn = NULL; if (!chn) { CoorIDCode = CID_NoChain; return NULL; } if ((0<=resNo) && (resNonResidues)) res = chn->residue[resNo]; else res = NULL; if (!res) { CoorIDCode = CID_NoResidue; return NULL; } if ((0<=atomNo) && (atomNonAtoms)) atm = res->atom[atomNo]; else atm = NULL; if (!atm) CoorIDCode = CID_NoAtom; else CoorIDCode = CID_Ok; return atm; } PAtom CoorManager::GetAtom ( cpstr CID ) { int modno,sn,rc; ChainID chname; InsCode ic; ResName resname; AtomName aname; Element elname; AltLoc aloc; CoorIDCode = CID_Ok; rc = ParseAtomPath ( CID,modno,chname,sn,ic,resname, aname,elname,aloc,&DefPath ); if ((rc<0) || (rc & APATH_Incomplete)) { CoorIDCode = CID_WrongPath; return NULL; } return GetAtom ( modno,chname,sn,ic,aname,elname,aloc ); } void CoorManager::GetAtomTable ( PPAtom & atomTable, int & NumberOfAtoms ) { atomTable = atom; NumberOfAtoms = nAtoms; } void CoorManager::GetAtomTable ( int modelNo, const ChainID chainID, int seqNo, const InsCode insCode, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; atomTable = NULL; NumberOfAtoms = 0; if ((0GetResidue ( chainID,seqNo,insCode ); if (res) { atomTable = res->atom; NumberOfAtoms = res->nAtoms; } } } } void CoorManager::GetAtomTable ( int modelNo, int chainNo, int seqNo, const InsCode insCode, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; atomTable = NULL; NumberOfAtoms = 0; if ((0GetResidue ( chainNo,seqNo,insCode ); if (res) { atomTable = res->atom; NumberOfAtoms = res->nAtoms; } } } } void CoorManager::GetAtomTable ( int modelNo, const ChainID chainID, int resNo, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; atomTable = NULL; NumberOfAtoms = 0; if ((0GetResidue ( chainID,resNo ); if (res) { atomTable = res->atom; NumberOfAtoms = res->nAtoms; } } } } void CoorManager::GetAtomTable ( int modelNo, int chainNo, int resNo, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; atomTable = NULL; NumberOfAtoms = 0; if ((0GetResidue ( chainNo,resNo ); if (res) { atomTable = res->atom; NumberOfAtoms = res->nAtoms; } } } } void CoorManager::GetAtomTable ( cpstr CID, PPAtom & atomTable, int & NumberOfAtoms ) { int modno,sn,rc; ChainID chname; InsCode ic; ResName resname; AtomName aname; Element elname; AltLoc aloc; PResidue res; atomTable = NULL; NumberOfAtoms = 0; CoorIDCode = CID_Ok; rc = ParseAtomPath ( CID,modno,chname,sn,ic,resname, aname,elname,aloc,&DefPath ); if ((rc<0) || (rc & (APATH_WC_ModelNo | APATH_WC_ChainID | APATH_WC_SeqNum | APATH_WC_InsCode))) { CoorIDCode = CID_WrongPath; return; } res = GetResidue ( modno,chname,sn,ic ); if (res) { atomTable = res->atom; NumberOfAtoms = res->nAtoms; } } void CoorManager::GetAtomTable1 ( PPAtom & atomTable, int & NumberOfAtoms ) { int i,j; if (atomTable) delete[] atomTable; if (nAtoms>0) { atomTable = new PAtom[nAtoms]; j = 0; for (i=0;iTer) atomTable[j++] = atom[i]; } NumberOfAtoms = j; } else { atomTable = NULL; NumberOfAtoms = 0; } } void CoorManager::GetAtomTable1 ( int modelNo, const ChainID chainID, int seqNo, const InsCode insCode, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; res = NULL; if ((0GetResidue ( chainID,seqNo,insCode ); } if (res) res->GetAtomTable1 ( atomTable,NumberOfAtoms ); else { if (atomTable) delete[] atomTable; atomTable = NULL; NumberOfAtoms = 0; } } void CoorManager::GetAtomTable1 ( int modelNo, int chainNo, int seqNo, const InsCode insCode, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; res = NULL; if ((0GetResidue ( chainNo,seqNo,insCode ); } if (res) res->GetAtomTable1 ( atomTable,NumberOfAtoms ); else { if (atomTable) delete[] atomTable; atomTable = NULL; NumberOfAtoms = 0; } } void CoorManager::GetAtomTable1 ( int modelNo, const ChainID chainID, int resNo, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; res = NULL; if ((0GetResidue ( chainID,resNo ); } if (res) res->GetAtomTable1 ( atomTable,NumberOfAtoms ); else { if (atomTable) delete[] atomTable; atomTable = NULL; NumberOfAtoms = 0; } } void CoorManager::GetAtomTable1 ( int modelNo, int chainNo, int resNo, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; res = NULL; if ((0GetResidue ( chainNo,resNo ); } if (res) res->GetAtomTable1 ( atomTable,NumberOfAtoms ); else { if (atomTable) delete[] atomTable; atomTable = NULL; NumberOfAtoms = 0; } } void CoorManager::GetAtomTable1 ( cpstr CID, PPAtom & atomTable, int & NumberOfAtoms ) { int modno,sn,rc; ChainID chname; InsCode ic; ResName resname; AtomName aname; Element elname; AltLoc aloc; PResidue res; atomTable = NULL; NumberOfAtoms = 0; CoorIDCode = CID_Ok; rc = ParseAtomPath ( CID,modno,chname,sn,ic,resname, aname,elname,aloc,&DefPath ); if ((rc<0) || (rc & (APATH_WC_ModelNo | APATH_WC_ChainID | APATH_WC_SeqNum | APATH_WC_InsCode))) { CoorIDCode = CID_WrongPath; return; } res = GetResidue ( modno,chname,sn,ic ); if (res) res->GetAtomTable1 ( atomTable,NumberOfAtoms ); else { if (atomTable) delete[] atomTable; atomTable = NULL; NumberOfAtoms = 0; } } int CoorManager::DeleteAtom ( int modelNo, const ChainID chID, int seqNo, const InsCode insCode, const AtomName aname, const Element elmnt, const AltLoc aloc ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAtom ( chID,seqNo,insCode, aname,elmnt,aloc ); } return 0; } int CoorManager::DeleteAtom ( int modelNo, const ChainID chID, int seqNo, const InsCode insCode, int atomNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAtom ( chID,seqNo,insCode,atomNo ); } return 0; } int CoorManager::DeleteAtom ( int modelNo, const ChainID chID, int resNo, const AtomName aname, const Element elmnt, const AltLoc aloc ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAtom ( chID,resNo, aname,elmnt,aloc ); } return 0; } int CoorManager::DeleteAtom ( int modelNo, const ChainID chID, int resNo, int atomNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAtom ( chID,resNo,atomNo ); } return 0; } int CoorManager::DeleteAtom ( int modelNo, int chNo, int seqNo, const InsCode insCode, const AtomName aname, const Element elmnt, const AltLoc aloc ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAtom ( chNo,seqNo,insCode, aname,elmnt,aloc ); } return 0; } int CoorManager::DeleteAtom ( int modelNo, int chNo, int seqNo, const InsCode insCode, int atomNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAtom ( chNo,seqNo,insCode,atomNo ); } return 0; } int CoorManager::DeleteAtom ( int modelNo, int chNo, int resNo, const AtomName aname, const Element elmnt, const AltLoc aloc ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAtom ( chNo,resNo, aname,elmnt,aloc ); } return 0; } int CoorManager::DeleteAtom ( int modelNo, int chNo, int resNo, int atomNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAtom ( chNo,resNo,atomNo ); } return 0; } int CoorManager::DeleteAllAtoms ( int modelNo, const ChainID chID, int seqNo, const InsCode insCode ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAllAtoms ( chID,seqNo,insCode ); } return 0; } int CoorManager::DeleteAllAtoms ( int modelNo, const ChainID chID, int resNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAllAtoms ( chID,resNo ); } return 0; } int CoorManager::DeleteAllAtoms ( int modelNo, const ChainID chID ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAllAtoms ( chID ); } return 0; } int CoorManager::DeleteAllAtoms ( int modelNo, int chNo, int seqNo, const InsCode insCode ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAllAtoms ( chNo,seqNo,insCode ); } return 0; } int CoorManager::DeleteAllAtoms ( int modelNo, int chNo, int resNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAllAtoms ( chNo,resNo ); } return 0; } int CoorManager::DeleteAllAtoms ( int modelNo, int chNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAllAtoms ( chNo ); } return 0; } int CoorManager::DeleteAllAtoms ( int modelNo ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->DeleteAllAtoms(); } return 0; } int CoorManager::DeleteAllAtoms() { int i,k; k = 0; for (i=0;iDeleteAllAtoms(); return k; } /* int CoorManager::DeleteAltLocs() { // This function leaves only alternative location with maximal // occupancy, if those are equal or unspecified, the one with // "least" alternative location indicator. // The function returns the number of deleted atoms and optimizes // the atom index. ChainID chID; ResName rName; InsCode iCode; AtomName aname; AltLoc aLoc,aL; realtype occupancy,occ; int seqNum; int i,j,k,i1,i2,n; k = 0; n = 0; i = 0; while (iGetSeqNum (); occupancy = atom[i]->GetOccupancy(); strcpy ( chID ,atom[i]->GetChainID() ); strcpy ( rName,atom[i]->GetResName() ); strcpy ( iCode,atom[i]->GetInsCode() ); strcpy ( aname,atom[i]->name ); strcpy ( aLoc ,atom[i]->altLoc ); j = i+1; i1 = -1; i2 = i; while (jGetSeqNum()==seqNum) && (!strcmp(atom[j]->name,aname)) && (!strcmp(atom[j]->GetInsCode(),iCode)) && (!strcmp(atom[j]->GetResName(),rName)) && (!strcmp(atom[j]->GetChainID(),chID ))) { occ = atom[j]->GetOccupancy(); if (occ>occupancy) { occupancy = occ; i1 = j; } if (aLoc[0]) { strcpy ( aL,atom[j]->altLoc ); if (!aL[0]) { aLoc[0] = char(0); i2 = j; } else if (strcmp(aL,aLoc)<0) { strcpy ( aLoc,aL ); i2 = j; } } j++; } else break; } else j++; if (i1<0) { if (atom[i]->WhatIsSet & ASET_Occupancy) i1 = i; else i1 = i2; } while (iindex = k+1; } k++; } } i++; } } else i++; } nAtoms = k; return n; } */ int CoorManager::DeleteAltLocs() { // This function leaves only alternative location with maximal // occupancy, if those are equal or unspecified, the one with // "least" alternative location indicator. // The function returns the number of deleted atoms. All tables // remain untrimmed, so that explicit trimming or calling // FinishStructEdit() at some point is required. int i,n; n = 0; for (i=0;iDeleteAltLocs(); return n; } int CoorManager::AddAtom ( int modelNo, const ChainID chID, int seqNo, const InsCode insCode, PAtom atom ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->AddAtom ( chID,seqNo,insCode,atom ); } return 0; } int CoorManager::AddAtom ( int modelNo, const ChainID chID, int resNo, PAtom atom ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->AddAtom ( chID,resNo,atom ); } return 0; } int CoorManager::AddAtom ( int modelNo, int chNo, int seqNo, const InsCode insCode, PAtom atom ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->AddAtom ( chNo,seqNo,insCode,atom ); } return 0; } int CoorManager::AddAtom ( int modelNo, int chNo, int resNo, PAtom atom ) { if ((modelNo>0) && (modelNo<=nModels)) { if (model[modelNo-1]) return model[modelNo-1]->AddAtom ( chNo,resNo,atom ); } return 0; } void CoorManager::RemoveBricks() { int i,j,k; if (brick) { for (i=0;ix-xbrick_0)/brick_size); ny = (int)floor((A->y-ybrick_0)/brick_size); nz = (int)floor((A->z-zbrick_0)/brick_size); if ((ny<0) || (nz<0) || (nx>=nbrick_x) || (ny>=nbrick_y) || (nz>=nbrick_z)) nx = -1; } void CoorManager::GetBrickCoor ( realtype x, realtype y, realtype z, int & nx, int & ny, int & nz ) { nx = (int)floor((x-xbrick_0)/brick_size); ny = (int)floor((y-ybrick_0)/brick_size); nz = (int)floor((z-zbrick_0)/brick_size); if ((ny<0) || (nz<0) || (nx>=nbrick_x) || (ny>=nbrick_y) || (nz>=nbrick_z)) nx = -1; } void CoorManager::GetBrickCoor ( vect3 & xyz, int & nx, int & ny, int & nz ) { nx = (int)floor((xyz[0]-xbrick_0)/brick_size); ny = (int)floor((xyz[1]-ybrick_0)/brick_size); nz = (int)floor((xyz[2]-zbrick_0)/brick_size); if ((ny<0) || (nz<0) || (nx>=nbrick_x) || (ny>=nbrick_y) || (nz>=nbrick_z)) nx = -1; } void CoorManager::GetBrickDimension ( int & nxmax, int & nymax, int & nzmax ) { if (!brick) { nxmax = 0; nymax = 0; nzmax = 0; } else { nxmax = nbrick_x; nymax = nbrick_y; nzmax = nbrick_z; } } PBrick CoorManager::GetBrick ( int nx, int ny, int nz ) { if (!brick) return NULL; if ((nx>=0) && (nx=0) && (ny=0) && (nz0) { // find the range of coordinates x1 = MaxReal; x2 = -x1; y1 = MaxReal; y2 = -y1; z1 = MaxReal; z2 = -z1; for (i=0;iTer) && (A[i]->WhatIsSet & ASET_Coordinates)) { if (A[i]->xx; if (A[i]->x>x2) x2 = A[i]->x; if (A[i]->yy; if (A[i]->y>y2) y2 = A[i]->y; if (A[i]->zz; if (A[i]->z>z2) z2 = A[i]->z; } } if (x1Ter) && (A[i]->WhatIsSet & ASET_Coordinates)) { GetBrickCoor ( A[i],nx,ny,nz ); if (nx>=0) { if (!brick) { brick = new PPPBrick[nbrick_x]; for (j=0;jAddAtom ( A[i],i ); } else printf ( " error in " "CoorManager::MakeBricks!!!\n" ); } } } } } void CoorManager::RemoveMBricks() { int i,j,k; if (mbrick) { for (i=0;ix-xmbrick_0)/mbrick_size); ny = (int)floor((A->y-ymbrick_0)/mbrick_size); nz = (int)floor((A->z-zmbrick_0)/mbrick_size); if ((ny<0) || (nz<0) || (nx>=nmbrick_x) || (ny>=nmbrick_y) || (nz>=nmbrick_z)) nx = -nx-1; } void CoorManager::GetMBrickCoor ( realtype x, realtype y, realtype z, int & nx, int & ny, int & nz ) { nx = (int)floor((x-xmbrick_0)/mbrick_size); ny = (int)floor((y-ymbrick_0)/mbrick_size); nz = (int)floor((z-zmbrick_0)/mbrick_size); if ((ny<0) || (nz<0) || (nx>=nmbrick_x) || (ny>=nmbrick_y) || (nz>=nmbrick_z)) nx = -nx-1; } void CoorManager::GetMBrickDimension ( int & nxmax, int & nymax, int & nzmax ) { if (!brick) { nxmax = 0; nymax = 0; nzmax = 0; } else { nxmax = nmbrick_x; nymax = nmbrick_y; nzmax = nmbrick_z; } } PMBrick CoorManager::GetMBrick ( int nx, int ny, int nz ) { if (!mbrick) return NULL; if ((nx>=0) && (nx=0) && (ny=0) && (nzTer) && (A->WhatIsSet & ASET_Coordinates)) { if (A->xx; if (A->x>x2) x2 = A->x; if (A->yy; if (A->y>y2) y2 = A->y; if (A->zz; if (A->z>z2) z2 = A->z; } } } if (x1Ter) && (A->WhatIsSet & ASET_Coordinates)) { GetMBrickCoor ( A,nx,ny,nz ); if (nx>=0) { if (!mbrick) { mbrick = new PPPMBrick[nmbrick_x]; for (k=0;kAddAtom ( A,i,j ); } else printf ( " error in " "CoorManager::MakeMBricks!!!\n" ); } } } } } int CoorManager::GenerateSymMates ( PGenSym genSym ) { // // The function generates symmetry mates according to symmetry // operations found in GenSym. Results of first symmetry operation // (number 0) always replaces the existing set of atoms, others // are added as additional sets. // If GenSym is set to NULL, the function generates all // symmetry mates for the unit cell taking the symmetry information // from cryst.SymOps. // The newly generated chains are added to each model. These // chains have many-character chain names, composed as 'x_n', // where 'x' is the original name and 'n' is a unique number, which // coincides with the symmetry operation (order) number; number '_0' // (for the very first symmetry operatyion) is missing. Another // side effect is the disorder in atoms' serial numbers. // The hierarchy should therefore be cleaned after // generating the symmetry mates. An appropriate way to do // that is to issue the following call: // // PDBCleanup ( PDBCLEAN_TER | PDBCLEAN_ALTCODE_STRONG | // PDBCLEAN_CHAIN_STRONG | PDBCLEAN_SERIAL ); // PPCoorManager Mate; int i,j,k,n,nMates,nMates1,nAtoms1; PPAtom Atom1; PPModel Model1; if (genSym) nMates = genSym->GetNofSymOps(); else nMates = cryst.GetNumberOfSymOps(); if (nMates<=0) return GSM_NoSymOps; if (!cryst.areMatrices()) return GSM_NoTransfMatrices; if (!cryst.isCellParameters()) return GSM_NoCell; nMates1 = nMates-1; if (nMates1>0) { // Generate symmetry mates in parallel hierarchies Mate = new PCoorManager[nMates1]; for (i=0;iCopy ( this ); Mate[i]->ApplySymTransform ( i+1,genSym ); } // apply 1st symmetry operation: if (genSym) ApplySymTransform ( 0,genSym ); // Gather all symmetry mates in 'this' hierarchy nAtoms1 = nMates*nAtoms; // new number of atoms Atom1 = new PAtom[nAtoms1]; // new array of atoms if (nModels>0) Model1 = new PModel[nModels]; // new array of else Model1 = NULL; // models k = 0; // index of collected atoms for (i=0;iSetMMDBManager ( PManager(this),i+1 ); for (j=0;jnChains;j++) Model1[i]->MoveChain ( model[i]->chain[j],atom,Atom1,k,0 ); for (n=0;nnChains;j++) Model1[i]->MoveChain ( Mate[n]->model[i]->chain[j], Mate[n]->atom,Atom1,k,n+1 ); } else Model1[i] = NULL; if (model) delete[] model; model = Model1; for (i=0;iTer) atom[i]->Transform ( TMatrix ); } } void CoorManager::ApplySymTransform ( int SymOpNo, PGenSym genSym ) { // This procedure applies the symmetry operation number SymOpNo // (starting from 0 on) and renames chains as specified in // GenSym. // The chains don't have to be renamed. The number of chains // to be renamed is obtained as GenSym->nChains[SymOpNo], their // old names - as GenSym->chID1[SymOpNo][j], and their new names // - as GenSym->chID2[SymOpNo][j], 0<=jnChains[SymOpNo]. mat44 tmat; int i,j,k,nChn; PPChain chain; if (cryst.GetTMatrix(tmat,SymOpNo,0,0,0,PSymOps(genSym)) ==SYMOP_Ok) { for (i=0;iTer) atom[i]->Transform ( tmat ); } if (genSym) for (i=0;iGetChainTable ( chain,nChn ); for (j=0;jnChains[SymOpNo];j++) for (k=0;kchainID,genSym->chID1[SymOpNo][j])) chain[k]->SetChainID ( genSym->chID2[SymOpNo][j] ); } } } void GetEulerRotMatrix ( mat33 & erm, realtype alpha, realtype beta, realtype gamma ) { // Calculates the Euler rotation matrix for rotation: // 1) about z-axis by angle alpha (0..2*Pi) // 2) about new y-axis by angle beta (0..Pi) // 3) about new z-axis by angle gamma (0..2*Pi) realtype ca,cb,cg, sa,sb,sg; ca = cos(alpha); sa = sin(alpha); cb = cos(beta); sb = sin(beta); cg = cos(gamma); sg = sin(gamma); erm[0][0] = ca*cb*cg - sa*sg; erm[0][1] = cb*cg*sa + ca*sg; erm[0][2] = -cg*sb; erm[1][0] = -cg*sa - ca*cb*sg; erm[1][1] = ca*cg - cb*sa*sg; erm[1][2] = sb*sg; erm[2][0] = ca*sb; erm[2][1] = sa*sb; erm[2][2] = cb; } void GetEulerTMatrix ( mat44 & erm, realtype alpha, realtype beta, realtype gamma, realtype x0, realtype y0, realtype z0 ) { // Calculates the Euler rotation-translation matrix for rotation: // 1) about z-axis by angle alpha // 2) about new y-axis by angle beta // 3) about new z-axis by angle gamma // Point (x0,y0,z0) is the center of rotation. mat33 m; m[0][0] = 1.0; GetEulerRotMatrix ( m,alpha,beta,gamma ); erm[0][0] = m[0][0]; erm[0][1] = m[0][1]; erm[0][2] = m[0][2]; erm[1][0] = m[1][0]; erm[1][1] = m[1][1]; erm[1][2] = m[1][2]; erm[2][0] = m[2][0]; erm[2][1] = m[2][1]; erm[2][2] = m[2][2]; erm[3][0] = 0.0; erm[3][1] = 0.0; erm[3][2] = 0.0; erm[3][3] = 1.0; erm[0][3] = x0 - m[0][0]*x0 - m[0][1]*y0 - m[0][2]*z0; erm[1][3] = y0 - m[1][0]*x0 - m[1][1]*y0 - m[1][2]*z0; erm[2][3] = z0 - m[2][0]*x0 - m[2][1]*y0 - m[2][2]*z0; } void EulerRotation ( PPAtom A, int nA, realtype alpha, realtype beta, realtype gamma, realtype x0, realtype y0, realtype z0 ) { // Euler rotation: 1) about z-axis by angle alpha // 2) about new y-axis by angle beta // 3) about new z-axis by angle gamma // Point (x0,y0,z0) is the center of rotation. mat33 m; realtype x,y,z; int i; m[0][0] = 1.0; GetEulerRotMatrix ( m,alpha,beta,gamma ); for (i=0;iTer) && (A[i]->WhatIsSet & ASET_Coordinates)) { x = A[i]->x - x0; y = A[i]->y - y0; z = A[i]->z - z0; A[i]->x = m[0][0]*x + m[0][1]*y + m[0][2]*z + x0; A[i]->y = m[1][0]*x + m[1][1]*y + m[1][2]*z + y0; A[i]->z = m[2][0]*x + m[2][1]*y + m[2][2]*z + z0; } } } void GetVecRotMatrix ( mat33 & vrm, realtype alpha, realtype vx, realtype vy, realtype vz ) { // Calculates the rotation matrix for rotation by angle alpha about // arbitrary vector directed as (vx,vy,vz) = (vx2-vx1,vy2-vy1,vz2-vz1). realtype ca,sa, rx,ry,rz, vl; ca = cos(alpha); sa = sin(alpha); vl = sqrt ( vx*vx + vy*vy + vz*vz ); if (vl<=0.0) return; rx = vx/vl; ry = vy/vl; rz = vz/vl; vrm[0][0] = rx*rx*(1.0-ca) + ca; vrm[0][1] = rx*ry*(1.0-ca) - rz*sa; vrm[0][2] = rx*rz*(1.0-ca) + ry*sa; vrm[1][0] = ry*rx*(1.0-ca) + rz*sa; vrm[1][1] = ry*ry*(1.0-ca) + ca; vrm[1][2] = ry*rz*(1.0-ca) - rx*sa; vrm[2][0] = rz*rx*(1.0-ca) - ry*sa; vrm[2][1] = rz*ry*(1.0-ca) + rx*sa; vrm[2][2] = rz*rz*(1.0-ca) + ca; } void GetRotParameters ( mat33 & vrm, realtype & alpha, realtype & vx, realtype & vy, realtype & vz ) { // Given the rotation matrix vrm, GetRotParameters(..) // returns the rotation angle alpha and the normalized // rotation axis vector (vx,vy,vz). // The rotation angle and vector are determined up to // their sign (however correlated, so that being substituted // into GetVecRotMatrix(..) they yield the same rotation // matrix). // The function does not check for vrm to be a valid // rotation matrix. realtype ca,sa,vl; ca = (vrm[0][0]+vrm[1][1]+vrm[2][2]-1.0)/2.0; if (ca<-1.0) ca = -1.0; // does not work if rotation if (ca>1.0) ca = 1.0; // matrix is correct sa = sqrt(1.0-ca*ca); if (sa>0.0) { alpha = acos(ca); // coefficient of 2 is corrected by normalization below vx = (vrm[2][1]-vrm[1][2])/sa; vy = (vrm[0][2]-vrm[2][0])/sa; vz = (vrm[1][0]-vrm[0][1])/sa; // the following code is formally redundant if rotation // matrix is correct, however it eliminates the round-offs vl = sqrt(vx*vx+vy*vy+vz*vz); vx /= vl; vy /= vl; vz /= vl; } else { // zero rotation, arbitrary axis would do alpha = 0.0; vx = 1.0; vy = 0.0; vz = 0.0; } } void GetVecTMatrix ( mat44 & vrm, realtype alpha, realtype vx, realtype vy, realtype vz, realtype x0, realtype y0, realtype z0 ) { // Calculates the rotation-translation matrix for rotation by angle // alpha about arbitrary vector directed as (vx,vy,vz) = // (vx2-vx1,vy2-vy1,vz2-vz1). Point (x0,y0,z0) is the center of // rotation -- actually a point belonging to the rotation axis. mat33 m; GetVecRotMatrix ( m,alpha,vx,vy,vz ); vrm[0][0] = m[0][0]; vrm[0][1] = m[0][1]; vrm[0][2] = m[0][2]; vrm[1][0] = m[1][0]; vrm[1][1] = m[1][1]; vrm[1][2] = m[1][2]; vrm[2][0] = m[2][0]; vrm[2][1] = m[2][1]; vrm[2][2] = m[2][2]; vrm[3][0] = 0.0; vrm[3][1] = 0.0; vrm[3][2] = 0.0; vrm[3][3] = 1.0; vrm[0][3] = x0 - m[0][0]*x0 - m[0][1]*y0 - m[0][2]*z0; vrm[1][3] = y0 - m[1][0]*x0 - m[1][1]*y0 - m[1][2]*z0; vrm[2][3] = z0 - m[2][0]*x0 - m[2][1]*y0 - m[2][2]*z0; } void VectorRotation ( PPAtom A, int nA, realtype alpha, realtype vx, realtype vy, realtype vz, realtype x0, realtype y0, realtype z0 ) { // Vector rotation is rotation by angle alpha about arbitrary // vector directed as (vx,vy,vz) = (vx2-vx1,vy2-vy1,vz2-vz1). // Point (x0,y0,z0) is the center of rotation -- actually // a point belonging to the rotation axis. mat33 m; realtype x,y,z; int i; GetVecRotMatrix ( m, alpha,vx,vy,vz ); for (i=0;iTer) && (A[i]->WhatIsSet & ASET_Coordinates)) { x = A[i]->x - x0; y = A[i]->y - y0; z = A[i]->z - z0; A[i]->x = m[0][0]*x + m[0][1]*y + m[0][2]*z + x0; A[i]->y = m[1][0]*x + m[1][1]*y + m[1][2]*z + y0; A[i]->z = m[2][0]*x + m[2][1]*y + m[2][2]*z + z0; } } } void GetMassCenter ( PPAtom A, int nA, realtype & xmc, realtype & ymc, realtype & zmc ) { realtype w,mass; int i,k; xmc = 0.0; ymc = 0.0; zmc = 0.0; mass = 0.0; for (i=0;iTer) && (A[i]->WhatIsSet & ASET_Coordinates)) { k = getElementNo ( A[i]->element ); if (k>=0) w = MolecWeight[k]; else w = 1.0; xmc += w*A[i]->x; ymc += w*A[i]->y; zmc += w*A[i]->z; mass += w; } } if (mass>0.0) { xmc /= mass; ymc /= mass; zmc /= mass; } } int CoorManager::BringToUnitCell() { // brings all chains into 0th unit cell PChain chain; PPAtom atom; realtype x0,y0,z0, x,y,z, xf,yf,zf, sx,sy,sz; realtype dx,dy,dz, d,d0; int nAtoms; int i,j,k,n,m,nt, ic,jc,kc, is,js,ks; if (!cryst.areMatrices()) return -1; is = 0; // this is only js = 0; // to depress ks = 0; // "uninitialized" worning cryst.Frac2Orth ( 0.5,0.5,0.5, x0,y0,z0 ); nt = 0; for (i=0;inChains;j++) { chain = model[i]->chain[j]; if (chain) { x = 0.0; y = 0.0; z = 0.0; m = 0; for (k=0;knResidues;k++) if (chain->residue[k]) { chain->residue[k]->GetAtomTable ( atom,nAtoms ); for (n=0;nTer) { x += atom[n]->x; y += atom[n]->y; z += atom[n]->z; m++; } } } x /= m; y /= m; z /= m; cryst.Orth2Frac ( x,y,z, xf,yf,zf ); sx = frac ( xf ); sy = frac ( yf ); sz = frac ( zf ); d0 = MaxReal; for (ic=-3;ic<3;ic++) for (jc=-3;jc<3;jc++) for (kc=-3;kc<3;kc++) { cryst.Frac2Orth ( sx+ic,sy+jc,sz+kc, dx,dy,dz ); dx -= x0; dy -= y0; dz -= z0; d = dx*dx + dy*dy + dz*dz; if (d1.0e-10) || (fabs(sy)>1.0e-10) || (fabs(sz)>1.0e-10)) { nt++; for (k=0;knResidues;k++) if (chain->residue[k]) { chain->residue[k]->GetAtomTable ( atom,nAtoms ); for (n=0;nTer) { cryst.Orth2Frac ( atom[n]->x,atom[n]->y, atom[n]->z, xf,yf,zf ); cryst.Frac2Orth ( xf-sx,yf-sy,zf-sz, atom[n]->x,atom[n]->y, atom[n]->z ); } } } } } } } return nt; // number of converted chains } bool CoorManager::Frac2Orth ( realtype xfrac, realtype yfrac, realtype zfrac, realtype & xorth, realtype & yorth, realtype & zorth ) { return cryst.Frac2Orth ( xfrac,yfrac,zfrac, xorth,yorth,zorth ); } bool CoorManager::Orth2Frac ( realtype xorth, realtype yorth, realtype zorth, realtype & xfrac, realtype & yfrac, realtype & zfrac ) { return cryst.Orth2Frac ( xorth,yorth,zorth, xfrac,yfrac,zfrac ); } bool CoorManager::Frac2Orth ( mat44 & F, mat44 & T ) { return cryst.Frac2Orth ( F,T ); } bool CoorManager::Orth2Frac ( mat44 & T, mat44 & F ) { return cryst.Orth2Frac ( T,F ); } // ------------------------ Contacts ------------------------------- #define CA_CA_Dist2 16.0 void CoorManager::FindSeqSection ( PAtom atom, int seqDist, int & seq1, int & seq2 ) { PAtom a; PResidue res; PChain chain; realtype x0,y0,z0, x,y,z, dx,dy,dz, d2; int i1; bool B0,B; x = 0.0; y = 0.0; z = 0.0; x0 = 0.0; y0 = 0.0; z0 = 0.0; res = atom->residue; if ((!res) || (seqDist<=0)) { seq1 = MaxInt4; seq2 = MinInt4; return; } chain = res->chain; if (!chain) { seq1 = MaxInt4; seq2 = MinInt4; return; } if (seqDist==1) { seq1 = res->index; seq2 = seq1; return; } a = res->GetAtom ( pstr("CA"),pstr("C"),NULL ); if (a) { x0 = a->x; y0 = a->y; z0 = a->z; B0 = true; } else B0 = false; if (B0) { x = x0; y = y0; z = z0; } B = B0; seq2 = res->index; i1 = IMin(chain->nResidues,seq2+seqDist)-1; while (seq2residue[seq2]) { a = chain->residue[seq2]->GetAtom ( pstr("CA"),pstr("C"),NULL ); if (a && B) { dx = x-a->x; dy = y-a->y; dz = z-a->z; d2 = dx*dx + dy*dy + dz*dz; if (d2>CA_CA_Dist2) { seq2--; break; } } if (a) { x = a->x; y = a->y; z = a->z; B = true; } else B = false; } } if (B0) { x = x0; y = y0; z = z0; } B = B0; seq1 = res->index; i1 = IMax(0,seq1-seqDist+1); while (seq1>i1) { seq1--; if (chain->residue[seq1]) { a = chain->residue[seq1]->GetAtom ( pstr("CA"),pstr("C"),NULL ); if (a && B) { dx = x-a->x; dy = y-a->y; dz = z-a->z; d2 = dx*dx + dy*dy + dz*dz; if (d2>CA_CA_Dist2) { seq1++; break; } } if (a) { x = a->x; y = a->y; z = a->z; B = true; } else B = false; } } } bool CoorManager::iContact ( PAtom a1, PAtom a2, int seq1, int seq2, realtype dd, realtype d12, realtype d22, realtype & d2 ) { // seq1..seq2 is forbidden region for residue sequence numbers PResidue res1,res2; PChain chain1,chain2; realtype dx,dy,dz; if (a2->Ter) return false; dx = fabs(a2->x-a1->x); if (dx<=dd) { dy = fabs(a2->y-a1->y); if (dy<=dd) { dz = fabs(a2->z-a1->z); if (dz<=dd) { d2 = dx*dx + dy*dy + dz*dz; if ((d12<=d2) && (d2<=d22)) { if (seq1<=seq2) { res1 = a1->residue; res2 = a2->residue; if (res1 && res2) { chain1 = res1->chain; chain2 = res2->chain; if (chain1 && chain2) { if (!strcmp(chain1->chainID,chain2->chainID)) { if ((seq1<=res2->index) && (res2->index<=seq2)) return false; } } } } return true; } } } } return false; } bool CoorManager::iContact ( realtype x, realtype y, realtype z, PAtom a2, realtype dd, realtype d12, realtype d22, realtype & d2 ) { realtype dx,dy,dz; if (a2->Ter) return false; dx = fabs(a2->x-x); if (dx<=dd) { dy = fabs(a2->y-y); if (dy<=dd) { dz = fabs(a2->z-z); if (dz<=dd) { d2 = dx*dx + dy*dy + dz*dz; if ((d12<=d2) && (d2<=d22)) return true; } } } return false; } void CoorManager::SeekContacts ( PPAtom AIndex, int ilen, int atomNum, realtype dist1, realtype dist2, int seqDist, RPContact contact, int & ncontacts, int maxlen, long group ) { PContactIndex contactIndex; realtype d12,d22,d2; int i,seq1,seq2; if (!AIndex) return; if (dist2Ter) return; contactIndex = new ContactIndex ( contact,maxlen,ncontacts,ilen ); FindSeqSection ( AIndex[atomNum],seqDist,seq1,seq2 ); d12 = dist1*dist1; d22 = dist2*dist2; for (i=0;iAddContact ( atomNum,i,sqrt(d2),group ); } contactIndex->GetIndex ( contact,ncontacts ); delete contactIndex; } void CoorManager::SeekContacts ( PAtom A, PPAtom AIndex, int ilen, realtype dist1, realtype dist2, int seqDist, RPContact contact, int & ncontacts, int maxlen, long group ) { PContactIndex contactIndex; realtype d12,d22,d2; int i,seq1,seq2; if (!AIndex) return; if (dist2Ter) return; contactIndex = new ContactIndex ( contact,maxlen,ncontacts,ilen ); FindSeqSection ( A,seqDist,seq1,seq2 ); d12 = dist1*dist1; d22 = dist2*dist2; for (i=0;iAddContact ( -1,i,sqrt(d2),group ); } contactIndex->GetIndex ( contact,ncontacts ); delete contactIndex; } void CoorManager::SeekContacts ( PPAtom AIndex1, int ilen1, PPAtom AIndex2, int ilen2, realtype dist1, realtype dist2, int seqDist, RPContact contact, int & ncontacts, int maxlen, mat44 * TMatrix, long group, int bricking, bool doSqrt ) { // It is Ok to have NULL pointers in AIndex1 and AIndex2 PContactIndex contactIndex; PPAtom A1,A2; rvector sx0,sy0,sz0; rvector dx0,dy0,dz0; realtype d12,d22,d2, eps; int l1,l2, i,j, nx,ny,nz, dn; int ix1,ix2, iy1,iy2, iz1,iz2, ix,iy,iz; int seq1,seq2; PBrick B; bool swap,UnitT; if ((dist2x; sy0[i] = AIndex1[i]->y; sz0[i] = AIndex1[i]->z; } // Save original AIndex2 coordinates and modify the index GetVectorMemory ( dx0,ilen2,0 ); GetVectorMemory ( dy0,ilen2,0 ); GetVectorMemory ( dz0,ilen2,0 ); for (i=0;ix; dy0[i] = AIndex2[i]->y; dz0[i] = AIndex2[i]->z; AIndex2[i]->Transform ( *TMatrix ); } } } // choose A2 as the largest atom set convenient for // bricking (bricking on larger set is more efficient) if (bricking & BRICK_ON_1) { A1 = AIndex2; A2 = AIndex1; l1 = ilen2; l2 = ilen1; swap = true; } else if (bricking & BRICK_ON_2) { A1 = AIndex1; A2 = AIndex2; l1 = ilen1; l2 = ilen2; swap = false; } else if (ilen1<=ilen2) { A1 = AIndex1; A2 = AIndex2; l1 = ilen1; l2 = ilen2; swap = false; } else { A1 = AIndex2; A2 = AIndex1; l1 = ilen2; l2 = ilen1; swap = true; } d12 = dist1*dist1; d22 = dist2*dist2; if (((bricking & BRICK_READY)==0) || (!brick)) MakeBricks ( A2,l2,dist2*1.5 ); dn = mround(dist2/brick_size)+1; if (brick) for (i=0;iTer) { if (UnitT) { // No transformation -- AIndex1 and AIndex2 are unmodified. // Calculate the forbidden sequence region FindSeqSection ( A1[i],seqDist,seq1,seq2 ); // And the brick location GetBrickCoor ( A1[i],nx,ny,nz ); } else { // AIndex2 and AIndex1 are modified, but the sequence // distance does not apply to physically different chains // (meaning that transformation of A2 effectively makes // a different chain). Use unmodified atom coordinates // of 1st set for calculating the brick location. if (swap) GetBrickCoor ( A1[i],nx,ny,nz ); // A1 is AIndex2 else GetBrickCoor ( sx0[i],sy0[i],sz0[i],nx,ny,nz ); } if (nx>=0) { ix1 = IMax ( 0,nx-dn ); iy1 = IMax ( 0,ny-dn ); iz1 = IMax ( 0,nz-dn ); ix2 = IMin ( nbrick_x,nx+dn+1 ); iy2 = IMin ( nbrick_y,ny+dn+1 ); iz2 = IMin ( nbrick_z,nz+dn+1 ); if (UnitT) { // AIndex1 unmodified, use it for (ix=ix1;ixnAtoms;j++) if (B->atom[j]!=A1[i]) { if (iContact(A1[i],B->atom[j],seq1,seq2, dist2,d12,d22,d2)) { if (doSqrt) d2 = sqrt(d2); if (swap) contactIndex->AddContact ( B->id[j],i,d2,group ); else contactIndex->AddContact ( i,B->id[j],d2,group ); } } } } else if (swap) { // A1 stands for AIndex2, it is modified and we need to use // the modified coordinates for (ix=ix1;ixnAtoms;j++) if (iContact(A1[i]->x,A1[i]->y,A1[i]->z, B->atom[j], dist2,d12,d22,d2)) { if (doSqrt) d2 = sqrt(d2); contactIndex->AddContact ( B->id[j],i,d2,group ); } } } else { // A1 stands for AIndex1, it may be modified (if AIndex1 // and AIndex2 overlap) -- use its unmodified coordinates // instead. for (ix=ix1;ixnAtoms;j++) if (iContact(sx0[i],sy0[i],sz0[i], B->atom[j],dist2,d12,d22,d2)) { if (doSqrt) d2 = sqrt(d2); contactIndex->AddContact ( i,B->id[j],d2,group ); } } } } } } if (!UnitT) { // restore original coordinates for (i=0;ix = sx0[i]; AIndex1[i]->y = sy0[i]; AIndex1[i]->z = sz0[i]; } for (i=0;ix = dx0[i]; AIndex2[i]->y = dy0[i]; AIndex2[i]->z = dz0[i]; } FreeVectorMemory ( sx0,0 ); FreeVectorMemory ( sy0,0 ); FreeVectorMemory ( sz0,0 ); FreeVectorMemory ( dx0,0 ); FreeVectorMemory ( dy0,0 ); FreeVectorMemory ( dz0,0 ); } contactIndex->GetIndex ( contact,ncontacts ); delete contactIndex; } void CoorManager::SeekContacts ( PPAtom AIndex1, int ilen1, PPAtom AIndex2, int ilen2, realtype contDist, PContact contact, int & ncontacts, int bricking ) { // Simplified optimized for speed version: // - no NULL pointers and Ters in AIndex1 and AIndex2 // - no checks for identity atoms in AIndex1 and AIndex2 // - contact must be pre-allocated with at least ilen1*ilen2 elements // - contact returns square distances // - ncontacts is always reset PPAtom A1,A2; realtype contDist2, dx,dy,dz, d2; int l1,l2, i,j, nx,ny,nz, dn; int ix1,ix2, iy1,iy2, iz1,iz2, ix,iy,iz; PBrick B; bool swap; // choose A2 as the largest atom set convenient for // bricking (bricking on larger set is more efficient) if (bricking & BRICK_ON_1) { A1 = AIndex2; A2 = AIndex1; l1 = ilen2; l2 = ilen1; swap = true; } else if (bricking & BRICK_ON_2) { A1 = AIndex1; A2 = AIndex2; l1 = ilen1; l2 = ilen2; swap = false; } else if (ilen1<=ilen2) { A1 = AIndex1; A2 = AIndex2; l1 = ilen1; l2 = ilen2; swap = false; } else { A1 = AIndex2; A2 = AIndex1; l1 = ilen2; l2 = ilen1; swap = true; } contDist2 = contDist*contDist; if (((bricking & BRICK_READY)==0) || (!brick)) MakeBricks ( A2,l2,contDist*1.5 ); ncontacts = 0; if (!brick) return; dn = (int)floor(contDist/brick_size)+1; if (swap) { for (i=0;i=0) { ix1 = IMax ( 0,nx-dn ); iy1 = IMax ( 0,ny-dn ); iz1 = IMax ( 0,nz-dn ); ix2 = IMin ( nbrick_x,nx+dn+1 ); iy2 = IMin ( nbrick_y,ny+dn+1 ); iz2 = IMin ( nbrick_z,nz+dn+1 ); for (ix=ix1;ixnAtoms;j++) { dx = A1[i]->x - B->atom[j]->x; dy = A1[i]->y - B->atom[j]->y; dz = A1[i]->z - B->atom[j]->z; d2 = dx*dx + dy*dy + dz*dz; if (d2<=contDist2) { contact[ncontacts].id1 = B->id[j]; contact[ncontacts].id2 = i; contact[ncontacts].dist = d2; ncontacts++; } } } } } } else { for (i=0;i=0) { ix1 = IMax ( 0,nx-dn ); iy1 = IMax ( 0,ny-dn ); iz1 = IMax ( 0,nz-dn ); ix2 = IMin ( nbrick_x,nx+dn+1 ); iy2 = IMin ( nbrick_y,ny+dn+1 ); iz2 = IMin ( nbrick_z,nz+dn+1 ); for (ix=ix1;ixnAtoms;j++) { dx = A1[i]->x - B->atom[j]->x; dy = A1[i]->y - B->atom[j]->y; dz = A1[i]->z - B->atom[j]->z; d2 = dx*dx + dy*dy + dz*dz; if (d2<=contDist2) { contact[ncontacts].id1 = i; contact[ncontacts].id2 = B->id[j]; contact[ncontacts].dist = d2; ncontacts++; } } } } } } } void CoorManager::SeekContacts ( vect3 * xyz, int nxyz, realtype contDist, PContact contact, int & ncontacts ) { // Simplified optimized for speed and convenience version: // - bricking is pre-done // - contacting set of atoms is given as a bare vect3 (xyz) // coordinate vector // - no checks for identity atoms // - contact must be pre-allocated with at least ilen1*ilen2 // elements // - contact returns square distances // - ncontacts is always reset realtype contDist2, dx,dy,dz, d2; int i,j, nx,ny,nz, dn; int ix1,ix2, iy1,iy2, iz1,iz2, ix,iy,iz; PBrick B; contDist2 = contDist*contDist; ncontacts = 0; if (!brick) return; dn = (int)floor(contDist/brick_size)+1; for (i=0;i=0) { ix1 = IMax ( 0,nx-dn ); iy1 = IMax ( 0,ny-dn ); iz1 = IMax ( 0,nz-dn ); ix2 = IMin ( nbrick_x,nx+dn+1 ); iy2 = IMin ( nbrick_y,ny+dn+1 ); iz2 = IMin ( nbrick_z,nz+dn+1 ); for (ix=ix1;ixnAtoms;j++) { dx = xyz[i][0] - B->atom[j]->x; dy = xyz[i][1] - B->atom[j]->y; dz = xyz[i][2] - B->atom[j]->z; d2 = dx*dx + dy*dy + dz*dz; if (d2<=contDist2) { contact[ncontacts].id1 = B->id[j]; contact[ncontacts].id2 = i; contact[ncontacts].dist = d2; ncontacts++; } } } } } } void CoorManager::SeekContacts ( PPAtom AIndex1, int ilen1, PPAtom * AIndex2, ivector ilen2, int nStructures, realtype dist1, realtype dist2, PPMContact & contact, int bricking ) { // It is Ok to have NULL pointers in AIndex1 and AIndex2 PMBrick B; PAtom A; realtype d12,d22,d2; int dn, i,j,k, nx,ny,nz, ix1,iy1,iz1, ix2,iy2,iz2; int ix,iy,iz; if (dist2Ter) { contact[i] = new MContact(nStructures); contact[i]->contactID = i; // Calculate the brick location GetMBrickCoor ( A,nx,ny,nz ); if (nx>=0) { ix1 = IMax ( 0,nx-dn ); iy1 = IMax ( 0,ny-dn ); iz1 = IMax ( 0,nz-dn ); ix2 = IMin ( nmbrick_x,nx+dn+1 ); iy2 = IMin ( nmbrick_y,ny+dn+1 ); iz2 = IMin ( nmbrick_z,nz+dn+1 ); for (ix=ix1;ixnAtoms[j];k++) if (B->atom[j][k]!=A) { if (iContact(A,B->atom[j][k], MaxInt4,MinInt4, dist2,d12,d22,d2)) contact[i]->AddContact ( B->atom[j][k],j,B->id[j][k] ); } } } } } } else for (i=0;i ((PContact)data)[j].id1); lt = (((PContact)data)[i].id1 < ((PContact)data)[j].id1); break; case CNSORT_1DEC : gt = (((PContact)data)[j].id1 > ((PContact)data)[i].id1); lt = (((PContact)data)[j].id1 < ((PContact)data)[i].id1); break; case CNSORT_2INC : gt = (((PContact)data)[i].id2 > ((PContact)data)[j].id2); lt = (((PContact)data)[i].id2 < ((PContact)data)[j].id2); break; case CNSORT_2DEC : gt = (((PContact)data)[j].id2 > ((PContact)data)[i].id2); lt = (((PContact)data)[j].id2 < ((PContact)data)[i].id2); break; case CNSORT_DINC : gt = (((PContact)data)[i].dist > ((PContact)data)[j].dist); lt = (((PContact)data)[i].dist < ((PContact)data)[j].dist); break; case CNSORT_DDEC : gt = (((PContact)data)[j].dist > ((PContact)data)[i].dist); lt = (((PContact)data)[j].dist < ((PContact)data)[i].dist); break; } if (gt) return 1; if (lt) return -1; return 0; } void QSortContacts::Swap ( int i, int j ) { ((PContact)data)[i].Swap ( ((PContact)data)[j] ); } void QSortContacts::Sort ( PContact contact, int ncontacts, int sortmode ) { mode = sortmode; if (mode!=CNSORT_OFF) QuickSort::Sort ( &(contact[0]),ncontacts ); } void SortContacts ( PContact contact, int ncontacts, CNSORT_DIR sortmode ) { QSortContacts SC; if (sortmode!=CNSORT_OFF) SC.Sort ( contact,ncontacts,sortmode ); } // ------------------- Stream functions ---------------------- void CoorManager::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); Root::write ( f ); if (!isCompactBinary()) { f.WriteInt ( &CoorIDCode ); f.WriteReal ( &brick_size ); f.WriteReal ( &xbrick_0 ); f.WriteReal ( &ybrick_0 ); f.WriteReal ( &zbrick_0 ); f.WriteInt ( &nbrick_x ); f.WriteInt ( &nbrick_y ); f.WriteInt ( &nbrick_z ); } } void CoorManager::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); Root::read ( f ); if (!isCompactBinary()) { f.ReadInt ( &CoorIDCode ); f.ReadReal ( &brick_size ); f.ReadReal ( &xbrick_0 ); f.ReadReal ( &ybrick_0 ); f.ReadReal ( &zbrick_0 ); f.ReadInt ( &nbrick_x ); f.ReadInt ( &nbrick_y ); f.ReadInt ( &nbrick_z ); } } MakeStreamFunctions(CoorManager); // =================================================================== int SuperposeAtoms ( mat44 & T, PPAtom A1, int nA, PPAtom A2, ivector C ) { realtype xc1,yc1,zc1, xc2,yc2,zc2, det,B; rmatrix A,U,V; rvector W,RV1; vect3 vc1,vc2; int i,j,k,i1,i2,nat; // 1. Set unit matrix as "default" return for (i=0;i<4;i++) { for (j=0;j<4;j++) T[i][j] = 0.0; T[i][i] = 1.0; } // 2. Calculate mass centers xc1 = 0.0; yc1 = 0.0; zc1 = 0.0; xc2 = 0.0; yc2 = 0.0; zc2 = 0.0; nat = 0; if (C) { for (i1=0;i1Ter) { i2 = C[i1]; if (i2>=0) { xc1 += A1[i1]->x; yc1 += A1[i1]->y; zc1 += A1[i1]->z; xc2 += A2[i2]->x; yc2 += A2[i2]->y; zc2 += A2[i2]->z; nat++; } } } else { for (i=0;iTer) && (!A2[i]->Ter)) { xc1 += A1[i]->x; yc1 += A1[i]->y; zc1 += A1[i]->z; xc2 += A2[i]->x; yc2 += A2[i]->y; zc2 += A2[i]->z; nat++; } } if (nat>1) { xc1 /= nat; yc1 /= nat; zc1 /= nat; xc2 /= nat; yc2 /= nat; zc2 /= nat; } else if (nat>0) { T[0][3] = xc2 - xc1; T[1][3] = yc2 - yc1; T[2][3] = zc2 - zc1; return SPOSEAT_Ok; } else return SPOSEAT_NoAtoms; // 3. Calculate the correlation matrix GetMatrixMemory ( A,3,3,1,1 ); for (i=1;i<=3;i++) for (j=1;j<=3;j++) A[i][j] = 0.0; if (C) { for (i1=0;i1Ter) { i2 = C[i1]; if (i2>=0) { vc1[0] = A1[i1]->x - xc1; vc1[1] = A1[i1]->y - yc1; vc1[2] = A1[i1]->z - zc1; vc2[0] = A2[i2]->x - xc2; vc2[1] = A2[i2]->y - yc2; vc2[2] = A2[i2]->z - zc2; for (i=1;i<=3;i++) for (j=1;j<=3;j++) A[i][j] += vc1[j-1]*vc2[i-1]; } } } else { for (k=0;kTer) && (!A2[k]->Ter)) { vc1[0] = A1[k]->x - xc1; vc1[1] = A1[k]->y - yc1; vc1[2] = A1[k]->z - zc1; vc2[0] = A2[k]->x - xc2; vc2[1] = A2[k]->y - yc2; vc2[2] = A2[k]->z - zc2; for (i=1;i<=3;i++) for (j=1;j<=3;j++) A[i][j] += vc1[j-1]*vc2[i-1]; } } // 4. Calculate transformation matrix (to be applied to A1) det = A[1][1]*A[2][2]*A[3][3] + A[1][2]*A[2][3]*A[3][1] + A[2][1]*A[3][2]*A[1][3] - A[1][3]*A[2][2]*A[3][1] - A[1][1]*A[2][3]*A[3][2] - A[3][3]*A[1][2]*A[2][1]; // 4.1 SV-decompose the correlation matrix GetMatrixMemory ( U ,3,3,1,1 ); GetMatrixMemory ( V ,3,3,1,1 ); GetVectorMemory ( W ,3,1 ); GetVectorMemory ( RV1,3,1 ); math::SVD ( 3,3,3,A,U,V,W,RV1,true,true,i ); if (i!=0) { FreeVectorMemory ( RV1,1 ); FreeVectorMemory ( W ,1 ); FreeMatrixMemory ( V ,3,1,1 ); FreeMatrixMemory ( U ,3,1,1 ); FreeMatrixMemory ( A ,3,1,1 ); return SPOSEAT_SVD_Fail; } // 4.2 Check for parasite inversion and fix it if found if (det<=0.0) { k = 0; B = MaxReal; for (j=1;j<=3;j++) if (W[j]x - A[1]->x; U[1] = A[0]->y - A[1]->y; U[2] = A[0]->z - A[1]->z; W[0] = A[2]->x - A[1]->x; W[1] = A[2]->y - A[1]->y; W[2] = A[2]->z - A[1]->z; V[0] = A[3]->x - A[2]->x; V[1] = A[3]->y - A[2]->y; V[2] = A[3]->z - A[2]->z; a[0] = U[1]*W[2] - W[1]*U[2]; a[1] = U[2]*W[0] - W[2]*U[0]; a[2] = U[0]*W[1] - W[0]*U[1]; b[0] = V[1]*W[2] - W[1]*V[2]; b[1] = V[2]*W[0] - W[2]*V[0]; b[2] = V[0]*W[1] - W[0]*V[1]; c[0] = a[1]*b[2] - b[1]*a[2]; c[1] = a[2]*b[0] - b[2]*a[0]; c[2] = a[0]*b[1] - b[0]*a[1]; Wmag = sqrt(W[0]*W[0]+W[1]*W[1]+W[2]*W[2]); S = c[0]*W[0] + c[1]*W[1] + c[2]*W[2]; T = a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; T *= Wmag; if ((S==0.0) && (T==0.0)) return NO_TORSION; else return atan2(S,T); } realtype getPsi ( PPAtom A ) { vect3 v1,v2; realtype l1,l2; v1[0] = A[0]->x - A[1]->x; v1[1] = A[0]->y - A[1]->y; v1[2] = A[0]->z - A[1]->z; v2[0] = A[2]->x - A[1]->x; v2[1] = A[2]->y - A[1]->y; v2[2] = A[2]->z - A[1]->z; l1 = v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]; if (l1==0.0) l1 = 1.0; l2 = v2[0]*v2[0] + v2[1]*v2[1] + v2[2]*v2[2]; if (l2==0.0) l2 = 1.0; return acos((v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])/sqrt(l1*l2)); } const realtype NO_TORSION = -MaxReal; } // namespace mmdb mmdb2-2.0.5/mmdb2/mmdb_math_rand.h0000664000175000017500000000456212401105774013560 00000000000000// $Id: mmdb_math_rand.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : Rand // ~~~~~~~~~ // **** Classes : RandomNumber ( random number generator ) // ~~~~~~~~~ // // (C) E. Krissinel 1997-2013 // // ================================================================= // #ifndef __MMDB_MATH_Rand__ #define __MMDB_MATH_Rand__ #include "mmdb_io_file.h" namespace mmdb { namespace math { // ------------------------------------------------------------- enum RN_MAX_SEED { _RN_MAX_IJ = 31328, _RN_MAX_KL = 30081 }; DefineClass(RandomNumber); class RandomNumber { public : RandomNumber ( long IJ=0, long KL=0 ); void Init ( long IJ=0, long KL=0 ); realtype gauss_rnd(); //!< Gaussian random numbers realtype random (); //!< Uniform [0..1] random number generator realtype srandom (); //!< Uniform [-1..1] random number generator void read ( io::RFile f ); void write ( io::RFile f ); protected : long I97,J97; realtype U[97],C,CD,CM; realtype gset; long iset; }; } // namespace math } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_coormngr.h0000664000175000017500000012632412601171753013454 00000000000000// $Id: mmdb_coormngr.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 07.09.15 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : mmdb_coormngr // ~~~~~~~~~ // Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::Brick ( space brick ) // ~~~~~~~~~ mmdb::CoorManager ( MMDB atom coordinate manager ) // // (C) E. Krissinel 2000-2015 // // ================================================================= // #ifndef __MMDB_CoorMngr__ #define __MMDB_CoorMngr__ #include "mmdb_root.h" namespace mmdb { // =========================== Brick ============================== // bricking control enum BRICK_STATE { BRICK_ON_1 = 0x00000001, BRICK_ON_2 = 0x00000002, BRICK_READY = 0x00000004 }; DefineClass(Brick); typedef PPBrick * PPPBrick; class Brick { public : int nAtoms; // number of atoms hit into brick PPAtom atom; // pointers to atoms ivector id; // atom ids (in present realization, these are // indices of atoms from the bricked array) Brick (); ~Brick(); void Clear (); void AddAtom ( PAtom A, int atomid ); protected : int nAllocAtoms; void InitBrick(); }; // =========================== MBrick ============================= // Bricking multiple structures DefineClass(MBrick); typedef PPMBrick * PPPMBrick; class MBrick { public : ivector nAtoms; // number of atoms in the brick PPAtom *atom; // pointers to atoms imatrix id; // atom ids (in present realization, these are // indices of atoms from the bricked array) MBrick ( int nStructures ); ~MBrick(); void Clear (); void AddAtom ( PAtom A, int structNo, int atomid ); protected : ivector nAlloAtoms; int nStruct; void InitMBrick ( int nStructures ); }; // ==================== GenSym ======================== DefineClass(GenSym); DefineStreamFunctions(GenSym); class GenSym : public SymOps { friend class CoorManager; public : GenSym (); GenSym ( io::RPStream Object ); ~GenSym(); void FreeMemory(); int AddSymOp ( cpstr XYZOperation ); // the number of just added operation may be obtained as // Nop = GenSym::GetNofSymOps()-1 . int AddRenChain ( int Nop, const ChainID ch1, const ChainID ch2 ); void Copy ( PSymOps genSym ); void write ( io::RFile f ); void read ( io::RFile f ); protected : PChainID * chID1; // pairs of chains to rename from chID1[n][i] PChainID * chID2; // to chID2[n][i] for each operation n1, all atoms belonging // to residues closer than // +/-(seqDist-1) around that of // atom AIndex[atomNum], are // neglected. If chain is broken // (has a gap) on section // [-(seqDist-1)..seqDist-1], the // section of neglection is // shortened to that gap. RPContact contact, // indices of contacting atoms // [0..ncontacts-1]. contact[i].id1 // is set to atomNum and // contact[i].id2 is set to the // index of 2nd contacting atom // in vector AIndex int & ncontacts, // number of contacts found. If // ncontacts>0 on input, it is // assumed that new contacts that // newly found contacts should be // appended to those already // existing int maxlen=0, // if <=0, then vector contact is // allocated dynamically. If // contact!=NULL, then it is // appended with new contacts. // The application is responsible // for deallocation of contact // after use. // If maxlen>0 then vector contact // is prohibited of dynamical // allocation/deallocation. In this // case, not more than maxlen // contacts will be returned. long group=0 // a contact group ID, which will be // simply stored in contact[i].group // fields. This ID may be useful // if contacts are obtained in // multiple calls of the function ); void SeekContacts ( PAtom A, // 1st atom in contact PPAtom AIndex, // index of atoms [0..ilen-1] to // check for contact with 1st atom int ilen, // length of index realtype dist1, // minimal contact distance realtype dist2, // maximal contact distance int seqDist, // the sequence distance to neglect. // If seqDist==0, all atoms are // checked for contact. If // seqDist==1, the atoms belonging // to the same residue as atom // A, are neglected. If seqDist>1, // all atoms belonging to residues // closer than +/-(seqDist-1) around // that of atom A, are neglected. If // chain is broken (has a gap) on // section // [-(seqDist-1)..seqDist-1], the // section of neglection is // shortened to that gap. RPContact contact, // indices of contacting atoms // [0..ncontacts-1]. contact[i].id1 // is set to -1, and contact[i].id2 // is set to the index of 2nd // contacting atom in vector AIndex int & ncontacts, // number of contacts found. If // ncontacts>0 on input, it is // assumed that new contacts that // newly found contacts should be // appended those already existing int maxlen=0, // if <=0, then vector contact is // allocated dynamically. If // contact!=NULL, then it is // appended with new contacts. // The application is responsible // for deallocation of contact // after use. // If maxlen>0 then vector contact // is prohibited of dynamical // allocation/deallocation. In this // case, not more than maxlen // contacts will be returned. long group=0 // a contact group ID, which will be // simply stored in contact[i].group // fields. This ID may be useful // if contacts are obtained in // multiple calls of the function ); void SeekContacts ( PPAtom AIndex1, // 1st atom index [0..ilen1-1] int ilen1, // length of 1st index PPAtom AIndex2, // 2nd atom index [0..ilen2-1] to // check for contact with 1st index int ilen2, // length of 2nd index realtype dist1, // minimal contact distance realtype dist2, // maximal contact distance int seqDist, // the sequence distance to // neglect. // If seqDist==0, all atoms are // checked for contact. // If seqDist==1, the atoms // belonging to the same residue // are neglected. // If seqDist>1, all atoms // belonging to residues closer than // +/-(seqDist-1) to each other, // are neglected. If chain is broken // (has a gap) on section // [-(seqDist-1)..seqDist-1], the // section of neglection is // shortened to that gap. RPContact contact, // indices of contacting atoms // [0..ncontacts-1]. contact[i].id1 // contains number of atom from 1st // index, and contact[i].id2 // contains number of atom from 2nd // index, contacting with the former // one int & ncontacts, // number of contacts found. If // ncontacts>0 on input, it is // assumed that newly found // contacts should be appended to // those already existing int maxlen=0, // if <=0, then vector contact is // allocated dynamically. If // contact!=NULL, then it is // appended with new contacts. // The application is responsible // for deallocation of contact // after use. // If maxlen>0 then vector contact // is prohibited of dynamical // allocation/deallocation. In this // case, not more than maxlen // contacts will be returned. mat44 * TMatrix=NULL, // transformation matrix for 2nd // set of atoms (AIndex2) long group=0, // a contact group ID, which will // be stored in contact[i].group // fields. This ID may be useful // if contacts are obtained in // multiple calls of the function int bricking=0, // bricking control; may be a // combination of BRICK_ON_1 or // BRICK_ON_2 with BRICK_READY bool doSqrt=true // if False, then Contact contains // square distances ); // Simplified optimized for speed version: // - no NULL pointers and Ters in AIndex1 and AIndex2 // - no checks for identity atoms in AIndex1 and AIndex2 // - contact must be pre-allocated with at least ilen1*ilen2 // elements // - contact returns square distances // - ncontacts is always reset void SeekContacts ( PPAtom AIndex1, // 1st atom index [0..ilen1-1] int ilen1, // length of 1st index PPAtom AIndex2, // 2nd atom index [0..ilen2-1] to // check for contact with 1st index int ilen2, // length of 2nd index realtype contDist, // maximal contact distance PContact contact, // indices of contacting atoms // [0..ncontacts-1]. contact[i].id1 // contains number of atom from 1st // index, and contact[i].id2 // contains number of atom from 2nd // index, contacting with the former // one. Must be pre-allocated int & ncontacts, // number of contacts found int bricking=0 // bricking control; may be a // combination of BRICK_ON_1 or // BRICK_ON_2 with BRICK_READY ); // Simplified optimized for speed and convenience version: // - bricking is pre-done // - contacting set of atoms is given as a bare vect3 (xyz) // coordinate vector // - no checks for identity atoms // - contact must be pre-allocated with at least ilen1*ilen2 // elements // - contact returns square distances // - ncontacts is always reset void SeekContacts ( vect3 * xyz, // 2nd atom index [0..ilen2-1] to // check for contact with 1st index // which was used for bricking int nxyz, // length of 2nd index realtype contDist, // maximal contact distance PContact contact, // indices of contacting atoms // [0..ncontacts-1]. contact[i].id1 // contains number of atom from 1st // index, and contact[i].id2 // contains number of atom from 2nd // index, contacting with the former // one. Must be pre-allocated int & ncontacts // number of contacts found ); void SeekContacts ( PPAtom AIndex1, // 1st atom index [0..ilen1-1] int ilen1, // length of 1st index PPAtom * AIndex2, // indexes of atoms to be checked // for contact with each atom from // Aindex1; dimension // [0..nStructures-1][0..ilen2[i]-1] ivector ilen2, // lengths of indexes AIndex2 int nStructures, // number of indexes AIndex2 realtype dist1, // minimal contact distance realtype dist2, // maximal contact distance PPMContact & contact, // resulting contacts, one structure // per each position in AIndex1. If // AIndex1[i] is NULL, contact[i] is // also NULL. "contact" is always // allocated, no re-use or // re-allocation is attempted. int bricking=0 // bricking control; may be // BRICK_READY if AIndex2 does not // change ); protected : // bricks realtype brick_size, xbrick_0,ybrick_0,zbrick_0; int nbrick_x,nbrick_y,nbrick_z; PPPBrick * brick; realtype mbrick_size, xmbrick_0,ymbrick_0,zmbrick_0; int nmbrick_x,nmbrick_y,nmbrick_z; PPPMBrick * mbrick; // --------------- Stream I/O ----------------------------- void write ( io::RFile f ); void read ( io::RFile f ); void InitMMDBCoorManager(); void ApplySymTransform ( int SymMatrixNo, PGenSym genSym=NULL ); void ResetManager (); void FindSeqSection ( PAtom atom, int seqDist, int & seq1, int & seq2 ); bool iContact ( PAtom a1, PAtom a2, int seq1, int seq2, realtype dd, realtype d12, realtype d22, realtype & d2 ); bool iContact ( realtype x, realtype y, realtype z, PAtom a2, realtype dd, realtype d12, realtype d22, realtype & d2 ); }; // =================================================================== // GetEulerRotMatrix(..) calculates the Euler rotation matrix // for rotation: // 1) about z-axis by angle alpha // 2) about new y-axis by angle beta // 3) about new z-axis by angle gamma extern void GetEulerRotMatrix ( mat33 & erm, realtype alpha, realtype beta, realtype gamma ); // GetEulerTMatrix(..) calculates the Euler rotation-translation // matrix for rotation: // 1) about z-axis by angle alpha // 2) about new y-axis by angle beta // 3) about new z-axis by angle gamma // Point (x0,y0,z0) is the center of rotation. extern void GetEulerTMatrix ( mat44 & erm, realtype alpha, realtype beta, realtype gamma, realtype x0, realtype y0, realtype z0 ); // Euler rotation: 1) about z-axis by angle alpha // 2) about new y-axis by angle beta // 3) about new z-axis by angle gamma // Point (x0,y0,z0) is the center of rotation. extern void EulerRotation ( PPAtom A, int nA, realtype alpha, realtype beta, realtype gamma, realtype x0, realtype y0, realtype z0 ); // GetVecRotMatrix(..) calculates the rotation matrix for // rotation by angle alpha about arbitrary vector directed // as (vx,vy,vz) = (vx2-vx1,vy2-vy1,vz2-vz1). extern void GetVecRotMatrix ( mat33 & vrm, realtype alpha, realtype vx, realtype vy, realtype vz ); // Given the rotation matrix vrm, GetRotParameters(..) // returns the rotation angle alpha and the normalized // rotation axis vector (vx,vy,vz). // The rotation angle and vector are determined up to // their sign (however correlated, so that being substituted // into GetVecRotMatrix(..) they yield the same rotation // matrix). // The function does not check for vrm to be a valid // rotation matrix. extern void GetRotParameters ( mat33 & vrm, realtype & alpha, realtype & vx, realtype & vy, realtype & vz ); // GetVecTMatrix(..) calculates the rotation-translation matrix // for rotation by angle alpha about arbitrary vector directed as // (vx,vy,vz) = (vx2-vx1,vy2-vy1,vz2-vz1). Point (x0,y0,z0) is // the center of rotation -- actually a point belonging to the // rotation axis. extern void GetVecTMatrix ( mat44 & vrm, realtype alpha, realtype vx, realtype vy, realtype vz, realtype x0, realtype y0, realtype z0 ); // Vector rotation is rotation by angle alpha about arbitrary // vector directed as (vx,vy,vz) = (vx2-vx1,vy2-vy1,vz2-vz1). // Point (x0,y0,z0) is the center of rotation -- actually // a point belonging to the rotation axis. extern void VectorRotation ( PPAtom A, int nA, realtype alpha, realtype vx, realtype vy, realtype vz, realtype x0, realtype y0, realtype z0 ); extern void GetMassCenter ( PPAtom A, int nA, realtype & xmc, realtype & ymc, realtype & zmc ); enum SPOSEAT_RC { SPOSEAT_Ok = 0, SPOSEAT_NoAtoms = 1, SPOSEAT_SVD_Fail = 2 }; // Given two sets of atoms, A1 and A2, SuperposeAtoms(...) calculates // the rotational-translational matrix T such that |T*A1 - A2| is // minimal in least-square terms. // If vector C is not given (default), all nA atoms of set A1 are // considered as corresponding to nA first atoms of set A2, // A1[i] <-> A2[i], 0<=i A2[C[i]] only for those i that C[i]>=0. // The default option (C==NULL) is thus identical to C[i]==i, 0<=i // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // // **** Classes : mmdb::ContainerClass ( containered class template ) // ~~~~~~~~~ mmdb::ContString ( containered string ) // mmdb::ClassContainer ( container of classes ) // mmdb::AtomPath ( atom path ID ) // mmdb::QuickSort ( quick sort of integers ) // // **** Functions : Date9to11 ( DD-MMM-YY -> DD-MMM-YYYY ) // ~~~~~~~~~~~ Date11to9 ( DD-MMM-YYYY -> DD-MMM-YY ) // Date9toCIF ( DD-MMM-YY -> YYYY-MM-DD ) // Date11toCIF( DD-MMM-YYYY -> YYYY-MM-DD ) // DateCIFto9 ( YYYY-MM-DD -> DD-MMM-YY ) // DateCIFto11( YYYY-MM-DD -> DD-MMM-YYYY ) // GetInteger ( reads integer from a string ) // GetReal ( reads real from a string ) // GetIntIns ( reads integer and insert code ) // PutInteger ( writes integer into a string ) // PutRealF ( writes real in F-form into a string ) // PutIntIns ( writes integer and insert code ) // CIFGetInteger ( reads and deletes int from CIF ) // CIFGetReal ( reads and deletes real from CIF ) // CIFGetString ( reads and deletes string from CIF) // CIFGetInteger1 (reads and del-s int from CIF loop) // CIFGetReal1 (reads and del-s int from CIF loop) // Mat4Inverse ( inversion of 4x4 matrices ) // GetErrorDescription (ascii line to an Error_XXXXX) // ParseAtomID ( parses atom ID line ) // ParseResID ( parses residue ID line ) // ParseAtomPath ( parses full atom path ) // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include #include #include "mmdb_utils.h" #include "hybrid_36.h" namespace mmdb { // ====================== Date functions ======================= static cpstr Month[12] = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" }; static cpstr nMonth[12] = { "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12" }; void Date9to11 ( cpstr Date9, pstr Date11 ) { // converts DD-MMM-YY to DD-MMM-YYYY int i; i = 0; while ((i<12) && (strncmp(Month[i],&(Date9[3]),3))) i++; if (i<12) { // DD-MMM-YY -> DD-MMM-YYYY strncpy ( Date11,Date9,7 ); if (Date9[7]!='0') strncpy ( &(Date11[7]),"19",2 ); else strncpy ( &(Date11[7]),"20",2 ); strncpy ( &(Date11[9]),&(Date9[7]),2 ); Date11[2] = '-'; Date11[6] = '-'; Date11[11] = char(0); } else { // DD-MM-YY -> DD-MMM-YYYY strncpy ( Date11,Date9,3 ); i = 0; while ((i<12) && (strncmp(nMonth[i],&(Date9[3]),2))) i++; if (i<12) { strncpy ( &(Date11[3]),Month[i],3 ); if (Date9[6]!='0') strncpy ( &(Date11[7]),"19",2 ); else strncpy ( &(Date11[7]),"20",2 ); strncpy ( &(Date11[9]),&(Date9[6]),2 ); Date11[2] = '-'; Date11[6] = '-'; Date11[11] = char(0); } else strcpy ( Date11," " ); } } void Date11to9 ( cpstr Date11, pstr Date9 ) { // converts DD-MMM-YYYY to DD-MMM-YY int i; i = 0; while ((i<12) && (strncmp(Month[i],&(Date11[3]),3))) i++; if (i<12) { // DD-MMM-YYYY -> DD-MMM-YY strncpy ( Date9,Date11,7 ); strncpy ( &(Date9[7]),&(Date11[9]),2 ); Date9[2] = '-'; Date9[6] = '-'; } else { // DD-MM-YYYY -> DD-MMM-YY strncpy ( Date9,Date11,3 ); i = 0; while ((i<12) && (strncmp(nMonth[i],&(Date11[3]),2))) i++; if (i<12) { strncpy ( &(Date9[3]),Month[i],3 ); strncpy ( &(Date9[7]),&(Date11[8]),2 ); Date9[2] = '-'; Date9[6] = '-'; } else strcpy ( Date9," " ); } } void Date9toCIF ( cpstr Date9, pstr DateCIF ) { // DD-MMM-YY -> YYYY-MM-DD ) int i; i = 0; while ((i<12) && (strncmp(Month[i],&(Date9[3]),3))) i++; if (i<12) { // DD-MMM-YY -> YYYY-MM-DD if (Date9[7]!='0') strcpy ( DateCIF,"19" ); else strcpy ( DateCIF,"20" ); strncpy ( &(DateCIF[2]),&(Date9[7]),2 ); strncpy ( &(DateCIF[5]),nMonth[i],2 ); } else { // DD-MM-YY -> YYYY-MM-DD if (Date9[6]!='0') strcpy ( DateCIF,"19" ); else strcpy ( DateCIF,"20" ); strncpy ( &(DateCIF[2]),&(Date9[6]),2 ); strncpy ( &(DateCIF[5]),&(Date9[3]),2 ); } DateCIF[4] = '-'; DateCIF[7] = '-'; strncpy ( &(DateCIF[8]),Date9,2 ); DateCIF[10] = char(0); } void Date11toCIF ( cpstr Date11, pstr DateCIF ) { // DD-MMM-YYYY -> YYYY-MM-DD int i; i = 0; while ((i<12) && (strncmp(Month[i],&(Date11[3]),3))) i++; if (i<12) { strncpy ( DateCIF,&(Date11[7]),4 ); strncpy ( &(DateCIF[5]),nMonth[i],2 ); } else { strncpy ( DateCIF,&(Date11[6]),4 ); strncpy ( &(DateCIF[5]),&(Date11[3]),2 ); } DateCIF[4] = '-'; DateCIF[7] = '-'; strncpy ( &(DateCIF[8]),Date11,2 ); DateCIF[10] = char(0); } void DateCIFto9 ( cpstr DateCIF, pstr Date9 ) { // YYYY-MM-DD -> DD-MMM-YY int i; strncpy ( Date9,&(DateCIF[8]),2 ); Date9[2] = '-'; i = 0; while ((i<12) && (strncmp(nMonth[i],&(DateCIF[5]),2))) i++; if (i<12) strncpy ( &(Date9[3]),Month[i],3 ); else { strncpy ( &(Date9[3]),&(DateCIF[5]),2 ); Date9[5] = 'X'; } Date9[6] = '-'; strncpy ( &(Date9[7]),&(DateCIF[2]),2 ); // DateCIF[9] = char(0); } void DateCIFto11 ( cpstr DateCIF, pstr Date11 ) { // YYYY-MM-DD -> DD-MMM-YYYY int i; strncpy ( Date11,&(DateCIF[8]),2 ); Date11[2] = '-'; i = 0; while ((i<12) && (strncmp(nMonth[i],&(DateCIF[5]),2))) i++; if (i<12) strncpy ( &(Date11[3]),Month[i],3 ); else { strncpy ( &(Date11[3]),&(DateCIF[5]),2 ); Date11[5] = 'X'; } Date11[6] = '-'; strncpy ( &(Date11[7]),DateCIF,4 ); // DateCIF[11] = char(0); } // =============== Format functions =================== bool GetInteger ( int & N, cpstr S, int M ) { // Returns true if S contains an integer number in its // first M characters. This number is returned in N. // The return is false if no integer number may be // recognized. In this case, N is assigned MinInt4 value. pstr endptr; char L[50]; strncpy ( L,S,M ); L[M] = char(0); N = mround(strtod(L,&endptr)); if ((N==0) && (endptr==L)) { N = MinInt4; // no number return false; } else return true; } bool GetReal ( realtype & R, cpstr S, int M ) { // Returns true if S contains a real number in its // first M characters. This number is returned in R. // The return is false if no real number may be // recognized. In this case, R is assigned -MaxReal value. pstr endptr; char L[50]; strncpy ( L,S,M ); L[M] = char(0); R = strtod(L,&endptr); if ((R==0.0) && (endptr==L)) { R = -MaxReal; // no number return false; } else return true; } bool GetIntIns ( int & N, pstr ins, cpstr S, int M ) { // Returns true if S contains an integer number in its // first M characters. This number is returned in N. In addition // to that, GetIntIns() retrieves the insertion code which may // follow the integer and returns it in "ins" (1 character + // terminating 0). // The return is false if no integer number may be // recognized. In this case, N is assigned MinInt4 value, // "ins" just returns (M+1)th symbol of S (+terminating 0). pstr endptr; char L[50]; if (S[M]!=' ') { ins[0] = S[M]; ins[1] = char(0); } else ins[0] = char(0); strncpy ( L,S,M ); L[M] = char(0); if ((M==4) && ((S[0]>='A') || ((S[0]=='-') && (S[1]>='A')))) hy36decode ( M,L,M,&N); else { endptr = NULL; N = mround(strtod(L,&endptr)); if ((N==0) && (endptr==L)) { N = MinInt4; // no number return false; } } return true; } void PutInteger ( pstr S, int N, int M ) { // Integer N is converted into ASCII string of length M // and pasted onto first M characters of string S. No // terminating zero is added. // If N is set to MinInt4, then first M characters of // string S are set to the space character. char L[50]; int i; if (N==MinInt4) for (i=0;iGetInteger ( I,Tag,Signal,true ); if (RC==mmcif::CIFRC_WrongFormat) { F = Loop->GetString ( Tag,Signal,RC ); if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", Loop->GetCategoryName(),Tag,Signal,F ); else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", Loop->GetCategoryName(),Tag,Signal ); Signal = -Error_UnrecognizedInteger-1; return Error_UnrecognizedInteger; } if (RC==mmcif::CIFRC_WrongIndex) { Signal = -1; return Error_NoData; } if (RC) { F = Loop->GetString ( Tag,Signal,RC ); if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", Loop->GetCategoryName(),Tag,Signal,F ); else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", Loop->GetCategoryName(),Tag,Signal ); Signal = -Error_NoData-1; return Error_NoData; } return Error_NoError; } ERROR_CODE CIFGetInteger1 ( int & I, mmcif::PLoop Loop, cpstr Tag, int nrow ) { pstr F; int RC; RC = Loop->GetInteger ( I,Tag,nrow,true ); if (RC==mmcif::CIFRC_WrongFormat) { F = Loop->GetString ( Tag,nrow,RC ); if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", Loop->GetCategoryName(),Tag,nrow,F ); else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", Loop->GetCategoryName(),Tag,nrow ); return Error_UnrecognizedInteger; } if (RC==mmcif::CIFRC_WrongIndex) return Error_NoData; if (RC) { F = Loop->GetString ( Tag,nrow,RC ); if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", Loop->GetCategoryName(),Tag,nrow,F ); else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", Loop->GetCategoryName(),Tag,nrow ); return Error_NoData; } return Error_NoError; } ERROR_CODE CIFGetReal ( realtype & R, mmcif::PLoop Loop, cpstr Tag, int & Signal ) { pstr F; int RC; RC = Loop->GetReal ( R,Tag,Signal,true ); if (RC==mmcif::CIFRC_WrongFormat) { F = Loop->GetString ( Tag,Signal,RC ); if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", Loop->GetCategoryName(),Tag,Signal,F ); else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", Loop->GetCategoryName(),Tag,Signal ); Signal = -Error_UnrecognizedReal-1; return Error_UnrecognizedReal; } if (RC==mmcif::CIFRC_WrongIndex) { Signal = -1; return Error_NoData; } if (RC) { F = Loop->GetString ( Tag,Signal,RC ); if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", Loop->GetCategoryName(),Tag,Signal,F ); else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", Loop->GetCategoryName(),Tag,Signal ); Signal = -Error_NoData-1; return Error_NoData; } return Error_NoError; } ERROR_CODE CIFGetReal1 ( realtype & R, mmcif::PLoop Loop, cpstr Tag, int nrow ) { pstr F; int RC; RC = Loop->GetReal ( R,Tag,nrow,true ); if (RC==mmcif::CIFRC_WrongFormat) { F = Loop->GetString ( Tag,nrow,RC ); if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", Loop->GetCategoryName(),Tag,nrow,F ); else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", Loop->GetCategoryName(),Tag,nrow ); return Error_UnrecognizedReal; } if (RC==mmcif::CIFRC_WrongIndex) return Error_NoData; if (RC) { F = Loop->GetString ( Tag,nrow,RC ); if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", Loop->GetCategoryName(),Tag,nrow,F ); else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", Loop->GetCategoryName(),Tag,nrow ); return Error_NoData; } return Error_NoError; } ERROR_CODE CIFGetString ( pstr S, mmcif::PLoop Loop, cpstr Tag, int row, int SLen, cpstr DefS ) { pstr F; int RC; F = Loop->GetString ( Tag,row,RC ); if ((!RC) && F) { strncpy ( S,F,SLen-1 ); Loop->DeleteField ( Tag,row ); return Error_NoError; } else { strcpy ( S,DefS ); return Error_EmptyCIFLoop; } } ERROR_CODE CIFGetInteger ( int & I, mmcif::PStruct Struct, cpstr Tag, bool Remove ) { pstr F; int RC; RC = Struct->GetInteger ( I,Tag,Remove ); if (RC==mmcif::CIFRC_WrongFormat) { F = Struct->GetString ( Tag,RC ); if (F) sprintf ( CIFErrorLocation,"structure %s.%s data %s", Struct->GetCategoryName(),Tag,F ); else sprintf ( CIFErrorLocation,"structure %s.%s data [NULL]", Struct->GetCategoryName(),Tag ); return Error_UnrecognizedInteger; } if (RC) { F = Struct->GetString ( Tag,RC ); if (F) sprintf ( CIFErrorLocation,"structure %s.%s data %s", Struct->GetCategoryName(),Tag,F ); else sprintf ( CIFErrorLocation,"structure %s.%s data [NULL]", Struct->GetCategoryName(),Tag ); return Error_NoData; } return Error_NoError; } ERROR_CODE CIFGetReal ( realtype & R, mmcif::PStruct Struct, cpstr Tag, bool Remove ) { pstr F; int RC; RC = Struct->GetReal ( R,Tag,Remove ); if (RC==mmcif::CIFRC_WrongFormat) { F = Struct->GetString ( Tag,RC ); if (F) sprintf ( CIFErrorLocation,"structure %s.%s data %s", Struct->GetCategoryName(),Tag,F ); else sprintf ( CIFErrorLocation,"structure %s.%s data [NULL]", Struct->GetCategoryName(),Tag ); return Error_UnrecognizedReal; } if (RC) { F = Struct->GetString ( Tag,RC ); if (F) sprintf ( CIFErrorLocation,"structure %s.%s data %s", Struct->GetCategoryName(),Tag,F ); else sprintf ( CIFErrorLocation,"structure %s.%s data [NULL]", Struct->GetCategoryName(),Tag ); return Error_NoData; } return Error_NoError; } ERROR_CODE CIFGetString ( pstr S, mmcif::PStruct Struct, cpstr Tag, int SLen, cpstr DefS, bool Remove ) { pstr F; int RC; F = Struct->GetString ( Tag,RC ); if ((!RC) && F) { strcpy_n0 ( S,F,SLen-1 ); if (Remove) Struct->DeleteField ( Tag ); return Error_NoError; } else { strcpy ( S,DefS ); return Error_EmptyCIFStruct; } } void PutIntIns ( pstr S, int N, int M, cpstr ins ) { // Integer N is converted into ASCII string of length M // and pasted onto first M characters of string S. No // terminating zero is added. The insert code ins is put // immediately after the integer. // If N is set to MinInt4, then first M+1 characters of // string S are set to space, and no insert code are // appended. char L[50]; int i; if (N==MinInt4) { for (i=0;i<=M;i++) S[i] = ' '; } else { if ((M!=4) || ((N>=-999) && (N<=9999))) sprintf ( L,"%*i",M,N ); else hy36encode ( M,N,L ); strcpy_n1 ( S,L,M ); if (ins[0]) S[M] = ins[0]; } } void Mat4Inverse ( mat44 & A, mat44 & AI ) { // *** FORMER RBRINV(A,AI) *** // Function to invert 4*4 matrices (AI=A^{-1}) mat44 c; mat33 x; realtype s,s1; int ii,jj,i,i1,j,j1; // ---- Get cofactors of 'a' in array 'c' s1 = 1.0; for (ii=0;ii<4;ii++) { s = s1; for (jj=0;jj<4;jj++) { i = -1; for (i1=0;i1<4;i1++) if (i1!=ii) { i++; j = -1; for (j1=0;j1<4;j1++) if (j1!=jj) { j++; x[i][j] = A[i1][j1]; } } c[ii][jj] = s*(x[0][0]*(x[1][1]*x[2][2]-x[1][2]*x[2][1]) + x[0][1]*(x[1][2]*x[2][0]-x[1][0]*x[2][2]) + x[0][2]*(x[1][0]*x[2][1]-x[1][1]*x[2][0])); s = -s; } s1 = -s1; } // ---- Calculate determinant s = 0.0; for (i=0;i<4;i++) s += A[i][0]*c[i][0]; // ---- Get inverse matrix if (s!=0.0) for (i=0;i<4;i++) for (j=0;j<4;j++) AI[i][j] = c[j][i]/s; } realtype Mat3Inverse ( mat33 & A, mat33 & AI ) { mat33 c,x; realtype s; int ii,jj,i,i1,j,j1; // Get cofactors of 'a' in array 'c' s = 1.0; for (ii=0;ii<3;ii++) for (jj=0;jj<3;jj++) { i = -1; for (i1=0;i1<3;i1++) if (i1!=ii) { i++; j = -1; for (j1=0;j1<3;j1++) if (j1!=jj) { j++; x[i][j] = A[i1][j1]; } } c[ii][jj] = s*(x[0][0]*x[1][1]-x[0][1]*x[1][0]); s = -s; } // Calculate determinant s = 0.0; for (i=0;i<3;i++) s += A[i][0]*c[i][0]; // Get inverse matrix if (s!=0.0) for (i=0;i<3;i++) for (j=0;j<3;j++) AI[i][j] = c[j][i]/s; return s; } void Mat4Mult ( mat44 & A, mat44 & B, mat44 & C ) { // Calculates A=B*C int i,j,k; for (i=0;i<4;i++) for (j=0;j<4;j++) { A[i][j] = 0.0; for (k=0;k<4;k++) A[i][j] += B[i][k]*C[k][j]; } } void Mat4Div1 ( mat44 & A, mat44 & B, mat44 & C ) { // Calculates A=B^{-1}*C mat44 B1; int i,j,k; B1[0][0] = 1.0; // in order to supress warnings from some // stupid compilers Mat4Inverse ( B,B1 ); for (i=0;i<4;i++) for (j=0;j<4;j++) { A[i][j] = 0.0; for (k=0;k<4;k++) A[i][j] += B1[i][k]*C[k][j]; } } void Mat4Div2 ( mat44 & A, mat44 & B, mat44 & C ) { // Calculates A=B*C^{-1} mat44 C1; int i,j,k; C1[0][0] = 1.0; // in order to supress warnings from some // stupid compilers Mat4Inverse ( C,C1 ); for (i=0;i<4;i++) for (j=0;j<4;j++) { A[i][j] = 0.0; for (k=0;k<4;k++) A[i][j] += B[i][k]*C1[k][j]; } } void Mat4Init ( mat44 & A ) { int i,j; for (i=0;i<4;i++) { for (j=0;j<4;j++) A[i][j] = 0.0; A[i][i] = 1.0; } } realtype Mat4RotDet ( mat44 & T ) { // returns determinant of the rotation part return T[0][0]*T[1][1]*T[2][2] + T[0][1]*T[1][2]*T[2][0] + T[1][0]*T[2][1]*T[0][2] - T[0][2]*T[1][1]*T[2][0] - T[0][0]*T[1][2]*T[2][1] - T[2][2]*T[0][1]*T[1][0]; } bool isMat4Unit ( mat44 & A, realtype eps, bool rotOnly ) { // returns true if A is a unit 4x4 matrix int i,j,k; bool B; if (rotOnly) k = 3; else k = 4; B = true; for (i=0;(iContinuationNo>1); } // =================== ContString ===================== ContString::ContString() : ContainerClass() { InitString(); } ContString::ContString ( cpstr S ) : ContainerClass() { InitString(); ConvertPDBASCII ( S ); } ContString::ContString ( io::RPStream Object ) : ContainerClass(Object) { InitString(); } ContString::~ContString() { if (Line) delete[] Line; if (CIFCategory) delete[] CIFCategory; if (CIFTag) delete[] CIFTag; } void ContString::InitString() { Line = NULL; CIFCategory = NULL; CIFTag = NULL; } ERROR_CODE ContString::ConvertPDBASCII ( cpstr S ) { CreateCopy ( Line,S ); return Error_NoError; } void ContString::PDBASCIIDump ( pstr S, int ) { if (Line) strcpy ( S,Line ); else strcpy ( S,"" ); } bool ContString::PDBASCIIDump1 ( io::RFile f ) { if (Line) f.WriteLine ( Line ); else f.LF(); return true; } /* void ContString::GetCIF1 ( mmcif::PData CIF, ERROR_CODE & Signal, int & pos ) { pstr F; int i,RC; char c; if ((!CIFCategory) || (!CIFTag)) { Signal = Error_EmptyCIF; return; } F = CIF->GetString ( CIFCategory,CIFTag,RC ); if (RC || (!F)) { Signal = Error_EmptyCIF; return; } if (Signal>=(int)strlen(F)) { CIF->DeleteField ( CIFCategory,CIFTag ); Signal = Error_EmptyCIF; return; } // i = Signal; // while (F[i] && (F[i]!='\n') && (F[i]!='\r')) i++; // if ((Signal==0) && (i==0)) { // i++; // if (((F[Signal]=='\n') && (F[i]=='\r')) || // ((F[Signal]=='\r') && (F[i]=='\n'))) i++; // Signal = i; // while (F[i] && (F[i]!='\n') && (F[i]!='\r')) i++; // } // c = F[i]; // F[i] = char(0); // CreateCopy ( Line,&(F[Signal]) ); // if (c) { // F[i] = c; // Signal = i+1; // if (((c=='\n') && (F[Signal]=='\r')) || // ((c=='\r') && (F[Signal]=='\n'))) Signal++; // } else // CIF->DeleteField ( CIFCategory,CIFTag ); i = pos; while (F[i] && (F[i]!='\n') && (F[i]!='\r')) i++; if ((pos==0) && (i==0)) { i++; if (((F[pos]=='\n') && (F[i]=='\r')) || ((F[pos]=='\r') && (F[i]=='\n'))) i++; pos = i; while (F[i] && (F[i]!='\n') && (F[i]!='\r')) i++; } c = F[i]; F[i] = char(0); CreateCopy ( Line,&(F[pos]) ); if (c) { F[i] = c; pos = i+1; if (((c=='\n') && (F[pos]=='\r')) || ((c=='\r') && (F[pos]=='\n'))) pos++; } else CIF->DeleteField ( CIFCategory,CIFTag ); } */ void ContString::MakeCIF ( mmcif::PData CIF, int N ) { pstr S; if ((!CIFCategory) || (!CIFTag)) return; S = new char[strlen(Line)+5]; strcpy ( S,"\n" ); strcat ( S,Line ); CIF->PutString ( S,CIFCategory,CIFTag,(N!=0) ); delete[] S; } bool ContString::Append ( PContainerClass CC ) { if (ContainerClass::Append(CC)) { if (!Line) { Line = PContString(CC)->Line; PContString(CC)->Line = NULL; } else CreateConcat ( Line,pstr("\n"),PContString(CC)->Line ); return true; } return false; } void ContString::Copy ( PContainerClass CString ) { CreateCopy ( Line,PContString(CString)->Line ); } void ContString::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); f.CreateWrite ( Line ); f.CreateWrite ( CIFCategory ); f.CreateWrite ( CIFTag ); } void ContString::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.CreateRead ( Line ); f.CreateRead ( CIFCategory ); f.CreateRead ( CIFTag ); } MakeStreamFunctions(ContString) // ============== ClassContainer ==================== MakeStreamFunctions(ContainerClass) ClassContainer::ClassContainer() : io::Stream() { Init(); } ClassContainer::ClassContainer ( io::RPStream Object ) : io::Stream(Object) { Init(); } void ClassContainer::Init() { length = 0; Container = NULL; } ClassContainer::~ClassContainer() { FreeContainer(); } void ClassContainer::FreeContainer() { int i; if (Container) { for (i=0;i0) { i = length-1; while (i>=0) { if (!Container[i]) i--; else if (Container[i]->GetClassID()!=Data->GetClassID()) i--; else break; } if (i>=0) { if (Container[i]->Append(Data)) { delete Data; return; } } } C1 = new PContainerClass[length+1]; for (i=0;iPDBASCIIDump1(f)) { Container[i]->PDBASCIIDump ( S,i ); j = strlen(S); while (j<80) S[j++] = ' '; S[80] = char(0); f.WriteLine ( S ); } } } ERROR_CODE ClassContainer::GetCIF ( mmcif::PData CIF, int ClassID ) { PContainerClass ContainerClass; int n; ERROR_CODE rc; n = -1; do { ContainerClass = MakeContainerClass ( ClassID ); rc = ContainerClass->GetCIF ( CIF,n ); if (rc==Error_NoError) AddData ( ContainerClass ); } while (rc==Error_NoError); delete ContainerClass; if (rc==Error_EmptyCIF) rc = Error_NoError; return rc; } void ClassContainer::MakeCIF ( mmcif::PData CIF ) { int i; for (i=0;iMakeCIF ( CIF,i ); } void ClassContainer::write ( io::RFile f ) { int i,ClassID; byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &length ); for (i=0;iGetClassID(); f.WriteInt ( &ClassID ); Container[i]->write ( f ); } else { ClassID = -1; f.WriteInt ( &ClassID ); } } PContainerClass ClassContainer::MakeContainerClass ( int ClassID ) { if (ClassID==ClassID_String) return new ContString(); return new ContainerClass(); } PContainerClass ClassContainer::GetContainerClass (int ContClassNo) { if ((ContClassNo<0) || (ContClassNo>=length)) return NULL; return Container[ContClassNo]; } void ClassContainer::Copy ( PClassContainer CContainer ) { int i; FreeContainer(); if (CContainer) { length = CContainer->length; if (length>0) { Container = new PContainerClass[length]; for (i=0;iContainer[i]) { Container[i] = MakeContainerClass ( CContainer->Container[i]->GetClassID() ); Container[i]->Copy ( CContainer->Container[i] ); } else Container[i] = NULL; } } } void ClassContainer::read ( io::RFile f ) { int i,ClassID; byte Version; FreeContainer(); f.ReadByte ( &Version ); f.ReadInt ( &length ); if (length>0) { Container = new PContainerClass[length]; for (i=0;i=0) { Container[i] = MakeContainerClass ( ClassID ); Container[i]->read ( f ); } else Container[i] = NULL; } } } MakeStreamFunctions(ClassContainer) // ====================== ID parsers ========================== AtomPath::AtomPath() : io::Stream() { InitAtomPath(); } AtomPath::AtomPath ( cpstr ID ) : io::Stream() { InitAtomPath(); SetPath ( ID ); } AtomPath::AtomPath ( io::RPStream Object ) : io::Stream(Object) { InitAtomPath(); } AtomPath::~AtomPath() {} void AtomPath::InitAtomPath() { modelNo = 0; chainID [0] = char(0); seqNum = MinInt4; insCode [0] = char(0); resName [0] = char(0); atomName[0] = char(0); element [0] = char(0); altLoc [0] = char(0); isSet = 0; } int AtomPath::SetPath ( cpstr ID ) { // 1. If ID starts with '/': // /mdl/chn/seq(res).i/atm[elm]:a // // 2. If ID starts with a letter: // chn/seq(res).i/atm[elm]:a // // 3. If ID starts with a number: // seq(res).i/atm[elm]:a // // 4. If ID contains colon ':' then // it may be just // atm[elm]:a // // All spaces are ignored. isSet // sets bit for each element present. // Any element may be a wildcard '*'. // Wildcard for model will set modelNo=0, // for sequence number will set // seqNum=MinInt4. // // Returns: // 0 <-> Ok // -1 <-> wrong numerical format for model // -2 <-> wrong numerical format for sequence number // char N[100]; pstr p,p1; int i,k; isSet = 0; // clear all bits. p = pstr(ID); while (*p==' ') p++; if (!(*p)) return 0; if (*p=='/') { // model number p++; i = 0; while ((*p) && (*p!='/')) { if (*p!=' ') N[i++] = *p; p++; } N[i] = char(0); if ((!N[0]) || (N[0]=='*')) modelNo = 0; else { modelNo = mround(strtod(N,&p1)); if ((modelNo==0) && (p1==N)) return -1; } isSet |= APATH_ModelNo; if (*p!='/') return 0; p++; while (*p==' ') p++; } if ((*p<'0') || (*p>'9')) { // chain ID i = 0; k = sizeof(ChainID)-1; while ((*p) && (*p!='/')) { if ((*p!=' ') && (i='0') && (*p<='9')) || (*p=='-') || (*p=='(') || (*p=='.')) { // sequence number, residue name and insertion code i = 0; while ((*p) && (*p!='/')) { if (*p!=' ') N[i++] = *p; p++; } N[i] = char(0); i = ParseResID ( N,seqNum,insCode,resName ); if (i==2) return -2; isSet |= APATH_SeqNum | APATH_InsCode | APATH_ResName; if (*p!='/') return 0; p++; while (*p==' ') p++; } if (strchr(p,':') || strchr(p,'[')) { // atom name, chemical element and alternative location i = 0; while (*p) { if (*p!=' ') N[i++] = *p; p++; } N[i] = char(0); ParseAtomID ( N,atomName,element,altLoc ); isSet |= APATH_AtomName | APATH_Element | APATH_AltLoc; } return 0; } void AtomPath::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); io::Stream::write ( f ); f.WriteInt ( &modelNo ); f.WriteInt ( &seqNum ); f.WriteInt ( &isSet ); f.WriteTerLine ( chainID ,false ); f.WriteTerLine ( insCode ,false ); f.WriteTerLine ( resName ,false ); f.WriteTerLine ( atomName,false ); f.WriteTerLine ( element ,false ); f.WriteTerLine ( altLoc ,false ); } void AtomPath::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); io::Stream::read ( f ); f.ReadInt ( &modelNo ); f.ReadInt ( &seqNum ); f.ReadInt ( &isSet ); f.ReadTerLine ( chainID ,false ); f.ReadTerLine ( insCode ,false ); f.ReadTerLine ( resName ,false ); f.ReadTerLine ( atomName,false ); f.ReadTerLine ( element ,false ); f.ReadTerLine ( altLoc ,false ); } MakeStreamFunctions(AtomPath) // -------------------------------------------------------- QuickSort::QuickSort() : io::Stream() { selSortLimit = 15; data = NULL; dlen = 0; } QuickSort::QuickSort ( io::RPStream Object ) : io::Stream(Object) { selSortLimit = 15; data = NULL; dlen = 0; } int QuickSort::Compare ( int i, int j ) { // sort by increasing data[i] if (((ivector)data)[i]<((ivector)data)[j]) return -1; if (((ivector)data)[i]>((ivector)data)[j]) return 1; return 0; } void QuickSort::Swap ( int i, int j ) { int b; b = ((ivector)data)[i]; ((ivector)data)[i] = ((ivector)data)[j]; ((ivector)data)[j] = b; } void QuickSort::SelectionSort ( int left, int right ) { int i,j,imin; for (i=left;i0) && (Compare(rm,lv)>0)); do lm++; while ((lm=l) i = l-1; wrd[i] = char(0); p = p1; } void ParseAtomID ( cpstr ID, AtomName aname, Element elname, AltLoc aloc ) { pstr p; p = pstr(ID); while (*p==' ') p++; strcpy ( aname ,"*" ); strcpy ( elname,"*" ); if (*p) aloc[0] = char(0); else strcpy ( aloc,"*" ); takeWord ( p,aname,pstr("[: "),sizeof(AtomName) ); if (*p=='[') { p++; takeWord ( p,elname,pstr("]: "),sizeof(Element) ); if (*p==']') p++; } if (*p==':') { p++; takeWord ( p,aloc,pstr(" "),sizeof(AltLoc) ); } } int ParseResID ( cpstr ID, int & sn, InsCode inscode, ResName resname ) { int RC; pstr p,p1; char N[100]; RC = 0; p = pstr(ID); while (*p==' ') p++; sn = ANY_RES; strcpy ( inscode,"*" ); strcpy ( resname,"*" ); N[0] = char(0); takeWord ( p,N,pstr("(./ "),sizeof(N) ); if ((!N[0]) || (N[0]=='*')) { sn = ANY_RES; RC = 1; } if (!RC) { sn = mround(strtod(N,&p1)); if (p1==N) RC = 2; else inscode[0] = char(0); } if (*p=='(') { p++; takeWord ( p,resname,pstr(")./ "),sizeof(ResName) ); if (*p==')') p++; } if (*p=='.') { p++; takeWord ( p,inscode,pstr("/ "),sizeof(InsCode) ); } return RC; } int ParseAtomPath ( cpstr ID, int & mdl, ChainID chn, int & sn, InsCode ic, ResName res, AtomName atm, Element elm, AltLoc aloc, PAtomPath DefPath ) { // /mdl/chn/seq(res).i/atm[elm]:a, may be partial char N[100]; pstr p,p1; int i,RC; bool wasRes; wasRes = false; RC = 0; p = pstr(ID); while (*p==' ') p++; mdl = 0; if (*p=='/') { p++; N[0] = char(0); takeWord ( p,N,pstr("/"),sizeof(N) ); if ((!N[0]) || (N[0]=='*')) mdl = 0; else { mdl = mround(strtod(N,&p1)); if ((mdl==0) && (p1==N)) return -1; } } else if (DefPath) { if (DefPath->isSet & APATH_ModelNo) mdl = DefPath->modelNo; } strcpy ( chn,"*" ); if (*p=='/') p++; if ((*p<'0') || (*p>'9')) { p1 = p; chn[0] = char(0); takeWord ( p,chn,pstr("/"),sizeof(ChainID) ); if (strpbrk(chn,"(.[:-")) { // this was not a chain ID! if (DefPath) { if (DefPath->isSet & APATH_ChainID) strcpy ( chn,DefPath->chainID ); } else strcpy ( chn,"*" ); p = p1; } } else if (DefPath) { if (DefPath->isSet & APATH_ChainID) strcpy ( chn,DefPath->chainID ); } if (*p=='/') p++; sn = ANY_RES; strcpy ( ic ,"*" ); strcpy ( res,"*" ); if (((*p>='0') && (*p<='9')) || (*p=='-') || (*p=='(') || (*p=='.')) { wasRes = true; N[0] = char(0); takeWord ( p,N,pstr("/"),sizeof(N) ); i = ParseResID ( N,sn,ic,res ); if (i==2) return -2; } else if (DefPath) { wasRes = (*p=='/'); if (DefPath->isSet & APATH_SeqNum) sn = DefPath->seqNum; if (DefPath->isSet & APATH_InsCode) strcpy ( ic,DefPath->insCode ); if (DefPath->isSet & APATH_ResName) strcpy ( res,DefPath->resName ); } if (*p=='/') p++; strcpy ( atm ,"*" ); strcpy ( elm ,"*" ); strcpy ( aloc,"*" ); if (wasRes || strchr(p,':') || strchr(p,'[')) { ParseAtomID ( p,atm,elm,aloc ); } else if (DefPath) { if (DefPath->isSet & APATH_AtomName) strcpy ( atm,DefPath->atomName ); if (DefPath->isSet & APATH_Element) strcpy ( elm,DefPath->element ); if (DefPath->isSet & APATH_ResName) strcpy ( aloc,DefPath->altLoc ); } if (mdl<=0) RC |= APATH_WC_ModelNo; if (chn[0]=='*') RC |= APATH_WC_ChainID; if (sn==ANY_RES) RC |= APATH_WC_SeqNum; if (ic[0]=='*') RC |= APATH_WC_InsCode; if (res[0]=='*') RC |= APATH_WC_ResName; if (atm[0]=='*') RC |= APATH_WC_AtomName; if (elm[0]=='*') RC |= APATH_WC_Element; if (aloc[0]=='*') RC |= APATH_WC_AltLoc; if (RC & (APATH_WC_ModelNo | APATH_WC_ChainID | APATH_WC_SeqNum | APATH_WC_InsCode | APATH_WC_AtomName | APATH_WC_AltLoc)) RC |= APATH_Incomplete; return RC; } int ParseSelectionPath ( cpstr CID, int & iModel, pstr Chains, int & sNum1, InsCode ic1, int & sNum2, InsCode ic2, pstr RNames, pstr ANames, pstr Elements, pstr altLocs ) { int l,j; pstr p,p1; pstr N; int seqNum [2]; InsCode insCode[2]; pstr ID; bool wasModel,wasChain,wasRes,haveNeg; l = IMax(10,strlen(CID))+1; ID = new char[l]; N = new char[l]; p = pstr(CID); p1 = ID; while (*p) { if (*p!=' ') { *p1 = *p; p1++; } p++; } *p1 = char(0); p = ID; iModel = 0; strcpy ( Chains,"*" ); seqNum[0] = ANY_RES; seqNum[1] = ANY_RES; strcpy ( insCode[0],"*" ); strcpy ( insCode[1],"*" ); strcpy ( RNames ,"*" ); strcpy ( ANames ,"*" ); strcpy ( Elements ,"*" ); strcpy ( altLocs ,"*" ); wasModel = false; wasChain = false; wasRes = false; if (*p=='/') { // CID starts with the slash -- take model number first p++; N[0] = char(0); takeWord ( p,N,pstr("/"),l ); if ((!N[0]) || (N[0]=='*')) iModel = 0; else { iModel = mround(strtod(N,&p1)); if ((iModel==0) && (p1==N)) return -1; } if (*p=='/') p++; wasModel = true; } if ((*p) && (wasModel || (*p<'0') || (*p>'9'))) { p1 = p; Chains[0] = char(0); takeWord ( p,Chains,pstr("/"),l ); if (strpbrk(Chains,"(.[:-")) { // this was not a chain ID! strcpy ( Chains,"*" ); p = p1; } else wasChain = true; if (*p=='/') p++; } if ((*p) && (wasChain || ((*p>='0') && (*p<='9')) || (*p=='-') || (*p=='(') || (*p=='.') || (*p=='*'))) { j = 0; do { // take the sequence number haveNeg = false; if (*p=='-') { haveNeg = true; p++; } N[0] = char(0); takeWord ( p,N,pstr("(.-/"),l ); if ((!N[0]) || (N[0]=='*')) seqNum[j] = ANY_RES; else { seqNum[j] = mround(strtod(N,&p1)); if (p1==N) return -2; if (haveNeg) seqNum[j] = - seqNum[j]; } // take the residue list if (*p=='(') { p++; takeWord ( p,RNames,pstr(").-/"),l ); if (*p==')') p++; } // take the insertion code if (seqNum[j]!=ANY_RES) insCode[j][0] = char(0); if (*p=='.') { p++; takeWord ( p,insCode[j],pstr("-/"),sizeof(InsCode) ); } if (*p=='-') { p++; j++; } else { if (j==0) { seqNum[1] = seqNum[0]; strcpy ( insCode[1],insCode[0] ); } j = 10; } } while (j<2); wasRes = true; } else wasRes = (*p=='/'); if (*p=='/') p++; if ((*p) && (wasRes || strchr(p,':') || strchr(p,'['))) { if (*p) altLocs[0] = char(0); takeWord ( p,ANames,pstr("[:"),l ); if (!ANames[0]) strcpy ( ANames,"*" ); if (*p=='[') { p++; takeWord ( p,Elements,pstr("]:"),l ); if (*p==']') p++; } if (*p==':') { p++; takeWord ( p,altLocs,pstr(" "),l ); } } /* printf ( " iModel = %i\n" " Chains = '%s'\n" " seqNum1 = %i\n" " insCode1 = '%s'\n" " seqNum2 = %i\n" " insCode2 = '%s'\n" " RNames = '%s'\n" " ANames = '%s'\n" " Elements = '%s'\n" " altLocs = '%s'\n", iModel,Chains,seqNum[0],insCode[0], seqNum[1],insCode[1],RNames,ANames, Elements,altLocs ); */ sNum1 = seqNum[0]; sNum2 = seqNum[1]; strcpy ( ic1,insCode[0] ); strcpy ( ic2,insCode[1] ); delete[] ID; delete[] N; return 0; } void MakeSelectionPath ( pstr CID, int iModel, cpstr Chains, int sNum1, const InsCode ic1, int sNum2, const InsCode ic2, cpstr RNames, cpstr ANames, cpstr Elements, cpstr altLocs ) { char S[100]; int k; if (iModel>0) { sprintf ( CID,"/%i",iModel ); k = 1; } else { CID[0] = char(0); k = 0; } if (Chains[0]!='*') { if (k>0) strcat ( CID,"/" ); strcat ( CID,Chains ); k = 2; } if ((sNum1!=-MaxInt4) || (ic1[0]!='*')) { if (k>0) { if (k<2) strcat ( CID,"/*" ); strcat ( CID,"/" ); } if (sNum1>-MaxInt4) sprintf ( S,"%i",sNum1 ); else strcpy ( S,"*" ); if (ic1[0]!='*') { strcat ( S,"." ); strcat ( S,ic1 ); } strcat ( CID,S ); if ((sNum2!=-MaxInt4) || (ic2[0]!='*')) { strcat ( CID,"-" ); if (sNum1>-MaxInt4) sprintf ( S,"%i",sNum2 ); else strcpy ( S,"*" ); if (ic2[0]!='*') { strcat ( S,"." ); strcat ( S,ic2 ); } strcat ( CID,S ); } k = 3; } if (RNames[0]!='*') { if (k<1) strcat ( CID,"(" ); else if (k<2) strcat ( CID,"*/*(" ); else if (k<3) strcat ( CID,"/*(" ); strcat ( CID,RNames ); strcat ( CID,")" ); k = 4; } if (ANames[0]!='*') { if (k<1) strcat ( CID,"/*/*/*/" ); // full path else if (k<2) strcat ( CID,"/*/*/" ); // /mdl + /*/*/ else if (k<3) strcat ( CID,"/*/" ); // /mdl/chn + /*/ else if (k<4) strcat ( CID,"/" ); // /mdl/chn/res + / strcat ( CID,ANames ); strcat ( CID,")" ); k = 5; } if (Elements[0]!='*') { if (k<1) strcat ( CID,"[" ); else if (k<2) strcat ( CID,"/*/*/*[" ); else if (k<3) strcat ( CID,"/*/*[" ); else if (k<4) strcat ( CID,"/*[" ); else if (k<5) strcat ( CID,"[" ); strcat ( CID,Elements ); strcat ( CID,"]" ); k = 6; } if (altLocs[0]!='*') { if (k<1) strcat ( CID,":" ); else if (k<2) strcat ( CID,"/*/*/*:" ); else if (k<3) strcat ( CID,"/*/*:" ); else if (k<4) strcat ( CID,"/*:" ); else if (k<6) strcat ( CID,":" ); strcat ( CID,altLocs ); } } } // namespace mmdb mmdb2-2.0.5/mmdb2/mmdb_math_align.h0000664000175000017500000001362012401105774013721 00000000000000// $Id: mmdb_math_align.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : Align // ~~~~~~~~~ // **** Classes : mmdb::math::Alignment (char strings alignment) // ~~~~~~~~~~~~ mmdb::math::Alignment1 (int vectors alignment) // // (C) E.Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_MATH_Align__ #define __MMDB_MATH_Align__ #include "mmdb_io_stream.h" namespace mmdb { namespace math { // ===================== AlignParams ====================== DefineClass(AlignParams); DefineStreamFunctions(AlignParams); class AlignParams : public io::Stream { public : realtype gapWeight,spaceWeight; realtype equalScore,nequalScore; int method; AlignParams(); AlignParams ( io::RPStream Object ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitAlignParams(); }; // ====================== Alignment ======================= DefineClass(Alignment); enum ALIGN_METHOD { ALIGN_GLOBAL = 0, ALIGN_LOCAL = 1, ALIGN_GLOBLOC = 2, ALIGN_FREEENDS = 3 }; class Alignment : public io::Stream { public : Alignment (); Alignment ( io::RPStream Object ); ~Alignment (); void SetAffineModel ( realtype WGap, realtype WSpace ); void SetScores ( realtype SEqual, realtype SNEqual ); void Align ( cpstr S, cpstr T, ALIGN_METHOD Method=ALIGN_GLOBAL ); inline pstr GetAlignedS() { return AlgnS; } inline pstr GetAlignedT() { return AlgnT; } inline realtype GetScore () { return VAchieved; } inline char GetSpace () { return Space; } realtype GetSimilarity(); // Score-weighted sequence id realtype GetSeqId (); // Primitive sequence id virtual void OutputResults ( io::RFile f, cpstr S, cpstr T ); void read ( io::RFile f ); void write ( io::RFile f ); protected : char Space; int AlignKey, SLen,TLen; rmatrix VT,ET,FT; pstr AlgnS,AlgnT; realtype VAchieved; realtype SEq,SNEq, Wg,Ws; virtual void InitAlignment(); virtual void FreeMemory (); virtual realtype Score ( char A, char B ); void BuildGATable ( cpstr S, cpstr T, bool FreeSEnd, bool FreeTEnd ); void BuildLATable ( cpstr S, cpstr T ); void Backtrace ( cpstr S, cpstr T, int J, int I, bool StopAtZero ); void AdjustEnds ( cpstr S, cpstr T, int J, int I ); void PrintVT ( cpstr S, cpstr T ); }; // ====================== Alignment1 ======================= DefineClass(Alignment1); class Alignment1 : public io::Stream { public : Alignment1 (); Alignment1 ( io::RPStream Object ); ~Alignment1(); void SetAffineModel ( realtype WGap, realtype WSpace ); void SetScores ( realtype SEqual, realtype SNEqual ); void Align ( ivector S, int SLength, ivector T, int TLength, ALIGN_METHOD Method=ALIGN_GLOBAL ); inline ivector GetAlignedS () { return AlgnS; } inline ivector GetAlignedT () { return AlgnT; } inline int GetAlignLength() { return AlgnLen; } inline realtype GetScore () { return VAchieved; } realtype GetSimilarity(); // Score-weighted sequence id virtual void OutputResults ( io::RFile f, ivector S, int lenS, ivector T, int lenT ); void read ( io::RFile f ); void write ( io::RFile f ); protected : int Space; int AlignKey, SLen,TLen, AlgnLen; rmatrix VT,ET,FT; ivector AlgnS,AlgnT; realtype VAchieved; realtype SEq,SNEq, Wg,Ws; virtual void InitAlignment1(); virtual void FreeMemory (); virtual realtype Score ( int A, int B ); void BuildGATable ( ivector S, ivector T, bool FreeSEnds, bool FreeTEnds ); void BuildLATable ( ivector S, ivector T ); void Backtrace ( ivector S, ivector T, int J, int I, bool StopAtZero ); void AdjustEnds ( ivector S, ivector T, int J, int I ); void PrintVT ( ivector S, ivector T ); }; } // namespace math } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_cifdefs.cpp0000664000175000017500000005311512401105774013557 00000000000000// $Id: mmdb_cifdefs.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 21.11.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDBF_Defs // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Namespace: mmdb:: // // CIF Definitions // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include "mmdb_cifdefs.h" namespace mmdb { // ------------------------------------------------------------------ cpstr CIFName ( int NameID, CIF_MODE Mode ) { // Gives CIF name according to CIF Mode. switch (Mode) { case CIF_NDB : switch (NameID) { case CAT_POLY_SEQ_SCHEME : return CIFCAT_NDB_POLY_SEQ_SCHEME; case TAG_ID_CODE : return CIFTAG_NDB_PDB_ID_CODE; case TAG_CHAIN_ID : return CIFTAG_NDB_CHAIN_ID; case TAG_SEQ_ALIGN_BEG : return CIFTAG_SEQ_ALIGN_BEG; case TAG_SEQ_ALIGN_BEG_INS_CODE : return CIFTAG_NDB_SEQ_ALIGN_BEG_INS_CODE; case TAG_SEQ_ALIGN_END : return CIFTAG_SEQ_ALIGN_END; case TAG_SEQ_ALIGN_END_INS_CODE : return CIFTAG_NDB_SEQ_ALIGN_END_INS_CODE; case TAG_DB_ACCESSION : return CIFTAG_NDB_DB_ACCESSION; case TAG_DB_ALIGN_BEG : return CIFTAG_DB_ALIGN_BEG; case TAG_DB_ALIGN_BEG_INS_CODE : return CIFTAG_NDB_DB_ALIGN_BEG_INS_CODE; case TAG_DB_ALIGN_END : return CIFTAG_DB_ALIGN_END; case TAG_DB_ALIGN_END_INS_CODE : return CIFTAG_NDB_DB_ALIGN_END_INS_CODE; case TAG_SEQ_CHAIN_ID : return CIFTAG_ID; default : return pstr("ERROR_IN_CIF_NAME_1"); } case CIF_PDBX : switch (NameID) { case CAT_POLY_SEQ_SCHEME : return CIFCAT_PDBX_POLY_SEQ_SCHEME; case TAG_ID_CODE : return CIFTAG_PDBX_PDB_ID_CODE; case TAG_CHAIN_ID : return CIFTAG_PDBX_STRAND_ID; case TAG_SEQ_ALIGN_BEG : return CIFTAG_SEQ_ALIGN_BEG; case TAG_SEQ_ALIGN_BEG_INS_CODE : return CIFTAG_PDBX_SEQ_ALIGN_BEG_INS_CODE; case TAG_SEQ_ALIGN_END : return CIFTAG_SEQ_ALIGN_END; case TAG_SEQ_ALIGN_END_INS_CODE : return CIFTAG_PDBX_SEQ_ALIGN_END_INS_CODE; case TAG_DB_ACCESSION : return CIFTAG_PDBX_DB_ACCESSION; case TAG_DB_ALIGN_BEG : return CIFTAG_DB_ALIGN_BEG; case TAG_DB_ALIGN_BEG_INS_CODE : return CIFTAG_PDBX_DB_ALIGN_BEG_INS_CODE; case TAG_DB_ALIGN_END : return CIFTAG_DB_ALIGN_END; case TAG_DB_ALIGN_END_INS_CODE : return CIFTAG_PDBX_DB_ALIGN_END_INS_CODE; case TAG_SEQ_CHAIN_ID : return CIFTAG_ASYM_ID; default : return pstr("ERROR_IN_CIF_NAME_2"); } default : return pstr("ERROR_IN_CIF_NAME_3"); } } cpstr CIFCAT_ATOM_SITE = cpstr("_atom_site"); cpstr CIFCAT_ATOM_SITE_ANISOTROP = cpstr("_atom_site_anisotrop"); cpstr CIFCAT_ATOM_SITES = cpstr("_atom_sites"); cpstr CIFCAT_AUDIT_AUTHOR = cpstr("_audit_author"); cpstr CIFCAT_CELL = cpstr("_cell"); cpstr CIFCAT_CHEM_COMP = cpstr("_chem_comp"); cpstr CIFCAT_CITATION = cpstr("_citation"); cpstr CIFCAT_DATABASE = cpstr("_database"); cpstr CIFCAT_DATABASE_PDB_CAVEAT = cpstr("_database_pdb_caveat"); cpstr CIFCAT_DATABASE_PDB_MATRIX = cpstr("_database_pdb_matrix"); cpstr CIFCAT_DATABASE_PDB_REV = cpstr("_database_pdb_rev"); cpstr CIFCAT_DATABASE_PDB_TVECT = cpstr("_database_pdb_tvect"); cpstr CIFCAT_ENTITY = cpstr("_entity"); cpstr CIFCAT_EXPTL = cpstr("_exptl"); cpstr CIFCAT_NDB_DATABASE_REMARK = cpstr("_ndb_database_remark"); cpstr CIFCAT_NDB_NONSTANDARD_LIST = cpstr("_ndb_nonstandard_list"); cpstr CIFCAT_NDB_POLY_SEQ_SCHEME = cpstr("_ndb_poly_seq_scheme"); cpstr CIFCAT_PDBX_POLY_SEQ_SCHEME = cpstr("_pdbx_poly_seq_scheme"); cpstr CIFCAT_REFINE = cpstr("_refine"); cpstr CIFCAT_SPRSDE = cpstr("_ndb_database_pdb_obs_spr"); cpstr CIFCAT_STRUCT = cpstr("_struct"); cpstr CIFCAT_STRUCT_ASYM = cpstr("_struct_asym"); cpstr CIFCAT_STRUCT_CONF = cpstr("_struct_conf"); cpstr CIFCAT_STRUCT_CONN = cpstr("_struct_conn"); cpstr CIFCAT_STRUCT_LINKR = cpstr("_struct_linkr"); cpstr CIFCAT_STRUCT_KEYWORDS = cpstr("_struct_keywords"); cpstr CIFCAT_STRUCT_NCS_OPER = cpstr("_struct_ncs_oper"); cpstr CIFCAT_STRUCT_REF = cpstr("_struct_ref"); cpstr CIFCAT_STRUCT_REF_SEQ = cpstr("_struct_ref_seq"); cpstr CIFCAT_STRUCT_REF_SEQ_DIF = cpstr("_struct_ref_seq_dif"); cpstr CIFCAT_STRUCT_SHEET = cpstr("_struct_sheet"); cpstr CIFCAT_STRUCT_SHEET_RANGE = cpstr("_struct_sheet_range"); cpstr CIFCAT_STRUCT_SHEET_ORDER = cpstr("_struct_sheet_order"); cpstr CIFCAT_STRUCT_SHEET_HBOND = cpstr("_struct_sheet_hbond"); cpstr CIFCAT_SYMMETRY = cpstr("_symmetry"); cpstr CIFCAT_OBSLTE = cpstr("_ndb_database_pdb_obs_spr"); cpstr CIFTAG_ANGLE_ALPHA = cpstr("angle_alpha"); cpstr CIFTAG_ANGLE_BETA = cpstr("angle_beta"); cpstr CIFTAG_ANGLE_GAMMA = cpstr("angle_gamma"); cpstr CIFTAG_ASYM_ID = cpstr("asym_id"); cpstr CIFTAG_ATOM_TYPE_SYMBOL = cpstr("atom_type_symbol"); cpstr CIFTAG_AUTH_ASYM_ID = cpstr("auth_asym_id"); cpstr CIFTAG_AUTH_ATOM_ID = cpstr("auth_atom_id"); cpstr CIFTAG_AUTH_COMP_ID = cpstr("auth_comp_id"); cpstr CIFTAG_AUTH_SEQ_ID = cpstr("auth_seq_id"); cpstr CIFTAG_B_ISO_OR_EQUIV = cpstr("B_iso_or_equiv"); cpstr CIFTAG_B_ISO_OR_EQUIV_ESD = cpstr("B_iso_or_equiv_esd"); cpstr CIFTAG_BEG_LABEL_ASYM_ID = cpstr("beg_label_asym_id"); cpstr CIFTAG_BEG_LABEL_COMP_ID = cpstr("beg_label_comp_id"); cpstr CIFTAG_BEG_LABEL_SEQ_ID = cpstr("beg_label_seq_id"); cpstr CIFTAG_CARTN_X = cpstr("cartn_x"); cpstr CIFTAG_CARTN_X_ESD = cpstr("cartn_x_esd"); cpstr CIFTAG_CARTN_Y = cpstr("cartn_y"); cpstr CIFTAG_CARTN_Y_ESD = cpstr("cartn_y_esd"); cpstr CIFTAG_CARTN_Z = cpstr("cartn_z"); cpstr CIFTAG_CARTN_Z_ESD = cpstr("cartn_z_esd"); cpstr CIFTAG_PDBX_FORMAL_CHARGE = cpstr("pdbx_formal_charge"); cpstr CIFTAG_CODE = cpstr("code"); cpstr CIFTAG_CODE_NDB = cpstr("code_NDB"); cpstr CIFTAG_CODE_PDB = cpstr("code_PDB"); cpstr CIFTAG_CONF_TYPE_ID = cpstr("conf_type_id"); cpstr CIFTAG_CONN_TYPE_ID = cpstr("conn_type_id"); cpstr CIFTAG_DATE = cpstr("date"); cpstr CIFTAG_DATE_ORIGINAL = cpstr("date_original"); cpstr CIFTAG_DB_ALIGN_BEG = cpstr("db_align_beg"); cpstr CIFTAG_DB_ALIGN_END = cpstr("db_align_end"); cpstr CIFTAG_DB_CODE = cpstr("db_code"); cpstr CIFTAG_DB_MON_ID = cpstr("db_mon_id"); cpstr CIFTAG_DB_NAME = cpstr("db_name"); cpstr CIFTAG_DETAILS = cpstr("details"); cpstr CIFTAG_END_LABEL_ASYM_ID = cpstr("end_label_asym_id"); cpstr CIFTAG_END_LABEL_COMP_ID = cpstr("end_label_comp_id"); cpstr CIFTAG_END_LABEL_SEQ_ID = cpstr("end_label_seq_id"); cpstr CIFTAG_ENTITY_ID = cpstr("entity_id"); cpstr CIFTAG_ENTRY_ID = cpstr("entry_id"); cpstr CIFTAG_FORMULA = cpstr("formula"); cpstr CIFTAG_FRACT_TRANSF_MATRIX11 = cpstr("fract_transf_matrix[1][1]"); cpstr CIFTAG_FRACT_TRANSF_MATRIX12 = cpstr("fract_transf_matrix[1][2]"); cpstr CIFTAG_FRACT_TRANSF_MATRIX13 = cpstr("fract_transf_matrix[1][3]"); cpstr CIFTAG_FRACT_TRANSF_MATRIX21 = cpstr("fract_transf_matrix[2][1]"); cpstr CIFTAG_FRACT_TRANSF_MATRIX22 = cpstr("fract_transf_matrix[2][2]"); cpstr CIFTAG_FRACT_TRANSF_MATRIX23 = cpstr("fract_transf_matrix[2][3]"); cpstr CIFTAG_FRACT_TRANSF_MATRIX31 = cpstr("fract_transf_matrix[3][1]"); cpstr CIFTAG_FRACT_TRANSF_MATRIX32 = cpstr("fract_transf_matrix[3][2]"); cpstr CIFTAG_FRACT_TRANSF_MATRIX33 = cpstr("fract_transf_matrix[3][3]"); cpstr CIFTAG_FRACT_TRANSF_VECTOR1 = cpstr("fract_transf_vector[1]"); cpstr CIFTAG_FRACT_TRANSF_VECTOR2 = cpstr("fract_transf_vector[2]"); cpstr CIFTAG_FRACT_TRANSF_VECTOR3 = cpstr("fract_transf_vector[3]"); cpstr CIFTAG_GROUP_PDB = cpstr("group_PDB" ); cpstr CIFTAG_ID = cpstr("id"); cpstr CIFTAG_INS_CODE = cpstr("ins_code"); cpstr CIFTAG_LABEL_ALT_ID = cpstr("label_alt_id"); cpstr CIFTAG_LABEL_ATOM_ID = cpstr("label_atom_id"); cpstr CIFTAG_LABEL_ASYM_ID = cpstr("label_asym_id"); cpstr CIFTAG_LABEL_COMP_ID = cpstr("label_comp_id"); cpstr CIFTAG_LABEL_ENTITY_ID = cpstr("label_entity_id"); cpstr CIFTAG_LABEL_SEQ_ID = cpstr("label_seq_id"); cpstr CIFTAG_LENGTH_A = cpstr("length_a"); cpstr CIFTAG_LENGTH_B = cpstr("length_b"); cpstr CIFTAG_LENGTH_C = cpstr("length_c"); cpstr CIFTAG_LS_D_RES_HIGH = cpstr("ls_d_res_high"); cpstr CIFTAG_MATRIX11 = cpstr("matrix[1][1]"); cpstr CIFTAG_MATRIX12 = cpstr("matrix[1][2]"); cpstr CIFTAG_MATRIX13 = cpstr("matrix[1][3]"); cpstr CIFTAG_MATRIX21 = cpstr("matrix[2][1]"); cpstr CIFTAG_MATRIX22 = cpstr("matrix[2][2]"); cpstr CIFTAG_MATRIX23 = cpstr("matrix[2][3]"); cpstr CIFTAG_MATRIX31 = cpstr("matrix[3][1]"); cpstr CIFTAG_MATRIX32 = cpstr("matrix[3][2]"); cpstr CIFTAG_MATRIX33 = cpstr("matrix[3][3]"); cpstr CIFTAG_METHOD = cpstr("method"); cpstr CIFTAG_MOD_TYPE = cpstr("mod_type"); cpstr CIFTAG_MON_ID = cpstr("mon_id"); cpstr CIFTAG_NAME = cpstr("name"); cpstr CIFTAG_NDB_BEG_LABEL_INS_CODE_PDB = cpstr("ndb_beg_label_ins_code_pdb"); cpstr CIFTAG_NDB_CHAIN_ID = cpstr("ndb_chain_id"); cpstr CIFTAG_NDB_COMPONENT_NO = cpstr("ndb_component_no"); cpstr CIFTAG_NDB_DESCRIPTOR = cpstr("ndb_descriptor"); cpstr CIFTAG_NDB_DB_ACCESSION = cpstr("ndb_db_accession"); cpstr CIFTAG_NDB_DB_ALIGN_BEG_INS_CODE = cpstr("ndb_db_align_beg_ins_code"); cpstr CIFTAG_NDB_DB_ALIGN_END_INS_CODE = cpstr("ndb_db_align_end_ins_code"); cpstr CIFTAG_NDB_END_LABEL_INS_CODE_PDB = cpstr("ndb_end_label_ins_code_pdb"); //cpstr CIFTAG_NDB_INS_CODE = cpstr("ndb_ins_code"); cpstr CIFTAG_PDBX_PDB_INS_CODE = cpstr("pdbx_PDB_ins_code"); cpstr CIFTAG_NDB_HELIX_CLASS_PDB = cpstr("ndb_helix_class_pdb"); cpstr CIFTAG_NDB_KEYWORDS = cpstr("ndb_keywords"); cpstr CIFTAG_NDB_LABEL_ALT_ID = cpstr("ndb_label_alt_id"); cpstr CIFTAG_NDB_LABEL_ATOM_ID = cpstr("ndb_label_atom_id"); cpstr CIFTAG_NDB_LABEL_ASYM_ID = cpstr("ndb_label_asym_id"); cpstr CIFTAG_NDB_LABEL_COMP_ID = cpstr("ndb_label_comp_id"); cpstr CIFTAG_NDB_LABEL_INS_CODE = cpstr("ndb_label_ins_code"); cpstr CIFTAG_NDB_LABEL_SEQ_NUM = cpstr("ndb_label_seq_num"); cpstr CIFTAG_NDB_LENGTH = cpstr("ndb_length"); cpstr CIFTAG_NDB_MODEL = cpstr("ndb_model"); cpstr CIFTAG_NDB_PDB_CHAIN_ID = cpstr("ndb_pdb_chain_id"); cpstr CIFTAG_NDB_PDB_ID = cpstr("ndb_pdb_id"); cpstr CIFTAG_NDB_PDB_ID_CODE = cpstr("ndb_pdb_id_code"); cpstr CIFTAG_NDB_PDB_INS_CODE = cpstr("ndb_pdb_ins_code"); cpstr CIFTAG_NDB_PTNR1_LABEL_INS_CODE = cpstr("ndb_ptnr1_label_ins_code"); cpstr CIFTAG_NDB_PTNR1_STANDARD_COMP_ID = cpstr("ndb_ptnr1_standard_comp_id"); cpstr CIFTAG_NDB_RANGE_1_BEG_LABEL_COMP_ID = cpstr("ndb_range_1_beg_label_comp_id"); cpstr CIFTAG_NDB_RANGE_1_BEG_LABEL_ASYM_ID = cpstr("ndb_range_1_beg_label_asym_id"); cpstr CIFTAG_NDB_RANGE_1_BEG_LABEL_INS_CODE= cpstr("ndb_range_1_beg_label_ins_code"); cpstr CIFTAG_NDB_RANGE_1_END_LABEL_COMP_ID = cpstr("ndb_range_1_end_label_comp_id"); cpstr CIFTAG_NDB_RANGE_1_END_LABEL_ASYM_ID = cpstr("ndb_range_1_end_label_asym_id"); cpstr CIFTAG_NDB_RANGE_1_END_LABEL_INS_CODE= cpstr("ndb_range_1_end_label_ins_code"); cpstr CIFTAG_NDB_SEQ_ALIGN_BEG = cpstr("ndb_seq_align_beg"); cpstr CIFTAG_NDB_SEQ_ALIGN_BEG_INS_CODE = cpstr("ndb_seq_align_beg_ins_code"); cpstr CIFTAG_NDB_SEQ_ALIGN_END = cpstr("ndb_seq_align_end"); cpstr CIFTAG_NDB_SEQ_ALIGN_END_INS_CODE = cpstr("ndb_seq_align_end_ins_code"); cpstr CIFTAG_NDB_SEQ_DB_NAME = cpstr("ndb_seq_db_name"); cpstr CIFTAG_NDB_SEQ_DB_ACCESSION_CODE = cpstr("ndb_seq_db_accession_code"); cpstr CIFTAG_NDB_SEQ_DB_SEQ_NUM = cpstr("ndb_seq_db_seq_num"); cpstr CIFTAG_NDB_SYNONYMS = cpstr("ndb_synonyms"); cpstr CIFTAG_NUM = cpstr("num"); cpstr CIFTAG_NUMBER_ATOMS_NH = cpstr("number_atoms_nh"); cpstr CIFTAG_NUMBER_STRANDS = cpstr("number_strands"); cpstr CIFTAG_OCCUPANCY = cpstr("occupancy"); cpstr CIFTAG_OCCUPANCY_ESD = cpstr("occupancy_esd"); cpstr CIFTAG_ORIGX11 = cpstr("origx[1][1]"); cpstr CIFTAG_ORIGX12 = cpstr("origx[1][2]"); cpstr CIFTAG_ORIGX13 = cpstr("origx[1][3]"); cpstr CIFTAG_ORIGX21 = cpstr("origx[2][1]"); cpstr CIFTAG_ORIGX22 = cpstr("origx[2][2]"); cpstr CIFTAG_ORIGX23 = cpstr("origx[2][3]"); cpstr CIFTAG_ORIGX31 = cpstr("origx[3][1]"); cpstr CIFTAG_ORIGX32 = cpstr("origx[3][2]"); cpstr CIFTAG_ORIGX33 = cpstr("origx[3][3]"); cpstr CIFTAG_ORIGX_VECTOR1 = cpstr("origx_vector[1]"); cpstr CIFTAG_ORIGX_VECTOR2 = cpstr("origx_vector[2]"); cpstr CIFTAG_ORIGX_VECTOR3 = cpstr("origx_vector[3]"); cpstr CIFTAG_PDB_ID = cpstr("pdb_id"); cpstr CIFTAG_PDB_MON_ID = cpstr("pdb_mon_id"); cpstr CIFTAG_PDB_STRAND_ID = cpstr("pdb_strand_id"); cpstr CIFTAG_PDBX_DB_ACCESSION = cpstr("pdbx_db_accession"); cpstr CIFTAG_PDBX_DB_ALIGN_BEG_INS_CODE = cpstr("pdbx_db_align_beg_ins_code"); cpstr CIFTAG_PDBX_DB_ALIGN_END_INS_CODE = cpstr("pdbx_db_align_end_ins_code"); cpstr CIFTAG_PDBX_PDB_ID_CODE = cpstr("pdbx_PDB_id_code"); cpstr CIFTAG_PDBX_PDB_MODEL_NUM = cpstr("pdbx_PDB_model_num"); cpstr CIFTAG_PDBX_STRAND_ID = cpstr("pdbx_strand_id"); cpstr CIFTAG_RANGE_1_BEG_LABEL_ATOM_ID = cpstr("range_1_beg_label_atom_id"); cpstr CIFTAG_RANGE_1_BEG_LABEL_SEQ_ID = cpstr("range_1_beg_label_seq_id"); cpstr CIFTAG_RANGE_1_END_LABEL_ATOM_ID = cpstr("range_1_end_label_atom_id"); cpstr CIFTAG_RANGE_1_END_LABEL_SEQ_ID = cpstr("range_1_end_label_seq_id"); cpstr CIFTAG_RANGE_ID_1 = cpstr("range_id_1"); cpstr CIFTAG_RANGE_ID_2 = cpstr("range_id_2"); cpstr CIFTAG_RCSB_RECORD_REVISED_1 = cpstr("rcsb_record_revised_1"); cpstr CIFTAG_RCSB_RECORD_REVISED_2 = cpstr("rcsb_record_revised_2"); cpstr CIFTAG_RCSB_RECORD_REVISED_3 = cpstr("rcsb_record_revised_3"); cpstr CIFTAG_RCSB_RECORD_REVISED_4 = cpstr("rcsb_record_revised_4"); cpstr CIFTAG_PDBX_SEQ_ALIGN_BEG_INS_CODE = cpstr("pdbx_seq_align_beg_ins_code"); cpstr CIFTAG_PDBX_SEQ_ALIGN_END_INS_CODE = cpstr("pdbx_seq_align_end_ins_code"); cpstr CIFTAG_PTNR1_LABEL_ASYM_ID = cpstr("ptnr1_label_asym_id"); cpstr CIFTAG_PTNR1_LABEL_COMP_ID = cpstr("ptnr1_label_comp_id"); cpstr CIFTAG_PTNR1_LABEL_SEQ_ID = cpstr("ptnr1_label_seq_id"); cpstr CIFTAG_REF_ID = cpstr("ref_id"); cpstr CIFTAG_REPLACES = cpstr("replaces"); cpstr CIFTAG_REPLACE_PDB_ID = cpstr("replace_pdb_id"); cpstr CIFTAG_SEGMENT_ID = cpstr("segment_id"); cpstr CIFTAG_SEQ_ALIGN_BEG = cpstr("seq_align_beg"); cpstr CIFTAG_SEQ_ALIGN_END = cpstr("seq_align_end"); cpstr CIFTAG_SEQ_NUM = cpstr("seq_num"); cpstr CIFTAG_SENSE = cpstr("sense"); cpstr CIFTAG_SHEET_ID = cpstr("sheet_id"); cpstr CIFTAG_SOURCE = cpstr("source"); cpstr CIFTAG_SPACE_GROUP_NAME_H_M = cpstr("space_group_name_H-M"); cpstr CIFTAG_TEXT = cpstr("text"); cpstr CIFTAG_TITLE = cpstr("title"); cpstr CIFTAG_TYPE = cpstr("type"); cpstr CIFTAG_TYPE_SYMBOL = cpstr("type_symbol"); cpstr CIFTAG_VECTOR1 = cpstr("vector[1]"); cpstr CIFTAG_VECTOR2 = cpstr("vector[2]"); cpstr CIFTAG_VECTOR3 = cpstr("vector[3]"); cpstr CIFTAG_U11 = cpstr("u[1][1]"); cpstr CIFTAG_U11_ESD = cpstr("u[1][1]_esd"); cpstr CIFTAG_U12 = cpstr("u[1][2]"); cpstr CIFTAG_U12_ESD = cpstr("u[1][2]_esd"); cpstr CIFTAG_U13 = cpstr("u[1][3]"); cpstr CIFTAG_U13_ESD = cpstr("u[1][3]_esd"); cpstr CIFTAG_U22 = cpstr("u[2][2]"); cpstr CIFTAG_U22_ESD = cpstr("u[2][2]_esd"); cpstr CIFTAG_U23 = cpstr("u[2][3]"); cpstr CIFTAG_U23_ESD = cpstr("u[2][3]_esd"); cpstr CIFTAG_U33 = cpstr("u[3][3]"); cpstr CIFTAG_U33_ESD = cpstr("u[3][3]_esd"); cpstr CIFTAG_Z_PDB = cpstr("z_pdb"); cpstr CIFTAG_CONN_PTNR1_AUTH_ATOM_ID = cpstr("ptnr1_auth_atom_id"); cpstr CIFTAG_CONN_PDBX_PTNR1_AUTH_ALT_ID = cpstr("pdbx_ptnr1_auth_alt_id"); cpstr CIFTAG_CONN_PTNR1_AUTH_COMP_ID = cpstr("ptnr1_auth_comp_id"); cpstr CIFTAG_CONN_PTNR1_AUTH_ASYM_ID = cpstr("ptnr1_auth_asym_id"); cpstr CIFTAG_CONN_PTNR1_AUTH_SEQ_ID = cpstr("ptnr1_auth_seq_id"); cpstr CIFTAG_CONN_PDBX_PTNR1_PDB_INS_CODE = cpstr("pdbx_ptnr1_PDB_ins_code"); cpstr CIFTAG_CONN_DIST = cpstr("link_dist"); cpstr CIFTAG_CONN_PTNR2_AUTH_ATOM_ID = cpstr("ptnr2_auth_atom_id"); cpstr CIFTAG_CONN_PDBX_PTNR2_AUTH_ALT_ID = cpstr("pdbx_ptnr2_auth_alt_id"); cpstr CIFTAG_CONN_PTNR2_AUTH_COMP_ID = cpstr("ptnr2_auth_comp_id"); cpstr CIFTAG_CONN_PTNR2_AUTH_ASYM_ID = cpstr("ptnr2_auth_asym_id"); cpstr CIFTAG_CONN_PTNR2_AUTH_SEQ_ID = cpstr("ptnr2_auth_seq_id"); cpstr CIFTAG_CONN_PDBX_PTNR2_PDB_INS_CODE = cpstr("pdbx_ptnr2_PDB_ins_code"); cpstr CIFTAG_CONN_PTNR1_SYMMETRY = cpstr("ptnr1_symmetry"); cpstr CIFTAG_CONN_PTNR2_SYMMETRY = cpstr("ptnr2_symmetry"); cpstr CIFTAG_CONN_NAME = cpstr("link_name"); } // namespace mmdb mmdb2-2.0.5/mmdb2/mmdb_ficif.cpp0000664000175000017500000004521212401105774013233 00000000000000// $Id: mmdb_ficif.cpp,v 1.19 2012/01/26 17:52:20 ekr Exp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2008. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 24.04.03 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_FICIF // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : // ~~~~~~~~~ // // (C) E. Krissinel 2000-2008 // // ================================================================= // #include "mmdb_mmcif_.h" #include "mmdb_ficif.h" // ================================================================== mmcif::PData mmCIFData = NULL; FORTRAN_SUBR ( MMDB_FCIF_INIT, mmdb_fcif_init,(),(),() ) { InitMatType(); mmCIFData = NULL; } void MMDB_CCIF_Init() { InitMatType(); mmCIFData = NULL; } FORTRAN_SUBR ( MMDB_FCIF_QUIT, mmdb_fcif_quit,(),(),() ) { if (mmCIFData) delete mmCIFData; mmCIFData = NULL; } void MMDB_CCIF_Quit() { if (mmCIFData) delete mmCIFData; mmCIFData = NULL; } pstr makeString ( pstr S, int SLen, pstr FS, int FSLen ) { GetStrTer ( S,FS,FSLen,SLen,FSLen ); CutSpaces ( S,SCUTKEY_END ); return S; } FORTRAN_SUBR ( MMDB_FCIF_CREATE, mmdb_fcif_create, ( // lengths-at-end list fpstr DataName, // file name int DataName_len // fortran-hidden length of DataName ), ( // lengths-in-structure list fpstr DataName ), ( // lengths-follow list fpstr DataName, int DataName_len ) ) { char S[500]; if (mmCIFData) delete mmCIFData; mmCIFData = new mmcif::Data ( makeString(S,sizeof(S), FTN_STR(DataName),FTN_LEN(DataName)) ); } void MMDB_CCIF_Create ( pstr DataName ) { if (mmCIFData) delete mmCIFData; mmCIFData = new mmcif::Data ( DataName ); } FORTRAN_SUBR ( MMDB_FCIF_WRITE, mmdb_fcif_write, ( // lengths-at-end list fpstr FileName, // file name int * iRet, // return code int FileName_len // fortran-hidden length of FileName ), ( // lengths-in-structure list fpstr FileName, int *iRet ), ( // lengths-follow list fpstr FileName, int FileName_len, int * iRet ) ) { pstr S; if (!mmCIFData) *iRet = -1000; else { S = new char[FTN_LEN(FileName)+10]; if (mmCIFData->WriteMMCIFData(makeString(S,FTN_LEN(FileName)+5, FTN_STR(FileName),FTN_LEN(FileName)))) *iRet = 0; else *iRet = 1; delete[] S; } } int MMDB_CCIF_Write ( pstr FileName ) { if (!mmCIFData) return -1000; else if (mmCIFData->WriteMMCIFData(FileName)) return 0; else return 1; } FORTRAN_SUBR ( MMDB_FCIF_PUTDATE, mmdb_fcif_putdate, ( // lengths-at-end list fpstr CatName, // category name fpstr Tag, // tag int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr CatName, fpstr Tag, int * iRet ), ( // lengths-follow list fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * iRet ) ) { char CN[200],TN[200]; if (!mmCIFData) *iRet = -1000; else *iRet = mmCIFData->PutDate ( makeString(CN,sizeof(CN), FTN_STR(CatName),FTN_LEN(CatName)), makeString(TN,sizeof(TN), FTN_STR(Tag),FTN_LEN(Tag)) ); } int MMDB_CCIF_PutDate ( pstr CatName, pstr Tag ) { if (!mmCIFData) return -1000; else return mmCIFData->PutDate ( CatName,Tag ); } FORTRAN_SUBR ( MMDB_FCIF_PUTDOT, mmdb_fcif_putdot, ( // lengths-at-end list fpstr CatName, // category name fpstr Tag, // tag int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr CatName, fpstr Tag, int * iRet ), ( // lengths-follow list fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * iRet ) ) { char CN[200],TN[200]; if (!mmCIFData) *iRet = -1000; else *iRet = mmCIFData->PutNoData ( mmcif::CIF_NODATA_DOT, makeString(CN,sizeof(CN), FTN_STR(CatName),FTN_LEN(CatName)), makeString(TN,sizeof(TN), FTN_STR(Tag),FTN_LEN(Tag)) ); } int MMDB_CCIF_PutDot ( pstr CatName, pstr Tag ) { if (!mmCIFData) return -1000; else return mmCIFData->PutNoData ( mmcif::CIF_NODATA_DOT, CatName,Tag ); } FORTRAN_SUBR ( MMDB_FCIF_PUTQUESTION, mmdb_fcif_putquestion, ( // lengths-at-end list fpstr CatName, // category name fpstr Tag, // tag int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr CatName, fpstr Tag, int * iRet ), ( // lengths-follow list fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * iRet ) ) { char CN[200],TN[200]; if (!mmCIFData) *iRet = -1000; else *iRet = mmCIFData->PutNoData ( mmcif::CIF_NODATA_QUESTION, makeString(CN,sizeof(CN), FTN_STR(CatName),FTN_LEN(CatName)), makeString(TN,sizeof(TN), FTN_STR(Tag),FTN_LEN(Tag)) ); } int MMDB_CCIF_PutQuestion ( pstr CatName, pstr Tag ) { if (!mmCIFData) return -1000; else return mmCIFData->PutNoData ( mmcif::CIF_NODATA_QUESTION, CatName,Tag ); } FORTRAN_SUBR ( MMDB_FCIF_PUTSTRING, mmdb_fcif_putstring, ( // lengths-at-end list fpstr Data, // data string to store fpstr CatName, // category name fpstr Tag, // tag int * iRet, // return code int Data_len, // fortran-hidden length of Data int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr Data, fpstr CatName, fpstr Tag, int * iRet ), ( // lengths-follow list fpstr Data, int Data_len, fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * iRet ) ) { char CN[200],TN[200]; pstr S; if (!mmCIFData) *iRet = -1000; else { S = new char[FTN_LEN(Data)+10]; *iRet = mmCIFData->PutString ( makeString(S,FTN_LEN(Data)+5, FTN_STR(Data),FTN_LEN(Data)), makeString(CN,sizeof(CN), FTN_STR(CatName),FTN_LEN(CatName)), makeString(TN,sizeof(TN), FTN_STR(Tag),FTN_LEN(Tag)) ); delete[] S; } } int MMDB_CCIF_PutString ( pstr Data, pstr CatName, pstr Tag ) { if (!mmCIFData) return -1000; else return mmCIFData->PutString ( Data,CatName,Tag ); } FORTRAN_SUBR ( MMDB_FCIF_PUTREAL, mmdb_fcif_putreal, ( // lengths-at-end list apireal * V, // real value to store fpstr CatName, // category name fpstr Tag, // tag int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list apireal * V, fpstr CatName, fpstr Tag, int * iRet ), ( // lengths-follow list apireal * V, fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * iRet ) ) { char CN[200],TN[200]; if (!mmCIFData) *iRet = -1000; else *iRet = mmCIFData->PutReal ( *V, makeString(CN,sizeof(CN), FTN_STR(CatName),FTN_LEN(CatName)), makeString(TN,sizeof(TN), FTN_STR(Tag),FTN_LEN(Tag)) ); } int MMDB_CCIF_PutReal ( realtype V, pstr CatName, pstr Tag ) { if (!mmCIFData) return -1000; else return mmCIFData->PutReal ( V,CatName,Tag ); } FORTRAN_SUBR ( MMDB_FCIF_PUTINTEGER, mmdb_fcif_putinteger, ( // lengths-at-end list int * I, // integer value to store fpstr CatName, // category name fpstr Tag, // tag int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list int * I, fpstr CatName, fpstr Tag, int * iRet ), ( // lengths-follow list int * I, fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * iRet ) ) { char CN[200],TN[200]; if (!mmCIFData) *iRet = -1000; else *iRet = mmCIFData->PutInteger ( *I, makeString(CN,sizeof(CN), FTN_STR(CatName),FTN_LEN(CatName)), makeString(TN,sizeof(TN), FTN_STR(Tag),FTN_LEN(Tag)) ); } int MMDB_CCIF_PutInteger ( int I, pstr CatName, pstr Tag ) { if (!mmCIFData) return -1000; else return mmCIFData->PutInteger ( I,CatName,Tag ); } FORTRAN_SUBR ( MMDB_FCIF_PUTLOOPDOT, mmdb_fcif_putloopdot, ( // lengths-at-end list fpstr CatName, // category name fpstr Tag, // tag int * nrow, // row number int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr CatName, fpstr Tag, int * nrow, int * iRet ), ( // lengths-follow list fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * nrow, int * iRet ) ) { char CN[200],TN[200]; if (!mmCIFData) *iRet = -1000; else *iRet = mmCIFData->PutLoopNoData ( mmcif::CIF_NODATA_DOT, makeString(CN,sizeof(CN), FTN_STR(CatName),FTN_LEN(CatName)), makeString(TN,sizeof(TN), FTN_STR(Tag),FTN_LEN(Tag)),*nrow ); } int MMDB_CCIF_PutLoopDot ( pstr CatName, pstr Tag, int nrow ) { if (!mmCIFData) return -1000; else return mmCIFData->PutLoopNoData ( mmcif::CIF_NODATA_DOT, CatName,Tag,nrow ); } FORTRAN_SUBR ( MMDB_FCIF_PUTLOOPQUESTION, mmdb_fcif_putloopquestion, ( // lengths-at-end list fpstr CatName, // category name fpstr Tag, // tag int * nrow, // row number int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr CatName, fpstr Tag, int * nrow, int * iRet ), ( // lengths-follow list fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * nrow, int * iRet ) ) { char CN[200],TN[200]; if (!mmCIFData) *iRet = -1000; else *iRet = mmCIFData->PutLoopNoData ( mmcif::CIF_NODATA_QUESTION, makeString(CN,sizeof(CN), FTN_STR(CatName),FTN_LEN(CatName)), makeString(TN,sizeof(TN), FTN_STR(Tag),FTN_LEN(Tag)),*nrow ); } int MMDB_CCIF_PutLoopQuestion ( pstr CatName, pstr Tag, int nrow ) { if (!mmCIFData) return -1000; else return mmCIFData->PutLoopNoData ( mmcif::CIF_NODATA_QUESTION, CatName,Tag,nrow ); } FORTRAN_SUBR ( MMDB_FCIF_PUTLOOPSTRING, mmdb_fcif_putloopstring, ( // lengths-at-end list fpstr Data, // data string to store fpstr CatName, // category name fpstr Tag, // tag int * nrow, // row number int * iRet, // return code int Data_len, // fortran-hidden length of Data int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list fpstr Data, fpstr CatName, fpstr Tag, int * nrow, int * iRet ), ( // lengths-follow list fpstr Data, int Data_len, fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * nrow, int * iRet ) ) { char CN[200],TN[200]; pstr S; if (!mmCIFData) *iRet = -1000; else { S = new char[FTN_LEN(Data)+10]; *iRet = mmCIFData->PutLoopString ( makeString(S,FTN_LEN(Data)+5, FTN_STR(Data),FTN_LEN(Data)), makeString(CN,sizeof(CN), FTN_STR(CatName),FTN_LEN(CatName)), makeString(TN,sizeof(TN), FTN_STR(Tag),FTN_LEN(Tag)),*nrow ); delete[] S; } } int MMDB_CCIF_PutLoopString ( pstr Data, pstr CatName, pstr Tag, int nrow ) { if (!mmCIFData) return -1000; else return mmCIFData->PutLoopString ( Data,CatName,Tag,nrow ); } FORTRAN_SUBR ( MMDB_FCIF_PUTLOOPREAL, mmdb_fcif_putloopreal, ( // lengths-at-end list apireal * V, // real value to store fpstr CatName, // category name fpstr Tag, // tag int * nrow, // row number int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list apireal * V, fpstr CatName, fpstr Tag, int * nrow, int * iRet ), ( // lengths-follow list apireal * V, fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * nrow, int * iRet ) ) { char CN[200],TN[200]; if (!mmCIFData) *iRet = -1000; else *iRet = mmCIFData->PutLoopReal ( *V, makeString(CN,sizeof(CN), FTN_STR(CatName),FTN_LEN(CatName)), makeString(TN,sizeof(TN), FTN_STR(Tag),FTN_LEN(Tag)),*nrow ); } int MMDB_CCIF_PutLoopReal ( realtype V, pstr CatName, pstr Tag, int nrow ) { if (!mmCIFData) return -1000; else return mmCIFData->PutLoopReal ( V,CatName,Tag,nrow ); } FORTRAN_SUBR ( MMDB_FCIF_PUTLOOPINTEGER, mmdb_fcif_putloopinteger, ( // lengths-at-end list int * I, // integer value to store fpstr CatName, // category name fpstr Tag, // tag int * nrow, // row number int * iRet, // return code int CatName_len, // fortran-hidden length of CatName int Tag_len // fortran-hidden length of Tag ), ( // lengths-in-structure list int * I, fpstr CatName, fpstr Tag, int * nrow, int * iRet ), ( // lengths-follow list int * I, fpstr CatName, int CatName_len, fpstr Tag, int Tag_len, int * nrow, int * iRet ) ) { char CN[200],TN[200]; if (!mmCIFData) *iRet = -1000; else *iRet = mmCIFData->PutLoopInteger ( *I, makeString(CN,sizeof(CN), FTN_STR(CatName),FTN_LEN(CatName)), makeString(TN,sizeof(TN), FTN_STR(Tag),FTN_LEN(Tag)),*nrow ); } int MMDB_CCIF_PutLoopInteger ( int I, pstr CatName, pstr Tag, int nrow ) { if (!mmCIFData) return -1000; else return mmCIFData->PutLoopInteger ( I,CatName,Tag,nrow ); } mmdb2-2.0.5/mmdb2/mmdb_tables.h0000664000175000017500000001044212571573314013076 00000000000000// $Id: mmdb_tables.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 24.07.15 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_Tables // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // // **** Namespace : mmdb:: // // **** Functions : // ~~~~~~~~~~~ // // **** Constants : AName ( array of 2-character atom names ) // ~~~~~~~~~~~ HAName ( array of 2=character heteroatom names ) // RName ( 3-characters amino acid names ) // RName1 ( 1-characters amino acid names ) // // // (C) E. Krissinel 2000-2015 // // ================================================================= // #ifndef __MMDB_Tables__ #define __MMDB_Tables__ #include "mmdb_mattype.h" namespace mmdb { // ================================================================= const int nElementNames = 117; const int nElementMetals = 91; const int nHydAtomNames = 14; extern cpstr const ElementName [nElementNames]; extern cpstr const ElementMetal [nElementMetals]; extern cpstr const HydAtomName [nHydAtomNames]; extern realtype const MolecWeight [nElementNames]; extern realtype const CovalentRadius[nElementNames]; extern realtype const VdWaalsRadius [nElementNames]; extern realtype const IonicRadius [nElementNames]; extern bool isMetal ( cpstr element ); const int ELEMENT_UNKNOWN = -1; extern int getElementNo ( cpstr element ); extern realtype getMolecWeight ( cpstr element ); extern realtype getCovalentRadius ( cpstr element ); extern realtype getVdWaalsRadius ( cpstr element ); const int nResNames = 26; extern cpstr const ResidueName [nResNames]; extern char const ResidueName1[nResNames]; extern int getResidueNo ( cpstr resName ); const realtype NAvogadro = 6.02214129e23; const int nSolventNames = 12; const int nAminoacidNames = 23; const int nNucleotideNames = 24; DefineStructure(AAProperty); struct AAProperty { char name[4]; realtype hydropathy; realtype charge; realtype relSolvEnergy; }; extern AAProperty const AAProperties[nAminoacidNames]; extern int const AASimilarity[nAminoacidNames][nAminoacidNames]; extern int GetAAPIndex ( cpstr resName ); // 0..nAminoacidNames-1 extern realtype GetAAHydropathy ( cpstr resName ); // -4.5...+4.5 extern realtype GetAACharge ( cpstr resName ); extern realtype GetAASolvationEnergy ( cpstr resName ); extern int GetAASimilarity ( cpstr resName1, cpstr resName2 ); // 0..5 extern cpstr const StdSolventName[nSolventNames]; extern cpstr const NucleotideName[nNucleotideNames]; extern bool isSolvent ( cpstr resName ); extern bool isAminoacid ( cpstr resName ); extern bool isNucleotide ( cpstr resName ); extern int isDNARNA ( cpstr resName ); // 0,1(DNA),2(RNA) extern bool isSugar ( cpstr resName ); extern void Get1LetterCode ( cpstr res3name, pstr res1code ); extern void Get1LetterCode ( cpstr res3name, char & res1code ); extern void Get3LetterCode ( cpstr res1name, pstr res3code ); } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_rwbrook.cpp0000664000175000017500000032501012473604423013641 00000000000000// $Id: mmdb_rwbrook.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2008. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 16.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_RWBrook // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB), "new rwbrook" // ~~~~~~~~~ // **** Functions : mmdb_f_init_ ( initializer ) // ~~~~~~~~~~~ mmdb_f_quit_ ( disposer ) // autoserials_ ( switch to the autoserials regime ) // setreadcoords_ ( switch for reading coordinates ) // simrwbrook_ ( simulates old RWBROOK printout ) // mmdb_f_openl_ ( associates a unit with a file ) // mmdb_f_open_ ( associates a unit with a file ) // mmdb_f_copy_ ( copies contents of units ) // mmdb_f_delete_ ( deletes part of a unit ) // mmdb_f_settype_ ( changes type of file and r/w mode ) // mmdb_f_setname_ ( changes file name ) // mmdb_f_write_ ( writes a data structure into file ) // mmdb_f_close_ ( closes and disposes a data str-re ) // mmdb_f_advance_ ( advances the internal pointer ) // mmdb_f_rewd_ ( sets internal pointer on the top ) // mmdb_f_bksp_ ( shifts int-l pointer 1 atom back ) // mmdb_f_atom_ ( reads/writes atom properties ) // mmdb_f_coord_ ( reads/writes atom coordinates ) // mmdb_f_setcell_ ( sets the crystal cell parameters ) // mmdb_f_wbspgrp_ ( sets the space group ) // mmdb_f_rbspgrp_ ( gets the space group ) // mmdb_f_wbcell_ ( sets the crystal cell parameters ) // mmdb_f_rbcell_ ( gets the crystal cell parameters ) // mmdb_f_rbcelln_ ( gets the crystal cell parameters ) // mmdb_f_rbrcel_ ( gets the recipricol cell ) // mmdb_f_rborf_ ( returns or fill transf. matrices ) // mmdb_f_orthmat_ ( calc. standard othogonalisations ) // mmdb_f_cvanisou_ ( converts between cryst-c units ) // mmdb_f_wremark_ ( writes a remark statement ) // mmdb_f_setter // mmdb_f_sethet // mmdb_f_getnofncsmates_ // rberrstop_ ( error messenger ) // rbcheckerr_ ( a simple error messenger ) // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include "string.h" #include "stdlib.h" #include "math.h" #include "mmdb_rwbrook.h" #include "mmdb_manager.h" #include "mmdb_tables.h" #include "hybrid_36.h" // ========================== Channel =========================== DefineClass(Channel) class Channel { public : int nUnit; // unit number int nType; // unit type: 0- PDB; 1- CIF; 2- binary int nRead; // 0: input, 1: output mmdb::PManager MMDBManager; // MMDB manager mmdb::pstr FName; // file name int fPos; // "position" in the file int ErrCode; // error code of last operation bool FAutoSer; // autoserials flag for reading PDB bool FReadCoords; // flag to read coordinate section bool FSimRWBROOK; // flag to simulate old RWBROOK's printout Channel (); ~Channel(); void Dispose(); void Init (); void SetFileType ( mmdb::pstr FType ); void SetFileName ( mmdb::pstr FileName, int FNameLen ); void IdentifyFile( mmdb::pstr ExistingFName ); bool EndOfFile (); mmdb::PAtom * GetAtomArray(); mmdb::PAtom GetAtomI ( int index ); mmdb::PCryst GetCryst (); bool areCrystMatrices(); void Frac2Orth ( mmdb::realtype x, mmdb::realtype y, mmdb::realtype z, mmdb::realtype & xx, mmdb::realtype & yy, mmdb::realtype & zz ); void Orth2Frac ( mmdb::realtype x, mmdb::realtype y, mmdb::realtype z, mmdb::realtype & xx, mmdb::realtype & yy, mmdb::realtype & zz ); void Cryst2Orth ( mmdb::rvector U ); void Orth2Cryst ( mmdb::rvector U ); int SetCell ( mmdb::realtype cell_a, mmdb::realtype cell_b, mmdb::realtype cell_c, mmdb::realtype cell_alpha, mmdb::realtype cell_beta, mmdb::realtype cell_gamma, int OrthCode ); int PutCell ( mmdb::realtype cell_a, mmdb::realtype cell_b, mmdb::realtype cell_c, mmdb::realtype cell_alpha, mmdb::realtype cell_beta, mmdb::realtype cell_gamma, int OrthCode ); int SetSpGroup ( mmdb::pstr spGroup ); int GetSpGroup ( mmdb::pstr spGroup ); int GetCell ( mmdb::realtype & cell_a, mmdb::realtype & cell_b, mmdb::realtype & cell_c, mmdb::realtype & cell_alpha, mmdb::realtype & cell_beta, mmdb::realtype & cell_gamma, mmdb::realtype & cell_v, int & OrthCode ); int GetRCell ( mmdb::realtype & cell_as, mmdb::realtype & cell_bs, mmdb::realtype & cell_cs, mmdb::realtype & cell_alphas, mmdb::realtype & cell_betas, mmdb::realtype & cell_gammas, mmdb::realtype & cell_vs ); int GetNumberOfNCSMates(); // Returns the number of // NCS mates not given in // the file (iGiven==0) void MakeCoordStructure(); void Read (); void Write(); void GetInputBuffer ( mmdb::pstr Line, int & count ); protected : void TranslateError(); }; Channel::Channel() { Init(); } Channel::~Channel() { Dispose(); } void Channel::Init() { nUnit = -1; nType = -1; nRead = 0; MMDBManager = NULL; FName = NULL; ErrCode = 0; fPos = 0; FAutoSer = false; FReadCoords = true; FSimRWBROOK = false; } void Channel::Dispose() { if (MMDBManager) delete MMDBManager; if (FName) delete[] FName; MMDBManager = NULL; FName = NULL; nUnit = -1; nType = -1; nRead = 0; ErrCode = 0; fPos = 0; } void Channel::SetFileType ( mmdb::pstr FType ) { switch (FType[0]) { default : case ' ' : if (nRead==0) nType = -1; // auto at reading else if (MMDBManager) nType = MMDBManager->GetFileType(); // auto at writing else nType = -1; break; case 'P' : nType = 0; break; // PDB case 'C' : nType = 1; break; // CIF case 'B' : nType = 2; break; // BIN } } void Channel::IdentifyFile ( mmdb::pstr ExistingFName ) { if (nType==-1) { if (ExistingFName) { if (mmdb::isMMDBBIN(ExistingFName)==0) nType = 2; else if (mmdb::isPDB(ExistingFName,mmdb::io::GZM_CHECK,true)==0) nType = 0; else if (mmdb::mmcif::isCIF(ExistingFName)==0) nType = 1; else nType = -2; // unidentified } else { if (MMDBManager) { if (MMDBManager->GetFileType()<0) nType = 0; // PDB else nType = MMDBManager->GetFileType(); // same as it was on last input } else nType = 0; } } } void Channel::SetFileName ( mmdb::pstr FileName, int FNameLen ) { if (FName) delete[] FName; FName = new char[FNameLen+1]; strncpy ( FName,FileName,FNameLen ); FName[FNameLen] = char(0); } void Channel::MakeCoordStructure() { if (MMDBManager) MMDBManager->Delete ( mmdb::MMDBFCM_All ); else { MMDBManager = new mmdb::Manager(); MMDBManager->SetFlag ( mmdb::MMDBF_AllowDuplChainID ); } } int Channel::GetNumberOfNCSMates() { // Returns the number of NCS mates not given in the file (iGiven==0) if (!MMDBManager) return RWBERR_NoData; return MMDBManager->GetNumberOfNCSMates(); } void Channel::Read() { int RC; ErrCode = -2; if (!FName) return; MakeCoordStructure(); IdentifyFile ( FName ); if (FAutoSer) MMDBManager->SetFlag ( mmdb::MMDBF_AutoSerials ); else MMDBManager->RemoveFlag ( mmdb::MMDBF_AutoSerials ); if (FReadCoords) MMDBManager->RemoveFlag ( mmdb::MMDBF_NoCoordRead ); else MMDBManager->SetFlag ( mmdb::MMDBF_NoCoordRead ); if (FSimRWBROOK) MMDBManager->SetFlag ( mmdb::MMDBF_SimRWBROOK ); else MMDBManager->RemoveFlag ( mmdb::MMDBF_SimRWBROOK ); MMDBManager->SetFlag ( mmdb::MMDBF_IgnoreDuplSeqNum | mmdb::MMDBF_IgnoreBlankLines | mmdb::MMDBF_IgnoreRemarks | mmdb::MMDBF_IgnoreNonCoorPDBErrors | mmdb::MMDBF_AllowDuplChainID ); switch (nType) { default : nType = 0; // nType=-2: unidentified: try PDB case 0 : ErrCode = MMDBManager->ReadPDBASCII ( FName ); break; case 1 : ErrCode = MMDBManager->ReadCIFASCII ( FName ); break; case 2 : ErrCode = MMDBManager->ReadMMDBF ( FName ); break; } if (ErrCode==0) { RC = MMDBManager->CrystReady(); switch (RC) { case mmdb::CRRDY_NoTransfMatrices : ErrCode = RWBERR_NoMatrices; break; case mmdb::CRRDY_Unchecked : ErrCode = RWBERR_NoCheck; break; case mmdb::CRRDY_Ambiguous : ErrCode = RWBERR_Disagreement; break; case mmdb::CRRDY_NoCell : ErrCode = RWBERR_NoCellParams; break; default : ; } } fPos = 0; // begining of the file TranslateError(); } void Channel::Write() { ErrCode = -3; if ((!MMDBManager) || (!FName)) return; IdentifyFile ( FName ); switch (nType) { default : nType = 0; // nType=-2: unidentified: make PDB case 0 : ErrCode = MMDBManager->WritePDBASCII ( FName ); break; case 1 : ErrCode = MMDBManager->WriteCIFASCII ( FName ); break; case 2 : ErrCode = MMDBManager->WriteMMDBF ( FName ); break; } // we do not change fPos here! TranslateError(); } void Channel::TranslateError() { switch (ErrCode) { case mmdb::Error_CantOpenFile : ErrCode = RWBERR_CantOpenFile; break; case mmdb::Error_UnrecognizedInteger : ErrCode = RWBERR_WrongInteger; break; case mmdb::Error_NoData : ErrCode = RWBERR_NotACIFFile; break; case mmdb::Error_WrongModelNo : ErrCode = RWBERR_WrongModelNo; break; case mmdb::Error_DuplicatedModel : ErrCode = RWBERR_DuplicatedModel; break; case mmdb::Error_ForeignFile : ErrCode = RWBERR_ForeignFile; break; case mmdb::Error_WrongEdition : ErrCode = RWBERR_WrongEdition; break; case mmdb::Error_ATOM_Unrecognized : ErrCode = RWBERR_ATOM_Unrecognd; break; case mmdb::Error_ATOM_AlreadySet : ErrCode = RWBERR_ATOM_AlreadySet; break; case mmdb::Error_ATOM_NoResidue : ErrCode = RWBERR_ATOM_NoResidue; break; case mmdb::Error_ATOM_Unmatch : ErrCode = RWBERR_ATOM_Unmatch; break; case mmdb::Error_NotACIFFile : ErrCode = RWBERR_NotACIFFile; break; case mmdb::Error_UnrecognCIFItems : ErrCode = RWBERR_UnrecognCIFItems; break; case mmdb::Error_MissingCIFField : ErrCode = RWBERR_MissingCIFField; break; case mmdb::Error_EmptyCIFLoop : ErrCode = RWBERR_EmptyCIFLoop; break; case mmdb::Error_UnexpEndOfCIF : ErrCode = RWBERR_UnexpEndOfCIF; break; case mmdb::Error_MissgCIFLoopField : ErrCode = RWBERR_MissgCIFLoopField; break; case mmdb::Error_NotACIFStructure : ErrCode = RWBERR_NotACIFStructure; break; case mmdb::Error_NotACIFLoop : ErrCode = RWBERR_NotACIFLoop; break; case mmdb::Error_UnrecognizedReal : ErrCode = RWBERR_WrongReal; break; case mmdb::Error_Ok : ErrCode = RWBERR_Ok; break; case mmdb::Error_WrongChainID : ErrCode = RWBERR_WrongChainID; break; case mmdb::Error_WrongEntryID : ErrCode = RWBERR_WrongEntryID; break; case mmdb::Error_SEQRES_serNum : ErrCode = RWBERR_SEQRES_serNum; break; case mmdb::Error_SEQRES_numRes : ErrCode = RWBERR_SEQRES_numRes; break; case mmdb::Error_SEQRES_extraRes : ErrCode = RWBERR_SEQRES_exraRes; break; case mmdb::Error_NCSM_Unrecognized : ErrCode = RWBERR_NCSM_Unrecogn; break; case mmdb::Error_NCSM_AlreadySet : ErrCode = RWBERR_NCSM_AlreadySet; break; case mmdb::Error_NCSM_WrongSerial : ErrCode = RWBERR_NCSM_WrongSerial; break; case mmdb::Error_NCSM_UnmatchIG : ErrCode = RWBERR_NCSM_UnmatchIG; break; case mmdb::Error_NoModel : ErrCode = RWBERR_NoModel; break; case mmdb::Error_NoSheetID : ErrCode = RWBERR_NoSheetID; break; case mmdb::Error_WrongSheetID : ErrCode = RWBERR_WrongSheetID; break; case mmdb::Error_WrongStrandNo : ErrCode = RWBERR_WrongStrandNo; break; case mmdb::Error_WrongNumberOfStrands : ErrCode = RWBERR_WrongNofStrands; break; case mmdb::Error_WrongSheetOrder : ErrCode = RWBERR_WrongSheetOrder; break; case mmdb::Error_HBondInconsistency : ErrCode = RWBERR_HBondInconsis; break; case mmdb::Error_EmptyResidueName : ErrCode = RWBERR_EmptyResidueName; break; case mmdb::Error_DuplicateSeqNum : ErrCode = RWBERR_DuplicateSeqNum; break; case mmdb::Error_NoLogicalName : ErrCode = RWBERR_NoLogicalName; break; case mmdb::Error_GeneralError1 : ErrCode = RWBERR_GeneralError1; break; default : ; } } bool Channel::EndOfFile() { int nA; if (MMDBManager) { nA = MMDBManager->GetNumberOfAtoms(); if (fPos>nA) { fPos = nA+1; return true; } } else return true; return false; } mmdb::PAtom * Channel::GetAtomArray() { if (MMDBManager) return MMDBManager->GetAtomArray(); else return NULL; } mmdb::PAtom Channel::GetAtomI ( int index ) { // returns index-th atom, as counted from the // top of file if (MMDBManager) return MMDBManager->GetAtomI ( index ); else return NULL; } mmdb::PCryst Channel::GetCryst() { if (MMDBManager) return MMDBManager->GetCrystData(); else return NULL; } bool Channel::areCrystMatrices() { if (MMDBManager) return MMDBManager->isTransfMatrix(); else return false; } void Channel::Frac2Orth ( mmdb::realtype x, mmdb::realtype y, mmdb::realtype z, mmdb::realtype & xx, mmdb::realtype & yy, mmdb::realtype & zz ) { if (MMDBManager) MMDBManager->Frac2Orth ( x,y,z,xx,yy,zz ); else { xx = x; yy = y; zz = z; } } void Channel::Orth2Frac ( mmdb::realtype x, mmdb::realtype y, mmdb::realtype z, mmdb::realtype & xx, mmdb::realtype & yy, mmdb::realtype & zz ) { if (MMDBManager) MMDBManager->Orth2Frac ( x,y,z,xx,yy,zz ); else { xx = x; yy = y; zz = z; } } void Channel::Cryst2Orth ( mmdb::rvector U ) { if (MMDBManager) MMDBManager->GetCrystData()->Cryst2Orth ( U ); } void Channel::Orth2Cryst ( mmdb::rvector U ) { if (MMDBManager) MMDBManager->GetCrystData()->Orth2Cryst ( U ); } int Channel::PutCell ( mmdb::realtype cell_a, mmdb::realtype cell_b, mmdb::realtype cell_c, mmdb::realtype cell_alpha, mmdb::realtype cell_beta, mmdb::realtype cell_gamma, int OrthCode ) { if (MMDBManager) { mmdb::PCryst cryst = MMDBManager->GetCrystData(); cryst->PutCell ( cell_a,cell_b,cell_c, cell_alpha,cell_beta,cell_gamma, OrthCode ); if ((cell_a!=0.0) || (OrthCode>0)) { if (cryst->CellCheck & mmdb::CCHK_Disagreement) return RWBERR_Disagreement; if (cryst->CellCheck & mmdb::CCHK_NoOrthCode) return RWBERR_NoOrthCode; if (cryst->CellCheck & mmdb::CCHK_Unchecked) return RWBERR_NoCheck; } return RWBERR_Ok; } else return RWBERR_NoFile; } int Channel::SetCell ( mmdb::realtype cell_a, mmdb::realtype cell_b, mmdb::realtype cell_c, mmdb::realtype cell_alpha, mmdb::realtype cell_beta, mmdb::realtype cell_gamma, int OrthCode ) { if (MMDBManager) { mmdb::PCryst cryst = MMDBManager->GetCrystData(); cryst->SetCell ( cell_a,cell_b,cell_c, cell_alpha,cell_beta,cell_gamma, OrthCode ); if (cryst->CellCheck & mmdb::CCHK_Disagreement) return RWBERR_Disagreement; if (cryst->CellCheck & mmdb::CCHK_NoOrthCode) return RWBERR_NoOrthCode; if (cryst->CellCheck & mmdb::CCHK_Unchecked) return RWBERR_NoCheck; return RWBERR_Ok; } else return RWBERR_NoFile; } int Channel::SetSpGroup ( mmdb::pstr spGroup ) { if (MMDBManager) { MMDBManager->SetSpaceGroup(spGroup); return RWBERR_Ok; } else return RWBERR_NoFile; } int Channel::GetSpGroup ( mmdb::pstr spGroup ) { if (MMDBManager) { mmdb::PCryst cryst = MMDBManager->GetCrystData(); if (cryst->WhatIsSet & mmdb::CSET_SpaceGroup) strcpy ( spGroup,cryst->spaceGroup ); else strcpy ( spGroup," " ); return RWBERR_Ok; } else return RWBERR_NoFile; } int Channel::GetCell ( mmdb::realtype & cell_a, mmdb::realtype & cell_b, mmdb::realtype & cell_c, mmdb::realtype & cell_alpha, mmdb::realtype & cell_beta, mmdb::realtype & cell_gamma, mmdb::realtype & cell_v, int & OrthCode ) { if (MMDBManager) { mmdb::PCryst cryst = MMDBManager->GetCrystData(); cell_a = cryst->a; cell_b = cryst->b; cell_c = cryst->c; cell_alpha = cryst->alpha; cell_beta = cryst->beta; cell_gamma = cryst->gamma; cell_v = cryst->Vol; OrthCode = cryst->NCode; if (!(cryst->WhatIsSet & mmdb::CSET_CellParams)) return RWBERR_NoCellParams; if (!(cryst->WhatIsSet & mmdb::CSET_Transforms)) return RWBERR_NoCheck; // if (MMDBManager->Cryst.CellCheck & mmdb::CCHK_NoOrthCode) // return RWBERR_NoOrthCode; return RWBERR_Ok; } else return RWBERR_NoFile; } int Channel::GetRCell ( mmdb::realtype & cell_as, mmdb::realtype & cell_bs, mmdb::realtype & cell_cs, mmdb::realtype & cell_alphas, mmdb::realtype & cell_betas, mmdb::realtype & cell_gammas, mmdb::realtype & cell_vs ) { if (MMDBManager) { mmdb::PCryst cryst = MMDBManager->GetCrystData(); cryst->GetRCell ( cell_as,cell_bs,cell_cs, cell_alphas,cell_betas,cell_gammas, cell_vs ); if (!(cryst->WhatIsSet & mmdb::CSET_CellParams)) return RWBERR_NoCellParams; if (!(cryst->WhatIsSet & mmdb::CSET_Transforms)) return RWBERR_NoCheck; return RWBERR_Ok; } else return RWBERR_NoFile; } void Channel::GetInputBuffer ( mmdb::pstr Line, int & count ) { if (MMDBManager) MMDBManager->GetInputBuffer ( Line,count ); else { strcpy ( Line,"" ); count = -1; } } // ======================== static data =========================== static int nChannels; // number of channels in processing static PChannel * channel; // array of channels in processing static bool FAutoSer; // flag to automatically generate // serial numbers at reading PDB files static bool FReadCoords; // flag to read coordinates; if set to // false, only the header of PDB file // is read static bool FSimRWBROOK; // flag to simulate old RWBROOK printout // as closely as possible static char LastFunc[80]; // name of the last called function static int LastUnit; // number of the last unit called static int LastRC; // last return code static int LastSer; // last serial number kept for // certain warnings // ======================== RWBrook API =========================== FORTRAN_SUBR ( MMDB_F_INIT, mmdb_f_init,(),(),() ) { mmdb::InitMatType(); nChannels = 0; channel = NULL; strcpy ( LastFunc,"MMDB_F_Init" ); LastUnit = -1; LastRC = 0; LastSer = 0; FAutoSer = false; FReadCoords = true; FSimRWBROOK = false; } FORTRAN_SUBR ( MMDB_F_QUIT, mmdb_f_quit,(),(),() ) { int i; for (i=0;inUnit==iUnit) return i; } return -1; } int MakeChannel ( int iUnit ) { // If iUnit-th unit already exists, it is // reinitialized. Otherwise the function looks // for a not used channel, and if there is one, // associates the new iUnit-th unit with it. // If there is no unused channels, the new one // is created and the new iUnit-th unit is // associated with it. // Returns serial number of the channel // associated with the newly reinitialized // or created unit. int i,m; PChannel * channel1; m = GetChannel ( iUnit ); if (m>=0) { // such channel already exists channel[m]->Dispose(); // clear it first channel[m]->Init(); // reinitialize it channel[m]->nUnit = iUnit; return m; } for (i=0;inUnit = iUnit; return m; } FORTRAN_SUBR ( MMDB_F_OPEN, mmdb_f_open, ( // lengths-at-end list mmdb::machine::fpstr FName, // file name mmdb::machine::fpstr RWStat, // "INPUT" or "OUTPUT" mmdb::machine::fpstr FType, // "PDB", "CIF", "BIN" or " " int * iUnit, // channel number int * iRet, // returns error code int FName_len, // fortran-hidden length of FName int RWStat_len, // fortran-hidden length of RWStat int FType_len // fortran-hidden length of FType ), ( // lengths-in-structure list mmdb::machine::fpstr FName, mmdb::machine::fpstr RWStat, mmdb::machine::fpstr FType, int * iUnit, int * iRet ), ( // lengths-follow list mmdb::machine::fpstr FName, int FName_len, mmdb::machine::fpstr RWStat, int RWStat_len, mmdb::machine::fpstr FType, int FType_len, int * iUnit, int * iRet ) ) { UNUSED_ARGUMENT(RWStat_len); UNUSED_ARGUMENT(FType_len); int k; char L[500]; #ifdef WIN32 mmdb::GetStrTerWin32File ( L,FTN_STR(FName),0,sizeof(L),FTN_LEN(FName) ); #else mmdb::GetStrTer ( L,FTN_STR(FName),0,sizeof(L),FTN_LEN(FName) ); #endif strcpy ( LastFunc,"MMDB_F_Open" ); LastUnit = *iUnit; if (*iUnit==0) { // generate unit number *iUnit = 1; do { k = GetChannel ( *iUnit ); if (k>=0) *iUnit = *iUnit+1; } while (k>=0); } // create channel k = MakeChannel ( *iUnit ); if (k>=0) { if (FTN_STR(RWStat)[0]=='I') { channel[k]->nRead = 0; channel[k]->FAutoSer = FAutoSer; channel[k]->FReadCoords = FReadCoords; channel[k]->FSimRWBROOK = FSimRWBROOK; } else channel[k]->nRead = 1; // store file name channel[k]->SetFileName ( L,sizeof(L) ); // store unit type channel[k]->SetFileType ( FTN_STR(FType) ); channel[k]->IdentifyFile( L ); if (FSimRWBROOK) { switch (channel[k]->nType) { default : printf ( " unknown-format" ); break; case 0 : printf ( " PDB" ); break; case 1 : printf ( " mmCIF" ); break; case 2 : printf ( " MMDB BINARY" ); } printf ( " file is being opened on unit %i",*iUnit ); if (FTN_STR(RWStat)[0]=='I') printf ( " for INPUT.\n\n" ); else printf ( " for OUTPUT.\n\n" ); } if (FTN_STR(RWStat)[0]=='I') { channel[k]->Read(); *iRet = channel[k]->ErrCode; } else { channel[k]->MakeCoordStructure(); channel[k]->fPos = 1; *iRet = RWBERR_Ok; } } else *iRet = RWBERR_NoChannel; LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_OPENL, mmdb_f_openl, ( // lengths-at-end list mmdb::machine::fpstr LName, // logical name mmdb::machine::fpstr RWStat, // "INPUT" or "OUTPUT" mmdb::machine::fpstr FType, // "PDB", "CIF", "BIN" or " " int * iUnit, // channel number int * iRet, // returns error code int LName_len, // fortran-hidden length of LName int RWStat_len, // fortran-hidden length of RWStat int FType_len // fortran-hidden length of FType ), ( // lengths-in-structure list mmdb::machine::fpstr LName, mmdb::machine::fpstr RWStat, mmdb::machine::fpstr FType, int * iUnit, int * iRet ), ( // lengths-follow list mmdb::machine::fpstr LName, int LName_len, mmdb::machine::fpstr RWStat, int RWStat_len, mmdb::machine::fpstr FType, int FType_len, int * iUnit, int * iRet ) ) { char L[200]; mmdb::pstr S; char_struct(FName) strcpy ( LastFunc,"MMDB_F_Openl" ); mmdb::GetStrTer ( L,FTN_STR(LName),0,sizeof(L),FTN_LEN(LName) ); S = getenv ( L ); if (S) { fill_char_struct(FName,S) } else if (FTN_STR(RWStat)[0]=='O') { // The user may not have assigned a logical // for output, so that the program should write file "XYZOUT". This // is allowed as a convenience when user is not really interested // in output file. fill_char_struct(FName,L) } else { *iRet = RWBERR_NoLogicalName; return; } printf ( "\n Logical name: %s File name: %s\n",L,FName ); FORTRAN_CALL ( MMDB_F_OPEN, mmdb_f_open, ( FName,RWStat,FType,iUnit,iRet, FName_len,RWStat_len,FType_len ), ( &FName,RWStat,FType,iUnit,iRet ), ( FName,FName_len,RWStat,RWStat_len, FType,FType_len,iUnit,iRet ) ); } FORTRAN_SUBR ( MMDB_F_COPY, mmdb_f_copy, ( // lengths-at-end list int * iUnit1, // destination unit int * iUnit2, // source unit int * copyKey, // copy key: // = 1 copy all // = 2 copy all except coordinates // = 3 copy title section only // = 4 copy crystallographic // section only // = 5 copy coordinate section only // any other value does not do anything int * iRet // return code: // =0 if success // =RWBERR_NoChannel if a unit // does not exist ), ( // lengths-in-structure list int * iUnit1, int * iUnit2, int * copyKey, int * iRet ), ( // lengths-follow list int * iUnit1, int * iUnit2, int * copyKey, int * iRet ) ) { int k1,k2; mmdb::COPY_MASK copyMask; strcpy ( LastFunc,"MMDB_F_Copy" ); LastUnit = *iUnit1; k1 = GetChannel ( LastUnit ); if (k1>=0) { if (channel[k1]->MMDBManager) { LastUnit = *iUnit2; k2 = GetChannel ( LastUnit ); if (k2>=0) { if (channel[k2]->MMDBManager) { switch (*copyKey) { case 1 : copyMask = mmdb::MMDBFCM_All; break; case 2 : copyMask = mmdb::MMDBFCM_Top; break; case 3 : copyMask = mmdb::MMDBFCM_Title; break; case 4 : copyMask = mmdb::MMDBFCM_Cryst; break; case 5 : copyMask = mmdb::MMDBFCM_Coord; break; default : copyMask = mmdb::MMDBFCM_None; } channel[k1]->MMDBManager->Copy ( channel[k2]->MMDBManager, copyMask ); *iRet = RWBERR_Ok; } else *iRet = RWBERR_NoFile; } else *iRet = RWBERR_NoChannel; } else *iRet = RWBERR_NoFile; } else *iRet = RWBERR_NoChannel; LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_DELETE, mmdb_f_delete, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" int * delKey, // delete key: // = 1 delete all // = 2 delete all except coordinates // = 3 delete title section only // = 4 delete crystallographic // section only // = 5 delete coordinate section only // any other value does not do anything int * iRet // return code: // =0 if success // =RWBERR_NoChannel if a unit // does not exist // =RWBERR_NoFile if a unit // was not opened ), ( // lengths-in-structure list int * iUnit, int * delKey, int * iRet ), ( // lengths-follow list int * iUnit, int * delKey, int * iRet ) ) { int k; mmdb::word delMask; strcpy ( LastFunc,"MMDB_F_Delete" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k>=0) { if (channel[k]->MMDBManager) { switch (*delKey) { case 1 : delMask = mmdb::MMDBFCM_All; break; case 2 : delMask = mmdb::MMDBFCM_Top; break; case 3 : delMask = mmdb::MMDBFCM_Title; break; case 4 : delMask = mmdb::MMDBFCM_Cryst; break; case 5 : delMask = mmdb::MMDBFCM_Coord; break; default : delMask = 0x0000; } channel[k]->MMDBManager->Delete ( delMask ); *iRet = RWBERR_Ok; } else *iRet = RWBERR_NoFile; } else *iRet = RWBERR_NoChannel; LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_SETTYPE, mmdb_f_settype, ( // lengths-at-end list int * iUnit, // unit number mmdb::machine::fpstr FType, // "PDB", "CIF", "BIN" or " " mmdb::machine::fpstr RWStat, // "INPUT" or "OUTPUT" int * iRet, // returns -1 if unit not found, // otherwise 0 int FType_len, // fortran-hidden length of FType int RWStat_len // fortran-hidden length of RWStat ), ( // lengths-in-structure list int * iUnit, mmdb::machine::fpstr FType, mmdb::machine::fpstr RWStat, int * iRet ), ( // length-follow list int * iUnit, mmdb::machine::fpstr FType, int FType_len, mmdb::machine::fpstr RWStat, int RWStat_len, int * iRet ) ) { UNUSED_ARGUMENT(FType_len); UNUSED_ARGUMENT(RWStat_len); int k; strcpy ( LastFunc,"MMDB_F_SetType" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k>=0) { // store unit type channel[k]->SetFileType ( FTN_STR(FType) ); // store unit mode if (FTN_STR(RWStat)[0]=='I') channel[k]->nRead = 0; else channel[k]->nRead = 1; *iRet = RWBERR_Ok; } else *iRet = RWBERR_NoChannel; LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_SETNAME, mmdb_f_setname, ( // lengths-at-end list int * iUnit, // unit number mmdb::machine::fpstr FName, // file name int * iRet, // returns -1 if unit not found, // otherwise 0 int FName_len // fortran-hidden length of FName ), ( // lengths-in-structure list int * iUnit, mmdb::machine::fpstr FName, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::fpstr FName, int FName_len, int * iRet ) ) { int k; strcpy ( LastFunc,"MMDB_F_SetName" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) *iRet = RWBERR_NoChannel; else { // store file name channel[k]->SetFileName ( FTN_STR(FName),FTN_LEN(FName) ); *iRet = RWBERR_Ok; } LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_WRITE, mmdb_f_write, ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ) ) { int k; strcpy ( LastFunc,"MMDB_F_Write" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) *iRet = RWBERR_NoChannel; else { channel[k]->Write(); *iRet = channel[k]->ErrCode; } LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_CLOSE, mmdb_f_close, ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ) ) { int k; strcpy ( LastFunc,"MMDB_F_Close" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) *iRet = RWBERR_NoChannel; else if (channel[k]->nRead==1) { channel[k]->Write(); *iRet = channel[k]->ErrCode; if (!(*iRet)) { delete channel[k]; channel[k] = NULL; } } else { delete channel[k]; channel[k] = NULL; *iRet = RWBERR_Ok; } LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_ADVANCE, mmdb_f_advance, ( // lengths-at-end list int * iUnit, // unit number int * iOut, // output echo file int * iTer, // FLAG =1, return iRet=1 if 'ter' card found // =0, do not return on 'ter' card int * iRet // =0 if normal return // =1 if return on 'ter' card (iTer=1) // =2 if return on end of file // =3 if return on 'hetatm' card // =RWBERR_NoChannel if unit does not exist // =RWBERR_NoAdvance if pointer was not // advanced ), ( // lengths-in-structure list int * iUnit, int * iOut, int * iTer, int * iRet ), ( // lengths-follow list int * iUnit, int * iOut, int * iTer, int * iRet ) ) { UNUSED_ARGUMENT(iOut); int k; mmdb::PAtom atom; strcpy ( LastFunc,"mmdb_f_advance" ); LastUnit = *iUnit; k = GetChannel ( *iUnit ); if (k<0) *iRet = RWBERR_NoChannel; else if (channel[k]->nRead==0) { // in the input file, try to get pointer on the next atom do { channel[k]->fPos++; // advance the pointer on Atom array if (channel[k]->EndOfFile()) { atom = NULL; break; } atom = channel[k]->GetAtomI ( channel[k]->fPos ); if (atom) { if ((atom->Ter) && (*iTer==0)) { // ignore 'ter' card if iTer is set to 0 atom = NULL; } } } while (!atom); if (!atom) *iRet = 2; // no atom found == end of file else if (atom->Ter) *iRet = 1; // 'ter' card encountered else if (atom->Het) *iRet = 3; // 'hetatm' card encountered else *iRet = 0; // advance ok; normal return } else { // in the output file, just advance the pointer if (channel[k]->fPos==0) { channel[k]->fPos++; *iRet = 0; } else { atom = channel[k]->GetAtomI ( channel[k]->fPos ); if (atom) { // the previous atom was set -- advance the pointer channel[k]->fPos++; *iRet = 0; } else // no atom was set; make no advancement *iRet = RWBERR_NoAdvance; } } LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_REWD, mmdb_f_rewd, ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ) ) { int k; strcpy ( LastFunc,"MMDB_F_Rewd" ); LastUnit = *iUnit; k = GetChannel ( *iUnit ); if (k>=0) { channel[k]->fPos = 0; if (channel[k]->nRead!=0) *iRet = RWBWAR_RewOutput; else *iRet = RWBERR_Ok; } else *iRet = RWBERR_NoChannel; LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_BKSP, mmdb_f_bksp, ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ) ) { int k; strcpy ( LastFunc,"MMDB_F_BkSp" ); LastUnit = *iUnit; k = GetChannel ( *iUnit ); if (k>=0) { *iRet = RWBERR_Ok; if (channel[k]->fPos==0) *iRet |= RWBWAR_FileTop; else channel[k]->fPos--; if (channel[k]->nRead!=0) *iRet |= RWBWAR_RewOutput; } else *iRet = RWBERR_NoChannel; LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_SEEK, mmdb_f_seek, ( // lengths-at-end list int * iUnit, // unit number int * fPos, // position to set int * iRet // return code: // 0 Ok // 1 'ter' card met // 2 end of file // 3 'hetatm' card met // <0 error: // RWBERR_NoChannel // iUnit was not // initialized // RWBERR_EmptyPointer // fPos-th position ), ( // lengths-in-structure list int * iUnit, int * fPos, int * iRet ), ( // lengths-follow list int * iUnit, int * fPos, int * iRet ) ) { int k; mmdb::PAtom atom; strcpy ( LastFunc,"MMDB_F_Seek" ); LastUnit = *iUnit; k = GetChannel ( *iUnit ); if (k<0) *iRet = RWBERR_NoChannel; else { // set the pointer channel[k]->fPos = mmdb::IMax(0,*fPos); if (*fPos==0) *iRet = RWBWAR_FileTop; else *iRet = RWBERR_Ok; if (channel[k]->nRead==0) { // in the input file, check the end-of-file state // and analyze the atom if (channel[k]->EndOfFile()) *iRet = 2; atom = channel[k]->GetAtomI ( channel[k]->fPos ); if (!atom) *iRet = RWBERR_EmptyPointer; // empty place else if (atom->Ter) *iRet = 1; // 'ter' card encountered else if (atom->Het) *iRet = 3; // 'hetatm' card encountered } // in the output file, there is nothing to do } LastRC = *iRet; } void Make_AN_ID_IZ ( mmdb::PAtom atom, mmdb::pstr AtNam, int AtNam_L, mmdb::pstr ID, int ID_L, int * IZ, int * iRet ) { char chrg[10]; int i,k; if (atom->Ter) { mmdb::strcpy_ns ( AtNam,mmdb::pstr(" "),AtNam_L ); mmdb::strcpy_ns ( ID ,mmdb::pstr(" "),ID_L ); *IZ = 7; } else { if (atom->name[0]==' ') mmdb::strcpy_ns ( AtNam,&(atom->name[1]),4 ); else mmdb::strcpy_ns ( AtNam,atom->name,4 ); // first try to identify the atom with the element name mmdb::strcpy_ns ( ID,atom->element,ID_L ); // not more than ID_L symbols // from element until but not including // the terminated null are copied into // ID, and the latter is padded with // spaces up to the length of ID_L if (ID_L>3) { // if length permits, add ID with atom charge // (always 2 symbols). atom->GetAtomCharge(chrg); ID[2] = chrg[0]; ID[3] = chrg[1]; } k = 0; while ((kelement[0]!=mmdb::ElementName[k][0]) || (atom->element[1]!=mmdb::ElementName[k][1]))) k++; if (k>=mmdb::nElementNames) { // no match for atom ID -- make sure to set it blank mmdb::strcpy_ns ( ID,mmdb::pstr(" "),ID_L ); // try to identify the atom using the atom name k = 0; while ((kname[0]!=mmdb::ElementName[k][0]) || (atom->name[1]!=mmdb::ElementName[k][1]))) k++; // try to identify a heteroatom i = 0; while ((i=mmdb::nElementNames)) { if ((atom->name[0]==mmdb::HydAtomName[i][0]) && (atom->name[1]==mmdb::HydAtomName[i][1])) k = 0; i++; } if (k>=mmdb::nElementNames) { // unknown or ambiguous formfactor k = -1; if ((atom->name[0]==' ') && (atom->name[1]=='A')) k = 6; if (k==-1) *iRet |= RWBWAR_UnkFormFactor; else *iRet |= RWBWAR_AmbFormFactor; } } *IZ = k+1; if (*IZ==0) mmdb::strcpy_ns ( ID,mmdb::pstr(" "),ID_L ); else { if (ID_L>3) { if (ID[0]==' ') { if ((AtNam[2]=='+') || (AtNam[2]=='-')) { ID[2] = AtNam[2]; ID[3] = AtNam[3]; } } else if ((ID[2]!='+') && (ID[2]!='-')) { ID[2] = ' '; ID[3] = ' '; } } mmdb::strcpy_ns ( ID,mmdb::ElementName[k],mmdb::IMin(2,ID_L) ); } } } FORTRAN_SUBR ( MMDB_F_ATOM, mmdb_f_atom, ( // lengths-at-end list int * iUnit, // unit number int * iSer, // atom serial number mmdb::machine::fpstr AtNam, // atom name (left justified) mmdb::machine::fpstr ResNam, // residue name mmdb::machine::fpstr ChnNam, // chain name int * iResN, // residue number as an integer mmdb::machine::fpstr ResNo, // residue number as character (input only) mmdb::machine::fpstr InsCod, // the insertion code mmdb::machine::fpstr AltCod, // the alternate conformation code mmdb::machine::fpstr segID, // segment ID int * IZ, // atomic number (input only, returned as // 7 from ambiguous atoms) mmdb::machine::fpstr ID, // atomic ID related to atomic number // (element symbol right justified), plus // the ionic state +2, +3 etc.. // int * iRet, // returns // RWBERR_NoChannel if iUnit was not // initialized // RWBERR_EmptyPointer if atom was not // advanced // RWBERR_Error1 internal error #1 // RWBERR_Error2 internal error #2 // RWBERR_Error3 internal error #3 // // >=0 : success, warning flags: // RWBWAR_WrongSerial if serial number // differs from the position // number in the file // RWBWAR_UnkFormFactor unknown formfactor // RWBWAR_AmbFormFactor ambiguous formfactor // int AtNam_len, // fortran-hidden length of AtNam int ResNam_len, // fortran-hidden length of ResNam int ChnNam_len, // fortran-hidden length of ChnNam int ResNo_len, // fortran-hidden length of ResNo int InsCod_len, // fortran-hidden length of InsCod int AltCod_len, // fortran-hidden length of AltCod int segID_len, // fortran-hidden length of SegID int ID_len // fortran-hidden length of ID ), ( // lengths-in-structure list int * iUnit, int * iSer, mmdb::machine::fpstr AtNam, mmdb::machine::fpstr ResNam, mmdb::machine::fpstr ChnNam, int * iResN, mmdb::machine::fpstr ResNo, mmdb::machine::fpstr InsCod, mmdb::machine::fpstr AltCod, mmdb::machine::fpstr segID, int * IZ, mmdb::machine::fpstr ID, int * iRet ), ( // lengths-follow list int * iUnit, int * iSer, mmdb::machine::fpstr AtNam, int AtNam_len, mmdb::machine::fpstr ResNam, int ResNam_len, mmdb::machine::fpstr ChnNam, int ChnNam_len, int * iResN, mmdb::machine::fpstr ResNo, int ResNo_len, mmdb::machine::fpstr InsCod, int InsCod_len, mmdb::machine::fpstr AltCod, int AltCod_len, mmdb::machine::fpstr segID, int segID_len, int * IZ, mmdb::machine::fpstr ID, int ID_len, int * iRet ) ) { int k,RC; mmdb::ChainID chainID; mmdb::ResName resName; mmdb::InsCode insCode; mmdb::AtomName atomName; mmdb::AltLoc altLoc; mmdb::SegID sgID; mmdb::Element element; mmdb::PAtom atom; char charge[10]; strcpy ( LastFunc,"MMDB_F_Atom" ); LastUnit = *iUnit; k = GetChannel ( *iUnit ); if (k<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } *iRet = RWBERR_Ok; if (channel[k]->nRead==0) { // reading the atom characteristics atom = channel[k]->GetAtomI ( channel[k]->fPos ); if (!atom) { // atom position was not advanced properly *iRet = RWBERR_EmptyPointer; LastRC = *iRet; return; } *iSer = atom->serNum; if (*iSer!=channel[k]->fPos) *iRet |= RWBWAR_WrongSerial; LastSer = *iSer; Make_AN_ID_IZ ( atom,FTN_STR(AtNam),FTN_LEN(AtNam), FTN_STR(ID),FTN_LEN(ID),IZ,iRet ); if (atom->residue) { mmdb::strcpy_ns ( FTN_STR(ResNam),atom->residue->name,FTN_LEN(ResNam) ); *iResN = atom->residue->seqNum; mmdb::PutInteger ( FTN_STR(ResNo),*iResN,mmdb::IMin(4,FTN_LEN(ResNo)) ); mmdb::strcpy_ns ( FTN_STR(InsCod),atom->residue->insCode,FTN_LEN(InsCod) ); mmdb::strcpy_ns ( &(FTN_STR(ResNo)[4]),FTN_STR(InsCod),FTN_LEN(ResNo)-4 ); mmdb::strcpy_ns ( FTN_STR(ChnNam),atom->GetChainID(),FTN_LEN(ChnNam) ); } else { mmdb::strcpy_ns ( FTN_STR(ResNam),mmdb::pstr(" "),FTN_LEN(ResNam) ); mmdb::strcpy_ns ( FTN_STR(ChnNam),mmdb::pstr(" ") ,FTN_LEN(ChnNam) ); *iResN = 0; mmdb::strcpy_ns ( FTN_STR(ResNo) ,mmdb::pstr("0") ,FTN_LEN(ResNo) ); mmdb::strcpy_ns ( FTN_STR(InsCod),mmdb::pstr(" ") ,FTN_LEN(InsCod) ); } mmdb::strcpy_ns ( FTN_STR(AltCod),atom->altLoc,FTN_LEN(AltCod) ); mmdb::strcpy_ns ( FTN_STR(segID) ,atom->segID ,FTN_LEN(segID) ); } else { // storing the atom characteristics if (!channel[k]->MMDBManager) { *iRet = RWBERR_Error1; // should never happen LastRC = *iRet; return; } mmdb::GetStrTer ( chainID,FTN_STR(ChnNam),1,sizeof(chainID),FTN_LEN(ChnNam) ); mmdb::GetStrTer ( resName,FTN_STR(ResNam),3,sizeof(resName),FTN_LEN(ResNam) ); mmdb::GetStrTer ( insCode,FTN_STR(InsCod),1,sizeof(insCode),FTN_LEN(InsCod) ); mmdb::GetStrTer ( altLoc ,FTN_STR(AltCod),1,sizeof(altLoc) ,FTN_LEN(AltCod) ); mmdb::GetStrTer ( sgID ,FTN_STR(segID) ,4,sizeof(sgID) ,FTN_LEN(segID) ); element[0] = FTN_STR(ID)[0]; element[1] = FTN_STR(ID)[1]; element[2] = char(0); if (FTN_LEN(ID)>3) { charge [0] = FTN_STR(ID)[2]; charge [1] = FTN_STR(ID)[3]; charge [2] = char(0); } else charge [0] = char(0); if (FTN_STR(ID)[0]==' ') { atomName[0] = char(0); // if ((FTN_STR(AtNam)[1]=='H') || // ((FTN_STR(AtNam)[1]=='D') && (FTN_STR(ID)[2]=='D'))) { // int i = 0; // while ((iMMDBManager->PutAtom ( channel[k]->fPos,*iSer, atomName,resName,chainID,*iResN, insCode,altLoc,sgID,element ); if (RC) { *iRet = RWBERR_Error2; // should never happen LastRC = *iRet; return; } mmdb::DelSpaces ( charge ); if (charge[0]) { atom = channel[k]->GetAtomI ( channel[k]->fPos ); if (!atom) { *iRet = RWBERR_EmptyPointer; // should never be so LastRC = *iRet; return; } atom->SetCharge ( charge ); } if (*iSer!=channel[k]->fPos) { *iRet |= RWBWAR_WrongSerial; // this is not the right thing at all atom = channel[k]->GetAtomI ( channel[k]->fPos ); if (!atom) { *iRet = RWBERR_EmptyPointer; // should never be so LastRC = *iRet; return; } // atom->serNum = *iSer; // - we allow for a mess in serials } LastSer = *iSer; } LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_SETTER, mmdb_f_setter, ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ) ) { int k; mmdb::PAtom atom; strcpy ( LastFunc,"MMDB_F_SetTer" ); LastUnit = *iUnit; k = GetChannel ( *iUnit ); if (k<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } atom = channel[k]->GetAtomI ( channel[k]->fPos ); *iRet = RWBERR_Ok; if (!atom) { *iRet = RWBERR_EmptyPointer; // atom position was not advanced properly LastRC = *iRet; return; } atom->Ter = true; atom->WhatIsSet |= mmdb::ASET_Coordinates; } FORTRAN_SUBR ( MMDB_F_SETHET, mmdb_f_sethet, ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ) ) { int k; mmdb::PAtom atom; strcpy ( LastFunc,"MMDB_F_SetHet" ); LastUnit = *iUnit; k = GetChannel ( *iUnit ); if (k<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } atom = channel[k]->GetAtomI ( channel[k]->fPos ); *iRet = RWBERR_Ok; if (!atom) { *iRet = RWBERR_EmptyPointer; // atom position was not advanced properly LastRC = *iRet; return; } atom->Het = true; atom->WhatIsSet |= mmdb::ASET_Coordinates; } FORTRAN_SUBR ( MMDB_F_GETHET, mmdb_f_gethet, ( int * iUnit, int * isHet, int * iRet ), ( int * iUnit, int * isHet, int * iRet ), ( int * iUnit, int * isHet, int * iRet ) ) { int k; mmdb::PAtom atom; strcpy ( LastFunc,"MMDB_F_GetHet" ); LastUnit = *iUnit; *isHet = 0; // no HETATM record k = GetChannel ( *iUnit ); if (k<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } atom = channel[k]->GetAtomI ( channel[k]->fPos ); *iRet = RWBERR_Ok; if (!atom) { *iRet = RWBERR_EmptyPointer; // atom position was not advance properly LastRC = *iRet; return; } if (atom->Het) *isHet = 1; // HETATM } // ------------------------------------------------------------------ // mmdb_f_getnofncsmates_(..) returns the number of NCS mates not // given in the file (iGiven=0). // // Negative returns N<0 mean an error. // // FORTRAN equivalent: subroutine MMDB_F_GetNofNCSMates ( iUnit,N ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,N FORTRAN_SUBR ( MMDB_F_GETNOFNCSMATES, mmdb_f_getnofncsmates, ( int * iUnit, int * N ), ( int * iUnit, int * N ), ( int * iUnit, int * N ) ) { int k; strcpy ( LastFunc,"mmdb_f_getnofncsmates" ); LastUnit = *iUnit; k = GetChannel ( *iUnit ); if (k<0) { *N = RWBERR_NoChannel; LastRC = *N; return; } *N = channel[k]->GetNumberOfNCSMates(); return; } FORTRAN_SUBR ( MMDB_F_COPYATOM, mmdb_f_copyatom, ( int * iUnit1, int * iUnit2, int * iRet ), ( int * iUnit1, int * iUnit2, int * iRet ), ( int * iUnit1, int * iUnit2, int * iRet ) ) { int k1,k2,RC; mmdb::PAtom atom; strcpy ( LastFunc,"mmdb_f_copyatom" ); LastUnit = *iUnit1; k1 = GetChannel ( *iUnit1 ); if (k1<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } k2 = GetChannel ( *iUnit2 ); if (k2<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } atom = channel[k1]->GetAtomI ( channel[k1]->fPos ); *iRet = RWBERR_Ok; if (!atom) { *iRet = RWBERR_EmptyPointer; // atom position was not advanced // properly LastRC = *iRet; return; } RC = channel[k2]->MMDBManager->PutAtom ( channel[k2]->fPos,atom, atom->serNum ); if (RC) { *iRet = RWBERR_Error2; // should never happen LastRC = *iRet; return; } LastSer = atom->serNum; } FORTRAN_SUBR ( MMDB_F_COORD, mmdb_f_coord, ( // lengths-at-end list int * iUnit, // unit number mmdb::machine::fpstr XFlag, // "F" or "O" flag for the fractional // or orthogonal coordinates x,y,z // for output files XFlag may also be // set to "HF" or "HO", where "F" and // "O" have the same meaning as before // and "H" indicates that the atom // should be marked as heteroatom mmdb::machine::fpstr BFlag , // "F" or "O" flag for temperature // factor in fractional or orthogonal // Us mmdb::machine::apireal * x, // x-coordinate mmdb::machine::apireal * y, // y-coordinate mmdb::machine::apireal * z, // z-coordinate mmdb::machine::apireal * occ, // occupancy mmdb::machine::apireal * BIso, // isotropic temperature factor mmdb::machine::apireal * U, // array(6) of the anisotr. t-factor int * iRet, // returns // RWBERR_NoChannel if iUnit was not // initialized // RWBERR_EmptyPointer if atom was not // advanced // RWBERR_NoMatrices if transformation // matrices are // undefined // RWBERR_NoCoordinates if coordinates were // not set in the atom // // >=0 : success, warning flags: // RWBERR_NoOccupancy if occupancy was // not set in the atom // RWBERR_NoTempFactor if temp. factor was // not set in the atom // int XFlag_len, // fortran-hidden length of XFlag int BFlag_len // fortran-hidden length of BFlag ), ( // lengths-in-structure list int * iUnit, mmdb::machine::fpstr XFlag, mmdb::machine::fpstr BFlag, mmdb::machine::apireal * x, mmdb::machine::apireal * y, mmdb::machine::apireal * z, mmdb::machine::apireal * occ, mmdb::machine::apireal * BIso, mmdb::machine::apireal * U, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::fpstr XFlag, int XFlag_len, mmdb::machine::fpstr BFlag, int BFlag_len, mmdb::machine::apireal * x, mmdb::machine::apireal * y, mmdb::machine::apireal * z, mmdb::machine::apireal * occ, mmdb::machine::apireal * BIso, mmdb::machine::apireal * U, int * iRet ) ) { UNUSED_ARGUMENT(XFlag_len); UNUSED_ARGUMENT(BFlag_len); mmdb::realtype AU[6]; mmdb::realtype xx,yy,zz; int k,i,m; mmdb::PAtom atom; strcpy ( LastFunc,"MMDB_F_Coord" ); LastUnit = *iUnit; k = GetChannel ( *iUnit ); if (k<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } atom = channel[k]->GetAtomI ( channel[k]->fPos ); *iRet = RWBERR_Ok; if (!atom) { *iRet = RWBERR_EmptyPointer; // atom position was not advanced properly LastRC = *iRet; return; } if ((FTN_STR(XFlag)[0]=='H') || (FTN_STR(XFlag)[0]=='h')) m = 1; else m = 0; if (channel[k]->nRead==0) { // reading the atomic coordinates if (atom->Ter) { *x = 0.0; *y = 0.0; *z = 0.0; *occ = 1.0; *BIso = 1.0; U[0] = 1.0; U[1] = 0.0; U[2] = 0.0; U[3] = 0.0; U[4] = 0.0; U[5] = 0.0; } else { if (atom->WhatIsSet & mmdb::ASET_Coordinates) { if ((FTN_STR(XFlag)[m]=='F') || (FTN_STR(XFlag)[m]=='f')) { // receive fractional coordinates if (channel[k]->areCrystMatrices()) { channel[k]->Orth2Frac ( atom->x,atom->y,atom->z,xx,yy,zz ); *x = (mmdb::machine::apireal)xx; *y = (mmdb::machine::apireal)yy; *z = (mmdb::machine::apireal)zz; } else { *x = (mmdb::machine::apireal)atom->x; *y = (mmdb::machine::apireal)atom->y; *z = (mmdb::machine::apireal)atom->z; *iRet = RWBERR_NoMatrices; } } else { // receive orthogonal coordinates *x = (mmdb::machine::apireal)atom->x; *y = (mmdb::machine::apireal)atom->y; *z = (mmdb::machine::apireal)atom->z; } } else { *x = 0.0; *y = 0.0; *z = 0.0; *iRet = RWBERR_NoCoordinates; } // calculate isotropic Uf from Uo, and convert it // if necessary if (atom->WhatIsSet & mmdb::ASET_Anis_tFac) { AU[0] = atom->u11; // this intermediate array is AU[1] = atom->u22; // required because of possible AU[2] = atom->u33; // type difference between AU[3] = atom->u12; // 'mmdb::machine::apireal' and 'realtype' AU[4] = atom->u13; AU[5] = atom->u23; *BIso = (mmdb::machine::apireal)(8.0*mmdb::Pi*mmdb::Pi*(AU[0]+AU[1]+AU[2])/3.0); if ((FTN_STR(BFlag)[0]=='F') || (FTN_STR(BFlag)[0]=='f')) { if (channel[k]->areCrystMatrices()) channel[k]->Orth2Cryst ( AU ); else if (*iRet==RWBERR_Ok) *iRet = RWBERR_NoMatrices; } for (i=0;i<6;i++) U[i] = (mmdb::machine::apireal)AU[i]; } else { for (i=0;i<6;i++) U[i] = 0.0; if (atom->WhatIsSet & mmdb::ASET_tempFactor) U[0] = (mmdb::machine::apireal)atom->tempFactor; else if (*iRet>=RWBERR_Ok) *iRet |= RWBWAR_NoTempFactor; *BIso = U[0]; } // get occupancy now if (atom->WhatIsSet & mmdb::ASET_Occupancy) *occ = (mmdb::machine::apireal)atom->occupancy; else { *occ = 0.0; if (*iRet>=RWBERR_Ok) *iRet |= RWBWAR_NoOccupancy; } } } else { // storing the atomic coordinates if (atom->Ter) { atom->x = 0.0; atom->y = 0.0; atom->z = 0.0; atom->WhatIsSet |= mmdb::ASET_Coordinates; atom->occupancy = 1.0; atom->tempFactor = 1.0; atom->u11 = 0.0; atom->u22 = 0.0; atom->u33 = 0.0; atom->u12 = 0.0; atom->u13 = 0.0; atom->u23 = 0.0; } else { if ((FTN_STR(XFlag)[m]=='F') || (FTN_STR(XFlag)[m]=='f')) { // convert fractional coordinates if (channel[k]->areCrystMatrices()) { xx = *x; yy = *y; zz = *z; channel[k]->Frac2Orth ( xx,yy,zz,atom->x,atom->y,atom->z ); atom->WhatIsSet |= mmdb::ASET_Coordinates; } else { atom->x = *x; atom->y = *y; atom->z = *z; *iRet = RWBERR_NoMatrices; atom->WhatIsSet &= ~mmdb::ASET_Coordinates; } } else { // store orthogonal coordinates atom->x = *x; atom->y = *y; atom->z = *z; atom->WhatIsSet |= mmdb::ASET_Coordinates; } atom->Het = (m>0); // calculate isotropic Uf from Uo, and convert it // if necessary if ((U[1]!=0.0) || (U[2]!=0.0)) { for (i=0;i<6;i++) AU[i] = U[i]; if ((FTN_STR(BFlag)[0]=='F') || (FTN_STR(BFlag)[0]=='f')) { if (channel[k]->areCrystMatrices()) channel[k]->Cryst2Orth ( AU ); else *iRet = RWBERR_NoMatrices; } *BIso = (mmdb::machine::apireal)(8.0*mmdb::Pi*mmdb::Pi*(AU[0]+AU[1]+AU[2])/3.0); atom->tempFactor = *BIso; atom->u11 = AU[0]; atom->u22 = AU[1]; atom->u33 = AU[2]; atom->u12 = AU[3]; atom->u13 = AU[4]; atom->u23 = AU[5]; atom->WhatIsSet |= mmdb::ASET_tempFactor | mmdb::ASET_Anis_tFac; } else { *BIso = U[0]; atom->tempFactor = *BIso; atom->u11 = 0.0; atom->u22 = 0.0; atom->u33 = 0.0; atom->u12 = 0.0; atom->u13 = 0.0; atom->u23 = 0.0; atom->WhatIsSet |= mmdb::ASET_tempFactor; } // store occupancy now atom->occupancy = *occ; atom->WhatIsSet |= mmdb::ASET_Occupancy; } } LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_SETCELL, mmdb_f_setcell, ( // lengths-at-end list int * iUnit, // unit number mmdb::machine::apireal * a, // cell parameter a, angstroms mmdb::machine::apireal * b, // cell parameter b, angstroms mmdb::machine::apireal * c, // cell parameter c, angstroms mmdb::machine::apireal * alpha, // cell parameter alpha, degrees mmdb::machine::apireal * beta, // cell parameter beta, degrees mmdb::machine::apireal * gamma, // cell parameter gamma, degrees int * ArgNCode, // orthogonalization code, 1-6 int * iRet // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_Disagreement if a // disagreement in // cell parameters // was found // RWBERR_NoOrthCode if no // orthogonalization // code was found // RWBERR_NoCheck if check // of cell parameters // has failed. // The last three returns would // rather indicate a programming // error in mmdb_rwbrook.cpp ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * a, mmdb::machine::apireal * b, mmdb::machine::apireal * c, mmdb::machine::apireal * alpha, mmdb::machine::apireal * beta, mmdb::machine::apireal * gamma, int * ArgNCode, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * a, mmdb::machine::apireal * b, mmdb::machine::apireal * c, mmdb::machine::apireal * alpha, mmdb::machine::apireal * beta, mmdb::machine::apireal * gamma, int * ArgNCode, int * iRet ) ) { int k; strcpy ( LastFunc,"MMDB_F_SetCell" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) *iRet = RWBERR_NoChannel; else *iRet = channel[k]->SetCell ( *a,*b,*c,*alpha,*beta,*gamma, *ArgNCode ); LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_WBSPGRP, mmdb_f_wbspgrp, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::fpstr spGroup, // space group int * iRet, // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed int spGroup_len // fortran-hidden length of spGroup ), ( // lengths-in-structure list int * iUnit, mmdb::machine::fpstr spGroup, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::fpstr spGroup, int spGroup_len, int * iRet ) ) { int k; mmdb::SymGroup spaceGroup; strcpy ( LastFunc,"MMDB_F_WBSpGrp" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) *iRet = RWBERR_NoChannel; else { // GetStrTer ( spaceGroup,FTN_STR(spGroup),0, // sizeof(spaceGroup),FTN_LEN(spGroup) ); mmdb::strcpy_ncss(spaceGroup,FTN_STR(spGroup),mmdb::IMin(FTN_LEN(spGroup), sizeof(spaceGroup)-1) ); *iRet = channel[k]->SetSpGroup ( spaceGroup ); } LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_RBSPGRP, mmdb_f_rbspgrp, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::fpstr spGroup, // space group int * iRet, // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed int spGroup_len // fortran-hidden length of spGroup ), ( // lengths-in-structure list int * iUnit, mmdb::machine::fpstr spGroup, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::fpstr spGroup, int spGroup_len, int * iRet ) ) { int k; char SpaceGroup[100]; strcpy ( LastFunc,"MMDB_F_RBSpGrp" ); if (*iUnit>0) LastUnit = *iUnit; SpaceGroup[0] = char(0); k = GetChannel ( LastUnit ); if (k<0) *iRet = RWBERR_NoChannel; else *iRet = channel[k]->GetSpGroup ( SpaceGroup ); // all extra "superficial spaces" are killed in the following mmdb::CutSpaces ( SpaceGroup,mmdb::SCUTKEY_BEGEND ); mmdb::strcpy_ns ( FTN_STR(spGroup),SpaceGroup,FTN_LEN(spGroup) ); LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_WBCELL , mmdb_f_wbcell, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::apireal * ArgCell, // array to accept the cell parameters // if ArgCell(1) is set to 0, then // the cell does not change int * ArgNCode, // orthogonalisation code // if ArgNCode is set to 0, then // the orthogonalisation matrices // do not change int * iRet // return code // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * ArgCell, int * ArgNCode, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * ArgCell, int * ArgNCode, int * iRet ) ) { int k; strcpy ( LastFunc,"MMDB_F_WBCell" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) *iRet = RWBERR_NoChannel; else *iRet = channel[k]->PutCell ( ArgCell[0],ArgCell[1],ArgCell[2], ArgCell[3],ArgCell[4],ArgCell[5], *ArgNCode ); LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_RBCELL, mmdb_f_rbcell, ( // lengths-at-end list int * iUnit, // unit number mmdb::machine::apireal * celld, // array to accept the cell parameters mmdb::machine::apireal * cvol, // returns the cell volume int * iRet // return code // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_Parameters if the // cell parameters // were not set // RWBERR_NoOrthCode if no // orthogonalization // code was found // RWBERR_NoCheck if check // of cell parameters // has failed. // The last three returns would // rather indicate a programming // error in mmdb_rwbrook.cpp ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * celld, mmdb::machine::apireal * cvol, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * celld, mmdb::machine::apireal * cvol, int * iRet ) ) { mmdb::realtype p[6]; mmdb::realtype v; int k,i,nc; strcpy ( LastFunc,"MMDB_F_RBCell" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } *iRet = channel[k]->GetCell ( p[0],p[1],p[2],p[3],p[4],p[5],v,nc ); if (*iRet==RWBERR_Ok) { for (i=0;i<6;i++) celld[i] = (mmdb::machine::apireal)p[i]; *cvol = (mmdb::machine::apireal)v; } LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_RBCELLN, mmdb_f_rbcelln, ( // lengths-at-end list int * iUnit, // unit number mmdb::machine::apireal * celld, // array to accept the cell parameters mmdb::machine::apireal * cvol, // returns the cell volume int * ArgNCode, // returns the orthogonalization code, 1-6 int * iRet // return code // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_Parameters if the // cell parameters // were not set // RWBERR_NoOrthCode if no // orthogonalization // code was found // RWBERR_NoCheck if check // of cell parameters // has failed. // The last three returns would // rather indicate a programming // error in mmdb_rwbrook.cpp ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * celld, mmdb::machine::apireal * cvol, int * ArgNCode, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * celld, mmdb::machine::apireal * cvol, int * ArgNCode, int * iRet ) ) { mmdb::realtype p[6]; mmdb::realtype v; int k,i,nc; strcpy ( LastFunc,"MMDB_F_RBCellN" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } *iRet = channel[k]->GetCell ( p[0],p[1],p[2],p[3],p[4],p[5],v,nc ); if (*iRet==RWBERR_Ok) { for (i=0;i<6;i++) celld[i] = (mmdb::machine::apireal)p[i]; *cvol = (mmdb::machine::apireal)v; *ArgNCode = nc; } LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_RBRCEL, mmdb_f_rbrcel, ( // lengths-at-end list int * iUnit, // unit number mmdb::machine::apireal * rcell, // array to accept the reciprocal // cell parameters mmdb::machine::apireal * rvol, // returns the reciprocal cell volume int * iRet // return code // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_Parameters if the // cell parameters // were not set // RWBERR_NoOrthCode if no // orthogonalization // code was found // RWBERR_NoCheck if check // of cell parameters // has failed. // The last three returns would // rather indicate a programming // error in mmdb_rwbrook.cpp ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * rcell, mmdb::machine::apireal * rvol, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * rcell, mmdb::machine::apireal * rvol, int * iRet ) ) { mmdb::realtype p[6]; mmdb::realtype v; int k,i; strcpy ( LastFunc,"MMDB_F_RBRCel" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } *iRet = channel[k]->GetRCell ( p[0],p[1],p[2],p[3],p[4],p[5],v ); if (*iRet==RWBERR_Ok) { for (i=0;i<6;i++) rcell[i] = (mmdb::machine::apireal)p[i]; *rvol = (mmdb::machine::apireal)v; } LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_RBORF, mmdb_f_rborf, ( // lengths-at-end list int * iUnit, // unit number mmdb::machine::apireal * RO, // array for orthogonalising matrix mmdb::machine::apireal * RF, // array for fractionalising matrix int * LCode, // buffer for orthogonalisation code int * iRet // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_NoMatrices if the // orthogonalisation // matrices were not // calculated ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * RO, mmdb::machine::apireal * RF, int * LCode, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * RO, mmdb::machine::apireal * RF, int * LCode, int * iRet ) ) { int i,j,k,l; mmdb::PCryst Cryst; strcpy ( LastFunc,"MMDB_F_RBORF" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } Cryst = channel[k]->GetCryst(); if (Cryst==NULL) { *iRet = RWBERR_NoFile; LastRC = *iRet; return; } *iRet = RWBERR_Ok; l = 0; if (RO[0]<=0.0000000001) { for (j=0;j<4;j++) for (i=0;i<4;i++) { RF[l] = (mmdb::machine::apireal)Cryst->RF[i][j]; RO[l] = (mmdb::machine::apireal)Cryst->RO[i][j]; l++; } *LCode = Cryst->NCode; if (!(Cryst->WhatIsSet & mmdb::CSET_Transforms)) *iRet = RWBERR_NoMatrices; } else { for (j=0;j<4;j++) for (i=0;i<4;i++) { Cryst->RF[i][j] = RF[l]; Cryst->RO[i][j] = RO[l]; l++; } Cryst->NCode = *LCode; Cryst->WhatIsSet |= mmdb::CSET_Transforms; } LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_ORTHMAT, mmdb_f_orthmat, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::apireal * Cell, // array of cell parameters: // Cell(1) - a Cell(4) - alpha // Cell(2) - b Cell(5) - beta // Cell(3) - c Cell(6) - gamma mmdb::machine::apireal * Vol, // returns cell volume mmdb::machine::apireal * RRR, // array (3,3,6), returns // orthogonalisation matrices int * iRet // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_NoMatrices if the // orthogonalisation // matrices were not // calculated ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * Cell, mmdb::machine::apireal * Vol, mmdb::machine::apireal * RRR, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * Cell, mmdb::machine::apireal * Vol, mmdb::machine::apireal * RRR, int * iRet ) ) { int i,j,k,l,m; mmdb::PCryst Cryst; mmdb::realtype CelDel; strcpy ( LastFunc,"MMDB_F_OrthMat" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } Cryst = channel[k]->GetCryst(); if (Cryst==NULL) { *iRet = RWBERR_NoFile; LastRC = *iRet; return; } CelDel = 0.0; if (Cell[0]>0.0) { if ((Cryst->WhatIsSet & mmdb::CSET_CellParams)==mmdb::CSET_CellParams) { CelDel = fabs((Cell[0]-Cryst->a)/Cell[0]); if (Cell[1]!=0.0) CelDel = mmdb::RMax(CelDel,fabs((Cell[1]-Cryst->b)/Cell[1])); if (Cell[2]!=0.0) CelDel = mmdb::RMax(CelDel,fabs((Cell[2]-Cryst->c)/Cell[2])); if (Cell[3]!=0.0) CelDel = mmdb::RMax(CelDel,fabs((Cell[3]-Cryst->alpha)/Cell[3])); if (Cell[4]!=0.0) CelDel = mmdb::RMax(CelDel,fabs((Cell[4]-Cryst->beta )/Cell[4])); if (Cell[5]!=0.0) CelDel = mmdb::RMax(CelDel,fabs((Cell[5]-Cryst->gamma)/Cell[5])); if (FSimRWBROOK && (CelDel>0.01)) printf ( "\n Inconsistency in Cell Dimensions" " - replacing old:\n" " Old cell: " "%10.5f%10.5f%10.5f%10.5f%10.5f%10.5f\n" " New cell: " "%10.5f%10.5f%10.5f%10.5f%10.5f%10.5f\n", Cryst->a,Cryst->b,Cryst->c, Cryst->alpha,Cryst->beta,Cryst->gamma, Cell[0],Cell[1],Cell[2],Cell[3],Cell[4],Cell[5] ); } Cryst->a = Cell[0]; Cryst->b = Cell[1]; Cryst->c = Cell[2]; Cryst->alpha = Cell[3]; Cryst->beta = Cell[4]; Cryst->gamma = Cell[5]; Cryst->WhatIsSet |= mmdb::CSET_CellParams; } else { Cell[0] = (mmdb::machine::apireal)Cryst->a; Cell[1] = (mmdb::machine::apireal)Cryst->b; Cell[2] = (mmdb::machine::apireal)Cryst->c; Cell[3] = (mmdb::machine::apireal)Cryst->alpha; Cell[4] = (mmdb::machine::apireal)Cryst->beta; Cell[5] = (mmdb::machine::apireal)Cryst->gamma; } if ((Cryst->WhatIsSet & mmdb::CSET_CellParams)!=mmdb::CSET_CellParams) { *iRet = RWBERR_NoCellParams; LastRC = *iRet; return; } *iRet = RWBERR_Ok; // Cryst->CalcOrthMatrices(); <-- old version, changed 09.01.2004 Cryst->CalcCoordTransforms(); Cryst->WhatIsSet |= mmdb::CSET_Transforms; if (CelDel>0.01) *Vol = -(mmdb::machine::apireal)Cryst->Vol; else *Vol = (mmdb::machine::apireal)Cryst->Vol; l = 0; for (j=0;j<3;j++) for (i=0;i<3;i++) for (m=0;m<6;m++) RRR[l++] = (mmdb::machine::apireal)Cryst->RR[m][j][i]; LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_CVANISOU, mmdb_f_cvanisou, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::apireal * U, // array of coordinates to convert int * iFlag, // =0: convert from fract. to orthog. // =1: convert from orthog. to fract. int * iRet // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_NoMatrices if the // orthogonalisation // matrices were not // calculated ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * U, int * iFlag, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * U, int * iFlag, int * iRet ) ) { int k,i; mmdb::PCryst Cryst; mmdb::realtype U1[6]; strcpy ( LastFunc,"MMDB_F_CVAnisou" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } Cryst = channel[k]->GetCryst(); if (Cryst==NULL) { *iRet = RWBERR_NoFile; LastRC = *iRet; return; } *iRet = RWBERR_Ok; for (i=0;i<6;i++) U1[i] = U[i]; if (iFlag==0) { if (!Cryst->Cryst2Orth(U1)) *iRet = RWBERR_NoMatrices; } else { if (!Cryst->Orth2Cryst(U1)) *iRet = RWBERR_NoMatrices; } if (*iRet==RWBERR_Ok) for (i=0;i<6;i++) U[i] = (mmdb::machine::apireal)U1[i]; LastRC = *iRet; } FORTRAN_SUBR ( MMDB_F_WREMARK, mmdb_f_wremark, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::fpstr Line, // line to be added int * iRet, // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // other return codea are those // returned by xyzopen1_(..) int Line_len // fortran-hidden length of Line ), ( // lengths-in-structure list int * iUnit, mmdb::machine::fpstr Line, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::fpstr Line, int Line_len, int *iRet ) ) { int k; char S[500]; strcpy ( LastFunc,"MMDB_F_WRemark" ); if (*iUnit>0) LastUnit = *iUnit; k = GetChannel ( LastUnit ); if (k<0) { *iRet = RWBERR_NoChannel; LastRC = *iRet; return; } if (channel[k]->MMDBManager) { mmdb::GetStrTer ( S,FTN_STR(Line),FTN_LEN(Line),sizeof(S),FTN_LEN(Line) ); *iRet = channel[k]->MMDBManager->PutPDBString ( S ); } else *iRet = RWBERR_NoFile; LastRC = *iRet; } /* FORTRAN_SUBR ( RBRINV, rbrinv, ( mmdb::machine::apireal * A, mmdb::machine::apireal * AI ), ( mmdb::machine::apireal * A, mmdb::machine::apireal * AI ), ( mmdb::machine::apireal * A, mmdb::machine::apireal * AI ) ) { mat44 A1,AI1; int i,j,k; k = 0; for (j=0;j<4;j++) for (i=0;i<4;i++) A1[j][i] = A[k++]; Mat4Inverse ( A1,AI1 ); k = 0; for (j=0;j<4;j++) for (i=0;i<4;i++) AI[k++] = AI1[j][i]; } */ /* FORTRAN_SUBR ( RES3TO1, res3to1, ( // lengths-at-end list mmdb::machine::fpstr ResNm3, // 3-char name, 4th char // will be set blank mmdb::machine::fpstr ResNm1, // 1-char name int ResNm3_len, // fortran-hidden length of ResNm3 int ResNm1_len // fortran-hidden length of ResNm3 ), ( // lengths-in-structure list mmdb::machine::fpstr ResNm3, mmdb::machine::fpstr ResNm1 ), ( // lengths-follow list mmdb::machine::fpstr ResNm3, int ResNm3_len, mmdb::machine::fpstr ResNm1, int ResNm1_len ) ) { int i; if (FTN_STR(ResNm3)[0]==' ') { for (i=0;i=0) printf ( " *** file : %s\n",channel[k]->FName ); for (i=0;i0) printf ( " *** position %i, serial number %i\n", channel[k]->fPos,LastSer ); else printf ( " *** position unavailable, serial number %i\n", LastSer ); } } if (!Msg) printf ( " *** warning: unknown warning code" ); return; } else Msg = MSG_Unknown; } if ((k>=0) && ( ((*iRet<=RWBERR_WrongInteger) && (*iRet>=RWBERR_DuplicatedModel)) || ((*iRet<=RWBERR_ATOM_Unrecognd) && (*iRet>=RWBERR_ATOM_Unmatch)) || ((*iRet<=RWBERR_NoData) && (*iRet>=RWBERR_DuplicateSeqNum)) )) channel[k]->GetInputBuffer ( ErrLine,lcount ); printf ( " \n *** RWBROOK error: point code unit function\n" ); printf ( " *** %5i %4i %4i %s\n",*iPlace,*iRet, *iUnit,LastFunc ); k = GetChannel(*iUnit); if (k>=0) printf ( " *** file : %s\n",channel[k]->FName ); printf ( " *** reason : %s\n",Msg ); if (lcount>=0) printf ( " *** at input line #%i:\n" " %s\n",lcount,ErrLine ); else if (lcount==-1) printf ( " *** at taking the following data from CIF:\n" " %s\n",ErrLine ); if (*iStop==0) { // will stop it printf ( " *** Execution stopped.\n \n" ); FORTRAN_CALL ( MMDB_F_QUIT, mmdb_f_quit,(),(),() ); // xyzquit_(); exit(0); } else // just warn, but no guarantee that it will not crash printf ( " *** continue running, may crash ...\n \n" ); } FORTRAN_SUBR ( RBCHECKERR, rbcheckerr, ( // lengths-at-end list int * iPlace, // (unique) identificator inside an application int * iStop // if 0 then stop if error ), ( // lengths-in-structure list int * iPlace, int * iStop ), ( // lengths-follow list int * iPlace, int * iStop ) ) { FORTRAN_CALL ( RBERRSTOP, rberrstop, ( iPlace,&LastRC,&LastUnit,iStop ), ( iPlace,&LastRC,&LastUnit,iStop ), ( iPlace,&LastRC,&LastUnit,iStop ) ); } /* hybrid-36 encoder: converts integer value to string result iwidth: must be 4 (e.g. for residue sequence numbers) or 5 (e.g. for atom serial numbers) value: integer value to be converted strval: char array containing string result */ FORTRAN_SUBR ( HY36ENCODE_F, hy36encode_f, (const int *iwidth, int *value, mmdb::machine::fpstr strval, int strval_len), (const int *iwidth, int *value, mmdb::machine::fpstr strval), (const int *iwidth, int *value, mmdb::machine::fpstr strval, int strval_len)) { unsigned width; char result[6]; width = (unsigned) *iwidth; if (hy36encode(width, *value, result)) { printf("problem in hy36encode_f! \n"); } mmdb::strcpy_ns(FTN_STR(strval),result,FTN_LEN(strval)); } /* hybrid-36 decoder: converts string s to integer result iwidth: must be 4 (e.g. for residue sequence numbers) or 5 (e.g. for atom serial numbers) strval: string to be converted value: integer holding the conversion result */ FORTRAN_SUBR ( HY36DECODE_F, hy36decode_f, (const int *iwidth, mmdb::machine::fpstr strval, int *value, int strval_len), (const int *iwidth, mmdb::machine::fpstr strval, int *value), (const int *iwidth, mmdb::machine::fpstr strval, int strval_len, int *value)) { UNUSED_ARGUMENT(strval); unsigned width; size_t length = FTN_LEN(strval); char* s; width = (unsigned) *iwidth; s = (char *) malloc((length+1)*sizeof(char)); s[length] = '\0'; if (hy36decode(width, s, width, value)) { printf("problem in hy36decode_f! \n"); } } mmdb2-2.0.5/mmdb2/mmdb_mask.h0000664000175000017500000000547412401105774012561 00000000000000// $Id: mmdb_mask.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDBF_Mask // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // // **** Classes : mmdb::Mask ( atom selection mask ) // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_Mask__ #define __MMDB_Mask__ #include "mmdb_io_stream.h" namespace mmdb { // ========================== Mask ============================= DefineClass(Mask); DefineStreamFunctions(Mask); class Mask : public io::Stream { public : Mask (); Mask ( io::RPStream Object ); ~Mask(); void SetMaskBit ( int BitNo ); void NewMask ( PPMask Mask, int nMasks ); void CopyMask ( PMask Mask ); // this = Mask void SetMask ( PMask Mask ); // this = this | Mask void RemoveMask ( PMask Mask ); // this = this & (~Mask) void SelMask ( PMask Mask ); // this = this & Mask void XadMask ( PMask Mask ); // this = this ^ Mask void ClearMask (); // this = NULL void NegMask (); // this = ~this bool CheckMask ( PMask Mask ); // true if the bit is on bool isMask (); // true if any mask bit is on inline int getLength() { return mlen; } pstr Print ( pstr S ); // returns binary string void write ( io::RFile f ); void read ( io::RFile f ); protected : int mlen; wvector m; void InitMask(); void Expand ( int n ); }; } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_uddata.cpp0000664000175000017500000003217712401105774013423 00000000000000// $Id: mmdb_uddata.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDBF_UDData // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // // **** Classes : mmdb::UDData ( user-defined data ) // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include "mmdb_uddata.h" namespace mmdb { // ======================== UDRegister ========================== #define nUDRTypes 5 UDRegister::UDRegister() : io::Stream() { InitUDRegister(); } UDRegister::UDRegister ( io::RPStream Object ) : io::Stream(Object) { InitUDRegister(); } UDRegister::~UDRegister() { FreeUDRegister(); } void UDRegister::InitUDRegister() { int i; for (i=0;i=0) && (udr_type=0) && (udr_type=0) && (udr_type=0) && (udr_type0) { IUDRegister[j] = new pstr[nIUDR[j]]; for (i=0;i0) { RUDRegister[j] = new pstr[nRUDR[j]]; for (i=0;i0) { SUDRegister[j] = new pstr[nSUDR[j]]; for (i=0;i> 8); SUData[0][1] = byte((newN & 0x00FF0000) >> 16); SUData[0][0] = byte((newN & 0xFF000000) >> 24); } int UDData::putUDData ( int UDDhandle, int iudd ) { ivector IUD; int i,l,udh; udh = UDDhandle & UDRF_MASK; if (udh<1) return UDDATA_WrongHandle; l = getNofIUData(); if (udh>l) { GetVectorMemory ( IUD,udh+1,0 ); IUD[0] = udh; for (i=1;i<=l;i++) IUD[i] = IUData[i]; for (i=l+1;il) { GetVectorMemory ( RUD,udh+1,0 ); RUD[0] = udh; for (i=1;i<=l;i++) RUD[i] = RUData[i]; for (i=l+1;il) { if (l>0) { GetVectorMemory ( SUD,udh+1,0 ); for (i=0;i<=l;i++) SUD[i] = SUData[i]; for (i=l+1;i<=udh;i++) SUD[i] = NULL; FreeVectorMemory ( SUData,0 ); SUData = SUD; } else { GetVectorMemory ( SUData,udh+1,0 ); SUData[0] = new char[4]; for (i=1;i<=udh;i++) SUData[i] = NULL; } setNofSUData ( udh ); } CreateCopy ( SUData[udh],sudd ); return UDDATA_Ok; } int UDData::getUDData ( int UDDhandle, int & iudd ) { int l,udh; iudd = 0; udh = UDDhandle & UDRF_MASK; if (udh<1) return UDDATA_WrongHandle; l = getNofIUData(); if (udh>l) return UDDATA_NoData; iudd = IUData[udh]; if (iudd==MinInt4) return UDDATA_NoData; return UDDATA_Ok; } int UDData::getUDData ( int UDDhandle, realtype & rudd ) { int l,udh; rudd = 0.0; udh = UDDhandle & UDRF_MASK; if (udh<1) return UDDATA_WrongHandle; l = getNofRUData(); if (udh>l) return UDDATA_NoData; rudd = RUData[udh]; if (rudd==-MaxReal) return UDDATA_NoData; return UDDATA_Ok; } int UDData::getUDData ( int UDDhandle, pstr sudd, int maxLen ) { int l,udh; sudd[0] = char(0); udh = UDDhandle & UDRF_MASK; if (udh<1) return UDDATA_WrongHandle; l = getNofSUData(); if (udh>l) return UDDATA_NoData; if (!SUData[udh]) return UDDATA_NoData; strcpy_n0 ( sudd,SUData[udh],maxLen-1 ); return UDDATA_Ok; } pstr UDData::getUDData ( int UDDhandle, int * retcode ) { int l,udh; udh = UDDhandle & UDRF_MASK; if (udh<1) { if (retcode) *retcode = UDDATA_WrongHandle; return NULL; } l = getNofSUData(); if (udh>l) { if (retcode) *retcode = UDDATA_NoData; return NULL; } if (!SUData[udh]) { if (retcode) *retcode = UDDATA_NoData; return NULL; } if (retcode) *retcode = UDDATA_Ok; return SUData[udh]; } int UDData::getUDData ( int UDDhandle, pstr & sudd ) { int l,udh; udh = UDDhandle & UDRF_MASK; if (udh<1) { if (sudd) { delete[] sudd; sudd = NULL; } return UDDATA_WrongHandle; } l = getNofSUData(); if (udh>l) { if (sudd) { delete[] sudd; sudd = NULL; } return UDDATA_NoData; } if (!SUData[udh]) { if (sudd) { delete[] sudd; sudd = NULL; } return UDDATA_NoData; } CreateCopy ( sudd,SUData[udh] ); return UDDATA_Ok; } void UDData::write ( io::RFile f ) { int i,l; byte Version=1; f.WriteByte ( &Version ); Mask::write ( f ); if (IUData) l = IUData[0]; else l = -1; f.WriteVector ( IUData,l+1,0 ); if (RUData) l = mround(RUData[0]); else l = -1; f.WriteVector ( RUData,l+1,0 ); l = getNofSUData(); f.WriteInt ( &l ); for (i=1;i<=l;i++) f.CreateWrite ( SUData[i] ); } void UDData::read ( io::RFile f ) { int i,l; byte Version; f.ReadByte ( &Version ); FreeUDDMemory(); Mask::read ( f ); f.CreateReadVector ( IUData,0 ); f.CreateReadVector ( RUData,0 ); f.ReadInt ( &l ); if (l>0) { SUData = new pstr[l+1]; SUData[0] = new char[4]; setNofSUData ( l ); for (i=1;i<=l;i++) { SUData[i] = NULL; f.CreateRead ( SUData[i] ); } } } MakeStreamFunctions(UDData) } // namespace mmdb mmdb2-2.0.5/mmdb2/mmdb_bondmngr.h0000664000175000017500000000415112401105774013423 00000000000000// $Id: mmdb_bondmngr.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 15.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : mmdb_bondmngr // ~~~~~~~~~ // Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::BondManager ( MMDB bonds maker ) // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_BondMngr__ #define __MMDB_BondMngr__ #include "mmdb_selmngr.h" namespace mmdb { // ======================= BondManager ======================= DefineClass(BondManager); DefineStreamFunctions(BondManager); class BondManager : public SelManager { public : BondManager (); BondManager ( io::RPStream Object ); ~BondManager(); void MakeBonds ( bool calc_only ); void RemoveBonds(); protected : void write ( io::RFile f ); void read ( io::RFile f ); }; } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_math_graph.cpp0000664000175000017500000017532412401105774014275 00000000000000// $Id: mmdb_math_graph.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : mmdb_math_graph // ~~~~~~~~~ // **** Namespace: mmdb::math:: // ~~~~~~~~~~ // **** Classes : Vertex ( graph vertex ) // ~~~~~~~~~ Edge ( graph edge ) // Graph ( structural graph ) // GMatch ( GMatch of structural graphs ) // GraphMatch ( CSIA algorithms for graphs GMatching ) // // (C) E. Krissinel 2000-2013 // // When used, please cite: // // Krissinel, E. and Henrick, K. (2004) // Common subgraph isomorphism detection by backtracking search. // Software - Practice and Experience, 34, 591-607. // // ================================================================= // #include #include #include "mmdb_math_graph.h" #include "mmdb_tables.h" namespace mmdb { namespace math { // ========================= Vertex ========================== Vertex::Vertex() : io::Stream() { InitVertex(); } Vertex::Vertex ( io::RPStream Object ) : io::Stream(Object) { InitVertex(); } Vertex::Vertex ( cpstr chem_elem ) : io::Stream() { InitVertex(); SetVertex ( chem_elem ); } Vertex::Vertex ( int vtype ) : io::Stream() { InitVertex(); SetVertex ( vtype ); } Vertex::Vertex ( int vtype, cpstr vname ) : io::Stream() { InitVertex(); SetVertex ( vtype,vname ); } Vertex::Vertex ( cpstr chem_elem, cpstr vname ) : io::Stream() { InitVertex (); SetVertex ( chem_elem ); CreateCopy ( name,vname ); } Vertex::~Vertex() { if (name) delete[] name; } void Vertex::InitVertex() { name = NULL; type = 0; type_ext = 0; property = 0; id = 0; user_id = 0; } void Vertex::SetVertex ( cpstr chem_elem ) { // This function generates vertex type according to a chemical // element name passed in chem_elem. // // The element type has the following meaning: // // 0xCHSSTTTT // // where // T - resreved for elemenmt type // S - resreved for symmetry relief // H - reserved for hydrogen bonds // C - resreved for chirality flags // // Note that when more than 2 symbols are used for chemical element // name (custom use), fields S may be reallocated for element type // and then symmetry relief becomes impossible. // CreateCopy ( name,chem_elem ); type = getElementNo ( chem_elem ); if (type==ELEMENT_UNKNOWN) { type = 0; if (name[0]) { type = (int)name[0]; if (name[1]) { type = type*256+(int)name[1]; if (name[2]) type = type*256+(int)name[2]; } } type += nElementNames; } } void Vertex::SetVertex ( int vtype ) { // This function sets vertex type. See comments above for // the general rule for vertex types implied by this code. char N[50]; int type0; type = vtype; type0 = vtype & TYPE_MASK; if ((type0>=1) && (type0<=nElementNames)) CreateCopy ( name,ElementName[type0-1] ); else { sprintf ( N,"%i",type ); CreateCopy ( name,N ); } } void Vertex::SetType ( int vtype ) { type = vtype; } void Vertex::SetTypeExt ( int typeExt ) { type_ext = typeExt; } void Vertex::SetVertex ( int vtype, cpstr vname ) { type = vtype; CreateCopy ( name,vname ); } void Vertex::SetName ( cpstr vname ) { CreateCopy ( name,vname ); } void Vertex::SetID ( int vid ) { id = vid; } void Vertex::SetProperty ( int vprop ) { property = vprop; } int Vertex::GetNBonds() { return ((type & HYDROGEN_BOND) >> 24); } void Vertex::AddBond() { int nb = GetNBonds()+1; type &= ~HYDROGEN_BOND; type |= nb << 24; } void Vertex::CopyNBonds ( PVertex V ) { int nb = V->GetNBonds(); type &= ~HYDROGEN_BOND; type |= nb << 24; } void Vertex::RemoveChirality() { type &= CHIRAL_MASK; } void Vertex::LeaveChirality ( int eltype ) { // leaves chirality only on specified elements int vtype; vtype = type & CHIRAL_MASK; if (vtype!=eltype) type = vtype; } void Vertex::SaveType() { user_id = type; } void Vertex::RestoreType() { type = user_id; } void Vertex::CopyType ( PVertex V ) { type = V->type; } void Vertex::Print ( int PKey ) { if (PKey!=0) printf ( " name type" ); else printf ( " %10s %5i",name,type ); } void Vertex::Copy ( PVertex V ) { CreateCopy ( name,V->name ); type = V->type; type_ext = V->type_ext; property = V->property; id = V->id; user_id = V->user_id; } void Vertex::write ( io::RFile f ) { int Version=2; f.WriteInt ( &Version ); f.CreateWrite ( name ); f.WriteInt ( &type ); f.WriteInt ( &property ); f.WriteInt ( &id ); f.WriteInt ( &user_id ); f.WriteInt ( &type_ext ); } void Vertex::read ( io::RFile f ) { int Version; f.ReadInt ( &Version ); f.CreateRead ( name ); f.ReadInt ( &type ); f.ReadInt ( &property ); f.ReadInt ( &id ); f.ReadInt ( &user_id ); if (Version>1) f.ReadInt ( &type_ext ); else type_ext = 0; } void Vertex::mem_write ( pstr S, int & l ) { byte Version=2; mmdb::mem_write_byte ( Version,S,l ); mmdb::mem_write ( name ,S,l ); mmdb::mem_write ( type ,S,l ); mmdb::mem_write ( property,S,l ); mmdb::mem_write ( id ,S,l ); mmdb::mem_write ( user_id ,S,l ); mmdb::mem_write ( type_ext,S,l ); } void Vertex::mem_read ( cpstr S, int & l ) { byte Version; mmdb::mem_read_byte ( Version,S,l ); mmdb::mem_read ( name ,S,l ); mmdb::mem_read ( type ,S,l ); mmdb::mem_read ( property,S,l ); mmdb::mem_read ( id ,S,l ); mmdb::mem_read ( user_id ,S,l ); mmdb::mem_read ( type_ext,S,l ); } MakeStreamFunctions(Vertex) // =========================== Edge ============================= Edge::Edge() : io::Stream() { InitEdge(); } Edge::Edge ( io::RPStream Object ) : io::Stream(Object) { InitEdge(); } Edge::Edge ( int vx1, int vx2, int btype ) { InitEdge(); SetEdge ( vx1,vx2,btype ); } Edge::~Edge() {} void Edge::InitEdge() { v1 = 0; v2 = 0; type = 0; property = 0; } #define NofBondTypes 4 static pstr BondType[NofBondTypes+1] = { pstr("SING"), pstr("DOUB"), pstr("AROM"), pstr("TRIP"), pstr("") // should be here for safety }; void Edge::SetEdge ( int vx1, int vx2, cpstr btype ) { v1 = vx1; v2 = vx2; type = 0; while (type=NofBondTypes) { type = 0; if (btype[0]) type = (int)btype[0]; if (btype[1]) type = type*16+(int)btype[1]; if (btype[2]) type = type*16+(int)btype[2]; type += NofBondTypes; } type++; } void Edge::SetEdge ( int vx1, int vx2, int btype ) { v1 = vx1; v2 = vx2; type = btype; } void Edge::SetType ( int btype ) { type = btype; } void Edge::SetProperty ( int eprop ) { property = eprop; } void Edge::SaveType() { property = type; } void Edge::RestoreType() { type = property; } void Edge::Print ( int PKey ) { if (PKey!=0) printf ( " v1 v2 type" ); else printf ( " %5i %5i %5i",v1,v2,type ); } void Edge::Copy ( PEdge G ) { v1 = G->v1; v2 = G->v2; type = G->type; property = G->property; } void Edge::write ( io::RFile f ) { int Version=1; f.WriteInt ( &Version ); f.WriteInt ( &v1 ); f.WriteInt ( &v2 ); f.WriteInt ( &type ); f.WriteInt ( &property ); } void Edge::read ( io::RFile f ) { int Version; f.ReadInt ( &Version ); f.ReadInt ( &v1 ); f.ReadInt ( &v2 ); f.ReadInt ( &type ); f.ReadInt ( &property ); } void Edge::mem_write ( pstr S, int & l ) { byte Version=1; mmdb::mem_write_byte ( Version,S,l ); mmdb::mem_write ( v1 ,S,l ); mmdb::mem_write ( v2 ,S,l ); mmdb::mem_write ( type ,S,l ); mmdb::mem_write ( property,S,l ); } void Edge::mem_read ( cpstr S, int & l ) { byte Version; mmdb::mem_read_byte ( Version,S,l ); mmdb::mem_read ( v1 ,S,l ); mmdb::mem_read ( v2 ,S,l ); mmdb::mem_read ( type ,S,l ); mmdb::mem_read ( property,S,l ); } MakeStreamFunctions(Edge) // ========================== Graph ============================ Graph::Graph() : io::Stream() { InitGraph(); } Graph::Graph ( PResidue R, cpstr altLoc ) : io::Stream() { InitGraph(); MakeGraph ( R,altLoc ); } Graph::Graph ( io::RPStream Object ) : io::Stream(Object) { InitGraph(); } Graph::~Graph() { FreeMemory(); } void Graph::InitGraph() { nVAlloc = 0; nEAlloc = 0; nGAlloc = 0; nVertices = 0; nEdges = 0; nAllVertices = 0; nAllEdges = 0; vertex = NULL; edge = NULL; graph = NULL; name = NULL; CreateCopy ( name,pstr("UNNAMED") ); } void Graph::FreeMemory() { int i; if (vertex) { for (i=0;i=nVAlloc) { nVAlloc += AllocPortion; V1 = new PVertex[nVAlloc]; for (i=0;i0) FreeMemory(); vertex = V; nVertices = vlen; nAllVertices = vlen; nVAlloc = vlen; } int Graph::GetVertexID ( int vertexNo ) { if ((vertexNo>0) && (vertexNo<=nAllVertices)) return vertex[vertexNo-1]->GetID(); else return MinInt4; } int Graph::GetNBondedVertices ( int vertexNo ) { if ((vertexNo>0) && (vertexNo<=nAllVertices)) { if (vertex[vertexNo-1]) return vertex[vertexNo-1]->GetNBonds(); } return 0; } int Graph::GetBondedVertexID ( int vertexNo, int bond_vx_type, int bondNo ) { int i,k, v1,v2; if ((vertexNo>0) && (vertexNo<=nAllVertices)) { if (vertex[vertexNo-1]) { if (vertex[vertexNo-1]->GetNBonds()>=bondNo) { k = 0; for (i=0;(iv1; v2 = edge[i]->v2; if ((v1==vertexNo) && ((vertex[v2-1]->type & (int)TYPE_MASK) == bond_vx_type) && (vertex[v2-1]->GetNBonds()==bondNo)) k = v2; if ((v2==vertexNo) && ((vertex[v1-1]->type & (int)TYPE_MASK) == bond_vx_type) && (vertex[v2-1]->GetNBonds()==bondNo)) k = v1; } if (k) return vertex[k-1]->GetID(); } } } return MinInt4; } PVertex Graph::GetVertex ( int vertexNo ) { if ((vertexNo>0) && (vertexNo<=nAllVertices)) return vertex[vertexNo-1]; else return NULL; } int Graph::GetVertexNo ( cpstr vname ) { int i,k; k = 0; if (vname) for (i=0;(iname)) k = i+1; return k; } PEdge Graph::GetEdge ( int edgeNo ) { if ((edgeNo>0) && (edgeNo<=nAllEdges)) return edge[edgeNo-1]; else return NULL; } void Graph::AddEdge ( PEdge G ) { int i; PPEdge G1; if (nAllEdges>=nEAlloc) { nEAlloc += AllocPortion; G1 = new PEdge[nEAlloc]; for (i=0;i0) FreeMemory(); edge = G; nEdges = glen; nAllEdges = glen; nEAlloc = glen; } void Graph::GetVertices ( PPVertex & V, int & nV ) { V = vertex; nV = nVertices; } void Graph::GetEdges ( PPEdge & E, int & nE ) { E = edge; nE = nEdges; } int Graph::MakeGraph ( PResidue R, cpstr altLoc ) { int i,j, a1,a2,e1,e2, nAltLocs,alflag, rc; bool B; rvector occupancy; AltLoc aLoc; PAltLoc aL; realtype dx,dy,dz, sr; PEdge G; rc = MKGRAPH_Ok; // reset graph FreeMemory(); occupancy = NULL; aL = NULL; R->GetAltLocations ( nAltLocs,aL,occupancy,alflag ); if (nAltLocs<=0) return MKGRAPH_NoAtoms; if (altLoc) strcpy ( aLoc,altLoc ); else aLoc[0] = char(0); if (nAltLocs<=1) { // Only one alt code is there, check if it is what was ordered if (strcmp(aLoc,aL[0])) { rc = MKGRAPH_ChangedAltLoc; strcpy ( aLoc,aL[0] ); } } else if ((alflag & ALF_Mess) || ((alflag & ALF_NoEmptyAltLoc) && (!aLoc[0]))) { // There is a mess in the residue alt codes, or empty alt code // does not designate a conformation but ordered. In this // situation build graph for maximal-occupancy conformation // and store its altLoc in aLoc. rc = MKGRAPH_MaxOccupancy; dx = -2.0; for (i=0;idx)) { dx = occupancy[i]; strcpy ( aLoc,aL[i] ); } } SetName ( R->name ); nVAlloc = R->nAtoms; // upper estimate for vertices to allocate if (nVAlloc<=0) { if (aL) delete[] aL; FreeVectorMemory ( occupancy,0 ); return MKGRAPH_NoAtoms; } // allocate vertex array vertex = new PVertex[nVAlloc]; for (i=0;inAtoms;i++) if (R->atom[i]) { if (!R->atom[i]->Ter) { if (nAltLocs>1) { // This is a many-altcode residue. aLoc contains the altcode // that has to be included. Check on it: B = !strcmp(aLoc,R->atom[i]->altLoc); if ((!B) && (!R->atom[i]->altLoc[0])) { // We got a non-aLoc code that is an "empty-altcode". // Check if this atom has the altcode that we need. for (j=i+1;(jnAtoms) && (!B);j++) if (R->atom[j]) { if ((!R->atom[j]->Ter) && (!strcmp(R->atom[j]->name,R->atom[i]->name))) B = !strcmp(aLoc,R->atom[j]->altLoc); } // if altcode=aLoc is not there for the atom (B is set // false) then we take its "empty-code" location B = !B; } } else B = true; if (B) { vertex[nVertices] = new Vertex ( R->atom[i]->element, R->atom[i]->name ); vertex[nVertices]->id = nVertices; vertex[nVertices]->user_id = i; nVertices++; } } } if (nVertices<=0) { if (aL) delete[] aL; FreeVectorMemory ( occupancy,0 ); return MKGRAPH_NoAtoms; } // make edges nEAlloc = 3*nVertices; edge = new PEdge[nEAlloc]; for (i=0;iuser_id; e1 = vertex[i]->type; if (e1>nElementNames) e1 = 6; e1--; for (j=i+1;juser_id; e2 = vertex[j]->type; if (e2>nElementNames) e2 = 6; e2--; dx = R->atom[a2]->x - R->atom[a1]->x; dy = R->atom[a2]->y - R->atom[a1]->y; dz = R->atom[a2]->z - R->atom[a1]->z; // sr = CovalentRadius[e1] + CovalentRadius[e2] + 0.15; sr = CovalentRadius[e1] + CovalentRadius[e2] + 0.25; if (dx*dx+dy*dy+dz*dzid = i+1; } if (aL) delete[] aL; FreeVectorMemory ( occupancy,0 ); nAllVertices = nVertices; nAllEdges = nEdges; return rc; } int Graph::MakeGraph ( PPAtom atom, int nAtoms ) { PEdge G; char atomID[100]; realtype dx,dy,dz, sr; int i,j, a1,a2,e1,e2, rc; rc = MKGRAPH_Ok; // reset graph FreeMemory(); nVAlloc = nAtoms; // upper estimate for vertices to allocate if (nVAlloc<=0) return MKGRAPH_NoAtoms; // allocate vertex array vertex = new PVertex[nVAlloc]; for (i=0;iTer) { vertex[nVertices] = new Vertex ( atom[i]->element, atom[i]->GetAtomIDfmt(atomID) ); vertex[nVertices]->user_id = i; nVertices++; } } if (nVertices<=0) { FreeMemory(); return MKGRAPH_NoAtoms; } // make edges nEAlloc = 3*nVertices; // just an inital guess edge = new PEdge[nEAlloc]; for (i=0;iuser_id; e1 = vertex[i]->type; if (e1>nElementNames) e1 = 6; e1--; for (j=i+1;juser_id; e2 = vertex[j]->type; if (e2>nElementNames) e2 = 6; e2--; dx = atom[a2]->x - atom[a1]->x; dy = atom[a2]->y - atom[a1]->y; dz = atom[a2]->z - atom[a1]->z; sr = CovalentRadius[e1] + CovalentRadius[e2] + 0.25; if (dx*dx+dy*dy+dz*dzid = i+1; } nAllVertices = nVertices; nAllEdges = nEdges; return rc; } void Graph::MakeVertexIDs() { int i; for (i=0;iid = i+1; } void Graph::HideType ( int bond_vx_type ) { // 1. Moves vertices bond_vx_type to the end of vertex array // 2. Moves edges to bond_vx_type vertices to the end of edge array // 3. Saves lengths of full vertex and edge arrays, and redefines // lengths to initial parts of the arrays not containing // bond_vx_type vertices. PPEdge Edge1; PPVertex Vertex1; int i,k,v1,v2, nEdges1,nVertices1; ivector iv; Edge1 = new PEdge[nEdges]; Vertex1 = new PVertex[nVertices]; GetVectorMemory ( iv,nVertices,1 ); for (i=0;iv1-1; v2 = edge[i]->v2-1; if (vertex[v1] && vertex[v2]) { if ((vertex[v1]->type & (int)TYPE_MASK)==bond_vx_type) { vertex[v2]->AddBond(); vertex[v1]->CopyNBonds ( vertex[v2] ); } if ((vertex[v2]->type & (int)TYPE_MASK)==bond_vx_type) { vertex[v1]->AddBond(); vertex[v2]->CopyNBonds ( vertex[v1] ); } } } nVertices1 = 0; for (i=0;itype & (int)TYPE_MASK)!=bond_vx_type) { Vertex1[nVertices1++] = vertex[i]; iv[i+1] = nVertices1; } } k = nVertices1; for (i=0;itype & (int)TYPE_MASK)==bond_vx_type) { Vertex1[k++] = vertex[i]; iv[i+1] = k; } } nEdges1 = 0; for (i=0;iv1 = iv[edge[i]->v1]; edge[i]->v2 = iv[edge[i]->v2]; if (((Vertex1[edge[i]->v1-1]->type & (int)TYPE_MASK) != bond_vx_type) && ((Vertex1[edge[i]->v2-1]->type & (int)TYPE_MASK) != bond_vx_type)) Edge1[nEdges1++] = edge[i]; } k = nEdges1; for (i=0;iv1-1]->type & (int)TYPE_MASK) == bond_vx_type) || ((Vertex1[edge[i]->v2-1]->type & (int)TYPE_MASK) == bond_vx_type)) Edge1[k++] = edge[i]; } nAllVertices = nVertices; nAllEdges = nEdges; nVAlloc = nVertices; nEAlloc = nEdges; nVertices = nVertices1; nEdges = nEdges1; if (vertex) delete[] vertex; if (edge) delete[] edge; FreeVectorMemory ( iv,1 ); vertex = Vertex1; edge = Edge1; } void Graph::ExcludeType ( int type ) { int i,k; ivector iv; GetVectorMemory ( iv,nAllVertices,1 ); k = 0; for (i=0;itype & (int)TYPE_MASK)!=type) { if (kv1]!=0) && (iv[edge[i]->v2]!=0)) { if (kv1 = iv[edge[k]->v1]; edge[k]->v2 = iv[edge[k]->v2]; k++; } else { delete edge[i]; edge[i] = NULL; } nAllEdges = k; nEdges = nAllEdges; FreeVectorMemory ( iv,1 ); } void Graph::RemoveChirality() { int i; for (i=0;iRemoveChirality(); } void Graph::LeaveChirality ( int eltype ) { // leaves chirality for specified atom types int i; for (i=0;iLeaveChirality ( eltype ); } void Graph::MakeSymmetryRelief ( bool noCO2 ) { // This function looks for groups of equivalent vertices // attached to a single vertice (e.g. chemical SO3 or // PO3 groups), and re-lables them by adding a unique // symmetry-relief number. This eliminates equivalent // GMatches (3! for each SO3/PO3 group), and increases // vertex diversity, which considerably speeds up GMatching. // The function is cheap and harmless even if such groups // of vertices are not found. // If noCO2 is true then CO2 symmetry is not releaved. ivector v,vc; int i,j,k,n,m,almask,vjtype, ctype,otype; bool noOxygens; otype = 0; ctype = 0; GetVectorMemory ( v ,nVertices,0 ); GetVectorMemory ( vc,nVertices,1 ); for (i=1;i<=nVertices;i++) vc[i] = 0; for (j=0;jv1>0) && (edge[j]->v1<=nVertices)) vc[edge[j]->v1]++; if ((edge[j]->v2>0) && (edge[j]->v2<=nVertices)) vc[edge[j]->v2]++; } almask = ~ATOM_LEAVING; if (noCO2) { ctype = getElementNo ( "C" ); otype = getElementNo ( "O" ); } noOxygens = false; for (i=1;i<=nVertices;i++) if (vc[i]>1) { // vertex at more than 1 edge // v[] will list connected vertices, k will be their number k = 0; for (j=0;jv1==i) && (vc[edge[j]->v2]==1) && (kv2-1; if ((edge[j]->v2==i) && (vc[edge[j]->v1]==1) && (kv1-1; } if (k>1) { if (noCO2) noOxygens = ((vertex[i-1]->type & almask)==ctype); // A group of vertices with single connection is // identified. Assign symmetry relief modifiers // to *equivalent* vertices in the group for (j=0;j=0) && (v[j]type & almask; if ((!noOxygens) || (vjtype!=otype)) { n = 1; // symmetry relief modifier for (m=j+1;m=0) && (v[m]type== (vertex[v[m]]->type & almask)) { vertex[v[m]]->type |= (n << 16); n++; v[m] = -1; } } } } } } FreeVectorMemory ( v ,0 ); FreeVectorMemory ( vc,1 ); } int Graph::Build ( bool bondOrder ) { int i,j, rc; if (nVertices<=0) return 2; if (nGAllocv1>=1) && (edge[i]->v1<=nVertices) && (edge[i]->v2>=1) && (edge[i]->v2<=nVertices)) { graph[edge[i]->v1][edge[i]->v2] = edge[i]->type; graph[edge[i]->v2][edge[i]->v1] = edge[i]->type; } else rc = 1; } else { for (i=0;iv1>=1) && (edge[i]->v1<=nVertices) && (edge[i]->v2>=1) && (edge[i]->v2<=nVertices)) { graph[edge[i]->v1][edge[i]->v2] = 1; graph[edge[i]->v2][edge[i]->v1] = 1; } else rc = 1; } return rc; } const int ring_mask[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080 }; void Graph::IdentifyRings() { GraphMatch GM; Graph ring; ivector F1,F2; AtomName aname; realtype p1,p2; int i,j,n,nrings,nv; Build ( false ); for (i=0;itype_ext = 0; GM.SetFlag ( GMF_UniqueMatch ); for (n=3;n<=10;n++) { ring.Reset(); for (i=1;i<=n;i++) { sprintf ( aname,"C%i",i ); ring.AddVertex ( new Vertex("C",aname) ); } ring.MakeVertexIDs(); for (i=1;i<=n;i++) { j = i+1; if (j>n) j = 1; ring.AddEdge ( new Edge(i,j,1) ); } ring.Build ( false ); GM.MatchGraphs ( this,&ring,n,false,EXTTYPE_Ignore ); nrings = GM.GetNofMatches(); for (i=0;itype_ext |= ring_mask[n]; } } } void Graph::markConnected ( int vno, int cno ) { int i; vertex[vno]->type_ext = cno; for (i=0;itype_ext)) markConnected ( i,cno ); } int Graph::IdentifyConnectedComponents() { // Returns the number of connected components and sets // vertex[]->type_ext equal to component number >=1. int nComponents,i; nComponents = 0; Build ( false ); for (i=0;itype_ext = 0; i = 0; while (itype_ext) i++; else break; if (i0) { printf ( " Vertices:\n"" ## " ); vertex[0]->Print(1); printf ( "\n" ); for (i=0;iPrint(0); printf ( "\n" ); } } if (nEdges>0) { printf ( " Edges:\n"" ## " ); edge[0]->Print(1); printf ( "\n" ); for (i=0;iPrint(0); printf ( "\n" ); } } } void Graph::Print1() { int i,j; for (i=0;iid,vertex[i]->type,vertex[i]->name ); for (j=0;jv1==i+1) printf ( " %4i(%i)",edge[j]->v2,edge[j]->type ); else if (edge[j]->v2==i+1) printf ( " %4i(%i)",edge[j]->v1,edge[j]->type ); printf ( "\n" ); } } void Graph::Copy ( PGraph G ) { int i; FreeMemory(); CreateCopy ( name,G->name ); nVertices = G->nVertices; nEdges = G->nEdges; nAllVertices = G->nAllVertices; nAllEdges = G->nAllEdges; if (nAllVertices>0) { nVAlloc = nAllVertices; vertex = new PVertex[nVAlloc]; for (i=0;iCopy ( G->vertex[i] ); } } if (nAllEdges>0) { nEAlloc = nAllEdges; edge = new PEdge[nEAlloc]; for (i=0;iCopy ( G->edge[i] ); } } } void Graph::write ( io::RFile f ) { int i; int Version=2; bool bondOrder=false; f.WriteInt ( &Version ); f.WriteBool ( &bondOrder ); f.CreateWrite ( name ); f.WriteInt ( &nVertices ); f.WriteInt ( &nEdges ); f.WriteInt ( &nAllVertices ); f.WriteInt ( &nAllEdges ); for (i=0;i1) { f.ReadInt ( &nAllVertices ); f.ReadInt ( &nAllEdges ); } else { nAllVertices = nVertices; nAllEdges = nEdges; } if (nAllVertices>0) { nVAlloc = nAllVertices; vertex = new PVertex[nVAlloc]; for (i=0;i0) { nEAlloc = nAllEdges; edge = new PEdge[nEAlloc]; for (i=0;imem_write ( S,l ); } else { k = 0; mmdb::mem_write ( k,S,l ); } for (i=0;imem_write ( S,l ); } else { k = 0; mmdb::mem_write ( k,S,l ); } } void Graph::mem_read ( cpstr S, int & l ) { int i,k; byte Version; bool bondOrder; FreeMemory(); mmdb::mem_read_byte ( Version,S,l ); mmdb::mem_read ( bondOrder ,S,l ); mmdb::mem_read ( name ,S,l ); mmdb::mem_read ( nVertices ,S,l ); mmdb::mem_read ( nEdges ,S,l ); mmdb::mem_read ( nAllVertices,S,l ); mmdb::mem_read ( nAllEdges ,S,l ); if (nAllVertices>0) { nVAlloc = nAllVertices; vertex = new PVertex[nVAlloc]; for (i=0;imem_read ( S,l ); } else vertex[i] = NULL; } } if (nAllEdges>0) { nEAlloc = nAllEdges; edge = new PEdge[nEAlloc]; for (i=0;imem_read ( S,l ); } else { edge[i] = NULL; } } } // Build ( bondOrder ); } MakeStreamFunctions(Graph) // ========================== GMatch ============================ GMatch::GMatch() : io::Stream() { InitGMatch(); } GMatch::GMatch ( io::RPStream Object ) : io::Stream ( Object ) { InitGMatch(); } GMatch::GMatch ( ivector FV1, ivector FV2, int nv, int n, int m ) { int i; if (FV1 && FV2) { n1 = n; n2 = m; nAlloc = n; GetVectorMemory ( F1,nAlloc,1 ); GetVectorMemory ( F2,nAlloc,1 ); mlength = nv; for (i=1;i<=mlength;i++) { F1[i] = FV1[i]; F2[i] = FV2[i]; } } else InitGMatch(); } void GMatch::InitGMatch() { mlength = 0; n1 = 0; n2 = 0; nAlloc = 0; F1 = NULL; F2 = NULL; } GMatch::~GMatch() { FreeVectorMemory ( F1,1 ); FreeVectorMemory ( F2,1 ); } void GMatch::SetMatch ( ivector FV1, ivector FV2, int nv, int n, int m ) { int i; if (FV1 && FV2) { if (nv>nAlloc) { FreeVectorMemory ( F1,1 ); FreeVectorMemory ( F2,1 ); nAlloc = n; GetVectorMemory ( F1,nAlloc,1 ); GetVectorMemory ( F2,nAlloc,1 ); } n1 = n; n2 = m; mlength = nv; for (i=1;i<=mlength;i++) { F1[i] = FV1[i]; F2[i] = FV2[i]; } } else { FreeVectorMemory ( F1,1 ); FreeVectorMemory ( F2,1 ); mlength = 0; n1 = 0; n2 = 0; } } bool GMatch::isMatch ( ivector FV1, ivector FV2, int nv ) { int i,j; bool B; if (FV1 && FV2 && (nv<=mlength)) { B = true; for (i=1;(i<=nv) && B;i++) { B = false; for (j=1;(j<=mlength) && (!B);j++) B = (FV1[i]==F1[j]) && (FV2[i]==F2[j]); } return B; } return false; } bool GMatch::isCombination ( ivector FV1, ivector FV2, int nv ) { int i,j; bool B; if (FV1 && FV2 && (nv==mlength)) { B = true; for (i=1;(i<=nv) && B;i++) { B = false; for (j=1;(j<=mlength) && (!B);j++) B = (FV1[i]==F1[j]); if (B) { B = false; for (j=1;(j<=mlength) && (!B);j++) B = (FV2[i]==F2[j]); } } return B; } return false; } void GMatch::GetMatch ( ivector & FV1, ivector & FV2, int & nv, realtype & p1, realtype & p2 ) { FV1 = F1; FV2 = F2; nv = mlength; p1 = mlength; if (p1>0.0) p1 /= n1; p2 = mlength; if (p2>0.0) p2 /= n2; } void GMatch::write ( io::RFile f ) { int i; int Version=1; f.WriteInt ( &Version ); f.WriteInt ( &mlength ); f.WriteInt ( &n1 ); f.WriteInt ( &n2 ); for (i=1;i<=mlength;i++) { f.WriteInt ( &(F1[i]) ); f.WriteInt ( &(F2[i]) ); } } void GMatch::read ( io::RFile f ) { int i,Version; FreeVectorMemory ( F1,1 ); FreeVectorMemory ( F2,1 ); f.ReadInt ( &Version ); f.ReadInt ( &mlength ); f.ReadInt ( &n1 ); f.ReadInt ( &n2 ); if (mlength>0) { nAlloc = n1; GetVectorMemory ( F1,nAlloc,1 ); GetVectorMemory ( F2,nAlloc,1 ); for (i=1;i<=mlength;i++) { f.ReadInt ( &(F1[i]) ); f.ReadInt ( &(F2[i]) ); } } } void GMatch::mem_write ( pstr S, int & l ) { int i; mmdb::mem_write ( mlength,S,l ); mmdb::mem_write ( n1 ,S,l ); mmdb::mem_write ( n2 ,S,l ); for (i=1;i<=mlength;i++) { mmdb::mem_write ( F1[i],S,l ); mmdb::mem_write ( F2[i],S,l ); } } void GMatch::mem_read ( cpstr S, int & l ) { int i; FreeVectorMemory ( F1,1 ); FreeVectorMemory ( F2,1 ); mmdb::mem_read ( mlength,S,l ); mmdb::mem_read ( n1 ,S,l ); mmdb::mem_read ( n2 ,S,l ); if (mlength>0) { nAlloc = n1; GetVectorMemory ( F1,nAlloc,1 ); GetVectorMemory ( F2,nAlloc,1 ); for (i=1;i<=mlength;i++) { mmdb::mem_read ( F1[i],S,l ); mmdb::mem_read ( F2[i],S,l ); } } } MakeStreamFunctions(GMatch) // ======================== GraphMatch ========================== GraphMatch::GraphMatch() : io::Stream() { InitGraphMatch(); } GraphMatch::GraphMatch ( io::RPStream Object ) : io::Stream ( Object ) { InitGraphMatch(); } GraphMatch::~GraphMatch() { FreeMemory(); } void GraphMatch::InitGraphMatch() { G1 = NULL; G2 = NULL; n = 0; m = 0; P = NULL; nAlloc = 0; mAlloc = 0; nMatches = 0; maxNMatches = -1; // unlimited Match = NULL; nMAlloc = 0; flags = 0; swap = false; wasFullMatch = false; maxMatch = 0; timeLimit = 0; // no time limit Stop = false; stopOnMaxNMathches = false; F1 = NULL; F2 = NULL; iF1 = NULL; ix = NULL; #ifndef _UseRecursion jj = NULL; #endif } void GraphMatch::SetFlag ( word flag ) { flags |= flag; } void GraphMatch::RemoveFlag ( word flag ) { flags &= ~flag; } void GraphMatch::SetMaxNofMatches ( int maxNofGMatches, bool stopOnMaxN ) { maxNMatches = maxNofGMatches; stopOnMaxNMathches = stopOnMaxN; } void GraphMatch::SetTimeLimit ( int maxTimeToRun ) { timeLimit = maxTimeToRun; } void GraphMatch::Reset() { FreeMemory(); } void GraphMatch::FreeMemory() { int i; if (P) { FreeMatrixMemory ( P[1],nAlloc,1,0 ); FreeRecHeap (); P = P + 1; delete[] P; P = NULL; } FreeMatrixMemory ( iF1,nAlloc,1,1 ); FreeVectorMemory ( F1 ,1 ); FreeVectorMemory ( F2 ,1 ); FreeVectorMemory ( ix ,1 ); nAlloc = 0; mAlloc = 0; if (Match) { for (i=0;inVertices<=Gh2->nVertices) { G1 = Gh1; G2 = Gh2; swap = false; } else { G1 = Gh2; G2 = Gh1; swap = true; } n = G1->nVertices; m = G2->nVertices; V1 = G1->vertex; V2 = G2->vertex; c1 = G1->graph; c2 = G2->graph; nMatches = 0; if (n<=0) return; if ((n>nAlloc) || (m>mAlloc)) GetMemory(); else FreeRecHeap(); n1 = Initialize ( vertexType,vertexExt ); if (n1<=0) return; GetRecHeap(); maxMatch = IMax(1,IMin(n,minMatch)); Stop = false; startTime = time(NULL); // Use of Backtrack(..) and Ullman() is completely // equivalent. One of them should be commented. if (minMatch=minMatch) Backtrack1 ( 1,n1 ); } else if (n1>=n) { #ifdef _UseRecursion Backtrack ( 1 ); #else Ullman(); #endif } } int GraphMatch::Initialize ( bool vertexType, int vertexExt ) { ivector jF1; int i,j,v1type,v1type_ext,v2type_ext,almask,iW,pl; wasFullMatch = false; jF1 = iF1[1]; for (i=1;i<=n;i++) jF1[i] = i; almask = ~ATOM_LEAVING; /* -- experiment for symmetry reliefs int v2type,v1type_sr,srmask; srmask = ~SYMREL_MASK; for (i=1;i<=n;i++) { if (vertexType) { ix[i] = 0; v1type = V1[i-1]->type & almask; v1type_sr = v1type & srmask; pl = 0; for (j=1;j<=m;j++) { v2type = V2[j-1]->type & almask; if ((v1type==v2type) || (v1type_sr==v2type) || (v1type==(v2type & srmask))) P[1][i][++pl] = j; } P[1][i][0] = pl; if (pl) ix[i] = i; } else { ix[i] = i; for (j=1;j<=m;j++) P[1][i][j] = j; P[1][i][0] = m; } F1[i] = 0; F2[i] = 0; } */ for (i=1;i<=n;i++) { ix[i] = 0; v1type = V1[i-1]->type & almask; v1type_ext = V1[i-1]->type_ext; pl = 0; for (j=1;j<=m;j++) if ((v1type==(V2[j-1]->type & almask)) || (!vertexType)) { if (vertexExt==EXTTYPE_Ignore) P[1][i][++pl] = j; else { v2type_ext = V2[j-1]->type_ext; if ((!v1type_ext) && (!v2type_ext)) P[1][i][++pl] = j; else switch (vertexExt) { default : case EXTTYPE_Ignore : P[1][i][++pl] = j; break; case EXTTYPE_Equal : if (v1type_ext==v2type_ext) P[1][i][++pl] = j; break; case EXTTYPE_AND : if (v1type_ext & v2type_ext) P[1][i][++pl] = j; break; case EXTTYPE_OR : if (v1type_ext | v2type_ext) P[1][i][++pl] = j; break; case EXTTYPE_XOR : if (v1type_ext ^ v2type_ext) P[1][i][++pl] = j; break; case EXTTYPE_NotEqual : if (v1type_ext!=v2type_ext) P[1][i][++pl] = j; break; case EXTTYPE_NotAND : if ((v1type_ext & v2type_ext) ==0) P[1][i][++pl] = j; break; case EXTTYPE_NotOR : if ((v1type_ext | v2type_ext) ==0) P[1][i][++pl] = j; } } } P[1][i][0] = pl; if (pl) ix[i] = i; F1[i] = 0; F2[i] = 0; } /* } else { for (i=1;i<=n;i++) { ix[i] = i; for (j=1;j<=m;j++) P[1][i][j] = j; P[1][i][0] = m; F1[i] = 0; F2[i] = 0; } } */ i = 1; j = n; while (i0) Stop = (difftime(time(NULL),startTime)>timeLimit); F1[i] = i; pli = P[i][i][0]; if (i>=n) { for (cntj=1;(cntj<=pli) && (!Stop);cntj++) { F2[n] = P[n][n][cntj]; CollectMatch ( n ); } } else { i1 = i+1; c1i = c1[i]; for (cntj=1;(cntj<=pli) && (!Stop);cntj++) { j = P[i][i][cntj]; F2[i] = j; // mapped F1[i]:F2[i], i.e. i:j // Forward checking c2j = c2[j]; pl2 = 1; for (k=i1;(k<=n) && (pl2>0);k++) { p1 = P[i][k]; p2 = P[i1][k]; c1ik = c1i[k]; pl1 = p1[0]; pl2 = 0; for (cntl=1;cntl<=pl1;cntl++) { l = p1[cntl]; if ((c1ik==c2j[l]) && // check that bonds are compatible (l!=j)) // and make sure jth vertex is excluded p2[++pl2] = l; } p2[0] = pl2; // new length of P-row } if (pl2>0) Backtrack ( i1 ); } } } #else void GraphMatch::Ullman() { // A non-recursive translation of Ullman's Backtrack. // It might give some gain in performance, although tests // on SGI machine show that the gain is negligible, (if // there is any at all) if compiler's optimization is // switched on. int i,pl,i1,pli,cntj,j,pl1,pl2,k,cntl,l,l1,cik; ivector ci,cj; ivector p1,p2; if (Stop) return; if (timeLimit>0) Stop = (difftime(time(NULL),startTime)>timeLimit); i = 1; jj[1] = 1; pl = P[1][1][0]; do { F1[i] = i; pli = P[i][i][0]; if (i>=n) { for (cntj=jj[n];(cntj<=pli) && (!Stop);cntj++) { jj[n]++; F2[n] = P[n][n][cntj]; CollectGMatch ( n ); } } else { i1 = i+1; ci = c1[i]; for (cntj=jj[i];(cntj<=pli) && (!Stop);cntj++) { jj[i]++; j = P[i][i][cntj]; F2[i] = j; // Forward checking cj = c2[j]; pl2 = 1; for (k=i1;(k<=n) && (pl2>0);k++) { p1 = P[i][k]; p2 = P[i1][k]; cik = ci[k]; pl1 = p1[0]; pl2 = 0; for (cntl=1;cntl<=pl1;cntl++) { l = p1[cntl]; if ((cik==cj[l]) && // check that bonds are compatible (l!=j)) // and make sure jth vertex is excluded p2[++pl2] = l; } p2[0] = pl2; // new length of P-row } if (pl2>0) { i++; jj[i] = 1; i++; // in order to compensate the following decrement break; } } } i--; } while ((!Stop) && ((jj[1]<=pl) || (i>1))); } #endif void GraphMatch::Backtrack1 ( int i, int k0 ) { // Recursive version of CSIA algorithm for partial // (substructure-to-substructure) GMatching int i1,pl0,cntj,j,k,pl1,pl2,cntl,l,c1ik,ii,iW,k1; ivector jF1,c1i,c2j; ivector p0,p1,p2; if (Stop) return; if (timeLimit>0) Stop = (difftime(time(NULL),startTime)>timeLimit); jF1 = iF1[i]; if (i>=k0) { F1[i] = jF1[i]; p0 = P[i][jF1[i]]; pl0 = p0[0]; // collect GMatches of k0-th (the upmost) level if (pl0>0) { maxMatch = k0; for (cntj=1;cntj<=pl0;cntj++) { F2[k0] = p0[cntj]; CollectMatch ( k0 ); } } } else { i1 = i+1; pl0 = P[i][jF1[i]][0]; j = i; for (k=i1;k<=k0;k++) if (P[i][jF1[k]][0]i) { iW = jF1[i]; jF1[i] = jF1[j]; jF1[j] = iW; } F1[i] = jF1[i]; p0 = P[i][jF1[i]]; pl0 = p0[0]; c1i = c1[jF1[i]]; // 1. Find all GMatches that include jF1[i]th vertex of graph G1 for (cntj=1;(cntj<=pl0) && (!Stop);cntj++) { j = p0[cntj]; F2[i] = j; // mapped F1[i]:F2[i], i.e. iF1[i][i]:j // Forward checking c2j = c2[j]; k1 = k0; // k1 is the limit for GMatch size for (k=i1;(k<=k0) && (k1>=maxMatch);k++) { ix[k] = 0; p1 = P[i] [jF1[k]]; p2 = P[i1][jF1[k]]; c1ik = c1i [jF1[k]]; pl1 = p1[0]; pl2 = 0; for (cntl=1;cntl<=pl1;cntl++) { l = p1[cntl]; if ((c1ik==c2j[l]) && // check that bonds are compatible (l!=j)) // and make sure jth vertex is excluded p2[++pl2] = l; } p2[0] = pl2; // new length of P-row if (pl2>0) { ix[k] = k; } else if (wasFullMatch) { k1 = maxMatch-1; // we are not interested in partial } else { // GMatch anymore k1--; } } if (k1>=maxMatch) { // shift unGMatching vertices to the end for (ii=1;ii<=n;ii++) iF1[i1][ii] = jF1[ii]; k = i1; l = k0; while (k=maxMatch) { CollectMatch ( i ); // collect GMatch of ith level maxMatch = i; } } } // 2. Find all GMatches that do not include jF1[i]th vertex // of graph G1 if (k0>maxMatch) { // Shift jF1[i]th vertex to the end iW = jF1[i]; jF1[i] = jF1[k0]; jF1[k0] = iW; Backtrack1 ( i,k0-1 ); } } } void GraphMatch::CollectMatch ( int nm ) { int i; bool B; PPGMatch M1; if (maxNMatches==0) return; // find out if this should be a new GMatch if (nMatches>0) { // a GMatch is already found; check with it if (nmmlength) return; if (nm>Match[0]->mlength) { nMatches = 0; } else if (flags & GMF_UniqueMatch) { // check if such a GMatch was already found B = false; for (i=0;(iisMatch(F1,F2,nm); if (B) return; // repeating GMatch -- just quit. } else if (flags & GMF_NoCombinations) { // check if such a GMatch was already found B = false; for (i=0;(iisCombination(F1,F2,nm); if (B) return; // repeating GMatch -- just quit. } } if (nMatches>=nMAlloc) { if ((nMAlloc0) nMAlloc = IMin(maxNMatches,nMAlloc+100); else nMAlloc += 100; M1 = new PGMatch[nMAlloc]; for (i=0;iSetMatch ( F1,F2,nm,n,m ); if (nm==n) wasFullMatch = true; if (nm>maxMatch) maxMatch = nm; nMatches++; if (stopOnMaxNMathches && (maxNMatches>0) && (nMatches>=maxNMatches)) Stop = true; } void GraphMatch::PrintMatches() { int i,j,k; if (nMatches<=0) printf ( "\n\n *** NO GMatchES FOUND\n\n" ); else { if (flags & GMF_UniqueMatch) printf ( "\n\n *** FOUND Unique GMatches\n\n" ); else printf ( "\n\n *** FOUND GMatches\n\n" ); printf ( " ## Vertices\n" ); for (i=0;imlength;j++) { if (swap) printf ( " (%i,%i)",Match[i]->F2[j],Match[i]->F1[j] ); else printf ( " (%i,%i)",Match[i]->F1[j],Match[i]->F2[j] ); k += 8; if (k>70) { printf ( "\n" ); k = 8; } } printf ( "\n" ); } } printf ( "\n **************************\n" ); } void GraphMatch::GetMatch ( int MatchNo, ivector & FV1, ivector & FV2, int & nv, realtype & p1, realtype & p2 ) { // do not allocate or dispose FV1 and FV2 in application! // FV1/p1 will always correspond to Gh1, and FV2/p2 - // to Gh2 as specified in GMatchGraphs(..) if ((MatchNo<0) || (MatchNo>=nMatches)) { FV1 = NULL; FV2 = NULL; nv = 0; p1 = 0.0; p2 = 0.0; } else if (swap) Match[MatchNo]->GetMatch ( FV2,FV1,nv,p2,p1 ); else Match[MatchNo]->GetMatch ( FV1,FV2,nv,p1,p2 ); } void GraphMatch::write ( io::RFile f ) { int i; int Version=1; f.WriteInt ( &Version ); f.WriteInt ( &nMatches ); f.WriteWord ( &flags ); f.WriteBool ( &swap ); for (i=0;iwrite ( f ); } void GraphMatch::read ( io::RFile f ) { int i,Version; FreeMemory (); f.ReadInt ( &Version ); f.ReadInt ( &nMatches ); f.ReadWord ( &flags ); f.ReadBool ( &swap ); if (nMatches>0) { nMAlloc = nMatches; Match = new PGMatch[nMatches]; for (i=0;iread ( f ); } } } void GraphMatch::mem_write ( pstr S, int & l ) { int i; mmdb::mem_write ( nMatches,S,l ); mmdb::mem_write ( flags ,S,l ); mmdb::mem_write ( swap ,S,l ); for (i=0;imem_write ( S,l ); } void GraphMatch::mem_read ( cpstr S, int & l ) { int i; FreeMemory (); mmdb::mem_read ( nMatches,S,l ); mmdb::mem_read ( flags ,S,l ); mmdb::mem_read ( swap ,S,l ); if (nMatches>0) { nMAlloc = nMatches; Match = new PGMatch[nMatches]; for (i=0;imem_read ( S,l ); } } } MakeStreamFunctions(GraphMatch) } // namespace math } // namespace mmdb // ============================================================= /* static char Mol1[][3] = { "C", "C", "C", "C", "C", "C" }; static int Bond1[] = { 1, 2, 1, 6, 2, 3, 3, 4, 4, 5, 5, 6 }; static char Mol2[][3] = { "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C" }; static int Bond2[] = { 1, 2, 1, 6, 2, 3, 3, 4, 4, 5, 5, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 6, 12 }; static char Mol1[][3] = { "C", "C", "N", "C" }; static int Bond1[] = { 1, 2, 2, 3, 3, 4 }; static char Mol2[][3] = { "C", "C", "N", "C" }; static int Bond2[] = { 1, 2, 2, 3, 2, 4, 3, 4 }; void TestGraphMatch() { int i,k1,k2, nv1,nb1, nv2,nb2; PVertex V; PEdge G; Graph G1,G2; GraphMatch U; G1.Reset (); G1.SetName ( "#1" ); nv1 = sizeof(Mol1)/3; for (i=0;iSetVertex ( Mol1[i] ); G1.AddVertex ( V ); } nb1 = sizeof(Bond1)/(2*sizeof(int)); k1 = 0; k2 = 1; for (i=0;iSetEdge ( Bond1[k1],Bond1[k2],1 ); G1.AddEdge ( G ); k1 += 2; k2 += 2; } G2.Reset (); G2.SetName ( "#2" ); nv2 = sizeof(Mol2)/3; for (i=0;iSetVertex ( Mol2[i] ); G2.AddVertex ( V ); } nb2 = sizeof(Bond2)/(2*sizeof(int)); k1 = 0; k2 = 1; for (i=0;iSetEdge ( Bond2[k1],Bond2[k2],1 ); G2.AddEdge ( G ); k1 += 2; k2 += 2; } G1.Build(); G2.Build(); U.GMatchGraphs ( &G1,&G2,nv1 ); U.PrintGMatches(); } */ mmdb2-2.0.5/mmdb2/mmdb_uddata.h0000664000175000017500000001030212401105774013052 00000000000000// $Id: mmdb_uddata.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDBF_UDData // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // // **** Classes : mmdb::UDData ( user-defined data ) // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_UDData__ #define __MMDB_UDData__ #include "mmdb_mask.h" namespace mmdb { // ======================= UDRegister ========================= enum UDR_TYPE { UDR_ATOM = 0, UDR_RESIDUE = 1, UDR_CHAIN = 2, UDR_MODEL = 3, UDR_HIERARCHY = 4 }; enum UDD_FLAG { UDRF_ATOM = 0x01000000, UDRF_RESIDUE = 0x02000000, UDRF_CHAIN = 0x04000000, UDRF_MODEL = 0x08000000, UDRF_HIERARCHY = 0x10000000, UDRF_MASK = 0x00FFFFFF }; DefineClass(UDRegister); DefineStreamFunctions(UDRegister); class UDRegister : public io::Stream { public : UDRegister (); UDRegister ( io::RPStream Object ); ~UDRegister(); int RegisterUDInteger ( UDR_TYPE udr_type, cpstr UDDataID ); int RegisterUDReal ( UDR_TYPE udr_type, cpstr UDDataID ); int RegisterUDString ( UDR_TYPE udr_type, cpstr UDDataID ); int GetUDDHandle ( UDR_TYPE udr_type, cpstr UDDataID ); void write ( io::RFile f ); void read ( io::RFile f ); protected : int nIUDR[5],nRUDR[5],nSUDR[5]; psvector IUDRegister[5]; psvector RUDRegister[5]; psvector SUDRegister[5]; void InitUDRegister (); void FreeUDRegister (); int RegisterUDData ( psvector & UDRegister, int & nUDR, cpstr UDDataID ); }; // ========================== UDData =========================== enum UDDATA_RC { UDDATA_Ok = 0, UDDATA_WrongHandle = -1, UDDATA_WrongUDRType = -2, UDDATA_NoData = -3 }; DefineClass(UDData); DefineStreamFunctions(UDData); class UDData : public Mask { friend class SelManager; public : UDData (); UDData ( io::RPStream Object ); ~UDData(); protected : ivector IUData; rvector RUData; psvector SUData; void InitUDData (); void FreeUDDMemory(); int getNofIUData (); int getNofRUData (); int getNofSUData (); void setNofSUData ( int newN ); int putUDData ( int UDDhandle, int iudd ); int putUDData ( int UDDhandle, realtype rudd ); int putUDData ( int UDDhandle, cpstr sudd ); int getUDData ( int UDDhandle, int & iudd ); int getUDData ( int UDDhandle, realtype & rudd ); int getUDData ( int UDDhandle, pstr sudd, int maxLen ); pstr getUDData ( int UDDhandle, int * retcode=NULL ); int getUDData ( int UDDhandle, pstr & sudd ); void write ( io::RFile f ); void read ( io::RFile f ); }; } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_math_.cpp0000664000175000017500000001165712401105774013251 00000000000000// $Id: mmdb_math.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 11.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : Math // ~~~~~~~~~ // **** Functions : mmdb::math::GetTorsion // ~~~~~~~~~~~ mmdb::math::GetAngle // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include "mmdb_math_.h" namespace mmdb { namespace math { // -------------------------------------------------------------- realtype GetTorsion ( rvector U, rvector W, rvector V ) { // U W V // o<----o----->o----->o // realtype A[3],B[3],C[3],Wmag,S,T; A[0] = U[1]*W[2] - W[1]*U[2]; A[1] = U[2]*W[0] - W[2]*U[0]; A[2] = U[0]*W[1] - W[0]*U[1]; B[0] = V[1]*W[2] - W[1]*V[2]; B[1] = V[2]*W[0] - W[2]*V[0]; B[2] = V[0]*W[1] - W[0]*V[1]; C[0] = A[1]*B[2] - B[1]*A[2]; C[1] = A[2]*B[0] - B[2]*A[0]; C[2] = A[0]*B[1] - B[0]*A[1]; Wmag = sqrt(W[0]*W[0]+W[1]*W[1]+W[2]*W[2]); S = C[0]*W[0] + C[1]*W[1] + C[2]*W[2]; T = A[0]*B[0] + A[1]*B[1] + A[2]*B[2]; T *= Wmag; if ((S==0.0) && (T==0.0)) return NO_TORSION; else return atan2(S,T); } realtype GetAngle ( rvector v1, rvector v2 ) { realtype l1,l2; l1 = v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2]; if (l1==0.0) l1 = 1.0; l2 = v2[0]*v2[0] + v2[1]*v2[1] + v2[2]*v2[2]; if (l2==0.0) l2 = 1.0; return acos((v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])/sqrt(l1*l2)); } #define nCombMax 500 realtype Combinations ( int n, int m ) { // 0<=n<=nCombMax, 0<=m<=n realtype P[nCombMax+1]; int i,j; if ((m<0) || (m>n)) return 0.0; if ((m==0) || (m==n)) return 1.0; if ((m==1) || (m==n-1)) return realtype(n); P[0] = 1.0; P[1] = 3.0; P[2] = 3.0; P[3] = 1.0; for (i=4;i<=n;i++) { P[i] = 1.0; for (j=i-1;j>0;j--) P[j] += P[j-1]; } return P[m]; } realtype log1mx ( realtype x ) { // Calculates precisely log(1-x) for x<1, including // very small x realtype z,z1,z2,n; if (x>=1.0-10.0*MachEps) z = -MaxReal; else if (fabs(x)>1.0e-8) z = log(1.0-x); else { z1 = x; z = 0.0; n = 1.0; do { z2 = z; z -= z1/n; z1 *= x; n += 1.0; } while (z!=z2); } return z; } realtype expc ( realtype x ) { // Calculates precisely 1 - exp(x) for any x including // very small values realtype z,z1,z2,n; if (x>LnMaxReal) z = -MaxReal; else if (x<-LnMaxReal) z = 1.0; else if (fabs(x)>1.0e-8) z = 1.0 - Exp(x); else { z1 = x; z = x; n = 1.0; do { z2 = z; n += 1.0; z1 *= x/n; z += z1; } while (z!=z2); z = -z; } return z; } realtype expc1mx ( realtype x, realtype y ) { // Calculates precisely 1-(1-x)**y including very small x and // very large y realtype z,z1,z2,n,s; // Calculate (1-x)**y as exp(y*log(1-x)). Get log(1-x) first: if (x>1.0e-8) z = log(1.0-x); else { z1 = x; z = 0.0; n = 1.0; do { z2 = z; z -= z1/n; z1 *= x; n += 1.0; } while (z!=z2); } // Now calculate 1 - exp(y*log(1-x)) : z *= y; if (fabs(z)>1.0e-8) s = 1.0 - exp(z); else { z1 = z; s = z; n = 1.0; do { z2 = s; n += 1.0; z1 *= z/n; s += z1; } while (s!=z2); s = -s; } return s; } } } mmdb2-2.0.5/mmdb2/mmdb_title.cpp0000664000175000017500000020742712401105774013304 00000000000000// $Id: mmdb_title.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 21.11.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_Title // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::TitleContainer (container of title classes) // ~~~~~~~~~ mmdb::ObsLine // mmdb::TitleLine // mmdb::Caveat // mmdb::Compound // mmdb::Source // mmdb::KeyWords // mmdb::ExpData // mmdb::MdlType // mmdb::Author // mmdb::RevData // mmdb::Supersede // mmdb::Journal // mmdb::Remark // mmdb::Biomolecule // mmdb::Title ( MMDB title section ) // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include #include "mmdb_title.h" #include "mmdb_cifdefs.h" namespace mmdb { // ============== TitleContainer ==================== PContainerClass TitleContainer::MakeContainerClass ( int ClassID ) { switch (ClassID) { default : case ClassID_Template : return ClassContainer::MakeContainerClass(ClassID); case ClassID_ObsLine : return new ObsLine (); case ClassID_CAVEAT : return new Caveat (); case ClassID_TitleLine : return new TitleLine(); case ClassID_Compound : return new Compound (); case ClassID_Source : return new Source (); case ClassID_ExpData : return new ExpData (); case ClassID_Author : return new Author (); case ClassID_RevData : return new RevData (); case ClassID_Supersede : return new Supersede(); case ClassID_Journal : return new Journal (); case ClassID_Remark : return new Remark (); } } MakeStreamFunctions(TitleContainer) // ================ ObsLine =================== ObsLine::ObsLine() : ContainerClass() { InitObsLine(); } ObsLine::ObsLine ( cpstr S ) : ContainerClass() { InitObsLine(); ConvertPDBASCII ( S ); } ObsLine::ObsLine ( io::RPStream Object ) : ContainerClass(Object) { InitObsLine(); } ObsLine::~ObsLine() {} void ObsLine::InitObsLine() { int i; strcpy ( repDate,"DD-MMM-YYYY" ); strcpy ( idCode, "----" ); for (i=0;i<8;i++) strcpy ( rIdCode[i]," " ); } void ObsLine::PDBASCIIDump ( pstr S, int N ) { // makes the ASCII PDB OBSLTE line number N // from the class' data int i; if (N==0) strcpy ( S,"OBSLTE " ); else sprintf ( S,"OBSLTE %2i",N+1 ); PadSpaces ( S,80 ); Date11to9 ( repDate,&(S[11]) ); strncpy ( &(S[21]),idCode,4 ); for (i=0;i<8;i++) strncpy ( &(S[31+5*i]),rIdCode[i],4 ); } void ObsLine::MakeCIF ( mmcif::PData CIF, int ) { mmcif::PLoop Loop; int RC,i,j; char DateCIF[20]; RC = CIF->AddLoop ( CIFCAT_OBSLTE,Loop ); if (RC!=mmcif::CIFRC_Ok) { // the category was (re)created, provide tags Loop->AddLoopTag ( CIFTAG_ID ); Loop->AddLoopTag ( CIFTAG_DATE ); Loop->AddLoopTag ( CIFTAG_REPLACE_PDB_ID ); Loop->AddLoopTag ( CIFTAG_PDB_ID ); } Date11toCIF ( repDate,DateCIF ); for (i=0;i<8;i++) { j = 0; while (rIdCode[i][j] && (rIdCode[i][j]==' ')) j++; if (rIdCode[i][j]) { Loop->AddString ( pstr("OBSLTE") ); Loop->AddString ( DateCIF ); Loop->AddString ( idCode ); Loop->AddString ( rIdCode[i] ); } } } ERROR_CODE ObsLine::ConvertPDBASCII ( cpstr S ) { int i; Date9to11 ( &(S[11]),repDate ); strncpy ( idCode,&(S[21]),4 ); idCode[4] = char(0); for (i=0;i<8;i++) { strncpy ( rIdCode[i],&(S[31+i*5]),4 ); rIdCode[i][4] = char(0); } return Error_NoError; } ERROR_CODE ObsLine::GetCIF ( mmcif::PData CIF, int & n ) { mmcif::PLoop Loop; int i,RC; pstr F,FDate,FID; char DateCIF [20]; char DateCIF0[20]; IDCode idCode1; Loop = CIF->GetLoop ( CIFCAT_OBSLTE ); if (!Loop) { n = -1; // signal to finish processing of this structure return Error_EmptyCIF; } i = 0; do { F = Loop->GetString ( CIFTAG_ID,n,RC ); if (RC) { if (i==0) n = -1; return Error_MissingCIFField; } if (F) { if (!strcmp(F,"OBSLTE")) { FDate = Loop->GetString ( CIFTAG_DATE,n,RC ); if ((!RC) && FDate) strncpy ( DateCIF,FDate,15 ); else strcpy ( DateCIF,"YYYY-MMM-DD" ); FID = Loop->GetString ( CIFTAG_REPLACE_PDB_ID,n,RC ); if ((!RC) && FID) strncpy ( idCode1,FID,sizeof(IDCode)-1 ); else idCode1[0] = char(0); if (i==0) { DateCIFto11 ( DateCIF,repDate ); DateCIF[11] = char(0); strcpy ( idCode ,idCode1 ); strcpy ( DateCIF0,DateCIF ); } else if ((strcmp(DateCIF0,DateCIF)) || (strcmp(idCode,idCode1))) return Error_MissingCIFField; FID = Loop->GetString ( CIFTAG_PDB_ID,n,RC ); if ((!RC) && FID) strncpy ( rIdCode[i],FID,sizeof(IDCode)-1 ); else rIdCode[i][0] = char(0); Loop->DeleteField ( CIFTAG_ID ,n ); Loop->DeleteField ( CIFTAG_DATE ,n ); Loop->DeleteField ( CIFTAG_REPLACE_PDB_ID,n ); Loop->DeleteField ( CIFTAG_PDB_ID ,n ); i++; } } n++; } while (i<8); return Error_NoError; } void ObsLine::Copy ( PContainerClass ObsLine ) { int i; strcpy ( repDate,PObsLine(ObsLine)->repDate ); strcpy ( idCode ,PObsLine(ObsLine)->idCode ); for (i=0;i<8;i++) strcpy ( rIdCode[i],PObsLine(ObsLine)->rIdCode[i] ); } void ObsLine::write ( io::RFile f ) { int i; byte Version=1; f.WriteByte ( &Version ); f.WriteTerLine ( repDate,false ); f.WriteTerLine ( idCode ,false ); for (i=0;i<8;i++) f.WriteTerLine ( rIdCode[i],false ); } void ObsLine::read ( io::RFile f ) { int i; byte Version; f.ReadByte ( &Version ); f.ReadTerLine ( repDate,false ); f.ReadTerLine ( idCode ,false ); for (i=0;i<8;i++) f.ReadTerLine ( rIdCode[i],false ); } MakeStreamFunctions(ObsLine) // =================== TitleLine ====================== TitleLine::TitleLine() : ContString() { InitTitleLine(); } TitleLine::TitleLine ( cpstr S ) : ContString() { InitTitleLine(); ConvertPDBASCII ( S ); } TitleLine::TitleLine ( io::RPStream Object ) : ContString(Object) { InitTitleLine(); } TitleLine::~TitleLine() { } void TitleLine::InitTitleLine() { CreateCopy ( CIFCategory,CIFCAT_STRUCT ); CreateCopy ( CIFTag, CIFTAG_TITLE ); } ERROR_CODE TitleLine::ConvertPDBASCII ( cpstr S ) { if (strlen(S)>10) CreateCopy ( Line,&(S[10]) ); else CreateCopy ( Line,pstr(" ") ); return Error_NoError; } void TitleLine::PDBASCIIDump ( pstr S, int N ) { if (N==0) strcpy ( S,"TITLE " ); else sprintf ( S,"TITLE %2i",N+1 ); strcat ( S,Line ); } void TitleLine::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); ContString::write ( f ); } void TitleLine::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); ContString::read ( f ); } MakeStreamFunctions(TitleLine) // =================== Caveat ====================== Caveat::Caveat() : ContString() { InitCaveat(); } Caveat::Caveat ( cpstr S ) : ContString() { InitCaveat(); ConvertPDBASCII ( S ); } Caveat::Caveat ( io::RPStream Object ) : ContString(Object) { InitCaveat(); } Caveat::~Caveat() {} void Caveat::InitCaveat() { strcpy ( idCode,"----" ); CreateCopy ( CIFCategory,CIFCAT_DATABASE_PDB_CAVEAT ); CreateCopy ( CIFTag ,CIFTAG_TEXT ); } ERROR_CODE Caveat::ConvertPDBASCII ( cpstr S ) { if (strlen(S)>12) { strncpy ( idCode,&(S[11]),4 ); idCode[4] = char(0); if (strlen(S)>19) CreateCopy ( Line,&(S[19]) ); else CreateCopy ( Line,pstr(" ") ); } else CreateCopy ( Line,pstr(" ") ); return Error_NoError; } void Caveat::PDBASCIIDump ( pstr S, int N ) { if (N==0) strcpy ( S,"CAVEAT " ); else sprintf ( S,"CAVEAT %2i ",N+1 ); strcat ( S,idCode ); strcat ( S," " ); strcat ( S,Line ); } void Caveat::MakeCIF ( mmcif::PData CIF, int N ) { char S[500]; CIF->PutString ( idCode,CIFCAT_DATABASE_PDB_CAVEAT,CIFTAG_ID,false ); strcpy ( S,"\n" ); strncat ( S,Line,sizeof(S)-2 ); S[sizeof(S)-1] = char(0); CIF->PutString ( S,CIFCAT_DATABASE_PDB_CAVEAT,CIFTAG_TEXT,(N!=0) ); } /* void Caveat::GetCIF1 ( mmcif::PData CIF, ERROR_CODE & Signal, int & pos ) { pstr F; int RC; F = CIF->GetString ( CIFCAT_DATABASE_PDB_CAVEAT,CIFTAG_ID,RC ); if ((!RC) && F) { strncpy ( idCode,F,sizeof(IDCode) ); idCode[sizeof(IDCode)-1] = char(0); } ContString::GetCIF1 ( CIF,Signal,pos ); if (Signal<0) CIF->DeleteField ( CIFCAT_DATABASE_PDB_CAVEAT,CIFTAG_ID ); } */ void Caveat::Copy ( PContainerClass Caveat ) { strcpy ( idCode,PCaveat(Caveat)->idCode ); ContString::Copy ( Caveat ); } void Caveat::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); f.WriteTerLine ( idCode,false ); ContString::write ( f ); } void Caveat::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.ReadTerLine ( idCode,false ); ContString::read ( f ); } MakeStreamFunctions(Caveat) // =================== Compound ====================== Compound::Compound() : ContString() { InitCompound(); } Compound::Compound ( cpstr S ) : ContString() { InitCompound(); ConvertPDBASCII ( S ); } Compound::Compound ( io::RPStream Object ) : ContString(Object) { InitCompound(); } Compound::~Compound() {} void Compound::InitCompound() { CreateCopy ( CIFCategory,CIFCAT_STRUCT ); CreateCopy ( CIFTag ,CIFTAG_NDB_DESCRIPTOR ); } ERROR_CODE Compound::ConvertPDBASCII ( cpstr S ) { if (strlen(S)>10) CreateCopy ( Line,&(S[10]) ); else CreateCopy ( Line,pstr(" ") ); return Error_NoError; } void Compound::PDBASCIIDump ( pstr S, int N ) { if (N==0) strcpy ( S,"COMPND " ); else sprintf ( S,"COMPND %2i",N+1 ); strcat ( S,Line ); } void Compound::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); ContString::write ( f ); } void Compound::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); ContString::read ( f ); } MakeStreamFunctions(Compound) // =================== Source ====================== Source::Source() : ContString() { InitSource(); } Source::Source ( cpstr S ) : ContString() { InitSource(); ConvertPDBASCII ( S ); } Source::Source ( io::RPStream Object ) : ContString(Object) { InitSource(); } Source::~Source() {} void Source::InitSource() { CreateCopy ( CIFCategory,CIFCAT_STRUCT ); CreateCopy ( CIFTag ,CIFTAG_SOURCE ); } ERROR_CODE Source::ConvertPDBASCII ( cpstr S ) { if (strlen(S)>10) CreateCopy ( Line,&(S[10]) ); else CreateCopy ( Line,pstr(" ") ); return Error_NoError; } void Source::PDBASCIIDump ( pstr S, int N ) { if (N==0) strcpy ( S,"SOURCE " ); else sprintf ( S,"SOURCE %2i",N+1 ); strcat ( S,Line ); } void Source::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); ContString::write ( f ); } void Source::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); ContString::read ( f ); } MakeStreamFunctions(Source) // =================== KeyWords ====================== KeyWords::KeyWords() : io::Stream() { Init(); } KeyWords::KeyWords ( cpstr S ) : io::Stream() { Init(); ConvertPDBASCII ( S ); } KeyWords::KeyWords ( io::RPStream Object ) : io::Stream(Object) { Init(); } KeyWords::~KeyWords() { Delete(); } void KeyWords::Init() { nKeyWords = 0; KeyWord = NULL; Cont = false; } void KeyWords::Delete() { int i; if (KeyWord) { for (i=0;i0) && (L[m]==' ')) m--; // remove padding spaces m++; L[m] = char(0); if (Cont) CreateConcat ( KeyWord[nKeyWords],L ); else CreateCopy ( KeyWord[nKeyWords],L ); if (S[i]==',') { i++; Cont = false; } else Cont = true; nKeyWords++; } return 0; } void KeyWords::PDBASCIIDump ( io::RFile f ) { int N,i,k,m1,m2,ms; char S[85]; char c; if (KeyWord) { N = 0; i = 0; while (i70) { CIF->PutString ( S,CIFCAT_STRUCT_KEYWORDS,CIFTAG_TEXT,true ); if (k>(int)sizeof(S)) { CIF->PutString ( KeyWord[i],CIFCAT_STRUCT_KEYWORDS, CIFTAG_TEXT,true ); k = 0; } strcpy ( S,"\n" ); } if (k>0) { strcat ( S,KeyWord[i] ); if (i1) CIF->PutString ( S,CIFCAT_STRUCT_KEYWORDS,CIFTAG_TEXT,true ); } void KeyWords::GetCIF ( mmcif::PData CIF ) { pstr F; int i,j,k; bool NB; char c; Delete(); F = CIF->GetString ( CIFCAT_STRUCT_KEYWORDS,CIFTAG_TEXT,i ); k = 0; if ((!i) && F) { i = 0; NB = false; while (F[i]) { if (F[i]==',') { nKeyWords++; NB = false; } else if (F[i]!=' ') NB = true; i++; } if (NB) nKeyWords++; KeyWord = new pstr[nKeyWords]; i = 0; while (F[i] && (kDeleteField ( CIFCAT_STRUCT_KEYWORDS,CIFTAG_TEXT ); } void KeyWords::Copy ( PKeyWords KeyWords ) { int i; Delete(); nKeyWords = KeyWords->nKeyWords; if (nKeyWords>0) { KeyWord = new pstr[nKeyWords]; for (i=0;iKeyWord[i] ); } } } void KeyWords::write ( io::RFile f ) { int i; byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &nKeyWords ); for (i=0;i0) { KeyWord = new pstr[nKeyWords]; for (i=0;i10) CreateCopy ( Line,&(S[10]) ); else CreateCopy ( Line,pstr(" ") ); return Error_NoError; } void ExpData::PDBASCIIDump ( pstr S, int N ) { if (N==0) strcpy ( S,"EXPDTA " ); else sprintf ( S,"EXPDTA %2i",N+1 ); strcat ( S,Line ); } void ExpData::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); ContString::write ( f ); } void ExpData::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); ContString::read ( f ); } MakeStreamFunctions(ExpData) // =================== MdlType ====================== MdlType::MdlType() : ContString() { InitMdlType(); } MdlType::MdlType ( cpstr S ) : ContString() { InitMdlType(); ConvertPDBASCII ( S ); } MdlType::MdlType ( io::RPStream Object ) : ContString(Object) { InitMdlType(); } MdlType::~MdlType() {} void MdlType::InitMdlType() { CreateCopy ( CIFCategory,CIFCAT_EXPTL ); CreateCopy ( CIFTag ,CIFTAG_METHOD ); } ERROR_CODE MdlType::ConvertPDBASCII ( cpstr S ) { if (strlen(S)>10) CreateCopy ( Line,&(S[10]) ); else CreateCopy ( Line,pstr(" ") ); return Error_NoError; } void MdlType::PDBASCIIDump ( pstr S, int N ) { if (N==0) strcpy ( S,"MDLTYP " ); else sprintf ( S,"MDLTYP %2i",N+1 ); strcat ( S,Line ); } void MdlType::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); ContString::write ( f ); } void MdlType::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); ContString::read ( f ); } MakeStreamFunctions(MdlType) // =================== Author ====================== Author::Author() : ContString() { InitAuthor(); } Author::Author ( cpstr S ) : ContString() { InitAuthor(); ConvertPDBASCII ( S ); } Author::Author ( io::RPStream Object ) : ContString(Object) { InitAuthor(); } Author::~Author() {} void Author::InitAuthor() { CreateCopy ( CIFCategory,CIFCAT_AUDIT_AUTHOR ); CreateCopy ( CIFTag ,CIFTAG_NAME ); } ERROR_CODE Author::ConvertPDBASCII ( cpstr S ) { if (strlen(S)>10) CreateCopy ( Line,&(S[10]) ); else CreateCopy ( Line,pstr(" ") ); return Error_NoError; } void Author::PDBASCIIDump ( pstr S, int N ) { if (N==0) strcpy ( S,"AUTHOR " ); else sprintf ( S,"AUTHOR %2i",N+1 ); strcat ( S,Line ); } void Author::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); ContString::write ( f ); } void Author::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); ContString::read ( f ); } MakeStreamFunctions(Author) // ================ RevData =================== RevData::RevData() : ContainerClass() { InitRevData(); } RevData::RevData ( cpstr S ) : ContainerClass() { InitRevData(); ConvertPDBASCII ( S ); } RevData::RevData ( io::RPStream Object ) : ContainerClass(Object) { InitRevData(); } RevData::~RevData() {} void RevData::InitRevData() { int i; modNum = 0; strcpy ( modDate,"DD-MMM-YYYY" ); strcpy ( modId , "----" ); modType = -1; for (i=0;i<4;i++) strcpy ( record[i]," " ); Warning = 0; } void RevData::PDBASCIIDump ( pstr S, int N ) { // makes the ASCII PDB REVDATA line number N // from the class' data int i; if (N==0) sprintf ( S,"REVDAT %3i " ,modNum ); else sprintf ( S,"REVDAT %3i%2i",modNum,N+1 ); i = strlen(S); while (i<80) S[i++] = ' '; S[i] = char(0); Date11to9 ( modDate,&(S[13]) ); strncpy ( &(S[23]),modId,5 ); S[31] = char(modType+int('0')); for (i=0;i<4;i++) strncpy ( &(S[39+i*7]),record[i],6 ); } void RevData::MakeCIF ( mmcif::PData CIF, int N ) { mmcif::PLoop Loop; int RC,i,j; char DateCIF[20]; RC = CIF->AddLoop ( CIFCAT_DATABASE_PDB_REV,Loop ); if ((RC!=mmcif::CIFRC_Ok) || (N==0)) { // the category was (re)created, privide tags Loop->AddLoopTag ( CIFTAG_NUM ); Loop->AddLoopTag ( CIFTAG_DATE ); Loop->AddLoopTag ( CIFTAG_REPLACES ); Loop->AddLoopTag ( CIFTAG_MOD_TYPE ); Loop->AddLoopTag ( CIFTAG_RCSB_RECORD_REVISED_1 ); Loop->AddLoopTag ( CIFTAG_RCSB_RECORD_REVISED_2 ); Loop->AddLoopTag ( CIFTAG_RCSB_RECORD_REVISED_3 ); Loop->AddLoopTag ( CIFTAG_RCSB_RECORD_REVISED_4 ); } Date11toCIF ( modDate,DateCIF ); Loop->AddInteger ( modNum ); Loop->AddString ( DateCIF ); Loop->AddString ( modId ); Loop->AddInteger ( modType ); for (i=0;i<4;i++) { j = 0; while (record[i][j] && (record[i][j]==' ')) j++; if (record[i][j]) Loop->AddString ( record[i] ); else Loop->AddString ( NULL ); } } ERROR_CODE RevData::GetCIF ( mmcif::PData CIF, int & n ) { mmcif::PLoop Loop; int RC; pstr F; Loop = CIF->GetLoop ( CIFCAT_DATABASE_PDB_REV ); if (!Loop) { n = -1; return Error_EmptyCIF; } RC = Loop->GetInteger ( modNum,CIFTAG_NUM,n,true ); if (RC==mmcif::CIFRC_WrongIndex) { n = -1; return Error_EmptyCIF; } if (RC==mmcif::CIFRC_WrongFormat) { sprintf ( CIFErrorLocation,"loop %s.%s row %i", CIFCAT_DATABASE_PDB_REV,CIFTAG_NUM,n ); n = -Error_UnrecognizedInteger-1; return Error_UnrecognizedInteger; } F = Loop->GetString ( CIFTAG_DATE,n,RC ); if ((!RC) && F) DateCIFto11 ( F,modDate ); F = Loop->GetString ( CIFTAG_REPLACES,n,RC ); if ((!RC) && F) strcpy ( modId,F ); RC = Loop->GetInteger ( modType,CIFTAG_MOD_TYPE,n,true ); if (RC==mmcif::CIFRC_WrongFormat) { sprintf ( CIFErrorLocation,"loop %s.%s row %i", CIFCAT_DATABASE_PDB_REV,CIFTAG_MOD_TYPE,n ); n = -Error_UnrecognizedInteger-1; return Error_UnrecognizedInteger; } F = Loop->GetString ( CIFTAG_RCSB_RECORD_REVISED_1,n,RC ); if ((!RC) && F) strcpy ( record[0],F ); F = Loop->GetString ( CIFTAG_RCSB_RECORD_REVISED_2,n,RC ); if ((!RC) && F) strcpy ( record[1],F ); F = Loop->GetString ( CIFTAG_RCSB_RECORD_REVISED_3,n,RC ); if ((!RC) && F) strcpy ( record[2],F ); F = Loop->GetString ( CIFTAG_RCSB_RECORD_REVISED_4,n,RC ); if ((!RC) && F) strcpy ( record[3],F ); Loop->DeleteField ( CIFTAG_DATE ,n ); Loop->DeleteField ( CIFTAG_REPLACES ,n ); Loop->DeleteField ( CIFTAG_RCSB_RECORD_REVISED_1,n ); Loop->DeleteField ( CIFTAG_RCSB_RECORD_REVISED_2,n ); Loop->DeleteField ( CIFTAG_RCSB_RECORD_REVISED_3,n ); Loop->DeleteField ( CIFTAG_RCSB_RECORD_REVISED_4,n ); n++; return Error_NoError; } ERROR_CODE RevData::ConvertPDBASCII ( cpstr S ) { int i; pstr endptr; char N[20]; Warning = 0; strncpy ( N,&(S[7]),3 ); N[3] = char(0); modNum = mround(strtod(N,&endptr)); if (endptr==N) Warning |= REVDAT_WARN_MODNUM; Date9to11 ( &(S[13]),modDate ); strncpy ( modId,&(S[23]),5 ); modId[5] = char(0); modType = int(S[31]) - int('0'); if (modType>9) Warning |= REVDAT_WARN_MODTYPE; for (i=0;i<4;i++) { strncpy ( record[i],&(S[39+i*7]),6 ); record[i][6] = char(0); } return Error_NoError; } void RevData::Copy ( PContainerClass RevData ) { int i; modNum = PRevData(RevData)->modNum; modType = PRevData(RevData)->modType; strcpy ( modDate,PRevData(RevData)->modDate ); strcpy ( modId ,PRevData(RevData)->modId ); for (i=0;i<4;i++) strcpy ( record[i],PRevData(RevData)->record[i] ); } void RevData::write ( io::RFile f ) { int i; byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &modNum ); f.WriteInt ( &modType ); f.WriteWord ( &Warning ); f.WriteTerLine ( modDate,false ); f.WriteTerLine ( modId ,false ); for (i=0;i<4;i++) f.WriteTerLine ( record[i],false ); } void RevData::read ( io::RFile f ) { int i; byte Version; f.ReadByte ( &Version ); f.ReadInt ( &modNum ); f.ReadInt ( &modType ); f.ReadWord ( &Warning ); f.ReadTerLine ( modDate,false ); f.ReadTerLine ( modId ,false ); for (i=0;i<4;i++) f.ReadTerLine ( record[i],false ); } MakeStreamFunctions(RevData) // ================ Supersede =================== Supersede::Supersede() : ContainerClass() { InitSupersede(); } Supersede::Supersede ( cpstr S ) : ContainerClass() { InitSupersede(); ConvertPDBASCII ( S ); } Supersede::Supersede ( io::RPStream Object ) : ContainerClass(Object) { InitSupersede(); } Supersede::~Supersede() {} void Supersede::InitSupersede() { int i; strcpy ( sprsdeDate,"DD-MMM-YYYY" ); strcpy ( idCode, "----" ); for (i=0;i<8;i++) strcpy ( sIdCode[i]," " ); } void Supersede::PDBASCIIDump ( pstr S, int N ) { // makes the ASCII PDB OBSLTE line number N // from the class' data int i; if (N==0) strcpy ( S,"SPRSDE " ); else sprintf ( S,"SPRSDE %2i",N+1 ); i = strlen(S); while (i<80) S[i++] = ' '; S[i] = char(0); if (N==0) { Date11to9 ( sprsdeDate,&(S[11]) ); strncpy ( &(S[21]),idCode,4 ); } for (i=0;i<8;i++) strncpy ( &(S[31+5*i]),sIdCode[i],4 ); } void Supersede::MakeCIF ( mmcif::PData CIF, int ) { mmcif::PLoop Loop; int RC,i,j; char DateCIF[20]; RC = CIF->AddLoop ( CIFCAT_SPRSDE,Loop ); if (RC!=mmcif::CIFRC_Ok) { // the category was (re)created, privide tags Loop->AddLoopTag ( CIFTAG_ID ); Loop->AddLoopTag ( CIFTAG_DATE ); Loop->AddLoopTag ( CIFTAG_REPLACE_PDB_ID ); Loop->AddLoopTag ( CIFTAG_PDB_ID ); } Date11toCIF ( sprsdeDate,DateCIF ); for (i=0;i<8;i++) { j = 0; while (sIdCode[i][j] && (sIdCode[i][j]==' ')) j++; if (sIdCode[i][j]) { Loop->AddString ( pstr("SPRSDE") ); Loop->AddString ( DateCIF ); Loop->AddString ( idCode ); Loop->AddString ( sIdCode[i] ); } } } ERROR_CODE Supersede::ConvertPDBASCII ( cpstr S ) { int i; if (S[9]==' ') { Date9to11 ( &(S[11]),sprsdeDate ); strncpy ( idCode,&(S[21]),4 ); idCode[4] = char(0); } for (i=0;i<8;i++) { strncpy ( sIdCode[i],&(S[31+i*5]),4 ); sIdCode[i][4] = char(0); } return Error_NoError; } ERROR_CODE Supersede::GetCIF ( mmcif::PData CIF, int & n ) { mmcif::PLoop Loop; int i,RC; pstr F,FDate,FID; char DateCIF [20]; char DateCIF0[20]; IDCode idCode1; Loop = CIF->GetLoop ( CIFCAT_SPRSDE ); if (!Loop) { n = -1; // signal to finish processing of this structure return Error_EmptyCIF; } i = 0; do { F = Loop->GetString ( CIFTAG_ID,n,RC ); if (RC) { if (i==0) { n = -1; return Error_EmptyCIF; } else return Error_NoError; } if (F) { if (!strcmp(F,"SPRSDE")) { FDate = Loop->GetString ( CIFTAG_DATE,n,RC ); if ((!RC) && FDate) strncpy ( DateCIF,FDate,15 ); else strcpy ( DateCIF,"YYYY-MMM-DD" ); FID = Loop->GetString ( CIFTAG_REPLACE_PDB_ID,n,RC ); if ((!RC) && FID) strncpy ( idCode1,FID,sizeof(IDCode)-1 ); else idCode1[0] = char(0); if (i==0) { DateCIFto11 ( DateCIF,sprsdeDate ); DateCIF[11] = char(0); strcpy ( idCode ,idCode1 ); strcpy ( DateCIF0,DateCIF ); } else if ((strcmp(DateCIF0,DateCIF)) || (strcmp(idCode,idCode1))) return Error_NoError; FID = Loop->GetString ( CIFTAG_PDB_ID,n,RC ); if ((!RC) && FID) strncpy ( sIdCode[i],FID,sizeof(IDCode)-1 ); else sIdCode[i][0] = char(0); Loop->DeleteField ( CIFTAG_ID ,n ); Loop->DeleteField ( CIFTAG_DATE ,n ); Loop->DeleteField ( CIFTAG_REPLACE_PDB_ID,n ); Loop->DeleteField ( CIFTAG_PDB_ID ,n ); i++; } } n++; } while (i<8); return Error_NoError; } void Supersede::Copy ( PContainerClass Supersede ) { int i; strcpy ( sprsdeDate,PSupersede(Supersede)->sprsdeDate ); strcpy ( idCode ,PSupersede(Supersede)->idCode ); for (i=0;i<8;i++) strcpy ( sIdCode[i],PSupersede(Supersede)->sIdCode[i] ); } void Supersede::write ( io::RFile f ) { int i; byte Version=1; f.WriteByte ( &Version ); f.WriteTerLine ( sprsdeDate,false ); f.WriteTerLine ( idCode ,false ); for (i=0;i<8;i++) f.WriteTerLine ( sIdCode[i],false ); } void Supersede::read ( io::RFile f ) { int i; byte Version; f.ReadByte ( &Version ); f.ReadTerLine ( sprsdeDate,false ); f.ReadTerLine ( idCode ,false ); for (i=0;i<8;i++) f.ReadTerLine ( sIdCode[i],false ); } MakeStreamFunctions(Supersede) // =================== Journal ====================== Journal::Journal() : ContString() { InitJournal(); } Journal::Journal ( cpstr S ) : ContString() { InitJournal(); ConvertPDBASCII ( S ); } Journal::Journal ( io::RPStream Object ) : ContString(Object) { InitJournal(); } Journal::~Journal() {} void Journal::InitJournal() { CreateCopy ( CIFCategory,CIFCAT_CITATION ); CreateCopy ( CIFTag ,CIFTAG_TEXT ); } ERROR_CODE Journal::ConvertPDBASCII ( cpstr S ) { if (strlen(S)>10) CreateCopy ( Line,&(S[10]) ); else CreateCopy ( Line,pstr(" ") ); return Error_NoError; } void Journal::PDBASCIIDump ( pstr S, int ) { strcpy ( S,"JRNL " ); strcat ( S,Line ); } void Journal::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); ContString::write ( f ); } void Journal::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); ContString::read ( f ); } MakeStreamFunctions(Journal) // =================== Remark ====================== Remark::Remark() : ContainerClass() { InitRemark(); } Remark::Remark ( cpstr S ) : ContainerClass() { InitRemark(); ConvertPDBASCII ( S ); } Remark::Remark ( io::RPStream Object ) : ContainerClass(Object) { InitRemark(); } Remark::~Remark() { if (remark) delete[] remark; } void Remark::InitRemark() { remarkNum = 0; remark = NULL; } ERROR_CODE Remark::ConvertPDBASCII ( cpstr S ) { int i; GetInteger ( remarkNum,&(S[7]),3 ); if (remarkNum==MinInt4) CreateCopy ( remark,S ); else if (strlen(S)>11) CreateCopy ( remark,&(S[11]) ); else CreateCopy ( remark,pstr(" ") ); i = strlen(remark)-1; while ((i>0) && (remark[i]==' ')) i--; remark[i+1] = char(0); return Error_NoError; } void Remark::PDBASCIIDump ( pstr S, int ) { if (remarkNum==MinInt4) strcpy ( S,remark ); else { strcpy ( S,"REMARK" ); PadSpaces ( S,80 ); PutInteger ( &(S[7]) ,remarkNum,3 ); strncpy ( &(S[11]),remark,IMin(68,strlen(remark)) ); } } void Remark::MakeCIF ( mmcif::PData CIF, int N ) { mmcif::PLoop Loop; int RC; RC = CIF->AddLoop ( CIFCAT_NDB_DATABASE_REMARK,Loop ); if ((RC!=mmcif::CIFRC_Ok) || (N==0)) { // the category was (re)created, privide tags Loop->AddLoopTag ( CIFTAG_ID ); Loop->AddLoopTag ( CIFTAG_TEXT ); } if (remarkNum==MinInt4) Loop->AddString ( NULL ); else Loop->AddInteger ( remarkNum ); Loop->AddString ( remark ); } ERROR_CODE Remark::GetCIF ( mmcif::PData CIF, int & n ) { mmcif::PLoop Loop; int RC; Loop = CIF->GetLoop ( CIFCAT_NDB_DATABASE_REMARK ); if (!Loop) { n = -1; return Error_EmptyCIF; } if (n>=Loop->GetLoopLength() ) { n = -1; return Error_EmptyCIF; } RC = Loop->GetInteger ( remarkNum,CIFTAG_ID,n,true ); if (RC==mmcif::CIFRC_WrongFormat) { sprintf ( CIFErrorLocation,"loop %s.%s row %i", CIFCAT_NDB_DATABASE_REMARK,CIFTAG_ID,n ); n = -Error_UnrecognizedInteger-1; return Error_UnrecognizedInteger; } else if (RC) remarkNum = MinInt4; Loop->GetString ( remark,CIFTAG_TEXT,n,true ); n++; return Error_NoError; } void Remark::Copy ( PContainerClass RemarkClass ) { remarkNum = PRemark(RemarkClass)->remarkNum; CreateCopy ( remark,PRemark(RemarkClass)->remark ); } void Remark::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &remarkNum ); f.CreateWrite ( remark ); } void Remark::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.ReadInt ( &remarkNum ); f.CreateRead ( remark ); } MakeStreamFunctions(Remark) // ================= Biomolecule ===================== #define R350_ERRBIOMT (-3) #define R350_ERROR (-2) #define R350_END (-1) #define R350_NONE 0 #define R350_BIOMOLECULE 1 #define R350_CHAINS 2 #define R350_BIOMT 3 void getRemarkKey ( RPRemark rem, int & lkey ) { if (rem) { if (rem->remarkNum!=350) lkey = R350_END; else if (rem->remark) { if (strcasestr(rem->remark,"BIOMOLECULE:")) lkey = R350_BIOMOLECULE; else if (strcasestr(rem->remark,"CHAINS:")) lkey = R350_CHAINS; else if (strcasestr(rem->remark,"BIOMT1") || strcasestr(rem->remark,"BIOMT2") || strcasestr(rem->remark,"BIOMT3")) lkey = R350_BIOMT; else lkey = R350_NONE; } } } int lookupRemarks ( int & i, RPRemark rem, RTitleContainer Remark ) { int l,lkey; l = Remark.Length(); lkey = R350_NONE; while ((iremark,"CHAINS:" ); if (p) p += 7; else { p = rem->remark; while (*p==' ') p++; if ((p[1]!=',') && (p[1]!=' ')) p = NULL; } if (p) { nAdd = strlen(p)/2 + 3; ch1 = chain; chain = new ChainID[nChains+nAdd]; for (j=0;jremarkNum!=350) lkey = R350_END; else getRemarkKey ( rem,lkey ); } } else lkey = R350_END; } while ((!rem) && (lkey==R350_NONE)); } return lkey; } int getBIOMT ( RPRemark rem, int biomtNo, mat44 & t, RTitleContainer Remark, int & i ) { char PN[20]; pstr p1,p2; int l,j,lkey; sprintf ( PN,"BIOMT%1i",biomtNo ); p1 = strcasestr ( rem->remark,PN ); if (!p1) return R350_ERRBIOMT; p1 += 6; while (*p1==' ') p1++; while (*p1 && (*p1!=' ')) p1++; l = biomtNo - 1; t[l][0] = strtod ( p1,&p2 ); if (p1==p2) return R350_ERRBIOMT; t[l][1] = strtod ( p2,&p1 ); if (p1==p2) return R350_ERRBIOMT; t[l][2] = strtod ( p1,&p2 ); if (p1==p2) return R350_ERRBIOMT; t[l][3] = strtod ( p2,&p1 ); if (p1==p2) return R350_ERRBIOMT; if (biomtNo==3) { for (j=0;j<3;j++) t[3][j] = 0.0; t[3][3] = 1.0; } l = Remark.Length(); lkey = R350_BIOMT; do { i++; if (iremarkNum!=350) lkey = R350_END; else getRemarkKey ( rem,lkey ); } } else lkey = R350_END; } while ((lkey==R350_NONE) || ((!rem) && (lkey==R350_BIOMT))); return lkey; } int BMApply::addMatrices ( int & i, RPRemark rem, RTitleContainer Remark ) { pmat44 tm1; int l,lkey,j,k1,k2,nAlloc; l = Remark.Length(); lkey = R350_BIOMT; nAlloc = nMatrices; while ((i=nAlloc) { nAlloc = nMatrices + 10; tm1 = tm; tm = new mat44[nAlloc]; for (j=0;jnChains; if (nChains>0) { chain = new ChainID[nChains]; for (i=0;ichain[i] ); } nMatrices = BMA->nMatrices; if (nMatrices>0) { tm = new mat44[nMatrices]; for (i=0;itm[i][j][k]; } } } void BMApply::write ( io::RFile f ) { int i,j,k; f.WriteInt ( &nChains ); for (i=0;i0) { chain = new ChainID[nChains]; for (i=0;i0) { tm = new mat44[nMatrices]; for (i=0;inChains*bmApply[i]->nMatrices; return k; } bool Biomolecule::checkComposition ( PChainID chID, ivector occ, ivector wocc, int n ) { // chID[n] is list of chain IDs // occ[n] is list of chain occurencies // wocc[n] is working array int i,j,k,k1; bool cmp; for (i=0;inChains) && cmp;j++) { k1 = -1; for (k=0;(kchain[j])) k1 = k; if (k1<0) cmp = false; // chain not found in the list else wocc[k1] += bmApply[i]->nMatrices; } for (i=0;(inBMAs; if (nBMAs>0) { bmApply = new PBMApply[nBMAs]; for (i=0;ibmApply[i]) { bmApply[i] = new BMApply(); bmApply[i]->Copy ( B->bmApply[i] ); } else bmApply[i] = NULL; } } } void Biomolecule::write ( io::RFile f ) { int i; f.WriteInt ( &nBMAs ); for (i=0;i0) { bmApply = new PBMApply[nBMAs]; for (i=0;i=10) && (PDBString[i]==' ')) i--; i++; c = PDBString[i]; PDBString[i] = char(0); CreateCopy ( classification,&(PDBString[10]) ); PDBString[i] = c; Date9to11 ( &(PDBString[50]),depDate ); strncpy ( idCode,&(PDBString[62]),4 ); idCode[4] = char(0); } else if (!strncmp(PDBString,"OBSLTE",6)) { ContainerClass = new ObsLine(PDBString); obsData.AddData ( ContainerClass ); } else if (!strncmp(PDBString,"TITLE ",6)) { ContainerClass = new TitleLine(PDBString); title.AddData ( ContainerClass ); } else if (!strncmp(PDBString,"CAVEAT",6)) { ContainerClass = new Caveat(PDBString); caveat.AddData ( ContainerClass ); } else if (!strncmp(PDBString,"COMPND",6)) { ContainerClass = new Compound(PDBString); compound.AddData ( ContainerClass ); } else if (!strncmp(PDBString,"SOURCE",6)) { ContainerClass = new Source(PDBString); source.AddData ( ContainerClass ); } else if (!strncmp(PDBString,"KEYWDS",6)) { keyWords.ConvertPDBASCII ( PDBString ); } else if (!strncmp(PDBString,"EXPDTA",6)) { ContainerClass = new ExpData(PDBString); expData.AddData ( ContainerClass ); } else if (!strncmp(PDBString,"MDLTYPE",6)) { ContainerClass = new MdlType(PDBString); mdlType.AddData ( ContainerClass ); } else if (!strncmp(PDBString,"AUTHOR",6)) { ContainerClass = new Author(PDBString); author.AddData ( ContainerClass ); } else if (!strncmp(PDBString,"REVDAT",6)) { ContainerClass = new RevData(PDBString); revData.AddData ( ContainerClass ); } else if (!strncmp(PDBString,"SPRSDE",6)) { ContainerClass = new Supersede(PDBString); supersede.AddData ( ContainerClass ); } else if (!strncmp(PDBString,"JRNL ",6)) { ContainerClass = new Journal(PDBString); journal.AddData ( ContainerClass ); } else if (!strncmp(PDBString,"REMARK",6)) { ContainerClass = new Remark(PDBString); remark.AddData ( ContainerClass ); } else if (!strncmp(PDBString,"SPLIT ",6)) { // do nothing at the moment } else return Error_WrongSection; // check for ID code in columns 73-80 if (!col73) { if (('0'<=idCode[0]) && (idCode[0]<='9')) { if (!strncasecmp(idCode,&(PDBString[72]),4)) col73 = true; } } return Error_NoError; } realtype Title::GetResolution() { // returns -1.0 if there is no resolution record in the file PRemark rem; pstr p,eptr; int i,l; if (resolution>-1.5) return resolution; l = remark.Length(); for (i=0;(iremarkNum==2) { if (rem->remark) { p = strcasestr ( rem->remark,"RESOLUTION" ); if (p) { while ((*p) && (*p!=' ')) p++; if (*p) { resolution = strtod ( p,&eptr ); if ((resolution<0.0) || (eptr==p)) resolution = -1.0; } } } } else if (rem->remarkNum>2) resolution = -1.0; } } return resolution; } PBiomolecule Title::addBiomolecule() { PPBiomolecule BM1; int i; BM1 = biomolecule; biomolecule = new PBiomolecule[nBiomolecules+1]; for (i=0;iremarkNum==350) lkey = 1; else if (rem->remarkNum>350) lkey = -1; } if (!lkey) i++; } BMol = NULL; BMA = NULL; while (lkey>0) { rem = (PRemark)remark.GetContainerClass ( i ); lkey = lookupRemarks ( i,rem,remark ); switch (lkey) { case R350_BIOMOLECULE : BMol = addBiomolecule(); i++; break; case R350_CHAINS : if (BMol) { BMA = BMol->addBMApply(); while (lkey==R350_CHAINS) lkey = BMA->addChains(i,rem,remark); } else lkey = R350_ERROR; break; case R350_BIOMT : if (BMA) lkey = BMA->addMatrices(i,rem,remark); else lkey = R350_ERROR; break; default : i++; } } if (lkey<=R350_ERROR) { FreeBiomolecules(); return lkey; } return nBiomolecules; } int Title::GetNofBiomolecules() { return nBiomolecules; } void Title::GetBiomolecules ( PPBiomolecule & BM, int & nBMs ) { BM = biomolecule; nBMs = nBiomolecules; } PBiomolecule Title::GetBiomolecule ( int bmNo ) { // bmno=0,1,.. if ((0<=bmNo) && (bmNoGetDataName ( S,true ); if (!S) CIF->GetString ( S,CIFCAT_DATABASE,CIFTAG_ENTRY_ID,true ); if (!S) CIF->GetString ( S,CIFCAT_DATABASE,CIFTAG_CODE_NDB,true ); if (!S) CIF->GetString ( S,CIFCAT_DATABASE,CIFTAG_CODE_PDB,true ); if (S) { strncpy ( idCode,S,sizeof(IDCode)-1 ); idCode[sizeof(IDCode)-1] = char(0); delete[] S; S = NULL; CIF->DeleteField ( CIFCAT_DATABASE,CIFTAG_ENTRY_ID ); CIF->DeleteField ( CIFCAT_DATABASE,CIFTAG_CODE_NDB ); CIF->DeleteField ( CIFCAT_DATABASE,CIFTAG_CODE_PDB ); } else idCode[0] = char(0); CIF->GetString ( classification,CIFCAT_STRUCT_KEYWORDS, CIFTAG_NDB_KEYWORDS,true ); CIF->GetString ( S,CIFCAT_DATABASE,CIFTAG_DATE_ORIGINAL,true ); if (S) { DateCIFto11 ( S,depDate ); delete[] S; S = NULL; } else depDate[0] = char(0); if (CIF->GetReal(resolution,CIFCAT_REFINE, CIFTAG_LS_D_RES_HIGH,false)!=mmcif::CIFRC_Ok) resolution = -2.0; obsData .GetCIF ( CIF,ClassID_ObsLine ); title .GetCIF ( CIF,ClassID_TitleLine ); caveat .GetCIF ( CIF,ClassID_CAVEAT ); compound.GetCIF ( CIF,ClassID_Compound ); source .GetCIF ( CIF,ClassID_Source ); keyWords.GetCIF ( CIF ); expData .GetCIF ( CIF,ClassID_ExpData ); mdlType .GetCIF ( CIF,ClassID_MdlType ); author .GetCIF ( CIF,ClassID_Author ); RC = revData.GetCIF ( CIF,ClassID_RevData ); if (RC!=Error_NoError) { supersede.GetCIF ( CIF,ClassID_Supersede ); journal .GetCIF ( CIF,ClassID_Journal ); RC = remark.GetCIF ( CIF,ClassID_Remark ); } return RC; } void Title::MakePDBHeaderString ( pstr PDBString ) { // makes the ASCII PDB HEADER line from the class' data int i; if (classification) { strcpy ( PDBString,"HEADER " ); strcat ( PDBString,classification ); i = strlen(PDBString); while (i<80) PDBString[i++] = ' '; PDBString[IMin(i,80)] = char(0); Date11to9 ( depDate,&(PDBString[50]) ); strncpy ( &(PDBString[62]),idCode,4 ); } else strcpy ( PDBString, "HEADER XXXXXXXXXXXXXXXXXXXXXXXXXXXX XX-XXX-XX ----" ); } pstr Title::GetStructureTitle ( pstr & S ) { // GetStructureTitle() returns the contents of TITLE record // unfolded into single line. If Title is missing, returns // contents of COMPND(:MOLECULE). If COMPND is missing, returns // HEADER. If Header is missing, returns PDB code. If no PDB // code is there, returns "Not available". PTitleLine TLine; PCompound CLine; pstr p; int i,cl,l; bool B; if (S) delete[] S; S = NULL; cl = title.Length(); if (cl>0) { l = 0; for (i=0;iLine)+5; } S = new char[l]; S[0] = char(0); for (i=0;i0) strcat ( S," " ); strcat_des ( S,TLine->Line ); } } } else { cl = compound.Length(); if (cl>0) { l = 0; p = NULL; B = true; for (i=0;(iLine,"MOLECULE:"); if (p) l += strlen_des(&(p[9]))+5; } else { p = strstr(CLine->Line,"MOLECULE:"); if (p) l += strlen_des(&(p[9]))+5; else { p = strchr(CLine->Line,':'); if (!p) { l += strlen_des(CLine->Line)+5; p = CLine->Line; } else B = false; } } } } if (l>0) { S = new char[l]; S[0] = char(0); p = NULL; B = true; for (i=0;(iLine,"MOLECULE:"); if (p) strcat_des ( S,&(p[9]) ); } else { p = strstr(CLine->Line,"MOLECULE:"); if (p) strcat_des ( S,&(p[9]) ); else { p = strchr(CLine->Line,':'); if (!p) { strcat_des ( S,CLine->Line ); p = CLine->Line; } else B = false; } } l = strlen(S)-1; if (S[l]==';') S[l] = char(0); } } } else { l = 0; for (i=0;iLine)+5; } S = new char[l]; S[0] = char(0); for (i=0;i0) strcat ( S," " ); strcat_des ( S,CLine->Line ); } } } } else if (classification) CreateCopy ( S,classification ); else if (idCode[0]) CreateCopy ( S,idCode ); else CreateCopy ( S,pstr("Not available") ); } if (!S[0]) CreateCopy ( S,pstr("Not available") ); return S; } void Title::PDBASCIIDump ( io::RFile f ) { char PDBString[100]; if (classification) { MakePDBHeaderString ( PDBString ); f.WriteLine ( PDBString ); } obsData .PDBASCIIDump ( f ); title .PDBASCIIDump ( f ); caveat .PDBASCIIDump ( f ); compound .PDBASCIIDump ( f ); source .PDBASCIIDump ( f ); keyWords .PDBASCIIDump ( f ); expData .PDBASCIIDump ( f ); mdlType .PDBASCIIDump ( f ); author .PDBASCIIDump ( f ); revData .PDBASCIIDump ( f ); supersede.PDBASCIIDump ( f ); journal .PDBASCIIDump ( f ); remark .PDBASCIIDump ( f ); } void Title::MakeCIF ( mmcif::PData CIF ) { char DateCIF[20]; if (idCode[0]) { CIF->PutDataName ( idCode ); CIF->PutString ( idCode, CIFCAT_DATABASE,CIFTAG_ENTRY_ID ); CIF->PutString ( idCode, CIFCAT_DATABASE,CIFTAG_CODE_NDB ); CIF->PutString ( idCode, CIFCAT_DATABASE,CIFTAG_CODE_PDB ); } else { CIF->PutDataName ( pstr("") ); CIF->PutString ( NULL, CIFCAT_DATABASE,CIFTAG_ENTRY_ID ); CIF->PutString ( NULL, CIFCAT_DATABASE,CIFTAG_CODE_NDB ); CIF->PutString ( NULL, CIFCAT_DATABASE,CIFTAG_CODE_PDB ); } CIF->PutString ( classification, CIFCAT_STRUCT_KEYWORDS, CIFTAG_NDB_KEYWORDS ); if (depDate[0]) { Date11toCIF ( depDate,DateCIF ); CIF->PutString ( DateCIF,CIFCAT_DATABASE,CIFTAG_DATE_ORIGINAL ); } else CIF->PutString ( NULL,CIFCAT_DATABASE,CIFTAG_DATE_ORIGINAL ); CIF->PutReal ( resolution,CIFCAT_REFINE,CIFTAG_LS_D_RES_HIGH,3 ); obsData .MakeCIF ( CIF ); title .MakeCIF ( CIF ); caveat .MakeCIF ( CIF ); compound .MakeCIF ( CIF ); source .MakeCIF ( CIF ); keyWords .MakeCIF ( CIF ); expData .MakeCIF ( CIF ); mdlType .MakeCIF ( CIF ); author .MakeCIF ( CIF ); revData .MakeCIF ( CIF ); supersede.MakeCIF ( CIF ); journal .MakeCIF ( CIF ); remark .MakeCIF ( CIF ); } void Title::Copy ( PTitle TS ) { int i; FreeBiomolecules(); if (TS) { CreateCopy ( classification,TS->classification ); strcpy ( depDate ,TS->depDate ); strcpy ( idCode ,TS->idCode ); resolution = TS->resolution; obsData .Copy ( &(TS->obsData) ); title .Copy ( &(TS->title) ); caveat .Copy ( &(TS->caveat) ); compound .Copy ( &(TS->compound) ); source .Copy ( &(TS->source) ); keyWords .Copy ( &(TS->keyWords) ); expData .Copy ( &(TS->expData) ); mdlType .Copy ( &(TS->mdlType) ); author .Copy ( &(TS->author) ); revData .Copy ( &(TS->revData) ); supersede.Copy ( &(TS->supersede) ); journal .Copy ( &(TS->journal) ); remark .Copy ( &(TS->remark) ); nBiomolecules = TS->nBiomolecules; if (nBiomolecules>0) { biomolecule = new PBiomolecule[nBiomolecules]; for (i=0;ibiomolecule[i]) { biomolecule[i] = new Biomolecule(); biomolecule[i]->Copy ( TS->biomolecule[i] ); } else biomolecule[i] = NULL; } } else { if (classification) delete[] classification; classification = NULL; resolution = -2.0; obsData .FreeContainer(); title .FreeContainer(); caveat .FreeContainer(); compound .FreeContainer(); source .FreeContainer(); keyWords .Delete (); expData .FreeContainer(); mdlType .FreeContainer(); author .FreeContainer(); revData .FreeContainer(); supersede.FreeContainer(); journal .FreeContainer(); remark .FreeContainer(); } } void Title::TrimInput ( pstr PDBString ) { if (col73) { if (!strncasecmp(idCode,&(PDBString[72]),4)) PDBString[72] = char(0); } PadSpaces ( PDBString,80 ); } void Title::write ( io::RFile f ) { // writes header to PDB binary file int i; byte Version=3; f.WriteByte ( &Version ); // Header data f.CreateWrite ( classification ); f.WriteTerLine ( depDate,false ); f.WriteTerLine ( idCode ,false ); f.WriteReal ( &resolution ); obsData .write ( f ); // Obsoletion data title .write ( f ); // Title caveat .write ( f ); // Error data compound .write ( f ); // Compound source .write ( f ); // Source keyWords .write ( f ); // Key words expData .write ( f ); // Experimental data mdlType .write ( f ); // Model descriptions author .write ( f ); // Author data revData .write ( f ); // Revision data supersede.write ( f ); // Supersede records journal .write ( f ); // Journal records remark .write ( f ); // Remarks f.WriteInt ( &nBiomolecules ); for (i=0;i1) f.ReadReal ( &resolution ); else resolution = -2.0; obsData .read ( f ); // Obsoletion data title .read ( f ); // Title caveat .read ( f ); // Error data compound .read ( f ); // Compound source .read ( f ); // Source keyWords .read ( f ); // Key words expData .read ( f ); // Experimental data if (Version>2) mdlType.read ( f ); // Model descriptions author .read ( f ); // Author data revData .read ( f ); // Revision data supersede.read ( f ); // Supersede records journal .read ( f ); // Journal records remark .read ( f ); // Remarks FreeBiomolecules(); if (Version>1) { f.ReadInt ( &nBiomolecules ); if (nBiomolecules>0) { biomolecule = new PBiomolecule[nBiomolecules]; for (i=0;iSetHeader ( pstr("MUSCLE PROTEIN"),pstr("02-JUN-1993"),pstr("1MYS") ); Hdr->MakePDBHeaderString ( S ); printf ( "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890\n" ); printf ( S ); printf ( "\n" ); strcpy ( S, // 1234567890123456789012345678901234567890123456789012345678901234567890 "HEADER HYDROLASE (CARBOXYLIC ESTER) 07-APR-01 2PHI" ); Hdr->ConvertPDBString ( S ); Hdr->MakePDBHeaderString ( S1 ); printf ( "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890\n" ); printf ( S1 ); printf ( "\n" ); Hdr->SetHeader ( pstr("MUSCLE PROTEIN;**A VERY LONG TITLE TEST;**ARBITRARY LENGTH"), pstr("02-JUN-1993"),pstr("1MYS") ); Hdr->MakePDBHeaderString ( S ); printf ( "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890\n" ); printf ( S ); printf ( "\n" ); delete Hdr; printf ( " header deleted \n" ); } void TestTitle() { // reads PDB title from file 'in.title' // and rewrites it into 'out.title' and 'abin.title' CFile f; char S[81]; PTitle Title; Title = new Title(); f.assign ( pstr("in.title"),true ); if (f.reset()) { while (!f.FileEnd()) { f.ReadLine ( S,sizeof(S) ); Title->ConvertPDBString ( S ); } f.shut(); } else { printf ( " Can't open input file 'in.title' \n" ); delete Title; return; } f.assign ( pstr("out.title"),true ); if (f.rewrite()) { Title->PDBASCIIDump ( f ); f.shut(); } else { printf ( " Can't open output file 'out.title' \n" ); delete Title; return; } f.assign ( pstr("mmdb.title.bin"),false ); if (f.rewrite()) { Title->write ( f ); f.shut(); } else { printf ( " Can't open binary file for writing.\n" ); delete Title; return; } delete Title; printf ( " Title deleted.\n" ); Title = new Title(); if (f.reset()) { Title->read ( f ); f.shut(); } else { printf ( " Can't open binary file for reading.\n" ); delete Title; return; } f.assign ( pstr("abin.title"),true ); if (f.rewrite()) { Title->PDBASCIIDump ( f ); f.shut(); } else { printf ( " Can't open output file 'abin.title' \n" ); } delete Title; } */ mmdb2-2.0.5/mmdb2/mmdb_machine_.h0000664000175000017500000003232612401105774013365 00000000000000// $Id: mmdb_machine.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : Machine // ~~~~~~~~~ // **** Functions : mmdb::machine::GetMachineID - returns ID code // ~~~~~~~~~~~ for the machine // mmdb::machine::GetMachineName - returns name of // the machine // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_Machine__ #define __MMDB_Machine__ #include "mmdb_mattype.h" /* // Programs written in plain C, should define __PlainC each time // this header is invoked. #ifdef __PlainC # undef __CPlusPlus #else # define __CPlusPlus #endif */ namespace mmdb { namespace machine { // ================== List of known machines ================= enum MACHINE { MACHINE_SGI = 1, MACHINE_RS6000 = 2, MACHINE_ALLIANT = 3, MACHINE_ARDENT = 4, MACHINE_TITAN = 5, MACHINE_STARDENT = 6, MACHINE_CONVEX = 7, MACHINE_ESV = 8, MACHINE_HP9000 = 9, MACHINE_SOLBOURNE = 10, MACHINE_SOLARIS = 11, MACHINE_ALPHA = 12, MACHINE_VMS = 13, MACHINE_MVS = 14, MACHINE_F2C_G77 = 15, MACHINE_LINUX = 16, MACHINE_UNKNOWN = 100 }; // ============= Identification of the machine =============== // IBM Unix RS/6000 #if defined(_AIX) || defined(___AIX) # define CALL_LIKE_HPUX 1 // Alliant #elif defined(alliant) # define CALL_LIKE_SUN 1 // Ardent, Stardent/Titan #elif defined(ardent) # define CALL_LIKE_STARDENT 1 #elif defined(titan) # define CALL_LIKE_STARDENT 2 #elif defined(stardent) # define CALL_LIKE_STARDENT 3 // Convex #elif defined(__convex__) || defined(__convexc__) # define CALL_LIKE_SUN 2 // Evans and Sutherland #elif defined(ESV) # define CALL_LIKE_SUN 3 // Hewlett Packard 9000/750 (RISC) models #elif defined(__hpux) # define CALL_LIKE_HPUX 2 // Silicon Graphics IRIX systems, Iris'es, Indigo's, Crimson's etc. #elif defined(__sgi) || defined(sgi) # define CALL_LIKE_SUN 4 // Solbourne's are Sun clones. #elif defined(solbourne) # define CALL_LIKE_SUN 5 // Solaris 1 and 2 #elif defined(sun) || defined(__sun) # define CALL_LIKE_SUN 6 // DEC, OSF/1, Alpha and Ultrix #elif defined(ultrix) || defined(__OSF1__) || defined(__osf__) # define CALL_LIKE_SUN 7 // VMS #elif defined(vms) || defined(__vms) || defined(__VMS) # define CALL_LIKE_VMS 1 // MVS stands for Microsoft Visual Studio #elif defined(_MVS) # define CALL_LIKE_MVS 1 #elif defined(F2C) || defined(G77) # define CALL_LIKE_SUN 8 #elif defined(linux) # define CALL_LIKE_SUN 9 #else //# error System type is not known -- see the Installation Guide # define CALL_LIKE_SUN 100 #endif // ================= Machine-dependent definitions ================== #ifdef CALL_LIKE_STARDENT // StrPar is used in Ardent-like machines' fortran calls // for passing a string parameter DefineStructure(StrPar) struct StrPar { pstr S; int len; int id; }; #endif // // Macro FORTRAN_SUBR(NAME,name,p_send,p_struct,p_sflw) // makes function header statements that allow for linking with // programs written in FORTRAN. // // Parameters: // // NAME name of the FORTRAN subroutine in capital letters // name name of the FORTRAN subroutine in small letters // p_send parameter list (in brackets) with string lengths // attached to the end of it (see below) // p_struct parameter list (in brackets) with strings passed // as complex parameters, or structures // p_sflw parameter list (in brackets) with string lengths // following immediately the string parameters // (see below) // // All non-string parameters must be passed as pointers, in // the same order as they enter the FORTRAN call. Rules for // the string parameters are as follows. // // 1. All strings should be specified as of 'fpstr' type. // The 'fpstr' type is defined below and depends on the // platform: // // a) whenever length of string is passed as a separate // parameter ( CALL_LIKE_SUN, CALL_LIKE_HPUX, // CALL_LIKE_MVS ) 'fpstr' is identical to 'pstr'. // You may choose arbitrary name for the string, // but you MUST use the same name, appended with // suffix '_len', for its length (see example below). // // b) whenever string and its length are passed as // complex parameter, 'fpstr' is identical to the // pointer on the corresponding structure: // CALL_LIKE_STARDENT : // 'fpstr' is identical to 'PStrPar' // CALL_LIKE_VMS : // 'fpstr' is identical to 'dsc$descriptor_s *' // // With 'fpstr' type, two important macro definition come: // // i) FTN_STR(s) - returns pointer to fortran-passed // string s. This pointer is always // of 'pstr' type // ii) FTN_LEN(s) - returns integer length of fortran- // passed string s. For this macro to // work properly with SUN- and MVS-like // machines, always use suffix '_len' // for the string length parameters as // described in a) above. // // 2. Three parameter lists, each enclosed in brackets, should // be given. These lists retain the general order of // parameters in the corresponding fortran call. Non-string // parameters are passed as pointers. String parameters // and their lengths are passed differently in different // lists: // // p_send strings enter their place in the list as in // the corresponding FORTRAN call, having 'fpstr' // parameter type. Their lengths are appended as // 'int' to the end of the list. They should // retain the order in which the strings appear // in the list. // // p_struct strings enter their place in the list as in // the corresponding FORTRAN call, having 'fpstr' // parameter type. // // p_sflw strings enter their place in the list as in // the corresponding FORTRAN call, having 'fpstr' // type and being immediately followed by their // lengths as 'int' parameters. // // // // Example: // // FORTRAN statement // // subroutine SomeSub ( k,s1,a,s2,m ) // integer k,m // real a // character*(*) s1,s2 // // is translated to // // FORTRAN_SUBR ( SOMESUB, somesub, // ( int * k, fpstr s1, float * a, fpstr s2, int * m, // int s1_len, int s2_len ), // ( int * k, fpstr s1, float * a, fpstr s2, int * m ), // ( int * k, fpstr s1, int s1_len, float * a, // fpstr s2, int s2_len, int * m ) ) // // // The macro should replace ordinary function header // statements to assure compatibility with FORTRAN links. // In header files, do not forget to add semicolumn: // // FORTRAN_SUBR ( .... ); // // while in source files use simply // // FORTRAN_SUBR ( .... ) { // // } // // // // Macro FORTRAN_CALL(NAME,name,p_send,p_struct,p_sflw) // calls function defined with macro FORTRAN_SUBR(...), from // a C/C++ application. Its parameters and their meaning are // exactly identical to those of FORTRAN_SUBR(...). // FORTRAN_CALL(...) should be followed by semicolon. // // **** type of real numbers in the API functions // comment or uncomment the proper string typedef float apireal; // FORTRAN real*4 /* typedef double apireal; // FORTRAN real*8 */ #if defined(CALL_LIKE_SUN) typedef pstr fpstr; # define FTN_STR(s) s # define FTN_LEN(s) s##_len # define char_struct(s) \ mmdb::pstr s; \ int s##_len; # define fill_char_struct(s,str) \ s = str; \ s##_len = strlen(str); # ifdef __cplusplus # define FORTRAN_SUBR(NAME,name,p_sun,p_stardent,p_mvs) \ extern "C" void name##_ p_sun # else # define FORTRAN_SUBR(NAME,name,p_sun,p_stardent,p_mvs) \ void name##_ p_sun # endif # define FORTRAN_EXTERN(NAME,name,p_sun,p_stardent,p_mvs) \ extern "C" void name##_ p_sun # define FORTRAN_CALL(NAME,name,p_sun,p_stardent,p_mvs) \ name##_ p_sun # elif defined(CALL_LIKE_HPUX) typedef pstr fpstr; # define FTN_STR(s) s # define FTN_LEN(s) s##_len # define char_struct(s) \ pstr s; \ int s##_len; # define fill_char_struct(s,str) \ s = str; \ s##_len = strlen(str); # ifdef __cplusplus # define FORTRAN_SUBR(NAME,name,p_sun,p_stardent,p_mvs) \ extern "C" void name p_sun # else # define FORTRAN_SUBR(NAME,name,p_sun,p_stardent,p_mvs) \ void name p_sun # endif # define FORTRAN_EXTERN(NAME,name,p_sun,p_stardent,p_mvs) \ extern "C" void name p_sun # define FORTRAN_CALL(NAME,name,p_sun,p_stardent,p_mvs) \ name p_sun #elif defined(CALL_LIKE_STARDENT) typedef PStrPar fpstr; # define FTN_STR(s) s->S # define FTN_LEN(s) s->len # define char_struct(s) \ StrPar s; # define fill_char_struct(s,str) \ s.S = str; \ s.len = strlen(FName); \ s.id = 0; # ifdef __cplusplus # define FORTRAN_SUBR(NAME,name,p_send,p_struct,p_sflw) \ extern "C" void NAME p_stardent # else # define FORTRAN_SUBR(NAME,name,p_send,p_struct,p_sflw) \ void NAME p_stardent # endif # define FORTRAN_EXTERN(NAME,name,p_sun,p_stardent,p_mvs) \ extern "C" void NAME p_stardent # define FORTRAN_CALL(NAME,name,p_send,p_struct,p_sflw) \ NAME p_stardent #elif defined(CALL_LIKE_VMS) typedef dsc$descriptor_s * fpstr; # define FTN_STR(s) s->dsc$a_pointer; # define FTN_LEN(s) s->dsc$w_length; # define character(s) \ dsc$descriptor_s s; # define fill_char_struct(s,str) \ s.dsc$a_pointer = str; \ s.dsc$w_length = strlen(str); \ s.dsc$b_dtype = DSC$K_DTYPE_T; \ s.dsc$b_class = DSC$K_CLASS_S; # ifdef __cplusplus # define FORTRAN_SUBR(NAME,name,p_sun,p_stardent,p_mvs) \ extern "C" void NAME p_stardent # else # define FORTRAN_SUBR(NAME,name,p_sun,p_stardent,p_mvs) \ void NAME p_stardent # endif # define FORTRAN_EXTERN(NAME,name,p_sun,p_stardent,p_mvs) \ extern "C" void NAME p_stardent # define FORTRAN_CALL(NAME,name,p_sun,p_stardent,p_mvs) \ NAME p_stardent #elif defined(CALL_LIKE_MVS) typedef pstr fpstr; # define FTN_STR(s) s # define FTN_LEN(s) s##_len # define char_struct(s) \ pstr s; \ int s##_len; # define fill_char_struct(s,str) \ s = str; \ s##_len = strlen(str); # ifdef __cplusplus # define FORTRAN_SUBR(NAME,name,p_sun,p_stardent,p_mvs) \ extern "C" void __stdcall NAME p_mvs # else # define FORTRAN_SUBR(NAME,name,p_sun,p_stardent,p_mvs) \ void __stdcall NAME p_mvs # endif # define FORTRAN_EXTERN(NAME,name,p_sun,p_stardent,p_mvs) \ extern "C" void NAME p_mvs # define FORTRAN_CALL(NAME,name,p_sun,p_stardent,p_mvs) \ NAME p_mvs #else # error Unknown machine!!! typedef pstr fpstr; # define FTN_STR(s) s # define FTN_LEN(s) s##_len # define char_struct(s) \ pstr s; \ int s##_len; # define fill_char_struct(s,str) \ s = str; \ s##_len = strlen(str); # ifdef __cplusplus # define FORTRAN_SUBR(NAME,name,p_sun,p_stardent,p_mvs) \ extern "C" void name##_ p_sun # else # define FORTRAN_SUBR(NAME,name,p_sun,p_stardent,p_mvs) \ void name##_ p_sun # endif # define FORTRAN_EXTERN(NAME,name,p_sun,p_stardent,p_mvs) \ extern "C" void name##_ p_sun # define FORTRAN_CALL(NAME,name,p_sun,p_stardent,p_mvs) \ name##_ p_sun #endif // ============== Machine-dependent functions =============== extern int GetMachineID (); extern mmdb::cpstr GetMachineName (); extern mmdb::cpstr GetMachineName ( int MachineID ); } } #endif mmdb2-2.0.5/mmdb2/mmdb_bondmngr.cpp0000664000175000017500000000670212401105774013762 00000000000000// $Id: mmdb_bondmngr.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 15.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : mmdb_bondmngr // ~~~~~~~~~ // Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::BondManager ( MMDB bonds maker ) // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include "mmdb_bondmngr.h" #include "mmdb_math_graph.h" namespace mmdb { // ===================== BondManager ===================== BondManager::BondManager() : SelManager() { } BondManager::BondManager ( io::RPStream Object ) : SelManager(Object) { } BondManager::~BondManager() {} void BondManager::MakeBonds ( bool calc_only ) { UNUSED_ARGUMENT(calc_only); PModel mdl; PChain chain; PResidue res; math::Graph graph; math::PPVertex V; math::PPEdge E; int i, im,ic,ir, nV,nE, k1,k2; RemoveBonds(); for (im=0;imnChains;ic++) { chain = mdl->chain[ic]; if (chain) for (ir=0;irnResidues;ir++) { res = chain->residue[ir]; if (res) { graph.MakeGraph ( res,NULL ); graph.GetVertices ( V,nV ); graph.GetEdges ( E,nE ); for (i=0;iGetVertex1()-1]->GetUserID(); k2 = V[E[i]->GetVertex2()-1]->GetUserID(); res->atom[k1]->AddBond ( res->atom[k2],E[i]->GetType() ); res->atom[k2]->AddBond ( res->atom[k1],E[i]->GetType() ); } } } } } } void BondManager::RemoveBonds() { int i; for (i=0;iFreeBonds(); } // ------------------- Stream functions ---------------------- void BondManager::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); SelManager::write ( f ); } void BondManager::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); SelManager::read ( f ); } MakeStreamFunctions(BondManager) } // namespace mmdb mmdb2-2.0.5/mmdb2/mmdb_symop.cpp0000664000175000017500000006000612401105774013320 00000000000000// $Id: mmdb_symop.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_SymOp // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // // **** Classes : mmdb::SymOp ( symmetry operators ) // ~~~~~~~~~ mmdb::SymOps ( container of symmetry operators ) // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include #include #include "mmdb_symop.h" namespace mmdb { // ==================== SymOp ======================== SymOp::SymOp() : io::Stream() { InitSymOp(); } SymOp::SymOp ( io::RPStream Object ) : io::Stream(Object) { InitSymOp(); } SymOp::~SymOp() { FreeMemory(); } void SymOp::InitSymOp() { int i,j; XYZOp = NULL; for (i=0;i<4;i++) { for (j=0;j<4;j++) T[i][j] = 0.0; T[i][i] = 1.0; } } void SymOp::FreeMemory() { if (XYZOp) delete[] XYZOp; XYZOp = NULL; } int SymOp::SetSymOp ( cpstr XYZOperation ) { int i,j; CreateCopy ( XYZOp,XYZOperation ); DelSpaces ( XYZOp ); for (i=0;i<4;i++) for (j=0;j<4;j++) T[i][j] = 0.0; i = GetOperation ( 0 ); if (!i) i = GetOperation ( 1 ); if (!i) i = GetOperation ( 2 ); T[3][3] = 1.0; return i; } pstr SymOp::GetSymOp() { if (XYZOp) return XYZOp; else return pstr(""); } int SymOp::GetOperation ( int n ) { char L[100]; pstr p1,p2; int len; realtype V; p1 = XYZOp; p2 = strchr ( p1,',' ); if (!p2) return SYMOP_WrongSyntax; if (n>0) { p1 = p2+1; p2 = strchr ( p1,',' ); if (!p2) return SYMOP_WrongSyntax; } if (n>1) { p1 = p2+1; p2 = NULL; } if (p2) *p2 = char(0); strcpy ( L,p1 ); if (p2) *p2 = ','; DelSpaces ( L ); if (!L[0]) return SYMOP_WrongSyntax; UpperCase ( L ); len = strlen ( L ); T[n][0] = 0.0; if (L[0]=='X') { T[n][0] += 1.0; L[0] = ' '; } do { p1 = strstr ( L,"+X" ); if (p1) { T[n][0] += 1.0; strncpy ( p1," ",2 ); } } while (p1); do { p1 = strstr ( L,"-X" ); if (p1) { T[n][0] -= 1.0; strncpy ( p1," ",2 ); } } while (p1); T[n][1] = 0.0; if (L[0]=='Y') { T[n][1] += 1.0; L[0] = ' '; } do { p1 = strstr ( L,"+Y" ); if (p1) { T[n][1] += 1.0; strncpy ( p1," ",2 ); } } while (p1); do { p1 = strstr ( L,"-Y" ); if (p1) { T[n][1] -= 1.0; strncpy ( p1," ",2 ); } } while (p1); T[n][2] = 0.0; if (L[0]=='Z') { T[n][2] += 1.0; L[0] = ' '; } do { p1 = strstr ( L,"+Z" ); if (p1) { T[n][2] += 1.0; strncpy ( p1," ",2 ); } } while (p1); do { p1 = strstr ( L,"-Z" ); if (p1) { T[n][2] -= 1.0; strncpy ( p1," ",2 ); } } while (p1); DelSpaces ( L ); if ((int)strlen(L)>=len) return SYMOP_NotAnOperation; // translational part p1 = L; T[n][3] = strtod ( p1,&p2 ); if (*p2=='/') { p1 = p2+1; V = strtod ( p1,&p2 ); if (V==0.0) return SYMOP_ZeroDenominator; T[n][3] /= V; } return SYMOP_Ok; } void MakeSign ( pstr S, realtype V, realtype & AV ) { int l; if (V>0.0) { l = strlen ( S ); if (l>0) { if (S[l-1]!=',') { strcat ( S,"+" ); } } AV = V; } else if (V<0.0) { strcat ( S,"-" ); AV = -V; } else { AV = V; return; } } #define __eps 1.0e-5 void GenTranslation ( pstr S, realtype V ) { realtype AV,nAV; char N[50]; int n,d; if (fabs(V)<=__eps) return; MakeSign ( S,V,AV ); d = 0; n = -1; while ((d<=20) && (n<0)) { d++; nAV = AV*d; n = mround(nAV); if (fabs(nAV-n)>__eps) n = -1; } if (d<=1) sprintf ( N,"%i" ,n ); else if (n>=0) sprintf ( N,"%i/%i" ,n,d ); else sprintf ( N,"%-.10g",AV ); strcat ( S,N ); } void GenTransformation ( pstr S, realtype V, pstr Axis ) { realtype AV,nAV; char N[50]; int n,d; if (fabs(V)<=__eps) return; MakeSign ( S,V,AV ); if (fabs(AV-1.0)>__eps) { d = 0; n = -1; while ((d<=20) && (n<0)) { d++; nAV = AV*d; n = mround(nAV); if (fabs(nAV-n)>__eps) n = -1; } if (n>=0) sprintf ( N,"%i/%i*",n,d ); else sprintf ( N,"%-.10g*",AV ); strcat ( S,N ); } strcat ( S,Axis ); } /* void GenTranslation ( pstr S, realtype V ) { realtype AV,fAV; int n,d; char N[50]; if (V==0.0) return; MakeSign ( S,V,AV ); n = mround(floor(AV+0.00000001)); fAV = AV-n; if (fabs(fAV-0.5)<=__eps) { n += 1; d = 2; } else if (fabs(fAV-0.25)<=__eps) { n += 1; d = 4; } else if (fabs(fAV-0.75)<=__eps) { n += 3; d = 4; } else if (fabs(fAV-0.33333333333)<=__eps) { n += 1; d = 3; } else if (fabs(fAV-0.66666666666)<=__eps) { n += 2; d = 3; } else if (fabs(fAV-0.16666666666)<=__eps) { n += 1; d = 6; } else if (fabs(fAV-0.83333333333)<=__eps) { n += 5; d = 6; } else d = 1; N[0] = char(0); if (d>1) sprintf ( N,"%i/%i",n,d ); else if (n>0) sprintf ( N,"%i",n ); else ParamStr ( N,pstr(""),AV ); strcat ( S,N ); } void GenTransformation ( pstr S, realtype V, pstr Axis ) { realtype AV; if (V==0.0) return; MakeSign ( S,V,AV ); if (fabs(AV-0.5)<=__eps) strcat ( S,"1/2*" ); else if (fabs(AV-0.25)<=__eps) strcat ( S,"1/4*" ); else if (fabs(AV-0.75)<=__eps) strcat ( S,"3/4*" ); else if (fabs(AV-0.33333333333)<=__eps) strcat ( S,"1/3*" ); else if (fabs(AV-0.66666666666)<=__eps) strcat ( S,"2/3*" ); else if (fabs(AV-0.16666666666)<=__eps) strcat ( S,"1/6*" ); else if (fabs(AV-0.83333333333)<=__eps) strcat ( S,"5/6*" ); else if (fabs(AV-1.0)>__eps) ParamStr ( S,pstr(""),AV, 10,pstr("*") ); strcat ( S,Axis ); } */ bool SymOp::CompileOpTitle ( pstr S ) { return CompileOpTitle ( S,T,true ); } bool SymOp::CompileOpTitle ( pstr S, mat44 symMat, bool compare ) { S[0] = char(0); GenTransformation ( S,symMat[0][0],pstr("X") ); GenTransformation ( S,symMat[0][1],pstr("Y") ); GenTransformation ( S,symMat[0][2],pstr("Z") ); GenTranslation ( S,symMat[0][3] ); strcat ( S,"," ); GenTransformation ( S,symMat[1][0],pstr("X") ); GenTransformation ( S,symMat[1][1],pstr("Y") ); GenTransformation ( S,symMat[1][2],pstr("Z") ); GenTranslation ( S,symMat[1][3] ); strcat ( S,"," ); GenTransformation ( S,symMat[2][0],pstr("X") ); GenTransformation ( S,symMat[2][1],pstr("Y") ); GenTransformation ( S,symMat[2][2],pstr("Z") ); GenTranslation ( S,symMat[2][3] ); DelSpaces ( S ); if ((!compare) || (!strcmp(S,XYZOp))) return true; else { S[0] = char(0); GenTranslation ( S,symMat[0][3] ); GenTransformation ( S,symMat[0][0],pstr("X") ); GenTransformation ( S,symMat[0][1],pstr("Y") ); GenTransformation ( S,symMat[0][2],pstr("Z") ); strcat ( S,"," ); GenTranslation ( S,symMat[1][3] ); GenTransformation ( S,symMat[1][0],pstr("X") ); GenTransformation ( S,symMat[1][1],pstr("Y") ); GenTransformation ( S,symMat[1][2],pstr("Z") ); strcat ( S,"," ); GenTranslation ( S,symMat[2][3] ); GenTransformation ( S,symMat[2][0],pstr("X") ); GenTransformation ( S,symMat[2][1],pstr("Y") ); GenTransformation ( S,symMat[2][2],pstr("Z") ); DelSpaces ( S ); if (!strcmp(S,XYZOp)) return true; } return false; } void SymOp::Transform ( realtype & x, realtype & y, realtype & z ) { realtype x1,y1,z1; x1 = T[0][0]*x + T[0][1]*y + T[0][2]*z + T[0][3]; y1 = T[1][0]*x + T[1][1]*y + T[1][2]*z + T[1][3]; z1 = T[2][0]*x + T[2][1]*y + T[2][2]*z + T[2][3]; x = x1; y = y1; z = z1; } void SymOp::GetTMatrix ( mat44 & TMatrix ) { // copies T to TMatrix int i,j; for (i=0;i<4;i++) for (j=0;j<4;j++) TMatrix[i][j] = T[i][j]; } void SymOp::SetTMatrix ( mat44 & TMatrix ) { // copies TMatrix to T int i,j; for (i=0;i<4;i++) for (j=0;j<4;j++) T[i][j] = TMatrix[i][j]; } void SymOp::Print() { int i; printf ( " operation '%s'\n",XYZOp ); for (i=0;i<4;i++) printf ( " %10.3g %10.3g %10.3g %10.3g\n", T[i][0],T[i][1],T[i][2],T[i][3] ); } void SymOp::Copy ( PSymOp SymOp ) { int i,j; CreateCopy ( XYZOp,SymOp->XYZOp ); for (i=0;i<4;i++) for (j=0;j<4;j++) T[i][j] = SymOp->T[i][j]; } void SymOp::write ( io::RFile f ) { int i,j; byte Version=1; f.WriteByte ( &Version ); f.CreateWrite ( XYZOp ); for (i=0;i<4;i++) for (j=0;j<4;j++) f.WriteReal ( &(T[i][j]) ); } void SymOp::read ( io::RFile f ) { int i,j; byte Version; f.ReadByte ( &Version ); f.CreateRead ( XYZOp ); for (i=0;i<4;i++) for (j=0;j<4;j++) f.ReadReal ( &(T[i][j]) ); } MakeStreamFunctions(SymOp) // ==================== SymOps ======================== SymOps::SymOps() : io::Stream() { InitSymOps(); } SymOps::SymOps ( io::RPStream Object ) : io::Stream(Object) { InitSymOps(); } SymOps::~SymOps() { FreeMemory(); } void SymOps::InitSymOps() { SpGroup = NULL; Nops = 0; symOp = NULL; } void SymOps::FreeMemory() { int i; if (SpGroup) delete[] SpGroup; SpGroup = NULL; if (symOp) { for (i=0;iSetSymOp ( S ); } f.shut(); return RC; } #define syminfo_file cpstr("syminfo.lib") int SymOps::SetGroup ( cpstr SpaceGroup, cpstr syminfo_lib ) { io::File f; pstr p; psvector lines,lines1; char S[500]; char G[100]; char O[100]; mat44 T1,T2,T3; int i,j,k,l,m,n,RC; int nlines,npops,ncops; FreeMemory(); npops = 0; ncops = 0; CreateCopy ( SpGroup,SpaceGroup ); if (!syminfo_lib) p = pstr(syminfo_file); else if (!syminfo_lib[0]) p = pstr(syminfo_file); else p = pstr(syminfo_lib); f.assign ( p,true ); if (!f.reset(true)) { p = getenv ( "SYMINFO" ); if (p) strcpy ( S,p ); else { p = getenv ( "CLIBD" ); if (p) { strcpy ( S,p ); if (S[strlen(S)-1]!='/') strcat ( S,"/" ); strcat ( S,"syminfo.lib" ); } else strcpy ( S,"syminfo.lib" ); } f.assign ( S,true ); if (!f.reset(true)) return SYMOP_NoLibFile; } if (strncasecmp(SpGroup,"Hall:",5)) { // normal space group symbol on input strcpy ( G," '" ); strcat ( G,SpGroup ); strcat ( G,"'" ); S[0] = char(0); while (!f.FileEnd() && !(strstr(S,G) && (strstr(S,"symbol xHM") || strstr(S,"symbol old")))) f.ReadLine ( S,sizeof(S) ); } else { // hall descriptor on input strcpy ( G," ' " ); p = &(SpGroup[5]); while (*p==' ') p++; strcat ( G,p ); strcat ( G,"'" ); S[0] = char(0); while (!f.FileEnd() && !(strstr(S,G) && strstr(S,"symbol Hall"))) f.ReadLine ( S,sizeof(S) ); } if (f.FileEnd()) { f.shut(); return SYMOP_UnknownSpaceGroup; } // found spacegroup, move to symop lines while (!f.FileEnd() && (!strstr(S,"symop"))) f.ReadLine ( S,sizeof(S) ); nlines = 256; GetVectorMemory ( lines,nlines,0 ); for (i=0;i=nlines) { nlines += + 256; GetVectorMemory ( lines1,nlines,0 ); for (i=0;i=nlines) { nlines += + 256; GetVectorMemory ( lines1,nlines,0 ); for (i=0;iSetSymOp ( lines[n++]+6 ); } // loop over non-trivial centering operators, and for each loop // over primtive operators for (i=1;(iSetSymOp ( lines[n]+6 ); symOp[i*npops+j]->GetTMatrix(T1); symOp[j]->GetTMatrix(T2); for (k=0;k<4;k++) for (l=0;l<4;l++) { T3[k][l] = 0.0; for (m=0;m<4;m++) T3[k][l] += T1[k][m]*T2[m][l]; } for (k=0;k<3;k++) // kdc fix T3[k][3] -= floor ( T3[k][3] ); // kdc fix symOp[i*npops+j]->CompileOpTitle ( O,T3,false ); symOp[i*npops+j]->SetSymOp ( O ); } } f.shut(); for (i=0;iSetSymOp ( S+6 ); } // skip identity centering operator f.ReadLine ( S,sizeof(S) ); // loop over non-trivial centering operators, and for each loop // over primtive operators for (i=1;(iSetSymOp ( S+6 ); SymOp[i*npops+j]->GetTMatrix(T1); SymOp[j]->GetTMatrix(T2); for (k=0;k<4;k++) for (l=0;l<4;l++) { T3[k][l] = 0.0; for (m=0;m<4;m++) T3[k][l] += T1[k][m]*T2[m][l]; } for (k=0;k<3;k++) // kdc fix T3[k][3] -= floor ( T3[k][3] ); // kdc fix SymOp[i*npops+j]->CompileOpTitle(O,T3,false); SymOp[i*npops+j]->SetSymOp (O); } } f.shut(); return RC; } */ void SymOps::Reset() { // removes all symmetry operations FreeMemory(); } int SymOps::AddSymOp ( cpstr XYZOperation ) { // adds a symmetry operation PPSymOp symOp1; int i; symOp1 = new PSymOp[Nops+1]; for (i=0;iSetSymOp ( XYZOperation ); } void SymOps::PutGroupName ( cpstr SpGroupName ) { CreateCopy ( SpGroup,SpGroupName ); } int SymOps::GetNofSymOps() { // GetNofSymOps() returns Nops -- the number of symmetry operations return Nops; } pstr SymOps::GetSymOp ( int Nop ) { if ((0<=Nop) && (NopGetSymOp(); else return pstr(""); } int SymOps::Transform ( realtype & x, realtype & y, realtype & z, int Nop ) { // Transform(..) transforms the coordinates according to the // symmetry operation Nop. The return code is non-zero if // Nop is a wrong operation number (must range from 0 to Nops-1). if ((Nop<0) || (Nop>=Nops)) return 1; if (symOp[Nop]) { symOp[Nop]->Transform ( x,y,z ); return 0; } else return 2; } int SymOps::GetTMatrix ( mat44 & TMatrix, int Nop ) { // GetTMatrix(..) returns the coordinate transformation matrix // for the symmetry operation Nop. The return code is non-zero if // Nop is a wrong operation number (must range from 0 to Nops-1). if ((Nop<0) || (Nop>=Nops)) return 1; if (symOp[Nop]) { symOp[Nop]->GetTMatrix ( TMatrix ); return 0; } else return 2; } void SymOps::Print() { int i; char S[200]; printf ( " SPACE GROUP '%s'\n",SpGroup ); for (i=0;iPrint(); if (symOp[i]->CompileOpTitle(S)) printf ( " CHECK STATUS: Ok\n" ); else printf ( " CHECK STATUS: Generated '%s'\n",S ); } } void SymOps::Copy ( PSymOps SymOps ) { int i; FreeMemory(); CreateCopy ( SpGroup,SymOps->SpGroup ); Nops = SymOps->Nops; if (Nops>0) { symOp = new PSymOp[Nops]; for (i=0;iCopy ( SymOps->symOp[i] ); } } } void SymOps::write ( io::RFile f ) { int i; byte Version=1; f.WriteByte ( &Version ); f.CreateWrite ( SpGroup ); f.WriteInt ( &Nops ); for (i=0;i0) { symOp = new PSymOp[Nops]; for (i=0;i // ~~~~~~~~~ // **** Classes : mmdb::math::BFGSMin ( minimization driver ) // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include "mmdb_math_bfgsmin.h" namespace mmdb { namespace math { // ============================================================== BFGSMin::BFGSMin() { MFunc = NULL; MFuncData = NULL; PFunc = NULL; PFuncData = NULL; N = 0; NAlloc = 0; Hsn = NULL; TL = NULL; LL = NULL; XOpt = NULL; XPlus = NULL; Sx = NULL; SN = NULL; HDiag = NULL; GradX = NULL; GPlus = NULL; StepSize = NULL; FNeighbor = NULL; us = NULL; uy = NULL; ut = NULL; Freese = NULL; Func = 0.0; FPlus = 0.0; FOpt = 0.0; TakenLambda = 0.0; ForDiff = false; CalcHess = false; Etha = 0.0; SqrtEtha = 0.0; CubertEtha = 0.0; TpF = 1.0; GrdEps = 0.0; StpEps = 0.0; MxStep = MaxReal; CnsMax = 0; MaxItn = 100; TermCode = BFGS_NoTermination; ModF = false; } BFGSMin::~BFGSMin() { FreeMemory(); } void BFGSMin::MinFunc ( rvector X, realtype & F ) { if (MFunc) (*MFunc)(MFuncData,N,X,F); else F = 0.0; } void BFGSMin::MinFunc1 ( rvector X, realtype & F ) { int i; MinFunc ( X,F ); if (ModF && (FEtha) Etha = MachEps; } SqrtEtha = sqrt(Etha); CubertEtha = Exp ( log(Etha)/3.0 ); if (Etha>0.01) { TermCode = BFGS_TooFewDigits; return; } if (TypF<=0.0) TpF = 1.0; else TpF = TypF; S1 = Exp(log(MachEps)/3.0); if (GrdTol>0.0) GrdEps = GrdTol; else { GrdEps = sqrt(Etha); if (S1>GrdEps) GrdEps = S1; } if (StpTol>0.0) StpEps = StpTol; else StpEps = Exp ( log(MachEps)*2.0/3.0 ); if (MaxStp>0.0) MxStep = MaxStp; else { S1 = 0.0; S2 = 0.0; for (i=1;i<=N;i++) { S0 = Sx[i]; S0 *= Sx[i]; S2 += S0; S0 *= x0[i]; S1 += S0*x0[i]; } S1 = sqrt(S1); S2 = sqrt(S2); if (S2>S1) MxStep = S2; else MxStep = S1; MxStep *= 1000.0; } if (ItnLmt>0) MaxItn = ItnLmt; else MaxItn = 100; TermCode = BFGS_NoTermination; } // ------------------------------------------------------------------- void BFGSMin::UMStop0 ( rvector x0, rvector Grad ) { int i; realtype S,Fmax,St; CnsMax = 0; if (TpF>fabs(Func)) Fmax = TpF; else Fmax = fabs(Func); S = 0.0; for (i=1;i<=N;i++) { St = fabs(x0[i]); if (1.0/Sx[i]>St) St = 1.0/Sx[i]; St = fabs(Grad[i])*St/Fmax; if (St>S) S = St; } if (S>=0.001*GrdEps) TermCode = BFGS_NoTermination; else TermCode = BFGS_SmallGradient; } // ------------------------------------------------------------------- void BFGSMin::UMStop ( rvector x0, rvector Grad, int RetCode, int ItnCnt, bool MaxTkn ) { // A7.2.1 : Checking the Stop Conditions int i; realtype Max1,Max2,MaxGrad,MaxStep, BB1,BB2; TermCode = BFGS_NoTermination; if (RetCode==1) TermCode = BFGS_LineSearchComplete; else { if (fabs(FPlus)>TpF) Max2 = fabs(FPlus); else Max2 = TpF; MaxGrad = 0.0; MaxStep = 0.0; for (i=1;i<=N;i++) { BB1 = fabs(XPlus[i]); BB2 = 1.0/Sx[i]; if (BB1>BB2) Max1 = BB1; else Max1 = BB2; BB1 = fabs(Grad[i])*Max1/Max2; if (BB1>MaxGrad) MaxGrad = BB1; BB2 = fabs(XPlus[i]-x0[i])/Max1; if (BB2>MaxStep) MaxStep = BB2; } if (MaxGradMaxItn) TermCode = BFGS_IterationLimit; else if (MaxTkn) { CnsMax++; if (CnsMax==5) TermCode = BFGS_LargeSteps; } else CnsMax = 0; } } // ------------------------------------------------------------------- void BFGSMin::MdHess ( rmatrix H, rvector HDg ) { // A5.5.1 : Setting up the hessian of model int i,j; realtype MaxDiag,MaxOff, MinEv,Mue,MaxPosDiag; realtype MaxOffl,MinDiag,MaxEv,MaxAdd,Sdd,OffRow; realtype BB; // Scaling for (i=1;i<=N;i++) for (j=i;j<=N;j++) H[i][j] /= (Sx[i]*Sx[j]); MaxDiag = H[1][1]; MinDiag = H[1][1]; MaxOff = 0.0; for (i=1;i<=N;i++) { if (H[i][i]>MaxDiag) MaxDiag = H[i][i]; if (H[i][i]MaxOff) MaxOff = BB; } } MaxPosDiag = 0.0; if (MaxDiag>MaxPosDiag) MaxPosDiag = MaxDiag; // Computing the shift of the spectra (the Mue) if (MinDiag>SqrtEps*MaxPosDiag) Mue = 0.0; else { Mue = 2.0*(MaxPosDiag-MinDiag)*SqrtEps-MinDiag; MaxDiag += Mue; } BB = MaxOff*(1.0+2.0*SqrtEps); if (BB>MaxDiag) { Mue = Mue+(MaxOff-MaxDiag)+2.0*SqrtEps*MaxOff; MaxDiag = BB; } if (MaxDiag==0.0) { // H = 0 Mue = 1.0; MaxDiag = 1.0; } if (Mue>0.0) for (i=1;i<=N;i++) Hsn[i][i] += Mue; MaxOffl = MaxOff/N; if (MaxDiag>MaxOffl) MaxOffl = MaxDiag; MaxOffl = sqrt(MaxOffl); for (i=1;i<=N;i++) HDg[i] = H[i][i]; PbCholDecomp ( N,HDg,MaxOffl,MachEps,H,MaxAdd ); if (MaxAdd>0.0) { MaxEv = HDg[1]; MinEv = HDg[1]; for (i=1;i<=N;i++) { OffRow = 0.0; if (i>1) for (j=1;jMaxEv) MaxEv = BB; BB = HDg[i]-OffRow; if (BBBB2) StepSizeJ = BB1; else StepSizeJ = BB2; if (X[j]<0.0) StepSizeJ = -StepSizeJ; StepSizeJ *= SqrtEtha; TempJ = X[j]; X[j] += StepSizeJ; StepSizeJ = X[j]-TempJ; MinFunc1 ( X,Fj ); if (TermCode!=BFGS_NoTermination) return; G[j] = (Fj-Fc)/StepSizeJ; X[j] = TempJ; Freese[j] = false; if (TL) { if ((fabs(X[j]-TL[j])<=StepSizeJ) && (G[j]<0.0)) { G[j] = 0.0; Freese[j] = true; } } if (LL) { if ((fabs(X[j]-LL[j])<=StepSizeJ) && (G[j]>0.0)) { G[j] = 0.0; Freese[j] = true; } } } } // ------------------------------------------------------------------- void BFGSMin::CDGrad ( rvector X, rvector G ) { // A5.6.4 : Central Differencies Approximation of // Gradient realtype StepSizeJ,TempJ,Fp,Fm, BB1,BB2; int j; for (j=1;j<=N;j++) { BB1 = fabs(X[j]); BB2 = 1.0/Sx[j]; if (BB1>BB2) StepSizeJ = BB1; else StepSizeJ = BB2; if (X[j]<0.0) StepSizeJ = -StepSizeJ; StepSizeJ *= CubertEtha; TempJ = X[j]; X[j] += StepSizeJ; StepSizeJ = X[j]-TempJ; MinFunc1 ( X,Fp ); if (TermCode!=BFGS_NoTermination) return; X[j] = TempJ-StepSizeJ; MinFunc1 ( X,Fm ); if (TermCode!=BFGS_NoTermination) return; G[j] = (Fp-Fm)/(2.0*StepSizeJ); X[j] = TempJ; } } // ------------------------------------------------------------------- void BFGSMin::Gradient ( rvector X, rvector G, realtype Fc ) { if (ForDiff) FDGrad ( X,G,Fc ); else CDGrad ( X,G ); } // ------------------------------------------------------------------- void BFGSMin::FDHessF ( realtype Fc, rvector X ) { // A5.6.2 : Finite-Difference Approximation of // the Hessian employing only the // function's values int i,j; realtype S,TempI,Fii,TempJ,Fij, BB1,BB2; for (i=1;i<=N;i++) if (!Freese[i]) { BB1 = fabs(X[i]); BB2 = 1.0/Sx[i]; if (BB1>BB2) S = BB1; else S = BB2; if (X[i]<0.0) S = -S; StepSize[i] = S*CubertEtha; TempI = X[i]; X[i] += StepSize[i]; StepSize[i] = X[i]-TempI; MinFunc1 ( X,FNeighbor[i] ); X[i] = TempI; if (TermCode!=BFGS_NoTermination) return; } for (i=1;i<=N;i++) if (!Freese[i]) { TempI = X[i]; X[i] += 2.0*StepSize[i]; MinFunc1 ( X,Fii ); if (TermCode!=BFGS_NoTermination) return; Hsn[i][i] = (( Fc -FNeighbor[i] ) + ( Fii-FNeighbor[i] )) / (StepSize[i]*StepSize[i]); X[i] = TempI+StepSize[i]; if (iTemp) Temp = TpF; for (i=1;i<=N;i++) { H[i][i] = Temp*Sx[i]*Sx[i]; if (isqrt(MachEps*NormS*NormY)) { if (AnalGrad) Tol = Etha; else Tol = sqrt(Etha); SkipUpdate = true; for (i=1;i<=N;i++) { tt = 0.0; for (j=1;j<=i;j++) tt += H[j][i]*us[j]; if (itt) tt = BB; if (fabs(uy[i]-ut[i])>=Tol*tt) SkipUpdate = false; } if (!SkipUpdate) { Temp2 = 0.0; for (i=1;i<=N;i++) Temp2 += us[i]*ut[i]; for (i=1;i<=N;i++) for (j=i;j<=N;j++) H[i][j] += uy[i]*uy[j]/Temp1 - ut[i]*ut[j]/Temp2; } } } // ------------------------------------------------------------------- void BFGSMin::Choose_Lambda ( rvector X, rvector S, realtype & Lambda0 ) { int i; realtype SS; for (i=1;i<=N;i++) if ((S[i]!=0.0) && (!Freese[i])) { SS = X[i] + Lambda0*S[i]; if (TL) { if (SS>TL[i]) Lambda0 = (TL[i]-X[i])/S[i]/(1.0+MachEps); } if (LL) { if (SSMxStep) { // restrict Newtonian step to MxStep S = MxStep/NewtLn; for (i=1;i<=N;i++) P[i] *= S; NewtLn = MxStep; } InitSp = 0.0; RelLng = 0.0; Lambda0 = 1.0; Choose_Lambda ( px0,P,Lambda0 ); for (i=1;i<=N;i++) { InitSp += G[i]*P[i]; B1 = fabs(px0[i]); B2 = 1.0/Sx[i]; if (B1>B2) S = B1; else S = B2; S = fabs(P[i])/S; if (S>RelLng) RelLng = S; } InitSp *= Lambda0; MinLam = StpEps/RelLng; Lambda = Lambda0; do { for (i=1;i<=N;i++) XPlus[i] = px0[i] + Lambda*P[i]; MinFunc1 ( XPlus,FPlus ); if (TermCode!=BFGS_NoTermination) return; if (FPlus<=pFunc+Alpha*Lambda*InitSp) { RetCode = 0; MaxTkn = (Lambda==Lambda0) && (NewtLn>0.99*MxStep); } else if (Lambda0.1*Lambda) Lambda = LamTem; else { Lambda *= 0.1; Lambda0 = Lambda; } if (Lambda>Lambda0) { Lambda = Lambda0; RetCode = 0; for (i=1;i<=N;i++) XPlus[i] = px0[i] + Lambda*P[i]; } } else { B1 = FPlus - pFunc - Lambda*InitSp; B2 = FplPre - pFunc - LamPre*InitSp; A = ( B1/(Lambda*Lambda) - B2/(LamPre*LamPre) ) / ( Lambda - LamPre ); B = ( -LamPre*B1/(Lambda*Lambda) + Lambda*B2/(LamPre*LamPre) ) / ( Lambda - LamPre ); Disc = B*B - 3.0*A*InitSp; if (A==0.0) LamTem = -InitSp/(2.0*B); else LamTem = (-B+sqrt(RMax(Disc,0.0)))/(3.0*A); B1 = 0.5*Lambda; if (B10.1*Lambda) Lambda = LamTem; else { Lambda *= 0.1; Lambda0 = Lambda; } if (Lambda>Lambda0) { Lambda = Lambda0; RetCode = 0; for (i=1;i<=N;i++) XPlus[i] = px0[i] + Lambda*P[i]; } } } while (RetCode>=2); TakenLambda = Lambda; } // ------------------------------------------------------------------- void BFGSMin::GetMemory() { if (N!=NAlloc) { FreeMemory(); GetMatrixMemory ( Hsn , N,N, 1,1 ); GetVectorMemory ( GPlus , N, 1 ); GetVectorMemory ( GradX , N, 1 ); GetVectorMemory ( HDiag , N, 1 ); GetVectorMemory ( SN , N, 1 ); GetVectorMemory ( Sx , N, 1 ); GetVectorMemory ( XPlus , N, 1 ); GetVectorMemory ( XOpt , N, 1 ); GetVectorMemory ( Freese, N, 1 ); if (CalcHess) { GetVectorMemory ( StepSize , N, 1 ); GetVectorMemory ( FNeighbor, N, 1 ); } else { GetVectorMemory ( us , N, 1 ); GetVectorMemory ( uy , N, 1 ); GetVectorMemory ( ut , N, 1 ); } NAlloc = N; } } void BFGSMin::FreeMemory() { if (NAlloc>0) { FreeVectorMemory ( us , 1 ); FreeVectorMemory ( uy , 1 ); FreeVectorMemory ( ut , 1 ); FreeVectorMemory ( Freese , 1 ); FreeVectorMemory ( StepSize , 1 ); FreeVectorMemory ( FNeighbor, 1 ); FreeVectorMemory ( XOpt , 1 ); FreeVectorMemory ( XPlus , 1 ); FreeVectorMemory ( Sx , 1 ); FreeVectorMemory ( SN , 1 ); FreeVectorMemory ( HDiag , 1 ); FreeVectorMemory ( GradX , 1 ); FreeVectorMemory ( GPlus , 1 ); FreeMatrixMemory ( Hsn , NAlloc, 1,1 ); } NAlloc = 0; } // ------------------------------------------------------------------- void BFGSMin::Relax() { int i; if (FPlus>FOpt) { for (i=1;i<=N;i++) XPlus[i] = XOpt[i]; FPlus = FOpt; } else { for (i=1;i<=N;i++) XOpt[i] = XPlus[i]; FOpt = FPlus; } } void BFGSMin::CopyPlus ( rvector x0 ) { int i; for (i=1;i<=N;i++) { x0 [i] = XPlus[i]; GradX[i] = GPlus[i]; } Func = FPlus; } // ------------------------------------------------------------------- void BFGSMin::BFGS_Driver ( int MinN, rvector x0, rvector TypX, realtype & FuncValue, int & TerminationCode, int Digits, int ItnLmt, realtype TypF, realtype GrdTol, realtype StpTol, realtype MaxStp, bool Hess, rvector LowLimit, rvector TopLimit ) { // D6.1.1 : Unconstrained Minimization Driver int i,RetCode; int ItnCnt; bool MaxTkn; TL = TopLimit; LL = LowLimit; ForDiff = true; N = MinN; CalcHess = Hess; ModF = false; GetMemory(); UMInCk ( x0,TypX,Digits,TypF, GrdTol,StpTol,MaxStp, ItnLmt ); if (TermCode!=BFGS_NoTermination) { FreeMemory(); FuncValue = Func; TerminationCode = TermCode; return; } ItnCnt = 0; MinFunc1 ( x0,Func ); if (TermCode!=BFGS_NoTermination) { FreeMemory(); FuncValue = Func; TerminationCode = TermCode; return; } FOpt = Func; FPlus = Func; for (i=1;i<=N;i++) { XOpt [i] = x0[i]; XPlus[i] = x0[i]; } ModF = true; Gradient ( x0,GradX,Func ); Print ( ItnCnt,x0,GradX,Func ); for (i=1;i<=N;i++) GPlus[i] = GradX[i]; if (TermCode!=BFGS_NoTermination) { Relax (); CopyPlus ( x0 ); FreeMemory(); FuncValue = Func; TerminationCode = TermCode; return; } UMStop0 ( x0,GradX ); if (TermCode!=BFGS_NoTermination) { FreeMemory(); FuncValue = Func; TerminationCode = TermCode; return; } if (!CalcHess) InitHessUnFac ( Func,Hsn ); RetCode = 0; while (TermCode==BFGS_NoTermination) { ItnCnt++; if (RetCode>=0) { if (CalcHess) { FDHessF ( Func,x0 ); if (TermCode!=BFGS_NoTermination) { Relax (); CopyPlus ( x0 ); FreeMemory(); FuncValue = Func; TerminationCode = TermCode; return; } } MdHess ( Hsn,HDiag ); } ChSolve ( N,Hsn,GradX,SN ); LineSearch ( x0,GradX,SN,Func,RetCode,MaxTkn ); if ((RetCode==1) && ForDiff) { RetCode = -1; ForDiff = false; } else Relax(); if (TermCode!=BFGS_NoTermination) { Relax (); CopyPlus ( x0 ); FreeMemory(); FuncValue = Func; TerminationCode = TermCode; return; } else Gradient ( XPlus,GPlus,FPlus ); if (TermCode!=BFGS_NoTermination) { Relax (); CopyPlus ( x0 ); FreeMemory(); FuncValue = Func; TerminationCode = TermCode; return; } if (RetCode>=0) { UMStop ( x0,GPlus,RetCode,ItnCnt,MaxTkn ); if ((!CalcHess) && (TermCode==BFGS_NoTermination)) BFGSUnFac ( x0,XPlus,GradX,GPlus,false,HDiag,Hsn ); } CopyPlus ( x0 ); Print ( ItnCnt, x0,GradX,Func ); } Relax (); FreeMemory(); FuncValue = Func; TerminationCode = TermCode; } } // namespace math } // namespace mmdb mmdb2-2.0.5/mmdb2/mmdb_mmcif_.cpp0000664000175000017500000031450712526416017013416 00000000000000// $Id: mmdb_mmcif_.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 10.05.15 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_MMCIF // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::mmcif::Category ( mmCIF category ) // ~~~~~~~~~ mmdb::mmcif::Struct ( mmCIF structure ) // mmdb::mmcif::Loop ( mmCIF loop ) // mmdb::mmcif::Data ( mmCIF data block ) // mmdb::mmcif::File ( mmCIF file ) // // (C) E. Krissinel 2000-2015 // // ================================================================= // #include #include #include #include "mmdb_mmcif_.h" namespace mmdb { namespace mmcif { // ====================== SortTags =============================== void SortTags ( psvector tag, int len, ivector index ) { int i,k,l,l1,l2; if (len==1) { index[0] = 0; return; } if (strcasecmp(tag[0],tag[1])<0) { index[0] = 0; index[1] = 1; } else { index[0] = 1; index[1] = 0; } for (k=2;k0) l2 = k; else { l1 = 0; while (l1l2;i--) index[i] = index[i-1]; index[l2] = k; } } // ====================== Category ========================== const int CIF_NODATA_DOT = 0; const int CIF_NODATA_QUESTION = 1; cpstr CIF_NODATA_DOT_FIELD = pstr("\x02" "."); cpstr CIF_NODATA_QUESTION_FIELD = pstr("\x02" "?"); Category::Category() : io::Stream() { InitCategory(); } Category::Category ( cpstr N ) : io::Stream() { InitCategory(); SetCategoryName ( N ); } Category::Category ( io::RPStream Object ) : io::Stream(Object) { InitCategory(); } Category::~Category() { FreeMemory(); } void Category::InitCategory() { name = NULL; nTags = 0; tag = NULL; index = NULL; nAllocTags = 0; } void Category::FreeMemory() { int i; if (name) delete[] name; name = NULL; for (i=0;inAllocTags) { nAT = nTagsNew + IMin(nAllocTags/2+1,20); GetVectorMemory ( tag1 ,nAT,0 ); GetVectorMemory ( index1,nAT,0 ); for (i=0;i=0) && (tagNo0) { k = 0; if (!index) GetVectorMemory ( index,nAllocTags,0 ); for (i=0;i=0 : position of the tag found // <0 : the tag was not found, it could be inserted before // (-RC-1)th element, where RC is the return value int l1,l2,l,k; if (!tag) return -1; if (!index) Sort(); l = 0; l1 = 0; l2 = nTags-1; k = 1; while (l10) l1 = l; else { l1 = l; break; } } if (k==0) return index[l]; // is at RCth position k = strcasecmp ( ttag,tag[index[l1]] ); if (k==0) return index[l1]; // is at RCth position if (k<0) return -1; // would be at (-RC-1)th position if (l2!=l1) { k = strcasecmp ( ttag,tag[index[l2]] ); if (k==0) return index[l2]; // is at RCth position if (k>0) return -2-l2; // would be at l2+1=(-RC-1)th position } return -2-l1; // would be at l1+1=(-RC-1)th position } int Category::AddTag ( cpstr ttag ) { // return -1: the tag has been added on the top of array; // index is added and sorted automatically // >=0: the tag is already in the array -- its position // is returned int i1,i; if (!tag) { ExpandTags ( 3 ); // get space for first 3 tags CreateCopy ( tag[0],ttag ); nTags = 1; return -nTags; // the tag has been added on the top of array } i1 = GetTagNo ( ttag ); if (i1>=0) return i1; // non-negative returns mean that // the tag is already in the array i1 = -i1-1; // otherwise the tag has to be added and indexed at here // put new tag on the top of array and update index ExpandTags ( nTags+1 ); CreateCopy ( tag[nTags],ttag ); for (i=nTags;i>i1;i--) index[i] = index[i-1]; index[i1] = nTags; nTags++; return -nTags; // the tag has been added on the top of array } void Category::PrintTags() { int i; Sort(); printf ( " Unsorted tags:\n" ); for (i=0;iname ); nTags = Category->nTags; nAllocTags = nTags; if (nTags>0) { GetVectorMemory ( tag ,nAllocTags,0 ); GetVectorMemory ( index,nAllocTags,0 ); for (i=0;itag[i] ); index[i] = Category->index[i]; } } } } void Category::write ( io::RFile f ) { int i; if (!index) Sort(); f.CreateWrite ( name ); f.WriteInt ( &nTags ); for (i=0;i0) { GetVectorMemory ( tag,nTags,0 ); for (i=0;inAT) { GetVectorMemory ( field1,nAllocTags,0 ); for (i=0;i=0) && (tagNo=0) && (field)) { if (field[k]) delete[] field[k]; field[k] = NULL; } return k; } int Struct::GetReal ( realtype & R, cpstr TName, bool Remove ) { pstr endptr; int RC; int k = GetTagNo ( TName ); R = 0.0; if (!field) return CIFRC_NoField; if (k<0) return CIFRC_NoTag; if (!field[k]) return CIFRC_NoField; if (field[k][0]==char(2)) return CIFRC_NoData; R = strtod ( field[k],&endptr ); if (endptr==field[k]) RC = CIFRC_WrongFormat; else { RC = 0; if (Remove) { delete[] field[k]; field[k] = NULL; } } return RC; } int Struct::GetInteger ( int & I, cpstr TName, bool Remove ) { pstr endptr; int RC; int k = GetTagNo ( TName ); I = 0; if (!field) return CIFRC_NoField; if (k<0) return CIFRC_NoTag; if (!field[k]) return CIFRC_NoField; if (field[k][0]==char(2)) { if (field[k][1]=='.') I = MinInt4; return CIFRC_NoData; } I = mround ( strtod(field[k],&endptr) ); if (endptr==field[k]) RC = CIFRC_WrongFormat; else { RC = 0; if (Remove) { delete[] field[k]; field[k] = NULL; } } return RC; } void Struct::PutString ( cpstr S, cpstr T, bool NonBlankOnly ) { pstr p; if (!S) PutNoData ( CIF_NODATA_QUESTION,T ); else { p = pstr(S); if (NonBlankOnly) while (*p==' ') p++; if (!(*p)) PutNoData ( CIF_NODATA_DOT,T ); else AddField ( S,T,false ); } } void Struct::PutDate ( cpstr T ) { time_t t; tm * tstruct; char S[100]; t = time ( NULL ); tstruct = localtime(&t); if (tstruct) sprintf ( S,"%4i-%02i-%02i", tstruct->tm_year+1900,tstruct->tm_mon+1,tstruct->tm_mday ); else strcpy ( S,"YYYY-MM-DD" ); AddField ( S,T,false ); } void Struct::PutNoData ( int NoDataType, cpstr T ) { char S[10]; S[0] = char(2); if (NoDataType==CIF_NODATA_DOT) S[1] = '.'; else S[1] = '?'; S[2] = char(0); AddField ( S,T,false ); } void Struct::PutReal ( realtype R, cpstr T, int prec ) { char rS[100]; sprintf ( rS,"%.*g",prec,R ); AddField ( rS,T,false ); } void Struct::PutReal ( realtype R, cpstr T, cpstr format ) { char rS[100]; sprintf ( rS,format,R ); AddField ( DelSpaces(rS,' '),T,false ); } void Struct::PutInteger ( int I, cpstr T ) { char iS[100]; if (I>MinInt4) { sprintf ( iS,"%i",I ); AddField ( iS,T,false ); } else PutNoData ( CIF_NODATA_DOT,T ); } #define NODATA_Q pstr("?") #define NODATA_P pstr(".") bool Struct::WriteMMCIFStruct ( cpstr FName, io::GZ_MODE gzipMode ) { io::File f; f.assign ( FName,true,false,gzipMode ); if (f.rewrite()) { WriteMMCIF ( f ); f.shut(); return true; } else return false; } #define _max_output_line_width 256 void Struct::WriteMMCIF ( io::RFile f ) { int i,j,k,l,m,n; pstr F; // calculate maximal length of tags l = 0; for (i=0;im) // wrap around if field is too long f.Write ( pstr("\n ") ); else { k = l-strlen(tag[i]); for (j=0;j0) { GetVectorMemory ( field,nTags,0 ); for (i=0;ifield[i] ); } } } void Struct::write ( io::RFile f ) { int i; Category::write ( f ); for (i=0;i0) { GetVectorMemory ( field,nTags,0 ); for (i=0;i=nTags) { delete[] field[j]; // delete empty row field[j] = NULL; } else nR++; // count non-empty row } if ((nT<=0) || (nR<=0)) FreeMemory(); // the loop is completely empty else if ((nT!=nTags) || (nR!=nAllocRows)) { f1 = new psvector[nR]; m = 0; for (j=0;jnAllocRows) { nAR = nRowsNew + IMin(nAllocRows/2+10,2000); field1 = new psvector[nAR]; for (i=0;i=nTags) iColumn = 0; } } } void Loop::AddNoData ( int NoDataType ) { char S[10]; S[0] = char(2); if (NoDataType==CIF_NODATA_DOT) S[1] = '.'; else S[1] = '?'; S[2] = char(0); AddString ( S ); } void Loop::AddReal ( realtype R, int prec ) { char rS[100]; sprintf ( rS,"%.*g",prec,R ); AddString ( rS ); } void Loop::AddReal ( realtype R, cpstr format ) { char rS[100]; sprintf ( rS,format,R ); AddString ( DelSpaces(rS,' ') ); } void Loop::AddInteger ( int I ) { char iS[100]; if (I>MinInt4) { sprintf ( iS,"%i",I ); AddString ( iS ); } else AddNoData ( CIF_NODATA_DOT ); } pstr Loop::GetField ( int rowNo, int tagNo ) { if ((tagNo>=0) && (tagNo=0) && (rowNo=nRows)) return CIFRC_WrongIndex; if (!field[nrow]) return CIFRC_NoField; if (!field[nrow][k]) return CIFRC_NoField; if (field[nrow][k][0]==char(2)) { if (Remove) { delete[] field[nrow][k]; field[nrow][k] = NULL; } } else if (Remove) { S = field[nrow][k]; field[nrow][k] = NULL; } else CreateCopy ( S,field[nrow][k] ); return 0; } pstr Loop::GetString ( cpstr TName, int nrow, int & RC ) { int k = GetTagNo ( TName ); if (k<0) { RC = CIFRC_NoTag; return NULL; } if ((nrow<0) || (nrow>=nRows)) { RC = CIFRC_WrongIndex; return NULL; } if (!field[nrow]) { RC = CIFRC_NoField; return NULL; } if (!field[nrow][k]) { RC = CIFRC_NoField; return NULL; } RC = 0; // char(2) means the field was either '.' or '?' if (field[nrow][k][0]==char(2)) return NULL; return field[nrow][k]; } // CopyString() does nothing if RC is not 0 void Loop::CopyString ( pstr buf, int maxlength, cpstr TName, int nrow, int & RC ) { pstr p; int k; if (RC) return; k = GetTagNo ( TName ); if (k<0) { RC = CIFRC_NoTag; buf[0] = char(0); return; } if ((nrow<0) || (nrow>=nRows)) { RC = CIFRC_WrongIndex; buf[0] = char(0); return; } if (!field[nrow]) { RC = CIFRC_NoField; buf[0] = char(0); return; } p = field[nrow][k]; if (!p) { RC = CIFRC_NoField; buf[0] = char(0); return; } // char(2) means the field was either '.' or '?' if (p[0]==char(2)) { buf[0] = p[0]; buf[1] = char(0); } else strncpy ( buf,p,IMin(maxlength,strlen(p)+1) ); } int Loop::DeleteField ( cpstr TName, int nrow ) { int k = GetTagNo ( TName ); if (k<0) return CIFRC_NoTag; if ((nrow<0) || (nrow>=nRows)) return CIFRC_WrongIndex; if (field[nrow]) { if (field[nrow][k]) delete[] field[nrow][k]; field[nrow][k] = NULL; } return k; } int Loop::DeleteRow ( int nrow ) { int i; if ((nrow<0) || (nrow>=nRows)) return CIFRC_WrongIndex; if (field[nrow]) { for (i=0;i=nRows)) return CIFRC_WrongIndex; R = 0.0; if (!field[nrow]) return CIFRC_NoField; if (!field[nrow][k]) return CIFRC_NoField; if (field[nrow][k][0]==char(2)) return CIFRC_NoField; R = strtod ( field[nrow][k],&endptr ); if (endptr==field[nrow][k]) return CIFRC_WrongFormat; if (Remove) { delete[] field[nrow][k]; field[nrow][k] = NULL; } return 0; } void Loop::CopyReal ( realtype & R, cpstr TName, int nrow, int & RC ) { pstr endptr; int k; if (RC) return; // R = 0.0; k = GetTagNo ( TName ); if (k<0) RC = CIFRC_NoTag; else if ((nrow<0) || (nrow>=nRows)) RC = CIFRC_WrongIndex; else if (!field[nrow]) RC = CIFRC_NoField; else if (!field[nrow][k]) RC = CIFRC_NoField; else if (field[nrow][k][0]==char(2)) RC = CIFRC_NoField; else { R = strtod ( field[nrow][k],&endptr ); if (endptr==field[nrow][k]) RC = CIFRC_WrongFormat; } } void Loop::CopyInteger ( int & I, cpstr TName, int nrow, int & RC ) { pstr endptr; int k; if (RC) return; I = 0; k = GetTagNo ( TName ); if (k<0) RC = CIFRC_NoTag; else if ((nrow<0) || (nrow>=nRows)) RC = CIFRC_WrongIndex; else if (!field[nrow]) RC = CIFRC_NoField; else if (!field[nrow][k]) RC = CIFRC_NoField; else if (field[nrow][k][0]==char(2)) RC = CIFRC_NoField; else { I = mround ( strtod ( field[nrow][k],&endptr ) ); if (endptr==field[nrow][k]) RC = CIFRC_WrongFormat; } } int Loop::GetInteger ( int & I, cpstr TName, int nrow, bool Remove ) { pstr endptr; int k = GetTagNo ( TName ); if (k<0) return CIFRC_NoTag; if ((nrow<0) || (nrow>=nRows)) return CIFRC_WrongIndex; I = 0; if (!field[nrow]) return CIFRC_NoField; if (!field[nrow][k]) return CIFRC_NoField; if (field[nrow][k][0]==char(2)) { if (field[nrow][k][1]=='.') I = MinInt4; return CIFRC_NoField; } I = mround ( strtod(field[nrow][k],&endptr) ); if (endptr==field[nrow][k]) return CIFRC_WrongFormat; if (Remove) { delete[] field[nrow][k]; field[nrow][k] = NULL; } return 0; } int Loop::GetSVector ( psvector & S, cpstr TName, int i1, int i2, bool Remove ) { int j,k,r1,r2; r1 = IMin(i1,i2); r2 = IMin(IMax(i1,i2),nRows-1); if ((r1<0) || (r1>=nRows) || (r2<0)) return CIFRC_WrongIndex; k = GetTagNo ( TName ); if (k<0) return CIFRC_NoTag; if (!S) GetVectorMemory ( S,r2-r1+1,r1 ); if (Remove) { for (j=r1;j<=r2;j++) if (field[j]) { S[j] = field[j][k]; field[j][k] = NULL; if (S[j]) { if (S[j][0]==char(2)) { delete[] S[j]; S[j] = NULL; } } } else S[j] = NULL; } else { for (j=r1;j<=r2;j++) { S[j] = NULL; if (field[j]) { if (field[j][k]) { if (field[j][k][0]!=char(2)) CreateCopy ( S[j],field[j][k] ); } } } } return 0; } int Loop::GetRVector ( rvector & R, cpstr TName, int i1, int i2, bool Remove ) { int j,k,r1,r2,RC; pstr endptr; r1 = IMin(i1,i2); r2 = IMin(IMax(i1,i2),nRows-1); if ((r1<0) || (r1>=nRows) || (r2<0)) return CIFRC_WrongIndex; k = GetTagNo ( TName ); if (k<0) return CIFRC_NoTag; if (!R) GetVectorMemory ( R,r2-r1+1,r1 ); RC = 0; for (j=r1;j<=r2;j++) { R[j] = 0.0; if (field[j]) { if (field[j][k]) { R[j] = strtod ( field[j][k],&endptr ); if (endptr==field[j][k]) RC = CIFRC_WrongFormat; if (Remove) { delete[] field[j][k]; field[j][k] = NULL; } } } } return RC; } int Loop::GetIVector ( ivector & I, cpstr TName, int i1, int i2, bool Remove ) { int j,k,r1,r2,RC; pstr endptr; r1 = IMin(i1,i2); r2 = IMin(IMax(i1,i2),nRows-1); if ((r1<0) || (r1>=nRows) || (r2<0)) return CIFRC_WrongIndex; k = GetTagNo ( TName ); if (k<0) return CIFRC_NoTag; if (!I) GetVectorMemory ( I,r2-r1+1,r1 ); RC = 0; for (j=r1;j<=r2;j++) { I[j] = 0; if (field[j]) { if (field[j][k]) { I[j] = mround ( strtod(field[j][k],&endptr) ); if (endptr==field[j][k]) RC = CIFRC_WrongFormat; if (Remove) { delete[] field[j][k]; field[j][k] = NULL; } } } } return RC; } void Loop::PutString ( cpstr S, cpstr T, int nrow ) { psmatrix field1; int nT,nR,iT,i,j; nT = nTags; nR = nRows; iT = AddTag ( T ); if (iT<0) iT = nTags-1; if (nTags>nT) { // a new tag has been added; all field must be reallocated. nRows = IMax(nR,nrow+1); // nrow is indexed like 0,1,... nAllocRows = IMax(nR,nrow+IMin(nR/2+1,2000)); field1 = new psvector[nAllocRows]; for (i=0;i=nR) { // only new rows are to be added ExpandRows ( nrow+1 ); nRows++; } if (!field[nrow]) { field[nrow] = new pstr[nTags]; for (j=0;j=nTags) iColumn = 0; } void Loop::PutNoData ( int NoDataType, cpstr T, int nrow ) { char S[10]; S[0] = char(2); if (NoDataType==CIF_NODATA_DOT) S[1] = '.'; else S[1] = '?'; S[2] = char(0); PutString ( S,T,nrow ); } void Loop::PutReal ( realtype R, cpstr T, int nrow, int prec ) { char rS[100]; sprintf ( rS,"%.*g",prec,R ); PutString ( rS,T,nrow ); } void Loop::PutReal ( realtype R, cpstr T, int nrow, cpstr format ) { char rS[100]; sprintf ( rS,format,R ); PutString ( DelSpaces(rS,' '),T,nrow ); } void Loop::PutInteger ( int I, cpstr T, int nrow ) { char iS[100]; if (I>MinInt4) { sprintf ( iS,"%i",I ); PutString ( iS,T,nrow ); } else PutNoData ( CIF_NODATA_DOT,T,nrow ); } void Loop::PutSVector ( psvector S, cpstr T, int i1, int i2 ) { int i,j,k; PutString ( S[i2],T,i2 ); if (iColumn==0) k = nTags-1; else k = iColumn-1; for (i=i2-1;i>=i1;i--) { if (!field[i]) { field[i] = new pstr[nTags]; for (j=0;j=i1;i--) { if (!field[i]) { field[i] = new pstr[nTags]; for (j=0;j=i1;l--) { if (!field[l]) { field[l] = new pstr[nTags]; for (j=0;j_max_output_line_width) { l[i] = -l[i]; k = 0; } } for (i=0;i_max_output_line_width) { f.LF(); m = k+1; } else while (n>0) { f.Write ( pstr(" ") ); n--; } if (field[i]) { if (field[i][j]) { F = field[i][j]; if (k>10000) { if (F[0]==char(2)) { f.Write ( pstr(" ") ); f.WriteLine ( &(F[1]) ); } else if (!F[0]) { f.Write ( pstr(" ") ); f.WriteLine ( NODATA_P ); } else { f.Write ( pstr(";") ); f.WriteLine ( F ); f.WriteLine ( pstr(";") ); } m = 0; k = 0; } else if ((((F[0]=='.') || (F[0]=='?')) && (!F[1])) || strchr(F,' ')) { f.Write ( pstr(" \"") ); f.Write ( F ); f.Write ( pstr("\"") ); k -= strlen(F)+2; } else if (F[0]==char(2)) { f.Write ( pstr(" ") ); f.Write ( &(F[1]) ); k--; } else if (!F[0]) { f.Write ( pstr(" ") ); f.Write ( NODATA_P ); k--; } else { f.Write ( pstr(" ") ); f.Write ( F ); k -= strlen(F); } } else { f.Write ( pstr(" ") ); f.Write ( NODATA_Q ); k--; } } else { f.Write ( pstr(" ") ); f.Write ( NODATA_Q ); k--; } } if (m) f.LF(); } } void Loop::Copy ( PCategory Loop ) { int i,j; Category::Copy ( Loop ); nRows = PLoop(Loop)->nRows; nAllocRows = nRows; if ((nTags>0) && (nRows>0)) { field = new psvector[nRows]; for (i=0;ifield[i]) { field[i] = new pstr[nTags]; for (j=0;jfield[i][j] ); } } else field[i] = NULL; } } iColumn = PLoop(Loop)->iColumn; } void Loop::write ( io::RFile f ) { int i,j; Category::write ( f ); f.WriteInt ( &nRows ); if ((nTags>0) && (nRows>0)) { for (i=0;i0) && (nRows>0)) { field = new psvector[nRows]; for (i=0;i0) { WrongCat = new pstr[nWrongFields]; WrongTag = new pstr[nWrongFields]; for (i=0;i>\n",lcount ); return CIFRC_NoDataLine; } llen = _max_buf_len; L = new char[llen]; i = 0; p += 5; while ((*p) && (*p!=' ') && (*p!=char(9))) { L[i++] = *p; p++; } L[i] = char(0); CreateCopy ( name,L ); // 2. Loop over tags until next 'data_' or end of file while (p) { // skip spaces while ((*p==' ') || (*p==char(9))) p++; if ((*p) && (*p!='#')) { // this is not a comment, continue if (*p=='_') GetDataItem ( f,S,L,p,lcount,llen ); else if (!strncmp(p,"loop_",5)) GetLoop ( f,S,L,p,lcount,llen ); else if (!strncmp(p,"data_",5)) { p = NULL; break; } else { // if got to here, the file is corrupted strcpy ( _err_string,S ); _err_line = lcount; Warning |= CIFW_UnrecognizedItems; if (flags & CIFFL_PrintWarnings) printf ( "\n **** mmCIF READ WARNING " "<>\n%s\n", lcount,S ); while ((*p) && (*p!=' ') && (*p!=char(9))) if (*p=='#') *p = char(0); else p++; } } else *p = char(0); if (Warning && (flags & CIFFL_StopOnWarnings)) { if (L) delete[] L; return Warning; } if (!(*p)) { if (!f.FileEnd()) { f.ReadLine ( S,_max_buf_len ); lcount++; p = &(S[0]); } else p = NULL; } } if (L) delete[] L; Optimize(); // get rid of over-allocated fields. return Warning; } void Data::GetDataItem ( io::RFile f, pstr S, pstr & L, pstr & p, int & lcount, int & llen ) { PStruct cifStruct; char T[100]; int RC,i; i = 0; while ((*p) && (*p!=' ') && (*p!=char(9)) && (*p!='.')) { if (i<(int)sizeof(T)-1) T[i++] = *p; p++; } T[i] = char(0); if (*p!='.') { // category name missing strcpy ( L,T ); // item name T[0] = char(1); // special T[1] = char(0); // category name } // look for category i = AddCategory ( T ); if (i<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated cifStruct = new Struct ( T ); Category[nCategories-1] = cifStruct; } else { cifStruct = PStruct(Category[i]); if (cifStruct->GetCategoryID()!=MMCIF_Struct) { strcpy ( _err_string,S ); _err_line = lcount; Warning |= CIFW_NotAStructure; if (flags & CIFFL_PrintWarnings) printf ( "\n **** mmCIF READ WARNING " "<>\n%s\n", lcount,T,S ); delete Category[i]; cifStruct = new Struct ( T ); Category[i] = cifStruct; } } if (*p=='.') { // get item name i = 0; p++; // skip period while ((*p) && (*p!=' ') && (*p!=char(9))) { T[i++] = *p; p++; } T[i] = char(0); } else strcpy ( T,L ); if (nWrongFields>0) { if (CheckWrongField(cifStruct->name,T)) { GetField ( f,S,L,p,lcount,llen ); cifStruct->DeleteField ( T ); return; } } RC = GetField ( f,S,L,p,lcount,llen ); if (RC) { strcpy ( _err_string,S ); _err_line = lcount; Warning |= CIFW_MissingField; if (flags & CIFFL_PrintWarnings) printf ( "\n **** mmCIF READ WARNING " "<>\n%s\n", lcount,S ); } while ((*p==' ') || (*p==char(9))) p++; if (*p=='#') *p = char(0); i = cifStruct->GetTagNo ( T ); if (i>=0) { if (flags & CIFFL_SuggestTags) { tagNo++; ParamStr ( T,pstr("\1"),tagNo ); } else { strcpy ( _err_string,S ); _err_line = lcount; Warning |= CIFW_DuplicateTag; if (flags & CIFFL_PrintWarnings) printf ( "\n **** mmCIF READ WARNING " "<>\n%s\n",lcount,S ); } } cifStruct->AddField ( L,T ); } void Data::GetLoop ( io::RFile f, pstr S, pstr & L, pstr & p, int & lcount, int & llen ) { PLoop cifLoop; pstr p1; char T[100]; bool Repeat,WrongField; int RC,i,nC; RC = 0; p += 5; // skip 'loop_' tag loopNo++; cifLoop = NULL; nC = -1; // undefined category number do { while ((*p==' ') || (*p==char(9))) p++; p1 = p; if (*p=='_') { // get category name i = 0; while ((*p) && (*p!=' ') && (*p!=char(9)) && (*p!='.')) { if (i<(int)sizeof(T)-1) T[i++] = *p; p++; } T[i] = char(0); if (*p!='.') { // category name missing strcpy ( L,T ); // item name if (flags & CIFFL_SuggestCategories) sprintf ( T,"X%i",loopNo ); else strcpy ( T,"X" ); T[0] = char(1); // special category name } if (cifLoop) { if (strcmp(cifLoop->GetCategoryName(),T)) { // loop ended, empty p = p1; // play back to last category cifLoop = NULL; } } else { // look for category i = AddCategory ( T ); if ((i!=nC) && (nC>=0)) { // empty loop; most probably // a corrupted file p = p1; // play back to last category strcpy ( _err_string,S ); _err_line = lcount; Warning |= CIFW_EmptyLoop; if (flags & CIFFL_PrintWarnings) printf ( "\n **** mmCIF READ WARNING " "<>\n%s\n",lcount,S ); // AddCategory(..) has added a NULL-Category on the top of // category list; remove it now DeleteCategory ( nCategories-1 ); cifLoop = NULL; // return; } if (i<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated cifLoop = new Loop ( T ); Category[nCategories-1] = cifLoop; nC = nCategories-1; } } /* else if (Loop) { if (!strcmp(Loop->GetCategoryName(), Category[i]->GetCategoryName())) { if (Loop->GetCategoryID()!=MMCIF_Loop) { Warning |= CIFW_NotALoop; if (flags & CIFFL_PrintWarnings) printf ( "\n **** mmCIF READ WARNING " "<>\n%s\n",lcount,T,S ); delete Category[i]; Loop = new Loop ( T ); Category[i] = Loop; } } else Loop = NULL; } */ if (cifLoop) { if (*p=='.') { // get item name i = 0; p++; // skip period while ((*p) && (*p!=' ') && (*p!=char(9))) { T[i++] = *p; p++; } T[i] = char(0); } else strcpy ( T,L ); if (nWrongFields>0) WrongField = CheckWrongField ( cifLoop->name,T ); else WrongField = false; if (!WrongField) { if (cifLoop->AddTag(T)>=0) { if (flags & CIFFL_SuggestTags) { tagNo++; ParamStr ( T,pstr("\1"),tagNo ); cifLoop->AddTag(T); } else { strcpy ( _err_string,S ); _err_line = lcount; Warning |= CIFW_DuplicateTag; if (flags & CIFFL_PrintWarnings) printf ( "\n **** mmCIF READ WARNING " "<>\n%s\n",lcount,S ); } } } Repeat = true; } else { p = p1; Repeat = false; } } else if (!(*p) || (*p=='#')) { Repeat = !f.FileEnd(); if (Repeat) { f.ReadLine ( S,_max_buf_len ); lcount++; p = &(S[0]); } else { strcpy ( _err_string,S ); _err_line = lcount; Warning |= CIFW_UnexpectedEOF; if (flags & CIFFL_PrintWarnings) printf ( "\n **** mmCIF READ WARNING " "<>\n%s\n", lcount,S ); } } else Repeat = false; } while (Repeat); if (cifLoop) { do { while ((*p==' ') || (*p==char(9))) p++; if (!(*p) || (*p=='#')) { Repeat = !f.FileEnd(); if (Repeat) { f.ReadLine ( S,_max_buf_len ); lcount++; p = &(S[0]); } } else if (*p=='_') Repeat = false; else if (!strncmp(p,"loop_",5)) Repeat = false; else if (!strncmp(p,"data_",5)) Repeat = false; else if (!strncmp(p,"stop_",5)) { p += 5; Repeat = false; } else { RC = GetField ( f,S,L,p,lcount,llen ); if (!RC) { cifLoop->AddString ( L ); Repeat = true; } else Repeat = false; } } while (Repeat); if ((cifLoop->iColumn!=0) || (RC)) { strcpy ( _err_string,S ); _err_line = lcount; Warning |= CIFW_LoopFieldMissing; if (flags & CIFFL_PrintWarnings) printf ( "\n **** mmCIF READ WARNING " "<>\n%s\n", lcount,S ); } } } int Data::GetField ( io::RFile f, pstr S, pstr & L, pstr & p, int & lcount, int & llen ) { bool Repeat; pstr L1; int i,flen; char c; flen = 0; L[flen] = char(0); do { // skip all spaces before the field while ((*p==' ') || (*p==char(9))) p++; if ((*p=='#') || (!(*p))) { // comment or end of line met; the field should be // found on the next line Repeat = !f.FileEnd(); if (Repeat) { // take the next line f.ReadLine ( S,_max_buf_len ); lcount++; p = &(S[0]); Repeat = (*p!=';'); } else { // end of file and the field is not taken L[0] = char(0); return 1; } } else // first symbol of a field is found Repeat = false; } while (Repeat); if (*p==';') { // this is a multiline field p++; strcpy ( L,p ); // take first line of the field flen = strlen(L); while (!f.FileEnd()) { f.ReadLine ( S,_max_buf_len ); lcount++; p = &(S[0]); if (*p==';') { // multiline field terminated p++; while ((*p==' ') || (*p==char(9))) p++; return 0; } else { // multiline field continues -- take next line flen += strlen(S)+2; if (flen>=llen) { llen = flen + IMin(2000,llen); L1 = new char[llen]; strcpy ( L1,L ); delete[] L; L = L1; } strcat ( L,"\n" ); strcat ( L,S ); } } // end of file -- take the last line of the multiline field p = &(S[strlen(S)]); } else { i = 0; if (*p!='_') { if ((*p=='\'') || (*p=='"')) { c = *p; // field in quotation marks do { p++; // stop taking characters either on end of line // or the quotation mark while ((*p) && (*p!=c)) { L[i++] = *p; p++; } while (*p==c) { // it was a quotation mark -- check that it is followed // by end of line or space p++; if ((*p) && (*p!=' ') && (*p!=char(9))) { // the quotation mark is not a field terminator and // belongs to the field. L[i++] = c; // take the quotation mark if (*p!=c) // take the non-space character L[i++] = *p; // but check for field terminator } } // terminate the loop only on space or end of line } while ((*p) && (*p!=' ') && (*p!=char(9))); if (*p) p++; L[i] = char(0); } else { // a simplest field without spaces while ((*p) && (*p!=' ') && (*p!=char(9))) { L[i++] = *p; p++; } L[i] = char(0); if (((L[0]=='.') || (L[0]=='?')) && (!L[1])) { // "no data" tokens L[1] = L[0]; L[0] = char(2); L[2] = char(0); } } } } return 0; } void Data::Sort() { int i,k; psvector cnames; k = 0; for (i=0;iSort(); cnames[i] = NULL; CreateCopy ( cnames[i],Category[i]->name ); } SortTags ( cnames,nCategories,index ); for (i=0;i=0 : position of the category found // <0 : the category was not found, it could be inserted before // (-RC-1)th element, where RC is the return value int l1,l2,l,k; if ((!Category) || (nCategories<1)) return -1; if (!index) Sort(); if (cname[0]) { l = 0; l1 = 0; l2 = nCategories-1; k = 1; while (l1name ); if (k<0) l2 = l; else if (k>0) l1 = l; else { l1 = l; break; } } if (k==0) return index[l]; // is at RCth position k = strcasecmp(cname,Category[index[l1]]->name); if (k==0) return index[l1]; // is at RCth position if (k<0) return -1; // would be at (-RC-1)th position if (l2!=l1) { k = strcasecmp(cname,Category[index[l2]]->name); if (k==0) return index[l2]; // is at RCth position if (k>0) return -2-l2; // would be at l2+1=(-RC-1)th position } return -2-l1; // would be at l1+1=(-RC-1)th position } else // 'root' category should be always on top if (Category[index[0]]->name[0]==char(1)) return index[0]; return -1; } int Data::AddCategory ( cpstr cname ) { // return -1: a place for category has been added on the top of array; // index is added and sorted automatically // >=0: the category is already in the array -- its position // is returned int l1,l; PPCategory Category1; ivector index1; if (!Category) { Category = new PCategory[1]; Category[0] = NULL; GetVectorMemory ( index,1,0 ); index[0] = 0; nCategories = 1; return -nCategories; // the category has been added on the top of array } l1 = GetCategoryNo ( cname ); if (l1>=0) return l1; // non-negative returns mean that // the category is already in the array l1 = -l1-1; // otherwise the category has to be added and indexed at here // put new NULL-category on the top of array and update the index Category1 = new PCategory[nCategories+1]; GetVectorMemory ( index1,nCategories+1,0 ); for (l=0;lWriteMMCIF ( f ); } // --------------- Retrieving data int Data::DeleteCategory ( cpstr CName ) { int k; k = GetCategoryNo ( CName ); if (k<0) return CIFRC_NoCategory; return DeleteCategory ( k ); } int Data::DeleteCategory ( int CatNo ) { int i; if (Category[CatNo]) delete Category[CatNo]; for (i=CatNo+1;iCatNo) index[i]--; i++; } i++; while (iCatNo) index[i]--; index[i-1] = index[i]; i++; } nCategories--; index [nCategories] = 0; Category[nCategories] = NULL; return 0; } int Data::DeleteStructure ( cpstr CName ) { int k; k = GetCategoryNo ( CName ); if (k<0) return CIFRC_NoCategory; if (Category[k]->GetCategoryID()==MMCIF_Struct) return DeleteCategory ( k ); else return CIFRC_NotAStructure; } int Data::DeleteLoop ( cpstr CName ) { int k; k = GetCategoryNo ( CName ); if (k<0) return CIFRC_NoCategory; if (Category[k]->GetCategoryID()==MMCIF_Loop) return DeleteCategory ( k ); else return CIFRC_NotALoop; } PCategory Data::GetCategory ( int categoryNo ) { if ((categoryNo>=0) && (categoryNoGetCategoryID()==MMCIF_Struct) return PStruct(Category[i]); else return NULL; } PLoop Data::GetLoop ( cpstr CName ) { int i; i = GetCategoryNo ( CName ); if (i<0) return NULL; if (Category[i]->GetCategoryID()==MMCIF_Loop) return PLoop(Category[i]); else return NULL; } PLoop Data::FindLoop ( cpstr * tagList ) { int i; for (i=0;iGetCategoryID()==MMCIF_Loop) { if (Category[i]->CheckTags(tagList)) return PLoop(Category[i]); } } return NULL; } void Data::GetDataName ( pstr & dname, bool Remove ) { if (Remove) { if (dname) delete[] dname; dname = name; name = NULL; } else CreateCopy ( dname,name ); } int Data::CheckData ( cpstr CName, cpstr TName ) { // CheckData(..) returns positive value if the field is in the // file: // CIFRC_Structure category CName is a structure // CIFRC_Loop category CName is a loop // Negative returns mean: // CIFRC_StructureNoTag category CName is present, // it is a structure, but it does not // have tag TName // CIFRC_LoopNoTag category CName is present, // it is a loop, but it does not have // tag TName // CIFRC_NoCategory category CName is not present. // If TName is set to NULL then only the CName is checked and // possible returns are CIFRC_Structure, CIFRC_Loop and // CIFRC_NoCategory. int i,k; i = GetCategoryNo ( CName ); if (i<0) return CIFRC_NoCategory; if (Category[i]->GetCategoryID()==MMCIF_Struct) k = CIFRC_Structure; else k = CIFRC_Loop; if (TName) { if (Category[i]->GetTagNo(TName)<0) { if (k==CIFRC_Structure) k = CIFRC_StructureNoTag; else k = CIFRC_LoopNoTag; } } return k; } void Data::Optimize() { int i,k; PPCategory C1; k = 0; for (i=0;iOptimize(); if (Category[i]->nTags<=0) { delete Category[i]; Category[i] = NULL; } else k++; } if (k>0) { if (k!=nCategories) { C1 = new PCategory[k]; k = 0; for (i=0;iGetCategoryID()!=MMCIF_Struct) return CIFRC_NotAStructure; return PStruct(Category[i])->GetString ( Dest,TName,Remove ); } pstr Data::GetString ( cpstr CName, cpstr TName, int & RC ) { int i = GetCategoryNo ( CName ); if (i<0) { RC = CIFRC_NoCategory; return NULL; } if (Category[i]->GetCategoryID()!=MMCIF_Struct) { RC = CIFRC_NotAStructure; return NULL; } return PStruct(Category[i])->GetString ( TName,RC ); } int Data::DeleteField ( cpstr CName, cpstr TName ) { int i = GetCategoryNo ( CName ); if (i<0) return CIFRC_NoCategory; if (Category[i]->GetCategoryID()!=MMCIF_Struct) return CIFRC_NotAStructure; return PStruct(Category[i])->DeleteField ( TName ); } int Data::GetReal ( realtype & R, cpstr CName, cpstr TName, bool Remove ) { int i = GetCategoryNo ( CName ); if (i<0) return CIFRC_NoCategory; if (Category[i]->GetCategoryID()!=MMCIF_Struct) return CIFRC_NotAStructure; return PStruct(Category[i])->GetReal ( R,TName,Remove ); } int Data::GetInteger ( int & I, cpstr CName, cpstr TName, bool Remove ) { int j = GetCategoryNo ( CName ); if (j<0) return CIFRC_NoCategory; if (Category[j]->GetCategoryID()!=MMCIF_Struct) return CIFRC_NotAStructure; return PStruct(Category[j])->GetInteger ( I,TName,Remove ); } int Data::GetLoopLength ( cpstr CName ) { // GetLoopLength(..) returns CIFRC_NotALoop if the category CName // is not a loop, CIFRC_NoCategory if the category CName is not // found. Non-negative returns give the length of the loop (may be // 0 if the loop is empty). int i; i = GetCategoryNo ( CName ); if (i<0) return CIFRC_NoCategory; if (Category[i]->GetCategoryID()!=MMCIF_Loop) return CIFRC_NotALoop; return PLoop(Category[i])->nRows; } int Data::GetLoopString ( pstr & Dest, cpstr CName, cpstr TName, int nrow, bool Remove ) { // GetLoopString(..), GetLoopReal(..) and GetLoopInteger(..) act // like GetString(..), GetReal(..) and GetInteger(..) above for // nrow-th element of the 'loop_' (indexed like 0..N-1 where N // is obtained through GetLoopLength(..)). They will return // CIFRC_WrongIndex if nrow is out of range. int i = GetCategoryNo ( CName ); if (i<0) return CIFRC_NoCategory; if (Category[i]->GetCategoryID()!=MMCIF_Loop) return CIFRC_NotALoop; return PLoop(Category[i])->GetString ( Dest,TName,nrow,Remove ); } pstr Data::GetLoopString ( cpstr CName, cpstr TName, int nrow, int & RC ) { int i = GetCategoryNo ( CName ); if (i<0) { RC = CIFRC_NoCategory; return NULL; } if (Category[i]->GetCategoryID()!=MMCIF_Loop) { RC = CIFRC_NotALoop; return NULL; } return PLoop(Category[i])->GetString ( TName,nrow,RC ); } int Data::DeleteLoopField ( cpstr CName, cpstr TName, int nrow ) { int i = GetCategoryNo ( CName ); if (i<0) return CIFRC_NoCategory; if (Category[i]->GetCategoryID()!=MMCIF_Loop) return CIFRC_NotALoop; return PLoop(Category[i])->DeleteField ( TName,nrow ); } int Data::GetLoopReal ( realtype & R, cpstr CName, cpstr TName, int nrow, bool Remove ) { int i = GetCategoryNo ( CName ); if (i<0) return CIFRC_NoCategory; if (Category[i]->GetCategoryID()!=MMCIF_Loop) return CIFRC_NotALoop; return PLoop(Category[i])->GetReal ( R,TName,nrow,Remove ); } int Data::GetLoopInteger ( int & I, cpstr CName, cpstr TName, int nrow, bool Remove ) { int j = GetCategoryNo ( CName ); if (j<0) return CIFRC_NoCategory; if (Category[j]->GetCategoryID()!=MMCIF_Loop) return CIFRC_NotALoop; return PLoop(Category[j])->GetInteger ( I,TName,nrow,Remove ); } int Data::GetLoopSVector ( psvector & S, cpstr CName, cpstr TName, int i1, int i2, bool Remove ) { // GetLoopSVector(..), GetLoopRVector(..) and GetLoopIVector(..) // read CIF 'loop_' data into allocated vectors of strings, reals and // integers, correspondingly. The vectors may be deallocated prior // to call and assigned NULL, in which case they will be allocated // with offsets of i1, which is also the lower index of the 'loop_' // data transferred into it. The upper vector index is given by i2 or // by the loop's length whichever is less. If vectors are not assigned // NULL prior the call, it is assumed that they are properly (i1-offset, // i2-i1+1 length) allocated. // The return codes are same as those of GetLoopString(..), // GetLoopReal(..) and GetLoopInteger(..). int i; i = GetCategoryNo ( CName ); if (i<0) return CIFRC_NoCategory; if (Category[i]->GetCategoryID()!=MMCIF_Loop) return CIFRC_NotALoop; return PLoop(Category[i])->GetSVector ( S,TName,i1,i2,Remove ); } int Data::GetLoopRVector ( rvector & R, cpstr CName, cpstr TName, int i1, int i2, bool Remove ) { int i; i = GetCategoryNo ( CName ); if (i<0) return CIFRC_NoCategory; if (Category[i]->GetCategoryID()!=MMCIF_Loop) return CIFRC_NotALoop; return PLoop(Category[i])->GetRVector ( R,TName,i1,i2,Remove ); } int Data::GetLoopIVector ( ivector & I, cpstr CName, cpstr TName, int i1, int i2, bool Remove ) { int j; j = GetCategoryNo ( CName ); if (j<0) return CIFRC_NoCategory; if (Category[j]->GetCategoryID()!=MMCIF_Loop) return CIFRC_NotALoop; return PLoop(Category[j])->GetIVector ( I,TName,i1,i2,Remove ); } // --------------- Storing data void Data::PutDataName ( cpstr dname ) { // stores name for 'data_' record CreateCopy ( name,dname ); } int Data::PutNoData ( int NoDataType, cpstr CName, cpstr TName ) { PStruct cifStruct; int i,RC; RC = CIFRC_Ok; // look for category i = AddCategory ( CName ); if (i<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated cifStruct = new Struct ( CName ); Category[nCategories-1] = cifStruct; } else { cifStruct = PStruct(Category[i]); if (cifStruct->GetCategoryID()!=MMCIF_Struct) { RC = CIFRC_NotAStructure; delete Category[i]; cifStruct = new Struct ( CName ); Category[i] = cifStruct; } } cifStruct->PutNoData ( NoDataType,TName ); return RC; } int Data::PutString ( cpstr S, cpstr CName, cpstr TName, bool Concatenate ) { // PutString(..), PutReal(..) and PutInteger(..) will put the // values given into the specified category (CName) under the // specified tag (TName). The category, tag and field are created // automatically; the field will be replaced silently if identical // CName.TName is specified in two calls. Calls of these functions // may follow in random order; however CIF file will have all tags // grouped by categories and catgories will follow in the order // of first appearance in PutString(..), PutReal(..) or // PutInteger(..). // Return code - one of CIFRC_Ok or CIFRC_NotAStruct PStruct cifStruct; int i,RC; RC = CIFRC_Ok; // look for category i = AddCategory ( CName ); if (i<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated cifStruct = new Struct ( CName ); Category[nCategories-1] = cifStruct; } else { cifStruct = PStruct(Category[i]); if (cifStruct->GetCategoryID()!=MMCIF_Struct) { RC = CIFRC_NotAStructure; delete Category[i]; cifStruct = new Struct ( CName ); Category[i] = cifStruct; } } cifStruct->AddField ( S,TName,Concatenate ); return RC; } int Data::PutDate ( cpstr CName, cpstr TName ) { PStruct cifStruct; int i,RC; RC = CIFRC_Ok; // look for category i = AddCategory ( CName ); if (i<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated cifStruct = new Struct ( CName ); Category[nCategories-1] = cifStruct; } else { cifStruct = PStruct(Category[i]); if (cifStruct->GetCategoryID()!=MMCIF_Struct) { RC = CIFRC_NotAStructure; delete Category[i]; cifStruct = new Struct ( CName ); Category[i] = cifStruct; } } cifStruct->PutDate ( TName ); return RC; } int Data::PutReal ( realtype R, cpstr CName, cpstr TName, int prec ) { char rS[100]; sprintf ( rS,"%.*g",prec,R ); return PutString ( rS,CName,TName,false ); } int Data::PutInteger ( int I, cpstr CName, cpstr TName ) { char iS[100]; if (I>MinInt4) sprintf ( iS,"%i",I ); else { iS[0] = char(2); iS[1] = '.'; iS[2] = char(0); } return PutString ( iS,CName,TName,false ); } int Data::AddLoop ( cpstr CName, PLoop & cifLoop ) { int i,RC; RC = CIFRC_Ok; // look for category i = AddCategory ( CName ); if (i<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated cifLoop = new Loop ( CName ); Category[nCategories-1] = cifLoop; RC = CIFRC_Created; } else { cifLoop = PLoop(Category[i]); if (cifLoop->GetCategoryID()!=MMCIF_Loop) { RC = CIFRC_NotALoop; delete Category[i]; cifLoop = new Loop ( CName ); Category[i] = cifLoop; } } return RC; } int Data::AddStructure ( cpstr CName, PStruct & cifStruct ) { int i,RC; RC = CIFRC_Ok; // look for category i = AddCategory ( CName ); if (i<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated cifStruct = new Struct ( CName ); Category[nCategories-1] = cifStruct; RC = CIFRC_Created; } else { cifStruct = PStruct(Category[i]); if (cifStruct->GetCategoryID()!=MMCIF_Struct) { RC = CIFRC_NotAStructure; delete Category[i]; cifStruct = new Struct ( CName ); Category[i] = cifStruct; } } return RC; } int Data::PutLoopNoData ( int NoDataType, cpstr CName, cpstr TName, int nrow ) { PLoop cifLoop; int i,RC; RC = CIFRC_Ok; // look for category i = AddCategory ( CName ); if (i<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated cifLoop = new Loop ( CName ); Category[nCategories-1] = cifLoop; } else { cifLoop = PLoop(Category[i]); if (cifLoop->GetCategoryID()!=MMCIF_Loop) { RC = CIFRC_NotALoop; delete Category[i]; cifLoop = new Loop ( CName ); Category[i] = cifLoop; } } cifLoop->PutNoData ( NoDataType,TName,nrow ); return RC; } int Data::PutLoopString ( cpstr S, cpstr CName, cpstr TName, int nrow ) { // PutLoopString(..), PutLoopReal(..) and PutLoopInteger(..) act // like PutString(..), PutReal(..) and PutInteger(..) above for // nrow-th element of the 'loop_' CName (indexed begining from 0). // In consequitive calls, given values of nrow does not have to be // ordered; the most efficient way is to start with HIGHEST value // for nrow in the loop and move down to 0. The least efficient way // is to start with nrow=0 and move up. PLoop cifLoop; int i,RC; RC = CIFRC_Ok; // look for category i = AddCategory ( CName ); if (i<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated cifLoop = new Loop ( CName ); Category[nCategories-1] = cifLoop; } else { cifLoop = PLoop(Category[i]); if (cifLoop->GetCategoryID()!=MMCIF_Loop) { RC = CIFRC_NotALoop; delete Category[i]; cifLoop = new Loop ( CName ); Category[i] = cifLoop; } } cifLoop->PutString ( S,TName,nrow ); return RC; } int Data::PutLoopReal ( realtype R, cpstr CName, cpstr TName, int nrow, int prec ) { char rS[100]; sprintf ( rS,"%.*g",prec,R ); return PutLoopString ( rS,CName,TName,nrow ); } int Data::PutLoopInteger ( int I, cpstr CName, cpstr TName, int nrow ) { char iS[100]; sprintf ( iS,"%i",I ); return PutLoopString ( iS,CName,TName,nrow ); } int Data::PutLoopSVector ( psvector S, cpstr CName, cpstr TName, int i1, int i2 ) { // PutLoopSVector(..), PutLoopRVector(..) and PutLoopIVector(..) // put vectors of values into specified loop fields. Parameters i1 // and i2 give the range of indices of values which are to be // transfered. To transfer an entire vector allocated as [0..N-1] // i1 shoudl be set to 0 and i2 - to N-1. Note that the loop is // always indexed as starting form 0 on, therefore negative i1 and // i2 are not allowed, and specifying i1>0 will leave first i1 // elements of the CIF loop for the corresponding tag undefined // (will be output like '?'). PLoop cifLoop; int i,RC; RC = CIFRC_Ok; // look for category i = AddCategory ( CName ); if (i<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated cifLoop = new Loop ( CName ); Category[nCategories-1] = cifLoop; } else { cifLoop = PLoop(Category[i]); if (cifLoop->GetCategoryID()!=MMCIF_Loop) { RC = CIFRC_NotALoop; delete Category[i]; cifLoop = new Loop ( CName ); Category[i] = cifLoop; } } cifLoop->PutSVector ( S,TName,i1,i2 ); return RC; } int Data::PutLoopRVector ( rvector R, cpstr CName, cpstr TName, int i1, int i2, int prec ) { PLoop cifLoop; int i,RC; RC = CIFRC_Ok; // look for category i = AddCategory ( CName ); if (i<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated cifLoop = new Loop ( CName ); Category[nCategories-1] = cifLoop; } else { cifLoop = PLoop(Category[i]); if (cifLoop->GetCategoryID()!=MMCIF_Loop) { RC = CIFRC_NotALoop; delete Category[i]; cifLoop = new Loop ( CName ); Category[i] = cifLoop; } } cifLoop->PutRVector ( R,TName,i1,i2,prec ); return RC; } int Data::PutLoopIVector ( ivector I, cpstr CName, cpstr TName, int i1, int i2 ) { PLoop cifLoop; int j,RC; RC = CIFRC_Ok; // look for category j = AddCategory ( CName ); if (j<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated cifLoop = new Loop ( CName ); Category[nCategories-1] = cifLoop; } else { cifLoop = PLoop(Category[j]); if (cifLoop->GetCategoryID()!=MMCIF_Loop) { RC = CIFRC_NotALoop; delete Category[j]; cifLoop = new Loop ( CName ); Category[j] = cifLoop; } } cifLoop->PutIVector ( I,TName,i1,i2 ); return RC; } int Data::RenameCategory ( cpstr CName, cpstr newCName ) { int i,RC; i = GetCategoryNo ( CName ); if (i>=0) { Category[i]->PutCategoryName ( newCName ); Sort(); RC = CIFRC_Ok; } else RC = CIFRC_NoCategory; return RC; } void Data::Copy ( PData Data ) { int i; FreeMemory(0); CreateCopy ( name,Data->name ); nCategories = Data->nCategories; if (nCategories>0) { Category = new PCategory[nCategories]; GetVectorMemory ( index,nCategories,0 ); for (i=0;iCategory[i]) { if (Data->Category[i]->GetCategoryID()==MMCIF_Struct) Category[i] = new Struct(); else Category[i] = new Loop(); Category[i]->Copy ( Data->Category[i] ); } else Category[i] = NULL; index[i] = Data->index[i]; } } flags = Data->flags; Warning = Data->Warning; } int Data::CopyCategory ( PData Data, cpstr CName, cpstr newCName ) { PCategory Cat; int i,di,dc,RC; di = Data->GetCategoryNo ( CName ); if (di>=0) { RC = CIFRC_Ok; dc = Data->Category[di]->GetCategoryID(); // look for category i = AddCategory ( CName ); if (i<0) { // negative value means that the category was not in the list, // but a place for it has been provided and index updated if (dc==MMCIF_Loop) Cat = new Loop ( CName ); else Cat = new Struct ( CName ); Category[nCategories-1] = Cat; } else { Cat = Category[i]; if (Cat->GetCategoryID()!=dc) { RC = CIFRC_NotAStructure; delete Category[i]; if (dc==MMCIF_Loop) Cat = new Loop ( CName ); else Cat = new Struct ( CName ); Category[i] = Cat; } } Cat->Copy ( Data->Category[di] ); if (newCName) { Cat->PutCategoryName ( newCName ); Sort(); } } else RC = CIFRC_NoCategory; return RC; } void Data::PrintCategories() { // for debuging only int i; printf ( " Total %i categories:\n",nCategories ); for (i=0;iGetCategoryID()==MMCIF_Loop) printf ( "Loop %s\n",Category[i]->name ); else printf ( "Structure %s\n",Category[i]->name ); } } void Data::write ( io::RFile f ) { int i,k; if (!index) Sort(); f.CreateWrite ( name ); f.WriteInt ( &nCategories ); for (i=0;iGetCategoryID(); f.WriteInt ( &k ); Category[i]->write ( f ); } else { k = -1; f.WriteInt ( &k ); } f.WriteInt ( &(index[i]) ); } f.WriteInt ( &flags ); f.WriteInt ( &Warning ); } void Data::read ( io::RFile f ) { int i,k; FreeMemory(0); f.CreateRead ( name ); f.ReadInt ( &nCategories ); if (nCategories>0) { Category = new PCategory[nCategories]; GetVectorMemory ( index,nCategories,0 ); for (i=0;i=0) { if (k==MMCIF_Struct) Category[i] = new Struct(); else Category[i] = new Loop(); Category[i]->read ( f ); } else Category[i] = NULL; f.ReadInt ( &(index[i]) ); } } f.ReadInt ( &flags ); f.ReadInt ( &Warning ); } MakeStreamFunctions(Data) // ====================== File ============================= File::File() : io::Stream() { InitFile(); } File::File ( cpstr FName, io::GZ_MODE gzipMode ) : io::Stream() { InitFile (); ReadMMCIFFile ( FName,gzipMode ); } File::File ( io::RPStream Object ) : io::Stream(Object) { InitFile(); } File::~File() { FreeMemory(); } void File::InitFile() { nData = 0; nAllocData = 0; data = NULL; index = NULL; PrintWarnings = false; StopOnWarning = false; } void File::FreeMemory() { int i; for (i=0;iSetPrintWarnings ( PrintWarnings ); CIF->SetStopOnWarning ( StopOnWarning ); RC = CIF->ReadMMCIFData ( f,S,lcount ); if (!RC) { ExpandData ( nData+1 ); data[nData] = CIF; nData++; CIF = NULL; } } if (CIF) delete CIF; f.shut(); if (RC==CIFRC_NoDataLine) { if (nData>0) RC = 0; } Sort(); return RC; } else return CIFRC_CantOpenFile; } int File::WriteMMCIFFile ( cpstr FName, io::GZ_MODE gzipMode ) { io::File f; f.assign ( FName,true,false,gzipMode ); if (f.rewrite()) { WriteMMCIF ( f ); f.shut(); return 0; } else return CIFRC_CantOpenFile; } void File::WriteMMCIF ( io::RFile f ) { int i; for (i=0;iWriteMMCIF ( f ); } void File::Sort() { psvector tag; int i; if (nData>0) { FreeVectorMemory ( index,0 ); GetVectorMemory ( index,nData,0 ); GetVectorMemory ( tag ,nData,0 ); for (i=0;iname ); } SortTags ( tag,nData,index ); for (i=0;i=0 : position of the DName found // <0 : the DName was not found, it could be inserted before // (-RC-1)th element, where RC is the return value int l1,l2,l,k; if (!data) return -1; if (!index) Sort(); l = 0; l1 = 0; l2 = nData-1; k = 1; while (l1name ); if (k<0) l2 = l; else if (k>0) l1 = l; else { l1 = l; break; } } if (k==0) return index[l]; // is at RCth position k = strcasecmp ( DName,data[index[l1]]->name ); if (k==0) return index[l1]; // is at RCth position if (k<0) return -1; // would be at (-RC-1)th position if (l2!=l1) { k = strcasecmp ( DName,data[index[l2]]->name ); if (k==0) return index[l2]; // is at RCth position if (k>0) return -2-l2; // would be at l2+1=(-RC-1)th position } return -2-l1; // would be at l1+1=(-RC-1)th position } PData File::GetCIFData ( int dataNo ) { if ((dataNo>=0) && (dataNo=0) return data[l]; else return NULL; } void File::ExpandData ( int nDataNew ) { int i,nAD; PPData data1; ivector index1; if (nDataNew>nAllocData) { nAD = nDataNew + IMin(nAllocData/2+1,100); data1 = new PData[nAD]; GetVectorMemory ( index1,nAD,0 ); for (i=0;i=0: the CIF data structure is already in the array // -- its position is returned int i1,i; if (!data) { ExpandData ( 3 ); // get space for first 3 CIF data structures data[0] = new Data ( DName ); nData = 1; return -nData; // the CIF data structure has been added // "on the top" of array } i1 = GetCIFDataNo ( DName ); if (i1>=0) return i1; // non-negative returns mean that the CIF // data structure is already in the array i1 = -i1-1; // otherwise the data has to be added and indexed at here // put new CIF data structure on the top of array and update index ExpandData ( nData+1 ); data[nData] = new Data ( DName ); for (i=nData;i>i1;i--) index[i] = index[i-1]; index[i1] = nData; nData++; return -nData; // the tag has been added on the top of array } int File::DeleteCIFData ( cpstr DName ) { int dataNo = GetCIFDataNo ( DName ); if (dataNo>=0) return DeleteCIFData ( dataNo ); return dataNo; } int File::DeleteCIFData ( int dataNo ) { int i; if ((0<=dataNo) && (dataNonData; nAllocData = nData; if (nData>0) { data = new PData[nData]; for (i=0;idata[i]) { data[i] = new Data(); data[i]->Copy ( File->data[i] ); } else data[i] = NULL; } } } void File::write ( io::RFile f ) { int i,k; f.WriteInt ( &nData ); for (i=0;iwrite ( f ); } else { k = 0; f.WriteInt ( &k ); } } void File::read ( io::RFile f ) { int i,k; FreeMemory(); f.ReadInt ( &nData ); nAllocData = nData; if (nData>0) { data = new PData[nData]; for (i=0;iread ( f ); } else data[i] = NULL; } } } MakeStreamFunctions(File) int isCIF ( cpstr FName, io::GZ_MODE gzipMode ) { io::File f; int rc; f.assign ( FName,true,false,gzipMode ); if (f.reset(true)) { rc = isCIF ( f ); f.shut(); } else rc = -1; return rc; } int isCIF ( io::RFile f ) { char S[_max_buf_len+1]; bool Done; pstr p; f.ReadLine ( S,_max_buf_len ); S[_max_buf_len] = char(0); Done = false; while (!Done) { p = &(S[0]); while ((*p==' ') || (*p==char(9))) p++; Done = !strncmp(p,"data_",5); if (!Done) { if (f.FileEnd()) { Done = true; p = NULL; } else { f.ReadLine ( S,_max_buf_len ); S[_max_buf_len] = char(0); } } } if (!p) return 1; if (!strncmp(p,"data_",5)) return 0; else return 1; } pstr GetCIFMessage ( pstr M, int RC ) { int LineNo; pstr InputLine; InputLine = GetMMCIFInputBuffer ( LineNo ); if (RC>10) { if (RC & CIFW_UnrecognizedItems) sprintf ( M,"unrecognized items found on %ith line\n%s", LineNo,InputLine ); else if (RC & CIFW_MissingField) sprintf ( M,"expected data field not found; line %i reads\n%s", LineNo,InputLine ); else if (RC & CIFW_EmptyLoop) sprintf ( M,"empty loop ('loop_') on %ith line\n%s", LineNo,InputLine ); else if (RC & CIFW_UnexpectedEOF) sprintf ( M,"unexpected end of file; line %i reads\n%s", LineNo,InputLine ); else if (RC & CIFW_LoopFieldMissing) sprintf ( M,"expected data field in a loop not found; " "line %i reads\n%s", LineNo,InputLine ); else if (RC & CIFW_LoopFieldMissing) sprintf ( M,"expected data field in a loop not found; " "line %i reads\n%s", LineNo,InputLine ); else if (RC & CIFW_NotAStructure) sprintf ( M,"a loop is used as a structure on line %i\n%s", LineNo,InputLine ); else if (RC & CIFW_NotALoop) sprintf ( M,"a structure is used as a loop on line %i\n%s", LineNo,InputLine ); else if (RC & CIFW_DuplicateTag) sprintf ( M,"duplicate tag was found on line %i\n%s", LineNo,InputLine ); else sprintf ( M,"undocumented warning issued for line %i\n%s", LineNo,InputLine ); } else if (RC<0) switch (RC) { case CIFRC_StructureNoTag : strcpy(M,"tag of a structure not " "found"); break; case CIFRC_LoopNoTag : strcpy(M,"tag of a loop not found"); break; case CIFRC_NoCategory : strcpy(M,"category not found"); break; case CIFRC_WrongFormat : strcpy(M,"wrong format of a number"); break; case CIFRC_NoTag : strcpy(M,"tag not found"); break; case CIFRC_NotAStructure : strcpy(M,"category is not a " "structure"); break; case CIFRC_NotALoop : strcpy(M,"category is not a loop"); break; case CIFRC_WrongIndex : strcpy(M,"index outside the loop's " "limits"); break; case CIFRC_NoField : strcpy(M,"data is absent"); break; case CIFRC_Created : strcpy(M,"category created"); break; case CIFRC_CantOpenFile : strcpy(M,"can't open CIF file"); break; case CIFRC_NoDataLine : strcpy(M,"'data_' tag not found." ); break; default : strcpy(M,"undocumented return code"); } return M; } } // namespace mmcif } // namespace mmdb mmdb2-2.0.5/mmdb2/mmdb_defs.h0000664000175000017500000002303412601171753012541 00000000000000// $Id: mmdb_defs.h,v 1.27 2012/01/26 17:52:20 ekr Exp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2015. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 07.09.15 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDBF_Defs // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // // Definition of types, constants and important classes. // // (C) E. Krissinel 2000-2015 // // ================================================================= // #ifndef __MMDB_Defs__ #define __MMDB_Defs__ #include "mmdb_mattype.h" namespace mmdb { enum MMDB_VERSION { MAJOR_VERSION = 2, //!< MMDB major version MINOR_VERSION = 0, //!< MMDB minor version MICRO_VERSION = 5 //!< MMDB micro version }; // ======================= types ================================= typedef char IDCode [16]; //!< ID code of PDB entry typedef IDCode * PIDCode; //!< pointer to ID code typedef PIDCode & RPIDCode; //!< ref. to pointer to ID code typedef char Date [12]; //!< date DD-MMM-YYYY typedef char RecName [7]; //!< name of PDB record typedef char ChainID [10]; //!< chain ID typedef ChainID * PChainID; //!< pointer to chain ID typedef char InsCode [10]; //!< insertion code typedef char DBName [10]; //!< sequence database name typedef char DBAcCode[20]; //!< seq. database accession code typedef DBAcCode * PDBAcCode; //!< pointer to seq. db acc code typedef char DBIdCode[20]; //!< seq. database ident-n code typedef DBIdCode * PDBIdCode; //!< pointer to DBIdCode typedef char ResName [20]; //!< residue name typedef ResName * PResName; //!< pointer to residue name typedef PResName * PPResName; //!< ptr to vector of residue names typedef char HelixID [20]; //!< helix ID typedef char StrandID[20]; //!< strand ID typedef char SheetID [20]; //!< sheet ID typedef char TurnID [20]; //!< turn ID typedef char LinkRID [20]; //!< Refmac link ID typedef char SymGroup[100]; //!< group of space symmetry typedef realtype vect3 [3]; //!< vector of 3 real numbers typedef vect3 * pvect3; //!< ptr to vector 3 typedef pvect3 & rpvect3; //!< ref to ptr to vector 3 typedef realtype vect4 [4]; //!< vector of 4 real numbers typedef vect3 mat33 [3]; //!< matrix 3x3 of real numbers typedef vect4 mat44 [4]; //!< matrix 4x4 of real numbers typedef mat44 * pmat44; //!< ptr to matrix 4x4 typedef mat44 & rmat44; //!< ref to matrix 4x4 typedef pmat44 * ppmat44; //!< ptr to ptr to matrix 4x4 typedef pmat44 & rpmat44; //!< ref to ptr to matrix 4x4 typedef mat33 mat633 [6]; //!< matrix 6x3x3 of real numbers typedef char AtomName[20]; //!< name of the atom typedef AtomName * PAtomName; //!< pointer to atom name typedef char AltLoc [20]; //!< alternate location indicator typedef AltLoc * PAltLoc; //!< pointer to alt loc indicator typedef char SegID [20]; //!< segment identifier typedef char Element [10]; //!< chemical element name typedef Element * PElement; //!< ptr to chemical element name typedef char EnergyType[10]; //!< energy type name typedef EnergyType * PEnergyType; //!< pointer to energy type name // do not forget update this when change the above typedefs: typedef char maxMMDBName[40]; // ===================== constants =============================== // ANY_RES should be used in selection functions for specifying // "any residue" to select. Defined in mmdb_selmngr.cpp extern const int ANY_RES; // PRNK_XXXXX are the print keys. PRNK_Silent supresses all print // inside mmdb_xxxx unless specifically ordered or catastrophic. // PRNK_SimRWBROOK instructs mmdb to issue, whenever possible and // necessary, printouts and warnings of RWBROOK (fortran) package. enum PRINT_KEY { PRNK_Silent = 0, PRNK_SimRWBROOK = 1 }; // Error_XXXX may be returned by XX::ConvertPDBString() and GetCIF(..) // functions. // Error_WrongSection is returned if the string passed into function // does not belong to the corresponding PDB section. enum ERROR_CODE { Error_EmptyCIF =-1, //!< used as signal at reading CIF files Error_NoError = 0, Error_Ok = 0, Error_WrongSection = 1, Error_WrongChainID = 2, Error_WrongEntryID = 3, // Error_SEQRES_serNum is returned by CSeqRes::ConvertPDBASCII() if // serial numbers of SEQRES records do not increment by 1 Error_SEQRES_serNum = 4, // Error_SEQRES_numRes is returned by CSeqRes::ConvertPDBASCII() if // SEQRES records show different number of residues Error_SEQRES_numRes = 5, // Error_SEQRES_extraRes is returned by CSeqRes::ConvertPDBASCII() if // SEQRES contains more residues than specified Error_SEQRES_extraRes = 6, Error_NCSM_Unrecognized = 7, Error_NCSM_AlreadySet = 8, Error_NCSM_WrongSerial = 9, Error_NCSM_UnmatchIG = 10, Error_ATOM_Unrecognized = 11, Error_ATOM_AlreadySet = 12, Error_ATOM_NoResidue = 13, Error_ATOM_Unmatch = 14, Error_CantOpenFile = 15, Error_UnrecognizedInteger = 16, Error_WrongModelNo = 17, Error_DuplicatedModel = 18, Error_NoModel = 19, Error_ForeignFile = 20, Error_WrongEdition = 21, // CIF specific Error_NotACIFFile = 22, Error_NoData = 23, Error_NoLoop = 24, Error_NoStruct = 25, Error_UnrecognCIFItems = 26, Error_MissingCIFField = 27, Error_EmptyCIFLoop = 28, Error_EmptyCIFStruct = 29, Error_UnexpEndOfCIF = 30, Error_MissgCIFLoopField = 31, Error_NotACIFStructure = 32, Error_NotACIFLoop = 33, Error_UnrecognizedReal = 34, Error_NoSheetID = 35, Error_WrongSheetID = 36, Error_WrongStrandNo = 37, // Error_WrongNumberOfStrands may be issued when reading // sheet data from CIF Error_WrongNumberOfStrands = 38, // Error_WrongSheetOrder may be issued when reading // sheet data from CIF Error_WrongSheetOrder = 39, // Error_HBondInconsistency may be issued when reading // sheet data from CIF Error_HBondInconsistency = 40, // Error_EmptyResidueName is issued when PDB ATOM record // does not have a residue name Error_EmptyResidueName = 41, // Error_DuplicateSeqNum is issued when PDB ATOM records // show the sequence number and insertion code assigned // to more than one residue name Error_DuplicateSeqNum = 42, // Error_NoLogicalName may be returned by file i/o functions // if the specified environmental variable for file name // is not found. Error_NoLogicalName = 43, // Error_EmptyFile may be returned at reading non-existing // coordinate files Error_EmptyFile = 44, Error_Unknown = 45, // Error_CIF_EmptyRow is the event of encountering // an empty row in _atom_site loop. It is handled // internally and has no effect on API Error_CIF_EmptyRow = 99999, Error_GeneralError1 = 10000 }; // ClassID_XXXX are used by container classes for proper // creating containered classes when reading from binary file. enum CLASS_ID { ClassID_Template , ClassID_String , ClassID_ObsLine , ClassID_TitleLine , ClassID_CAVEAT , ClassID_Compound , ClassID_Source , ClassID_ExpData , ClassID_MdlType , ClassID_Author , ClassID_RevData , ClassID_Supersede , ClassID_Journal , ClassID_Remark , ClassID_DBReference, ClassID_SeqAdv , ClassID_ModRes , ClassID_Het , ClassID_NCSMatrix , ClassID_TVect , ClassID_Helix , ClassID_Turn , ClassID_Link , ClassID_LinkR , ClassID_CisPep }; // ===================== classes =============================== DefineClass(Atom); DefineClass(Residue); DefineClass(Chain); DefineClass(Model); DefineClass(Manager); } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_chain.cpp0000664000175000017500000021510112601171753013233 00000000000000// $Id: mmdb_chain.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 16.05.14 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_Chain // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::ProModel ( a virtue of Model ) // ~~~~~~~~~ mmdb::DBReference ( DBREF records ) // mmdb::ChainContainer ( container of in-chain classes ) // mmdb::ContainerChain ( chain containered class template) // mmdb::SeqAdv ( SEQADV records ) // mmdb::SeqRes ( SEQRES records ) // mmdb::ModRes ( MODRES records ) // mmdb::HetRec ( HET records ) // mmdb::Chain ( chain class ) // // Copyright (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include #include "mmdb_chain.h" #include "mmdb_model.h" #include "mmdb_manager.h" #include "mmdb_cifdefs.h" namespace mmdb { // ================== ProModel ====================== MakeStreamFunctions(ProModel) // ============== ChainContainer ==================== PContainerClass ChainContainer::MakeContainerClass ( int ClassID ) { switch (ClassID) { default : case ClassID_Template : return ClassContainer::MakeContainerClass(ClassID); case ClassID_DBReference : return new DBReference ( chain ); case ClassID_SeqAdv : return new SeqAdv ( chain ); case ClassID_ModRes : return new ModRes ( chain ); case ClassID_Het : return new HetRec ( chain ); } } void ChainContainer::SetChain ( PChain Chain_Owner ) { int i; chain = Chain_Owner; for (i=0;iSetChain ( chain ); } cpstr ChainContainer::Get1stChainID() { int i; i = 0; if (Container) { while ((ichainID; else return NULL; } else return NULL; } void ChainContainer::MoveByChainID ( const ChainID chainID, PChainContainer ChainContainer ) { int i; for (i=0;ichainID,chainID)) { ChainContainer->AddData ( Container[i] ); Container[i] = NULL; } } } MakeStreamFunctions(ChainContainer) // ================ ContainerChain =================== ContainerChain::ContainerChain() : ContainerClass() { chain = NULL; chainID[0] = char(0); } ContainerChain::ContainerChain ( PChain Chain_Owner) : ContainerClass() { chain = Chain_Owner; if (chain) strcpy ( chainID,chain->GetChainID() ); else chainID[0] = char(0); } void ContainerChain::SetChain ( PChain Chain_Owner ) { chain = Chain_Owner; if (chain) strcpy ( chainID,chain->GetChainID() ); else strcpy ( chainID,"" ); } MakeStreamFunctions(ContainerChain) // ================ DBReference =================== DBReference::DBReference() : ContainerChain() { InitDBReference(); } DBReference::DBReference( PChain Chain_Owner ) : ContainerChain(Chain_Owner) { InitDBReference(); } DBReference::DBReference ( PChain Chain_Owner, cpstr S ) : ContainerChain(Chain_Owner) { InitDBReference(); ConvertPDBASCII ( S ); } DBReference::DBReference ( io::RPStream Object ) : ContainerChain(Object) { InitDBReference(); } DBReference::~DBReference() {} void DBReference::InitDBReference() { seqBeg = 0; strcpy ( insBeg ,"-" ); seqEnd = 0; strcpy ( insEnd ,"-" ); strcpy ( database ,"------" ); strcpy ( dbAccession,"--------" ); strcpy ( dbIdCode ,"------------" ); dbseqBeg = 0; strcpy ( dbinsBeg,"-" ); dbseqEnd = 0; strcpy ( dbinsEnd,"-" ); } void DBReference::PDBASCIIDump ( pstr S, int N ) { UNUSED_ARGUMENT(N); // makes the ASCII PDB DBREF line number N // from the class' data strcpy ( S,"DBREF" ); PadSpaces ( S,80 ); strcpy_n ( &(S[7]),chain->GetEntryID(),4 ); if (chain->chainID[0]) S[12] = chain->chainID[0]; PutIntIns ( &(S[14]),seqBeg,4,insBeg ); PutIntIns ( &(S[20]),seqEnd,4,insEnd ); strcpy_n ( &(S[26]),database ,6 ); strcpy_n ( &(S[33]),dbAccession,8 ); strcpy_n ( &(S[42]),dbIdCode ,12 ); PutIntIns ( &(S[55]),dbseqBeg,5,dbinsBeg ); PutIntIns ( &(S[62]),dbseqEnd,5,dbinsEnd ); } void DBReference::MakeCIF ( mmcif::PData CIF, int N ) { UNUSED_ARGUMENT(N); mmcif::PLoop Loop1,Loop2; int RC1,RC2; RC1 = CIF->AddLoop ( CIFCAT_STRUCT_REF_SEQ,Loop1 ); RC2 = CIF->AddLoop ( CIFCAT_STRUCT_REF ,Loop2 ); if ((RC1!=mmcif::CIFRC_Ok) || (RC2!=mmcif::CIFRC_Ok)) { // the category was (re)created, provide tags Loop1->AddLoopTag ( CIFTAG_NDB_PDB_ID_CODE ); Loop1->AddLoopTag ( CIFTAG_NDB_CHAIN_ID ); Loop1->AddLoopTag ( CIFTAG_SEQ_ALIGN_BEG ); Loop1->AddLoopTag ( CIFTAG_NDB_SEQ_ALIGN_BEG_INS_CODE ); Loop1->AddLoopTag ( CIFTAG_SEQ_ALIGN_END ); Loop1->AddLoopTag ( CIFTAG_NDB_SEQ_ALIGN_END_INS_CODE ); Loop1->AddLoopTag ( CIFTAG_NDB_DB_ACCESSION ); Loop1->AddLoopTag ( CIFTAG_DB_ALIGN_BEG ); Loop1->AddLoopTag ( CIFTAG_NDB_DB_ALIGN_BEG_INS_CODE ); Loop1->AddLoopTag ( CIFTAG_DB_ALIGN_END ); Loop1->AddLoopTag ( CIFTAG_NDB_DB_ALIGN_END_INS_CODE ); Loop2->AddLoopTag ( CIFTAG_DB_NAME ); Loop2->AddLoopTag ( CIFTAG_DB_CODE ); } Loop1->AddString ( chain->GetEntryID(),true ); Loop1->AddString ( chain->chainID ,true ); Loop1->AddInteger ( seqBeg ); Loop1->AddString ( insBeg ,true ); Loop1->AddInteger ( seqEnd ); Loop1->AddString ( insEnd ,true ); Loop1->AddString ( dbAccession ,true ); Loop1->AddInteger ( dbseqBeg ); Loop1->AddString ( dbinsBeg ,true ); Loop1->AddInteger ( dbseqEnd ); Loop1->AddString ( dbinsEnd ,true ); Loop2->AddString ( database,true ); Loop2->AddString ( dbIdCode,true ); } ERROR_CODE DBReference::GetCIF ( mmcif::PData CIF, int & n ) { // GetCIF(..) must be always run without reference to Chain, // see CModel::GetCIF(..). mmcif::PLoop Loop1,Loop2; mmcif::PStruct Struct2; pstr F; int RC,ref_id1,ref_id2; CIF_MODE CIFMode; ERROR_CODE rc; Loop1 = CIF->GetLoop ( CIFCAT_STRUCT_REF_SEQ ); if (!Loop1) { n = -1; return Error_EmptyCIF; } if (n>=Loop1->GetLoopLength()) { n = -1; return Error_EmptyCIF; } // Determine the ChainID first and store it locally. It will // be used by CModel for generating chains and placing the // primary structure data BEFORE reading the coordinate section. CIFMode = CIF_NDB; F = Loop1->GetString ( CIFName(TAG_CHAIN_ID,CIFMode),n,RC ); if ((RC) || (!F)) { CIFMode = CIF_PDBX; F = Loop1->GetString ( CIFName(TAG_CHAIN_ID,CIFMode),n,RC ); } if ((!RC) && F) { strcpy_n0 ( chainID,F,sizeof(ChainID)-1 ); Loop1->DeleteField ( CIFName(TAG_CHAIN_ID,CIFMode),n ); } else strcpy ( chainID,"" ); rc = CIFGetInteger(seqBeg,Loop1,CIFName(TAG_SEQ_ALIGN_BEG,CIFMode),n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( insBeg,Loop1,CIFName(TAG_SEQ_ALIGN_BEG_INS_CODE,CIFMode), n,sizeof(InsCode),pstr(" ") ); rc = CIFGetInteger(seqEnd,Loop1,CIFName(TAG_SEQ_ALIGN_END,CIFMode),n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( insEnd,Loop1,CIFName(TAG_SEQ_ALIGN_END_INS_CODE,CIFMode), n,sizeof(InsCode),pstr(" ") ); CIFGetString ( dbAccession,Loop1,CIFName(TAG_DB_ACCESSION,CIFMode), n,sizeof(DBAcCode),pstr(" ") ); rc = CIFGetInteger(dbseqBeg,Loop1,CIFName(TAG_DB_ALIGN_BEG,CIFMode),n); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( dbinsBeg,Loop1,CIFName(TAG_DB_ALIGN_BEG_INS_CODE,CIFMode), n,sizeof(InsCode),pstr(" ") ); rc = CIFGetInteger(dbseqEnd,Loop1,CIFName(TAG_DB_ALIGN_END,CIFMode),n); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( dbinsEnd,Loop1,CIFName(TAG_DB_ALIGN_END_INS_CODE,CIFMode), n,sizeof(InsCode),pstr(" ") ); Loop2 = CIF->GetLoop ( CIFCAT_STRUCT_REF ); if (Loop2) { CIFGetString ( database,Loop2,CIFTAG_DB_NAME,n, sizeof(DBName) ,pstr(" ") ); CIFGetString ( dbIdCode,Loop2,CIFTAG_DB_CODE,n, sizeof(DBIdCode),pstr(" ") ); } else if (CIFMode==CIF_PDBX) { Struct2 = CIF->GetStructure ( CIFCAT_STRUCT_REF ); if (Struct2 && (!CIFGetInteger(ref_id1,Loop1,CIFTAG_REF_ID,n)) && (!CIFGetInteger(ref_id2,Struct2,CIFTAG_ID,false))) { if (ref_id1==ref_id2) { CIFGetString ( database,Struct2,CIFTAG_DB_NAME, sizeof(DBName) ,pstr(" ") ,false ); CIFGetString ( dbIdCode,Struct2,CIFTAG_DB_CODE, sizeof(DBIdCode),pstr(" "),false ); } } } n++; return Error_NoError; } ERROR_CODE DBReference::ConvertPDBASCII ( cpstr S ) { IDCode idCode; if (chain->chainID[0]) { if (S[12]!=chain->chainID[0]) return Error_WrongChainID; } else if (S[12]!=' ') { chain->chainID[0] = S[12]; chain->chainID[1] = char(0); } else chain->chainID[0] = char(0); strcpy ( idCode,chain->GetEntryID() ); if (idCode[0]) { if (strncmp(&(S[7]),idCode,4) && (!ignoreNonCoorPDBErrors)) return Error_WrongEntryID; } else { GetString ( idCode,&(S[7]),4 ); chain->SetEntryID ( idCode ); } GetIntIns ( seqBeg,insBeg,&(S[14]),4 ); GetIntIns ( seqEnd,insEnd,&(S[20]),4 ); strcpy_ncs ( database ,&(S[26]),6 ); strcpy_ncs ( dbAccession ,&(S[33]),8 ); strcpy_ncs ( dbIdCode ,&(S[42]),12 ); GetIntIns ( dbseqBeg,dbinsBeg,&(S[55]),5 ); GetIntIns ( dbseqEnd,dbinsEnd,&(S[62]),5 ); return Error_NoError; } void DBReference::Copy ( PContainerClass DBRef ) { ContainerChain::Copy ( DBRef ); seqBeg = PDBReference(DBRef)->seqBeg; seqEnd = PDBReference(DBRef)->seqEnd; dbseqBeg = PDBReference(DBRef)->dbseqBeg; dbseqEnd = PDBReference(DBRef)->dbseqEnd; strcpy ( insBeg ,PDBReference(DBRef)->insBeg ); strcpy ( insEnd ,PDBReference(DBRef)->insEnd ); strcpy ( database ,PDBReference(DBRef)->database ); strcpy ( dbAccession,PDBReference(DBRef)->dbAccession ); strcpy ( dbIdCode ,PDBReference(DBRef)->dbIdCode ); strcpy ( dbinsBeg ,PDBReference(DBRef)->dbinsBeg ); strcpy ( dbinsEnd ,PDBReference(DBRef)->dbinsEnd ); } void DBReference::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &seqBeg ); f.WriteInt ( &seqEnd ); f.WriteInt ( &dbseqBeg ); f.WriteInt ( &dbseqEnd ); f.WriteTerLine ( insBeg ,false ); f.WriteTerLine ( insEnd ,false ); f.WriteTerLine ( database ,false ); f.WriteTerLine ( dbAccession,false ); f.WriteTerLine ( dbIdCode ,false ); f.WriteTerLine ( dbinsBeg ,false ); f.WriteTerLine ( dbinsEnd ,false ); } void DBReference::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.ReadInt ( &seqBeg ); f.ReadInt ( &seqEnd ); f.ReadInt ( &dbseqBeg ); f.ReadInt ( &dbseqEnd ); f.ReadTerLine ( insBeg ,false ); f.ReadTerLine ( insEnd ,false ); f.ReadTerLine ( database ,false ); f.ReadTerLine ( dbAccession,false ); f.ReadTerLine ( dbIdCode ,false ); f.ReadTerLine ( dbinsBeg ,false ); f.ReadTerLine ( dbinsEnd ,false ); } MakeStreamFunctions(DBReference) // ================ SeqAdv =================== SeqAdv::SeqAdv() : ContainerChain() { InitSeqAdv(); } SeqAdv::SeqAdv ( PChain Chain_Owner ) : ContainerChain(Chain_Owner) { InitSeqAdv(); } SeqAdv::SeqAdv ( PChain Chain_Owner, cpstr S ) : ContainerChain(Chain_Owner) { InitSeqAdv(); ConvertPDBASCII ( S ); } SeqAdv::SeqAdv ( io::RPStream Object ) : ContainerChain(Object) { InitSeqAdv(); } SeqAdv::~SeqAdv() { if (conflict) delete[] conflict; } void SeqAdv::InitSeqAdv() { strcpy ( resName ,"---" ); seqNum = 0; strcpy ( insCode ,"-" ); strcpy ( database ,"------" ); strcpy ( dbAccession,"---------" ); strcpy ( dbRes ,"---" ); dbSeq = 0; conflict = NULL; CreateCopy ( conflict,pstr(" ") ); } void SeqAdv::PDBASCIIDump ( pstr S, int N ) { UNUSED_ARGUMENT(N); // makes the ASCII PDB SEQADV line number N // from the class' data strcpy ( S,"SEQADV" ); PadSpaces ( S,80 ); strcpy_n ( &(S[7]) ,chain->GetEntryID(),4 ); strcpy_n ( &(S[12]),resName ,3 ); if (chain->chainID[0]) S[16] = chain->chainID[0]; PutIntIns ( &(S[18]),seqNum,4,insCode ); strcpy_n ( &(S[24]),database ,4 ); strcpy_n ( &(S[29]),dbAccession,9 ); strcpy_n ( &(S[39]),dbRes ,3 ); PutInteger ( &(S[43]),dbSeq ,5 ); strcpy_n ( &(S[49]),conflict,IMin(strlen(conflict),21) ); } ERROR_CODE SeqAdv::ConvertPDBASCII ( cpstr S ) { IDCode idCode; if (chain->chainID[0]) { if (S[16]!=chain->chainID[0]) return Error_WrongChainID; } else if (S[16]!=' ') { chain->chainID[0] = S[16]; chain->chainID[1] = char(0); } else chain->chainID[0] = char(0); strcpy ( idCode,chain->GetEntryID() ); if (idCode[0]) { if (strncmp(&(S[7]),idCode,4) && (!ignoreNonCoorPDBErrors)) return Error_WrongEntryID; } else { GetString ( idCode,&(S[7]),4 ); chain->SetEntryID ( idCode ); } strcpy_ncs ( resName ,&(S[12]),3 ); GetIntIns ( seqNum,insCode,&(S[18]),4 ); strcpy_ncs ( database ,&(S[24]),4 ); strcpy_ncs ( dbAccession ,&(S[29]),9 ); strcpy_ncs ( dbRes ,&(S[39]),3 ); GetInteger ( dbSeq,&(S[43]),5 ); CreateCopy ( conflict,&(S[49]) ); CutSpaces ( conflict,SCUTKEY_END ); return Error_NoError; } void SeqAdv::MakeCIF ( mmcif::PData CIF, int N ) { UNUSED_ARGUMENT(N); mmcif::PLoop Loop; int RC; RC = CIF->AddLoop ( CIFCAT_STRUCT_REF_SEQ_DIF,Loop ); if (RC!=mmcif::CIFRC_Ok) { // the category was (re)created, provide tags Loop->AddLoopTag ( CIFTAG_NDB_PDB_ID_CODE ); Loop->AddLoopTag ( CIFTAG_MON_ID ); Loop->AddLoopTag ( CIFTAG_NDB_PDB_CHAIN_ID ); Loop->AddLoopTag ( CIFTAG_SEQ_NUM ); Loop->AddLoopTag ( CIFTAG_NDB_PDB_INS_CODE ); Loop->AddLoopTag ( CIFTAG_NDB_SEQ_DB_NAME ); Loop->AddLoopTag ( CIFTAG_NDB_SEQ_DB_ACCESSION_CODE ); Loop->AddLoopTag ( CIFTAG_DB_MON_ID ); Loop->AddLoopTag ( CIFTAG_NDB_SEQ_DB_SEQ_NUM ); Loop->AddLoopTag ( CIFTAG_DETAILS ); } Loop->AddString ( chain->GetEntryID(),true ); Loop->AddString ( resName ,true ); Loop->AddString ( chain->chainID ,true ); Loop->AddInteger ( seqNum ); Loop->AddString ( insCode ,true ); Loop->AddString ( database ,true ); Loop->AddString ( dbAccession ,true ); Loop->AddString ( dbRes ,true ); Loop->AddInteger ( dbSeq ); Loop->AddString ( conflict ,true ); } ERROR_CODE SeqAdv::GetCIF ( mmcif::PData CIF, int & n ) { // GetCIF(..) must be always run without reference to Chain, // see CModel::GetCIF(..). mmcif::PLoop Loop; pstr F; int RC; Loop = CIF->GetLoop ( CIFCAT_STRUCT_REF_SEQ_DIF ); if (!Loop) { n = -1; return Error_EmptyCIF; } if (n>=Loop->GetLoopLength()) { n = -1; return Error_EmptyCIF; } // Determine the ChainID first and store it locally. It will // be used by CModel for generating chains and placing the // primary structure data BEFORE reading the coordinate section. F = Loop->GetString ( CIFTAG_NDB_PDB_CHAIN_ID,n,RC ); if ((!RC) && F) { strcpy_n0 ( chainID,F,sizeof(ChainID)-1 ); Loop->DeleteField ( CIFTAG_NDB_PDB_CHAIN_ID,n ); } else strcpy ( chainID,"" ); CIFGetString ( resName,Loop,CIFTAG_MON_ID,n,sizeof(ResName), pstr("UNK") ); CIFGetIntegerD ( seqNum,Loop,CIFTAG_SEQ_NUM ); CIFGetString ( insCode,Loop,CIFTAG_NDB_PDB_INS_CODE, n,sizeof(InsCode),pstr(" ") ); CIFGetString ( database,Loop,CIFTAG_NDB_SEQ_DB_NAME,n, sizeof(DBName),pstr(" ") ); CIFGetString ( dbAccession,Loop,CIFTAG_NDB_SEQ_DB_ACCESSION_CODE, n,sizeof(DBAcCode),pstr(" ") ); CIFGetString ( dbRes,Loop,CIFTAG_DB_MON_ID,n,sizeof(ResName), pstr(" ") ); CIFGetIntegerD ( dbSeq,Loop,CIFTAG_NDB_SEQ_DB_SEQ_NUM ); // if (CIFGetInteger1(dbSeq,Loop,CIFTAG_NDB_SEQ_DB_SEQ_NUM,n)) // dbSeq = MinInt4; F = Loop->GetString ( CIFTAG_DETAILS,n,RC ); if ((!RC) && F) { CreateCopy ( conflict,F ); Loop->DeleteField ( CIFTAG_DETAILS,n ); } else CreateCopy ( conflict,pstr(" ") ); n++; return Error_NoError; } void SeqAdv::Copy ( PContainerClass SeqAdv ) { ContainerClass::Copy ( SeqAdv ); seqNum = PSeqAdv(SeqAdv)->seqNum; dbSeq = PSeqAdv(SeqAdv)->dbSeq; strcpy ( resName ,PSeqAdv(SeqAdv)->resName ); strcpy ( insCode ,PSeqAdv(SeqAdv)->insCode ); strcpy ( database ,PSeqAdv(SeqAdv)->database ); strcpy ( dbAccession,PSeqAdv(SeqAdv)->dbAccession ); strcpy ( dbRes ,PSeqAdv(SeqAdv)->dbRes ); CreateCopy ( conflict,PSeqAdv(SeqAdv)->conflict ); } void SeqAdv::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &seqNum ); f.WriteInt ( &dbSeq ); f.WriteTerLine ( resName ,false ); f.WriteTerLine ( insCode ,false ); f.WriteTerLine ( database ,false ); f.WriteTerLine ( dbAccession,false ); f.WriteTerLine ( dbRes ,false ); f.CreateWrite ( conflict ); } void SeqAdv::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.ReadInt ( &seqNum ); f.ReadInt ( &dbSeq ); f.ReadTerLine ( resName ,false ); f.ReadTerLine ( insCode ,false ); f.ReadTerLine ( database ,false ); f.ReadTerLine ( dbAccession,false ); f.ReadTerLine ( dbRes ,false ); f.CreateRead ( conflict ); } MakeStreamFunctions(SeqAdv) // ================ SeqRes =================== SeqRes::SeqRes() : io::Stream() { InitSeqRes(); } SeqRes::SeqRes ( io::RPStream Object ) : io::Stream(Object) { InitSeqRes(); } SeqRes::~SeqRes() { FreeMemory(); } void SeqRes::SetChain ( PChain Chain_Owner ) { chain = Chain_Owner; if (chain) strcpy ( chainID,chain->chainID ); else strcpy ( chainID,"" ); } void SeqRes::InitSeqRes() { chain = NULL; numRes = -1; resName = NULL; serNum = 0; strcpy ( chainID,"" ); } void SeqRes::FreeMemory() { if (resName) delete[] resName; resName = NULL; numRes = -1; serNum = 0; } void SeqRes::PDBASCIIDump ( io::RFile f ) { // writes the ASCII PDB SEQRES lines into file f char S[100]; int i,k,sN; if (numRes<0) return; strcpy ( S,"SEQRES" ); PadSpaces ( S,80 ); if (chain->chainID[0]) S[11] = chain->chainID[0]; PutInteger ( &(S[13]),numRes,4 ); if (resName) { i = 0; sN = 1; while (ichainID[0]) { if (S[11]!=chain->chainID[0]) return Error_WrongChainID; } else if (S[11]!=' ') { chain->chainID[0] = S[11]; chain->chainID[1] = char(0); } else chain->chainID[0] = char(0); GetInteger ( sN,&(S[8]) ,3 ); GetInteger ( nR,&(S[13]),4 ); if (sN==0) { FreeMemory(); numRes = nR; } else { serNum++; if (sN!=serNum) return Error_SEQRES_serNum; if (sN==1) { FreeMemory(); resName = new ResName[nR]; for (i=0;i=nR) return Error_SEQRES_extraRes; k = 19; while ((iAddLoop ( CIFCAT_NDB_POLY_SEQ_SCHEME,Loop ); if (RC!=mmcif::CIFRC_Ok) { // the category was (re)created, provide tags Loop->AddLoopTag ( CIFTAG_ID ); Loop->AddLoopTag ( CIFTAG_MON_ID ); } if (resName) for (i=0;iAddString ( chain->chainID,true ); Loop->AddString ( resName[i] ,true ); } else for (i=0;iAddString ( chain->GetEntryID(),true ); Loop->AddString ( pstr("UNK") ,true ); } } ERROR_CODE SeqRes::GetCIF ( mmcif::PData CIF ) { // Tries to get sequence from the CIF structure. A sequence // for first met chain is extracted and then removed from // the CIF structure, so that sequential calls will extract // all sequencies. Chain ID is stored locally in chainID; // reference to parent chain is neither used nor checked. // Returns 0 if sequence was extracted and 1 otherwise. mmcif::PLoop Loop; ResName * rN; ChainID chID; pstr F; cpstr CHAIN_ID; int RC,i,l; CIF_MODE CIFMode; bool isMon; FreeMemory(); CIFMode = CIF_NDB; Loop = CIF->GetLoop ( CIFName(CAT_POLY_SEQ_SCHEME,CIFMode) ); if (!Loop) { CIFMode = CIF_PDBX; Loop = CIF->GetLoop ( CIFName(CAT_POLY_SEQ_SCHEME,CIFMode) ); if (!Loop) return Error_NoLoop; } l = Loop->GetLoopLength(); if (l<=0) return Error_NoLoop; rN = new ResName[l]; chainID[0] = char(1); numRes = 0; isMon = false; CHAIN_ID = CIFName(TAG_SEQ_CHAIN_ID,CIFMode); for (i=0;iGetString ( CHAIN_ID,i,RC ); if (!RC) { if (F) strcpy ( chID,F ); else chID[0] = char(0); if (chainID[0]==char(1)) strcpy ( chainID,chID ); if (!strcmp(chainID,chID)) { CIFGetString ( rN[numRes],Loop,CIFTAG_MON_ID,i, sizeof(ResName),pstr("UNK") ); Loop->DeleteField ( CHAIN_ID,i ); if (strcmp(rN[numRes],"UNK")) isMon = true; numRes++; } } } if (numRes==0) { numRes = -1; delete[] rN; return Error_EmptyCIFLoop; } if (isMon) { resName = new ResName[numRes]; for (i=0;inumRes; serNum = SeqRes->serNum; if (SeqRes->resName) { resName = new ResName[numRes]; for (i=0;iresName[i] ); } } void SeqRes::write ( io::RFile f ) { int i; byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &numRes ); f.WriteInt ( &serNum ); if (resName) i = 1; else i = 0; f.WriteInt ( &i ); if (resName) for (i=0;iGetEntryID(),4 ); strcpy_n ( &(S[12]),resName ,3 ); if (chain->chainID[0]) S[16] = chain->chainID[0]; PutIntIns ( &(S[18]),seqNum,4,insCode ); strcpy_n ( &(S[24]),stdRes ,3 ); strcpy_n ( &(S[29]),comment,IMin(strlen(comment),41) ); } ERROR_CODE ModRes::ConvertPDBASCII ( cpstr S ) { IDCode idCode; if (chain->chainID[0]) { if (S[16]!=chain->chainID[0]) return Error_WrongChainID; } else if (S[16]!=' ') { chain->chainID[0] = S[16]; chain->chainID[1] = char(0); } else chain->chainID[0] = char(0); strcpy ( idCode,chain->GetEntryID() ); if (idCode[0]) { if (strncmp(&(S[7]),idCode,4) && (!ignoreNonCoorPDBErrors)) return Error_WrongEntryID; } else { GetString ( idCode,&(S[7]),4 ); chain->SetEntryID ( idCode ); } GetString ( resName ,&(S[12]),3 ); GetIntIns ( seqNum,insCode,&(S[18]),4 ); GetString ( stdRes ,&(S[24]),3 ); CreateCopy ( comment ,&(S[29]) ); CutSpaces ( comment,SCUTKEY_END ); return Error_NoError; } void ModRes::MakeCIF ( mmcif::PData CIF, int N ) { UNUSED_ARGUMENT(CIF); UNUSED_ARGUMENT(N); /* -- apparently wrong use of _struct_conn, to be revised mmcif::PLoop Loop; int RC; RC = CIF->AddLoop ( CIFCAT_STRUCT_CONN,Loop ); if (RC!=mmcif::CIFRC_Ok) { // the category was (re)created, provide tags Loop->AddLoopTag ( CIFTAG_CONN_TYPE_ID ); Loop->AddLoopTag ( CIFTAG_NDB_PDB_ID ); Loop->AddLoopTag ( CIFTAG_PTNR1_LABEL_COMP_ID ); Loop->AddLoopTag ( CIFTAG_PTNR1_LABEL_ASYM_ID ); Loop->AddLoopTag ( CIFTAG_PTNR1_LABEL_SEQ_ID ); Loop->AddLoopTag ( CIFTAG_NDB_PTNR1_LABEL_INS_CODE ); Loop->AddLoopTag ( CIFTAG_NDB_PTNR1_STANDARD_COMP_ID ); Loop->AddLoopTag ( CIFTAG_DETAILS ); } Loop->AddString ( pstr("MODRES") ); Loop->AddString ( chain->GetEntryID(),true ); Loop->AddString ( resName ,true ); Loop->AddString ( chain->chainID ,true ); Loop->AddInteger ( seqNum ); Loop->AddString ( insCode ,true ); Loop->AddString ( stdRes ,true ); Loop->AddString ( comment ,true ); */ } ERROR_CODE ModRes::GetCIF ( mmcif::PData CIF, int & n ) { UNUSED_ARGUMENT(CIF); // GetCIF(..) must be always run without reference to Chain, // see CModel::GetCIF(..). /* -- apparently wrong use of _struct_conn, to be revised mmcif::PLoop Loop; pstr F; int l,RC; Loop = CIF->GetLoop ( CIFCAT_STRUCT_CONN ); if (!Loop) { n = -1; return; } l = Loop->GetLoopLength(); while (nGetString ( CIFTAG_CONN_TYPE_ID,n,RC ); if ((!RC) && F) { if (!strcmp(F,"MODRES")) break; } n++; } if (n>=l) { n = -1; return; } Loop->DeleteField ( CIFTAG_CONN_TYPE_ID,n ); // Determine the ChainID first and store it locally. It will // be used by CModel for generating chains and placing the // primary structure data BEFORE reading the coordinate section. F = Loop->GetString ( CIFTAG_PTNR1_LABEL_ASYM_ID,n,RC ); if ((!RC) && F) { strcpy_n0 ( chainID,F,sizeof(ChainID)-1 ); Loop->DeleteField ( CIFTAG_PTNR1_LABEL_ASYM_ID,n ); } else strcpy ( chainID,"" ); CIFGetString ( resName,Loop,CIFTAG_PTNR1_LABEL_COMP_ID,n, sizeof(ResName),pstr("UNK") ); if (CIFGetInteger(seqNum,Loop,CIFTAG_PTNR1_LABEL_SEQ_ID,n)) return; CIFGetString ( insCode,Loop,CIFTAG_NDB_PTNR1_LABEL_INS_CODE, n,sizeof(InsCode),pstr(" ") ); CIFGetString ( stdRes,Loop,CIFTAG_NDB_PTNR1_STANDARD_COMP_ID,n, sizeof(ResName),pstr("UNK") ); F = Loop->GetString ( CIFTAG_DETAILS,n,RC ); if ((!RC) && F) { CreateCopy ( comment,F ); Loop->DeleteField ( CIFTAG_DETAILS,n ); } else CreateCopy ( comment,pstr(" ") ); n++; */ n = -1; return Error_EmptyCIF; } void ModRes::Copy ( PContainerClass ModRes ) { seqNum = PModRes(ModRes)->seqNum; strcpy ( resName,PModRes(ModRes)->resName ); strcpy ( insCode,PModRes(ModRes)->insCode ); strcpy ( stdRes ,PModRes(ModRes)->stdRes ); CreateCopy ( comment,PModRes(ModRes)->comment ); } void ModRes::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &seqNum ); f.WriteTerLine ( resName,false ); f.WriteTerLine ( insCode,false ); f.WriteTerLine ( stdRes ,false ); f.CreateWrite ( comment ); } void ModRes::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.ReadInt ( &seqNum ); f.ReadTerLine ( resName,false ); f.ReadTerLine ( insCode,false ); f.ReadTerLine ( stdRes ,false ); f.CreateRead ( comment ); } MakeStreamFunctions(ModRes) // ================ HetRec ====================== HetRec::HetRec() : ContainerChain() { InitHetRec(); } HetRec::HetRec ( PChain Chain_Owner ) : ContainerChain(Chain_Owner) { InitHetRec(); } HetRec::HetRec ( PChain Chain_Owner, cpstr S ) : ContainerChain(Chain_Owner) { InitHetRec(); ConvertPDBASCII ( S ); } HetRec::HetRec ( io::RPStream Object ) : ContainerChain(Object) { InitHetRec(); } HetRec::~HetRec() { if (comment) delete[] comment; } void HetRec::InitHetRec() { strcpy ( hetID ,"---" ); strcpy ( insCode,"-" ); seqNum = 0; numHetAtoms = 0; comment = NULL; CreateCopy ( comment,pstr(" ") ); } void HetRec::PDBASCIIDump ( pstr S, int N ) { UNUSED_ARGUMENT(N); // makes the ASCII PDB MODRES line number N // from the class' data strcpy ( S,"HET" ); PadSpaces ( S,80 ); strcpy_n ( &(S[7]) ,hetID,3 ); if (chain->chainID[0]) S[12] = chain->chainID[0]; PutIntIns ( &(S[13]),seqNum,4,insCode ); PutInteger ( &(S[20]),numHetAtoms,5 ); strcpy_n ( &(S[30]),comment,IMin(strlen(comment),40) ); } ERROR_CODE HetRec::ConvertPDBASCII ( cpstr S ) { if (chain->chainID[0]) { if (S[12]!=chain->chainID[0]) return Error_WrongChainID; } else if (S[12]!=' ') { chain->chainID[0] = S[12]; chain->chainID[1] = char(0); } else chain->chainID[0] = char(0); GetString ( hetID ,&(S[7]) ,3 ); GetIntIns ( seqNum,insCode,&(S[13]),4 ); GetInteger ( numHetAtoms ,&(S[20]),5 ); CreateCopy ( comment ,&(S[30]) ); CutSpaces ( comment,SCUTKEY_END ); return Error_NoError; } void HetRec::MakeCIF ( mmcif::PData CIF, int N ) { UNUSED_ARGUMENT(N); mmcif::PLoop Loop; int RC; RC = CIF->AddLoop ( CIFCAT_NDB_NONSTANDARD_LIST,Loop ); if (RC!=mmcif::CIFRC_Ok) { // the category was (re)created, provide tags Loop->AddLoopTag ( CIFTAG_ID ); Loop->AddLoopTag ( CIFTAG_AUTH_ASYM_ID ); Loop->AddLoopTag ( CIFTAG_AUTH_SEQ_ID ); Loop->AddLoopTag ( CIFTAG_INS_CODE ); Loop->AddLoopTag ( CIFTAG_NUMBER_ATOMS_NH ); Loop->AddLoopTag ( CIFTAG_DETAILS ); } Loop->AddString ( hetID ,true ); Loop->AddString ( chain->chainID,true ); Loop->AddInteger ( seqNum ); Loop->AddString ( insCode ,true ); Loop->AddInteger ( numHetAtoms ); Loop->AddString ( comment ,true ); } ERROR_CODE HetRec::GetCIF ( mmcif::PData CIF, int & n ) { // GetCIF(..) must be always run without reference to Chain, // see CModel::GetCIF(..). mmcif::PLoop Loop; pstr F; int RC; ERROR_CODE rc; Loop = CIF->GetLoop ( CIFCAT_NDB_NONSTANDARD_LIST ); if (!Loop) { n = -1; return Error_EmptyCIF; } if (n>=Loop->GetLoopLength()) { n = -1; return Error_EmptyCIF; } // Determine the ChainID first and store it locally. It will // be used by CModel for generating chains and placing the // primary structure data BEFORE reading the coordinate section. F = Loop->GetString ( CIFTAG_AUTH_ASYM_ID,n,RC ); if ((!RC) && F) { strcpy_n0 ( chainID,F,sizeof(ChainID)-1 ); Loop->DeleteField ( CIFTAG_AUTH_ASYM_ID,n ); } else strcpy ( chainID,"" ); CIFGetString ( hetID,Loop,CIFTAG_ID,n,sizeof(ResName), pstr("UNK") ); rc = CIFGetInteger ( seqNum,Loop,CIFTAG_AUTH_SEQ_ID,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( insCode,Loop,CIFTAG_INS_CODE,n,sizeof(InsCode), pstr(" ") ); rc = CIFGetInteger ( numHetAtoms,Loop,CIFTAG_NUMBER_ATOMS_NH,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; F = Loop->GetString ( CIFTAG_DETAILS,n,RC ); if ((!RC) && F) { CreateCopy ( comment,F ); Loop->DeleteField ( CIFTAG_DETAILS,n ); } else CreateCopy ( comment,pstr(" ") ); n++; return Error_NoError; } void HetRec::Copy ( PContainerClass Het ) { seqNum = PHetRec(Het)->seqNum; numHetAtoms = PHetRec(Het)->numHetAtoms; strcpy ( hetID ,PHetRec(Het)->hetID ); strcpy ( insCode,PHetRec(Het)->insCode ); CreateCopy ( comment,PHetRec(Het)->comment ); } void HetRec::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &seqNum ); f.WriteInt ( &numHetAtoms ); f.WriteTerLine ( hetID ,false ); f.WriteTerLine ( insCode,false ); f.CreateWrite ( comment ); } void HetRec::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.ReadInt ( &seqNum ); f.ReadInt ( &numHetAtoms ); f.ReadTerLine ( hetID ,false ); f.ReadTerLine ( insCode,false ); f.CreateRead ( comment ); } MakeStreamFunctions(HetRec) // ===================== Chain ======================= Chain::Chain() : UDData() { InitChain(); SetChain ( pstr("") ); } Chain::Chain ( PProModel Model, const ChainID chID ) : UDData() { InitChain(); SetChain ( chID ); if (Model) Model->AddChain ( this ); } Chain::Chain ( io::RPStream Object ) : UDData(Object) { InitChain(); SetChain ( pstr("") ); } void Chain::InitChain() { nResidues = 0; resLen = 0; residue = NULL; model = NULL; chainID[0] = char(0); prevChainID[0] = char(0); nWeights = 0; Weight = 0.0; Exclude = true; } void Chain::SetChain ( const ChainID chID ) { strcpy ( chainID,chID ); if (chID[0]==' ') chainID[0] = char(0); DBRef .SetChain ( this ); seqAdv.SetChain ( this ); seqRes.SetChain ( this ); modRes.SetChain ( this ); Het .SetChain ( this ); } void Chain::SetChainID ( const ChainID chID ) { strcpy ( chainID,chID ); if (chID[0]==' ') chainID[0] = char(0); } Chain::~Chain() { FreeMemory(); if (model) model->_ExcludeChain ( chainID ); } void Chain::FreeMemory() { DeleteAllResidues(); if (residue) delete[] residue; resLen = 0; nResidues = 0; residue = NULL; FreeAnnotations(); } void Chain::FreeAnnotations() { DBRef .FreeContainer(); seqAdv.FreeContainer(); seqRes.FreeMemory (); modRes.FreeContainer(); Het .FreeContainer(); } void Chain::SetModel ( PProModel Model ) { model = Model; } PManager Chain::GetCoordHierarchy() { if (model) return model->GetCoordHierarchy(); return NULL; } void Chain::CheckInAtoms() { int i; if (GetCoordHierarchy()) for (i=0;iCheckInAtoms(); } ERROR_CODE Chain::ConvertDBREF ( cpstr PDBString ) { PContainerChain ContainerChain; ERROR_CODE RC; ContainerChain = new DBReference(this); RC = ContainerChain->ConvertPDBASCII ( PDBString ); if (RC) { delete ContainerChain; return RC; } DBRef.AddData ( ContainerChain ); return Error_NoError; } ERROR_CODE Chain::ConvertSEQADV ( cpstr PDBString ) { PContainerChain ContainerChain; ERROR_CODE RC; ContainerChain = new SeqAdv(this); RC = ContainerChain->ConvertPDBASCII ( PDBString ); if (RC) { delete ContainerChain; return RC; } seqAdv.AddData ( ContainerChain ); return Error_NoError; } ERROR_CODE Chain::ConvertSEQRES ( cpstr PDBString ) { return seqRes.ConvertPDBASCII ( PDBString ); } ERROR_CODE Chain::ConvertMODRES ( cpstr PDBString ) { PContainerChain ContainerChain; ERROR_CODE RC; ContainerChain = new ModRes(this); RC = ContainerChain->ConvertPDBASCII ( PDBString ); if (RC) { delete ContainerChain; return RC; } modRes.AddData ( ContainerChain ); return Error_NoError; } ERROR_CODE Chain::ConvertHET ( cpstr PDBString ) { PContainerChain ContainerChain; ERROR_CODE RC; ContainerChain = new HetRec(this); RC = ContainerChain->ConvertPDBASCII ( PDBString ); if (RC) { delete ContainerChain; return RC; } Het.AddData ( ContainerChain ); return Error_NoError; } void Chain::PDBASCIIDump ( io::RFile f ) { // this function was for test purposes and is not used // for normal function of MMDB DBRef .PDBASCIIDump ( f ); seqAdv.PDBASCIIDump ( f ); seqRes.PDBASCIIDump ( f ); modRes.PDBASCIIDump ( f ); Het .PDBASCIIDump ( f ); } void Chain::PDBASCIIAtomDump ( io::RFile f ) { int i; for (i=0;iPDBASCIIAtomDump ( f ); } void Chain::MakeAtomCIF ( mmcif::PData CIF ) { int i; for (i=0;iMakeAtomCIF ( CIF ); } int Chain::GetNumberOfResidues() { return nResidues; } PResidue Chain::GetResidue ( int resNo ) { if ((0<=resNo) && (resNoseqNum) && (!strcmp(insCode,residue[i]->insCode))) { if (!strcmp(resName,residue[i]->name)) return residue[i]; // it is there; just return the pointer else if (!Enforce) return NULL; // duplicate seqNum and insCode! } } } else { for (i=0;iseqNum) && (!residue[i]->insCode[0])) { if (!strcmp(resName,residue[i]->name)) return residue[i]; // it is there; just return the pointer else if (!Enforce) return NULL; // duplicate seqNum and insCode! } } } // expand the residue array, if necessary if (nResidues>=resLen) ExpandResidueArray ( 100 ); // create new residue residue[nResidues] = newResidue(); residue[nResidues]->SetChain ( this ); residue[nResidues]->SetResID ( resName,seqNum,insCode ); residue[nResidues]->index = nResidues; nResidues++; return residue[nResidues-1]; } void Chain::ExpandResidueArray ( int inc ) { PPResidue Residue1; int i; resLen += inc; Residue1 = new PResidue[resLen]; for (i=0;iseqNum) && (!strcmp(insCode,residue[i]->insCode))) return residue[i]; } } else { for (i=0;iseqNum) && (!residue[i]->insCode[0])) return residue[i]; } } return NULL; } int Chain::GetResidueNo ( int seqNum, const InsCode insCode ) { // GetResidueNo(..) returns the residue number in the chain's // residues table. Residues are numbered as 0..nres-1 as they appear // in the coordinate file. // If residue is not found, the function returns -1. int i; bool isInsCode; if (insCode) isInsCode = insCode[0]!=char(0); else isInsCode = false; if (isInsCode) { for (i=0;iseqNum) && (!strcmp(insCode,residue[i]->insCode))) return i; } } else { for (i=0;iseqNum) && (!residue[i]->insCode[0])) return i; } } return -1; } void Chain::GetResidueTable ( PPResidue & resTable, int & NumberOfResidues ) { resTable = residue; NumberOfResidues = nResidues; } int Chain::_ExcludeResidue ( const ResName resName, int seqNum, const InsCode insCode ) { // ExcludeResidue(..) excludes (but does not dispose!) a residue // from the chain. Returns 1 if the chain gets empty and 0 otherwise. int i,k; if (!Exclude) return 0; // find the residue k = -1; for (i=0;(iseqNum) && (!strcmp(insCode,residue[i]->insCode)) && (!strcmp(resName,residue[i]->name))) k = i; if (k>=0) { for (i=k+1;iindex = i-1; } nResidues--; residue[nResidues] = NULL; } if (nResidues<=0) return 1; else return 0; } // ------------------ Deleting residues -------------------------- int Chain::DeleteResidue ( int resNo ) { if ((0<=resNo) && (resNoseqNum) && (!strcmp(insCode,residue[i]->insCode))) { Exclude = false; delete residue[i]; residue[i] = NULL; Exclude = true; return 1; } } } else { for (i=0;iseqNum) && (!residue[i]->insCode[0])) { Exclude = false; delete residue[i]; residue[i] = NULL; Exclude = true; return 1; } } } return 0; } int Chain::DeleteAllResidues() { int i,k; Exclude = false; k = 0; for (i=0;iisSolvent()) { delete residue[i]; residue[i] = NULL; k++; } } Exclude = true; return k; } void Chain::TrimResidueTable() { int i,j; Exclude = false; j = 0; for (i=0;inAtoms>0) { if (jindex = j; residue[i] = NULL; } j++; } else { delete residue[i]; residue[i] = NULL; } } nResidues = j; Exclude = true; } int Chain::AddResidue ( PResidue res ) { // modify both CModel::Copy methods simultaneously! // // Copy(PCModel,PPAtom,int&) copies atoms into array 'atom' // starting from position atom_index. 'atom' should be able to // accept all new atoms - no checks on the length of 'atom' // is being made. This function should not be used in applications. return InsResidue ( res,nResidues ); } /* PCmmdbRoot mmdbRoot; PChain chain1; int i; for (i=0;i=resLen) ExpandResidueArray ( 100 ); if (res->GetCoordHierarchy()) { residue[nResidues] = newResidue(); residue[nResidues]->SetChain ( this ); residue[nResidues]->SetResID ( res->name,res->seqNum,res->insCode ); if (mmdbRoot) { // get space for new atoms mmdbRoot->AddAtomArray ( res->GetNumberOfAtoms(true) ); residue[nResidues]->Copy ( res,mmdbRoot->Atom,mmdbRoot->nAtoms ); } else { for (i=0;inAtoms;i++) residue[nResidues]->AddAtom ( res->atom[i] ); } } else { residue[nResidues] = res; chain1 = res->GetChain(); if (chain1) for (i=0;inResidues;i++) if (chain1->residue[i]==res) { chain1->residue[i] = NULL; break; } residue[nResidues]->SetChain ( this ); if (mmdbRoot) residue[nResidues]->CheckInAtoms(); } nResidues++; } return nResidues; } */ int Chain::InsResidue ( PResidue res, int seqNum, const InsCode insCode ) { return InsResidue ( res,GetResidueNo(seqNum,insCode) ); } int Chain::InsResidue ( PResidue res, int pos ) { // Inserts residue res onto position pos of the chain, // pos=0..nResidues-1 . Residues pos..nResidues-1 are // shifted up the chain. // The function places new atoms on the top of atom // index. It is advisable to call // CmmdbRoot::PDBCleanup ( PDBCLEAN_INDEX ) after all // insertions are done. PRoot mmdbRoot; PChain chain1; int i,pp; pp = IMax ( 0,IMin(nResidues,pos) ); for (i=0;i=resLen) ExpandResidueArray ( 100 ); // shift residues to the end of the chain as necessary for (i=nResidues;i>pp;i--) residue[i] = residue[i-1]; // insert the new residue if (res->GetCoordHierarchy()) { residue[pp] = newResidue(); residue[pp]->SetChain ( this ); residue[pp]->SetResID ( res->name,res->seqNum,res->insCode ); if (mmdbRoot) { // get space for new atoms mmdbRoot->AddAtomArray ( res->GetNumberOfAtoms(true) ); residue[pp]->_copy ( res,mmdbRoot->atom,mmdbRoot->nAtoms ); } else { for (i=0;inAtoms;i++) residue[pp]->AddAtom ( res->atom[i] ); } } else { residue[pp] = res; chain1 = res->GetChain(); if (chain1) for (i=0;inResidues;i++) if (chain1->residue[i]==res) { chain1->residue[i] = NULL; break; } residue[pp]->SetChain ( this ); if (mmdbRoot) residue[pp]->CheckInAtoms(); } nResidues++; } return nResidues; } // -------------------- Extracting atoms ----------------------- int Chain::GetNumberOfAtoms ( bool countTers ) { int i,na; na = 0; for (i=0;iGetNumberOfAtoms ( countTers ); return na; } int Chain::GetNumberOfAtoms ( int seqNo, const InsCode insCode ) { PResidue res; res = GetResidue ( seqNo,insCode ); if (res) return res->nAtoms; return 0; } int Chain::GetNumberOfAtoms ( int resNo ) { if ((0<=resNo) && (resNonAtoms; } return 0; } PAtom Chain::GetAtom ( int seqNo, const InsCode insCode, const AtomName aname, const Element elmnt, const AltLoc aloc ) { PResidue res; res = GetResidue ( seqNo,insCode ); if (res) return res->GetAtom ( aname,elmnt,aloc ); return NULL; } PAtom Chain::GetAtom ( int seqNo, const InsCode insCode, int atomNo ) { PResidue res; res = GetResidue ( seqNo,insCode ); if (res) { if ((0<=atomNo) && (atomNonAtoms)) return res->atom[atomNo]; } return NULL; } PAtom Chain::GetAtom ( int resNo, const AtomName aname, const Element elmnt, const AltLoc aloc ) { if ((0<=resNo) && (resNoGetAtom ( aname,elmnt,aloc ); } return NULL; } PAtom Chain::GetAtom ( int resNo, int atomNo ) { PResidue res; if ((0<=resNo) && (resNonAtoms)) return res->atom[atomNo]; } } return NULL; } void Chain::GetAtomTable ( int seqNo, const InsCode insCode, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; atomTable = NULL; NumberOfAtoms = 0; res = GetResidue ( seqNo,insCode ); if (res) { atomTable = res->atom; NumberOfAtoms = res->nAtoms; } } void Chain::GetAtomTable ( int resNo, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; atomTable = NULL; NumberOfAtoms = 0; if ((0<=resNo) && (resNoatom; NumberOfAtoms = res->nAtoms; } } } void Chain::GetAtomTable1 ( int seqNo, const InsCode insCode, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; res = GetResidue ( seqNo,insCode ); if (res) res->GetAtomTable1 ( atomTable,NumberOfAtoms ); else { if (atomTable) delete[] atomTable; atomTable = NULL; NumberOfAtoms = 0; } } void Chain::GetAtomTable1 ( int resNo, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; if ((0<=resNo) && (resNoGetAtomTable1 ( atomTable,NumberOfAtoms ); else { if (atomTable) delete[] atomTable; atomTable = NULL; NumberOfAtoms = 0; } } int Chain::DeleteAtom ( int seqNo, const InsCode insCode, const AtomName aname, const Element elmnt, const AltLoc aloc ) { PResidue res; res = GetResidue ( seqNo,insCode ); if (res) return res->DeleteAtom ( aname,elmnt,aloc ); return 0; } int Chain::DeleteAtom ( int seqNo, const InsCode insCode, int atomNo ) { PResidue res; res = GetResidue ( seqNo,insCode ); if (res) return res->DeleteAtom ( atomNo ); return 0; } int Chain::DeleteAtom ( int resNo, const AtomName aname, const Element elmnt, const AltLoc aloc ) { if ((0<=resNo) && (resNoDeleteAtom ( aname,elmnt,aloc ); } return 0; } int Chain::DeleteAtom ( int resNo, int atomNo ) { if ((0<=resNo) && (resNoDeleteAtom ( atomNo ); } return 0; } int Chain::DeleteAllAtoms ( int seqNo, const InsCode insCode ) { PResidue res; res = GetResidue ( seqNo,insCode ); if (res) return res->DeleteAllAtoms(); return 0; } int Chain::DeleteAllAtoms ( int resNo ) { if ((0<=resNo) && (resNoDeleteAllAtoms(); } return 0; } int Chain::DeleteAllAtoms() { int i,k; k = 0; for (i=0;iDeleteAllAtoms(); return k; } int Chain::DeleteAltLocs() { // This function leaves only alternative location with maximal // occupancy, if those are equal or unspecified, the one with // "least" alternative location indicator. // The function returns the number of deleted. All tables remain // untrimmed, so that explicit trimming or calling FinishStructEdit() // is required. int i,n; n = 0; for (i=0;iDeleteAltLocs(); return n; } int Chain::AddAtom ( int seqNo, const InsCode insCode, PAtom atom ) { PResidue res; res = GetResidue ( seqNo,insCode ); if (res) return res->AddAtom ( atom ); return 0; } int Chain::AddAtom ( int resNo, PAtom atom ) { if ((0<=resNo) && (resNoAddAtom ( atom ); } return 0; } void Chain::Copy ( PChain chain ) { // modify both Chain::_copy and Chain::Copy methods simultaneously! int i; FreeMemory(); if (chain) { CopyAnnotations ( chain ); nResidues = chain->nResidues; resLen = nResidues; if (nResidues>0) { residue = new PResidue[nResidues]; for (i=0;iSetChain ( this ); residue[i]->Copy ( chain->residue[i] ); } } } } void Chain::CopyAnnotations ( PChain chain ) { if (chain) { strcpy ( chainID ,chain->chainID ); strcpy ( prevChainID,chain->prevChainID ); DBRef .Copy ( &(chain->DBRef) ); seqAdv.Copy ( &(chain->seqAdv) ); // SEQADV records seqRes.Copy ( &(chain->seqRes) ); // SEQRES data modRes.Copy ( &(chain->modRes) ); // MODRES records Het .Copy ( &(chain->Het) ); // HET records } } void Chain::_copy ( PChain chain ) { // modify both Chain::_copy and Chain::Copy methods simultaneously! int i; FreeMemory(); strcpy ( chainID ,chain->chainID ); strcpy ( prevChainID,chain->prevChainID ); DBRef .Copy ( &(chain->DBRef) ); seqAdv.Copy ( &(chain->seqAdv) ); // SEQADV records seqRes.Copy ( &(chain->seqRes) ); // SEQRES data modRes.Copy ( &(chain->modRes) ); // MODRES records Het .Copy ( &(chain->Het) ); // HET records nResidues = chain->nResidues; resLen = nResidues; if (nResidues>0) { residue = new PResidue[nResidues]; for (i=0;iSetChain ( this ); residue[i]->_copy ( chain->residue[i] ); } } } void Chain::_copy ( PChain chain, PPAtom atom, int & atom_index ) { // modify both Chain::_copy and Chain::Copy methods simultaneously! int i; FreeMemory(); strcpy ( chainID ,chain->chainID ); strcpy ( prevChainID,chain->prevChainID ); DBRef .Copy ( &(chain->DBRef) ); seqAdv.Copy ( &(chain->seqAdv) ); // SEQADV records seqRes.Copy ( &(chain->seqRes) ); // SEQRES data modRes.Copy ( &(chain->modRes) ); // MODRES records Het .Copy ( &(chain->Het) ); // HET records nResidues = chain->nResidues; resLen = nResidues; if (nResidues>0) { residue = new PResidue[nResidues]; for (i=0;iresidue[i]) { residue[i] = newResidue(); residue[i]->SetChain ( this ); residue[i]->_copy ( chain->residue[i],atom,atom_index ); } else residue[i] = NULL; } } /* void Chain::Duplicate ( PChain Chain ) { int i; FreeMemory(); strcpy ( chainID ,chain->chainID ); strcpy ( prevChainID,chain->prevChainID ); DBReference.Copy ( &(chain->DBReference) ); SeqAdv .Copy ( &(chain->SeqAdv) ); // SEQADV records SeqRes .Copy ( &(chain->SeqRes) ); // SEQRES data ModRes .Copy ( &(chain->ModRes) ); // MODRES records Het .Copy ( &(chain->Het) ); // HET records nResidues = chain->nResidues; resLen = nResidues; if (nResidues>0) { Residue = new PResidue[nResidues]; for (i=0;iSetChain ( this ); residue[i]->Duplicate ( chain->residue[i] ); } } } */ cpstr Chain::GetEntryID() { if (model) return model->GetEntryID(); else return pstr(""); } void Chain::SetEntryID ( const IDCode idCode ) { if (model) model->SetEntryID ( idCode ); } int Chain::GetModelNum() { if (model) return model->GetSerNum(); return 0; } cpstr Chain::GetChainID ( pstr ChID ) { ChID[0] = char(0); if (model) sprintf ( ChID,"/%i/",model->GetSerNum() ); else strcpy ( ChID,"/-/" ); strcat ( ChID,chainID ); return ChID; } void Chain::GetAtomStatistics ( RAtomStat AS ) { AS.Init(); CalAtomStatistics ( AS ); AS.Finish(); } void Chain::CalAtomStatistics ( RAtomStat AS ) { int i; for (i=0;iCalAtomStatistics ( AS ); } void Chain::ApplyTransform ( mat44 & TMatrix ) { // transforms all coordinates by multiplying with matrix TMatrix int i; for (i=0;iApplyTransform ( TMatrix ); } bool Chain::isSolventChain() { // returns true if chain contains only solvent molecules bool B,P; int i; B = true; P = false; for (i=0;(iisSolvent(); } return (B && P); } bool Chain::isInSelection ( int selHnd ) { PRoot mmdbRoot = (PRoot)GetCoordHierarchy(); PMask mask; if (mmdbRoot) { mask = mmdbRoot->GetSelMask ( selHnd ); if (mask) return CheckMask ( mask ); } return false; } bool Chain::isAminoacidChain() { // returns true if chain contains at least one aminoacid residue bool B,P; int i; B = false; P = false; for (i=0;(iisAminoacid(); } return (B && P); } bool Chain::isNucleotideChain() { // returns true if chain contains at least one nucleotide residue bool B,P; int i; B = false; P = false; for (i=0;(iisNucleotide(); } return (B && P); } int Chain::CheckID ( const ChainID chID ) { if (chID) { if (!strcmp(chID,chainID)) return 1; } return 0; } int Chain::CheckIDS ( cpstr CID ) { ChainID chn; InsCode inscode; ResName resname; AtomName atm; Element elm; AltLoc aloc; int mdl,sn,rc; rc = ParseAtomPath ( CID,mdl,chn,sn,inscode,resname, atm,elm,aloc,NULL ); if (rc>=0) { if (!strcmp(chn,chainID)) return 1; } return 0; } int Chain::GetNumberOfDBRefs() { return DBRef.Length(); } PDBReference Chain::GetDBRef ( int dbRefNo ) { return (PDBReference)DBRef.GetContainerClass ( dbRefNo ); } void Chain::MaskAtoms ( PMask mask ) { int i; for (i=0;iMaskAtoms ( mask ); } void Chain::MaskResidues ( PMask mask ) { int i; for (i=0;iSetMask ( mask ); } void Chain::UnmaskAtoms ( PMask mask ) { int i; for (i=0;iUnmaskAtoms ( mask ); } void Chain::UnmaskResidues ( PMask mask ) { int i; for (i=0;iRemoveMask ( mask ); } // ------- user-defined data handlers int Chain::PutUDData ( int UDDhandle, int iudd ) { if (UDDhandle & UDRF_CHAIN) return UDData::putUDData ( UDDhandle,iudd ); else return UDDATA_WrongUDRType; } int Chain::PutUDData ( int UDDhandle, realtype rudd ) { if (UDDhandle & UDRF_CHAIN) return UDData::putUDData ( UDDhandle,rudd ); else return UDDATA_WrongUDRType; } int Chain::PutUDData ( int UDDhandle, cpstr sudd ) { if (UDDhandle & UDRF_CHAIN) return UDData::putUDData ( UDDhandle,sudd ); else return UDDATA_WrongUDRType; } int Chain::GetUDData ( int UDDhandle, int & iudd ) { if (UDDhandle & UDRF_CHAIN) return UDData::getUDData ( UDDhandle,iudd ); else return UDDATA_WrongUDRType; } int Chain::GetUDData ( int UDDhandle, realtype & rudd ) { if (UDDhandle & UDRF_CHAIN) return UDData::getUDData ( UDDhandle,rudd ); else return UDDATA_WrongUDRType; } int Chain::GetUDData ( int UDDhandle, pstr sudd, int maxLen ) { if (UDDhandle & UDRF_CHAIN) return UDData::getUDData ( UDDhandle,sudd,maxLen ); else return UDDATA_WrongUDRType; } int Chain::GetUDData ( int UDDhandle, pstr & sudd ) { if (UDDhandle & UDRF_CHAIN) return UDData::getUDData ( UDDhandle,sudd ); else return UDDATA_WrongUDRType; } // ------------------------------------------------------------------- DefineClass(SortResidues) class QSortResidues : public QuickSort { public : QSortResidues() : QuickSort() {} int Compare ( int i, int j ); void Swap ( int i, int j ); void Sort ( PPResidue res, int nresidues ); }; int QSortResidues::Compare ( int i, int j ) { int diff; diff = ((PPResidue)data)[i]->seqNum - ((PPResidue)data)[j]->seqNum; if (diff==0) diff = strcmp( (PPResidue(data))[i]->insCode, (PPResidue(data))[j]->insCode ); if (diff>0) return 1; if (diff<0) return -1; return 0; } void QSortResidues::Swap ( int i, int j ) { PResidue res; res = ((PPResidue)data)[i]; ((PPResidue)data)[i] = ((PPResidue)data)[j]; ((PPResidue)data)[j] = res; } void QSortResidues::Sort ( PPResidue res, int nresidues ) { QuickSort::Sort ( &(res[0]),nresidues ); } void Chain::SortResidues() { QSortResidues SR; TrimResidueTable(); SR.Sort ( residue,nResidues ); } int Chain::GetNofModResidues() { return modRes.Length(); } PModRes Chain::GetModResidue ( int modResNo ) { return PModRes(modRes.GetContainerClass(modResNo)); } void Chain::write ( io::RFile f ) { int i; byte Version=2; bool compactBinary = false; PManager M = GetCoordHierarchy(); if (M) compactBinary = M->isCompactBinary(); f.WriteByte ( &Version ); f.WriteBool ( &compactBinary ); f.WriteTerLine ( chainID,false ); f.WriteInt ( &nResidues ); for (i=0;iwrite ( f ); if (!compactBinary) { UDData::write ( f ); f.WriteTerLine ( prevChainID,false ); DBRef .write ( f ); // Database reference seqAdv.write ( f ); // SEQADV records seqRes.write ( f ); // SEQRES data modRes.write ( f ); // MODRES records Het .write ( f ); // HET records } } void Chain::read ( io::RFile f ) { // The Atom array in CmmdbRoot must be already read // prior to calling this function! int i; byte Version; bool compactBinary; FreeMemory(); f.ReadByte ( &Version ); f.ReadBool ( &compactBinary ); f.ReadTerLine ( chainID,false ); SetChain ( chainID ); f.ReadInt ( &nResidues ); resLen = nResidues; if (nResidues>0) { residue = new PResidue[nResidues]; for (i=0;iSetChain ( this ); residue[i]->read ( f ); } } if (!compactBinary) { UDData::read ( f ); f.ReadTerLine ( prevChainID,false ); DBRef .read ( f ); // Database reference seqAdv.read ( f ); // SEQADV records seqRes.read ( f ); // SEQRES data modRes.read ( f ); // MODRES records Het .read ( f ); // HET records } } MakeFactoryFunctions(Chain) } // namespace mmdb // =================================================================== /* void TestChain() { // reads from 'in.chain', writes into // 'out.chain' and 'abin.chain' CFile f; char S[81]; PChain Chain; Chain = newChain(); f.assign ( "in.chain",true ); if (f.reset()) { while (!f.FileEnd()) { f.ReadLine ( S,sizeof(S) ); chain->ConvertPDBString ( S ); } f.shut(); } else { printf ( " Can't open input file 'in.chain' \n" ); delete Chain; return; } f.assign ( "out.chain",true ); if (f.rewrite()) { chain->PDBASCIIDump ( f ); f.shut(); } else { printf ( " Can't open output file 'out.chain' \n" ); delete Chain; return; } f.assign ( "mmdb.chain.bin",false ); if (f.rewrite()) { chain->write ( f ); f.shut(); } else { printf ( " Can't open binary chain file for writing.\n" ); delete Chain; return; } delete Chain; printf ( " Chain deleted.\n" ); Chain = newChain(); if (f.reset()) { chain->read ( f ); f.shut(); } else { printf ( " Can't open binary chain file for reading.\n" ); delete Chain; return; } f.assign ( "abin.chain",true ); if (f.rewrite()) { chain->PDBASCIIDump ( f ); f.shut(); } else printf ( " Can't open output file 'abin.chain' \n" ); delete Chain; } */ mmdb2-2.0.5/mmdb2/mmdb_cifdefs.h0000664000175000017500000003617412401105774013232 00000000000000// $Id: mmdb_cifdefs.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 21.11.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDBF_Defs // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Namespace: mmdb:: // // CIF Definitions // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_CIFDefs__ #define __MMDB_CIFDefs__ #include "mmdb_mattype.h" namespace mmdb { // ------------------------------------------------------------------ // Mode IDs enum CIF_MODE { CIF_NDB = 0, CIF_PDBX = 1 }; // CIF IDs for mode-dependent CIF names enum CIF_ID { CAT_POLY_SEQ_SCHEME = 1, TAG_CHAIN_ID = 101, TAG_DB_ACCESSION = 102, TAG_DB_ALIGN_BEG = 103, TAG_DB_ALIGN_BEG_INS_CODE = 104, TAG_DB_ALIGN_END = 105, TAG_DB_ALIGN_END_INS_CODE = 106, TAG_ID_CODE = 107, TAG_SEQ_CHAIN_ID = 108, TAG_SEQ_ALIGN_BEG = 109, TAG_SEQ_ALIGN_BEG_INS_CODE = 110, TAG_SEQ_ALIGN_END = 111, TAG_SEQ_ALIGN_END_INS_CODE = 112 }; // CIFName(..) gives CIF name according to CIF Mode. extern cpstr CIFName ( int NameID, CIF_MODE Mode ); // ------------------------------------------------------------------ extern cpstr CIFCAT_ATOM_SITE ; extern cpstr CIFCAT_ATOM_SITE_ANISOTROP ; extern cpstr CIFCAT_ATOM_SITES ; extern cpstr CIFCAT_AUDIT_AUTHOR ; extern cpstr CIFCAT_CELL ; extern cpstr CIFCAT_CHEM_COMP ; extern cpstr CIFCAT_CITATION ; extern cpstr CIFCAT_DATABASE ; extern cpstr CIFCAT_DATABASE_PDB_CAVEAT ; extern cpstr CIFCAT_DATABASE_PDB_MATRIX ; extern cpstr CIFCAT_DATABASE_PDB_REV ; extern cpstr CIFCAT_DATABASE_PDB_TVECT ; extern cpstr CIFCAT_ENTITY ; extern cpstr CIFCAT_EXPTL ; extern cpstr CIFCAT_NDB_DATABASE_REMARK ; extern cpstr CIFCAT_NDB_NONSTANDARD_LIST ; extern cpstr CIFCAT_NDB_POLY_SEQ_SCHEME ; extern cpstr CIFCAT_PDBX_POLY_SEQ_SCHEME ; extern cpstr CIFCAT_REFINE ; extern cpstr CIFCAT_SPRSDE ; extern cpstr CIFCAT_STRUCT ; extern cpstr CIFCAT_STRUCT_ASYM ; extern cpstr CIFCAT_STRUCT_CONF ; extern cpstr CIFCAT_STRUCT_CONN ; extern cpstr CIFCAT_STRUCT_LINKR ; extern cpstr CIFCAT_STRUCT_KEYWORDS ; extern cpstr CIFCAT_STRUCT_NCS_OPER ; extern cpstr CIFCAT_STRUCT_REF ; extern cpstr CIFCAT_STRUCT_REF_SEQ ; extern cpstr CIFCAT_STRUCT_REF_SEQ_DIF ; extern cpstr CIFCAT_STRUCT_SHEET ; extern cpstr CIFCAT_STRUCT_SHEET_RANGE ; extern cpstr CIFCAT_STRUCT_SHEET_ORDER ; extern cpstr CIFCAT_STRUCT_SHEET_HBOND ; extern cpstr CIFCAT_SYMMETRY ; extern cpstr CIFCAT_OBSLTE ; extern cpstr CIFTAG_ANGLE_ALPHA ; extern cpstr CIFTAG_ANGLE_BETA ; extern cpstr CIFTAG_ANGLE_GAMMA ; extern cpstr CIFTAG_ASYM_ID ; extern cpstr CIFTAG_ATOM_TYPE_SYMBOL ; extern cpstr CIFTAG_AUTH_ASYM_ID ; extern cpstr CIFTAG_AUTH_ATOM_ID ; extern cpstr CIFTAG_AUTH_COMP_ID ; extern cpstr CIFTAG_AUTH_SEQ_ID ; extern cpstr CIFTAG_B_ISO_OR_EQUIV ; extern cpstr CIFTAG_B_ISO_OR_EQUIV_ESD ; extern cpstr CIFTAG_BEG_LABEL_ASYM_ID ; extern cpstr CIFTAG_BEG_LABEL_COMP_ID ; extern cpstr CIFTAG_BEG_LABEL_SEQ_ID ; extern cpstr CIFTAG_CARTN_X ; extern cpstr CIFTAG_CARTN_X_ESD ; extern cpstr CIFTAG_CARTN_Y ; extern cpstr CIFTAG_CARTN_Y_ESD ; extern cpstr CIFTAG_CARTN_Z ; extern cpstr CIFTAG_CARTN_Z_ESD ; extern cpstr CIFTAG_PDBX_FORMAL_CHARGE ; extern cpstr CIFTAG_CODE ; extern cpstr CIFTAG_CODE_NDB ; extern cpstr CIFTAG_CODE_PDB ; extern cpstr CIFTAG_CONF_TYPE_ID ; extern cpstr CIFTAG_CONN_TYPE_ID ; extern cpstr CIFTAG_DATE ; extern cpstr CIFTAG_DATE_ORIGINAL ; extern cpstr CIFTAG_DB_ALIGN_BEG ; extern cpstr CIFTAG_DB_ALIGN_END ; extern cpstr CIFTAG_DB_CODE ; extern cpstr CIFTAG_DB_MON_ID ; extern cpstr CIFTAG_DB_NAME ; extern cpstr CIFTAG_DETAILS ; extern cpstr CIFTAG_END_LABEL_ASYM_ID ; extern cpstr CIFTAG_END_LABEL_COMP_ID ; extern cpstr CIFTAG_END_LABEL_SEQ_ID ; extern cpstr CIFTAG_ENTITY_ID ; extern cpstr CIFTAG_ENTRY_ID ; extern cpstr CIFTAG_FORMULA ; extern cpstr CIFTAG_FRACT_TRANSF_MATRIX11 ; extern cpstr CIFTAG_FRACT_TRANSF_MATRIX12 ; extern cpstr CIFTAG_FRACT_TRANSF_MATRIX13 ; extern cpstr CIFTAG_FRACT_TRANSF_MATRIX21 ; extern cpstr CIFTAG_FRACT_TRANSF_MATRIX22 ; extern cpstr CIFTAG_FRACT_TRANSF_MATRIX23 ; extern cpstr CIFTAG_FRACT_TRANSF_MATRIX31 ; extern cpstr CIFTAG_FRACT_TRANSF_MATRIX32 ; extern cpstr CIFTAG_FRACT_TRANSF_MATRIX33 ; extern cpstr CIFTAG_FRACT_TRANSF_VECTOR1 ; extern cpstr CIFTAG_FRACT_TRANSF_VECTOR2 ; extern cpstr CIFTAG_FRACT_TRANSF_VECTOR3 ; extern cpstr CIFTAG_GROUP_PDB ; extern cpstr CIFTAG_ID ; extern cpstr CIFTAG_INS_CODE ; extern cpstr CIFTAG_LABEL_ALT_ID ; extern cpstr CIFTAG_LABEL_ATOM_ID ; extern cpstr CIFTAG_LABEL_ASYM_ID ; extern cpstr CIFTAG_LABEL_COMP_ID ; extern cpstr CIFTAG_LABEL_ENTITY_ID ; extern cpstr CIFTAG_LABEL_SEQ_ID ; extern cpstr CIFTAG_LENGTH_A ; extern cpstr CIFTAG_LENGTH_B ; extern cpstr CIFTAG_LENGTH_C ; extern cpstr CIFTAG_LS_D_RES_HIGH ; extern cpstr CIFTAG_MATRIX11 ; extern cpstr CIFTAG_MATRIX12 ; extern cpstr CIFTAG_MATRIX13 ; extern cpstr CIFTAG_MATRIX21 ; extern cpstr CIFTAG_MATRIX22 ; extern cpstr CIFTAG_MATRIX23 ; extern cpstr CIFTAG_MATRIX31 ; extern cpstr CIFTAG_MATRIX32 ; extern cpstr CIFTAG_MATRIX33 ; extern cpstr CIFTAG_METHOD ; extern cpstr CIFTAG_MOD_TYPE ; extern cpstr CIFTAG_MON_ID ; extern cpstr CIFTAG_NAME ; extern cpstr CIFTAG_NDB_BEG_LABEL_INS_CODE_PDB ; extern cpstr CIFTAG_NDB_CHAIN_ID ; extern cpstr CIFTAG_NDB_COMPONENT_NO ; extern cpstr CIFTAG_NDB_DESCRIPTOR ; extern cpstr CIFTAG_NDB_DB_ACCESSION ; extern cpstr CIFTAG_NDB_DB_ALIGN_BEG_INS_CODE ; extern cpstr CIFTAG_NDB_DB_ALIGN_END_INS_CODE ; extern cpstr CIFTAG_NDB_END_LABEL_INS_CODE_PDB ; extern cpstr CIFTAG_PDBX_PDB_INS_CODE ; extern cpstr CIFTAG_NDB_HELIX_CLASS_PDB ; extern cpstr CIFTAG_NDB_KEYWORDS ; extern cpstr CIFTAG_NDB_LABEL_ALT_ID ; extern cpstr CIFTAG_NDB_LABEL_ATOM_ID ; extern cpstr CIFTAG_NDB_LABEL_ASYM_ID ; extern cpstr CIFTAG_NDB_LABEL_COMP_ID ; extern cpstr CIFTAG_NDB_LABEL_INS_CODE ; extern cpstr CIFTAG_NDB_LABEL_SEQ_NUM ; extern cpstr CIFTAG_NDB_LENGTH ; extern cpstr CIFTAG_NDB_MODEL ; extern cpstr CIFTAG_NDB_PDB_CHAIN_ID ; extern cpstr CIFTAG_NDB_PDB_ID ; extern cpstr CIFTAG_NDB_PDB_ID_CODE ; extern cpstr CIFTAG_NDB_PDB_INS_CODE ; extern cpstr CIFTAG_NDB_PTNR1_LABEL_INS_CODE ; extern cpstr CIFTAG_NDB_PTNR1_STANDARD_COMP_ID ; extern cpstr CIFTAG_NDB_RANGE_1_BEG_LABEL_COMP_ID ; extern cpstr CIFTAG_NDB_RANGE_1_BEG_LABEL_ASYM_ID ; extern cpstr CIFTAG_NDB_RANGE_1_BEG_LABEL_INS_CODE; extern cpstr CIFTAG_NDB_RANGE_1_END_LABEL_COMP_ID ; extern cpstr CIFTAG_NDB_RANGE_1_END_LABEL_ASYM_ID ; extern cpstr CIFTAG_NDB_RANGE_1_END_LABEL_INS_CODE; extern cpstr CIFTAG_NDB_SEQ_ALIGN_BEG ; extern cpstr CIFTAG_NDB_SEQ_ALIGN_BEG_INS_CODE ; extern cpstr CIFTAG_NDB_SEQ_ALIGN_END ; extern cpstr CIFTAG_NDB_SEQ_ALIGN_END_INS_CODE ; extern cpstr CIFTAG_NDB_SEQ_DB_NAME ; extern cpstr CIFTAG_NDB_SEQ_DB_ACCESSION_CODE ; extern cpstr CIFTAG_NDB_SEQ_DB_SEQ_NUM ; extern cpstr CIFTAG_NDB_SYNONYMS ; extern cpstr CIFTAG_NUM ; extern cpstr CIFTAG_NUMBER_ATOMS_NH ; extern cpstr CIFTAG_NUMBER_STRANDS ; extern cpstr CIFTAG_OCCUPANCY ; extern cpstr CIFTAG_OCCUPANCY_ESD ; extern cpstr CIFTAG_ORIGX11 ; extern cpstr CIFTAG_ORIGX12 ; extern cpstr CIFTAG_ORIGX13 ; extern cpstr CIFTAG_ORIGX21 ; extern cpstr CIFTAG_ORIGX22 ; extern cpstr CIFTAG_ORIGX23 ; extern cpstr CIFTAG_ORIGX31 ; extern cpstr CIFTAG_ORIGX32 ; extern cpstr CIFTAG_ORIGX33 ; extern cpstr CIFTAG_ORIGX_VECTOR1 ; extern cpstr CIFTAG_ORIGX_VECTOR2 ; extern cpstr CIFTAG_ORIGX_VECTOR3 ; extern cpstr CIFTAG_PDB_ID ; extern cpstr CIFTAG_PDB_MON_ID ; extern cpstr CIFTAG_PDB_STRAND_ID ; extern cpstr CIFTAG_PDBX_DB_ACCESSION ; extern cpstr CIFTAG_PDBX_DB_ALIGN_BEG_INS_CODE ; extern cpstr CIFTAG_PDBX_DB_ALIGN_END_INS_CODE ; extern cpstr CIFTAG_PDBX_PDB_ID_CODE ; extern cpstr CIFTAG_PDBX_PDB_MODEL_NUM ; extern cpstr CIFTAG_PDBX_STRAND_ID ; extern cpstr CIFTAG_RANGE_1_BEG_LABEL_ATOM_ID ; extern cpstr CIFTAG_RANGE_1_BEG_LABEL_SEQ_ID ; extern cpstr CIFTAG_RANGE_1_END_LABEL_ATOM_ID ; extern cpstr CIFTAG_RANGE_1_END_LABEL_SEQ_ID ; extern cpstr CIFTAG_RANGE_ID_1 ; extern cpstr CIFTAG_RANGE_ID_2 ; extern cpstr CIFTAG_RCSB_RECORD_REVISED_1 ; extern cpstr CIFTAG_RCSB_RECORD_REVISED_2 ; extern cpstr CIFTAG_RCSB_RECORD_REVISED_3 ; extern cpstr CIFTAG_RCSB_RECORD_REVISED_4 ; extern cpstr CIFTAG_PDBX_SEQ_ALIGN_BEG_INS_CODE ; extern cpstr CIFTAG_PDBX_SEQ_ALIGN_END_INS_CODE ; extern cpstr CIFTAG_PTNR1_LABEL_ASYM_ID ; extern cpstr CIFTAG_PTNR1_LABEL_COMP_ID ; extern cpstr CIFTAG_PTNR1_LABEL_SEQ_ID ; extern cpstr CIFTAG_REF_ID ; extern cpstr CIFTAG_REPLACES ; extern cpstr CIFTAG_REPLACE_PDB_ID ; extern cpstr CIFTAG_SEGMENT_ID ; extern cpstr CIFTAG_SEQ_ALIGN_BEG ; extern cpstr CIFTAG_SEQ_ALIGN_END ; extern cpstr CIFTAG_SEQ_NUM ; extern cpstr CIFTAG_SENSE ; extern cpstr CIFTAG_SHEET_ID ; extern cpstr CIFTAG_SOURCE ; extern cpstr CIFTAG_SPACE_GROUP_NAME_H_M ; extern cpstr CIFTAG_TEXT ; extern cpstr CIFTAG_TITLE ; extern cpstr CIFTAG_TYPE ; extern cpstr CIFTAG_TYPE_SYMBOL ; extern cpstr CIFTAG_VECTOR1 ; extern cpstr CIFTAG_VECTOR2 ; extern cpstr CIFTAG_VECTOR3 ; extern cpstr CIFTAG_U11 ; extern cpstr CIFTAG_U11_ESD ; extern cpstr CIFTAG_U12 ; extern cpstr CIFTAG_U12_ESD ; extern cpstr CIFTAG_U13 ; extern cpstr CIFTAG_U13_ESD ; extern cpstr CIFTAG_U22 ; extern cpstr CIFTAG_U22_ESD ; extern cpstr CIFTAG_U23 ; extern cpstr CIFTAG_U23_ESD ; extern cpstr CIFTAG_U33 ; extern cpstr CIFTAG_U33_ESD ; extern cpstr CIFTAG_Z_PDB ; extern cpstr CIFTAG_CONN_PTNR1_AUTH_ATOM_ID ; extern cpstr CIFTAG_CONN_PDBX_PTNR1_AUTH_ALT_ID ; extern cpstr CIFTAG_CONN_PTNR1_AUTH_COMP_ID ; extern cpstr CIFTAG_CONN_PTNR1_AUTH_ASYM_ID ; extern cpstr CIFTAG_CONN_PTNR1_AUTH_SEQ_ID ; extern cpstr CIFTAG_CONN_PDBX_PTNR1_PDB_INS_CODE ; extern cpstr CIFTAG_CONN_DIST ; extern cpstr CIFTAG_CONN_PTNR2_AUTH_ATOM_ID ; extern cpstr CIFTAG_CONN_PDBX_PTNR2_AUTH_ALT_ID ; extern cpstr CIFTAG_CONN_PTNR2_AUTH_COMP_ID ; extern cpstr CIFTAG_CONN_PTNR2_AUTH_ASYM_ID ; extern cpstr CIFTAG_CONN_PTNR2_AUTH_SEQ_ID ; extern cpstr CIFTAG_CONN_PDBX_PTNR2_PDB_INS_CODE ; extern cpstr CIFTAG_CONN_PTNR1_SYMMETRY ; extern cpstr CIFTAG_CONN_PTNR2_SYMMETRY ; extern cpstr CIFTAG_CONN_NAME ; } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_title.h0000664000175000017500000004406712601171753012752 00000000000000// $Id: mmdb_title.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_Title // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::TitleContainer (container of title classes) // ~~~~~~~~~ mmdb::ObsLine // mmdb::TitleLine // mmdb::Caveat // mmdb::Compound // mmdb::Source // mmdb::KeyWords // mmdb::ExpData // mmdb::MdlType // mmdb::Author // mmdb::RevData // mmdb::Supersede // mmdb::Journal // mmdb::Remark // mmdb::Biomolecule // mmdb::Title ( MMDB title section ) // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_Title__ #define __MMDB_Title__ #include "mmdb_io_stream.h" #include "mmdb_defs.h" #include "mmdb_utils.h" #include "mmdb_mmcif_.h" namespace mmdb { // ====================== TitleContainer ======================= DefineClass(TitleContainer); DefineStreamFunctions(TitleContainer); class TitleContainer : public ClassContainer { public : TitleContainer () : ClassContainer() {} TitleContainer ( io::RPStream Object ) : ClassContainer ( Object ) {} ~TitleContainer() {} PContainerClass MakeContainerClass ( int ClassID ); }; // ================== ObsLine ======================== DefineClass(ObsLine); DefineStreamFunctions(ObsLine); class ObsLine : public ContainerClass { public : Date repDate; // date of replacement IDCode idCode; // ID code of replaced entry IDCode rIdCode[8]; // ID codes of entries that replaced this one ObsLine (); ObsLine ( cpstr S ); ObsLine ( io::RPStream Object ); ~ObsLine(); void PDBASCIIDump ( pstr S, int N ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_ObsLine; } void Copy ( PContainerClass ObsLine ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitObsLine(); }; // ==================== TitleLine ===================== DefineClass(TitleLine); DefineStreamFunctions(TitleLine); class TitleLine : public ContString { public : TitleLine (); TitleLine ( cpstr S ); TitleLine ( io::RPStream Object ); ~TitleLine(); ERROR_CODE ConvertPDBASCII ( cpstr S ); void PDBASCIIDump ( pstr S, int N ); bool PDBASCIIDump1 ( io::RFile ) { return false; } CLASS_ID GetClassID () { return ClassID_TitleLine; } void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitTitleLine(); }; // ==================== Caveat ===================== DefineClass(Caveat); DefineStreamFunctions(Caveat); class Caveat : public ContString { public : IDCode idCode; // ID code of the entry Caveat (); Caveat ( cpstr S ); Caveat ( io::RPStream Object ); ~Caveat(); void PDBASCIIDump ( pstr S, int N ); bool PDBASCIIDump1 ( io::RFile ) { return false; } void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); // virtual void GetCIF1 ( mmcif::PData CIF, ERROR_CODE & Signal, // int & pos ); CLASS_ID GetClassID () { return ClassID_CAVEAT; } void Copy ( PContainerClass Caveat ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitCaveat(); }; // ==================== Compound ===================== DefineClass(Compound); DefineStreamFunctions(Compound); class Compound : public ContString { public : Compound (); Compound ( cpstr S ); Compound ( io::RPStream Object ); ~Compound(); void PDBASCIIDump ( pstr S, int N ); bool PDBASCIIDump1 ( io::RFile ) { return false; } ERROR_CODE ConvertPDBASCII ( cpstr S ); CLASS_ID GetClassID () { return ClassID_Compound; } void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitCompound(); }; // ==================== Source ===================== DefineClass(Source); DefineStreamFunctions(Source); class Source : public ContString { public : Source (); Source ( cpstr S ); Source ( io::RPStream Object ); ~Source(); void PDBASCIIDump ( pstr S, int N ); bool PDBASCIIDump1 ( io::RFile ) { return false; } ERROR_CODE ConvertPDBASCII ( cpstr S ); CLASS_ID GetClassID () { return ClassID_Source; } void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitSource(); }; // ==================== KeyWords ===================== DefineClass(KeyWords); DefineStreamFunctions(KeyWords); class KeyWords : public io::Stream { public : int nKeyWords; // number of key words psvector KeyWord; // key word array KeyWords (); KeyWords ( cpstr S ); KeyWords ( io::RPStream Object ); ~KeyWords(); void Delete (); void PDBASCIIDump ( io::RFile f ); void MakeCIF ( mmcif::PData CIF ); int ConvertPDBASCII ( cpstr S ); void GetCIF ( mmcif::PData CIF ); void Copy ( PKeyWords KeyWords ); void write ( io::RFile f ); void read ( io::RFile f ); protected : bool Cont; void Init(); }; // ==================== ExpData ===================== DefineClass(ExpData); DefineStreamFunctions(ExpData); class ExpData : public ContString { public : ExpData (); ExpData ( cpstr S ); ExpData ( io::RPStream Object ); ~ExpData(); void PDBASCIIDump ( pstr S, int N ); bool PDBASCIIDump1 ( io::RFile ) { return false; } ERROR_CODE ConvertPDBASCII ( cpstr S ); CLASS_ID GetClassID () { return ClassID_ExpData; } void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitExpData(); }; // ==================== MdlType ===================== DefineClass(MdlType); DefineStreamFunctions(MdlType); class MdlType : public ContString { public : MdlType (); MdlType ( cpstr S ); MdlType ( io::RPStream Object ); ~MdlType(); void PDBASCIIDump ( pstr S, int N ); bool PDBASCIIDump1 ( io::RFile ) { return false; } ERROR_CODE ConvertPDBASCII ( cpstr S ); CLASS_ID GetClassID () { return ClassID_MdlType; } void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitMdlType(); }; // ==================== Author ===================== DefineClass(Author); DefineStreamFunctions(Author); class Author : public ContString { public : Author (); Author ( cpstr S ); Author ( io::RPStream Object ); ~Author(); void PDBASCIIDump ( pstr S, int N ); bool PDBASCIIDump1 ( io::RFile ) { return false; } ERROR_CODE ConvertPDBASCII ( cpstr S ); CLASS_ID GetClassID () { return ClassID_Author; } void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitAuthor(); }; // ==================== RevData ===================== DefineClass(RevData); DefineStreamFunctions(RevData); enum REVDAT_WARNING { REVDAT_WARN_MODNUM = 0x00000001, REVDAT_WARN_MODTYPE = 0x00000002 }; class RevData : public ContainerClass { public : int modNum; Date modDate; char modId[13]; int modType; RecName record[4]; word Warning; RevData (); RevData ( cpstr S ); RevData ( io::RPStream Object ); ~RevData(); void PDBASCIIDump ( pstr S, int N ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_RevData; } void Copy ( PContainerClass RevData ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitRevData(); }; // ================== Supersede ======================== DefineClass(Supersede); DefineStreamFunctions(Supersede); class Supersede : public ContainerClass { public : Date sprsdeDate; // date of supersede IDCode idCode; // ID code of the entry IDCode sIdCode[8]; // ID codes of superseded entries Supersede (); Supersede ( cpstr S ); Supersede ( io::RPStream Object ); ~Supersede(); void PDBASCIIDump ( pstr S, int N ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_Supersede; } void Copy ( PContainerClass Supersede ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitSupersede(); }; // ==================== Journal ===================== DefineClass(Journal); DefineStreamFunctions(Journal); class Journal : public ContString { public : Journal (); Journal ( cpstr S ); Journal ( io::RPStream Object ); ~Journal(); void PDBASCIIDump ( pstr S, int N ); bool PDBASCIIDump1 ( io::RFile ) { return false; } ERROR_CODE ConvertPDBASCII ( cpstr S ); CLASS_ID GetClassID () { return ClassID_Journal; } void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitJournal(); }; // ==================== Remark ===================== DefineClass(Remark); DefineStreamFunctions(Remark); class Remark : public ContainerClass { public : int remarkNum; // remark id pstr remark; // remark line Remark (); Remark ( cpstr S ); Remark ( io::RPStream Object ); ~Remark(); void PDBASCIIDump ( pstr S, int N ); void MakeCIF ( mmcif::PData CIF, int N ); ERROR_CODE ConvertPDBASCII ( cpstr S ); ERROR_CODE GetCIF ( mmcif::PData CIF, int & n ); CLASS_ID GetClassID () { return ClassID_Remark; } void Copy ( PContainerClass RemarkClass ); void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitRemark(); }; // ================= Biomolecule ===================== DefineClass(BMApply); DefineStreamFunctions(BMApply); class BMApply : public io::Stream { public : PChainID chain; int nChains; pmat44 tm; int nMatrices; BMApply (); BMApply ( io::RPStream Object ); ~BMApply(); void FreeMemory(); int addChains ( int & i, RPRemark rem, RTitleContainer Remark ); int addMatrices ( int & i, RPRemark rem, RTitleContainer Remark ); void Copy ( PBMApply BMA ); // if BMA is NULL, then empties // the class void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitBMApply(); }; DefineClass(Biomolecule); DefineStreamFunctions(Biomolecule); class Biomolecule : public io::Stream { public : PPBMApply bmApply; int nBMAs; Biomolecule (); Biomolecule ( io::RPStream Object ); ~Biomolecule(); void FreeMemory(); PBMApply addBMApply(); int Size(); bool checkComposition ( PChainID chID, ivector occ, ivector wocc, int n ); void Copy ( PBiomolecule B ); // if B is NULL, then empties // the class void write ( io::RFile f ); void read ( io::RFile f ); protected : void InitBiomolecule(); }; // ================= Title ======================= DefineClass(Title); DefineStreamFunctions(Title); class Title : public io::Stream { friend class Model; friend class Chain; friend class Root; public : Title (); Title ( io::RPStream Object ); ~Title(); void FreeMemory ( bool keepBiomolecules ); // Fills the PDB file header void SetHeader ( cpstr Classification, // any length is Ok cpstr DepDate, // DD-MMM-YYYY cpstr ID_Code ); // not more than 11 chars // Interprets the ASCII PDB line belonging to the title section // and fills the corresponding fields. // Returns zero if the line was converted, otherwise returns a // non-negative value of Error_XXXX. // PDBString must be not shorter than 81 characters. ERROR_CODE ConvertPDBString ( pstr PDBString ); // MakePDBString() makes the ASCII PDB HEADER line from the // class data. PDBString must be not shorter than 81 characters. void MakePDBHeaderString ( pstr PDBString ); // GetStructureTitle() returns the contents of TITLE record // unfolded into single line. If Title is missing, returns // contents of COMPND(:MOLECULE). If COMPND is missing, returns // HEADER. If Header is missing, returns PDB code. If no PDB // code is there, returns "Not available". pstr GetStructureTitle ( pstr & S ); PTitleContainer GetObsData () { return &obsData; } PTitleContainer GetCaveat () { return &caveat; } PTitleContainer GetCompound() { return &compound; } PTitleContainer GetSource () { return &source; } PKeyWords GetKeyWords() { return &keyWords; } PTitleContainer GetExpData () { return &expData; } PTitleContainer GetMdlType () { return &mdlType; } PTitleContainer GetRemarks () { return &remark; } PTitleContainer GetJournal () { return &journal; } realtype GetResolution(); // -1.0 mean no resolution record in file int ParseBiomolecules(); // returns the number of biomolecules, // -2 for general format error // -3 for errors in BIOMT records int GetNofBiomolecules(); void GetBiomolecules ( PPBiomolecule & BM, int & nBMs ); PBiomolecule GetBiomolecule ( int bmNo ); // bmno=0,1,.. // returns NULL if bmNo is incorrect void PDBASCIIDump ( io::RFile f ); void MakeCIF ( mmcif::PData CIF ); // GetCIF(..) returns the same code as ConvertPDBString(..) // save for Error_WrongSection ERROR_CODE GetCIF ( mmcif::PData CIF ); inline pstr GetIDCode() { return idCode; } inline bool GetCol73 () { return col73; } void TrimInput ( pstr PDBString ); void Copy ( PTitle TS ); // if TS is NULL, then empties // the class void write ( io::RFile f ); // writes header to PDB binary file void read ( io::RFile f ); // reads header from PDB binary file protected : // Header data pstr classification; // classification of the molecule Date depDate; // deposition date DD-MMM-YYYY IDCode idCode; // unique PDB identifier realtype resolution; // resolution bool col73; // True if columns 73-80 contain PDB ID TitleContainer obsData; // obsoletion data TitleContainer title; // title data TitleContainer caveat; // error data TitleContainer compound; // compound data TitleContainer source; // source KeyWords keyWords; // key words TitleContainer expData; // experimental data TitleContainer mdlType; // model descriptions TitleContainer author; // author data TitleContainer revData; // revision data TitleContainer supersede; // supersede records TitleContainer journal; // journal records TitleContainer remark; // remark records PPBiomolecule biomolecule; int nBiomolecules; void Init(); void FreeBiomolecules(); PBiomolecule addBiomolecule(); }; extern void TestHeader(); extern void TestTitle (); // reads PDB title from file 'in.title' // and rewrites it into 'out.title' and // 'abin.title' } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_seqsuperpose.h0000775000175000017500000001211112401105774014351 00000000000000// $Id: mmdb_seqsuperpose.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 19.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : SeqSuperpose // ~~~~~~~~~ // **** Classes : mmdb::SeqSuperpose // ~~~~~~~~~ // // (C) E.Krissinel 2005-2013 // // ================================================================= // #ifndef __Seq_Superpose__ #define __Seq_Superpose__ #include "mmdb_manager.h" #include "mmdb_math_align.h" namespace mmdb { // ================================================================= enum SEQSP_RC { SEQSP_Ok = 0, SEQSP_IterLimit = 100, SEQSP_SeqThreshold = 101 }; DefineClass(SeqSuperpose); class SeqSuperpose { public : mat44 TMatrix; // superposes Ca1 over Ca2: |T*Ca1 - Ca2|->min realtype Q; // Q-score realtype rmsd; // rmsd realtype seqId; // sequence identity in structure alignment realtype _seqId; // sequence identity in sequence alignment int Nalign; // alignment length in structure alignment ivector c1; // sup-n vector: Ca1[i]->Ca2[c1[i]] if c1[i]>=0 ivector c2; // sup-n vector: Ca2[i]->Ca1[c2[i]] if c2[i]>=0 SeqSuperpose(); ~SeqSuperpose(); // Given two sets of atoms, Calpha1 and Calpha2, Superpose(...) // calculates the rotational-translational matrix TMatrix such // that |TMatrix*Calpha1 - Calpha2| is minimal in least-square // terms. // In difference of a full-scale SSM, this simplified version // uses initial superposition from sequence alignment, hence // it should be applied only to similar chains where calculation // time is crucial. seqThreshold specifies a threshold of // sequence identity (0<=seqThreshold<=1), below which // structural alignment is not performed and Superpose(..) // returns SEQSP_SeqThreshold. // // If keepBricks is set True, then space bricks are not // removed in MMDB and may be used in the next call if // vector Calpha2 does not change. This saves computation // time. // // The alignment results return in public fields above: // TMatrix - transformation matrix (1 if not aligned) // Q - quality Q-score (-1 if not aligned) // rmsd - r.m.s.d (MaxReal if not aligned) // seqId - sequence identity in structure alignment // (0 if not aligned) // Nalign - alignment length in structure alignment // (0 if not aligned) // c1,c2 - atom corrspondences: // Calpha1[i] <=> Calpha2[c1[i]] // Calpha2[i] <=> Calpha1[c2[i]] // // Upon success, Superpose(...) returns SEQSP_Ok // int Superpose ( PManager MMDB, PPAtom Calpha1, int nCalpha1, PPAtom Calpha2, int nCalpha2, realtype seqThreshold, bool keepBricks ); protected : math::PAlignment Align; PManager M; // pointers to PPAtom Ca1,Ca2; // the input data int nCa1,nCa2; // copy chain lengths ivector cn1,cn2; // temporary contact arrays realtype Rmsd0; // quality optimization parameter realtype maxContact; // maximal Calpha-pair contact parameter PContact contact; int ncontacts; void SeqSuperposeInit(); void FreeMemory (); realtype MatchQuality ( int Nalign, realtype Rmsd, int nres1, int nres2 ); realtype MatchQuality2 ( int Nalign, realtype dist2, int nres1, int nres2 ); void MakeContacts ( mat44 & TM, realtype cont_est ); int makeStructAlignment ( realtype seqThreshold, bool keepBricks ); }; } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/hybrid_36.cpp0000664000175000017500000002052412461512315012743 00000000000000// $Id: hybrid_36.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // /*! C port of the hy36encode() and hy36decode() functions in the hybrid_36.py Python prototype/reference implementation. See the Python script for more information. This file has no external dependencies, NOT even standard C headers. Optionally, use hybrid_36_c.h, or simply copy the declarations into your code. This file is unrestricted Open Source (cctbx.sf.net). Please send corrections and enhancements to cctbx@cci.lbl.gov . See also: http://cci.lbl.gov/hybrid_36/ Ralf W. Grosse-Kunstleve, Feb 2007. */ /* The following #include may be commented out. It is here only to enforce consistency of the declarations and the definitions. */ #ifndef IOTBX_PDB_HYBRID_36_C_H #include "hybrid_36.h" #endif /* All static functions below are implementation details (and not accessible from other translation units). */ static const char* digits_upper() { return "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } static const char* digits_lower() { return "0123456789abcdefghijklmnopqrstuvwxyz"; } static const char* value_out_of_range() { return "value out of range."; } static const char* invalid_number_literal() { return "invalid number literal."; } static const char* unsupported_width() { return "unsupported width."; } static void fill_with_stars(unsigned width, char* result) { while (width) { *result++ = '*'; width--; } *result = '\0'; } static void encode_pure( const char* digits, unsigned digits_size, unsigned width, int value, char* result) { char buf[16]; int rest; unsigned i, j; i = 0; j = 0; if (value < 0) { j = 1; value = -value; } while (1) { rest = value / digits_size; buf[i++] = digits[value - rest * digits_size]; if (rest == 0) break; value = rest; } if (j) buf[i++] = '-'; for(j=i;j 127) { *result = 0; return invalid_number_literal(); } if (si == ' ') { if (!have_non_blank) continue; value *= digits_size; } else if (si == '-') { if (have_non_blank) { *result = 0; return invalid_number_literal(); } have_non_blank = 1; have_minus = 1; continue; } else { have_non_blank = 1; dv = digits_values[si]; if (dv < 0 || dv >= (int)digits_size) { *result = 0; return invalid_number_literal(); } value *= digits_size; value += dv; } } if (have_minus) value = -value; *result = value; return 0; } /*! hybrid-36 encoder: converts integer value to string result width: must be 4 (e.g. for residue sequence numbers) or 5 (e.g. for atom serial numbers) value: integer value to be converted result: pointer to char array of size width+1 or greater on return result is null-terminated return value: pointer to error message, if any, or 0 on success Example usage (from C++): char result[4+1]; const char* errmsg = hy36encode(4, 12345, result); if (errmsg) throw std::runtime_error(errmsg); */ const char* hy36encode(unsigned width, int value, char* result) { int i = value; if (width == 4U) { if (i >= -999) { if (i < 10000) { encode_pure(digits_upper(), 10U, 4U, i, result); return 0; } i -= 10000; if (i < 1213056 /* 26*36**3 */) { i += 466560 /* 10*36**3 */; encode_pure(digits_upper(), 36U, 0U, i, result); return 0; } i -= 1213056; if (i < 1213056) { i += 466560; encode_pure(digits_lower(), 36U, 0U, i, result); return 0; } } } else if (width == 5U) { if (i >= -9999) { if (i < 100000) { encode_pure(digits_upper(), 10U, 5U, i, result); return 0; } i -= 100000; if (i < 43670016 /* 26*36**4 */) { i += 16796160 /* 10*36**4 */; encode_pure(digits_upper(), 36U, 0U, i, result); return 0; } i -= 43670016; if (i < 43670016) { i += 16796160; encode_pure(digits_lower(), 36U, 0U, i, result); return 0; } } } else { fill_with_stars(width, result); return unsupported_width(); } fill_with_stars(width, result); return value_out_of_range(); } /*! hybrid-36 decoder: converts string s to integer result width: must be 4 (e.g. for residue sequence numbers) or 5 (e.g. for atom serial numbers) s: string to be converted does not have to be null-terminated s_size: size of s must be equal to width, or an error message is returned otherwise result: integer holding the conversion result return value: pointer to error message, if any, or 0 on success Example usage (from C++): int result; const char* errmsg = hy36decode(width, "A1T5", 4, &result); if (errmsg) throw std::runtime_error(errmsg); */ const char* hy36decode(unsigned width, const char* s, unsigned s_size, int* result) { static int first_call = 1; static int digits_values_upper[128U]; static int digits_values_lower[128U]; static const char* ie_range = "internal error hy36decode: integer value out of range."; unsigned i; int di; const char* errmsg; if (first_call) { first_call = 0; for(i=0;i<128U;i++) digits_values_upper[i] = -1; for(i=0;i<128U;i++) digits_values_lower[i] = -1; for(i=0;i<36U;i++) { di = digits_upper()[i]; if (di < 0 || di > 127) { *result = 0; return ie_range; } digits_values_upper[di] = i; } for(i=0;i<36U;i++) { di = digits_lower()[i]; if (di < 0 || di > 127) { *result = 0; return ie_range; } digits_values_lower[di] = i; } } if (s_size == width) { di = s[0]; if (di >= 0 && di <= 127) { if (digits_values_upper[di] >= 10) { errmsg = decode_pure(digits_values_upper, 36U, s, s_size, result); if (errmsg == 0) { /* result - 10*36**(width-1) + 10**width */ if (width == 4U) (*result) -= 456560; else if (width == 5U) (*result) -= 16696160; else { *result = 0; return unsupported_width(); } return 0; } } else if (digits_values_lower[di] >= 10) { errmsg = decode_pure(digits_values_lower, 36U, s, s_size, result); if (errmsg == 0) { /* result + 16*36**(width-1) + 10**width */ if (width == 4U) (*result) += 756496; else if (width == 5U) (*result) += 26973856; else { *result = 0; return unsupported_width(); } return 0; } } else { errmsg = decode_pure(digits_values_upper, 10U, s, s_size, result); if (errmsg) return errmsg; if (!(width == 4U || width == 5U)) { *result = 0; return unsupported_width(); } return 0; } } } *result = 0; return invalid_number_literal(); } mmdb2-2.0.5/mmdb2/mmdb_model.cpp0000664000175000017500000045077512601171753013273 00000000000000// $Id: mmdb_model.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 11.09.15 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_Model // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::HetCompound ( description of het compounds ) // ~~~~~~~~~ mmdb::HetCompounds (HETNAM, HETSYN, FORMULA records) // mmdb::SSContainer (container for helixes and turns) // mmdb::Helix ( helix info ) // mmdb::Strand ( strand info ) // mmdb::Sheet ( sheet info ) // mmdb::Sheets ( container for sheets ) // mmdb::Turn ( turn info ) // mmdb::LinkContainer ( container for link data ) // mmdb::Link ( link data ) // mmdb::LinkRContainer ( container for refmac link ) // mmdb::LinkR ( link data ) // mmdb::CisPepContainer ( container for CisPep data ) // mmdb::CisPep ( CisPep data ) // mmdb::Model ( PDB model ) // // Copyright (C) E. Krissinel 2000-2015 // // ================================================================= // #include #include #include "mmdb_model.h" #include "mmdb_manager.h" #include "mmdb_cifdefs.h" namespace mmdb { // =================== HetCompound ========================= HetCompound::HetCompound ( cpstr HetName ) : io::Stream() { InitHetCompound ( HetName ); } HetCompound::HetCompound ( io::RPStream Object ) : io::Stream(Object) { InitHetCompound ( pstr("---") ); } HetCompound::~HetCompound() { FreeMemory(); } void HetCompound::InitHetCompound ( cpstr HetName ) { strcpy_n0 ( hetID,HetName,sizeof(ResName) ); comment = NULL; nSynonyms = 0; hetSynonym = NULL; compNum = MinInt4; wc = ' '; Formula = NULL; } void HetCompound::FreeMemory() { int i; if (comment) { delete[] comment; comment = NULL; } if (hetSynonym) { for (i=0;i53) { i = 0; while (p1[i] && (i<53) && (p1[i]!=' ')) i++; p2 = &(p1[i]); c = *p2; *p2 = char(0); } if (*p1) { strcat ( S,p1 ); PadSpaces ( S,80 ); f.WriteLine ( S ); } else N--; if (p2) { *p2 = c; if (c) p1 = p2+1; else p2 = NULL; } } while (p2); } void HetCompound::HETSYN_PDBDump ( io::RFile f ) { char S[100]; pstr p; char c; int N,k,i,l; if (!hetSynonym) return; N = 0; k = 0; p = &(hetSynonym[0][0]); do { N++; if (N==1) sprintf ( S,"HETSYN %3s " ,hetID ); else sprintf ( S,"HETSYN %2i %3s ",N,hetID ); i = 0; do { l = strlen(p)+2; if (i+l<54) { strcat ( S,p ); if (k51) { i--; while ((i>0) && (p[i]!=' ')) i--; } if (i<2) i = 51; // no spaces! c = p[i]; p[i] = char(0); strcat ( S,p ); p[i] = c; p = &(p[i]); while (*p==' ') p++; } i = 60; // break loop } } while (i<54); PadSpaces ( S,80 ); f.WriteLine ( S ); } while (kMinInt4) { if (N==1) sprintf ( S,"FORMUL %2i %3s " ,compNum,hetID ); else sprintf ( S,"FORMUL %2i %3s %2i ",compNum,hetID,N ); } else { if (N==1) sprintf ( S,"FORMUL %3s " ,hetID ); else sprintf ( S,"FORMUL %3s %2i ",hetID,N ); } S[18] = wc; p2 = strchr(p1,'\n'); if (p2) { c = *p2; *p2 = char(0); } else if (strlen(p1)>50) { while (*p1==' ') p1++; i = 0; while (p1[i] && (i<50) && (p1[i]!=' ')) i++; p2 = &(p1[i]); c = *p2; *p2 = char(0); } strcat ( S,p1 ); if (p2) { *p2 = c; p1 = p2+1; } PadSpaces ( S,80 ); f.WriteLine ( S ); } while (p2); } void HetCompound::FormComString ( pstr & F ) { pstr p; int i; if (F) { delete[] F; F = NULL; } if (comment) { CreateCopy ( F,comment ); i = 0; p = comment; while (*p) { p++; if (*p=='\n') i = 0; else i++; if (i>68) { F[i] = char(0); CreateConcat ( F,pstr("\n"),p ); i = 0; } } } } void HetCompound::FormSynString ( pstr & F ) { pstr p; char c; int i,k,l; if (F) { delete[] F; F = NULL; } if (hetSynonym) { CreateCopy ( F,pstr(" ") ); k = 0; p = &(hetSynonym[0][0]); do { l = strlen(p)+2; if (l<=60) { if (k60) { i--; while ((i>0) && (p[i]!=' ')) i--; } if (i<2) i = 60; // no spaces! c = p[i]; p[i] = char(0); CreateConcat ( F,p,pstr("\n ") ); p[i] = c; p = &(p[i]); while (*p==' ') p++; } } while (k68) { F[i] = char(0); CreateConcat ( F,pstr("\n"),p ); i = 0; } } } } void HetCompound::Copy ( PHetCompound hetCompound ) { int i; FreeMemory (); strcpy ( hetID ,hetCompound->hetID ); CreateCopy ( comment,hetCompound->comment ); nSynonyms = hetCompound->nSynonyms; if (nSynonyms>0) { hetSynonym = new pstr[nSynonyms]; for (i=0;ihetSynonym[i] ); } } compNum = hetCompound->compNum; wc = hetCompound->wc; CreateCopy ( Formula,hetCompound->Formula ); } void HetCompound::write ( io::RFile f ) { int i; byte Version=1; f.WriteByte ( &Version ); f.WriteTerLine ( hetID,false ); f.CreateWrite ( comment ); f.WriteInt ( &nSynonyms ); for (i=0;i0) { hetSynonym = new pstr[nSynonyms]; for (i=0;i12) { strcpy_n0 ( hetID,&(S[11]),3 ); i = AddHetName ( hetID ); if (l>15) { if (hetCompound[i]->comment) strcpy ( L,"\n" ); else L[0] = char(0); strcat ( L,&(S[15]) ); CutSpaces ( L,SCUTKEY_END ); CreateConcat ( hetCompound[i]->comment,L ); } } } void HetCompounds::ConvertHETSYN ( cpstr S ) { ResName hetID; char L[100]; int l,i,j,k; l = strlen(S); if (l>12) { strcpy_n0 ( hetID,&(S[11]),3 ); i = AddHetName ( hetID ); if (l>15) { j = 15; do { while (S[j]==' ') j++; k = 0; if (S[j]) { while (S[j] && (S[j]!=';')) L[k++] = S[j++]; L[k--] = char(0); while ((k>0) && (L[k]==' ')) L[k--] = char(0); if (L[0]) { hetCompound[i]->AddKeyWord ( L,Closed ); Closed = (S[j]==';'); } if (S[j]) j++; } } while (S[j]); /* p1 = &(S[15]); do { p2 = strchr ( p1,';' ); if (p2) { c = *p2; *p2 = char(0); } strcpy_css ( L,p1 ); if (L[0]) hetCompound[i]->AddKeyWord ( L,Closed ); if (p2) { if (L[0]) Closed = true; *p2 = c; p1 = p2+1; } else if (L[0]) Closed = false; } while (p2); */ } } } void HetCompounds::ConvertFORMUL ( cpstr S ) { ResName hetID; char L[100]; int l,i; l = strlen(S); if (l>13) { strcpy_n0 ( hetID,&(S[12]),3 ); i = AddHetName ( hetID ); if (l>18) { GetInteger ( hetCompound[i]->compNum,&(S[9]),2 ); hetCompound[i]->wc = S[18]; if (strlen(S)>19) { if (hetCompound[i]->Formula) strcpy ( L,"\n" ); else L[0] = char(0); strcat ( L,&(S[19]) ); CutSpaces ( L,SCUTKEY_END ); CreateConcat ( hetCompound[i]->Formula,L ); } } } } int HetCompounds::AddHetName ( cpstr H ) { PPHetCompound HC1; int i; i = 0; while (ihetID,H)) break; } i++; } if (i>=nHets) { HC1 = new PHetCompound[nHets+1]; for (i=0;iHETNAM_PDBDump ( f ); for (i=0;iHETSYN_PDBDump ( f ); for (i=0;iFORMUL_PDBDump ( f ); } void HetCompounds::MakeCIF ( mmcif::PData CIF ) { mmcif::PLoop Loop; pstr F; int RC; int i; if (!hetCompound) return; RC = CIF->AddLoop ( CIFCAT_CHEM_COMP,Loop ); if (RC!=mmcif::CIFRC_Ok) { Loop->AddLoopTag ( CIFTAG_ID ); Loop->AddLoopTag ( CIFTAG_NAME ); Loop->AddLoopTag ( CIFTAG_NDB_SYNONYMS ); Loop->AddLoopTag ( CIFTAG_NDB_COMPONENT_NO ); Loop->AddLoopTag ( CIFTAG_FORMULA ); } F = NULL; for (i=0;iAddString ( hetCompound[i]->hetID ); hetCompound[i]->FormComString ( F ); Loop->AddString ( F ); hetCompound[i]->FormSynString ( F ); Loop->AddString ( F ); if (hetCompound[i]->compNum>MinInt4) Loop->AddInteger ( hetCompound[i]->compNum ); else Loop->AddNoData ( mmcif::CIF_NODATA_QUESTION ); hetCompound[i]->FormForString ( F ); Loop->AddString ( F ); } if (F) delete[] F; } ERROR_CODE HetCompounds::GetCIF ( mmcif::PData CIF ) { mmcif::PLoop Loop; char L[100]; ResName hetID; pstr F,p1,p2; char c; int RC,i,l,k; FreeMemory(); c = char(0); // only to supress compiler warnings Loop = CIF->GetLoop ( CIFCAT_CHEM_COMP ); if (!Loop) return Error_NoError; l = Loop->GetLoopLength(); F = NULL; for (i=0;iGetString ( hetCompound[k]->comment,CIFTAG_NAME,i,true ); RC = Loop->GetInteger ( hetCompound[k]->compNum, CIFTAG_NDB_COMPONENT_NO,i,true ); if (RC) hetCompound[i]->compNum = MinInt4; Loop->GetString ( hetCompound[k]->Formula,CIFTAG_FORMULA,i,true ); RC = Loop->GetString ( F,CIFTAG_NDB_SYNONYMS,i,true ); if ((!RC) && F ) { p1 = &(F[0]); while (*p1) { if (*p1=='\n') *p1 = ' '; p1++; } p1 = &(F[0]); do { p2 = strchr ( p1,';' ); if (p2) { c = *p2; *p2 = char(0); } strcpy_css ( L,p1 ); hetCompound[i]->AddKeyWord ( L,true ); if (p2) { *p2 = c; p1 = p2+1; } } while (p2); } hetCompound[i]->wc = ' '; } // CIF->DeleteLoop ( CIFCAT_CHEM_COMP ); if (F) delete[] F; return Error_NoError; } void HetCompounds::Copy ( PHetCompounds HetCompounds ) { int i; FreeMemory(); nHets = HetCompounds->nHets; if (nHets>0) { hetCompound = new PHetCompound[nHets]; for (i=0;iCopy ( HetCompounds->hetCompound[i] ); } } } void HetCompounds::write ( io::RFile f ) { int i; byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &nHets ); for (i=0;iwrite ( f ); } void HetCompounds::read ( io::RFile f ) { int i; byte Version; FreeMemory(); f.ReadByte ( &Version ); f.ReadInt ( &nHets ); if (nHets>0) { hetCompound = new PHetCompound[nHets]; for (i=0;iread ( f ); } } } MakeStreamFunctions(HetCompounds) // ==================== SSContainer ========================= PContainerClass SSContainer::MakeContainerClass ( int ClassID ) { switch (ClassID) { default : case ClassID_Template : return ClassContainer::MakeContainerClass(ClassID); case ClassID_Helix : return new Helix(); case ClassID_Turn : return new Turn (); } } MakeStreamFunctions(SSContainer) // ================ Helix =================== Helix::Helix() : ContainerClass() { InitHelix(); } Helix::Helix ( cpstr S ) : ContainerClass() { InitHelix(); ConvertPDBASCII ( S ); } Helix::Helix ( io::RPStream Object ) : ContainerClass(Object) { InitHelix(); } Helix::~Helix() { if (comment) delete[] comment; } void Helix::InitHelix() { serNum = 0; // serial number strcpy ( helixID ,"---" ); // helix ID strcpy ( initResName,"---" ); // name of the helix's initial residue strcpy ( initChainID,"" ); // chain ID for the chain // containing the helix initSeqNum = 0; // sequence number of the initial // residue strcpy ( initICode ,"" ); // insertion code of the initial // residue strcpy ( endResName ,"---" ); // name of the helix's terminal residue strcpy ( endChainID ,"" ); // chain ID for the chain // containing the helix endSeqNum = 0; // sequence number of the terminal // residue strcpy ( endICode ,"" ); // insertion code of the terminal // residue helixClass = 0; // helix class comment = NULL; // comment about the helix length = 0; // length of the helix } void Helix::PDBASCIIDump ( pstr S, int N ) { UNUSED_ARGUMENT(N); // makes the ASCII PDB OBSLTE line number N // from the class' data strcpy ( S,"HELIX" ); PadSpaces ( S,80 ); PutInteger ( &(S[7]) ,serNum ,3 ); strcpy_n1 ( &(S[11]),helixID ,3 ); strcpy_n1 ( &(S[15]),initResName,3 ); if (initChainID[0]) S[19] = initChainID[0]; PutIntIns ( &(S[21]),initSeqNum ,4,initICode ); strcpy_n1 ( &(S[27]),endResName ,3 ); if (endChainID[0]) S[31] = endChainID[0]; PutIntIns ( &(S[33]),endSeqNum ,4,endICode ); PutInteger ( &(S[38]),helixClass ,2 ); if (comment) strcpy_n ( &(S[40]),comment ,30 ); PutInteger ( &(S[71]),length ,5 ); } void AddStructConfTags ( mmcif::PLoop Loop ) { Loop->AddLoopTag ( CIFTAG_CONF_TYPE_ID ); Loop->AddLoopTag ( CIFTAG_ID ); Loop->AddLoopTag ( CIFTAG_PDB_ID ); Loop->AddLoopTag ( CIFTAG_BEG_LABEL_COMP_ID ); Loop->AddLoopTag ( CIFTAG_BEG_LABEL_ASYM_ID ); Loop->AddLoopTag ( CIFTAG_BEG_LABEL_SEQ_ID ); Loop->AddLoopTag ( CIFTAG_NDB_BEG_LABEL_INS_CODE_PDB ); Loop->AddLoopTag ( CIFTAG_END_LABEL_COMP_ID ); Loop->AddLoopTag ( CIFTAG_END_LABEL_ASYM_ID ); Loop->AddLoopTag ( CIFTAG_END_LABEL_SEQ_ID ); Loop->AddLoopTag ( CIFTAG_NDB_END_LABEL_INS_CODE_PDB ); Loop->AddLoopTag ( CIFTAG_NDB_HELIX_CLASS_PDB ); Loop->AddLoopTag ( CIFTAG_DETAILS ); Loop->AddLoopTag ( CIFTAG_NDB_LENGTH ); } #define HelixTypeID "HELX_P" void Helix::MakeCIF ( mmcif::PData CIF, int N ) { UNUSED_ARGUMENT(N); mmcif::PLoop Loop; int RC; RC = CIF->AddLoop ( CIFCAT_STRUCT_CONF,Loop ); if (RC!=mmcif::CIFRC_Ok) // the category was (re)created, provide tags AddStructConfTags ( Loop ); Loop->AddString ( pstr(HelixTypeID) ); Loop->AddInteger ( serNum ); Loop->AddString ( helixID ); Loop->AddString ( initResName ); Loop->AddString ( initChainID ); Loop->AddInteger ( initSeqNum ); Loop->AddString ( initICode,true ); Loop->AddString ( endResName ); Loop->AddString ( endChainID ); Loop->AddInteger ( endSeqNum ); Loop->AddString ( endICode ,true ); Loop->AddInteger ( helixClass ); Loop->AddString ( comment ); Loop->AddInteger ( length ); } ERROR_CODE Helix::ConvertPDBASCII ( cpstr S ) { char L[100]; GetInteger ( serNum ,&(S[7]) ,3 ); strcpy_ncss ( helixID ,&(S[11]),3 ); strcpy_ncss ( initResName,&(S[15]),3 ); strcpy_ncss ( initChainID,&(S[19]),1 ); GetIntIns ( initSeqNum,initICode,&(S[21]),4 ); strcpy_ncss ( endResName ,&(S[27]),3 ); strcpy_ncss ( endChainID ,&(S[31]),1 ); GetIntIns ( endSeqNum ,endICode ,&(S[33]),4 ); GetInteger ( helixClass ,&(S[38]),2 ); strcpy_ncss ( L ,&(S[40]),30 ); CreateCopy ( comment ,L ); GetInteger ( length ,&(S[71]),5 ); return Error_NoError; } ERROR_CODE Helix::GetCIF ( mmcif::PData CIF, int & n ) { mmcif::PLoop Loop; int RC,l; pstr F; bool Done; ERROR_CODE rc; Loop = CIF->GetLoop ( CIFCAT_STRUCT_CONF ); if (!Loop) { n = -1; // signal to finish processing of this structure return Error_EmptyCIF; } l = Loop->GetLoopLength(); Done = n>=l; while (!Done) { F = Loop->GetString ( CIFTAG_CONF_TYPE_ID,n,RC ); if ((!RC) && F) Done = (strcmp(F,HelixTypeID)==0); else Done = false; if (!Done) { n++; Done = n>=l; } } if (n>=l) { n = -1; // finish processing of Helix return Error_EmptyCIF; } Loop->DeleteField ( CIFTAG_CONF_TYPE_ID,n ); rc = CIFGetInteger ( serNum,Loop,CIFTAG_ID,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( helixID ,Loop,CIFTAG_PDB_ID, n,sizeof(helixID),pstr(" ") ); CIFGetString ( initResName,Loop,CIFTAG_BEG_LABEL_COMP_ID, n,sizeof(initResName),pstr(" ") ); CIFGetString ( initChainID,Loop,CIFTAG_BEG_LABEL_ASYM_ID, n,sizeof(initChainID),pstr("") ); CIFGetString ( initICode ,Loop,CIFTAG_NDB_BEG_LABEL_INS_CODE_PDB, n,sizeof(initICode),pstr("") ); if (CIFGetInteger(initSeqNum,Loop,CIFTAG_BEG_LABEL_SEQ_ID,n)) if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( endResName,Loop,CIFTAG_END_LABEL_COMP_ID, n,sizeof(endResName),pstr(" ") ); CIFGetString ( endChainID,Loop,CIFTAG_END_LABEL_ASYM_ID, n,sizeof(endChainID),pstr("") ); CIFGetString ( endICode ,Loop,CIFTAG_NDB_END_LABEL_INS_CODE_PDB, n,sizeof(endICode),pstr("") ); rc = CIFGetInteger(endSeqNum,Loop,CIFTAG_END_LABEL_SEQ_ID,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; rc = CIFGetInteger(helixClass,Loop,CIFTAG_NDB_HELIX_CLASS_PDB,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CreateCopy ( comment,Loop->GetString(CIFTAG_DETAILS,n,RC)); Loop->DeleteField ( CIFTAG_DETAILS,n ); rc = CIFGetInteger ( length,Loop,CIFTAG_NDB_LENGTH,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; n++; return Error_NoError; } void Helix::Copy ( PContainerClass Helix ) { serNum = PHelix(Helix)->serNum; initSeqNum = PHelix(Helix)->initSeqNum; endSeqNum = PHelix(Helix)->endSeqNum; helixClass = PHelix(Helix)->helixClass; length = PHelix(Helix)->length; strcpy ( helixID ,PHelix(Helix)->helixID ); strcpy ( initResName,PHelix(Helix)->initResName ); strcpy ( initChainID,PHelix(Helix)->initChainID ); strcpy ( initICode ,PHelix(Helix)->initICode ); strcpy ( endResName ,PHelix(Helix)->endResName ); strcpy ( endChainID ,PHelix(Helix)->endChainID ); strcpy ( endICode ,PHelix(Helix)->endICode ); CreateCopy ( comment,PHelix(Helix)->comment ); } void Helix::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &serNum ); f.WriteInt ( &initSeqNum ); f.WriteInt ( &endSeqNum ); f.WriteInt ( &helixClass ); f.WriteInt ( &length ); f.WriteTerLine ( helixID ,false ); f.WriteTerLine ( initResName,false ); f.WriteTerLine ( initChainID,false ); f.WriteTerLine ( initICode ,false ); f.WriteTerLine ( endResName ,false ); f.WriteTerLine ( endChainID ,false ); f.WriteTerLine ( endICode ,false ); f.CreateWrite ( comment ); } void Helix::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.ReadInt ( &serNum ); f.ReadInt ( &initSeqNum ); f.ReadInt ( &endSeqNum ); f.ReadInt ( &helixClass ); f.ReadInt ( &length ); f.ReadTerLine ( helixID ,false ); f.ReadTerLine ( initResName,false ); f.ReadTerLine ( initChainID,false ); f.ReadTerLine ( initICode ,false ); f.ReadTerLine ( endResName ,false ); f.ReadTerLine ( endChainID ,false ); f.ReadTerLine ( endICode ,false ); f.CreateRead ( comment ); } MakeStreamFunctions(Helix) // ================ Strand ===================== Strand::Strand () : io::Stream() { InitStrand(); } Strand::Strand ( io::RPStream Object ) : io::Stream(Object) { InitStrand(); } Strand::~Strand() { } void Strand::InitStrand() { initSeqNum = MinInt4; endSeqNum = MinInt4; sense = 0; curResSeq = MinInt4; prevResSeq = MinInt4; strandNo = 0; strcpy ( sheetID ,"sheet_0" ); strcpy ( initResName," " ); strcpy ( initChainID,"" ); strcpy ( initICode ,"" ); strcpy ( endResName ," " ); strcpy ( endChainID ,"" ); strcpy ( endICode ,"" ); strcpy ( curAtom ," " ); strcpy ( curResName ," " ); strcpy ( curChainID ,"" ); strcpy ( curICode ,"" ); strcpy ( prevAtom ," " ); strcpy ( prevResName," " ); strcpy ( prevChainID,"" ); strcpy ( prevICode ,"" ); } void Strand::PDBASCIIDump ( pstr S ) { // Finishes making the ASCII PDB SHEET line number N // from the class' data. Making is initiated by Sheet. strcpy_n1 ( &(S[17]),initResName,3 ); if (initChainID[0]) S[21] = initChainID[0]; PutIntIns ( &(S[22]),initSeqNum ,4,initICode ); strcpy_n1 ( &(S[28]),endResName ,3 ); if (endChainID[0]) S[32] = endChainID[0]; PutIntIns ( &(S[33]),endSeqNum ,4,endICode ); PutInteger ( &(S[38]),sense ,2 ); strcpy_n1 ( &(S[41]),curAtom ,4 ); strcpy_n1 ( &(S[45]),curResName ,3 ); if (curChainID[0]) S[49] = curChainID[0]; PutIntIns ( &(S[50]),curResSeq ,4,curICode ); strcpy_n1 ( &(S[56]),prevAtom ,4 ); strcpy_n1 ( &(S[60]),prevResName,3 ); if (prevChainID[0]) S[64] = prevChainID[0]; PutIntIns ( &(S[65]),prevResSeq ,4,prevICode ); } void Strand::MakeCIF ( mmcif::PData CIF ) { mmcif::PLoop Loop; int RC; RC = CIF->AddLoop ( CIFCAT_STRUCT_SHEET_RANGE,Loop ); if (RC!=mmcif::CIFRC_Ok) { // the category was (re)created, provide tags Loop->AddLoopTag ( CIFTAG_SHEET_ID ); Loop->AddLoopTag ( CIFTAG_ID ); Loop->AddLoopTag ( CIFTAG_BEG_LABEL_COMP_ID ); Loop->AddLoopTag ( CIFTAG_BEG_LABEL_ASYM_ID ); Loop->AddLoopTag ( CIFTAG_BEG_LABEL_SEQ_ID ); Loop->AddLoopTag ( CIFTAG_NDB_BEG_LABEL_INS_CODE_PDB ); Loop->AddLoopTag ( CIFTAG_END_LABEL_COMP_ID ); Loop->AddLoopTag ( CIFTAG_END_LABEL_ASYM_ID ); Loop->AddLoopTag ( CIFTAG_END_LABEL_SEQ_ID ); Loop->AddLoopTag ( CIFTAG_NDB_END_LABEL_INS_CODE_PDB ); } Loop->AddString ( sheetID ); Loop->AddInteger ( strandNo ); Loop->AddString ( initResName ); Loop->AddString ( initChainID ); Loop->AddInteger ( initSeqNum ); Loop->AddString ( initICode,true ); Loop->AddString ( endResName ); Loop->AddString ( endChainID ); Loop->AddInteger ( endSeqNum ); Loop->AddString ( endICode ,true ); } ERROR_CODE Strand::ConvertPDBASCII ( cpstr S ) { GetInteger ( strandNo ,&(S[7]) ,3 ); strcpy_ncss ( sheetID ,&(S[11]) ,3 ); strcpy_ncss ( initResName,&(S[17]) ,3 ); strcpy_ncss ( initChainID,&(S[21]) ,1 ); GetIntIns ( initSeqNum ,initICode,&(S[22]),4 ); strcpy_ncss ( endResName ,&(S[28]) ,3 ); strcpy_ncss ( endChainID ,&(S[32]) ,1 ); GetIntIns ( endSeqNum ,endICode ,&(S[33]),4 ); GetInteger ( sense ,&(S[38]) ,2 ); GetString ( curAtom ,&(S[41]) ,4 ); strcpy_ncss ( curResName ,&(S[45]) ,3 ); strcpy_ncss ( curChainID ,&(S[49]) ,1 ); GetIntIns ( curResSeq ,curICode ,&(S[50]),4 ); GetString ( prevAtom ,&(S[56]) ,4 ); strcpy_ncss ( prevResName,&(S[60]) ,3 ); strcpy_ncss ( prevChainID,&(S[64]) ,1 ); GetIntIns ( prevResSeq ,prevICode,&(S[65]),4 ); return Error_NoError; } int Strand::GetCIF ( mmcif::PData CIF, cpstr sheet_id ) { mmcif::PLoop Loop; int RC,l,i,sNo; pstr F; Loop = CIF->GetLoop ( CIFCAT_STRUCT_SHEET_RANGE ); if (Loop) { l = Loop->GetLoopLength(); i = 0; while (iGetString ( CIFTAG_SHEET_ID,i,RC ); if (F && (!RC)) { if (!strcmp(F,sheet_id)) { strcpy ( sheetID,sheet_id ); if (CIFGetInteger(sNo,Loop,CIFTAG_ID,i)) return i; if (sNo==strandNo) { CIFGetString ( initResName,Loop,CIFTAG_BEG_LABEL_COMP_ID, i,sizeof(initResName),pstr(" ") ); CIFGetString ( initChainID,Loop,CIFTAG_BEG_LABEL_ASYM_ID, i,sizeof(initChainID),pstr("") ); CIFGetString ( initICode,Loop, CIFTAG_NDB_BEG_LABEL_INS_CODE_PDB, i,sizeof(initICode),pstr("") ); if (CIFGetInteger(initSeqNum,Loop, CIFTAG_BEG_LABEL_SEQ_ID,i)) return i; CIFGetString ( endResName,Loop,CIFTAG_END_LABEL_COMP_ID, i,sizeof(endResName),pstr(" ") ); CIFGetString ( endChainID,Loop,CIFTAG_END_LABEL_ASYM_ID, i,sizeof(endChainID),pstr("") ); CIFGetString ( endICode ,Loop, CIFTAG_NDB_END_LABEL_INS_CODE_PDB, i,sizeof(endICode),pstr("") ); if (CIFGetInteger(endSeqNum,Loop, CIFTAG_END_LABEL_SEQ_ID,i)) return i; Loop->DeleteRow ( i ); i = l+100; // break the loop } } } i++; } } return 0; } void Strand::Copy ( PStrand Strand ) { initSeqNum = Strand->initSeqNum; endSeqNum = Strand->endSeqNum; sense = Strand->sense; curResSeq = Strand->curResSeq; prevResSeq = Strand->prevResSeq; strcpy ( initResName,Strand->initResName ); strcpy ( initChainID,Strand->initChainID ); strcpy ( initICode ,Strand->initICode ); strcpy ( endResName ,Strand->endResName ); strcpy ( endChainID ,Strand->endChainID ); strcpy ( endICode ,Strand->endICode ); strcpy ( curAtom ,Strand->curAtom ); strcpy ( curResName ,Strand->curResName ); strcpy ( curChainID ,Strand->curChainID ); strcpy ( curICode ,Strand->curICode ); strcpy ( prevAtom ,Strand->prevAtom ); strcpy ( prevResName,Strand->prevResName ); strcpy ( prevChainID,Strand->prevChainID ); strcpy ( prevICode ,Strand->prevICode ); } void Strand::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &initSeqNum ); f.WriteInt ( &endSeqNum ); f.WriteInt ( &sense ); f.WriteInt ( &curResSeq ); f.WriteInt ( &prevResSeq ); f.WriteTerLine ( initResName,false ); f.WriteTerLine ( initChainID,false ); f.WriteTerLine ( initICode ,false ); f.WriteTerLine ( endResName ,false ); f.WriteTerLine ( endChainID ,false ); f.WriteTerLine ( endICode ,false ); f.WriteTerLine ( curAtom ,false ); f.WriteTerLine ( curResName ,false ); f.WriteTerLine ( curChainID ,false ); f.WriteTerLine ( curICode ,false ); f.WriteTerLine ( prevAtom ,false ); f.WriteTerLine ( prevResName,false ); f.WriteTerLine ( prevChainID,false ); f.WriteTerLine ( prevICode ,false ); } void Strand::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.ReadInt ( &initSeqNum ); f.ReadInt ( &endSeqNum ); f.ReadInt ( &sense ); f.ReadInt ( &curResSeq ); f.ReadInt ( &prevResSeq ); f.ReadTerLine ( initResName,false ); f.ReadTerLine ( initChainID,false ); f.ReadTerLine ( initICode ,false ); f.ReadTerLine ( endResName ,false ); f.ReadTerLine ( endChainID ,false ); f.ReadTerLine ( endICode ,false ); f.ReadTerLine ( curAtom ,false ); f.ReadTerLine ( curResName ,false ); f.ReadTerLine ( curChainID ,false ); f.ReadTerLine ( curICode ,false ); f.ReadTerLine ( prevAtom ,false ); f.ReadTerLine ( prevResName,false ); f.ReadTerLine ( prevChainID,false ); f.ReadTerLine ( prevICode ,false ); } MakeStreamFunctions(Strand) // ================ Sheet =================== Sheet::Sheet() : io::Stream() { InitSheet(); } Sheet::Sheet ( io::RPStream Object ) : io::Stream(Object) { InitSheet(); } Sheet::~Sheet() { FreeMemory(); } void Sheet::InitSheet() { nStrands = 0; sheetID[0] = char(0); strand = NULL; } void Sheet::FreeMemory() { int i; if (strand) { for (i=0;iPDBASCIIDump ( S ); f.WriteLine ( S ); } } void Sheet::OrderSheet() { int i,k; PPStrand strand1; k = 0; for (i=0;iAddLoop ( CIFCAT_STRUCT_SHEET,Loop ); if (RC!=mmcif::CIFRC_Ok) { // the category was (re)created, provide tags Loop->AddLoopTag ( CIFTAG_SHEET_ID ); Loop->AddLoopTag ( CIFTAG_NUMBER_STRANDS ); } Loop->AddString ( sheetID ); Loop->AddInteger ( nStrands ); for (i=0;iMakeCIF ( CIF ); if (strand[i]->sense!=0) isSense = true; } if (nStrands>1) { if (isSense) { RC = CIF->AddLoop ( CIFCAT_STRUCT_SHEET_ORDER,Loop ); if (RC!=mmcif::CIFRC_Ok) { // the category was (re)created, provide tags Loop->AddLoopTag ( CIFTAG_SHEET_ID ); Loop->AddLoopTag ( CIFTAG_RANGE_ID_1 ); Loop->AddLoopTag ( CIFTAG_RANGE_ID_2 ); Loop->AddLoopTag ( CIFTAG_SENSE ); } for (i=1;iAddString ( sheetID ); Loop->AddInteger ( strand[i-1]->strandNo ); Loop->AddInteger ( strand[i] ->strandNo ); if (strand[i]->sense>0) Loop->AddString ( pstr("parallel") ); else Loop->AddString ( pstr("anti-parallel") ); } } RC = CIF->AddLoop ( CIFCAT_STRUCT_SHEET_HBOND,Loop ); if (RC!=mmcif::CIFRC_Ok) { // the category was (re)created, provide tags Loop->AddLoopTag ( CIFTAG_SHEET_ID ); Loop->AddLoopTag ( CIFTAG_RANGE_ID_1 ); Loop->AddLoopTag ( CIFTAG_RANGE_ID_2 ); Loop->AddLoopTag ( CIFTAG_RANGE_1_BEG_LABEL_ATOM_ID ); Loop->AddLoopTag ( CIFTAG_NDB_RANGE_1_BEG_LABEL_COMP_ID ); Loop->AddLoopTag ( CIFTAG_NDB_RANGE_1_BEG_LABEL_ASYM_ID ); Loop->AddLoopTag ( CIFTAG_RANGE_1_BEG_LABEL_SEQ_ID ); Loop->AddLoopTag ( CIFTAG_NDB_RANGE_1_BEG_LABEL_INS_CODE ); Loop->AddLoopTag ( CIFTAG_RANGE_1_END_LABEL_ATOM_ID ); Loop->AddLoopTag ( CIFTAG_NDB_RANGE_1_END_LABEL_COMP_ID ); Loop->AddLoopTag ( CIFTAG_NDB_RANGE_1_END_LABEL_ASYM_ID ); Loop->AddLoopTag ( CIFTAG_RANGE_1_END_LABEL_SEQ_ID ); Loop->AddLoopTag ( CIFTAG_NDB_RANGE_1_END_LABEL_INS_CODE ); } for (i=1;iAddString ( sheetID ); Loop->AddInteger ( strand[i-1]->strandNo ); Loop->AddInteger ( strand[i]->strandNo ); Loop->AddString ( strand[i]->curAtom ); Loop->AddString ( strand[i]->curResName ); Loop->AddString ( strand[i]->curChainID ); Loop->AddInteger ( strand[i]->curResSeq ); Loop->AddString ( strand[i]->curICode ,true ); Loop->AddString ( strand[i]->prevAtom ); Loop->AddString ( strand[i]->prevResName ); Loop->AddString ( strand[i]->prevChainID ); Loop->AddInteger ( strand[i]->prevResSeq ); Loop->AddString ( strand[i]->prevICode,true ); } } } ERROR_CODE Sheet::ConvertPDBASCII ( cpstr S ) { int i,k,ns; SheetID SID; PPStrand strand1; GetInteger ( k ,&(S[7]) ,3 ); strcpy_ncss ( SID,&(S[11]),3 ); GetInteger ( ns ,&(S[14]),2 ); // if (!SID[0]) return Error_NoSheetID; if (!sheetID[0]) strcpy ( sheetID,SID ); else if (strcmp(sheetID,SID)) return Error_WrongSheetID; if (k<=0) return Error_WrongStrandNo; ns = IMax(k,ns); if (!strand) { strand = new PStrand[ns]; for (i=0;inStrands) { strand1 = new PStrand[ns]; for (i=0;iConvertPDBASCII ( S ); } void Sheet::TryStrand ( int strand_no ) { int i,k; PPStrand strand1; k = -1; for (i=0;(istrandNo==strand_no) k = i; if (k<0) { strand1 = new PStrand[nStrands+1]; for (i=0;istrandNo = strand_no; nStrands++; } } void Sheet::CIFFindStrands ( mmcif::PData CIF, cpstr Category ) { // just look for all strands mentioned for the sheet mmcif::PLoop Loop; pstr F; int RC,i,l,sNo; Loop = CIF->GetLoop ( Category ); if (Loop) { l = Loop->GetLoopLength(); for (i=0;iGetString ( CIFTAG_SHEET_ID,i,RC ); if (F && (!RC)) { if (!strcmp(F,sheetID)) { if (!Loop->GetInteger(sNo,CIFTAG_ID,i)) TryStrand ( sNo ); if (!Loop->GetInteger(sNo,CIFTAG_RANGE_ID_1,i)) TryStrand ( sNo ); if (!Loop->GetInteger(sNo,CIFTAG_RANGE_ID_2,i)) TryStrand ( sNo ); } } } } } int Sheet::GetStrand ( int strand_no ) { int i; for (i=0;istrandNo==strand_no) return i; } return -1; } int Sheet::GetCIF ( mmcif::PData CIF ) { mmcif::PLoop Loop; int i,ns,l,k,k2,RC,sNo; pstr F; ivector pair; bool Ok; pair = NULL; // First find all strands and create // the corresponding classes. The CIF fields // are not removed at this stage. CIFFindStrands ( CIF,CIFCAT_STRUCT_SHEET_ORDER ); CIFFindStrands ( CIF,CIFCAT_STRUCT_SHEET_RANGE ); CIFFindStrands ( CIF,CIFCAT_STRUCT_SHEET_HBOND ); // Check number of strands Loop = CIF->GetLoop ( CIFCAT_STRUCT_SHEET ); if (Loop) { l = Loop->GetLoopLength(); i = 0; while (iGetString ( CIFTAG_SHEET_ID,i,RC ); if (F && (!RC)) { if (!strcmp(F,sheetID)) { RC = CIFGetInteger1 ( ns,Loop,CIFTAG_NUMBER_STRANDS,i ); if ((!RC) && (ns!=nStrands)) return Error_WrongNumberOfStrands; Loop->DeleteRow ( i ); i = l+100; // break loop } } i++; } } // Read each strand RC = 0; for (i=0;(iGetCIF ( CIF,sheetID ); if (RC) return RC; if (nStrands>1) { GetVectorMemory ( pair,nStrands,0 ); for (i=0;iGetLoop ( CIFCAT_STRUCT_SHEET_ORDER ); if (Loop) { Ok = true; l = Loop->GetLoopLength(); for (i=0;(iGetString ( CIFTAG_SHEET_ID,i,RC ); if (F && (!RC)) { if (!strcmp(F,sheetID)) { if (!Loop->GetInteger(sNo,CIFTAG_RANGE_ID_1,i)) { k = GetStrand ( sNo ); if ((k>=0) && (!Loop->GetInteger(sNo,CIFTAG_RANGE_ID_2,i))) { pair[k] = GetStrand ( sNo ); if (pair[k]>=0) { F = Loop->GetString ( CIFTAG_SENSE,i,RC ); if (F && (!RC)) { if (!strcasecmp(F,"anti-parallel")) strand[pair[k]]->sense = -1; else if (!strcasecmp(F,"parallel")) strand[pair[k]]->sense = 1; } Loop->DeleteRow ( i ); } else Ok = false; } else Ok = false; } else Ok = false; } } } if (!Ok) { FreeVectorMemory ( pair,0 ); return Error_WrongSheetOrder; } } Loop = CIF->GetLoop ( CIFCAT_STRUCT_SHEET_HBOND ); if (Loop) { Ok = true; l = Loop->GetLoopLength(); for (i=0;(iGetString ( CIFTAG_SHEET_ID,i,RC ); if (F && (!RC)) { if (!strcmp(F,sheetID)) { if (!Loop->GetInteger(sNo,CIFTAG_RANGE_ID_1,i)) { k = GetStrand ( sNo ); if ((k>=0) && (!Loop->GetInteger(sNo,CIFTAG_RANGE_ID_1,i))) { k2 = GetStrand ( sNo ); if (k2>=0) { if (pair[k]==k2) { CIFGetString ( strand[k2]->curAtom,Loop, CIFTAG_RANGE_1_BEG_LABEL_ATOM_ID, i,sizeof(strand[k2]->curAtom), pstr(" ") ); CIFGetString ( strand[k2]->curResName,Loop, CIFTAG_NDB_RANGE_1_BEG_LABEL_COMP_ID, i,sizeof(strand[k2]->curResName), pstr(" ") ); CIFGetString ( strand[k2]->curChainID,Loop, CIFTAG_NDB_RANGE_1_BEG_LABEL_ASYM_ID, i,sizeof(strand[k2]->curChainID), pstr(" ") ); if (CIFGetInteger(strand[k2]->curResSeq,Loop, CIFTAG_RANGE_1_BEG_LABEL_SEQ_ID,i)) { FreeVectorMemory ( pair,0 ); return i; } CIFGetString ( strand[k2]->curICode,Loop, CIFTAG_NDB_RANGE_1_BEG_LABEL_INS_CODE, i,sizeof(strand[k2]->curICode), pstr(" ") ); CIFGetString ( strand[k2]->prevAtom,Loop, CIFTAG_RANGE_1_END_LABEL_ATOM_ID, i,sizeof(strand[k2]->prevAtom), pstr(" ") ); CIFGetString ( strand[k2]->prevResName,Loop, CIFTAG_NDB_RANGE_1_END_LABEL_COMP_ID, i,sizeof(strand[k2]->prevResName), pstr(" ") ); CIFGetString ( strand[k2]->prevChainID,Loop, CIFTAG_NDB_RANGE_1_END_LABEL_ASYM_ID, i,sizeof(strand[k2]->prevChainID), pstr(" ") ); if (CIFGetInteger(strand[k2]->prevResSeq,Loop, CIFTAG_RANGE_1_END_LABEL_SEQ_ID,i)) { FreeVectorMemory ( pair,0 ); return i; } CIFGetString ( strand[k2]->prevICode,Loop, CIFTAG_NDB_RANGE_1_END_LABEL_INS_CODE, i,sizeof(strand[k2]->prevICode), pstr(" ") ); Loop->DeleteRow ( i ); } else Ok = false; } else Ok = false; } else Ok = false; } else Ok = false; } } } if (!Ok) { FreeVectorMemory ( pair,0 ); return Error_HBondInconsistency; } } } FreeVectorMemory ( pair,0 ); return 0; } void Sheet::Copy ( PSheet Sheet ) { int i; FreeMemory(); nStrands = Sheet->nStrands; if (nStrands>0) { strand = new PStrand[nStrands]; for (i=0;istrand[i]) { strand[i] = new Strand(); strand[i]->Copy ( Sheet->strand[i] ); } else strand[i] = NULL; } strcpy ( sheetID,Sheet->sheetID ); } void Sheet::write ( io::RFile f ) { int i; byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &nStrands ); for (i=0;i0) { strand = new PStrand[nStrands]; for (i=0;iPDBASCIIDump ( f ); } void Sheets::MakeCIF ( mmcif::PData CIF ) { int i; if (sheet) for (i=0;iMakeCIF ( CIF ); } ERROR_CODE Sheets::ConvertPDBASCII ( cpstr S ) { PPSheet sheet1; SheetID sheetID; int i,k; strcpy_ncss ( sheetID,&(S[11]),3 ); // if (!sheetID[0]) return Error_NoSheetID; k = -1; for (i=0;isheetID)) { k = i; break; } } if (k<0) { sheet1 = new PSheet[nSheets+1]; for (i=0;iConvertPDBASCII ( S ); } void Sheets::CIFFindSheets ( mmcif::PData CIF, cpstr Category ) { mmcif::PLoop Loop; int RC,i,j,k,l; pstr F; PPSheet sheet1; Loop = CIF->GetLoop ( Category ); if (Loop) { l = Loop->GetLoopLength(); for (i=0;iGetString ( CIFTAG_SHEET_ID,i,RC ); if (F && (!RC)) { k = -1; j = 0; while ((jsheetID)) k = j; } j++; } if (k<0) { sheet1 = new PSheet[nSheets+1]; for (i=0;isheetID,F ); nSheets++; } } } } } int Sheets::GetCIF ( mmcif::PData CIF ) { int i,RC; FreeMemory(); // First find all sheet names and create // the corresponding classes. The CIF fields // are not removed at this stage. CIFFindSheets ( CIF,CIFCAT_STRUCT_SHEET ); CIFFindSheets ( CIF,CIFCAT_STRUCT_SHEET_ORDER ); CIFFindSheets ( CIF,CIFCAT_STRUCT_SHEET_RANGE ); CIFFindSheets ( CIF,CIFCAT_STRUCT_SHEET_HBOND ); // Read each sheet i = 0; RC = 0; while ((iGetCIF ( CIF ); i++; } return RC; } void Sheets::Copy ( PSheets Sheets ) { int i; FreeMemory(); if (Sheets->nSheets>0) { nSheets = Sheets->nSheets; sheet = new PSheet[nSheets]; for (i=0;isheet[i]) { sheet[i] = new Sheet(); sheet[i]->Copy ( Sheets->sheet[i] ); } else sheet[i] = NULL; } } void Sheets::write ( io::RFile f ) { int i; byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &nSheets ); for (i=0;i0) { sheet = new PSheet[nSheets]; for (i=0;iAddLoop ( CIFCAT_STRUCT_CONF,Loop ); if (RC!=mmcif::CIFRC_Ok) // the category was (re)created, provide tags AddStructConfTags ( Loop ); Loop->AddString ( pstr(TurnTypeID) ); Loop->AddInteger ( serNum ); Loop->AddString ( turnID ); Loop->AddString ( initResName ); Loop->AddString ( initChainID ); Loop->AddInteger ( initSeqNum ); Loop->AddString ( initICode,true ); Loop->AddString ( endResName ); Loop->AddString ( endChainID ); Loop->AddInteger ( endSeqNum ); Loop->AddString ( endICode ,true ); Loop->AddNoData ( mmcif::CIF_NODATA_QUESTION ); Loop->AddString ( comment ); Loop->AddNoData ( mmcif::CIF_NODATA_QUESTION ); } ERROR_CODE Turn::ConvertPDBASCII ( cpstr S ) { char L[100]; GetInteger ( serNum ,&(S[7]) ,3 ); strcpy_ncss ( turnID ,&(S[11]),3 ); strcpy_ncss ( initResName,&(S[15]),3 ); strcpy_ncss ( initChainID,&(S[19]),1 ); GetIntIns ( initSeqNum,initICode,&(S[20]),4 ); strcpy_ncss ( endResName ,&(S[26]),3 ); strcpy_ncss ( endChainID ,&(S[30]),1 ); GetIntIns ( endSeqNum ,endICode ,&(S[31]),4 ); strcpy_ncss ( L ,&(S[40]),30 ); CreateCopy ( comment ,L ); return Error_NoError; } ERROR_CODE Turn::GetCIF ( mmcif::PData CIF, int & n ) { mmcif::PLoop Loop; int RC,l; pstr F; bool Done; ERROR_CODE rc; Loop = CIF->GetLoop ( CIFCAT_STRUCT_CONF ); if (!Loop) { n = -1; // signal to finish processing of this structure return Error_EmptyCIF; } l = Loop->GetLoopLength(); Done = n>=l; while (!Done) { F = Loop->GetString ( CIFTAG_CONF_TYPE_ID,n,RC ); if ((!RC) && F) Done = (strcmp(F,TurnTypeID)==0); else Done = false; if (!Done) { n++; Done = n>=l; } } if (n>=l) { n = -1; // finish processing of Turn return Error_EmptyCIF; } Loop->DeleteField ( CIFTAG_CONF_TYPE_ID,n ); rc = CIFGetInteger ( serNum,Loop,CIFTAG_ID,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( turnID,Loop,CIFTAG_PDB_ID,n, sizeof(turnID),pstr(" ") ); CIFGetString ( initResName,Loop,CIFTAG_BEG_LABEL_COMP_ID, n,sizeof(initResName),pstr(" ") ); CIFGetString ( initChainID,Loop,CIFTAG_BEG_LABEL_ASYM_ID, n,sizeof(initChainID),pstr(" ") ); CIFGetString ( initICode ,Loop,CIFTAG_NDB_BEG_LABEL_INS_CODE_PDB, n,sizeof(initICode),pstr(" ") ); rc = CIFGetInteger ( initSeqNum,Loop,CIFTAG_BEG_LABEL_SEQ_ID,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( endResName,Loop,CIFTAG_END_LABEL_COMP_ID, n,sizeof(endResName),pstr(" ") ); CIFGetString ( endChainID,Loop,CIFTAG_END_LABEL_ASYM_ID, n,sizeof(endChainID),pstr(" ") ); CIFGetString ( endICode ,Loop,CIFTAG_NDB_END_LABEL_INS_CODE_PDB, n,sizeof(endICode),pstr(" ") ); rc = CIFGetInteger ( endSeqNum,Loop,CIFTAG_END_LABEL_SEQ_ID,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CreateCopy ( comment,Loop->GetString(CIFTAG_DETAILS,n,RC)); Loop->DeleteField ( CIFTAG_DETAILS,n ); n++; return Error_NoError; } void Turn::Copy ( PContainerClass Turn ) { serNum = PTurn(Turn)->serNum; initSeqNum = PTurn(Turn)->initSeqNum; endSeqNum = PTurn(Turn)->endSeqNum; strcpy ( turnID ,PTurn(Turn)->turnID ); strcpy ( initResName,PTurn(Turn)->initResName ); strcpy ( initChainID,PTurn(Turn)->initChainID ); strcpy ( initICode ,PTurn(Turn)->initICode ); strcpy ( endResName ,PTurn(Turn)->endResName ); strcpy ( endChainID ,PTurn(Turn)->endChainID ); strcpy ( endICode ,PTurn(Turn)->endICode ); CreateCopy ( comment,PTurn(Turn)->comment ); } void Turn::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &serNum ); f.WriteInt ( &initSeqNum ); f.WriteInt ( &endSeqNum ); f.WriteTerLine ( turnID ,false ); f.WriteTerLine ( initResName,false ); f.WriteTerLine ( initChainID,false ); f.WriteTerLine ( initICode ,false ); f.WriteTerLine ( endResName ,false ); f.WriteTerLine ( endChainID ,false ); f.WriteTerLine ( endICode ,false ); f.CreateWrite ( comment ); } void Turn::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.ReadInt ( &serNum ); f.ReadInt ( &initSeqNum ); f.ReadInt ( &endSeqNum ); f.ReadTerLine ( turnID ,false ); f.ReadTerLine ( initResName,false ); f.ReadTerLine ( initChainID,false ); f.ReadTerLine ( initICode ,false ); f.ReadTerLine ( endResName ,false ); f.ReadTerLine ( endChainID ,false ); f.ReadTerLine ( endICode ,false ); f.CreateRead ( comment ); } MakeStreamFunctions(Turn) // =================== LinkContainer ======================== PContainerClass LinkContainer::MakeContainerClass ( int ClassID ) { switch (ClassID) { default : case ClassID_Template : return ClassContainer::MakeContainerClass(ClassID); case ClassID_Link : return new Link(); } } MakeStreamFunctions(LinkContainer) // ======================== Link =========================== Link::Link() : ContainerClass() { InitLink(); } Link::Link ( cpstr S ) : ContainerClass() { InitLink(); ConvertPDBASCII ( S ); } Link::Link ( io::RPStream Object ) : ContainerClass(Object) { InitLink(); } Link::~Link() {} void Link::InitLink() { strcpy ( atName1 ,"----" ); // name of 1st linked atom strcpy ( aloc1 ," " ); // alternative location of 1st atom strcpy ( resName1,"---" ); // residue name of 1st linked atom strcpy ( chainID1," " ); // chain ID of 1st linked atom seqNum1 = 0; // sequence number of 1st linked atom strcpy ( insCode1," " ); // insertion code of 1st linked atom strcpy ( atName2 ,"----" ); // name of 2nd linked atom strcpy ( aloc2 ," " ); // alternative location of 2nd atom strcpy ( resName2,"---" ); // residue name of 2nd linked atom strcpy ( chainID2," " ); // chain ID of 2nd linked atom seqNum2 = 0; // sequence number of 2nd linked atom strcpy ( insCode2," " ); // insertion code of 2nd linked atom s1 = 1; // sym id of 1st atom i1 = 5; j1 = 5; k1 = 5; s2 = 1; // sym id of 2nd atom i2 = 5; j2 = 5; k2 = 5; dist = -1.0; // no distance } void Link::PDBASCIIDump ( pstr S, int N ) { UNUSED_ARGUMENT(N); // makes the ASCII PDB OBSLTE line number N // from the class' data strcpy ( S,"LINK" ); PadSpaces ( S,80 ); strcpy_n1 ( &(S[12]),atName1 ,4 ); strcpy_n1 ( &(S[16]),aloc1 ,1 ); strcpy_n1 ( &(S[17]),resName1,3 ); strcpy_n1 ( &(S[21]),chainID1,1 ); PutIntIns ( &(S[22]),seqNum1 ,4,insCode1 ); strcpy_n1 ( &(S[42]),atName2 ,4 ); strcpy_n1 ( &(S[46]),aloc2 ,1 ); strcpy_n1 ( &(S[47]),resName2,3 ); strcpy_n1 ( &(S[51]),chainID2,1 ); PutIntIns ( &(S[52]),seqNum2 ,4,insCode2 ); PutInteger ( &(S[59]),s1,3 ); PutInteger ( &(S[62]),i1,1 ); PutInteger ( &(S[63]),j1,1 ); PutInteger ( &(S[64]),k1,1 ); PutInteger ( &(S[66]),s2,3 ); PutInteger ( &(S[69]),i2,1 ); PutInteger ( &(S[70]),j2,1 ); PutInteger ( &(S[71]),k2,1 ); if (dist>0.0) PutRealF ( &(S[73]),dist,5,3 ); } #define LinkTypeID "LINK" void AddStructConnTags ( mmcif::PLoop Loop ) { Loop->AddLoopTag ( CIFTAG_ID ); Loop->AddLoopTag ( CIFTAG_CONN_TYPE_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_ATOM_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR1_AUTH_ALT_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_COMP_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_ASYM_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_SEQ_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR1_PDB_INS_CODE ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_ATOM_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR2_AUTH_ALT_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_COMP_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_ASYM_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_SEQ_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR2_PDB_INS_CODE ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_SYMMETRY ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_SYMMETRY ); Loop->AddLoopTag ( CIFTAG_CONN_DIST ); } void Link::MakeCIF ( mmcif::PData CIF, int N ) { UNUSED_ARGUMENT(N); mmcif::PLoop Loop; char S[100]; int RC; RC = CIF->AddLoop ( CIFCAT_STRUCT_CONN,Loop ); if (RC!=mmcif::CIFRC_Ok) // the category was (re)created, provide tags AddStructConnTags ( Loop ); Loop->AddString ( "1" ); // should be a counter Loop->AddString ( pstr(LinkTypeID) ); Loop->AddString ( atName1 ); Loop->AddString ( aloc1 ); Loop->AddString ( resName1 ); Loop->AddString ( chainID1 ); Loop->AddInteger ( seqNum1 ); Loop->AddString ( insCode1 ); Loop->AddString ( atName2 ); Loop->AddString ( aloc2 ); Loop->AddString ( resName2 ); Loop->AddString ( chainID2 ); Loop->AddInteger ( seqNum2 ); Loop->AddString ( insCode2 ); sprintf ( S,"%i%i%i%i",s1,i1,j1,k1 ); Loop->AddString ( S ); sprintf ( S,"%i%i%i%i",s2,i2,j2,k2 ); Loop->AddString ( S ); Loop->AddReal ( dist ); } ERROR_CODE Link::ConvertPDBASCII ( cpstr S ) { GetString ( atName1 ,&(S[12]),4 ); strcpy_ncss ( aloc1 ,&(S[16]),1 ); strcpy_ncss ( resName1,&(S[17]),3 ); strcpy_ncss ( chainID1,&(S[21]),1 ); GetIntIns ( seqNum1,insCode1,&(S[22]),4 ); GetString ( atName2 ,&(S[42]),4 ); strcpy_ncss ( aloc2 ,&(S[46]),1 ); strcpy_ncss ( resName2,&(S[47]),3 ); strcpy_ncss ( chainID2,&(S[51]),1 ); GetIntIns ( seqNum2,insCode2,&(S[52]),4 ); GetInteger ( s1,&(S[59]),3 ); GetInteger ( i1,&(S[62]),1 ); GetInteger ( j1,&(S[63]),1 ); GetInteger ( k1,&(S[64]),1 ); GetInteger ( s2,&(S[66]),3 ); GetInteger ( i2,&(S[69]),1 ); GetInteger ( j2,&(S[70]),1 ); GetInteger ( k2,&(S[71]),1 ); if (!GetReal(dist,&(S[73]),5)) dist = -1.0; return Error_NoError; } ERROR_CODE Link::GetCIF ( mmcif::PData CIF, int & n ) { mmcif::PLoop Loop; pstr F; char S[100]; int RC,l; bool Done; ERROR_CODE rc; Loop = CIF->GetLoop ( CIFCAT_STRUCT_CONN ); if (!Loop) { n = -1; // signal to finish processing of this structure return Error_EmptyCIF; } l = Loop->GetLoopLength(); Done = (n>=l); while (!Done) { F = Loop->GetString ( CIFTAG_CONN_TYPE_ID,n,RC ); if ((!RC) && F) Done = (strcmp(F,LinkTypeID)==0); else Done = false; if (!Done) { n++; Done = (n>=l); } } if (n>=l) { n = -1; // finish processing of Turn return Error_EmptyCIF; } Loop->DeleteField ( CIFTAG_CONN_TYPE_ID,n ); // CIFGetInteger ( l,Loop,CIFTAG_ID,n ); CIFGetString ( atName1,Loop,CIFTAG_CONN_PTNR1_AUTH_ATOM_ID,n, sizeof(atName1),pstr(" ") ); CIFGetString ( aloc1,Loop,CIFTAG_CONN_PDBX_PTNR1_AUTH_ALT_ID,n, sizeof(aloc1),pstr(" ") ); CIFGetString ( resName1,Loop,CIFTAG_CONN_PTNR1_AUTH_COMP_ID,n, sizeof(resName1),pstr(" ") ); CIFGetString ( chainID1,Loop,CIFTAG_CONN_PTNR1_AUTH_ASYM_ID,n, sizeof(chainID1),pstr(" ") ); rc = CIFGetInteger ( seqNum1,Loop,CIFTAG_CONN_PTNR1_AUTH_SEQ_ID,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( insCode1,Loop,CIFTAG_CONN_PDBX_PTNR1_PDB_INS_CODE, n,sizeof(insCode1),pstr(" ") ); CIFGetString ( atName2,Loop,CIFTAG_CONN_PTNR2_AUTH_ATOM_ID,n, sizeof(atName2),pstr(" ") ); CIFGetString ( aloc2,Loop,CIFTAG_CONN_PDBX_PTNR2_AUTH_ALT_ID,n, sizeof(aloc2),pstr(" ") ); CIFGetString ( resName2,Loop,CIFTAG_CONN_PTNR2_AUTH_COMP_ID,n, sizeof(resName2),pstr(" ") ); CIFGetString ( chainID2,Loop,CIFTAG_CONN_PTNR2_AUTH_ASYM_ID,n, sizeof(chainID2),pstr(" ") ); rc = CIFGetInteger ( seqNum2,Loop,CIFTAG_CONN_PTNR2_AUTH_SEQ_ID,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( insCode2,Loop,CIFTAG_CONN_PDBX_PTNR2_PDB_INS_CODE, n,sizeof(insCode2),pstr(" ") ); CIFGetString ( S,Loop,CIFTAG_CONN_PTNR1_SYMMETRY,n, sizeof(S),pstr("") ); if (S[0]) { l = strlen(S)-1; k1 = int(S[l--]) - int('0'); j1 = int(S[l--]) - int('0'); i1 = int(S[l--]) - int('0'); S[l] = char(0); s1 = atoi(S); } CIFGetString ( S,Loop,CIFTAG_CONN_PTNR2_SYMMETRY,n, sizeof(S),pstr("") ); if (S[0]) { l = strlen(S)-1; k2 = int(S[l--]) - int('0'); j2 = int(S[l--]) - int('0'); i2 = int(S[l--]) - int('0'); S[l] = char(0); s2 = atoi(S); } rc = CIFGetReal ( dist,Loop,CIFTAG_CONN_DIST,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; n++; return Error_NoError; } void Link::Copy ( PContainerClass Link ) { strcpy ( atName1 ,PLink(Link)->atName1 ); strcpy ( aloc1 ,PLink(Link)->aloc1 ); strcpy ( resName1,PLink(Link)->resName1 ); strcpy ( chainID1,PLink(Link)->chainID1 ); seqNum1 = PLink(Link)->seqNum1; strcpy ( insCode1,PLink(Link)->insCode1 ); strcpy ( atName2 ,PLink(Link)->atName2 ); strcpy ( aloc2 ,PLink(Link)->aloc2 ); strcpy ( resName2,PLink(Link)->resName2 ); strcpy ( chainID2,PLink(Link)->chainID2 ); seqNum2 = PLink(Link)->seqNum2; strcpy ( insCode2,PLink(Link)->insCode2 ); s1 = PLink(Link)->s1; i1 = PLink(Link)->i1; j1 = PLink(Link)->j1; k1 = PLink(Link)->k1; s2 = PLink(Link)->s2; i2 = PLink(Link)->i2; j2 = PLink(Link)->j2; k2 = PLink(Link)->k2; dist = PLink(Link)->dist; } void Link::write ( io::RFile f ) { byte Version=2; f.WriteByte ( &Version ); f.WriteTerLine ( atName1 ,false ); f.WriteTerLine ( aloc1 ,false ); f.WriteTerLine ( resName1,false ); f.WriteTerLine ( chainID1,false ); f.WriteInt ( &seqNum1 ); f.WriteTerLine ( insCode1,false ); f.WriteTerLine ( atName2 ,false ); f.WriteTerLine ( aloc2 ,false ); f.WriteTerLine ( resName2,false ); f.WriteTerLine ( chainID2,false ); f.WriteInt ( &seqNum2 ); f.WriteTerLine ( insCode2,false ); f.WriteInt ( &s1 ); f.WriteInt ( &i1 ); f.WriteInt ( &j1 ); f.WriteInt ( &k1 ); f.WriteInt ( &s2 ); f.WriteInt ( &i2 ); f.WriteInt ( &j2 ); f.WriteInt ( &k2 ); f.WriteReal ( &dist ); } void Link::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.ReadTerLine ( atName1 ,false ); f.ReadTerLine ( aloc1 ,false ); f.ReadTerLine ( resName1,false ); f.ReadTerLine ( chainID1,false ); f.ReadInt ( &seqNum1 ); f.ReadTerLine ( insCode1,false ); f.ReadTerLine ( atName2 ,false ); f.ReadTerLine ( aloc2 ,false ); f.ReadTerLine ( resName2,false ); f.ReadTerLine ( chainID2,false ); f.ReadInt ( &seqNum2 ); f.ReadTerLine ( insCode2,false ); f.ReadInt ( &s1 ); f.ReadInt ( &i1 ); f.ReadInt ( &j1 ); f.ReadInt ( &k1 ); f.ReadInt ( &s2 ); f.ReadInt ( &i2 ); f.ReadInt ( &j2 ); f.ReadInt ( &k2 ); if (Version>1) f.ReadReal ( &dist ); } MakeStreamFunctions(Link) // =================== LinkRContainer ======================= PContainerClass LinkRContainer::MakeContainerClass ( int ClassID ) { switch (ClassID) { default : case ClassID_Template : return ClassContainer::MakeContainerClass(ClassID); case ClassID_LinkR : return new LinkR(); } } MakeStreamFunctions(LinkRContainer) // ======================== LinkR =========================== LinkR::LinkR() : ContainerClass() { InitLinkR(); } LinkR::LinkR ( cpstr S ) : ContainerClass() { InitLinkR(); ConvertPDBASCII ( S ); } LinkR::LinkR ( io::RPStream Object ) : ContainerClass(Object) { InitLinkR(); } LinkR::~LinkR() {} void LinkR::InitLinkR() { strcpy ( linkRID ,"----" ); // link name strcpy ( atName1 ,"----" ); // name of 1st linked atom strcpy ( aloc1 ," " ); // alternative location of 1st atom strcpy ( resName1,"---" ); // residue name of 1st linked atom strcpy ( chainID1," " ); // chain ID of 1st linked atom seqNum1 = 0; // sequence number of 1st linked atom strcpy ( insCode1," " ); // insertion code of 1st linked atom strcpy ( atName2 ,"----" ); // name of 2nd linked atom strcpy ( aloc2 ," " ); // alternative location of 2nd atom strcpy ( resName2,"---" ); // residue name of 2nd linked atom strcpy ( chainID2," " ); // chain ID of 2nd linked atom seqNum2 = 0; // sequence number of 2nd linked atom strcpy ( insCode2," " ); // insertion code of 2nd linked atom dist = 0.0; // link distance } /* LINK LYS A 27 PLP A 255 PLPLYS LINK MAN S 3 MAN S 4 BETA1-4 LINK C6 BBEN B 1 O1 BMAF S 2 BEN-MAF LINK OE2 AGLU A 320 C1 AMAF S 2 GLU-MAF LINK OE2 GLU A 67 1.895 ZN ZN R 5 GLU-ZN LINK NE2 HIS A 71 2.055 ZN ZN R 5 HIS-ZN LINK O ARG A 69 2.240 NA NA R 9 ARG-NA 012345678901234567890123456789012345678901234567890123456789012345678901234567890 1 2 3 4 5 6 7 */ void LinkR::PDBASCIIDump ( pstr S, int N ) { UNUSED_ARGUMENT(N); // makes the ASCII PDB OBSLTE line number N // from the class' data strcpy ( S,"LINKR" ); PadSpaces ( S,80 ); strcpy_n1 ( &(S[12]),atName1 ,4 ); strcpy_n1 ( &(S[16]),aloc1 ,1 ); strcpy_n1 ( &(S[17]),resName1,3 ); strcpy_n1 ( &(S[21]),chainID1,1 ); PutIntIns ( &(S[22]),seqNum1 ,4,insCode1 ); if (dist>0.0) PutRealF ( &(S[32]),dist,7,3 ); strcpy_n1 ( &(S[42]),atName2 ,4 ); strcpy_n1 ( &(S[46]),aloc2 ,1 ); strcpy_n1 ( &(S[47]),resName2,3 ); strcpy_n1 ( &(S[51]),chainID2,1 ); PutIntIns ( &(S[52]),seqNum2 ,4,insCode2 ); strcpy_ns ( &(S[72]),linkRID,8 ); } #define LinkRTypeID "LINKR" void AddStructConnLinkRTags ( mmcif::PLoop Loop ) { Loop->AddLoopTag ( CIFTAG_ID ); Loop->AddLoopTag ( CIFTAG_CONN_TYPE_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_ATOM_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR1_AUTH_ALT_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_COMP_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_ASYM_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_SEQ_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR1_PDB_INS_CODE ); Loop->AddLoopTag ( CIFTAG_CONN_DIST ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_ATOM_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR2_AUTH_ALT_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_COMP_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_ASYM_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_SEQ_ID ); Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR2_PDB_INS_CODE ); Loop->AddLoopTag ( CIFTAG_CONN_NAME ); } void LinkR::MakeCIF ( mmcif::PData CIF, int N ) { UNUSED_ARGUMENT(N); mmcif::PLoop Loop; int RC; RC = CIF->AddLoop ( CIFCAT_STRUCT_LINKR,Loop ); if (RC!=mmcif::CIFRC_Ok) // the category was (re)created, provide tags AddStructConnLinkRTags ( Loop ); Loop->AddString ( "1" ); // should be a counter Loop->AddString ( pstr(LinkTypeID) ); Loop->AddString ( atName1 ); Loop->AddString ( aloc1 ); Loop->AddString ( resName1 ); Loop->AddString ( chainID1 ); Loop->AddInteger ( seqNum1 ); Loop->AddString ( insCode1 ); Loop->AddReal ( dist ); Loop->AddString ( atName2 ); Loop->AddString ( aloc2 ); Loop->AddString ( resName2 ); Loop->AddString ( chainID2 ); Loop->AddInteger ( seqNum2 ); Loop->AddString ( insCode2 ); Loop->AddString ( linkRID ); } ERROR_CODE LinkR::ConvertPDBASCII ( cpstr S ) { GetString ( atName1 ,&(S[12]),4 ); strcpy_ncss ( aloc1 ,&(S[16]),1 ); strcpy_ncss ( resName1,&(S[17]),3 ); strcpy_ncss ( chainID1,&(S[21]),1 ); GetIntIns ( seqNum1,insCode1,&(S[22]),4 ); if (!GetReal(dist,&(S[32]),7)) dist = 0.0; GetString ( atName2 ,&(S[42]),4 ); strcpy_ncss ( aloc2 ,&(S[46]),1 ); strcpy_ncss ( resName2,&(S[47]),3 ); strcpy_ncss ( chainID2,&(S[51]),1 ); GetIntIns ( seqNum2,insCode2,&(S[52]),4 ); strcpy_ncss ( linkRID,&(S[72]),8 ); return Error_NoError ; } ERROR_CODE LinkR::GetCIF ( mmcif::PData CIF, int & n ) { mmcif::PLoop Loop; pstr F; int RC,l; bool Done; ERROR_CODE rc; Loop = CIF->GetLoop ( CIFCAT_STRUCT_CONN ); if (!Loop) { n = -1; // signal to finish processing of this structure return Error_EmptyCIF; } l = Loop->GetLoopLength(); Done = (n>=l); while (!Done) { F = Loop->GetString ( CIFTAG_CONN_TYPE_ID,n,RC ); if ((!RC) && F) Done = (strcmp(F,LinkTypeID)==0); else Done = false; if (!Done) { n++; Done = (n>=l); } } if (n>=l) { n = -1; // finish processing of Turn return Error_EmptyCIF; } Loop->DeleteField ( CIFTAG_CONN_TYPE_ID,n ); // CIFGetInteger ( l,Loop,CIFTAG_ID,n ); CIFGetString ( atName1,Loop,CIFTAG_CONN_PTNR1_AUTH_ATOM_ID,n, sizeof(atName1),pstr(" ") ); CIFGetString ( aloc1,Loop,CIFTAG_CONN_PDBX_PTNR1_AUTH_ALT_ID,n, sizeof(aloc1),pstr(" ") ); CIFGetString ( resName1,Loop,CIFTAG_CONN_PTNR1_AUTH_COMP_ID,n, sizeof(resName1),pstr(" ") ); CIFGetString ( chainID1,Loop,CIFTAG_CONN_PTNR1_AUTH_ASYM_ID,n, sizeof(chainID1),pstr(" ") ); rc = CIFGetInteger ( seqNum1,Loop,CIFTAG_CONN_PTNR1_AUTH_SEQ_ID,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( insCode1,Loop,CIFTAG_CONN_PDBX_PTNR1_PDB_INS_CODE, n,sizeof(insCode1),pstr(" ") ); rc = CIFGetReal ( dist,Loop,CIFTAG_CONN_DIST,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( atName2,Loop,CIFTAG_CONN_PTNR2_AUTH_ATOM_ID,n, sizeof(atName2),pstr(" ") ); CIFGetString ( aloc2,Loop,CIFTAG_CONN_PDBX_PTNR2_AUTH_ALT_ID,n, sizeof(aloc2),pstr(" ") ); CIFGetString ( resName2,Loop,CIFTAG_CONN_PTNR2_AUTH_COMP_ID,n, sizeof(resName2),pstr(" ") ); CIFGetString ( chainID2,Loop,CIFTAG_CONN_PTNR2_AUTH_ASYM_ID,n, sizeof(chainID2),pstr(" ") ); rc = CIFGetInteger ( seqNum2,Loop,CIFTAG_CONN_PTNR2_AUTH_SEQ_ID,n ); if (rc==Error_NoData) return Error_EmptyCIF; if (rc!=Error_NoError) return rc; CIFGetString ( insCode2,Loop,CIFTAG_CONN_PDBX_PTNR2_PDB_INS_CODE, n,sizeof(insCode2),pstr(" ") ); CIFGetString ( linkRID,Loop,CIFTAG_CONN_NAME,n, sizeof(linkRID),pstr(" ") ); n++; return Error_NoError; } void LinkR::Copy ( PContainerClass LinkR ) { strcpy ( atName1 ,PLinkR(LinkR)->atName1 ); strcpy ( aloc1 ,PLinkR(LinkR)->aloc1 ); strcpy ( resName1,PLinkR(LinkR)->resName1 ); strcpy ( chainID1,PLinkR(LinkR)->chainID1 ); seqNum1 = PLinkR(LinkR)->seqNum1; strcpy ( insCode1,PLinkR(LinkR)->insCode1 ); dist = PLinkR(LinkR)->dist; strcpy ( atName2 ,PLinkR(LinkR)->atName2 ); strcpy ( aloc2 ,PLinkR(LinkR)->aloc2 ); strcpy ( resName2,PLinkR(LinkR)->resName2 ); strcpy ( chainID2,PLinkR(LinkR)->chainID2 ); seqNum2 = PLinkR(LinkR)->seqNum2; strcpy ( insCode2,PLinkR(LinkR)->insCode2 ); strcpy ( linkRID,PLinkR(LinkR)->linkRID ); } void LinkR::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); f.WriteTerLine ( atName1 ,false ); f.WriteTerLine ( aloc1 ,false ); f.WriteTerLine ( resName1,false ); f.WriteTerLine ( chainID1,false ); f.WriteInt ( &seqNum1 ); f.WriteTerLine ( insCode1,false ); f.WriteReal ( &dist ); f.WriteTerLine ( atName2 ,false ); f.WriteTerLine ( aloc2 ,false ); f.WriteTerLine ( resName2,false ); f.WriteTerLine ( chainID2,false ); f.WriteInt ( &seqNum2 ); f.WriteTerLine ( insCode2,false ); f.WriteTerLine ( linkRID,false ); } void LinkR::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.ReadTerLine ( atName1 ,false ); f.ReadTerLine ( aloc1 ,false ); f.ReadTerLine ( resName1,false ); f.ReadTerLine ( chainID1,false ); f.ReadInt ( &seqNum1 ); f.ReadTerLine ( insCode1,false ); f.ReadReal ( &dist ); f.ReadTerLine ( atName2 ,false ); f.ReadTerLine ( aloc2 ,false ); f.ReadTerLine ( resName2,false ); f.ReadTerLine ( chainID2,false ); f.ReadInt ( &seqNum2 ); f.ReadTerLine ( insCode2,false ); f.ReadTerLine ( linkRID,false ); } MakeStreamFunctions(LinkR) // =================== CisPepContainer ====================== PContainerClass CisPepContainer::MakeContainerClass ( int ClassID ) { switch (ClassID) { default : case ClassID_Template : return ClassContainer::MakeContainerClass(ClassID); case ClassID_CisPep : return new CisPep(); } } MakeStreamFunctions(CisPepContainer) // ======================== CisPep ========================== CisPep::CisPep() : ContainerClass() { InitCisPep(); } CisPep::CisPep ( cpstr S ) : ContainerClass() { InitCisPep(); ConvertPDBASCII ( S ); } CisPep::CisPep ( io::RPStream Object ) : ContainerClass(Object) { InitCisPep(); } CisPep::~CisPep() {} void CisPep::InitCisPep() { serNum = 1; // record serial number strcpy ( pep1 ,"---" ); // residue name strcpy ( chainID1," " ); // chain identifier 1 seqNum1 = 0; // residue sequence number 1 strcpy ( icode1 ," " ); // insertion code 1 strcpy ( pep2 ,"---" ); // residue name 2 strcpy ( chainID2," " ); // chain identifier 2 seqNum2 = 0; // residue sequence number 2 strcpy ( icode2 ," " ); // insertion code 2 modNum = 0; // model number measure = 0.0; // measure of the angle in degrees. } void CisPep::PDBASCIIDump ( pstr S, int N ) { UNUSED_ARGUMENT(N); strcpy ( S,"CISPEP" ); PadSpaces ( S,80 ); PutInteger ( &(S[7]),serNum,3 ); strcpy_n1 ( &(S[11]),pep1 ,3 ); strcpy_n1 ( &(S[15]),chainID1,1 ); PutIntIns ( &(S[17]),seqNum1 ,4,icode1 ); strcpy_n1 ( &(S[25]),pep2 ,3 ); strcpy_n1 ( &(S[29]),chainID2,1 ); PutIntIns ( &(S[31]),seqNum2 ,4,icode1 ); PutInteger ( &(S[43]),modNum,3 ); PutRealF ( &(S[53]),measure,6,2 ); } ERROR_CODE CisPep::ConvertPDBASCII ( cpstr S ) { GetInteger ( serNum ,&(S[7]) ,3 ); strcpy_ncss ( pep1 ,&(S[11]),3 ); strcpy_ncss ( chainID1,&(S[15]),1 ); GetIntIns ( seqNum1,icode1,&(S[17]),4 ); strcpy_ncss ( pep2 ,&(S[25]),3 ); strcpy_ncss ( chainID2,&(S[29]),1 ); GetIntIns ( seqNum2,icode2,&(S[31]),4 ); GetInteger ( modNum ,&(S[43]),3 ); GetReal ( measure ,&(S[53]),6 ); return Error_NoError; } void CisPep::Copy ( PContainerClass CisPep ) { serNum = PCisPep(CisPep)->serNum; strcpy ( pep1 ,PCisPep(CisPep)->pep1 ); strcpy ( chainID1,PCisPep(CisPep)->chainID1 ); seqNum1 = PCisPep(CisPep)->seqNum1; strcpy ( icode1 ,PCisPep(CisPep)->icode1 ); strcpy ( pep2 ,PCisPep(CisPep)->pep2 ); strcpy ( chainID2,PCisPep(CisPep)->chainID2 ); seqNum2 = PCisPep(CisPep)->seqNum2; strcpy ( icode2 ,PCisPep(CisPep)->icode2 ); modNum = PCisPep(CisPep)->modNum; measure = PCisPep(CisPep)->measure; } void CisPep::write ( io::RFile f ) { byte Version=1; f.WriteByte ( &Version ); f.WriteInt ( &serNum ); f.WriteTerLine ( pep1 ,false ); f.WriteTerLine ( chainID1,false ); f.WriteInt ( &seqNum1 ); f.WriteTerLine ( icode1 ,false ); f.WriteTerLine ( pep2 ,false ); f.WriteTerLine ( chainID2,false ); f.WriteInt ( &seqNum2 ); f.WriteTerLine ( icode2 ,false ); f.WriteInt ( &modNum ); f.WriteReal ( &measure ); } void CisPep::read ( io::RFile f ) { byte Version; f.ReadByte ( &Version ); f.ReadInt ( &serNum ); f.ReadTerLine ( pep1 ,false ); f.ReadTerLine ( chainID1,false ); f.ReadInt ( &seqNum1 ); f.ReadTerLine ( icode1 ,false ); f.ReadTerLine ( pep2 ,false ); f.ReadTerLine ( chainID2,false ); f.ReadInt ( &seqNum2 ); f.ReadTerLine ( icode2 ,false ); f.ReadInt ( &modNum ); f.ReadReal ( &measure ); } MakeStreamFunctions(CisPep) // ===================== Model ======================= Model::Model() : ProModel() { InitModel(); } Model::Model ( PManager MMDBM, int serialNum ) : ProModel() { InitModel(); manager = MMDBM; serNum = serialNum; } Model::Model ( io::RPStream Object ) : ProModel(Object) { InitModel(); } void Model::InitModel() { serNum = 0; nChains = 0; nChainsAlloc = 0; chain = NULL; manager = NULL; Exclude = true; } Model::~Model() { FreeMemory(); if (manager) manager->_ExcludeModel ( serNum ); } void Model::FreeMemory() { DeleteAllChains(); if (chain) delete[] chain; chain = NULL; nChains = 0; nChainsAlloc = 0; RemoveSecStructure(); RemoveHetInfo (); RemoveLinks (); RemoveLinkRs (); RemoveCisPeps (); } void Model::SetMMDBManager ( PManager MMDBM, int serialNum ) { manager = MMDBM; serNum = serialNum; } void Model::CheckInAtoms() { int i; if (manager) for (i=0;iCheckInAtoms(); } int Model::GetNumberOfAtoms ( bool countTers ) { // returns number of atoms in the model int i,na; na = 0; for (i=0;iGetNumberOfAtoms ( countTers ); return na; } int Model::GetNumberOfResidues() { // returns number of residues in the model PChain chn; int ic,ir,nr; nr = 0; for (ic=0;icnResidues;ir++) if (chn->residue[ir]) nr++; } return nr; } // ---------------- Extracting chains -------------------------- int Model::GetNumberOfChains() { return nChains; } PChain Model::GetChain ( int chainNo ) { if ((0<=chainNo) && (chainNo=nChainsAlloc) { nChainsAlloc = nOfChains+10; chain1 = new PChain[nChainsAlloc]; for (i=0;ichainID[0]) { chn = chain[i]; if (chn->GetNumberOfResidues()>0) k++; } } if (k) sprintf ( chainID,"%s%i",chID,k-1 ); else if (!chn) strcpy ( chainID,chID ); // chain is absent else return chn; // the only empty chain } else { if (chID[0]) { for (i=0;(ichainID)) chn = chain[i]; // it is there; just return the pointer } } else { for (i=0;(ichainID[0]) chn = chain[i]; // it is there; just return the pointer } } if (chn) return chn; strcpy ( chainID,chID ); } ExpandChainArray ( nChains ); // create new chain chain[nChains] = newChain(); chain[nChains]->SetChain ( chainID ); chain[nChains]->SetModel ( this ); nChains++; return chain[nChains-1]; } PChain Model::CreateChain ( const ChainID chID ) { // CreateChain() creates a new chain with chain ID regardless // the presence of same-ID chains in the model. This function // was introduced only for compatibility with older CCP4 // applications and using it in any new developments should be // strictly discouraged. ExpandChainArray ( nChains ); // create new chain chain[nChains] = newChain(); chain[nChains]->SetChain ( chID ); chain[nChains]->SetModel ( this ); nChains++; return chain[nChains-1]; } void Model::GetChainTable ( PPChain & chainTable, int & NumberOfChains ) { chainTable = chain; NumberOfChains = nChains; } bool Model::GetNewChainID ( ChainID chID, int length ) { int i,k; bool found; memset ( chID,0,sizeof(ChainID) ); chID[0] = 'A'; do { found = false; for (i=0;(ichainID)); if (found) { k = 0; while (kchainID)) return chain[i]; // it is there; just return the pointer } } else { for (i=0;ichainID[0]) return chain[i]; // it is there; just return the pointer } } return NULL; } // ------------------ Deleting chains -------------------------- int Model::DeleteChain ( int chainNo ) { if ((0<=chainNo) && (chainNochainID)) { Exclude = false; delete chain[i]; chain[i] = NULL; Exclude = true; return 1; } } } else { for (i=0;ichainID[0]) { Exclude = false; delete chain[i]; chain[i] = NULL; Exclude = true; return 1; } } } return 0; } int Model::DeleteAllChains() { int i,k; Exclude = false; k = 0; for (i=0;iisSolventChain()) { delete chain[i]; chain[i] = NULL; k++; } } Exclude = true; return k; } void Model::TrimChainTable() { int i,j; Exclude = false; j = 0; for (i=0;inResidues>0) { if (jnResidues; return 0; } int Model::GetNumberOfResidues ( int chainNo ) { if ((0<=chainNo) && (chainNonResidues; } return 0; } PResidue Model::GetResidue ( const ChainID chainID, int seqNo, const InsCode insCode ) { PChain chn; chn = GetChain ( chainID ); if (chn) return chn->GetResidue ( seqNo,insCode ); return NULL; } PResidue Model::GetResidue ( const ChainID chainID, int resNo ) { PChain chn; chn = GetChain ( chainID ); if (chn) { if ((0<=resNo) && (resNonResidues)) return chn->residue[resNo]; } return NULL; } PResidue Model::GetResidue ( int chainNo, int seqNo, const InsCode insCode ) { if ((0<=chainNo) && (chainNoGetResidue ( seqNo,insCode ); } return NULL; } PResidue Model::GetResidue ( int chainNo, int resNo ) { if ((0<=chainNo) && (chainNonResidues)) return chain[chainNo]->residue[resNo]; } } return NULL; } int Model::GetResidueNo ( const ChainID chainID, int seqNo, const InsCode insCode ) { PChain chn; chn = GetChain ( chainID ); if (chn) return chn->GetResidueNo ( seqNo,insCode ); return -2; } int Model::GetResidueNo ( int chainNo, int seqNo, const InsCode insCode ) { if ((0<=chainNo) && (chainNoGetResidueNo ( seqNo,insCode ); } return -2; } void Model::GetResidueTable ( PPResidue & resTable, int & NumberOfResidues ) { // resTable has to be NULL or it will be reallocated. The application // is responsible for deallocating the resTable (but not of its // residues!). This does not apply to other GetResidueTable // functions. PPChain chn; PPResidue res; int i,j,k,nChns,nResidues; if (resTable) { delete[] resTable; resTable = NULL; } NumberOfResidues = 0; GetChainTable ( chn,nChns ); for (i=0;iGetResidueTable ( res,nResidues ); NumberOfResidues += nResidues; } if (NumberOfResidues>0) { resTable = new PResidue[NumberOfResidues]; k = 0; GetChainTable ( chn,nChns ); for (i=0;iGetResidueTable ( res,nResidues ); for (j=0;jresidue; NumberOfResidues = chn->nResidues; } } void Model::GetResidueTable ( int chainNo, PPResidue & resTable, int & NumberOfResidues ) { resTable = NULL; NumberOfResidues = 0; if ((0<=chainNo) && (chainNoresidue; NumberOfResidues = chain[chainNo]->nResidues; } } } int Model::DeleteResidue ( const ChainID chainID, int seqNo, const InsCode insCode ) { PChain chn; chn = GetChain ( chainID ); if (chn) return chn->DeleteResidue ( seqNo,insCode ); return 0; } int Model::DeleteResidue ( const ChainID chainID, int resNo ) { PChain chn; chn = GetChain ( chainID ); if (chn) return chn->DeleteResidue ( resNo ); return 0; } int Model::DeleteResidue ( int chainNo, int seqNo, const InsCode insCode ) { if ((0<=chainNo) && (chainNoDeleteResidue ( seqNo,insCode ); } return 0; } int Model::DeleteResidue ( int chainNo, int resNo ) { if ((0<=chainNo) && (chainNoDeleteResidue ( resNo ); } return 0; } int Model::DeleteAllResidues ( const ChainID chainID ) { PChain chn; chn = GetChain ( chainID ); if (chn) return chn->DeleteAllResidues(); return 0; } int Model::DeleteAllResidues ( int chainNo ) { if ((0<=chainNo) && (chainNoDeleteAllResidues(); } return 0; } int Model::DeleteAllResidues() { int i,k; k = 0; for (i=0;iDeleteAllResidues(); return k; } int Model::DeleteSolvent() { int i,k; Exclude = false; k = 0; for (i=0;iDeleteSolvent(); chain[i]->TrimResidueTable(); if (chain[i]->nResidues<=0) { delete chain[i]; chain[i] = NULL; } } Exclude = true; return k; } int Model::AddResidue ( const ChainID chainID, PResidue res ) { PChain chn; chn = GetChain ( chainID ); if (chn) return chn->AddResidue ( res ); return 0; } int Model::AddResidue ( int chainNo, PResidue res ) { if ((0<=chainNo) && (chainNoAddResidue ( res ); } return 0; } int Model::_ExcludeChain ( const ChainID chainID ) { // _ExcludeChain(..) excludes (but does not dispose!) a chain // from the model. Returns 1 if the model gets empty and 0 otherwise. int i,k; if (!Exclude) return 0; // find the chain k = -1; for (i=0;(ichainID)) k = i; if (k>=0) { for (i=k+1;iGetChainID(), (PPChain(data))[j]->GetChainID() ); if (diff>0) diff = 1; if (diff<0) diff = -1; if (sKey==SORT_CHAIN_ChainID_Desc) return -diff; return diff; } void QSortChains::Swap ( int i, int j ) { PChain chn; chn = ((PPChain)data)[i]; ((PPChain)data)[i] = ((PPChain)data)[j]; ((PPChain)data)[j] = chn; } void QSortChains::Sort ( PPChain chain, int nChains, int sortKey ) { sKey = sortKey; QuickSort::Sort ( &(chain[0]),nChains ); } void Model::SortChains ( int sortKey ) { QSortChains SC; TrimChainTable(); SC.Sort ( chain,nChains,sortKey ); } // -------------------- Extracting atoms ----------------------- int Model::GetNumberOfAtoms ( const ChainID chainID, int seqNo, const InsCode insCode ) { PChain chn; PResidue res; chn = GetChain ( chainID ); if (chn) { res = chn->GetResidue ( seqNo,insCode ); if (res) return res->nAtoms; } return 0; } int Model::GetNumberOfAtoms ( int chainNo, int seqNo, const InsCode insCode ) { PChain chn; PResidue res; chn = GetChain ( chainNo ); if (chn) { res = chn->GetResidue ( seqNo,insCode ); if (res) return res->nAtoms; } return 0; } int Model::GetNumberOfAtoms ( const ChainID chainID, int resNo ) { PChain chn; PResidue res; chn = GetChain ( chainID ); if (chn) { if ((0<=resNo) && (resNonResidues)) { res = chn->residue[resNo]; if (res) return res->nAtoms; } } return 0; } int Model::GetNumberOfAtoms ( int chainNo, int resNo ) { PChain chn; PResidue res; if ((0<=chainNo) && (chainNonResidues)) { res = chn->residue[resNo]; if (res) return res->nAtoms; } } } return 0; } PAtom Model::GetAtom ( const ChainID chID, int seqNo, const InsCode insCode, const AtomName aname, const Element elmnt, const AltLoc aloc ) { PChain chn; PResidue res; chn = GetChain ( chID ); if (chn) { res = chn->GetResidue ( seqNo,insCode ); if (res) return res->GetAtom ( aname,elmnt,aloc ); } return NULL; } PAtom Model::GetAtom ( const ChainID chID, int seqNo, const InsCode insCode, int atomNo ) { PChain chn; PResidue res; chn = GetChain ( chID ); if (chn) { res = chn->GetResidue ( seqNo,insCode ); if (res) { if ((0<=atomNo) && (atomNonAtoms)) return res->atom[atomNo]; } } return NULL; } PAtom Model::GetAtom ( const ChainID chID, int resNo, const AtomName aname, const Element elmnt, const AltLoc aloc ) { PChain chn; PResidue res; chn = GetChain ( chID ); if (chn) { if ((0<=resNo) && (resNonResidues)) { res = chn->residue[resNo]; if (res) return res->GetAtom ( aname,elmnt,aloc ); } } return NULL; } PAtom Model::GetAtom ( const ChainID chID, int resNo, int atomNo ) { PChain chn; PResidue res; chn = GetChain ( chID ); if (chn) { if ((0<=resNo) && (resNonResidues)) { res = chn->residue[resNo]; if (res) { if ((0<=atomNo) && (atomNonAtoms)) return res->atom[atomNo]; } } } return NULL; } PAtom Model::GetAtom ( int chNo, int seqNo, const InsCode insCode, const AtomName aname, const Element elmnt, const AltLoc aloc ) { PResidue res; if ((0<=chNo) && (chNoGetResidue ( seqNo,insCode ); if (res) return res->GetAtom ( aname,elmnt,aloc ); } } return NULL; } PAtom Model::GetAtom ( int chNo, int seqNo, const InsCode insCode, int atomNo ) { PResidue res; if ((0<=chNo) && (chNoGetResidue ( seqNo,insCode ); if (res) { if ((0<=atomNo) && (atomNonAtoms)) return res->atom[atomNo]; } } } return NULL; } PAtom Model::GetAtom ( int chNo, int resNo, const AtomName aname, const Element elmnt, const AltLoc aloc ) { PResidue res; if ((0<=chNo) && (chNonResidues)) { res = chain[chNo]->residue[resNo]; if (res) return res->GetAtom ( aname,elmnt,aloc ); } } } return NULL; } PAtom Model::GetAtom ( int chNo, int resNo, int atomNo ) { PResidue res; if ((0<=chNo) && (chNonResidues)) { res = chain[chNo]->residue[resNo]; if (res) { if ((0<=atomNo) && (atomNonAtoms)) return res->atom[atomNo]; } } } } return NULL; } void Model::GetAtomTable ( const ChainID chainID, int seqNo, const InsCode insCode, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; atomTable = NULL; NumberOfAtoms = 0; res = GetResidue ( chainID,seqNo,insCode ); if (res) { atomTable = res->atom; NumberOfAtoms = res->nAtoms; } } void Model::GetAtomTable ( int chainNo, int seqNo, const InsCode insCode, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; atomTable = NULL; NumberOfAtoms = 0; res = GetResidue ( chainNo,seqNo,insCode ); if (res) { atomTable = res->atom; NumberOfAtoms = res->nAtoms; } } void Model::GetAtomTable ( const ChainID chainID, int resNo, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; atomTable = NULL; NumberOfAtoms = 0; res = GetResidue ( chainID,resNo ); if (res) { atomTable = res->atom; NumberOfAtoms = res->nAtoms; } } void Model::GetAtomTable ( int chainNo, int resNo, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; atomTable = NULL; NumberOfAtoms = 0; res = GetResidue ( chainNo,resNo ); if (res) { atomTable = res->atom; NumberOfAtoms = res->nAtoms; } } void Model::GetAtomTable1 ( const ChainID chainID, int seqNo, const InsCode insCode, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; res = GetResidue ( chainID,seqNo,insCode ); if (res) res->GetAtomTable1 ( atomTable,NumberOfAtoms ); else { if (atomTable) delete[] atomTable; atomTable = NULL; NumberOfAtoms = 0; } } void Model::GetAtomTable1 ( int chainNo, int seqNo, const InsCode insCode, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; res = GetResidue ( chainNo,seqNo,insCode ); if (res) res->GetAtomTable1 ( atomTable,NumberOfAtoms ); else { if (atomTable) delete[] atomTable; atomTable = NULL; NumberOfAtoms = 0; } } void Model::GetAtomTable1 ( const ChainID chainID, int resNo, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; res = GetResidue ( chainID,resNo ); if (res) res->GetAtomTable1 ( atomTable,NumberOfAtoms ); else { if (atomTable) delete[] atomTable; atomTable = NULL; NumberOfAtoms = 0; } } void Model::GetAtomTable1 ( int chainNo, int resNo, PPAtom & atomTable, int & NumberOfAtoms ) { PResidue res; res = GetResidue ( chainNo,resNo ); if (res) res->GetAtomTable1 ( atomTable,NumberOfAtoms ); else { if (atomTable) delete[] atomTable; atomTable = NULL; NumberOfAtoms = 0; } } int Model::DeleteAtom ( const ChainID chID, int seqNo, const InsCode insCode, const AtomName aname, const Element elmnt, const AltLoc aloc ) { PChain chn; chn = GetChain ( chID ); if (chn) return chn->DeleteAtom ( seqNo,insCode,aname,elmnt,aloc ); return 0; } int Model::DeleteAtom ( const ChainID chID, int seqNo, const InsCode insCode, int atomNo ) { PChain chn; chn = GetChain ( chID ); if (chn) return chn->DeleteAtom ( seqNo,insCode,atomNo ); return 0; } int Model::DeleteAtom ( const ChainID chID, int resNo, const AtomName aname, const Element elmnt, const AltLoc aloc ) { PChain chn; chn = GetChain ( chID ); if (chn) return chn->DeleteAtom ( resNo,aname,elmnt,aloc ); return 0; } int Model::DeleteAtom ( const ChainID chID, int resNo, int atomNo ) { PChain chn; chn = GetChain ( chID ); if (chn) return chn->DeleteAtom ( resNo,atomNo ); return 0; } int Model::DeleteAtom ( int chNo, int seqNo, const InsCode insCode, const AtomName aname, const Element elmnt, const AltLoc aloc ) { if ((0<=chNo) && (chNoDeleteAtom ( seqNo,insCode,aname, elmnt,aloc ); } return 0; } int Model::DeleteAtom ( int chNo, int seqNo, const InsCode insCode, int atomNo ) { if ((0<=chNo) && (chNoDeleteAtom ( seqNo,insCode,atomNo ); } return 0; } int Model::DeleteAtom ( int chNo, int resNo, const AtomName aname, const Element elmnt, const AltLoc aloc ) { if ((0<=chNo) && (chNoDeleteAtom ( resNo,aname,elmnt,aloc ); } return 0; } int Model::DeleteAtom ( int chNo, int resNo, int atomNo ) { if ((0<=chNo) && (chNoDeleteAtom ( resNo,atomNo ); } return 0; } int Model::DeleteAllAtoms ( const ChainID chID, int seqNo, const InsCode insCode ) { PChain chn; chn = GetChain ( chID ); if (chn) return chn->DeleteAllAtoms ( seqNo,insCode ); return 0; } int Model::DeleteAllAtoms ( const ChainID chID, int resNo ) { PChain chn; chn = GetChain ( chID ); if (chn) return chn->DeleteAllAtoms ( resNo ); return 0; } int Model::DeleteAllAtoms ( const ChainID chID ) { PChain chn; chn = GetChain ( chID ); if (chn) return chn->DeleteAllAtoms(); return 0; } int Model::DeleteAllAtoms ( int chNo, int seqNo, const InsCode insCode ) { if ((0<=chNo) && (chNoDeleteAllAtoms ( seqNo,insCode ); } return 0; } int Model::DeleteAllAtoms ( int chNo, int resNo ) { if ((0<=chNo) && (chNoDeleteAllAtoms ( resNo ); } return 0; } int Model::DeleteAllAtoms ( int chNo ) { if ((0<=chNo) && (chNoDeleteAllAtoms(); } return 0; } int Model::DeleteAllAtoms() { int i,k; k = 0; for (i=0;iDeleteAllAtoms(); return k; } int Model::DeleteAltLocs() { // This function leaves only alternative location with maximal // occupancy, if those are equal or unspecified, the one with // "least" alternative location indicator. // The function returns the number of deleted. All tables remain // untrimmed, so that explicit trimming or calling FinishStructEdit() // is required. int i,n; n = 0; for (i=0;iDeleteAltLocs(); return n; } int Model::AddAtom ( const ChainID chID, int seqNo, const InsCode insCode, PAtom atom ) { PChain chn; chn = GetChain ( chID ); if (chn) return chn->AddAtom ( seqNo,insCode,atom ); return 0; } int Model::AddAtom ( const ChainID chID, int resNo, PAtom atom ) { PChain chn; chn = GetChain ( chID ); if (chn) return chn->AddAtom ( resNo,atom ); return 0; } int Model::AddAtom ( int chNo, int seqNo, const InsCode insCode, PAtom atom ) { if ((0<=chNo) && (chNoAddAtom ( seqNo,insCode,atom ); } return 0; } int Model::AddAtom ( int chNo, int resNo, PAtom atom ) { if ((0<=chNo) && (chNoAddAtom ( resNo,atom ); } return 0; } void Model::GetAtomStatistics ( RAtomStat AS ) { AS.Init(); CalAtomStatistics ( AS ); AS.Finish(); } void Model::CalAtomStatistics ( RAtomStat AS ) { int i; for (i=0;iCalAtomStatistics ( AS ); } ERROR_CODE Model::ConvertPDBString ( pstr PDBString ) { // Interprets PDB records DBREF, SEQADV, SEQRES, MODRES. // Returns zero if the line was converted, otherwise returns a // non-negative value of Error_XXXX. // PDBString must be not shorter than 81 characters. ChainID chainID; PChain chn; PHelix helix; PTurn turn; PLink link; PLinkR linkR; PCisPep cispep; ERROR_CODE RC; // pad input line with spaces, if necessary PadSpaces ( PDBString,80 ); chainID[0] = char(0); chainID[1] = char(0); if (!strncmp(PDBString,"DBREF ",6)) { if (PDBString[12]!=' ') chainID[0] = PDBString[12]; chn = GetChainCreate ( chainID,false ); return chn->ConvertDBREF ( PDBString ); } else if (!strncmp(PDBString,"SEQADV",6)) { if (PDBString[16]!=' ') chainID[0] = PDBString[16]; chn = GetChainCreate ( chainID,false ); return chn->ConvertSEQADV ( PDBString ); } else if (!strncmp(PDBString,"SEQRES",6)) { if (PDBString[11]!=' ') chainID[0] = PDBString[11]; chn = GetChainCreate ( chainID,false ); return chn->ConvertSEQRES ( PDBString ); } else if (!strncmp(PDBString,"MODRES",6)) { if (PDBString[16]!=' ') chainID[0] = PDBString[16]; chn = GetChainCreate ( chainID,false ); return chn->ConvertMODRES ( PDBString ); } else if (!strncmp(PDBString,"HET ",6)) { if (PDBString[12]!=' ') chainID[0] = PDBString[12]; chn = GetChainCreate ( chainID,false ); return chn->ConvertHET ( PDBString ); } else if (!strncmp(PDBString,"HETNAM",6)) { hetCompounds.ConvertHETNAM ( PDBString ); return Error_NoError; } else if (!strncmp(PDBString,"HETSYN",6)) { hetCompounds.ConvertHETSYN ( PDBString ); return Error_NoError; } else if (!strncmp(PDBString,"FORMUL",6)) { hetCompounds.ConvertFORMUL ( PDBString ); return Error_NoError; } else if (!strncmp(PDBString,"HELIX ",6)) { helix = new Helix(); RC = helix->ConvertPDBASCII(PDBString); if (RC==0) helices.AddData ( helix ); else delete helix; return RC; } else if (!strncmp(PDBString,"SHEET ",6)) { return sheets.ConvertPDBASCII ( PDBString ); } else if (!strncmp(PDBString,"TURN ",6)) { turn = new Turn(); RC = turn->ConvertPDBASCII(PDBString); if (RC==0) turns.AddData ( turn ); else delete turn; return RC; } else if (!strncmp(PDBString,"LINK ",6)) { link = new Link(); RC = link->ConvertPDBASCII(PDBString); if (RC==0) links.AddData ( link ); else delete link; return RC; } else if (!strncmp(PDBString,"LINKR ",6)) { linkR = new LinkR(); RC = linkR->ConvertPDBASCII(PDBString); if (RC==0) linkRs.AddData ( linkR ); else delete linkR; return RC; } else if (!strncmp(PDBString,"CISPEP",6)) { cispep = new CisPep(); RC = cispep->ConvertPDBASCII(PDBString); if (RC==0) cisPeps.AddData ( cispep ); else delete cispep; return RC; } else return Error_WrongSection; } void Model::PDBASCIIDumpPS ( io::RFile f ) { int i; for (i=0;iDBRef.PDBASCIIDump ( f ); for (i=0;iseqAdv.PDBASCIIDump ( f ); for (i=0;iseqRes.PDBASCIIDump ( f ); for (i=0;imodRes.PDBASCIIDump ( f ); for (i=0;iHet.PDBASCIIDump ( f ); hetCompounds.PDBASCIIDump ( f ); helices .PDBASCIIDump ( f ); sheets .PDBASCIIDump ( f ); turns .PDBASCIIDump ( f ); links .PDBASCIIDump ( f ); linkRs .PDBASCIIDump ( f ); } void Model::PDBASCIIDumpCP ( io::RFile f ) { cisPeps.PDBASCIIDump ( f ); } void Model::PDBASCIIDump ( io::RFile f ) { char S[100]; int i; bool singleModel = true; if (manager) singleModel = (manager->nModels<=1); if (!singleModel) { strcpy ( S,"MODEL " ); PadSpaces ( S,80 ); PutInteger ( &(S[10]),serNum,4 ); f.WriteLine ( S ); } for (i=0;iPDBASCIIAtomDump ( f ); if (!singleModel) { strcpy ( S,"ENDMDL" ); PadSpaces ( S,80 ); f.WriteLine ( S ); } } void Model::MakeAtomCIF ( mmcif::PData CIF ) { int i; for (i=0;iMakeAtomCIF ( CIF ); } void Model::MakePSCIF ( mmcif::PData CIF ) { int i; for (i=0;iDBRef.MakeCIF ( CIF ); for (i=0;iseqAdv.MakeCIF ( CIF ); for (i=0;iseqRes.MakeCIF ( CIF ); for (i=0;imodRes.MakeCIF ( CIF ); for (i=0;iHet.MakeCIF ( CIF ); hetCompounds.MakeCIF ( CIF ); helices .MakeCIF ( CIF ); sheets .MakeCIF ( CIF ); turns .MakeCIF ( CIF ); links .MakeCIF ( CIF ); linkRs .MakeCIF ( CIF ); } ERROR_CODE Model::GetCIFPSClass ( mmcif::PData CIF, int ClassID ) { ChainContainer PSClass; PChainContainer Dest; ERROR_CODE RC; cpstr chainID; PChain chn; PSClass.SetChain ( NULL ); RC = PSClass.GetCIF ( CIF,ClassID ); if (RC!=Error_NoError) return RC; chainID = PSClass.Get1stChainID(); while (chainID) { chn = GetChainCreate ( chainID,false ); switch (ClassID) { case ClassID_DBReference : Dest = &(chn->DBRef); break; case ClassID_SeqAdv : Dest = &(chn->seqAdv); break; case ClassID_ModRes : Dest = &(chn->modRes); break; case ClassID_Het : Dest = &(chn->Het); break; default : Dest = NULL; } if (Dest) { PSClass.MoveByChainID ( chainID,Dest ); Dest->SetChain ( chn ); } else printf ( " **** PROGRAM ERROR: wrong call to" " Model::GetCIFPSClass(..)\n" ); chainID = PSClass.Get1stChainID(); } return Error_NoError; } ERROR_CODE Model::GetCIF ( mmcif::PData CIF ) { SeqRes seqRes; ERROR_CODE RC; PChain chn; RC = GetCIFPSClass ( CIF,ClassID_DBReference ); if (RC!=Error_NoError) return RC; RC = GetCIFPSClass ( CIF,ClassID_SeqAdv ); if (RC!=Error_NoError) return RC; RC = seqRes.GetCIF ( CIF ); while (RC==Error_NoError) { chn = GetChainCreate ( seqRes.chainID,false ); chn->seqRes.Copy ( &seqRes ); RC = seqRes.GetCIF ( CIF ); } RC = GetCIFPSClass ( CIF,ClassID_ModRes ); if (RC!=Error_NoError) return RC; RC = GetCIFPSClass ( CIF,ClassID_Het ); if (RC!=Error_NoError) return RC; hetCompounds.GetCIF ( CIF ); helices .GetCIF ( CIF,ClassID_Helix ); sheets .GetCIF ( CIF ); turns .GetCIF ( CIF,ClassID_Turn ); links .GetCIF ( CIF,ClassID_Link ); linkRs .GetCIF ( CIF,ClassID_LinkR ); return RC; } cpstr Model::GetEntryID() { if (manager) return manager->title.idCode; else return pstr(""); } void Model::SetEntryID ( const IDCode idCode ) { if (manager) manager->SetEntryID ( idCode ); } int Model::GetNumberOfAllAtoms() { if (manager) return manager->nAtoms; else return 0; } int Model::GetSerNum() { return serNum; } PAtom * Model::GetAllAtoms() { if (manager) return manager->atom; else return NULL; } cpstr Model::GetModelID ( pstr modelID ) { modelID[0] = char(0); sprintf ( modelID,"/%i",serNum ); return modelID; } int Model::GetNumberOfModels() { if (manager) return manager->nModels; else return 0; } void Model::Copy ( PModel model ) { // modify both Model::_copy and Model::Copy methods simultaneously! int i; FreeMemory(); if (model) { serNum = model->serNum; nChains = model->nChains; nChainsAlloc = nChains; if (nChains>0) { chain = new PChain[nChainsAlloc]; for (i=0;ichain[i]) { chain[i] = newChain(); chain[i]->SetModel ( this ); chain[i]->Copy ( model->chain[i] ); } else chain[i] = NULL; } } hetCompounds.Copy ( &(model->hetCompounds) ); helices .Copy ( &(model->helices) ); sheets .Copy ( &(model->sheets) ); turns .Copy ( &(model->turns) ); links .Copy ( &(model->links) ); linkRs .Copy ( &(model->linkRs) ); cisPeps .Copy ( &(model->cisPeps) ); } } void Model::CopyHets ( PModel model ) { if (model) hetCompounds.Copy ( &(model->hetCompounds) ); } void Model::CopySecStructure ( PModel model ) { if (model) { helices.Copy ( &(model->helices) ); sheets .Copy ( &(model->sheets) ); turns .Copy ( &(model->turns) ); } } void Model::CopyLinks ( PModel model ) { if (model)links.Copy ( &(model->links) ); } void Model::CopyLinkRs ( PModel model ) { if (model) linkRs.Copy ( &(model->linkRs) ); } void Model::CopyCisPeps ( PModel model ) { if (model) cisPeps.Copy ( &(model->cisPeps) ); } void Model::_copy ( PModel model ) { // modify both Model::_copy and Model::Copy methods simultaneously! int i; FreeMemory(); if (model) { serNum = model->serNum; nChains = model->nChains; nChainsAlloc = nChains; if (nChains>0) { chain = new PChain[nChainsAlloc]; for (i=0;ichain[i]) { chain[i] = newChain(); chain[i]->SetModel ( this ); chain[i]->_copy ( model->chain[i] ); } else chain[i] = NULL; } } hetCompounds.Copy ( &(model->hetCompounds) ); helices .Copy ( &(model->helices) ); sheets .Copy ( &(model->sheets) ); turns .Copy ( &(model->turns) ); links .Copy ( &(model->links) ); linkRs .Copy ( &(model->linkRs) ); cisPeps .Copy ( &(model->cisPeps) ); } } void Model::_copy ( PModel model, PPAtom atom, int & atom_index ) { // modify both Model::_copy and Model::Copy methods simultaneously! // // _copy(PModel,PPAtom,int&) does copy atoms into array 'atom' // starting from position atom_index. 'atom' should be able to // accept all new atoms - no checks on the length of 'atom' // is being made. This function should not be used in applications. int i; FreeMemory(); if (model) { serNum = model->serNum; nChains = model->nChains; nChainsAlloc = nChains; if (nChains>0) { chain = new PChain[nChainsAlloc]; for (i=0;ichain[i]) { chain[i] = newChain(); chain[i]->SetModel ( this ); chain[i]->_copy ( model->chain[i],atom,atom_index ); } else chain[i] = NULL; } } hetCompounds.Copy ( &(model->hetCompounds) ); helices .Copy ( &(model->helices) ); sheets .Copy ( &(model->sheets) ); turns .Copy ( &(model->turns) ); links .Copy ( &(model->links) ); linkRs .Copy ( &(model->linkRs) ); } } int Model::AddChain ( PChain chn ) { // modify both Model::Copy methods simultaneously! // // Copy(PModel,PPAtom,int&) copies atoms into array 'atom' // starting from position atom_index. 'atom' should be able to // accept all new atoms - no checks on the length of 'atom' // is being made. This function should not be used in applications. PModel model1; int i; for (i=0;iGetCoordHierarchy()) { // The chain is associated with a coordinate hierarchy. It should // remain there, therefore we physically copy all its residues // and atoms. chain[nChains] = newChain(); chain[nChains]->SetModel ( this ); if (manager) { // get space for new atoms manager->AddAtomArray ( chn->GetNumberOfAtoms(true) ); chain[nChains]->_copy ( chn,manager->atom,manager->nAtoms ); } else { for (i=0;inResidues;i++) chain[nChains]->AddResidue ( chn->residue[i] ); } } else { // The chain is not associated with a coordinate hierarchy. Such // unregistered objects are simply taken over, i.e. moved into // the new destination (model). chain[nChains] = chn; // remove chain from its model: model1 = chn->GetModel(); if (model1) for (i=0;inChains;i++) if (model1->chain[i]==chn) { model1->chain[i] = NULL; break; } chain[nChains]->SetModel ( this ); if (manager) chain[nChains]->CheckInAtoms(); } nChains++; } return nChains; } void Model::MoveChain ( PChain & m_chain, PPAtom m_atom, PPAtom atom, int & atom_index, int chain_ext ) { // MoveChain(..) adds chain m_chain on the top Chain array. // The pointer on chain is then set to NULL (m_chain=NULL). // If chain_ext is greater than 0, the moved chain will be // forcefully renamed; the new name is composed as the previous // one + underscore + chain_ext (e.g. A_1). If thus generated // name duplicates any of existing chain IDs, or if chain_ext // was set to 0 and there is a duplication of chain IDs, the // name is again modified as above, with the extension number // generated automatically (this may result in IDs like // A_1_10). // m_atom must give pointer to the Atom array, from which // the atoms belonging to m_chain, are moved to Atom array // given by 'atom', starting from poisition 'atom_index'. // 'atom_index' is then automatically updated to the next // free position in 'atom'. // Note1: the moved atoms will occupy a continuous range // in 'atom' array; no checks on whether the corresponding // cells are occupied or not, are performed. // Note2: the 'atom_index' is numbered from 0 on, i.e. // it is equal to atom[atom_index]->index-1; atom[]->index // is assigned automatically. ChainID chainID; int i,j,k,Ok; PPChain chain1; PResidue crRes; if (!m_chain) return; // modify chain ID with the extension given if (chain_ext>0) sprintf ( chainID,"%s_%i",m_chain->chainID,chain_ext ); else strcpy ( chainID,m_chain->chainID ); // Choose the chain ID. If a chain with such ID is // already present in the model, it will be assigned // a new ID 'ID_n', where 'ID' stands for the original // chain ID and 'n' is the minimum (integer) number // chosen such that 'name_n' represents a new chain ID // (in the model). k = 0; do { Ok = true; for (i=0;(ichainID)) Ok = false; if (!Ok) { k++; if (chain_ext>0) sprintf ( chainID,"%s_%i_%i",m_chain->chainID, chain_ext,k ); else sprintf ( chainID,"%s_%i",m_chain->chainID,k ); } } while (!Ok); // add chain on the top of Chain array. strcpy ( m_chain->chainID,chainID ); if (nChains>=nChainsAlloc) { nChainsAlloc = nChains+10; chain1 = new PChain[nChainsAlloc]; k = 0; for (i=0;iSetModel ( this ); nChains++; // Move all atoms of the chain. While residues belong // atoms belong to the chain's manager class. Therefore // they should be moved from one manager to another. for (i=0;inResidues;i++) { crRes = m_chain->residue[i]; if (crRes) for (j=0;jnAtoms;j++) if (crRes->atom[j]) { k = crRes->atom[j]->index-1; atom[atom_index] = m_atom[k]; atom[atom_index]->index = atom_index+1; atom_index++; m_atom[k] = NULL; // moved! } } m_chain = NULL; // moved! } void Model::GetAIndexRange ( int & i1, int & i2 ) { PChain chn; PResidue res; int ic,ir,ia; i1 = MaxInt4; i2 = MinInt4; for (ic=0;icnResidues;ir++) { res = chn->residue[ir]; if (res) { for (ia=0;ianAtoms;ia++) if (res->atom[ia]) { if (res->atom[ia]->indexatom[ia]->index; if (res->atom[ia]->index>i2) i2 = res->atom[ia]->index; } } } } } } void Model::MaskAtoms ( PMask Mask ) { int i; for (i=0;iMaskAtoms ( Mask ); } void Model::MaskResidues ( PMask Mask ) { int i; for (i=0;iMaskResidues ( Mask ); } void Model::MaskChains ( PMask Mask ) { int i; for (i=0;iSetMask ( Mask ); } void Model::UnmaskAtoms ( PMask Mask ) { int i; for (i=0;iUnmaskAtoms ( Mask ); } void Model::UnmaskResidues ( PMask Mask ) { int i; for (i=0;iUnmaskResidues ( Mask ); } void Model::UnmaskChains ( PMask Mask ) { int i; for (i=0;iRemoveMask ( Mask ); } // ------ Getting Secondary Structure Elements int Model::GetNumberOfHelices() { return helices.Length(); } int Model::GetNumberOfSheets() { return sheets.nSheets; } PHelix Model::GetHelix ( int serialNum ) { return (PHelix)helices.GetContainerClass ( serialNum-1 ); } void Model::GetSheetID ( int serialNum, SheetID sheetID ) { if ((1<=serialNum) && (serialNum<=sheets.nSheets)) { if (sheets.sheet[serialNum-1]) { strcpy ( sheetID,sheets.sheet[serialNum-1]->sheetID ); return; } } sheetID[0] = char(0); } PSheet Model::GetSheet ( int serialNum ) { if ((1<=serialNum) && (serialNum<=sheets.nSheets)) return sheets.sheet[serialNum-1]; else return NULL; } PSheet Model::GetSheet ( const SheetID sheetID ) { int i; for (i=0;isheetID,sheetID)) return sheets.sheet[i]; } return NULL; } int Model::GetNumberOfStrands ( int sheetSerNum ) { if ((1<=sheetSerNum) && (sheetSerNum<=sheets.nSheets)) { if (sheets.sheet[sheetSerNum-1]) return sheets.sheet[sheetSerNum-1]->nStrands; } return 0; } int Model::GetNumberOfStrands ( const SheetID sheetID ) { int i; for (i=0;isheetID,sheetID)) return sheets.sheet[i]->nStrands; } return 0; } PStrand Model::GetStrand ( int sheetSerNum, int strandSerNum ) { PSheet sheet; if ((1<=sheetSerNum) && (sheetSerNum<=sheets.nSheets)) { sheet = sheets.sheet[sheetSerNum-1]; if (sheet) { if ((1<=strandSerNum) && (strandSerNum<=sheet->nStrands)) return sheet->strand[strandSerNum-1]; } } return NULL; } PStrand Model::GetStrand ( const SheetID sheetID, int strandSerNum ) { int i; PSheet sheet; for (i=0;isheetID,sheetID)) { sheet = sheets.sheet[i]; if (sheet) { if ((1<=strandSerNum) && (strandSerNum<=sheet->nStrands)) return sheet->strand[strandSerNum-1]; } } } return NULL; } void Model::RemoveSecStructure() { helices.FreeContainer(); sheets .FreeMemory (); turns .FreeContainer(); } void Model::RemoveHetInfo() { hetCompounds.FreeMemory(); } int Model::GetNumberOfLinks() { return links.Length(); } PLink Model::GetLink ( int serialNum ) { return (PLink)links.GetContainerClass ( serialNum-1 ); } void Model::RemoveLinks() { links.FreeContainer(); } void Model::AddLink ( PLink link ) { links.AddData ( link ); } int Model::GetNumberOfLinkRs() { return linkRs.Length(); } PLinkR Model::GetLinkR ( int serialNum ) { return (PLinkR)linkRs.GetContainerClass ( serialNum-1 ); } void Model::RemoveLinkRs() { linkRs.FreeContainer(); } void Model::AddLinkR ( PLinkR linkR ) { linkRs.AddData ( linkR ); } int Model::GetNumberOfCisPeps() { return cisPeps.Length(); } PCisPep Model::GetCisPep ( int CisPepNum ) { return (PCisPep)cisPeps.GetContainerClass ( CisPepNum-1 ); } void Model::RemoveCisPeps() { cisPeps.FreeContainer(); } void Model::AddCisPep ( PCisPep cisPep ) { cisPeps.AddData ( cisPep ); } void Model::ApplyTransform ( mat44 & TMatrix ) { // transforms all coordinates by multiplying with matrix TMatrix int i; for (i=0;iApplyTransform ( TMatrix ); } bool Model::isInSelection ( int selHnd ) { PMask mask; if (manager) { mask = PRoot(manager)->GetSelMask ( selHnd ); if (mask) return CheckMask ( mask ); } return false; } // ------- user-defined data handlers int Model::PutUDData ( int UDDhandle, int iudd ) { if (UDDhandle & UDRF_MODEL) return UDData::putUDData ( UDDhandle,iudd ); else return UDDATA_WrongUDRType; } int Model::PutUDData ( int UDDhandle, realtype rudd ) { if (UDDhandle & UDRF_MODEL) return UDData::putUDData ( UDDhandle,rudd ); else return UDDATA_WrongUDRType; } int Model::PutUDData ( int UDDhandle, cpstr sudd ) { if (UDDhandle & UDRF_MODEL) return UDData::putUDData ( UDDhandle,sudd ); else return UDDATA_WrongUDRType; } int Model::GetUDData ( int UDDhandle, int & iudd ) { if (UDDhandle & UDRF_MODEL) return UDData::getUDData ( UDDhandle,iudd ); else return UDDATA_WrongUDRType; } int Model::GetUDData ( int UDDhandle, realtype & rudd ) { if (UDDhandle & UDRF_MODEL) return UDData::getUDData ( UDDhandle,rudd ); else return UDDATA_WrongUDRType; } int Model::GetUDData ( int UDDhandle, pstr sudd, int maxLen ) { if (UDDhandle & UDRF_MODEL) return UDData::getUDData ( UDDhandle,sudd,maxLen ); else return UDDATA_WrongUDRType; } int Model::GetUDData ( int UDDhandle, pstr & sudd ) { if (UDDhandle & UDRF_MODEL) return UDData::getUDData ( UDDhandle,sudd ); else return UDDATA_WrongUDRType; } // ------- calculation of Secondary Structure int Model::CalcSecStructure ( bool flagBulge, int aminoSelHnd ) { // This function is contributed by Liz Potterton, University of York //------------------------------------------------------------------ // Define a secondary structure type of each amino acid residue in the // structure. // Procedure: // Find all amino acids // Find all pairs of amino acids which have inter-Ca distance < 10.0A // Test for hydrogen bonds between the main chain N and O of the close // residues and store the information in the hbonds matrix // Analyse the info in hbonds matrix to assign secondary structure to // secstr vector PPResidue Res; PPAtom Ca; PChain chn; PContact contact; imatrix hbonds; PPAtom * hbond_atoms; int nres, ncontacts; int ir1,ir2, irdif; int i,j,k,l; // 1a. Get protein residues from selection handle if (aminoSelHnd>=0) { manager->GetSelIndex(aminoSelHnd,Res,nres); // printf ( " nres %3i " ,nres ); if (nres<=0) return SSERC_noResidues; } else { // 1b. Get all protein residues nres = 0; for (i=0;inResidues; if (nres<=0) return SSERC_noResidues; Res = new PResidue[nres]; nres = 0; for (i=0;inResidues; for (j=0;jresidue[j]; } } if (nres<=0) { delete[] Res; return SSERC_noResidues; } } // 2. Get C-alphas of all aminoacids Ca = new PAtom[nres]; k = 0; for (i=0;i=0 || Res[i]->isAminoacid()) { Ca[i] = Res[i]->GetAtom("CA", " C", "*"); k++; } else Ca[i] = NULL; Res[i]->SSE = SSE_None; } else Ca[i] = NULL; if (k<=0) { delete[] Res; delete[] Ca; return SSERC_noAminoacids; } // 3. Find all close Calphas - i.e. find the contacts between // the two equivalent sets of Ca atoms contact = NULL; ncontacts = 0; manager->SeekContacts ( Ca,nres, Ca,nres, 2.0,10.0, 2, contact,ncontacts,0 ); manager->RemoveBricks(); if (ncontacts<=0) { delete[] Res; delete[] Ca; if (contact) delete[] contact; return SSERC_noSSE; } // 4. Get and initialize memory for analysing the SSE GetMatrixMemory ( hbonds,nres,3,0,0 ); hbond_atoms = new PPAtom[nres]; for (i=0;i2) { // test if there is donor Hbond from residue ir1 if (Res[ir1]->isMainchainHBond(Res[ir2])) { k = 0; while ((hbonds[ir1][k]!=0) && (k<2)) k++; hbonds [ir1][k] = -irdif; hbond_atoms[ir1][k] = Res[ir1]->GetAtom ( "N" ); hbond_atoms[ir1][k+3] = Res[ir2]->GetAtom ( "O" ); } // test if there is donor Hbond from residue ir2 if (Res[ir2]->isMainchainHBond(Res[ir1])) { k = 0; while ((hbonds[ir2][k]!=0) && (k<2)) k++; hbonds [ir2][k] = irdif; hbond_atoms[ir2][k] = Res[ir2]->GetAtom ( "N" ); hbond_atoms[ir2][k+3] = Res[ir1]->GetAtom ( "O" ); } } } // 6. Assign the turns - if there is bifurcated bond then the 4-turn // takes precedence - read the paper to make sense of this for (i=0;iSSE = SSE_5Turn; Res[i-2]->SSE = SSE_5Turn; Res[i-3]->SSE = SSE_5Turn; Res[i-4]->SSE = SSE_5Turn; } if (hbonds[i][k]==-3) { Res[i-1]->SSE = SSE_3Turn; Res[i-2]->SSE = SSE_3Turn; } k++; } } for (i=0;iSSE = SSE_4Turn; Res[i-2]->SSE = SSE_4Turn; Res[i-3]->SSE = SSE_4Turn; } k++; } } // 7. Look for consecutive 4-turns which make alpha helix for (i=1;iSSE==SSE_Helix) || (Res[i ]->SSE==SSE_4Turn)) && ((Res[i+1]->SSE==SSE_Helix) || (Res[i+1]->SSE==SSE_4Turn)) && ((Res[i+2]->SSE==SSE_Helix) || (Res[i+2]->SSE==SSE_4Turn)) && ((Res[i+3]->SSE==SSE_Helix) || (Res[i+3]->SSE==SSE_4Turn))) for (j=i;j<=i+3;j++) Res[j]->SSE = SSE_Helix; } for (i=0;iSSE = SSE_Strand; Res[j]->SSE = SSE_Strand; } // Parallel strand if (hbonds[j][l]==-irdif-2) { Res[i-1]->SSE = SSE_Strand; Res[j ]->SSE = SSE_Strand; } // Parallel beta bulge if (hbonds[j][l]==-irdif-3) { if (flagBulge) { if (Res[i-1]->SSE==SSE_None) Res[i-1]->SSE = SSE_Bulge; if (Res[i-2]->SSE==SSE_None) Res[i-2]->SSE = SSE_Bulge; if (Res[j ]->SSE==SSE_None) Res[j ]->SSE = SSE_Bulge; } else { if (Res[i-1]->SSE==SSE_None) Res[i-1]->SSE = SSE_Strand; if (Res[i-2]->SSE==SSE_None) Res[i-2]->SSE = SSE_Strand; if (Res[j ]->SSE==SSE_None) Res[j ]->SSE = SSE_Strand; } } l++; } // Test for 'wide' hbond j = i + hbonds[i][k] + 2; if (jSSE = SSE_Strand; Res[j-1]->SSE = SSE_Strand; } // Parallel strands if (hbonds[j][l]==-irdif-2) { Res[i ]->SSE = SSE_Strand; Res[j-1]->SSE = SSE_Strand; } l++; } } // test for anti-parallel B-bulge between 'close' hbonds j = i + hbonds[i][k] - 1; if (j>=0) { l = 0; while ((l<=2) && (hbonds[j][l]!=0)) { if (hbonds[j][l]==-irdif+1) { if (flagBulge) { if (Res[i ]->SSE==SSE_None) Res[i ]->SSE = SSE_Bulge; if (Res[j+1]->SSE==SSE_None) Res[j+1]->SSE = SSE_Bulge; if (Res[j ]->SSE==SSE_None) Res[j ]->SSE = SSE_Bulge; } else { if (Res[i ]->SSE==SSE_None) Res[i ]->SSE = SSE_Strand; if (Res[j+1]->SSE==SSE_None) Res[j+1]->SSE = SSE_Strand; if (Res[j ]->SSE==SSE_None) Res[j ]->SSE = SSE_Strand; } } l++; } } // test for anti-parallel B-bulge between 'wide' hbonds j = i + hbonds[i][k] + 3; if (j0)) { if (flagBulge) { if (Res[i-1]->SSE==SSE_None) Res[i-1]->SSE = SSE_Bulge; if (Res[j-1]->SSE==SSE_None) Res[j-1]->SSE = SSE_Bulge; if (Res[j-2]->SSE==SSE_None) Res[j-2]->SSE = SSE_Bulge; } else { if (Res[i-1]->SSE==SSE_None) Res[i-1]->SSE = SSE_Strand; if (Res[j-1]->SSE==SSE_None) Res[j-1]->SSE = SSE_Strand; if (Res[j-2]->SSE==SSE_None) Res[j-2]->SSE = SSE_Strand; } } else if (hbonds[j][l]==-irdif-3) { // and bulge in parallel strand if (flagBulge) { if (Res[i ]->SSE==SSE_None) Res[i ]->SSE = SSE_Bulge; if (Res[j-1]->SSE==SSE_None) Res[j-1]->SSE = SSE_Bulge; if (Res[j-2]->SSE==SSE_None) Res[j-2]->SSE = SSE_Bulge; } else { if (Res[i ]->SSE==SSE_None) Res[i ]->SSE = SSE_Strand; if (Res[j-1]->SSE==SSE_None) Res[j-1]->SSE = SSE_Strand; if (Res[j-2]->SSE==SSE_None) Res[j-2]->SSE = SSE_Strand; } } l++; } } k++; } // Finish looping over Hbonds for residue (k loop) } // Finish looping over residues ( i loop) // 8. Free memory if (hbond_atoms) { for (i=0;iisCompactBinary(); f.WriteByte ( &Version ); f.WriteBool ( &compactBinary ); f.WriteInt ( &serNum ); f.WriteInt ( &nChains ); for (i=0;iwrite ( f ); } if (!compactBinary) { ProModel::write ( f ); hetCompounds.write ( f ); helices .write ( f ); sheets .write ( f ); turns .write ( f ); links .write ( f ); linkRs .write ( f ); } } void Model::read ( io::RFile f ) { int i,k; byte Version; bool compactBinary; FreeMemory(); f.ReadByte ( &Version ); f.ReadBool ( &compactBinary ); f.ReadInt ( &serNum ); f.ReadInt ( &nChains ); nChainsAlloc = nChains; if (nChains>0) { chain = new PChain[nChainsAlloc]; for (i=0;iSetModel ( this ); chain[i]->read ( f ); } } } if (!compactBinary) { ProModel::read ( f ); hetCompounds.read ( f ); helices .read ( f ); sheets .read ( f ); turns .read ( f ); links .read ( f ); linkRs .read ( f ); } } MakeFactoryFunctions(Model) } // namespace mmdb mmdb2-2.0.5/mmdb2/mmdb_tables.cpp0000664000175000017500000006052012571573314013433 00000000000000// $Id: mmdb_tables.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 24.07.15 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : MMDB_Tables // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // // **** Namespace : mmdb:: // // **** Functions : // ~~~~~~~~~~~ // // **** Constants : AName ( array of 2-character atom names ) // ~~~~~~~~~~~ HAName ( array of 2=character heteroatom names ) // RName ( 3-characters amino acid names ) // RName1 ( 1-characters amino acid names ) // // // (C) E. Krissinel 2000-2015 // // ================================================================= // #include #include "mmdb_tables.h" #include "mmdb_defs.h" namespace mmdb { // =============================================================== cpstr const ElementName[nElementNames] = { " H", "HE", "LI", "BE", " B", " C", " N", " O", " F", "NE", "NA", "MG", "AL", "SI", " P", " S", "CL", "AR", " K", "CA", "SC", "TI", " V", "CR", "MN", "FE", "CO", "NI", "CU", "ZN", "GA", "GE", "AS", "SE", "BR", "KR", "RB", "SR", " Y", "ZR", "NB", "MO", "TC", "RU", "RH", "PD", "AG", "CD", "IN", "SN", "SB", "TE", " I", "XE", "CS", "BA", "LA", "CE", "PR", "ND", "PM", "SM", "EU", "GD", "TB", "DY", "HO", "ER", "TM", "YB", "LU", "HF", "TA", " W", "RE", "OS", "IR", "PT", "AU", "HG", "TL", "PB", "BI", "PO", "AT", "RN", "FR", "RA", "AC", "TH", "PA", " U", "NP", "PU", "AM", "CM", "BK", "CF", "ES", "FM", "MD", "NO", "LR", "RF", "DB", "SG", "BH", "HS", "MT", "UN", "UU", "UB", "UQ", "UH", "UO", " D", "AN" }; realtype const MolecWeight[nElementNames] = { 1.0079, 4.0026, 6.9410, 9.0122, 10.811, 12.011, 14.007, 15.999, 18.998, 20.180, 22.990, 24.305, 26.982, 28.086, 30.974, 32.066, 35.453, 39.948, 39.098, 40.078, 44.956, 47.867, 50.942, 51.996, 54.938, 55.845, 58.993, 58.693, 63.546, 65.390, 69.723, 72.610, 74.922, 78.960, 79.904, 83.800, 85.468, 87.620, 88.906, 91.224, 92.906, 95.940, 97.907, 101.07, 102.91, 106.42, 107.87, 112.41, 114.82, 118.71, 121.76, 127.60, 126.90, 131.29, 132.91, 137.33, 138.91, 140.12, 140.91, 144.24, 144.91, 150.36, 151.96, 157.25, 158.93, 162.50, 164.93, 167.26, 168.93, 173.04, 174.97, 178.49, 180.95, 183.84, 186.21, 190.23, 192.22, 195.08, 196.97, 200.59, 204.38, 207.20, 208.98, 208.98, 209.99, 222.02, 232.02, 226.03, 227.03, 232.04, 231.04, 238.03, 237.05, 244.06, 243.06, 247.07, 247.07, 251.08, 252.08, 257.10, 258.10, 259.10, 262.11, 263.11, 262.11, 266.12, 264.12, 269.13, 268.14, 272.15, 272.15, 277.00, 289.00, 289.00, 293.00, 2.0200, 3.0300 }; realtype const CovalentRadius[nElementNames] = { 0.32, 0.93, 1.23, 0.90, 0.82, 0.77, 0.75, 0.73, 0.72, 0.71, 1.54, 1.36, 1.18, 1.11, 1.06, 1.02, 0.99, 0.98, 2.03, 1.91, 1.62, 1.45, 1.34, 1.18, 1.17, 1.17, 1.16, 1.15, 1.17, 1.25, 1.26, 1.22, 1.20, 1.16, 1.14, 1.12, 2.16, 1.91, 1.62, 1.45, 1.34, 1.30, 1.27, 1.25, 1.25, 1.28, 1.34, 1.48, 1.44, 1.41, 1.40, 1.36, 1.33, 1.31, 2.35, 1.98, 1.69, 1.44, 1.34, 1.30, 1.28, 1.26, 1.27, 1.30, 1.34, 1.49, 1.48, 1.47, 1.46, 1.46, 1.45, 1.43, 2.50, 2.40, 2.20, 1.65, 1.65, 1.64, 1.63, 1.62, 1.85, 1.61, 1.59, 1.59, 1.58, 1.57, 1.56, 1.74, 1.56, 1.65, 1.65, 1.42, 1.65, 1.65, 1.65, 1.65, 1.65, 1.65, 1.65, 1.65, 1.65, 1.65, 1.65, 0.32, 0.10, /**/ 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, 0.32, 0.32 }; realtype const VdWaalsRadius[nElementNames] = { 1.20, 1.40, 1.82, 1.78, 1.74, 1.70, 1.55, 1.52, 1.47, 1.54, // ^^^^ ^^^^ <- only a guess 2.27, 1.73, 1.80, 2.10, 1.80, 1.80, 1.75, 1.88, // ^^^^ 2.75, 2.65, // ^^^^ 2.55, 2.45, 2.35, 2.20, 1.73, 1.90, // ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ 1.75, 1.63, 1.40, 1.39, // ^^^^ 1.87, 1.86, 1.85, 1.90, 1.85, 2.02, // ^^^^ 2.75, 2.65, //^^^^ ^^^^ 2.55, 2.45, 2.35, 2.20, 2.05, 1.90, // ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ 1.75, 1.63, 1.72, 1.58, // ^^^^ 1.93, 2.17, 2.10, 2.06, 1.98, 2.16, // ^^^^ 2.75, 2.75, //^^^^ ^^^^ 2.75, 2.75, 2.75, 2.75, 2.75, 2.75, 2.75, // ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ 2.75, 2.75, 2.75, 2.75, 2.75, 2.65, 2.55, // ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ 2.45, 2.35, 2.25, 2.15, 2.05, 1.95, // ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ 1.85, 1.75, 1.66, 1.55, // ^^^^ 1.96, 2.02, 2.00, 2.00, 2.00, 2.00, // ^^^^ ^^^^ ^^^^ ^^^^ 2.75, 2.75, //^^^^ ^^^^ 2.50, 2.25, 1.95, 1.86, 1.80, 1.80, 1.80, // ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ 1.80, 1.80, 1.80, 1.80, 1.80, 1.80, 1.80, // ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ 1.80, 1.80, 1.80, 1.80, 1.80, 1.80, // ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ 1.80, 1.80, 1.80, 1.80, // ^^^^ ^^^^ ^^^^ ^^^^ 1.80, 1.80, 1.80, // ^^^^ ^^^^ ^^^^ 1.30, 1.50 //^^^^ ^^^^ }; realtype const IonicRadius[nElementNames] = { 0.79, 0.49, 2.05, 1.40, 1.17, 0.91, 0.75, 0.65, 0.57, 0.51, 2.23, 1.72, 1.82, 1.46, 1.23, 1.09, 0.97, 0.88, 2.77, 2.23, 2.09, 2.00, 1.92, 1.85, 1.79, 1.72, 1.67, 1.62, 1.57, 1.53, 1.81, 1.52, 1.33, 1.22, 1.12, 1.03, 2.98, 2.45, 2.27, 2.16, 2.09, 2.01, 1.95, 1.89, 1.83, 1.79, 1.75, 1.71, 2.00, 1.72, 1.53, 1.42, 1.32, 1.24, 3.34, 2.78, 2.74, 2.16, 2.09, 2.02, 1.97, 1.92, 1.87, 1.83, 1.79, 1.76, 2.08, 1.81, 1.63, 1.53, 1.43, 1.34, 3.50, 3.00, 3.20, 2.70, 2.67, 2.64, 2.62, 2.59, 2.56, 2.54, 2.51, 2.49, 2.47, 2.45, 2.42, 2.40, 2.25, 3.16, 3.14, 3.11, 3.08, 3.05, 3.02, 2.99, 2.97, 2.95, 2.92, 2.90, 2.87, 2.85 }; cpstr const ElementMetal[nElementMetals] = { "LI", "BE", "NA", "MG", "AL", " K", "CA", "SC", "TI", " V", "MN", "FE", "CO", "NI", "CU", "ZN", "GA", "RB", "SR", " Y", "ZR", "NB", "MO", "TC", "RU", "RH", "PD", "AG", "CD", "IN", "SN", "SB", "CS", "BA", "LA", "CE", "PR", "ND", "PM", "SM", "EU", "GD", "TB", "DY", "HO", "ER", "TM", "YB", "LU", "HF", "TA", " W", "RE", "OS", "IR", "PT", "AU", "HG", "TL", "PB", "BI", "PO", "FR", "RA", "AC", "TH", "PA", " U", "NP", "PU", "AM", "CM", "BK", "CF", "ES", "FM", "MD", "NO", "LR", "RF", "DB", "SG", "BH", "HS", "MT", "UN", "UU", "UB", "UQ", "UH", "UO" }; cpstr const HydAtomName[nHydAtomNames] = { "0H", "1H", "2H", "3H", "4H", "5H", "6H", "7H", "8H", "9H", "HH", "*H", "'H", """H" }; bool isMetal ( cpstr element ) { char name[3]; bool isThere; int i; if (!element[1]) { name[0] = ' '; name[1] = element[0]; } else strncpy ( name,element,2 ); name[2] = char(0); isThere = false; for (i=0;(i=nElementNames) return ELEMENT_UNKNOWN; return type+1; // so that hydrogen is 1 } realtype getMolecWeight ( cpstr element ) { int type=0; char El[3]; if ((!element[1]) || (element[1]==' ')) { El[0] = ' '; El[1] = element[0]; } else { El[0] = element[0]; El[1] = element[1]; } El[2] = char(0); UpperCase ( El ); while (type=nElementNames) return 1.0; return MolecWeight[type]; } realtype getCovalentRadius ( cpstr element ) { int type=0; char El[3]; if ((!element[1]) || (element[1]==' ')) { El[0] = ' '; El[1] = element[0]; } else { El[0] = element[0]; El[1] = element[1]; } El[2] = char(0); UpperCase ( El ); while (type=nElementNames) return 2.2*CovalentRadius[0]; return CovalentRadius[type]; } realtype getVdWaalsRadius ( cpstr element ) { int type=0; char El[3]; if ((!element[1]) || (element[1]==' ')) { El[0] = ' '; El[1] = element[0]; } else { El[0] = element[0]; El[1] = element[1]; } El[2] = char(0); UpperCase ( El ); while (type=nElementNames) return 1.8; return VdWaalsRadius[type]; } cpstr const ResidueName[nResNames] = { "ALA", "ARG", "ASN", "ASP", "CYS", "CYH", "GLN", "GLU", "GLY", "HIS", "ILE", "LEU", "LYS", "MET", "PHE", "PRO", "SER", "THR", "TRP", "TYR", "VAL", "HEM", "WAT", "SUL", "END", "DUM" }; int getResidueNo ( cpstr resName ) { int i,m; m = -1; for (i=0;(i // ~~~~~~~~~ // **** Classes : mmdb::math::BFGSMin ( minimization driver ) // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_MATH_BFGSMin__ #define __MMDB_MATH_BFGSMin__ #include #include "mmdb_mattype.h" #include "mmdb_math_linalg.h" namespace mmdb { namespace math { // ============================================================== enum BFGS_RC { BFGS_TooFewDigits = -2, BFGS_WrongSpaceDim = -1, BFGS_NoTermination = 0, BFGS_SmallGradient = 1, BFGS_SmallStep = 2, BFGS_LineSearchComplete = 3, BFGS_IterationLimit = 4, BFGS_LargeSteps = 5, BFGS_Stopped = 6 }; typedef void BFGSMinFunc ( void * UserData, int N, rvector X, realtype & F ); typedef BFGSMinFunc * PBFGSMinFunc; typedef void BFGSPrintFunc ( void * UserData, int N, int Itn, rvector X, rvector G, realtype F ); typedef BFGSPrintFunc * PBFGSPrintFunc; DefineClass(BFGSMin); class BFGSMin { public : BFGSMin (); virtual ~BFGSMin(); virtual void MinFunc ( rvector X, realtype & F ); virtual void Print ( int Itn, rvector X, rvector G, realtype F ); void SetMinFunction ( void * UserData, PBFGSMinFunc Fnc ); void SetPrintFunction ( void * UserData, PBFGSPrintFunc Fnc ); // ====================================================== // // .--------------------------------------------. // | | // | UNCONSTRAINED MINIMIZATION DRIVER | // | | // `--------------------------------------------' // // Finds a minimum of function F(X), X is vector [1..N], // defined by virtual MinFunc. Virtual Print provides // information on every iteration step. // // // Input parameters : // ----------------------- // // N is the dimension the minimization space // // x0 [1..N] is the initial point for minimization // // TypX [1..N] is the array of the typical ranges of // X - components, which are used for the scaling. // If TypX<=0.0 then 1.0 will be substituted // // Digits is the number of valid decimal digits in // the calculated value of minimizing function ( F ). // If Digits<=0 then the Driver will consider // that the F is computed with usual machine's // noise // // ItnLmt is the maximum available number of iterations. // If ItnLmt=0 then 100 will be substituted // // TypF is the expected absolute value of F in the // minimum, which is used in the stop criterion. // If TypF<=0.0 then 1.0 will be substituted // // GrdTol is the desired absolute value of the gradient // vector in the minimum of F . If GrdTol<=0.0 // then the some value correlated with machine's // noise will be substituted // // StpTol is the minimum available step for the minimi- // zation. The execution stops if the distance // between two consequential approximation will be // less then StpTol . If StpTol<=0.0 then the // some value correlated with machine's noise // will be substituted // // MaxStp is the maximum available step for then minimi- // zation. This parameter only prevents the appea- // rance of the too large steps, but the execution // stops if more than 5 steps with length of MaxStep // will consequently appear. // // // // Outpute parameters : // -------------------------- // // x0 will be the point at which the minimisation // had stopped // // Func will be the function's value at x0 // // TermCode will be the reason of stopping : // // 1 <=> the norm of gradient vector at x0 is // less than GrdTol ; the x0 is probable // point of the minimum // 2 <=> the distance between two last approxima- // tions was less than StpTol ; the x0 // may be the point of minimum // 3 <=> the gradient length is greater than // GrdTol , but future minimization fails ; // it may be the consequence of the errors // at the computing of gradient, but also // x0 could be the point of minimum // 4 <=> the iteration limit had been exchausted // 5 <=> more than 5 steps with length of // MaxStp had been made // 6 <=> the termination key ( Esc or End ) // had been pressed. // // // ======================================================== void BFGS_Driver ( int MinN, rvector x0, rvector TypX, realtype & FuncValue, int & TerminationCode, int Digits = 0, int ItnLmt = 0, realtype TypF = 0.0, realtype GrdTol = 0.0, realtype StpTol = 0.0, realtype MaxStp = MaxReal, bool Hess = false, rvector LowLimit = NULL, rvector TopLimit = NULL ); void Stop(); // generates stop signal to stop optimization protected : PBFGSMinFunc MFunc; void * MFuncData; PBFGSPrintFunc PFunc; void * PFuncData; int N,NAlloc; rmatrix Hsn; rvector TL,LL,XOpt,XPlus,Sx,SN,HDiag,GradX,GPlus; rvector StepSize,FNeighbor; rvector us,uy,ut; bvector Freese; realtype Func,FPlus,FOpt; realtype TakenLambda; bool ForDiff; // if True then forward differences are // used for the 1st estimation of the // Hessian (which is less expensive), // otherwise central differences will // be employed (which is more expensive). bool CalcHess; realtype Etha,SqrtEtha,CubertEtha,TpF,GrdEps,StpEps,MxStep; realtype SqrtEps; int CnsMax,MaxItn,TermCode; bool ModF; void MinFunc1 ( rvector X, realtype & F ); void UMInCk ( rvector x0, rvector TypX, int Digits, realtype TypF, realtype GrdTol, realtype StpTol, realtype MaxStp, int ItnLmt ); void UMStop0 ( rvector x0, rvector Grad ); void UMStop ( rvector x0, rvector Grad, int RetCode, int ItnCnt, bool MaxTkn ); virtual void Gradient ( rvector X, rvector G, realtype Fc ); virtual void FDHessF ( realtype Fc, rvector X ); void FDGrad ( rvector X, rvector G, realtype Fc ); void CDGrad ( rvector X, rvector G ); void MdHess ( rmatrix H, rvector HDg ); void InitHessUnFac ( realtype F, rmatrix H ); void BFGSUnFac ( rvector Xc, rvector Xp, rvector Gc, rvector Gp, bool AnalGrad, rvector HDg, rmatrix H ); void Choose_Lambda ( rvector X, rvector S, realtype & Lambda0 ); void LineSearch ( rvector px0, rvector G, rvector P, realtype pFunc, int & RetCode, bool & MaxTkn ); void GetMemory (); void FreeMemory (); void Relax (); void CopyPlus ( rvector x0 ); }; } } #endif mmdb2-2.0.5/mmdb2/mmdb_math_graph.h0000664000175000017500000003660612401105774013741 00000000000000// $Id: mmdb_math_graph.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : mmdb_math_graph // ~~~~~~~~~ // **** Namespace: mmdb::math:: // ~~~~~~~~~~ // **** Classes : Vertex ( graph vertex ) // ~~~~~~~~~ Edge ( graph edge ) // Graph ( structural graph ) // Match ( match of structural graphs ) // GraphMatch ( CSIA algorithms for graphs matching ) // // (C) E. Krissinel 2000-2013 // // When used, please cite: // // Krissinel, E. and Henrick, K. (2004) // Common subgraph isomorphism detection by backtracking search. // Software - Practice and Experience, 34, 591-607. // // ================================================================= // #ifndef __MMDB_MATH_Graph__ #define __MMDB_MATH_Graph__ #include #include "mmdb_atom.h" namespace mmdb { namespace math { // ========================= Vertex ========================== DefineClass(Vertex); enum GRAPH_FLAG { CHIRAL_RIGHT = 0x10000000, CHIRAL_LEFT = 0x20000000, ATOM_LEAVING = 0x40000000, HYDROGEN_BOND = 0x0F000000, SYMREL_MASK = 0x00FF0000, CHIRAL_MASK = 0xCFFFFFFF, TYPE_MASK = 0x00FFFFFF }; class Vertex : public io::Stream { friend class Graph; friend class GraphMatch; public: Vertex (); Vertex ( io::RPStream Object ); Vertex ( int vtype, cpstr vname ); Vertex ( int vtype ); Vertex ( cpstr chem_elem ); Vertex ( cpstr chem_elem, cpstr name ); ~Vertex(); void SetVertex ( cpstr chem_elem ); void SetVertex ( int vtype, cpstr vname ); void SetVertex ( int vtype ); void SetType ( int vtype ); void SetTypeExt ( int typeExt ); void RemoveChirality(); void LeaveChirality ( int eltype ); void SetName ( cpstr vname ); void SetProperty ( int vprop ); void SetID ( int vid ); void AddBond (); void CopyNBonds ( PVertex V ); inline void SetUserID ( int vid ) { user_id = vid; } inline int GetProperty () { return property; } inline int GetID () { return id; } inline int GetUserID () { return user_id; } inline cpstr GetName () { return name; } inline int GetType () { return type; } inline int GetTypeExt () { return type_ext; } int GetNBonds (); void SaveType (); // in userid void RestoreType (); // from userid void CopyType ( PVertex V ); virtual void Print ( int PKey ); virtual void Copy ( PVertex V ); void read ( io::RFile f ); void write ( io::RFile f ); void mem_read ( cpstr S, int & l ); void mem_write ( pstr S, int & l ); protected: pstr name; // name may be general, "C", "Hg", "Cl" etc. int type; // type of vertex, see comments in // mmdb_math_graph.cpp int type_ext; // vertex type extention int property; // flagwise properties -- user-defined int id; // a graph-defined vertex id int user_id; // a user-defined vertex id void InitVertex(); }; DefineStreamFunctions(Vertex); // ========================== Edge =========================== enum GRAPH_BOND { BOND_SINGLE = 1, BOND_DOUBLE = 2, BOND_AROMATIC = 3, BOND_TRIPLE = 4 }; DefineClass(Edge); class Edge : public io::Stream { friend class Graph; friend class CGMatch; public: Edge (); Edge ( io::RPStream Object ); Edge ( int vx1, int vx2, int btype ); // vx1,vx2 are numbered // as 1,2,3 on and refer // to vertices in the order // as they were added to // the graph; btype>0 ~Edge(); void SetEdge ( int vx1, int vx2, cpstr btype ); void SetEdge ( int vx1, int vx2, int btype ); // btype>0 void SetType ( int btype ); void SetProperty ( int eprop ); void SaveType (); // in property void RestoreType (); // from property inline int GetVertex1 () { return v1; } inline int GetVertex2 () { return v2; } inline int GetType () { return type; } inline int GetProperty () { return property; } virtual void Print ( int PKey ); virtual void Copy ( PEdge G ); void read ( io::RFile f ); void write ( io::RFile f ); void mem_read ( cpstr S, int & l ); void mem_write ( pstr S, int & l ); protected: int v1,v2; // >=1 int type; int property; void InitEdge(); }; DefineStreamFunctions(Edge); // ========================== Graph ============================ enum GRAPH_RC { MKGRAPH_Ok = 0, MKGRAPH_NoAtoms = -1, MKGRAPH_ChangedAltLoc = 1, MKGRAPH_MaxOccupancy = 2 }; DefineClass(Graph); class Graph : public io::Stream { friend class GraphMatch; friend class CSBase0; public : Graph (); Graph ( PResidue R, cpstr altLoc=NULL ); Graph ( io::RPStream Object ); ~Graph(); void Reset (); void SetName ( cpstr gname ); inline pstr GetName() { return name; } // AddVertex(..) and AddEdge(..) do not copy the objects, but // take them over. This means that application should forget // about pointers to V and G once they were given to Graph. // Vertices and edges must be allocated newly prior each call // to AddVertex(..) and AddEdge(..). void AddVertex ( PVertex V ); void AddEdge ( PEdge G ); void SetVertices ( PPVertex V, int vlen ); void SetEdges ( PPEdge G, int glen ); void RemoveChirality(); void LeaveChirality ( int eltype ); // MakeGraph(..) makes a graph corresponding to residue R. // The graphs vertices then correspond to the residue's atoms // (Vertex::userid points to atom R->atom[Vertex::userid]), // edges are calculated as chemical bonds between atoms basing // on the table of cut-off distances. // altCode specifies a particular conformation that should be // used for making the graph. If it is set to "" or NULL ("empty" // altcode) but the residue does not have conformation which // contains *only* ""-altcode atoms, a conformation corresponding // to maximal occupancy will be used. The same will happen if // altcode information in residue is not correct, whatever altCode // is specified. // After making the graph, Build(..) should be called as usual // before graph matching. // Non-negative return means that graph has been made. // MakeGraph(..) may return: // MKGRAPH_Ok everything is Ok // MKGRAPH_NoAtoms residue does not have atoms, graph // is not made // MKGRAPH_ChangedAltLoc a different altcode was used because // the residue has only one altcode and // that is different of // MKGRAPH_MaxOccupancy a maximal-occupancy conformation has // been chosen because of default // ""-altcode supplied or incorrect // altcode information in the residue int MakeGraph ( PResidue R, cpstr altLoc=NULL ); int MakeGraph ( PPAtom atom, int nAtoms ); void HideType ( int bond_vx_type ); void ExcludeType ( int type ); void MakeSymmetryRelief ( bool noCO2 ); void IdentifyRings (); int IdentifyConnectedComponents(); // returns their number >= 1 int Build ( bool bondOrder ); // returns 0 if Ok void MakeVertexIDs (); // simply numbers vertices as 1.. on int GetVertexID ( int vertexNo ); int GetVertexNo ( cpstr vname ); // GetBondedVertexID(..) works after MoveType(..) int GetNBondedVertices ( int vertexNo ); int GetBondedVertexID ( int vertexNo, int bond_vx_type, int bondNo ); PVertex GetVertex ( int vertexNo ); // 1<=vertexNo<=nVertices inline int GetNofVertices() { return nVertices; } PEdge GetEdge ( int edgeNo ); // 1<=edgeNo<=nEdges inline int GetNofEdges() { return nEdges; } void GetVertices ( PPVertex & V, int & nV ); void GetEdges ( PPEdge & E, int & nE ); virtual void Print(); void Print1(); virtual void Copy ( PGraph G ); void read ( io::RFile f ); void write ( io::RFile f ); void mem_read ( cpstr S, int & l ); void mem_write ( pstr S, int & l ); protected : pstr name; int nVertices,nEdges, nAllVertices,nAllEdges; PPVertex vertex; PPEdge edge; imatrix graph; void InitGraph (); void FreeMemory(); void markConnected ( int vno, int cno ); private : int nVAlloc,nEAlloc,nGAlloc; }; DefineStreamFunctions(Graph); // ========================= GMatch ========================== DefineClass(GMatch); DefineStreamFunctions(GMatch); class GMatch : public io::Stream { friend class GraphMatch; public : GMatch (); GMatch ( io::RPStream Object ); GMatch ( ivector FV1, ivector FV2, int nv, int n, int m ); ~GMatch(); // FV1[] and FV2[] are copied into internal buffers void SetMatch ( ivector FV1, ivector FV2, int nv, int n, int m ); bool isMatch ( ivector FV1, ivector FV2, int nv ); bool isCombination ( ivector FV1, ivector FV2, int nv ); // do not allocate or dispose FV1 and FV2 in application! void GetMatch ( ivector & FV1, ivector & FV2, int & nv, realtype & p1, realtype & p2 ); void read ( io::RFile f ); void write ( io::RFile f ); void mem_read ( cpstr S, int & l ); void mem_write ( pstr S, int & l ); protected : int n1,n2,mlength; ivector F1,F2; void InitGMatch(); private : int nAlloc; }; // ======================= GraphMatch ========================= #define _UseRecursion enum GRAPH_MATCH_FLAG { GMF_UniqueMatch = 0x00000001, GMF_NoCombinations = 0x00000002 }; enum VERTEX_EXT_TYPE { EXTTYPE_Ignore = 0, EXTTYPE_Equal = 1, EXTTYPE_AND = 2, EXTTYPE_OR = 3, EXTTYPE_XOR = 4, EXTTYPE_NotEqual = 5, EXTTYPE_NotAND = 6, EXTTYPE_NotOR = 7 }; DefineClass(GraphMatch); class GraphMatch : public io::Stream { public : GraphMatch (); GraphMatch ( io::RPStream Object ); ~GraphMatch(); void SetFlag ( word flag ); void RemoveFlag ( word flag ); void SetMaxNofMatches ( int maxNofMatches, bool stopOnMaxN ); void SetTimeLimit ( int maxTimeToRun=0 ); inline bool GetStopSignal() { return Stop; } void Reset(); // MatchGraphs looks for maximal common subgraphs of size // not less than minMatch. The number of found subgraphs // is returned by GetNofMatches(), the subgraph vertices // are returned by GetMatch(..). Control parameters: // vertexType true if vertex type should be taken // into account and False otherwise // vertexExt key to use extended vertex types (defined // as type_ext in Vertex). void MatchGraphs ( PGraph Gh1, PGraph Gh2, int minMatch, bool vertexType=true, VERTEX_EXT_TYPE vertexExt=EXTTYPE_Ignore ); void PrintMatches (); inline int GetNofMatches () { return nMatches; } inline int GetMaxMatchSize() { return maxMatch; } // do not allocate or dispose FV1 and FV2 in application! // FV1/p1 will always correspond to Gh1, and FV2/p2 - // to Gh2 as specified in MatchGraphs(..) void GetMatch ( int MatchNo, ivector & FV1, ivector & FV2, int & nv, realtype & p1, realtype & p2 ); void read ( io::RFile f ); void write ( io::RFile f ); void mem_read ( cpstr S, int & l ); void mem_write ( pstr S, int & l ); protected : PGraph G1,G2; PPVertex V1; PPVertex V2; imatrix c1,c2; bool swap; #ifndef _UseRecursion ivector jj; #endif int n,m; imatrix3 P; imatrix iF1; ivector F1,F2,ix; int nMatches,maxNMatches; PPGMatch Match; bool wasFullMatch,Stop,stopOnMaxNMathches; word flags; int maxMatch,timeLimit; void InitGraphMatch(); void FreeMemory (); void FreeRecHeap (); void GetMemory (); void GetRecHeap (); int Initialize ( bool vertexType, int vertexExt ); #ifdef _UseRecursion void Backtrack ( int i ); // exact matching #else void Ullman (); #endif void Backtrack1 ( int i, int k0 ); // exact/partial matching void CollectMatch ( int nm ); private : int nAlloc,mAlloc,nMAlloc; time_t startTime; }; DefineStreamFunctions(GraphMatch); extern void SetGraphAllocPortion ( int alloc_portion ); /* extern void TestGraphMatch(); */ } // namespace math } // namespace mmdb #endif mmdb2-2.0.5/mmdb2/mmdb_math_fft.h0000775000175000017500000000625012401105774013412 00000000000000// $Id: mmdb_math_fft.h $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2005-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : FFT // ~~~~~~~~~ // **** Functions: mmdb::math::FFT // ~~~~~~~~~ mmdb::math::RealFFT // mmdb::math::TwoFFT // mmdb::math::Convolve // mmdb::math::mConvolve // // (C) E.Krissinel 2005-2013 // // ================================================================= // #ifndef __FFT__ #define __FFT__ #include "mmdb_mattype.h" namespace mmdb { namespace math { extern void FFT ( rvector data, int nn, bool Forward=true ); extern void RealFFT ( rvector data, int n, bool Forward=true ); extern void TwoFFT ( rvector data1, rvector data2, rvector fft1, rvector fft2, int n ); extern void Convolve ( rvector data, int n, rvector respns, int m, rvector ans, bool Conv=true ); // mConvolve ( data,n,m ) replaces array data[0..n-1] with the result // of m recursive convolutions (m>1) defined as // // data_m = data (*) data_{m-1} // // where data_m is the result of mth convolution, data_0=data. // The definition of the convolution is // // [a (*) b]_i = Sum_j { a_j * b_{i-j} } // // On input, data[] is considered as containing the signal // sampled at both positive and negative times in the wrap-around // order, that is // // data[i], 0<=i // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB), "new rwbrook" // ~~~~~~~~~ // **** Functions : mmdb_f_init_ ( initializer ) // ~~~~~~~~~~~ mmdb_f_quit_ ( disposer ) // autoserials_ ( switch to the autoserials regime ) // setreadcoords_ ( switch for reading coordinates ) // simrwbrook_ ( simulates old RWBROOK printout ) // mmdb_f_openl_ ( associates a unit with a file ) // mmdb_f_open_ ( associates a unit with a file ) // mmdb_f_copy_ ( copies contents of units ) // mmdb_f_delete_ ( deletes part of a unit ) // mmdb_f_settype_ ( changes type of file and r/w mode ) // mmdb_f_setname_ ( changes file name ) // mmdb_f_write_ ( writes a data structure into file ) // mmdb_f_close_ ( closes and disposes a data str-re ) // mmdb_f_advance_ ( advances the internal pointer ) // mmdb_f_rewd_ ( sets internal pointer on the top ) // mmdb_f_bksp_ ( shifts int-l pointer 1 atom back ) // mmdb_f_atom_ ( reads/writes atom properties ) // mmdb_f_coord_ ( reads/writes atom coordinates ) // mmdb_f_setcell_ ( sets the crystal cell parameters ) // mmdb_f_wbspgrp_ ( sets the space group ) // mmdb_f_rbspgrp_ ( gets the space group ) // mmdb_f_wbcell_ ( sets the crystal cell parameters ) // mmdb_f_rbcell_ ( gets the crystal cell parameters ) // mmdb_f_rbcelln_ ( gets the crystal cell parameters ) // mmdb_f_rbrcel_ ( gets the recipricol cell ) // mmdb_f_rborf_ ( returns or fill transf. matrices ) // mmdb_f_orthmat_ ( calc. standard othogonalisations ) // mmdb_f_cvanisou_ ( converts between cryst-c units ) // mmdb_f_wremark_ ( writes a remark statement ) // mmdb_f_setter // mmdb_f_sethet // mmdb_f_getnofncsmates_ // rberrstop_ ( error messenger ) // rbcheckerr_ ( a simple error messenger ) // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_RWBrook__ #define __MMDB_RWBrook__ #include "mmdb_mattype.h" #include "mmdb_machine_.h" // ****** mmdb_rwbrook error codes enum RWB_ERROR { RWBERR_Ok = 0, RWBERR_NoChannel = -1, RWBERR_NoFile = -2, RWBERR_NoLogicalName = -3, RWBERR_CantOpenFile = -4, RWBERR_WrongInteger = -5, RWBERR_WrongModelNo = -6, RWBERR_DuplicatedModel = -7, RWBERR_ForeignFile = -8, RWBERR_WrongEdition = -9, RWBERR_ATOM_Unrecognd = -10, RWBERR_ATOM_AlreadySet = -11, RWBERR_ATOM_NoResidue = -12, RWBERR_ATOM_Unmatch = -13, RWBERR_NoAdvance = -14, RWBERR_EmptyPointer = -15, RWBERR_NoMatrices = -16, RWBERR_NoCoordinates = -17, RWBERR_Disagreement = -18, RWBERR_NoOrthCode = -19, RWBERR_NoCheck = -20, RWBERR_NoCellParams = -21, RWBERR_NotACIFFile = -22, RWBERR_NoData = -23, RWBERR_UnrecognCIFItems = -24, RWBERR_MissingCIFField = -25, RWBERR_EmptyCIFLoop = -26, RWBERR_UnexpEndOfCIF = -27, RWBERR_MissgCIFLoopField = -28, RWBERR_NotACIFStructure = -29, RWBERR_NotACIFLoop = -30, RWBERR_WrongReal = -31, RWBERR_WrongChainID = -32, RWBERR_WrongEntryID = -33, RWBERR_SEQRES_serNum = -34, RWBERR_SEQRES_numRes = -35, RWBERR_SEQRES_exraRes = -36, RWBERR_NCSM_Unrecogn = -37, RWBERR_NCSM_AlreadySet = -38, RWBERR_NCSM_WrongSerial = -39, RWBERR_NCSM_UnmatchIG = -40, RWBERR_NoModel = -41, RWBERR_NoSheetID = -42, RWBERR_WrongSheetID = -43, RWBERR_WrongStrandNo = -44, RWBERR_WrongNofStrands = -45, RWBERR_WrongSheetOrder = -46, RWBERR_HBondInconsis = -47, RWBERR_EmptyResidueName = -48, RWBERR_DuplicateSeqNum = -49, RWBERR_GeneralError1 = -50, RWBERR_Error1 = -101, RWBERR_Error2 = -102, RWBERR_Error3 = -103 }; // ***** mmdb_rwbrook warning flags // 0x00004000 means "it's a warning" enum RWB_WARNING { RWBWAR_Warning = 0x00004000, RWBWAR_RewOutput = 0x00004010, RWBWAR_FileTop = 0x00004020, RWBWAR_WrongSerial = 0x00004040, RWBWAR_UnkFormFactor = 0x00004080, RWBWAR_AmbFormFactor = 0x00004100, RWBWAR_NoOccupancy = 0x00004200, RWBWAR_NoTempFactor = 0x00004400 }; // ------------------------------------------------------------------ // mmdb_f_init_() makes a general initialization of the file system. // It must be called ONLY ONCE from the top of an application. // FORTRAN equivalent: subroutine MMDB_F_Init // ~~~~~~~~~~~~~~~~~~~ FORTRAN_SUBR ( MMDB_F_INIT, mmdb_f_init, (),(),() ); // ------------------------------------------------------------------ // mmdb_f_quit_() disposes the file system. A correct use assumes that // it will be called before an application quits. // FORTRAN equivalent: subroutine MMDB_F_Quit // ~~~~~~~~~~~~~~~~~~~ FORTRAN_SUBR ( MMDB_F_QUIT, mmdb_f_quit, (),(),() ); // ------------------------------------------------------------------ // autoserials_(..) switches On/Off the regime of automatical // generation of atom serial numbers at reading from PDB ASCII file. // The autoserials regime is On if iOnOff parameter is set to // non-zero, and the regime is turned Off otherwise. The setting // will last until next call to autoserials_(..) // // When this regime is Off (default state), all atom serial // numbers are expected to be in strictly incremental order and // any deviation from this rule will cause end of reading and // MMDB_F_Open_(..) will issue the RWBERR_AlreadySet error code. If // this code is then passed to error messengers (rberrstop_(..) or // rbcheckerr_(..)) the application will stop. It is Ok, however, // for serial numbers to increment by 2 or more. // // When the autoserials regime is On, MMDB_F_Open_(..) does not pay // attention to the serial numbers and generates them for each // atom in strict incremental-by-one. This will work correctly only // if all atom records ("ATOM"/"HETATM", "SIGATM", "ANISOU" and // "SIGUIJ") are grouped, for every atom, as they should (precisely, // "ATOM" or "HETATM" opens the group, then "SIGATM", "ANISOU" and // "SIGUIJ" should follow until next "ATOM"/"HETATM" is met). // FORTRAN equivalent: subroutine AutoSerials ( iOnOff ) // ~~~~~~~~~~~~~~~~~~~ integer iOnOff FORTRAN_SUBR ( AUTOSERIALS,autoserials, ( int * iOnOff ), ( int * iOnOff ), ( int * iOnOff ) ); // ------------------------------------------------------------------ // setreadcoords_(..) switches On/Off the reading of atomic // coordinates when mmdb_f_open_ is called for input. The coordinates // will be read if iOnOff parameter is set to non-zero, otherwise // the reading will stop on the coordinate section of PDB file. // The setting will last until the next call to setreadcoords_(..). // // By default, the coordinates are read. // // FORTRAN equivalent: subroutine SetReadCoords ( iOnOff ) // ~~~~~~~~~~~~~~~~~~~ integer iOnOff FORTRAN_SUBR ( SETREADCOORDS,setreadcoords, ( int * iOnOff ), ( int * iOnOff ), ( int * iOnOff ) ); // ------------------------------------------------------------------ // simrwbrook_(..) switches On/Off the regime of exact following // the old fortran RWBROOK's way of issuing messages and warnings. // // By default, this regime is switched off, which supresses all // messages from mmdb_rwbrook unless directly ordered or catastrophic. // Switching this regime on will make the printout of converted // programs significantly closer to that resulting from the use of // old fortran RWBROOK package. The setting will last until the // next call to simrwbrook_(..). // // FORTRAN equivalent: subroutine SimRWBROOK ( iOnOff ) // ~~~~~~~~~~~~~~~~~~~ integer iOnOff FORTRAN_SUBR ( SIMRWBROOK,simrwbrook, ( int * iOnOff ), ( int * iOnOff ), ( int * iOnOff ) ); // ------------------------------------------------------------------ // mmdb_f_open_(..) associates a coordinate file with channel number // given in iUnit. If iUnit was previously associated with another // or the same file, the file gets complete logical reinitialization // which means that all previous modifications to the file are lost // unless stored on disk with mmdb_f_write_(..) or mmdb_f_close_(..). // // If the file is to be opened for input (RWStat is set to // "INPUT"), all contents of the file is read into memory. It may be // then modified and written back into a file (same or different). // // If the file is to be opened for output (RWStat is set to // "OUTPUT"), no file is physically opened, and only empty data // structure is created in the memory. It may then be added with the // data and stored in a disk file. // // If FType is set to "PDB" or " ", the physical file is assumed // to be read or written in the PDB format. "CIF" option is reserved // for mmCIF files and is not realized at present. "BIN" means // binary format. Note that both file name and file type may be // changed before writting the file (see mmdb_f_setname_(..) and // mmdb_f_settype_(..)). // // mmdb_f_open(..) sets an internal pointer to "before the first" // atom in the file (therefore it should be advanced to get access // to the first atom, see mmdb_f_advance1_(..)). This pointer is used // for getting atomic coordinates and other atomic characteristics // from the file structure or for storing them into the structure. // The pointer may be advanced, backspaced or set to a specific // position in the file structure (see below). // // iRet returns the error code (defined above). Extended // information on the error may be then obtained through the // geterror_(..) function immediately after return from // mmdb_f_open_(..). // FORTRAN equivalent: subroutine MMDB_F_Open ( LName,RWStat,FType, // ~~~~~~~~~~~~~~~~~~~ iUnit,iRet ) // character*(*) LName,RWStat,FType // integer iUnit,iRet FORTRAN_SUBR ( MMDB_F_OPEN, mmdb_f_open, ( // lengths-at-end list mmdb::machine::fpstr LName, // logical name mmdb::machine::fpstr RWStat, // "INPUT" or "OUTPUT" mmdb::machine::fpstr FType, // "PDB", "CIF", "BIN" or " " int * iUnit, // channel number int * iRet, // returns error code int LName_len, // fortran-hidden length of LName int RWStat_len, // fortran-hidden length of RWStat int FType_len // fortran-hidden length of FType ), ( // lengths-in-structure list mmdb::machine::fpstr LName, mmdb::machine::fpstr RWStat, mmdb::machine::fpstr FType, int * iUnit, int * iRet ), ( // lengths-follow list mmdb::machine::fpstr LName, int LName_len, mmdb::machine::fpstr RWStat, int RWStat_len, mmdb::machine::fpstr FType, int FType_len, int * iUnit, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_open1_(..) is equivalent to mmdb_f_open_(..) but takes directly // the file name (FName) instead of logical name (LName). // // FORTRAN equivalent: subroutine MMDB_F_Open1 ( FName,RWStat,FType, // ~~~~~~~~~~~~~~~~~~~ iUnit,iRet ) // character*(*) FName,RWStat,FType // integer iUnit,iRet FORTRAN_SUBR ( MMDB_F_OPEN1, mmdb_f_open1, ( // lengths-at-end list mmdb::machine::fpstr FName, // file name mmdb::machine::fpstr RWStat, // "INPUT" or "OUTPUT" mmdb::machine::fpstr FType, // "PDB", "CIF", "BIN" or " " int * iUnit, // channel number int * iRet, // returns error code int FName_len, // fortran-hidden length of FName int RWStat_len, // fortran-hidden length of RWStat int FType_len // fortran-hidden length of FType ), ( // lengths-in-structure list mmdb::machine::fpstr FName, mmdb::machine::fpstr RWStat, mmdb::machine::fpstr FType, int * iUnit, int * iRet ), ( // lengths-follow list mmdb::machine::fpstr FName, int FName_len, mmdb::machine::fpstr RWStat, int RWStat_len, mmdb::machine::fpstr FType, int FType_len, int * iUnit, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_copy_(..) copies the specified part(s) of iUnit2 into iUnit1. // All data which contained in the corresponding part(s) of iUnit1 // before the copying, is destroyed. // // FORTRAN equivalent: subroutine MMDB_F_Copy ( iUnit1,iUnit2, // ~~~~~~~~~~~~~~~~~~~ copyKey,iRet ) // integer iUnit1,iUnit2,copyKey,iRet FORTRAN_SUBR ( MMDB_F_COPY, mmdb_f_copy, ( // lengths-at-end list int * iUnit1, // destination unit int * iUnit2, // source unit int * copyKey, // copy key: // = 1 copy all // = 2 copy all except coordinates // = 3 copy title section only // = 4 copy crystallographic // section only // = 5 copy coordinate section only // any other value does not do anything int * iRet // return code: // =0 if success // =RWBERR_NoChannel if a unit // does not exist // =RWBERR_NoFile if a unit // was not opened ), ( // lengths-in-structure list int * iUnit1, int * iUnit2, int * copyKey, int * iRet ), ( // lengths-follow list int * iUnit1, int * iUnit2, int * copyKey, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_delete_(..) deletes the specified parts of iUnit-th unit. // The delete keys are exactly the same as copy keys in mmdb_f_copy_(..). // // FORTRAN equivalent: subroutine MMDB_F_Delete ( iUnit1,iUnit2, // ~~~~~~~~~~~~~~~~~~~ CopyAtoms,iRet ) // integer iUnit1,iUnit2,CopyAtoms,iRet FORTRAN_SUBR ( MMDB_F_DELETE, mmdb_f_delete, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" int * delKey, // delete key: // = 1 delete all // = 2 delete all except coordinates // = 3 delete title section only // = 4 delete crystallographic // section only // = 5 delete coordinate section only // any other value does not do anything int * iRet // return code: // =0 if success // =RWBERR_NoChannel if a unit // does not exist // =RWBERR_NoFile if a unit // was not opened ), ( // lengths-in-structure list int * iUnit, int * delKey, int * iRet ), ( // lengths-follow list int * iUnit, int * delKey, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_settype_(..) changes the type and/or the read/write mode of // a unit iUnit, previously initialized with mmdb_f_open_(..). The file // is not read from or purged onto disk, no data change occurs. // // iRet returns either RWBERR_NoChannel if the unit was not // previously initialized by mmdb_f_open_(..), or RWBERR_Ok in the case // of success. // FORTRAN equivalent: subroutine MMDB_F_SetType ( iUnit,FType, // ~~~~~~~~~~~~~~~~~~~ RWState,iRet ) // character*(*) FType,RWState // integer iUnit,iRet FORTRAN_SUBR ( MMDB_F_SETTYPE, mmdb_f_settype, ( // lengths-at-end list int * iUnit, // unit number mmdb::machine::fpstr FType, // "PDB", "CIF", "BIN" or " " mmdb::machine::fpstr RWStat, // "INPUT" or "OUTPUT" int * iRet, // returns -1 if unit not found, // otherwise 0 int FType_len, // fortran-hidden length of FType int RWStat_len // fortran-hidden length of RWStat ), ( // lengths-in-structure list int * iUnit, mmdb::machine::fpstr FType, mmdb::machine::fpstr RWStat, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::fpstr FType, int FType_len, mmdb::machine::fpstr RWStat, int RWStat_len, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_setname_(..) changes the file name for a unit iUnit, // previously initialized with mmdb_f_open_(..). The file is not // read from or purged onto disk, no data change occurs. // // iRet returns either RWBERR_NoChannel if the unit was not // previously initialized by mmdb_f_open_(..), or RWBERR_Ok in the case // of success. // FORTRAN equivalent: subroutine MMDB_F_SetName ( iUnit,FName, // ~~~~~~~~~~~~~~~~~~~ iRet ) // character*(*) FName // integer iUnit,iRet FORTRAN_SUBR ( MMDB_F_SETNAME, mmdb_f_setname, ( // lengths-at-end list int * iUnit, // unit number mmdb::machine::fpstr FName, // file name int * iRet, // returns -1 if unit not found, // otherwise 0 int FName_len // fortran-hidden length of FName ), ( // lengths-in-structure list int * iUnit, mmdb::machine::fpstr FName, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::fpstr FName, int FName_len, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_write_(..) writes content of unit iUnit into a disk file. // iRet will be set to -1 if the unit was not previously opened with // mmdb_f_open_(..). If writting was successful, iRet is set to 0, // otherwise geterror(..) will return an information about the // error occured. // // Note that you may write even units associated with input in // call to mmdb_f_open(..). The file type does not change unless // explicitely changed with mmdb_f_settype_(..). // FORTRAN equivalent: subroutine MMDB_F_Write ( iUnit,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,iRet FORTRAN_SUBR ( MMDB_F_WRITE, mmdb_f_write, ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_close_(..) acts as mmdb_f_write_(..) if unit iUnit has been // associated with output in mmdb_f_open_(..) or in the call to // mmdb_f_settype(..). After writing the file, the unit iUnit is // completely disposed. // If unit iUnit is associated with input, mmdb_f_close_(..) merely // disposes it and all the information contained will be lost. // FORTRAN equivalent: subroutine MMDB_F_Close ( iUnit,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,iRet FORTRAN_SUBR ( MMDB_F_CLOSE, mmdb_f_close, ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ) ); // ------------------------------------------------------------------ // If unit iUnit is associated with input, mmdb_f_advance_(..) sets // the internal pointer on the next atom in the file. The atom // properties may then be retrieved using mmdb_f_atom_(..) and // mmdb_f_coord_(..). If iTer is set to 0, then 'ter' cards are // completely ignored. If iTer is set to 1, then 'ter' card will // cause return with iRet=1 with internal pointer left on this 'ter' // card. iRet=2 mean end of file, and iRet=0 means that the pointer // was successfully advanced to the next atom. // // If unit iUnit is associated with output, mmdb_f_advance_(..) // merely advances the pointer. No actual change in the data // structure or on disk occurs. The new position will be filled with // atom data after execution of mmdb_f_atom_(..) and/or mmdb_f_coord_(..). // The pointer WILL NOT be advanced if none of these functions were // called since last advancement, in which case iRet will return // RWBERR_NoAdvance. After successfull advancement, iRet will // return 0. // FORTRAN equivalent: subroutine MMDB_F_Advance ( iUnit,iOut,iTer,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,iOut,iTer,iRet // Relation to the former XYZAdvance fortran subroutione: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // subroutine XYZAdvance ( iUnit,iOut,iTer,*,* ) // integer iRet // character*80 ErrLin // call MMDB_F_Advance ( iUnit,iOut,iTer,iRet ) // if (iRet.eq.1) return 1 // if (iRet.eq.2) return 2 // if (iRet.eq.RWBERR_NoChannel) then // ErrLin = ' ERROR: in MMDB_F_ADVANCE file has not been opened' // call CCPErr ( 1,ErrLin ) // endif // return // end // // where parameter iOut IS NOT USED. FORTRAN_SUBR ( MMDB_F_ADVANCE, mmdb_f_advance, ( // lengths-at-end list int * iUnit, // unit number int * iOut, // output echo file int * iTer, // FLAG =1, return iRet=1 if 'ter' card found // =0, do not return on 'ter' card int * iRet // =0 if normal return // =1 if return on 'ter' card (iTer=1) // =2 if return on end of file // =3 if return on 'hetatm' card // =RWBERR_NoChannel if unit does not exist // =RWBERR_NoAdvance if pointer was not // advanced ), ( // lengths-in-structure list int * iUnit, int * iOut, int * iTer, int * iRet ), ( // lengths-follow list int * iUnit, int * iOut, int * iTer, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_rewd_(..) sets the internal pointer to the "begining" of // the data structure associated with unit *iUnit. This means that // one should the "advance" it with mmdb_f_advance_(..) in order // to get access to the first atom. // iRet returns RWBERR_NoChannel if iUnit-th unit was not // initialized, RWBWAR_RewOutput if the unit was associated with // output, and 0 otherwise. // FORTRAN equivalent: subroutine MMDB_F_Rewd ( iUnit,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,iRet FORTRAN_SUBR ( MMDB_F_REWD, mmdb_f_rewd, ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_bksp_(..) shifts the internal pointer for one atom back in // the data structure associated with unit *iUnit. This means that // the combination of mmdb_f_advance1_(..) and mmdb_f_bksp_(..) leaves the // pointer unchanged. // iRet returns RWBERR_NoChannel if iUnit-th unit was not // initialized, and sets bit RWBWAR_RewOutput if the unit was // associated with output, RWBWAR_FileTop if the pointer is already // on the top of the structure, and 0 otherwise. // FORTRAN equivalent: subroutine MMDB_F_Bksp ( iUnit,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,iRet FORTRAN_SUBR ( MMDB_F_BKSP, mmdb_f_bksp, ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_seek_(..) sets the internal pointer to the specified // position. If fPos==0, *iRet will return bit RWBWAR_FileTop. // If unit iUnit is associated with input, iRet will return 2 if // fPos is given a value outside the file range, 1 if a 'ter' card // is met and 3 if a 'hetatm' card is met. // iRet returns RWBERR_NoChannel if iUnit-th unit was not // initialized, and RWBERR_EmptyPointer if fPos-th position in the // input file is not occupied. // FORTRAN equivalent: subroutine MMDB_F_Seek ( iUnit,fPos,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,fPos,iRet FORTRAN_SUBR ( MMDB_F_SEEK, mmdb_f_seek, ( // lengths-at-end list int * iUnit, // unit number int * fPos, // position to set int * iRet // return code: // 0 Ok // 1 'ter' card met // 2 end of file // 3 'hetatm' card met // <0 error: // RWBERR_NoChannel // iUnit was not // initialized // RWBERR_EmptyPointer // fPos-th position ), ( // lengths-in-structure list int * iUnit, int * fPos, int * iRet ), ( // lengths-follow list int * iUnit, int * fPos, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_atom_(..) reads or writes the atom name, residue name, // chain name and other parameters listed from/into the // data structure associated with the unit number iUnit (cf. // mmdb_f_open_(..)). The position in the structure is adjusted // with the help of mmdb_f_advance_(..), mmdb_f_rewd_(..) or // mmdb_f_bksp_(..). // FORTRAN equivalent: subroutine MMDB_F_Atom ( iUnit,iSer,AtNam, // ~~~~~~~~~~~~~~~~~~~ ResNam,ChnNam,iResN,ResNo, // InsCod,AltCod,SegID,IZ,ID, // iRet ) // integer iUnit,iSer,iResN,IZ,iRet // character*(*) AtNam,ResNam,ChnNam,ResNo // character*(*) InsCod,AltCod,SegID,ID FORTRAN_SUBR ( MMDB_F_ATOM, mmdb_f_atom, ( // lengths-at-end list int * iUnit, // unit number int * iSer, // atom serial number mmdb::machine::fpstr AtNam, // atom name (left justified) mmdb::machine::fpstr ResNam, // residue name mmdb::machine::fpstr ChnNam, // chain name int * iResN, // residue number as an integer mmdb::machine::fpstr ResNo, // residue number as character (input only) mmdb::machine::fpstr InsCod, // the insertion code mmdb::machine::fpstr AltCod, // the alternate conformation code mmdb::machine::fpstr segID, // segment ID int * IZ, // atomic number (input only, returned as // 7 from ambiguous atoms) mmdb::machine::fpstr ID, // atomic ID related to atomic number // (element symbol right justified), plus // the ionic state +2, +3 etc.. // int * iRet, // returns // RWBERR_NoChannel if iUnit was not // initialized // RWBERR_EmptyPointer if atom was not // advanced // RWBERR_Error1 internal error #1 // RWBERR_Error2 internal error #2 // RWBERR_Error3 internal error #3 // // >=0 : success, warning flags: // RWBWAR_WrongSerial if serial number // differs from the position // number in the file // RWBWAR_UnkFormFactor unknown formfactor // RWBWAR_AmbFormFactor ambiguous formfactor // int AtNam_len, // fortran-hidden length of AtNam int ResNam_len, // fortran-hidden length of ResNam int ChnNam_len, // fortran-hidden length of ChnNam int ResNo_len, // fortran-hidden length of ResNo int InsCod_len, // fortran-hidden length of InsCod int AltCod_len, // fortran-hidden length of AltCod int segID_len, // fortran-hidden length of SegID int ID_len // fortran-hidden length of ID ), ( // lengths-in-structure list int * iUnit, int * iSer, mmdb::machine::fpstr AtNam, mmdb::machine::fpstr ResNam, mmdb::machine::fpstr ChnNam, int * iResN, mmdb::machine::fpstr ResNo, mmdb::machine::fpstr InsCod, mmdb::machine::fpstr AltCod, mmdb::machine::fpstr segID, int * IZ, mmdb::machine::fpstr ID, int * iRet ), ( // lengths-follow list int * iUnit, int * iSer, mmdb::machine::fpstr AtNam, int AtNam_len, mmdb::machine::fpstr ResNam, int ResNam_len, mmdb::machine::fpstr ChnNam, int ChnNam_len, int * iResN, mmdb::machine::fpstr ResNo, int ResNo_len, mmdb::machine::fpstr InsCod, int InsCod_len, mmdb::machine::fpstr AltCod, int AltCod_len, mmdb::machine::fpstr segID, int segID_len, int * IZ, mmdb::machine::fpstr ID, int ID_len, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_copyatom_(..) copies atom from current position in // channel iUnit1 to current position in channel iUnit2. // FORTRAN equivalent: subroutine MMDB_F_CopyAtom ( iUnit1, // ~~~~~~~~~~~~~~~~~~~ iUnit2,iRet ) // integer iUnit1,iUnit2,iRet FORTRAN_SUBR ( MMDB_F_COPYATOM, mmdb_f_copyatom, ( // length-at-end list int * iUnit1, // source channel number int * iUnit2, // destination channel number int * iRet // returns // RWBERR_NoChannel if iUnit was not // initialized // RWBERR_EmptyPointer if atom was not // advanced // >=0 : success ), ( // length-in-structure list int * iUnit1, int * iUnit2, int * iRet ), ( // length-follow list int * iUnit1, int * iUnit2, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_coord_(..) reads or writes the atom coordinates, occupancy // and temperature factor from/into the data structure associated // with the unit number iUnit (cf. mmdb_f_open_(..)). The position in // the structure is adjusted with the help of mmdb_f_advance_(..), // mmdb_f_rewd_(..) or mmdb_f_bksp_(..). // It is important that mmdb_f_coord_(..) was called AFTER // mmdb_f_atom_(..) if channel iUnit is associated with output // (otherwise iRet will return RWBERR_EmptyPointer). // FORTRAN equivalent: subroutine MMDB_F_Coord ( iUnit,XFlag,BFlag, // ~~~~~~~~~~~~~~~~~~~ x,y,z,occ,BIso,U,iRet ) // integer iUnit,iRet // character*(*) XFlag,BFlag // real x,y,z,occ,BIso,U(6) // Be sure that real-type parameters of mmdb_f_coord_(..) match those // of FORTRAN call. The real type is set with typedef apireal // statement in the begining of this file. FORTRAN_SUBR ( MMDB_F_COORD, mmdb_f_coord, ( // lengths-at-end list int * iUnit, // unit number mmdb::machine::fpstr XFlag, // "F" or "O" flag for the fractional // or orthogonal coordinates x,y,z // for output files XFlag may also be // set to "HF" or "HO", where "F" and // "O" have the same meaning as before // and "H" indicates that the atom // should be marked as heteroatom mmdb::machine::fpstr BFlag , // "F" or "O" flag for temperature // factor in fractional or orthogonal // Us mmdb::machine::apireal * x, // x-coordinate mmdb::machine::apireal * y, // y-coordinate mmdb::machine::apireal * z, // z-coordinate mmdb::machine::apireal * occ, // occupancy mmdb::machine::apireal * BIso, // isotropic temperature factor mmdb::machine::apireal * U, // array(6) of the anisotr. t-factor int * iRet, // returns // RWBERR_NoChannel if iUnit was not // initialized // RWBERR_EmptyPointer if atom was not // advanced // RWBERR_NoMatrices if transformation // matrices are // undefined // RWBERR_NoCoordinates if coordinates were // not set in the atom // // >=0 : success, warning flags: // RWBERR_NoOccupancy if occupancy was // not set in the atom // RWBERR_NoTempFactor if temp. factor was // not set in the atom // int XFlag_len, // fortran-hidden length of XFlag int BFlag_len // fortran-hidden length of BFlag ), ( // lengths-in-structure list int * iUnit, mmdb::machine::fpstr XFlag, mmdb::machine::fpstr BFlag, mmdb::machine::apireal * x, mmdb::machine::apireal * y, mmdb::machine::apireal * z, mmdb::machine::apireal * occ, mmdb::machine::apireal * BIso, mmdb::machine::apireal * U, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::fpstr XFlag, int XFlag_len, mmdb::machine::fpstr BFlag, int BFlag_len, mmdb::machine::apireal * x, mmdb::machine::apireal * y, mmdb::machine::apireal * z, mmdb::machine::apireal * occ, mmdb::machine::apireal * BIso, mmdb::machine::apireal * U, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_setter_(..) sets the termination flag, so that the current // atom will be converted into terminator of a chain and appear as // 'ter' card in the output. The atom should be set by mmdb_f_atom_ // first, but the coordinates (mmdb_f_coord_(..)) do not have to be // specified. // FORTRAN equivalent: subroutine MMDB_F_SetTer ( iUnit,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,iRet FORTRAN_SUBR ( MMDB_F_SETTER, mmdb_f_setter, ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_sethet_(..) sets the heteroatom flag, so that the current // atom will appear as 'hetatm' card in the output. The atom should // be set by mmdb_f_atom_ first and then mmdb_f_coord_(..) and // mmdb_f_sethet_(..) should be called to specify its coordinates and // heteroatom status. // FORTRAN equivalent: subroutine MMDB_F_SetHet ( iUnit,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,iRet FORTRAN_SUBR ( MMDB_F_SETHET, mmdb_f_sethet, ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ), ( int * iUnit, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_getnofncsmates_(..) returns the number of NCS mates not // given in the file (iGiven=0). // // Negative returns N<0 mean an error. // // FORTRAN equivalent: subroutine MMDB_F_GetNofNCSMates ( iUnit,N ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,N FORTRAN_SUBR ( MMDB_F_GETNOFNCSMATES, mmdb_f_getnofncsmates, ( int * iUnit, int * N ), ( int * iUnit, int * N ), ( int * iUnit, int * N ) ); // ------------------------------------------------------------------ // mmdb_f_setcell_(..) sets the crystal cell properties and calculates // the orthogonal-fractional transformation matrices for unit iUnit. // FORTRAN equivalent: subroutine MMDB_F_SetCell ( iUnit,a,b,c, // ~~~~~~~~~~~~~~~~~~~ alpha,beta,gamma, // ArgNCode,iRet ) // integer iUnit,ArgNCode,iRet // real a,b,c,alpha,beta,gamma // Relation to the former RBFRAC2 FORTRAN subroutine: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // subroutine RBFRAC2 ( a,b,c,alpha,beta,gamma,ArgNCode ) // // ** the unit number iUnit and buffer for the return code iRet // have to be supplied. FORTRAN_SUBR ( MMDB_F_SETCELL, mmdb_f_setcell, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::apireal * a, // cell parameter a, angstroms mmdb::machine::apireal * b, // cell parameter b, angstroms mmdb::machine::apireal * c, // cell parameter c, angstroms mmdb::machine::apireal * alpha, // cell parameter alpha, degrees mmdb::machine::apireal * beta, // cell parameter beta, degrees mmdb::machine::apireal * gamma, // cell parameter gamma, degrees int * ArgNCode, // orthogonalization code, 1-6 int * iRet // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_Disagreement if a // disagreement in // cell parameters // was found // RWBERR_NoOrthCode if no // orthogonalization // code was found // RWBERR_NoCheck if check // of cell parameters // has failed. // The last three returns would // rather indicate a programming // error in mmdb_rwbrook.cpp ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * a, mmdb::machine::apireal * b, mmdb::machine::apireal * c, mmdb::machine::apireal * alpha, mmdb::machine::apireal * beta, mmdb::machine::apireal * gamma, int * ArgNCode, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * a, mmdb::machine::apireal * b, mmdb::machine::apireal * c, mmdb::machine::apireal * alpha, mmdb::machine::apireal * beta, mmdb::machine::apireal * gamma, int * ArgNCode, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_wbspgrp_(..) sets the space group // FORTRAN equivalent: subroutine MMDB_F_WBSpGrp ( iUnit,spGroup,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,iRet // character*(*) spGroup // Relation to the former WBSpGrp FORTRAN subroutine: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // subroutine WBSpGrp ( spGroup ) // // ** the unit number iUnit and buffer for the return code iRet // have to be supplied. FORTRAN_SUBR ( MMDB_F_WBSPGRP, mmdb_f_wbspgrp, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::fpstr spGroup, // space group int * iRet, // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed int spGroup_len // fortran-hidden length of spGroup ), ( // lengths-in-structure list int * iUnit, mmdb::machine::fpstr spGroup, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::fpstr spGroup, int spGroup_len, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_rbspgrp_(..) retrieves the space group // FORTRAN equivalent: subroutine MMDB_F_RBSpGrp ( iUnit,spGroup,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,iRet // character*(*) spGroup // Relation to the former RBSpGrp FORTRAN subroutine: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // subroutine RBSpGrp ( spGroup ) // // ** the unit number iUnit and buffer for the return code iRet // have to be supplied. FORTRAN_SUBR ( MMDB_F_RBSPGRP, mmdb_f_rbspgrp, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::fpstr spGroup, // space group int * iRet, // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed int spGroup_len // fortran-hidden length of spGroup ), ( // lengths-in-structure list int * iUnit, mmdb::machine::fpstr spGroup, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::fpstr spGroup, int spGroup_len, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_wbcell_(..) sets the crystal cell properties into the // channel iUnit. // FORTRAN equivalent: subroutine MMDB_F_WBCell ( iUnit,ArgCell, // ~~~~~~~~~~~~~~~~~~~ ArgNCode,iRet ) // integer iUnit,ArgNCode,iRet // real ArgCell(6) // // Relation to the former WBCELL FORTRAN subroutine: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // subroutine WBCELL ( iUnit,ArgCell,ArgNCode ) // // ** the buffer for the return code iRet has to be supplied FORTRAN_SUBR ( MMDB_F_WBCELL, mmdb_f_wbcell, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::apireal * ArgCell, // array to accept the cell parameters // if ArgCell(1) is set to 0, then // the cell does not change int * ArgNCode, // orthogonalisation code // if ArgNCode is set to 0, then // the orthogonalisation matrices // do not change int * iRet // return code // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * ArgCell, int * ArgNCode, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * ArgCell, int * ArgNCode, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_rbcell_(..) retrieves the crystal cell properties from the // channel iUnit. // FORTRAN equivalent: subroutine MMDB_F_RBCell ( iUnit,celld,cvol,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,iRet // real celld(6),cvol // character*(*) spGroup // Relation to the former RBCELL FORTRAN subroutine: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // subroutine RBCELL ( celld,cvol ) // // ** the unit number iUnit and buffer for the return code iRet // have to be supplied. FORTRAN_SUBR ( MMDB_F_RBCELL, mmdb_f_rbcell, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::apireal * celld, // array to accept the cell parameters mmdb::machine::apireal * cvol, // returns the cell volume int * iRet // return code // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_Parameters if the // cell parameters // were not set // RWBERR_NoOrthCode if no // orthogonalization // code was found // RWBERR_NoCheck if check // of cell parameters // has failed. // The last three returns would // rather indicate a programming // error in mmdb_rwbrook.cpp ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * celld, mmdb::machine::apireal * cvol, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * celld, mmdb::machine::apireal * cvol, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_rbcelln_(..) retrieves the crystal cell properties from the // channel iUnit. // FORTRAN equivalent: subroutine MMDB_F_RBCellN ( iUnit,celld,cvol, // ~~~~~~~~~~~~~~~~~~~ ArgNCode,iRet ) // integer iUnit,ArgNCode,iRet // real celld(6),cvol // Relation to the former RBCELL FORTRAN subroutine: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // subroutine RBCELL ( celld,cvol ) // // ** the unit number iUnit, buffer for orthogonalization code // ArgNCode and for the return code iRet have to be supplied. FORTRAN_SUBR ( MMDB_F_RBCELLN, mmdb_f_rbcelln, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::apireal * celld, // array to accept the cell parameters mmdb::machine::apireal * cvol, // returns the cell volume int * ArgNCode, // returns the orthogonalization code, 1-6 int * iRet // return code // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_Parameters if the // cell parameters // were not set // RWBERR_NoOrthCode if no // orthogonalization // code was found // RWBERR_NoCheck if check // of cell parameters // has failed. // The last three returns would // rather indicate a programming // error in mmdb_rwbrook.cpp ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * celld, mmdb::machine::apireal * cvol, int * ArgNCode, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * celld, mmdb::machine::apireal * cvol, int * ArgNCode, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_rbrcel_(..) retrieves the reciprocal cell dimensions and // reciprocal cell volume from the channel iUnit. // FORTRAN equivalent: subroutine MMDB_F_RBRCel ( iUnit,rcell,rvol, // ~~~~~~~~~~~~~~~~~~~ iRet ) // integer iUnit,iRet // real rcell(6),rvol // Relation to the former RBRCEL FORTRAN subroutine: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // subroutine RBRCEL ( rcell,rvol ) // // ** the unit number iUnit and buffer for the return code iRet // have to be supplied. FORTRAN_SUBR ( MMDB_F_RBRCEL, mmdb_f_rbrcel, ( // lengths-at-end list int * iUnit, // unit number mmdb::machine::apireal * rcell, // array to accept the reciprocal // cell parameters mmdb::machine::apireal * rvol, // returns the reciprocal cell volume int * iRet // return code // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_Parameters if the // cell parameters // were not set // RWBERR_NoOrthCode if no // orthogonalization // code was found // RWBERR_NoCheck if check // of cell parameters // has failed. // The last three returns would // rather indicate a programming // error in mmdb_rwbrook.cpp ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * rcell, mmdb::machine::apireal * rvol, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * rcell, mmdb::machine::apireal * rvol, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_rborf_(..) fills or retrieves the fractionalising (RF) and // orthogonalising (RO) 4x4 matrices, as well as the orthogonalisation // code (LCode) in/from unit iUnit. // If RO[1][1] (fortran notations, or RO[0] in C/C++) is set to 0.0 // then the matrices are retrieved and returned in RF and RO; // otherwise RF and RO are stored in the unit. // FORTRAN equivalent: subroutine MMDB_F_RBORF ( iUnit,RO,RF, // ~~~~~~~~~~~~~~~~~~~ LCode,iRet ) // integer iUnit,LCode,iRet // real RO(4,4),RF(4,4) // Relation to the former RBRORF2 FORTRAN subroutine: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // subroutine RBRORF2 ( RO,RF,LCode ) // // ** the unit number iUnit and buffer for the return code iRet // have to be supplied. FORTRAN_SUBR ( MMDB_F_RBORF, mmdb_f_rborf, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::apireal * RO, // array for orthogonalising matrix mmdb::machine::apireal * RF, // array for fractionalising matrix int * LCode, // buffer for orthogonalisation code int * iRet // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_NoMatrices if the // orthogonalisation // matrices were not // calculated ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * RO, mmdb::machine::apireal * RF, int * LCode, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * RO, mmdb::machine::apireal * RF, int * LCode, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_orthmat_(..) calculates matrices for standard orthogonalisations // and cell volume. // If Cell(1) is greater then zero, the existing cell parameters // will be substituted. If new cell parameters differ substantially // from the old ones, the returned value of Vol will be negative. // FORTRAN equivalent: subroutine MMDB_F_OrthMat ( iUnit,Cell,Vol, // ~~~~~~~~~~~~~~~~~~~ RRR,iRet // integer iUnit,iRet // real Cell(6),Vol,RRR(3,3,6) // Relation to the former RBFRO1 FORTRAN subroutine: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // subroutine RBFRO1 ( Cell,Vol,RRR ) // // ** the unit number iUnit and buffer for the return code iRet // have to be supplied. FORTRAN_SUBR ( MMDB_F_ORTHMAT, mmdb_f_orthmat, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::apireal * Cell, // array of cell parameters: // Cell(1) - a Cell(4) - alpha // Cell(2) - b Cell(5) - beta // Cell(3) - c Cell(6) - gamma mmdb::machine::apireal * Vol, // returns cell volume mmdb::machine::apireal * RRR, // array (3,3,6), returns // orthogonalisation matrices int * iRet // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_NoMatrices if the // orthogonalisation // matrices were not // calculated ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * Cell, mmdb::machine::apireal * Vol, mmdb::machine::apireal * RRR, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * Cell, mmdb::machine::apireal * Vol, mmdb::machine::apireal * RRR, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_cvanisou_(..) converts between crystallographic bs and // orthogonal Us or the other way round. // FORTRAN equivalent: subroutine MMDB_F_CVAnisou ( iUnit,U,iFlag,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,iFlag,iRet // real U(6) // Relation to the former CVANISOU FORTRAN subroutine: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // subroutine CVANISOU ( U,iFlag ) // // ** the unit number iUnit and buffer for the return code iRet // have to be supplied. FORTRAN_SUBR ( MMDB_F_CVANISOU, mmdb_f_cvanisou, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::apireal * U, // array of coordinates to convert int * iFlag, // =0: convert from fract. to orthog. // =1: convert from orthog. to fract. int * iRet // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // RWBERR_NoMatrices if the // orthogonalisation // matrices were not // calculated ), ( // lengths-in-structure list int * iUnit, mmdb::machine::apireal * U, int * iFlag, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::apireal * U, int * iFlag, int * iRet ) ); // ------------------------------------------------------------------ // mmdb_f_wremark_(..) writes a remark line into data structure. // Generally, it puts the line on its place according to a PDB // keyword which should start the line. The line will be always the // last one in its group (last remark with given number or without // it, last JRNL record, last ATOM etc.). If the keyword is not // recognized, the line is appended after the coordinate section. // iRet will return same codes as those in mmdb_f_open1_(..) plus // additional ones specified below. // FORTRAN equivalent: subroutine MMDB_F_WRemark ( iUnit,Line,iRet ) // ~~~~~~~~~~~~~~~~~~~ integer iUnit,iRet // character*(*) Line // Relation to the former WRemark FORTRAN subroutine: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // subroutine WRemark ( iUnit,Line ) // // ** the buffer for return code iRet has to be supplied FORTRAN_SUBR ( MMDB_F_WREMARK, mmdb_f_wremark, ( // lengths-at-end list int * iUnit, // unit number; *iUnit<=0 means // "the last mentioned unit" mmdb::machine::fpstr Line, // line to be added int * iRet, // return code: // RWBERR_Ok - success // RWBERR_NoChannel if unit // iUnit was not // initialized // RWBERR_NoFile if unit // has been disposed // other return codea are those // returned by mmdb_f_open1_(..) int Line_len // fortran-hidden length of Line ), ( // lengths-in-structure list int * iUnit, mmdb::machine::fpstr Line, int * iRet ), ( // lengths-follow list int * iUnit, mmdb::machine::fpstr Line, int Line_len, int *iRet ) ); /* // ------------------------------------------------------------------ // rbrinv_(..) takes 4x4 real matrix A and returns its inverse in // matrix AI. // FORTRAN equivalent: subroutine RBRInv ( A,AI ) // ~~~~~~~~~~~~~~~~~~~ real A(4,4),AI(4,4) FORTRAN_SUBR ( RBRINV, rbrinv, ( mmdb::machine::apireal * A, mmdb::machine::apireal * AI ), ( mmdb::machine::apireal * A, mmdb::machine::apireal * AI ), ( mmdb::machine::apireal * A, mmdb::machine::apireal * AI ) ); */ /* // ------------------------------------------------------------------ // res3to1_(..) returns the 3-character or 1-character residue // codes. One of them should be supplied (with the other one set // blank), the routine returns the other one. // FORTRAN equivalent: subroutine Res3to1 ( ResNm3,resNm1 ) // ~~~~~~~~~~~~~~~~~~~ character*4 ResNm3 // cgaracter*1 ResNm1 FORTRAN_SUBR ( RES3TO1, res3to1, ( // lengths-at-end list mmdb::machine::fpstr ResNm3, // 3-char name, 4th char // will be set blank mmdb::machine::fpstr ResNm1, // 1-char name int ResNm3_len, // fortran-hidden length of ResNm3 int ResNm1_len // fortran-hidden length of ResNm3 ), ( // lengths-in-structure list mmdb::machine::fpstr ResNm3, mmdb::machine::fpstr ResNm1 ), ( // lengths-follow list mmdb::machine::fpstr ResNm3, int ResNm3_len, mmdb::machine::fpstr ResNm1, int ResNm1_len ) ); */ // ------------------------------------------------------------------ // rberrstop_(..) checks the return code got from one of the above // functions, and if it indicates an error, it issues the following // type of message (example) // // *** RWBROOK error: point code unit function // *** 12 -3 3 MMDB_F_Open // *** file : input.pdb // *** reason : cannot open a file // *** Execution stopped. // // if iStop is set to 0, and one of the following type // // *** RWBROOK error: point code unit function // *** 12 -3 3 MMDB_F_Open // *** file : input.pdb // *** reason : cannot open a file // *** continue running, may crash ... // // if iStop is not null. // // iPlace (12 in the above samples) should be given a number which // is unique through an application; it serves to the identifying // the particular call which caused the problem. The return code // (-3 in the above samples) is that what is back in the iRet // parameter to the above functions. If iRet is set to RWBERR_Ok, // rberrstop_(..) makes no action. If rberrstop_(..) is called // immediately after a call to an RWBROOK function, e.g. // // call MMDB_F_Open ( FName,RWStat,FType,iUnit,iRet ) // call RBErrStop ( 12,iRet,iUnit,0 ) // // then the name of the misfunctioned call (MMDB_F_Open in the above // samples) will be identified automatically and correctly. // FORTRAN equivalent: subroutine RBErrStop ( iPlace,iRet, // ~~~~~~~~~~~~~~~~~~~ iUnit ,iStop ) // integer iUnit,iPlace,iRet,iStop FORTRAN_SUBR ( RBERRSTOP, rberrstop, ( // lengths-at-end list int * iPlace, // (unique) identificator inside an application int * iRet, // return code to check int * iUnit, // unit number int * iStop // if 0 then stop if error ), ( // lengths-in-structure list int * iPlace, int * iRet, int * iUnit, int * iStop ), ( // lengths-follow list int * iPlace, int * iRet, int * iUnit, int * iStop ) ); // ------------------------------------------------------------------ // rbcheckerr_(..) represents a simplified call to rberrstop_(..). // It will work properly only if rbcheckerr_(..) is called // immediately after an API function to be checked: // // call MMDB_F_Open ( FName,RWStat,FType,iUnit,iRet ) // call RBCheckErr ( 12,0 ) // // FORTRAN equivalent: subroutine RBCheckErr ( iPlace,iStop ) // ~~~~~~~~~~~~~~~~~~~ integer iPlace,iStop FORTRAN_SUBR ( RBCHECKERR, rbcheckerr, ( // lengths-at-end list int * iPlace, // (unique) identificator inside an application int * iStop // if 0 then stop if error ), ( // lengths-in-structure list int * iPlace, int * iStop ), ( // lengths-follow list int * iPlace, int * iStop ) ); #endif mmdb2-2.0.5/mmdb2/mmdb_machine_.cpp0000664000175000017500000001170712401105774013720 00000000000000// $Id: mmdb_machine.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : Machine // ~~~~~~~~~ // **** Functions : mmdb::machine::GetMachineID - returns ID code // ~~~~~~~~~~~ for the machine // mmdb::machine::GetMachineName - returns name of // the machine // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include "mmdb_machine_.h" namespace mmdb { namespace machine { #ifdef CALL_LIKE_SUN int GetMachineID() { int k = CALL_LIKE_SUN; switch (k) { case 1 : return MACHINE_ALLIANT; case 2 : return MACHINE_CONVEX; case 3 : return MACHINE_ESV; case 4 : return MACHINE_SGI; case 5 : return MACHINE_SOLBOURNE; case 6 : return MACHINE_SOLARIS; case 7 : return MACHINE_ALPHA; case 8 : return MACHINE_F2C_G77; case 9 : return MACHINE_LINUX; default : return MACHINE_UNKNOWN; } } #elif defined(CALL_LIKE_HPUX) int GetMachineID() { int k = CALL_LIKE_HPUX; switch (k) { case 1 : return MACHINE_RS6000; case 2 : return MACHINE_HP9000; default : return MACHINE_UNKNOWN; } } #elif defined(CALL_LIKE_STARDENT) int GetMachineID() { int k = CALL_LIKE_STARDENT; switch (k) { case 1 : return MACHINE_ARDENT; case 2 : return MACHINE_TITAN; case 3 : return MACHINE_STARDENT; default : return MACHINE_UNKNOWN; } } #elif defined(CALL_LIKE_VMS) int GetMachineID() { return MACHINE_VMS; } #elif defined(CALL_LIKE_MVS) int GetMachineID() { return MACHINE_MVS; } #else int GetMachineID() { return MACHINE_UNKNOWN; } #endif static cpstr MCH_SGI = cpstr("Silicon Graphics"); static cpstr MCH_RS6000 = cpstr("IBM RS/6000"); static cpstr MCH_ALLIANT = cpstr("Alliant"); static cpstr MCH_ARDENT = cpstr("Ardent"); static cpstr MCH_TITAN = cpstr("Titan"); static cpstr MCH_STARDENT = cpstr("Stardent"); static cpstr MCH_CONVEX = cpstr("Convex"); static cpstr MCH_ESV = cpstr("Evans or Sutherland"); static cpstr MCH_HP9000 = cpstr("Hewlett Packard 9000"); static cpstr MCH_SOLBOURNE = cpstr("Solbourne"); static cpstr MCH_SOLARIS = cpstr("Solaris"); static cpstr MCH_ALPHA = cpstr("DEC Alpha"); static cpstr MCH_VMS = cpstr("A VMS machine"); static cpstr MCH_MVS = cpstr("MS Windows"); static cpstr MCH_F2C_G77 = cpstr("SUN compatible"); static cpstr MCH_LINUX = cpstr("Linux"); cpstr GetMachineName ( int MachineID ) { switch (MachineID) { case MACHINE_SGI : return MCH_SGI; case MACHINE_RS6000 : return MCH_RS6000; case MACHINE_ALLIANT : return MCH_ALLIANT; case MACHINE_ARDENT : return MCH_ARDENT; case MACHINE_TITAN : return MCH_TITAN; case MACHINE_STARDENT : return MCH_STARDENT; case MACHINE_CONVEX : return MCH_CONVEX; case MACHINE_ESV : return MCH_ESV; case MACHINE_HP9000 : return MCH_HP9000; case MACHINE_SOLBOURNE : return MCH_SOLBOURNE; case MACHINE_SOLARIS : return MCH_SOLARIS; case MACHINE_ALPHA : return MCH_ALPHA; case MACHINE_VMS : return MCH_VMS; case MACHINE_MVS : return MCH_MVS; case MACHINE_F2C_G77 : return MCH_F2C_G77; case MACHINE_LINUX : return MCH_LINUX; default : case MACHINE_UNKNOWN : return pstr("Unidentified machine"); } } cpstr GetMachineName() { return GetMachineName ( GetMachineID() ); } } } mmdb2-2.0.5/mmdb2/mmdb_math_align.cpp0000664000175000017500000010263212401105774014256 00000000000000// $Id: mmdb_math_align.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2000-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : Align // ~~~~~~~~~ // **** Classes : mmdb::math::Alignment (char strings alignment) // ~~~~~~~~~~~~ mmdb::math::Alignment1 (int vectors alignment) // // (C) E.Krissinel 2000-2013 // // ================================================================= // #include #include #include "mmdb_math_align.h" namespace mmdb { namespace math { // ===================== CAligParams ====================== AlignParams::AlignParams() : Stream() { InitAlignParams(); } AlignParams::AlignParams ( io::RPStream Object ) : io::Stream ( Object ) { InitAlignParams(); } void AlignParams::InitAlignParams() { gapWeight = -1.0; spaceWeight = -1.0; equalScore = 2.0; nequalScore = -1.0; method = ALIGN_GLOBAL; } void AlignParams::write ( io::RFile f ) { f.WriteReal ( &gapWeight ); f.WriteReal ( &spaceWeight ); f.WriteReal ( &equalScore ); f.WriteReal ( &nequalScore ); f.WriteInt ( &method ); } void AlignParams::read ( io::RFile f ) { f.ReadReal ( &gapWeight ); f.ReadReal ( &spaceWeight ); f.ReadReal ( &equalScore ); f.ReadReal ( &nequalScore ); f.ReadInt ( &method ); } MakeStreamFunctions(AlignParams) // ===================== Alignment ====================== Alignment::Alignment() : io::Stream() { InitAlignment(); } Alignment::Alignment ( io::RPStream Object ) : io::Stream ( Object ) { InitAlignment(); } Alignment::~Alignment() { FreeMemory(); } void Alignment::InitAlignment() { Space = '-'; SLen = 0; TLen = 0; VT = NULL; ET = NULL; FT = NULL; AlgnS = NULL; AlgnT = NULL; AlignKey = ALIGN_GLOBAL; VAchieved = 0.0; SEq = 2.0; SNEq = -1.0; Wg = 0.0; Ws = -1.0; } void Alignment::FreeMemory() { FreeMatrixMemory ( VT,TLen+1,0,0 ); FreeMatrixMemory ( ET,TLen+1,0,0 ); FreeMatrixMemory ( FT,TLen+1,0,0 ); if (AlgnS) { delete[] AlgnS; AlgnS = NULL; } if (AlgnT) { delete[] AlgnT; AlgnT = NULL; } TLen = 0; SLen = 0; } void Alignment::SetAffineModel ( realtype WGap, realtype WSpace ) { Wg = WGap; Ws = WSpace; } void Alignment::SetScores ( realtype SEqual, realtype SNEqual ) { SEq = SEqual; SNEq = SNEqual; } void Alignment::Align ( cpstr S, cpstr T, ALIGN_METHOD Method ) { int i,j,i0,j0; FreeMemory(); AlignKey = Method; switch (Method) { default : case ALIGN_GLOBAL : // global pairwise alignment of S and T BuildGATable ( S,T, false,false ); VAchieved = VT[TLen][SLen]; Backtrace ( S,T,SLen,TLen,false ); if ((AlgnS[0]!=Space) && (AlgnT[0]!=Space)) VAchieved -= Wg; break; case ALIGN_LOCAL : // local pairwise alignment of S and T BuildLATable ( S,T ); VAchieved = 0.0; i0 = -1; j0 = -1; for (i=0;i<=TLen;i++) for (j=0;j<=SLen;j++) if (VT[i][j]>VAchieved) { VAchieved = VT[i][j]; i0 = i; j0 = j; } Backtrace ( S,T,j0,i0,true ); break; case ALIGN_GLOBLOC : // global alignment with non-penalized // end gaps in T BuildGATable ( S,T,false,true ); VAchieved = -MaxReal; i0 = -1; j0 = -1; for (i=0;i<=TLen;i++) if (VT[i][SLen]>VAchieved) { VAchieved = VT[i][SLen]; i0 = i; j0 = SLen; } Backtrace ( S,T,j0,i0,false ); AdjustEnds ( S,T,j0,i0 ); break; case ALIGN_FREEENDS : // global alignment with non-penalized // end gaps in both S and T BuildGATable ( S,T,true,true ); VAchieved = -MaxReal; i0 = -1; j0 = -1; for (i=0;i<=TLen;i++) if (VT[i][SLen]>VAchieved) { VAchieved = VT[i][SLen]; i0 = i; j0 = SLen; } for (j=0;j<=SLen;j++) if (VT[TLen][j]>VAchieved) { VAchieved = VT[TLen][j]; i0 = TLen; j0 = j; } Backtrace ( S,T,j0,i0,false ); AdjustEnds ( S,T,j0,i0 ); } } void Alignment::BuildGATable ( cpstr S, cpstr T, bool FreeSEnd, bool FreeTEnd ) { int i,j; realtype V1; SLen = strlen ( S ); TLen = strlen ( T ); GetMatrixMemory ( VT,TLen+1,SLen+1,0,0 ); GetMatrixMemory ( ET,TLen+1,SLen+1,0,0 ); GetMatrixMemory ( FT,TLen+1,SLen+1,0,0 ); // Base conditions if (FreeSEnd || FreeTEnd) VT[0][0] = RMax(0.0,Wg); else VT[0][0] = Wg; ET[0][0] = VT[0][0]; FT[0][0] = VT[0][0]; if (FreeTEnd) for (i=1;i<=TLen;i++) { V1 = RMax ( 0.0,VT[i-1][0]+Ws ); VT[i][0] = V1; ET[i][0] = V1; } else for (i=1;i<=TLen;i++) { V1 = VT[i-1][0] + Ws; VT[i][0] = V1; ET[i][0] = V1; } if (FreeSEnd) for (j=1;j<=SLen;j++) { V1 = RMax ( 0.0,VT[0][j-1]+Ws ); VT[0][j] = V1; FT[0][j] = V1; } else for (j=1;j<=SLen;j++) { V1 = VT[0][j-1] + Ws; VT[0][j] = V1; FT[0][j] = V1; } // Recurrence for (i=1;i<=TLen;i++) for (j=1;j<=SLen;j++) { V1 = VT[i-1][j-1] + Score(T[i-1],S[j-1]); ET[i][j] = RMax ( ET[i][j-1]+Ws,VT[i][j-1]+Wg+Ws ); FT[i][j] = RMax ( FT[i-1][j]+Ws,VT[i-1][j]+Wg+Ws ); VT[i][j] = RMax ( RMax(V1,ET[i][j]),FT[i][j] ); } FreeMatrixMemory ( ET,TLen+1,0,0 ); FreeMatrixMemory ( FT,TLen+1,0,0 ); // PrintVT ( S,T ); } void Alignment::BuildLATable ( cpstr S, cpstr T ) { int i,j; realtype V1; SLen = strlen ( S ); TLen = strlen ( T ); GetMatrixMemory ( VT,TLen+1,SLen+1,0,0 ); GetMatrixMemory ( ET,TLen+1,SLen+1,0,0 ); GetMatrixMemory ( FT,TLen+1,SLen+1,0,0 ); // Base conditions VT[0][0] = RMax ( 0.0,Wg ); ET[0][0] = VT[0][0]; FT[0][0] = VT[0][0]; for (i=1;i<=TLen;i++) { V1 = RMax ( 0.0,VT[i-1][0]+Ws ); VT[i][0] = V1; ET[i][0] = V1; } for (j=1;j<=SLen;j++) { V1 = RMax ( 0.0,VT[0][j-1]+Ws ); VT[0][j] = V1; FT[0][j] = V1; } // Recurrence for (i=1;i<=TLen;i++) for (j=1;j<=SLen;j++) { V1 = VT[i-1][j-1] + Score(T[i-1],S[j-1]); ET[i][j] = RMax ( ET[i][j-1]+Ws,VT[i][j-1]+Wg+Ws ); FT[i][j] = RMax ( FT[i-1][j]+Ws,VT[i-1][j]+Wg+Ws ); VT[i][j] = RMax ( RMax(V1,ET[i][j]),RMax(0.0,FT[i][j]) ); } FreeMatrixMemory ( ET,TLen+1,0,0 ); FreeMatrixMemory ( FT,TLen+1,0,0 ); // PrintVT ( S,T ); } void Alignment::PrintVT ( cpstr S, cpstr T ) { int i,j; printf ( "\n " ); for (j=0;j<=SLen;j++) printf ( " %2i",j ); printf ( " \n " ); for (j=1;j<=SLen;j++) printf ( " %c ",S[j-1] ); printf ( " \n\n " ); for (i=0;i<=TLen;i++) { if (i>0) printf ( " %2i %c ",i,T[i-1] ); else printf ( " %2i ",i ); for (j=0;j<=SLen;j++) printf ( " %2i",mround(VT[i][j]) ); printf ( " \n " ); } printf ( " \n" ); } void Alignment::Backtrace ( cpstr S, cpstr T, int J, int I, bool StopAtZero ) { int i,j,k, i1,j1, sk,tk; char C; realtype V,SV,TV; bool Stop; // 1. Allocate memory if (AlgnS) delete[] AlgnS; if (AlgnT) delete[] AlgnT; i = SLen+TLen+1; AlgnS = new char[i]; AlgnT = new char[i]; memset ( AlgnS,Space,i ); memset ( AlgnT,Space,i ); // 2. Initialize backtracing i = I; // backtracing j = J; // indices k = 0; // alignment index SV = 0.0; sk = -1; // alignment indices and leading elements TV = 0.0; tk = -1; // for vertical and horizontal sections // 3. Backtracing Stop = false; while ((!Stop) && (i>0) && (j>0)) { V = VT[i][j]; // find next leading element if (VT[i][j-1]>VT[i-1][j]) { i1 = i; j1 = j-1; } else { i1 = i-1; j1 = j; } if (VT[i-1][j-1]>=VT[i1][j1]) { i1 = i-1; j1 = j-1; } //printf ( " i=%i j=%i \n",i,j ); Stop = StopAtZero && (VT[i1][j1]<=0.0); // used at local alignment // treat horizontal section if ((sk<0) || (V>SV)) { sk = k; SV = V; } if ((j1!=j) || Stop) { // end of horizontal section AlgnS[sk] = S[j-1]; sk = -1; } // treat vertical section if ((tk<0) || (V>TV)) { tk = k; TV = V; } if ((i1!=i) || Stop) { // end of vertical section AlgnT[tk] = T[i-1]; tk = -1; } i = i1; j = j1; k++; } if (!StopAtZero) { // 4. Finish the last horizontal section sk = k; while (j>0) AlgnS[k++] = S[--j]; // 5. Finish the last vertical section while (i>0) AlgnT[sk++] = T[--i]; k = IMax ( k,sk ); } // 6. Put the termination character AlgnS[k] = char(0); AlgnT[k] = char(0); // 7. Reverse the strings i = 0; j = k-1; if (StopAtZero) { // should work only for local alignment while ((j>0) && ((AlgnS[j]==Space) || (AlgnT[j]==Space))) j--; k = j+1; AlgnS[k] = char(0); AlgnT[k] = char(0); } while (j>i) { C = AlgnS[i]; AlgnS[i] = AlgnS[j]; AlgnS[j] = C; C = AlgnT[i]; AlgnT[i] = AlgnT[j]; AlgnT[j] = C; i++; j--; } // 8. Collapse the alternating spaces do { k = 0; i = 0; while (AlgnS[k]) { if ((AlgnS[k]==Space) && (AlgnT[k]==Space)) k++; else if ((AlgnS[k]==Space) && (AlgnS[k+1]!=Space) && (AlgnT[k]!=Space) && (AlgnT[k+1]==Space)) { AlgnS[i] = AlgnS[k+1]; AlgnT[i] = AlgnT[k]; k++; } else if ((AlgnS[k]!=Space) && (AlgnS[k+1]==Space) && (AlgnT[k]==Space) && (AlgnT[k+1]!=Space)) { AlgnS[i] = AlgnS[k]; AlgnT[i] = AlgnT[k+1]; k++; } else if (i!=k) { AlgnS[i] = AlgnS[k]; AlgnT[i] = AlgnT[k]; } if (AlgnS[k]) { k++; i++; } } if (i!=k) { // terminating character AlgnS[i] = AlgnS[k]; AlgnT[i] = AlgnT[k]; } } while (k>i); } void Alignment::AdjustEnds ( cpstr S, cpstr T, int J, int I ) { int si,ti,m; if (JI) { k = J-I; strcat ( AlgnT,&(T[IMax(0,TLen-k)]) ); k = strlen ( AlgnS ); m = strlen ( AlgnT ); while (kJ) { k = I-J; strcat ( AlgnS,&(S[IMax(0,SLen-k)]) ); k = strlen ( AlgnT ); m = strlen ( AlgnS ); while (k0.0) && (a>0.0)) return s/a; return 0.0; } realtype Alignment::GetSeqId() { realtype s; int i,n,ne,ns,nt; ne = 0; ns = 0; nt = 0; n = IMin ( strlen(AlgnS),strlen(AlgnT) ); for (i=0;i0.0) return ne/s; return 0.0; } #define WrapPeriod 61 void Alignment::OutputResults ( io::RFile f, cpstr S, cpstr T ) { int k,l,n; char P[3]; P[1] = char(0); if ((!AlgnS) || (!AlgnT)) { f.LF(); f.WriteLine ( pstr(" NO ALIGNMENT HAS BEEN DONE.") ); f.shut(); return; } f.LF(); f.WriteLine ( pstr(" ======== INPUT DATA") ); f.LF(); f.WriteLine ( pstr(" String S:") ); f.Write ( pstr(" ") ); l = 1; k = 0; while (S[k]) { P[0] = S[k++]; f.Write ( P ); l++; if (l>=WrapPeriod) { f.LF(); f.Write ( pstr(" ") ); l = 1; } } f.LF(); f.LF(); f.WriteLine ( pstr(" String T:") ); f.Write ( pstr(" ") ); l = 1; k = 0; while (T[k]) { P[0] = T[k++]; f.Write ( P ); l++; if (l>=WrapPeriod) { f.LF(); f.Write ( pstr(" ") ); l = 1; } } f.LF(); f.LF(); f.WriteParameter ( pstr(" Score equal") ,SEq ,20,10 ); f.WriteParameter ( pstr(" Score unequal"),SNEq,20,10 ); f.LF(); f.WriteParameter ( pstr(" Gap weight") ,Wg ,20,10 ); f.WriteParameter ( pstr(" Space weight") ,Ws ,20,10 ); f.LF(); f.LF(); f.Write ( pstr(" ======== RESULT OF ") ); switch (AlignKey) { default : case ALIGN_GLOBAL : f.Write ( pstr("GLOBAL") ); break; case ALIGN_LOCAL : f.Write ( pstr("LOCAL") ); break; case ALIGN_GLOBLOC : f.Write ( pstr("GLOBAL/LOCAL") ); break; case ALIGN_FREEENDS : f.Write ( pstr("FREE-ENDS") ); } f.WriteLine ( pstr(" ALIGNMENT") ); f.LF(); if (AlignKey==ALIGN_GLOBLOC) { f.WriteLine ( pstr(" End gaps in T-string were not penalized") ); f.LF(); } f.WriteParameter ( pstr(" Highest score achieved:"),VAchieved,26,10 ); f.LF(); f.WriteLine ( pstr(" Aligned S (upper string) and T (lower string):") ); f.LF(); k = 0; n = 0; l = 1; f.Write ( pstr(" ") ); while (AlgnS[k]) { P[0] = AlgnS[k++]; f.Write ( P ); l++; if ((l>=WrapPeriod) || (!AlgnS[k])) { f.LF(); f.Write ( pstr(" ") ); l = 1; while (AlgnT[n] && (lVAchieved) { VAchieved = VT[i][j]; i0 = i; j0 = j; } Backtrace ( S,T,j0,i0,true ); break; case ALIGN_GLOBLOC : // global alignment with non-penalized // end gaps in T BuildGATable ( S,T,false,true ); VAchieved = -MaxReal; i0 = -1; j0 = -1; for (i=0;i<=TLen;i++) if (VT[i][SLen]>VAchieved) { VAchieved = VT[i][SLen]; i0 = i; j0 = SLen; } Backtrace ( S,T,j0,i0,false ); AdjustEnds ( S,T,j0,i0 ); break; case ALIGN_FREEENDS : // global alignment with non-penalized // end gaps in both S and T BuildGATable ( S,T,true,true ); VAchieved = -MaxReal; i0 = -1; j0 = -1; for (i=0;i<=TLen;i++) if (VT[i][SLen]>VAchieved) { VAchieved = VT[i][SLen]; i0 = i; j0 = SLen; } for (j=0;j<=SLen;j++) if (VT[TLen][j]>VAchieved) { VAchieved = VT[TLen][j]; i0 = TLen; j0 = j; } Backtrace ( S,T,j0,i0,false ); AdjustEnds ( S,T,j0,i0 ); } } void Alignment1::BuildGATable ( ivector S, ivector T, bool FreeSEnd, bool FreeTEnd ) { int i,j; realtype V1; GetMatrixMemory ( VT,TLen+1,SLen+1,0,0 ); GetMatrixMemory ( ET,TLen+1,SLen+1,0,0 ); GetMatrixMemory ( FT,TLen+1,SLen+1,0,0 ); // Base conditions if (FreeSEnd || FreeTEnd) VT[0][0] = RMax(0.0,Wg); else VT[0][0] = Wg; ET[0][0] = VT[0][0]; FT[0][0] = VT[0][0]; if (FreeTEnd) for (i=1;i<=TLen;i++) { V1 = RMax ( 0.0,VT[i-1][0]+Ws ); VT[i][0] = V1; ET[i][0] = V1; } else for (i=1;i<=TLen;i++) { V1 = VT[i-1][0] + Ws; VT[i][0] = V1; ET[i][0] = V1; } if (FreeSEnd) for (j=1;j<=SLen;j++) { V1 = RMax ( 0.0,VT[0][j-1]+Ws ); VT[0][j] = V1; FT[0][j] = V1; } else for (j=1;j<=SLen;j++) { V1 = VT[0][j-1] + Ws; VT[0][j] = V1; FT[0][j] = V1; } // Recurrence for (i=1;i<=TLen;i++) for (j=1;j<=SLen;j++) { V1 = VT[i-1][j-1] + Score(T[i-1],S[j-1]); ET[i][j] = RMax ( ET[i][j-1]+Ws,VT[i][j-1]+Wg+Ws ); FT[i][j] = RMax ( FT[i-1][j]+Ws,VT[i-1][j]+Wg+Ws ); VT[i][j] = RMax ( RMax(V1,ET[i][j]),FT[i][j] ); } FreeMatrixMemory ( ET,TLen+1,0,0 ); FreeMatrixMemory ( FT,TLen+1,0,0 ); // PrintVT ( S,T ); } void Alignment1::BuildLATable ( ivector S, ivector T ) { int i,j; realtype V1; GetMatrixMemory ( VT,TLen+1,SLen+1,0,0 ); GetMatrixMemory ( ET,TLen+1,SLen+1,0,0 ); GetMatrixMemory ( FT,TLen+1,SLen+1,0,0 ); // Base conditions VT[0][0] = RMax ( 0.0,Wg ); ET[0][0] = VT[0][0]; FT[0][0] = VT[0][0]; for (i=1;i<=TLen;i++) { V1 = RMax ( 0.0,VT[i-1][0]+Ws ); VT[i][0] = V1; ET[i][0] = V1; } for (j=1;j<=SLen;j++) { V1 = RMax ( 0.0,VT[0][j-1]+Ws ); VT[0][j] = V1; FT[0][j] = V1; } // Recurrence for (i=1;i<=TLen;i++) for (j=1;j<=SLen;j++) { V1 = VT[i-1][j-1] + Score(T[i-1],S[j-1]); ET[i][j] = RMax ( ET[i][j-1]+Ws,VT[i][j-1]+Wg+Ws ); FT[i][j] = RMax ( FT[i-1][j]+Ws,VT[i-1][j]+Wg+Ws ); VT[i][j] = RMax ( RMax(V1,ET[i][j]),RMax(0.0,FT[i][j]) ); } FreeMatrixMemory ( ET,TLen+1,0,0 ); FreeMatrixMemory ( FT,TLen+1,0,0 ); // PrintVT ( S,T ); } void Alignment1::PrintVT ( ivector S, ivector T ) { int i,j; printf ( "\n " ); for (j=0;j<=SLen;j++) printf ( " %2i",j ); printf ( " \n " ); for (j=1;j<=SLen;j++) printf ( " %3i ",S[j-1] ); printf ( " \n\n " ); for (i=0;i<=TLen;i++) { if (i>0) printf ( " %2i %3i ",i,T[i-1] ); else printf ( " %2i ",i ); for (j=0;j<=SLen;j++) printf ( " %2i",mround(VT[i][j]) ); printf ( " \n " ); } printf ( " \n" ); } void Alignment1::Backtrace ( ivector S, ivector T, int J, int I, bool StopAtZero ) { int i,j,k, i1,j1, sk,tk; int C; realtype V,SV,TV; bool Stop; // 1. Allocate memory FreeVectorMemory ( AlgnS,0 ); FreeVectorMemory ( AlgnT,0 ); AlgnLen = 0; k = SLen+TLen+1; GetVectorMemory ( AlgnS,k,0 ); GetVectorMemory ( AlgnT,k,0 ); for (i=0;i0) && (j>0)) { V = VT[i][j]; // find next leading element if (VT[i][j-1]>VT[i-1][j]) { i1 = i; j1 = j-1; } else { i1 = i-1; j1 = j; } if (VT[i-1][j-1]>=VT[i1][j1]) { i1 = i-1; j1 = j-1; } Stop = StopAtZero && (VT[i1][j1]<=0.0); // used at local alignment // treat horizontal section if ((sk<0) || (V>SV)) { sk = k; SV = V; } if ((j1!=j) || Stop) { // end of horizontal section AlgnS[sk] = S[j-1]; sk = -1; } // treat vertical section if ((tk<0) || (V>TV)) { tk = k; TV = V; } if ((i1!=i) || Stop) { // end of vertical section AlgnT[tk] = T[i-1]; tk = -1; } i = i1; j = j1; k++; } if (!StopAtZero) { // 4. Finish the last horizontal section sk = k; while (j>0) AlgnS[k++] = S[--j]; // 5. Finish the last vertical section while (i>0) AlgnT[sk++] = T[--i]; k = IMax ( k,sk ); } // 6. Put the termination character AlgnLen = k; // 7. Reverse the strings i = 0; j = k-1; if (StopAtZero) { // should work only for local alignment while ((j>0) && ((AlgnS[j]==Space) || (AlgnT[j]==Space))) j--; AlgnLen = j+1; } while (j>i) { C = AlgnS[i]; AlgnS[i] = AlgnS[j]; AlgnS[j] = C; C = AlgnT[i]; AlgnT[i] = AlgnT[j]; AlgnT[j] = C; i++; j--; } // 8. Filter out parasite spaces k = 0; i = 0; while (ki); } void Alignment1::AdjustEnds ( ivector S, ivector T, int J, int I ) { int is,it; is = J; it = I; while ((is0.0) && (a>0.0)) return s/a; return 0.0; } void Alignment1::OutputResults ( io::RFile f, ivector S, int lenS, ivector T, int lenT ) { int k,l,n; char P[10]; if ((!AlgnS) || (!AlgnT)) { f.LF(); f.WriteLine ( pstr(" NO ALIGNMENT HAS BEEN DONE.") ); f.shut(); return; } f.LF(); f.WriteLine ( pstr(" ======== INPUT DATA") ); f.LF(); f.WriteLine ( pstr(" String S:") ); f.Write ( pstr(" ") ); l = 1; k = 0; while (k=WrapPeriod) { f.LF(); f.Write ( pstr(" ") ); l = 1; } } f.LF(); f.LF(); f.WriteLine ( pstr(" String T:") ); f.Write ( pstr(" ") ); l = 1; k = 0; while (k=WrapPeriod) { f.LF(); f.Write ( pstr(" ") ); l = 1; } } f.LF(); f.LF(); f.WriteParameter ( pstr(" Score equal") ,SEq ,20,10 ); f.WriteParameter ( pstr(" Score unequal"),SNEq,20,10 ); f.LF(); f.WriteParameter ( pstr(" Gap weight") ,Wg ,20,10 ); f.WriteParameter ( pstr(" Space weight") ,Ws ,20,10 ); f.LF(); f.LF(); f.Write ( pstr(" ======== RESULT OF ") ); switch (AlignKey) { default : case ALIGN_GLOBAL : f.Write ( pstr("GLOBAL") ); break; case ALIGN_LOCAL : f.Write ( pstr("LOCAL") ); break; case ALIGN_GLOBLOC : f.Write ( pstr("GLOBAL/LOCAL") ); break; case ALIGN_FREEENDS : f.Write ( pstr("FREE-ENDS") ); } f.WriteLine ( pstr(" ALIGNMENT") ); f.LF(); if (AlignKey==ALIGN_GLOBLOC) { f.WriteLine ( pstr(" End gaps in T-string were not penalized") ); f.LF(); } f.WriteParameter ( pstr(" Highest score achieved:"), VAchieved,26,10 ); f.LF(); f.WriteLine ( pstr(" Aligned S (upper string) and T " "(lower string):") ); f.LF(); k = 0; n = 0; l = 1; f.Write ( pstr(" ") ); while (k=WrapPeriod) || (!AlgnS[k])) { f.LF(); f.Write ( pstr(" ") ); l = 1; while ((n // ~~~~~~~~~ // **** Functions : mmdb::math::GetTorsion // ~~~~~~~~~~~ mmdb::math::GetAngle // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_Math__ #define __MMDB_Math__ #include "mmdb_mattype.h" namespace mmdb { namespace math { // ------------------------------------------------------------------ const realtype NO_TORSION = -MaxReal; // U[0,1,2] = x,y,z extern realtype GetTorsion ( rvector U, rvector W, rvector V ); extern realtype GetAngle ( rvector U, rvector V ); // Calculates the binomial coefficient n choose m, 0<=n<=500, 0<=m<=n extern realtype Combinations ( int n, int m ); // Calculates precisely log(1-x) for x<1, including very small x extern realtype log1mx ( realtype x ); // Calculates precisely 1 - exp(x) for any x including very small values extern realtype expc ( realtype x ); inline double exp10 ( double x ) { return exp(x*ln10); } // Calculates precisely 1-(1-x)**y including very small x and very large y extern realtype expc1mx ( realtype x, realtype y ); } } #endif mmdb2-2.0.5/mmdb2/mmdb_math_fft.cpp0000775000175000017500000002606412401105774013752 00000000000000// $Id: mmdb_math_fft.cpp $ // ================================================================= // // CCP4 Coordinate Library: support of coordinate-related // functionality in protein crystallography applications. // // Copyright (C) Eugene Krissinel 2005-2013. // // This library is free software: you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License version 3, modified in accordance with the provisions // of the license to address the requirements of UK law. // // You should have received a copy of the modified GNU Lesser // General Public License along with this library. If not, copies // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // ================================================================= // // 12.09.13 <-- Date of Last Modification. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ----------------------------------------------------------------- // // **** Module : FFT // ~~~~~~~~~ // **** Functions: mmdb::math::FFT // ~~~~~~~~~ mmdb::math::RealFFT // mmdb::math::TwoFFT // mmdb::math::Convolve // mmdb::math::mConvolve // // (C) E.Krissinel 2005-2013 // // ================================================================= // #include #include "mmdb_math_fft.h" namespace mmdb { namespace math { void FFT ( rvector data, int nn, bool Forward ) { // Replaces data[1:2*nn] by its discrete Fourier transform, // if Forward is true; or replaces data[1:2*nn] by nn times its // inverse discrete Fourier transform if Forward is false. // On call, // data[i], i=1,3,5 ... nn-1 are real parts of function, // data[i], i=2,4,6 ... nn are imaginary parts. // nn MUST be an integer power of 2 (this is not checked for!). // User should allocate data with GetVectorMemory and deallocate // it with FreeVectorMemory to assure correct managing of indices // 1..2*nn (not 0..2*nn-1). // On return, // data[i], i=1,3,5 ... nn-1 are real parts, and // data[i], i=2,4,6 ... nn are imaginary parts of positive part // of spectra, with frequences // 0,1/(nn*D),2/(nn*D) ... (nn/2-1)/(nn*D); // data[nn+1] and data[nn+2] are real and imaginary parts for // the frequances +/-1/(2*D) // data[i], i=nn+3,nn+5,nn+7 ... 2*nn-1 are real parts, and // data[i], i=nn+4,nn+6,nn+8 ... 2*nn are imaginary parts of // negative part of the spectra with frequences // -(nn/2-1)/(nn*D), -(nn/2-2)/(nn*D), -1/(nn*D) // int i,istep,j,m,mmax,n; realtype tempi,tempr; long double theta,wi,wpi,wpr,wr,wtemp; // this should be of // maximal precision n = 2*nn; j = 1; for (i=1;i<=n;i+=2) { if (j>i) { tempr = data[j]; tempi = data[j+1]; data[j] = data[i]; data[j+1] = data[i+1]; data[i] = tempr; data[i+1] = tempi; } m = n/2; while ((m>=2) && (j>m)) { j -= m; m /= 2; } j += m; } mmax = 2; while (n>mmax) { istep = 2*mmax; theta = 2.0*Pi/mmax; if (!Forward) theta = -theta; wpr = sin(0.5*theta); wpr = -2.0*wpr*wpr; wpi = sin(theta); wr = 1.0; wi = 0.0; for (m=1;m<=mmax;m+=2) { for (i=m;i<=n;i+=istep) { j = i + mmax; tempr = wr*data[j] - wi*data[j+1]; tempi = wr*data[j+1] + wi*data[j]; data[j] = data[i] - tempr; data[j+1] = data[i+1] - tempi; data[i] = data[i] + tempr; data[i+1] = data[i+1] + tempi; } wtemp = wr; wr = wr*wpr - wi*wpi + wr; wi = wi*wpr + wtemp*wpi + wi; } mmax = istep; } } void RealFFT ( rvector data, int n, bool Forward ) { // Calculates the Fourier transform of a set of n real-valued data // points. Replaces this data (which is stored in array data[1:n]) // by the positive frequency half of its complex Fourier transform. // The real-valued first and last components of the complex transform // are returned as elements data[1] and data[2], respectively. // n MUST be a power of 2. This routine also calculates the // inverse transform of a complex data array if it is the transform // of real data (Result in this case must be multiplied by 2/n). // Array data should be allocated with GetVectorMemory. // int i,i1,i2,i3,i4,n2p3; realtype c1,c2,h1i,h1r,h2i,h2r; long double theta,wi,wpi,wpr,wr,wtemp; theta = 2.0*Pi/n; c1 = 0.5; if (Forward) { c2 = -0.5; FFT ( data,n/2,true ); } else { c2 = 0.5; theta = -theta; } wpr = sin(0.5*theta); wpr = -2.0*wpr*wpr; wpi = sin(theta); wr = 1.0 + wpr; wi = wpi; n2p3 = n + 3; for (i=2;i<=n/4;i++) { i1 = 2*i - 1; i2 = i1 + 1; i3 = n2p3 - i2; i4 = i3 + 1; h1r = c1*(data[i1] + data[i3]); h1i = c1*(data[i2] - data[i4]); h2r = -c2*(data[i2] + data[i4]); h2i = c2*(data[i1] - data[i3]); data[i1] = h1r + wr*h2r - wi*h2i; data[i2] = h1i + wr*h2i + wi*h2r; data[i3] = h1r - wr*h2r + wi*h2i; data[i4] = -h1i + wr*h2i + wi*h2r; wtemp = wr; wr = wr*wpr - wi*wpi + wr; wi = wi*wpr + wtemp*wpi + wi; } if (Forward) { h1r = data[1]; data[1] = h1r + data[2]; data[2] = h1r - data[2]; } else { h1r = data[1]; data[1] = c1*(h1r+data[2]); data[2] = c1*(h1r-data[2]); FFT ( data,n/2,false ); } } void TwoFFT ( rvector data1, rvector data2, rvector fft1, rvector fft2, int n ) { // Given two real input arrays data1[1:n] and data2[1:n], // this routine calls FFT and returns two "complex" output // arrays fft1[1:2*n] and fft2[1:2*n] (2*i-1 ith real, // 2*i ith imaginary), which contain the discrete Fourier // transforms of the respective data arrays. n MUST be // an integer power of 2. int i,j,n2, bj,bn; realtype h1r,h1i,h2r,h2i; i = 1; for (j=1;j<=n;j++) { fft1[i++] = data1[j]; fft1[i++] = data2[j]; } FFT ( fft1,n,true ); fft2[1] = fft1[2]; fft2[2] = 0.0; fft1[2] = 0.0; n2 = n + 2; for (j=2;j<=n/2+1;j++) { bj = 2*j-1; bn = 2*(n2-j)-1; h1r = 0.5*(fft1[bj] + fft1[bn]); h1i = 0.5*(fft1[bj+1] - fft1[bn+1]); h2r = 0.5*(fft1[bj+1] + fft1[bn+1]); h2i = 0.5*(fft1[bn] - fft1[bj]); fft1[bj] = h1r; fft1[bj+1] = h1i; fft1[bn] = h1r; fft1[bn+1] = -h1i; fft2[bj] = h2r; fft2[bj+1] = h2i; fft2[bn] = h2r; fft2[bn+1] = -h2i; } } void Convolve ( rvector data, int n, rvector respns, int m, rvector ans, bool Conv ) { // Convolves or Deconvolves a real data set data[1:n] (including // any user-supplied zero padding) with a response function // respns[1..n], stored in wrap-around order in a real array of // length m1) defined as // // data_m = data (*) data_{m-1} // // where data_m is the result of mth convolution, data_0=data. // The definition of the convolution is // // [a (*) b]_i = Sum_j { a_j * b_{i-j} } // // On input, data[] is considered as containing the signal // sampled at both positive and negative times in the wrap-around // order, that is // // data[i], 0<=i1) G = data[i+1]; else G = 0.0; } else { R = d1; G = 0.0; } phi = atan2(G,R) * m1; B = pow(R*R+G*G,m2); R = B*cos(phi); G = B*sin(phi); if (i // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // // **** Classes : mmdb::Mask ( atom selection mask ) // ~~~~~~~~~ // // (C) E. Krissinel 2000-2013 // // ================================================================= // #include #include #include "mmdb_mask.h" namespace mmdb { // ==================== Mask ======================== Mask::Mask() : io::Stream() { InitMask(); } Mask::Mask ( io::RPStream Object ) : io::Stream(Object) { InitMask(); } Mask::~Mask() { ClearMask(); } void Mask::InitMask() { mlen = 0; m = NULL; } void Mask::SetMaskBit ( int BitNo ) { int n,i; n = BitNo/(8*sizeof(word)); Expand ( n+1 ); i = BitNo - n*(8*sizeof(word)); m[n] |= ((word)1 << i); } void Mask::Expand ( int n ) { wvector m1; int i; if (mlen0)) { nlen = 0; w = 0; while (w==0) { for (i=0;imlen) w |= Mask[i]->m[nlen]; } nlen++; w = ~w; } Expand ( nlen ); i = nlen-1; m[i] = 1; while (!(m[i] & w)) m[i] <<= 1; } else { Expand ( 1 ); m[0] = 1; } } void Mask::CopyMask ( PMask Mask ) { int i; if (mlen!=Mask->mlen) ClearMask(); if (Mask) { mlen = Mask->mlen; if (mlen>0) { m = new word[mlen]; for (i=0;im[i]; } } } void Mask::SetMask ( PMask Mask ) { int i; if (Mask) { Expand ( Mask->mlen ); for (i=0;imlen;i++) m[i] |= Mask->m[i]; } } void Mask::RemoveMask ( PMask Mask ) { int i,l; if (Mask) { l = IMin(mlen,Mask->mlen); for (i=0;im[i]; } } void Mask::SelMask ( PMask Mask ) { int i,l; if (Mask) { l = IMin(mlen,Mask->mlen); for (i=0;im[i]; for (i=l;imlen ); for (i=0;imlen;i++) m[i] ^= Mask->m[i]; } } void Mask::ClearMask() { if (m) delete[] m; m = NULL; mlen = 0; } void Mask::NegMask() { int i; for (i=0;imlen); while ((im[i]))) i++; return (i0) { m = new word[mlen]; for (i=0;i // ~~~~~~~~~ // **** Project : MacroMolecular Data Base (MMDB) // ~~~~~~~~~ // **** Classes : mmdb::mmcif::Category ( mmCIF category ) // ~~~~~~~~~ mmdb::mmcif::Struct ( mmCIF structure ) // mmdb::mmcif::Loop ( mmCIF loop ) // mmdb::mmcif::Data ( mmCIF data block ) // mmdb::mmcif::File ( mmCIF file ) // // (C) E. Krissinel 2000-2013 // // ================================================================= // #ifndef __MMDB_MMCIF__ #define __MMDB_MMCIF__ #include "mmdb_io_stream.h" namespace mmdb { namespace mmcif { // ====================== Category ========================== enum MMCIF_ITEM { MMCIF_Category = 0, MMCIF_Struct = 1, MMCIF_Loop = 2, MMCIF_Data = 3 }; DefineClass(Category); DefineStreamFunctions(Category); /// \brief mmcif::Category is a base class for mmcif::Struct and /// mmcif::Loop, implementations of mmCIF's "structure" and /// "loop" categories. /*! This class is not instantiated independently in any applications, however, it provides a few public functions which work for both mmcif::Struct and mmcif::Loop. All data in mmCIF hierarchy is addressed using construct "category.tag" plus row number (>=0) for loops. Category names should always start from underscore, while tags normally start with a letter, e.g. "_barrel.id". See general principles of working with mmCIF files and mmCIF hierarchies in Section \"\ref mmcif_handler\". */ class Category : public io::Stream { friend class Data; public : /// \brief Basic constructor. Category (); /// \brief Constructor that assigns category name. /// \param[in] N category name (must start with underscore). Category ( cpstr N ); /// \brief Constructor for MMDB data streaming functions. Category ( io::RPStream Object ); /// \brief Destructor. ~Category(); /// \brief Returns category name. /// \return NULL if name was not set /// \return pointer to character string if name was set inline pstr GetCategoryName() { return name; } /// \brief Sets category name. /// \param N new category name void SetCategoryName ( cpstr N ); /// \brief Returns category type. /// This function may be used when retrieving categories /// (structures and loops) from data blocks (mmcif::Data). /// \return MMCIF_Category for mmcif::Category /// \return MMCIF_Struct for mmcif::Struct /// \return MMCIF_Loop for mmcif::Loop virtual MMCIF_ITEM GetCategoryID() { return MMCIF_Category; } /// \brief Virtual function for writing category's content /// into mmCIF file. /// Default implementation does nothing. virtual void WriteMMCIF ( io::RFile ) {} /// \brief Virtual function for optimizig data structures. /// Optimized data structures take less RAM and their indexes /// are sorted for quicker access. Sorting is done automatically /// as new data is added to the category. If the /// category is edited (fields/data removed), it may need /// optimization and re-sorting for efficiency.\n\n /// The sorting preserves the order of actual appearance of /// tags in mmCIF file. If a category is created /// programmatically, the order of tags in mmCIF file will be /// the same as order of adding them to the category. virtual void Optimize(); /// \brief Sorts category's data for quicker access. /// The sorting is essentially re-indexing of data for quicker /// access. It does not change the order of data in both mmCIF /// hierarchy and mmCIF file. E.g., if tag "serial_no" was 2nd /// one in given category before sorting, it will remain on 2nd /// place after it, therefore no change in tag number passed /// to functions in mmcif::Struct, mmcif::Loop and mmcif::Data. void Sort(); /// \brief Returns serial number of a tag in the category. /// \param[in] ttag tag (or name of a field in category) /// \return \b >=0 : the tag is in given position /// \return \b <0 : the tag was not found, but it could be /// inserted before tag with (-rc-1)th index, where /// 'rc' is the return. int GetTagNo ( cpstr ttag ); /// \brief Adds a tag to the category. /// Adding a tag in mmcif::Category does not reserve any /// placeholder for the corresponding value. All tags get /// automatically sorted (reindexed) for quicker access. /// Tags will appear in mmCIF file in order of their addition /// to the category. /// \param[in] ttag tag to be added. /// \return \b >=0 the tag is already in the category, and return /// is its serial number. No changes to the category /// is done /// \return \b <0 the tag was added to the list of tags, and /// return is minus total number of tags in the /// category. int AddTag ( cpstr ttag ); /// \brief Returns the total number of tags in the category int GetNofTags() { return nTags; } /// \brief Returns tag with the specified serial number. /// The tags are enumerated as 0..GetNofTags()-1. /// \param tagNo tag's serial number /// \return \b NULL: tagNo is outside the range /// of 0..GetNofTags()-1 /// \return \b not \b NULL: tag in tagNo'th position pstr GetTag ( int tagNo ); // 0..nTags-1 /// \brief Prints list of tags to stdout. /// Both sorted and unsorted tags are printed to standard /// output. This function may be used for debugging. void PrintTags(); /// \brief Returns true if all tags from the list are found /// in the category. /// The size of the list of tags may be less than the number /// of tags in the category, and order of tags is disregarded. /// \param[in] tagList list of tags to be checked for presence /// in the category. The list must end with NULL /// pointer, or your program will crash. /// \return \b true if all tags from the list were found in the /// category /// \return \b false if one or more tags from the list were not /// found in the category. /// /// Example: /// \code /// cpstr tagList[] = {"id","type","date",NULL}; /// mmcif::Struct cifStruct; /// if (cifStruct.CheckTags(tagList)) /// printf ( " all tags are found in category %s\n", /// cifStruct.GetCategoryName() ); /// \endcode /// This function is useful for finding categories in /// "dirty cifs", where category name is not given. bool CheckTags ( cpstr * tagList ); /// \brief Deep copy of categories. /// Deep copy duplicates all data and memory allocations, /// producing a genuine clone of the original. Only deep copy /// should be used for copying MMDB objects, a mere assignment /// operator will fail you. /// \param[in] Category a pointer to mmcif::Category, the content of /// which is copied into 'this' category. virtual void Copy ( PCategory Category ); /// \brief MMDB stream writer. void write ( io::RFile f ); /// \brief MMDB stream reader. void read ( io::RFile f ); protected: int nTags; pstr name; psvector tag; ivector index; int nAllocTags; void InitCategory (); virtual void FreeMemory (); void ExpandTags ( int nTagsNew ); void PutCategoryName ( cpstr newName ); }; // ====================== Struct ============================ DefineClass(Struct); DefineStreamFunctions(Struct); /// \brief Constants used to specify mmCIF's \"data not given\" and /// \"data not available\" data types. extern const int CIF_NODATA_DOT; extern const int CIF_NODATA_QUESTION; extern cpstr CIF_NODATA_DOT_FIELD; extern cpstr CIF_NODATA_QUESTION_FIELD; /// \brief mmcif::Struct represents mmCIF's \"structure\" category, /// where data follows directly the corresponding tag. /*! mmCIF's \"structure\" category has the following form: \code _structure_name.tag0 value0 _structure_name.tag1 value1 ........... _structure_name.tagN valueN \endcode mmcif::Struct represents this construct by keeping category name (\"_structure_name\") and associated lists of tags (\"tag0,tag1...tagN\") and their values (\"value0,value1...valueN\"). The structure is created automatically when an mmCIF file is read, or it may be created programatically and then pushed into file. Access to data is provided via tags. Internally, all values are kept as character fields, and it is only on the retrieval stage that they are converted to other data types (integers, floats or strings). If conversion is not possible, an error code is returned by the corresponding functions, which should be checked by the application. See general principles of working with mmCIF files and mmCIF hierarchies, as well as some code samples, in Section \"\ref mmcif_handler\". */ class Struct : public Category { public : /// \brief Basic constructor Struct (); /// \brief Constructor that assigns structure name. /// \param[in] N structure name (must start with underscore). Struct ( cpstr N ); /// \brief Constructor for MMDB data streaming functions Struct ( io::RPStream Object ); /// \brief Destructor ~Struct(); /// \brief Adds field to the structure. /// \param[in] F field value /// \param[in] T tag name /// \param[in] Concatenate flag to concatenate existing field /// with the value of \b F. If tag \b T is already in /// the structure and \b Concatenate=true, then /// value of \b F is appended to the existing field. /// Otherwise, the field is replaced with the value /// of \b F void AddField ( cpstr F, cpstr T, bool Concatenate=false ); /// \brief Returns category type \b MMCIF_Struct. MMCIF_ITEM GetCategoryID() { return MMCIF_Struct; } /// \brief Optimizes structure for RAM and data access speed. /// Optimized data structures take less RAM and their indexes /// are sorted for quicker access. Sorting is done automatically /// as new data is added to the category. If the structure /// is edited (fields/data removed), it may need /// optimization and re-sorting for efficiency.\n\n /// The sorting preserves the order of actual appearance of /// tags in mmCIF file. If a structure is created /// programmatically, the order of tags in mmCIF file will be /// the same as order of adding them to the structure. void Optimize(); /// \brief Returns value of field corresponding to tag in the /// specified position. /// Tag positions are defined by the order of their appearance in /// mmCIF file (if structure was read from a file), or by the /// order of their addition to the structure (if structure was /// created programmatically). Tags are numbered as /// 0...GetNofTags()-1. /// \param[in] tagNo tag number (position in the structure) /// \return \b NULL: tag does not exist /// \return \b CIF_NODATA_DOT_FIELD the field contains /// \"data not given\" value /// \return \b CIF_NODATA_QUESTION_FIELD the field contains /// \"data not available\" value /// \return \b not \b NULL: string value of the field pstr GetField ( int tagNo ); // 0..nTags-1 /// \brief Fetches value, corresponding to the given tag, as /// a string /// \param[out] S pointer to string, which will point to newly /// allocated character string, containing value /// associated with tag \b TName. If tag or value /// is not found, or if value corresponds to /// mmCIF's \"data not given\" or /// \"data not available\", \b S returns NULL. /// \param[in] TName character string with tag name /// \param[in] Remove flag to remove the tag and its value from /// structure after it is read. /// \return \b CIFRC_NoTag: tag is not found /// \return \b CIFRC_NoField: value is not found /// \return \b CIFRC_Ok: success. If \b S returns NULL, then /// the value corresponds to either /// \"data not available\" or /// \"data not given\". /// \remarks If \b S!=NULL at time of call, the function will /// try to dispose the string it points on. This allows a slick /// re-use of the same pointer in consequitive calls. This also /// means that one should never pass unallocated pointer to /// this function. Safe use assumes the following patern: /// \code /// mmcif::Struct mmCIFStruct; /// pstr S; // this is merely "char *S" /// int rc; /// /// S = NULL; // null pointer before first use /// rc = mmCIFStruct.GetString ( S,"id" ); /// if (rc) CreateCopy ( S,"*** data not found" ); /// if (!S) CreateCopy ( S,"*** data not given or not available" ); /// printf ( " rc=%i, S='%s'\n",rc,S ); /// /// rc = mmCIFStruct.GetString ( S,"property" ); /// if (rc) CreateCopy ( S,"*** data not found" ); /// if (!S) CreateCopy ( S,"*** data not given or not available" ); /// printf ( " rc=%i, S='%s'\n",rc,S ); /// /// // etc etc etc /// /// delete[] S; // application is responsible for final /// // disposal of memory /// \endcode int GetString ( pstr & S, cpstr TName, bool Remove=false ); /// \brief Returns pointer to value associated with given tag. /// \param[in] TName character string with tag name /// \param[out] RC return code: /// \arg \b CIFRC_NoTag: tag is not found /// \arg \b CIFRC_NoField: value is not found /// \arg \b CIFRC_Ok: success. If function returns NULL, then /// the value corresponds to either /// \"data not available\" or /// \"data not given\". /// \return \b NULL: either tag or value is not found, or the /// value is \"data not available\" or \"data not given\". /// Read return code \b RC in order to interpret NULL return. /// \return \b not \b NULL: pointer (\c char \c *) to value /// associated with \b TName. /// \remarks Never try to dispose memory pointed by the return /// value, or your program will crash. pstr GetString ( cpstr TName, int & RC ); // NULL if TName // is not there /// \brief Deletes field associated with given tag. /// \param[in] TName character string with tag name /// \return \b >=0: field deleted /// \return \b <0: either field or tag is not found int DeleteField ( cpstr TName ); // <0 the field was not there /// \brief Fetches value, corresponding to the given tag, as /// a real number. /// \param[out] R reference to real number to accept the value. /// In case of failure, \b R returns zero. /// \param[in] TName character string with tag name /// \param[in] Remove flag to remove the tag and its value from /// structure after it is read. /// \return \b CIFRC_NoTag: tag is not found /// \return \b CIFRC_NoField: field is not found /// \return \b CIFRC_WrongFormat: value is not a real or integer /// number. /// \return \b CIFRC_NoData: value is either /// \"data not available\" or /// \"data not given\". /// \return \b CIFRC_Ok: success. int GetReal ( realtype & R, cpstr TName, bool Remove=false ); /// \brief Fetches value, corresponding to the given tag, as /// an integer number. /// \param[out] I reference to integer number to accept the /// value. In case of failure, \b I returns zero, except /// when value is \"data not available\" or /// \"data not given\", when I returns \c MinInt4. /// \param[in] TName character string with tag name /// \param[in] Remove flag to remove the tag and its value from /// structure after it is read. /// \return \arg \b CIFRC_NoTag: tag is not found /// \return \b CIFRC_NoField: field is not found /// \return \b CIFRC_WrongFormat: value is not an integer number. /// \return \b CIFRC_NoData: value is either /// \"data not available\" or /// \"data not given\". /// \return \b CIFRC_Ok: success. int GetInteger ( int & I, cpstr TName, bool Remove=false ); /// \brief Sets string value for given tag. /// \param[in] S character string with value to be set. /// If \b S==NULL, the \"data not given\" value /// will be set. If \b S==\"\" (empty string), the /// \"data not available\" value is stored. /// \param[in] TName character string with tag name. If tag /// is not found, it will be added to the structure. /// \param[in] NonBlankOnly flag to treat white-space-only /// strings: /// \arg \b false: set as is /// \arg \b true: set \"data not available\" value instead. void PutString ( cpstr S, cpstr TName, bool NonBlankOnly=false ); /// \brief Sets current date in format YYYY-MM-DD as a value /// for given tag. /// \param[in] T character string with tag name. If tag /// is not found, it will be added to the structure. void PutDate ( cpstr T ); /// \brief Sets \"data not given\" or \"data not available\" /// values for given tag. /// \param[in] NoDataType can be either /// \arg \b CIF_NODATA_DOT for \"data not given\" /// \arg \b CIF_NODATA_QUESTION for \"data not available\" /// \param[in] T character string with tag name. If tag /// is not found, it will be added to the structure. void PutNoData ( int NoDataType, cpstr T ); /// \brief Sets float-point value for given tag. /// \param[in] R real number with value to be set. /// \param[in] TName character string with tag name. If tag /// is not found, it will be added to the structure. /// \param[in] prec float-point precision; g-format with given /// precision will be used void PutReal ( realtype R, cpstr TName, int prec=8 ); /// \brief Sets float-point value for given tag. /// \param[in] R real number with value to be set. /// \param[in] TName character string with tag name. If tag /// is not found, it will be added to the structure. /// \param[in] format format string to convert \b R. void PutReal ( realtype R, cpstr TName, cpstr format ); /// \brief Sets integer value for given tag. /// \param[in] I integer number with value to be set. /// \param[in] TName character string with tag name. If tag /// is not found, it will be added to the structure. void PutInteger ( int I, cpstr TName ); /// \brief Writes structure data in mmCIF format into file. /// \param[in] FName character string with file name. /// \param[in] gzipMode flag to controll compression of files: /// \arg \b GZM_NONE: do not compress /// \arg \b GZM_CHECK: check file name suffix and compress /// (or not) accordingly /// \arg \b GZM_ENFORCE_GZIP: force gzip compression despite /// suffix /// \arg \b GZM_ENFORCE_COMPRESS: force using compress despite /// suffix /// \return \b true: success /// \return \b false: can not open file for writing. /// \remarks This function does not create a valid mmCIF file /// as \"data_XXX\" record will be missing. It may be used for /// debugging though. bool WriteMMCIFStruct ( cpstr FName, io::GZ_MODE gzipMode=io::GZM_CHECK ); /// \brief Writes structure into given file. /// \param f reference to MMDB's file class. The file should be /// opened and closed by application. /// \remarks There is a very limited use of this function on /// application level. It is primarily used by mmcif::Data class. void WriteMMCIF ( io::RFile f ); /// \brief Deep copy of structures. /// Deep copy duplicates all data and memory allocations, /// producing a genuine clone of the original. Only deep copy /// should be used for copying MMDB objects, a mere assignment /// operator will fail you. /// \param[in] Struct a pointer to mmcif::Struct, the content of /// which is copied into 'this' structure. void Copy ( PCategory Struct ); /// \brief MMDB stream writer. void write ( io::RFile f ); /// \brief MMDB stream reader. void read ( io::RFile f ); protected: psvector field; void InitStruct(); void FreeMemory(); }; // ====================== Loop ============================== DefineClass(Loop); DefineStreamFunctions(Loop); /// \brief mmcif::Loop represents mmCIF's \"loop\" category, which keeps /// rows of data values associated with tags. /*! mmCIF's \"loop\" category has the following form: \code loop_ _loop_name.tag0 value0 _loop_name.tag1 value1 ........... _loop_name.tagN valueN value00 value10 ... valueN0 value01 value11 ... valueN1 ........... value0M value1M ... valueNM \endcode mmcif::Loop represents this construct by keeping category name (\"_loop_name\") and associated lists of tags (\"tag0,tag1...tagN\") and data vectors (\"[value00...value0M],[value10...value1M]...[valueN0...valueNM]\"). The loop object is created automatically when an mmCIF file is read, or it may be created programatically and then pushed into file. Access to data is provided via tags and data indexes. Internally, all values are kept as character fields, and it is only on the retrieval stage that they are converted to other data types (integers, floats or strings). If conversion is not possible, an error code is returned by the corresponding functions, which should be checked by the application. The following code gives an example of creating mmCIF loop category and populating it with data: \code mmcif::Loop loop; char S[100]; int i; // Specify loop name: loop.SetCategoryName ( "_sample_loop" ); // Create loop structure, i.e., list of tags first: loop.AddLoopTag ( "id" ); loop.AddLoopTag ( "name" ); loop.AddLoopTag ( "value" ); // Now populate it with data. This my be done in 2 ways. // Here is how you write loop data in stream fashion, // value-after-value: for (i=0;i<3;i++) { loop.AddInteger ( i ); sprintf ( S,"1st_way-%i",i ); loop.AddString ( S ); loop.AddReal ( 2.5*(i+1) ); } // Here is how you populate loop data using direct-access // functions: for (i=3;i<6;i++) { loop.PutReal ( 2.5*(i+1),"value",i ); loop.PutInteger ( i,"id" ); sprintf ( S,"2nd way: %i",i ); loop.PutString ( S,"name" ); } loop.WriteMMCIFLoop ( "sample_loop.cif" ); \endcode The resulting file \b sample_loop.cif will contain: \code loop_ _sample_loop.id _sample_loop.name _sample_loop.value 0 1st_way-0 2.5 1 1st_way-1 5.0 2 1st_way-2 7.5 3 "2nd way: 3" 10.0 4 "2nd way: 4" 12.5 5 "2nd way: 5" 15.0 \endcode See general principles of working with mmCIF files and mmCIF hierarchies, as well as some code samples, in Section \"\ref mmcif_handler\". */ class Loop : public Category { friend class Data; public : /// \brief Basic constructor Loop (); /// \brief Constructor that assigns structure name. /// \param[in] N structure name (must start with underscore). Loop ( cpstr N ); /// \brief Constructor for MMDB data streaming functions Loop ( io::RPStream Object ); /// \brief Destructor ~Loop(); /// \brief Adds tag to the loop. /// The tag is appended to the list of existing tags. The order /// of tags cannot be changed. /// \param[in] T tag name /// \param[in] Remove flag to remove all fields in the loop. void AddLoopTag ( cpstr T, bool Remove=true ); /// \brief Sets string value at current loop position. /// When \b mmcif::Loop::Add[Data] functions use internal loop /// pointer. When category is created or cleared (by using /// \b mmcif::Loop::AddLoopTag ( T,true )) the pointer is set to /// 0th row and 0th column (tag). After each call to /// \b mmcif::Loop::Add[Data] function, internal pointer advances /// to next column (tag), and wraps over to next row, 0th tag, /// if list of tags is exhausted. Any remaining fields in last /// row will be populated with \"data not given\" value. /// \param[in] S character string with value to be set. /// If \b S==NULL, the \"data not given\" value /// will be set. If \b S==\"\" (empty string), the /// \"data not available\" value is stored. /// \param[in] NonBlankOnly flag to treat white-space-only /// strings: /// \arg \b false: set as is /// \arg \b true: set \"data not available\" value instead. void AddString ( cpstr S, bool NonBlankOnly=false ); /// \brief Sets \"data not given\" or \"data not available\" at /// current loop position. /// When \b mmcif::Loop::Add[Data] functions use internal loop /// pointer. When category is created or cleared (by using /// \b mmcif::Loop::AddLoopTag ( T,true )) the pointer is set to /// 0th row and 0th column (tag). After each call to /// \b mmcif::Loop::Add[Data] function, internal pointer advances /// to next column (tag), and wraps over to next row, 0th tag, /// if list of tags is exhausted. Any remaining fields in last /// row will be populated with \"data not given\" value. /// \param[in] NoDataType integer key specifying which type of /// data absence should be set as a value: /// \arg \b CIF_NODATA_DOT for \"data not given\" /// \arg \b CIF_NODATA_QUESTION for \"data not available\" void AddNoData ( int NoDataType ); /// \brief Sets float-point value at current loop position. /// When \b mmcif::Loop::Add[Data] functions use internal loop /// pointer. When category is created or cleared (by using /// \b mmcif::Loop::AddLoopTag ( T,true )) the pointer is set to /// 0th row and 0th column (tag). After each call to /// \b mmcif::Loop::Add[Data] function, internal pointer advances /// to next column (tag), and wraps over to next row, 0th tag, /// if list of tags is exhausted. Any remaining fields in last /// row will be populated with \"data not given\" value. /// \param[in] R real number with value to be set. /// \param[in] prec float-point precision; g-format with given /// precision will be used void AddReal ( realtype R, int prec=8 ); /// \brief Sets float-point value at current loop position in /// given format. /// When \b mmcif::Loop::Add[Data] functions use internal loop /// pointer. When category is created or cleared (by using /// \b mmcif::Loop::AddLoopTag ( T,true )) the pointer is set to /// 0th row and 0th column (tag). After each call to /// \b mmcif::Loop::Add[Data] function, internal pointer advances /// to next column (tag), and wraps over to next row, 0th tag, /// if list of tags is exhausted. Any remaining fields in last /// row will be populated with \"data not given\" value. /// \brief Sets float-point value for given tag. /// \param[in] R real number with value to be set. /// \param[in] format format string to convert \b R. void AddReal ( realtype R, cpstr format ); /// \brief Sets integer value at current loop position in given /// format. /// When \b mmcif::Loop::Add[Data] functions use internal loop /// pointer. When category is created or cleared (by using /// \b mmcif::Loop::AddLoopTag ( T,true )) the pointer is set to /// 0th row and 0th column (tag). After each call to /// \b mmcif::Loop::Add[Data] function, internal pointer advances /// to next column (tag), and wraps over to next row, 0th tag, /// if list of tags is exhausted. Any remaining fields in last /// row will be populated with \"data not given\" value. /// \param[in] I integer number with value to be set. void AddInteger ( int I ); /// \brief Returns current length of the loop (i.e. the number /// of rows). /// \return number of data rows in the loop. int GetLoopLength() { return nRows; } /// \brief Returns string pointer on the field corresponding to /// tag in the specified position, in the specified row. /// Tag positions are defined by the order of their appearance in /// mmCIF file (if loop was read from a file), or by the /// order of their addition to the loop (if loop was /// created programmatically). /// \param[in] rowNo row number (0...GetLoopLength()-1) /// \param[in] tagNo tag number (0...GetNofTags()-1) /// \return \b NULL: tag or row do not exist /// \return \b CIF_NODATA_DOT_FIELD the field contains /// \"data not given\" value /// \return \b CIF_NODATA_QUESTION_FIELD the field contains /// \"data not available\" value /// \return \b not \b NULL: string value of the field /// \remarks Never try to dispose memory pointed by the return /// value, or your program will crash. pstr GetField ( int rowNo, int tagNo ); /// \brief Fetches value, corresponding to the given tag, in /// the given row, as a string /// \param[out] S pointer to string, which will point to newly /// allocated character string, containing value /// associated with tag \b TName and row \b nrow. /// If tag, row or value /// is not found, or if value corresponds to /// mmCIF's \"data not given\" or /// \"data not available\", \b S returns NULL. /// \param[in] TName character string with tag name /// \param[in] nrow row number (0...GetLoopLength()-1) /// \param[in] Remove flag to remove the field from /// structure after it is read. /// \return \b CIFRC_NoTag: tag is not found /// \return \b CIFRC_WrongIndex: row is not found /// \return \b CIFRC_NoField: value is not found /// \return \b CIFRC_Ok: success. If \b S returns NULL, then /// the value corresponds to either /// \"data not available\" or /// \"data not given\". /// \remarks If \b S!=NULL at time of call, the function will /// try to dispose the string it points on. This allows a slick /// re-use of the same pointer in consequitive calls. This also /// means that one should never pass unallocated pointer to /// this function. Safe use assumes the following patern: /// \code /// mmcif::Loop mmCIFLoop; /// pstr S; // this is merely "char *S" /// int rc; /// /// S = NULL; // null pointer before first use /// rc = mmCIFLoop.GetString ( S,"id",1 ); /// if (rc) CreateCopy ( S,"*** data not found" ); /// if (!S) CreateCopy ( S,"*** data not given or not available" ); /// printf ( " rc=%i, S='%s'\n",rc,S ); /// /// rc = mmCIFLoop.GetString ( S,"property",0 ); /// if (rc) CreateCopy ( S,"*** data not found" ); /// if (!S) CreateCopy ( S,"*** data not given or not available" ); /// printf ( " rc=%i, S='%s'\n",rc,S ); /// /// // etc etc etc /// /// delete[] S; // application is responsible for final /// // disposal of memory /// \endcode int GetString ( pstr & S, cpstr TName, int nrow, bool Remove=false ); /// \brief Returns pointer to value associated with given tag, /// in the given row of the loop. /// \param[in] TName character string with tag name /// \param[in] nrow row number (0...GetLoopLength()-1) /// \param[out] RC return code: /// \arg \b CIFRC_NoTag: tag is not found /// \arg \b CIFRC_WrongIndex: row is not found /// \arg \b CIFRC_NoField: value is not found /// \arg \b CIFRC_Ok: success. If function returns NULL, then /// the value corresponds to either /// \"data not available\" or /// \"data not given\". /// \return \b NULL: either tag, row or value is not found, or the /// value is \"data not available\" or \"data not given\". /// Read return code \b RC in order to interpret NULL return. /// \return \b not \b NULL: pointer (\c char \c *) to value /// associated with \b TName. /// \remarks Never try to dispose memory pointed by the return /// value, or your program will crash. pstr GetString ( cpstr TName, int nrow, int & RC ); /// \brief Copies value, associated with given tag, /// in the given row, into specified buffer. /// Terminating NULL character is appended. /// \param[out] buf character string to accept the value /// \param[in] maxlength maximum number of bytes to copy /// \param[in] TName character string with tag name /// \param[in] nrow row number (0...GetLoopLength()-1) /// \param[out] RC return code: /// \arg \b CIFRC_NoTag: tag is not found /// \arg \b CIFRC_WrongIndex: row is not found /// \arg \b CIFRC_NoField: value is not found /// \arg \b CIFRC_Ok: success. /// \remarks Destination string \b buf is not modified if /// \b RC!=CIFRC_Ok . void CopyString ( pstr buf, int maxlength, cpstr TName, int nrow, int & RC ); /// \brief Deletes field associated with given tag in /// the given row. /// \param[in] TName character string with tag name /// \param[in] nrow row number (0...GetLoopLength()-1) /// \return \b >=0: field deleted /// \return \b <0: either field or tag is not found int DeleteField ( cpstr TName, int nrow ); /// \brief Deletes all fields in given row. /// \param[in] nrow row number (0...GetLoopLength()-1) /// \return \b CIFRC_Ok: fields deleted /// \return \b CIFRC_WrongIndex: row not found /// \remarks Note that this function delets just the fields, but /// not the row. If you wish the row to be deleted, call /// mmcif::Loop::Optimize() function after this one. int DeleteRow ( int nrow ); /// \brief Fetches value, corresponding to the given tag, /// in the given row, as a real number. /// \param[out] R reference to real number to accept the value. /// In case of failure, \b R returns zero. /// \param[in] TName character string with tag name /// \param[in] nrow row number (0...GetLoopLength()-1) /// \param[in] Remove flag to remove the field from /// the loop after it is read. /// \return \b CIFRC_NoTag: tag is not found /// \return \b CIFRC_WrongIndex: row not found /// \return \b CIFRC_NoField: field is not found /// \return \b CIFRC_WrongFormat: value is not a real or integer /// number. /// \return \b CIFRC_NoData: value is either /// \"data not available\" or /// \"data not given\". /// \return \b CIFRC_Ok: success. int GetReal ( realtype & R, cpstr TName, int nrow, bool Remove=false ); /// \brief Copies value, associated with given tag, /// in the given row, into specified destination as /// a real number. /// \param[out] R reference to real number to accept the value /// \param[in] TName character string with tag name /// \param[in] nrow row number (0...GetLoopLength()-1) /// \param[out] RC return code: /// \arg \b CIFRC_NoTag: tag is not found /// \arg \b CIFRC_WrongIndex: row is not found /// \arg \b CIFRC_NoField: value is not found /// \arg \b CIFRC_Ok: success. /// \remarks Destination \b R is set 0 if \b RC!=CIFRC_Ok. void CopyReal ( realtype & R, cpstr TName, int nrow, int & RC ); /// \brief Copies value, associated with given tag, /// in the given row, into specified destination as /// an integer number. /// \param[out] I reference to integer number to accept the value /// \param[in] TName character string with tag name /// \param[in] nrow row number (0...GetLoopLength()-1) /// \param[out] RC return code: /// \arg \b CIFRC_NoTag: tag is not found /// \arg \b CIFRC_WrongIndex: row is not found /// \arg \b CIFRC_NoField: value is not found /// \arg \b CIFRC_Ok: success. /// \remarks Destination \b I is set 0 if \b RC!=CIFRC_Ok. void CopyInteger ( int & I, cpstr TName, int nrow, int & RC ); /// \brief Fetches value, corresponding to the given tag, /// in the given row, as an integer number. /// \param[out] I reference to integer number to accept the value. /// In case of failure, \b R returns zero. /// \param[in] TName character string with tag name /// \param[in] nrow row number (0...GetLoopLength()-1) /// \param[in] Remove flag to remove the field from /// the loop after it is read. /// \return \b CIFRC_NoTag: tag is not found /// \return \b CIFRC_WrongIndex: row not found /// \return \b CIFRC_NoField: field is not found /// \return \b CIFRC_WrongFormat: value is not a real or integer /// number. /// \return \b CIFRC_NoData: value is either /// \"data not available\" or /// \"data not given\". /// \return \b CIFRC_Ok: success. int GetInteger ( int & I, cpstr TName, int nrow, bool Remove=false ); /// \brief Fetches set of values, corresponding to the given /// tag, in the given range of rows, as a vector of /// strings. /// \param[out] S reference to string vector to accept /// the values. if \b S==NULL , the vector will be /// allocated with starting index of \b i1. /// \param[in] TName character string with tag name /// \param[in] i1 minimum row number to fetch, the actual /// index will be calculated as \b max(0,min(i1,i2)) /// \param[in] i2 maximum row number to fetch, the actual /// index will be calculated as /// \b min(GetLoopLength()-1,max(i1,i2)) /// \param[in] Remove flag to remove fetched fields from /// the loop after they are read. /// \return \b CIFRC_NoTag: tag is not found /// \return \b CIFRC_WrongIndex: invalid range of rows /// \return \b CIFRC_Ok: success. /// /// For safe use, \b S should be pre-allocated by calling /// process. Only elements \b S[i1] to \b S[i2] will contain /// fetched data, others remain untouched. The calling /// process is responsible for the disposal of \b S. Example: /// \code /// mmcif::Loop loop; /// psvector S; // equivalent to char **S /// int i,i1,i2,rc,n; /// /// // ... get loop data /// /// n = loop.GetLoopLength(); /// i1 = 5; i2 = n - 5; // could be wrong! /// /// // allocate vector of strings /// GetVectorMemory ( S,n,0 ); // "0" for starting index /// for (i=0;i