1 // $Id: mmdb_chain.h $ 2 // ================================================================= 3 // 4 // CCP4 Coordinate Library: support of coordinate-related 5 // functionality in protein crystallography applications. 6 // 7 // Copyright (C) Eugene Krissinel 2000-2013. 8 // 9 // This library is free software: you can redistribute it and/or 10 // modify it under the terms of the GNU Lesser General Public 11 // License version 3, modified in accordance with the provisions 12 // of the license to address the requirements of UK law. 13 // 14 // You should have received a copy of the modified GNU Lesser 15 // General Public License along with this library. If not, copies 16 // may be downloaded from http://www.ccp4.ac.uk/ccp4license.php 17 // 18 // This program is distributed in the hope that it will be useful, 19 // but WITHOUT ANY WARRANTY; without even the implied warranty of 20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 // GNU Lesser General Public License for more details. 22 // 23 // ================================================================= 24 // 25 // 23.12.15 <-- Date of Last Modification. 26 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 // ----------------------------------------------------------------- 28 // 29 // **** Module : MMDB_Chain <implementation> 30 // ~~~~~~~~~ 31 // **** Project : MacroMolecular Data Base (MMDB) 32 // ~~~~~~~~~ 33 // **** Classes : mmdb::ProModel ( a virtue of Model ) 34 // ~~~~~~~~~ mmdb::DBReference ( DBREF records ) 35 // mmdb::ChainContainer ( container of in-chain classes ) 36 // mmdb::ContainerChain ( chain containered class template) 37 // mmdb::SeqAdv ( SEQADV records ) 38 // mmdb::SeqRes ( SEQRES records ) 39 // mmdb::ModRes ( MODRES records ) 40 // mmdb::HetRec ( HET records ) 41 // mmdb::Chain ( chain class ) 42 // 43 // Copyright (C) E. Krissinel 2000-2015 44 // 45 // ================================================================= 46 // 47 48 #include <string.h> 49 #include <stdlib.h> 50 51 #include "mmdb_chain.h" 52 #include "mmdb_model.h" 53 #include "mmdb_manager.h" 54 #include "mmdb_cifdefs.h" 55 #include "mmdb_tables.h" 56 57 namespace mmdb { 58 59 // ================== ProModel ====================== 60 MakeStreamFunctions(ProModel)61 MakeStreamFunctions(ProModel) 62 63 // ============== ChainContainer ==================== 64 65 PContainerClass ChainContainer::MakeContainerClass ( int ClassID ) { 66 switch (ClassID) { 67 default : 68 case ClassID_Template : return 69 ClassContainer::MakeContainerClass(ClassID); 70 case ClassID_DBReference : return new DBReference ( chain ); 71 case ClassID_SeqAdv : return new SeqAdv ( chain ); 72 case ClassID_ModRes : return new ModRes ( chain ); 73 case ClassID_Het : return new HetRec ( chain ); 74 } 75 } 76 SetChain(PChain Chain_Owner)77 void ChainContainer::SetChain ( PChain Chain_Owner ) { 78 int i; 79 chain = Chain_Owner; 80 for (i=0;i<length;i++) 81 if (Container[i]) 82 (void)PContainerChain(Container[i])->SetChain ( chain ); 83 } 84 Get1stChainID()85 cpstr ChainContainer::Get1stChainID() { 86 int i; 87 i = 0; 88 if (Container) { 89 while ((i<length-1) && (!Container[i])) i++; 90 if (Container[i]) 91 return PContainerChain(Container[i])->chainID; 92 else return NULL; 93 } else 94 return NULL; 95 } 96 MoveByChainID(const ChainID chainID,PChainContainer ChainContainer)97 void ChainContainer::MoveByChainID ( const ChainID chainID, 98 PChainContainer ChainContainer ) { 99 int i; 100 for (i=0;i<length;i++) 101 if (Container[i]) { 102 if (!strcmp(PContainerChain(Container[i])->chainID,chainID)) { 103 ChainContainer->AddData ( Container[i] ); 104 Container[i] = NULL; 105 } 106 } 107 } 108 109 MakeStreamFunctions(ChainContainer)110 MakeStreamFunctions(ChainContainer) 111 112 113 // ================ ContainerChain =================== 114 115 ContainerChain::ContainerChain() : ContainerClass() { 116 chain = NULL; 117 chainID[0] = char(0); 118 } 119 ContainerChain(PChain Chain_Owner)120 ContainerChain::ContainerChain ( PChain Chain_Owner) 121 : ContainerClass() { 122 chain = Chain_Owner; 123 if (chain) strcpy ( chainID,chain->GetChainID() ); 124 else chainID[0] = char(0); 125 } 126 SetChain(PChain Chain_Owner)127 void ContainerChain::SetChain ( PChain Chain_Owner ) { 128 chain = Chain_Owner; 129 if (chain) strcpy ( chainID,chain->GetChainID() ); 130 else strcpy ( chainID,"" ); 131 } 132 MakeStreamFunctions(ContainerChain)133 MakeStreamFunctions(ContainerChain) 134 135 136 // ================ DBReference =================== 137 138 DBReference::DBReference() : ContainerChain() { 139 InitDBReference(); 140 } 141 DBReference(PChain Chain_Owner)142 DBReference::DBReference( PChain Chain_Owner ) 143 : ContainerChain(Chain_Owner) { 144 InitDBReference(); 145 } 146 DBReference(PChain Chain_Owner,cpstr S)147 DBReference::DBReference ( PChain Chain_Owner, cpstr S ) 148 : ContainerChain(Chain_Owner) { 149 InitDBReference(); 150 ConvertPDBASCII ( S ); 151 } 152 DBReference(io::RPStream Object)153 DBReference::DBReference ( io::RPStream Object ) 154 : ContainerChain(Object) { 155 InitDBReference(); 156 } 157 ~DBReference()158 DBReference::~DBReference() {} 159 InitDBReference()160 void DBReference::InitDBReference() { 161 seqBeg = 0; 162 strcpy ( insBeg ,"-" ); 163 seqEnd = 0; 164 strcpy ( insEnd ,"-" ); 165 strcpy ( database ,"------" ); 166 strcpy ( dbAccession,"--------" ); 167 strcpy ( dbIdCode ,"------------" ); 168 dbseqBeg = 0; 169 strcpy ( dbinsBeg,"-" ); 170 dbseqEnd = 0; 171 strcpy ( dbinsEnd,"-" ); 172 } 173 PDBASCIIDump(pstr S,int N)174 void DBReference::PDBASCIIDump ( pstr S, int N ) { 175 UNUSED_ARGUMENT(N); 176 // makes the ASCII PDB DBREF line number N 177 // from the class' data 178 strcpy ( S,"DBREF" ); 179 PadSpaces ( S,80 ); 180 strcpy_n ( &(S[7]),chain->GetEntryID(),4 ); 181 if (chain->chainID[0]) S[12] = chain->chainID[0]; 182 PutIntIns ( &(S[14]),seqBeg,4,insBeg ); 183 PutIntIns ( &(S[20]),seqEnd,4,insEnd ); 184 strcpy_n ( &(S[26]),database ,6 ); 185 strcpy_n ( &(S[33]),dbAccession,8 ); 186 strcpy_n ( &(S[42]),dbIdCode ,12 ); 187 PutIntIns ( &(S[55]),dbseqBeg,5,dbinsBeg ); 188 PutIntIns ( &(S[62]),dbseqEnd,5,dbinsEnd ); 189 } 190 MakeCIF(mmcif::PData CIF,int N)191 void DBReference::MakeCIF ( mmcif::PData CIF, int N ) { 192 UNUSED_ARGUMENT(N); 193 mmcif::PLoop Loop1,Loop2; 194 int RC1,RC2; 195 196 RC1 = CIF->AddLoop ( CIFCAT_STRUCT_REF_SEQ,Loop1 ); 197 RC2 = CIF->AddLoop ( CIFCAT_STRUCT_REF ,Loop2 ); 198 199 if ((RC1!=mmcif::CIFRC_Ok) || (RC2!=mmcif::CIFRC_Ok)) { 200 // the category was (re)created, provide tags 201 Loop1->AddLoopTag ( CIFTAG_NDB_PDB_ID_CODE ); 202 Loop1->AddLoopTag ( CIFTAG_NDB_CHAIN_ID ); 203 Loop1->AddLoopTag ( CIFTAG_SEQ_ALIGN_BEG ); 204 Loop1->AddLoopTag ( CIFTAG_NDB_SEQ_ALIGN_BEG_INS_CODE ); 205 Loop1->AddLoopTag ( CIFTAG_SEQ_ALIGN_END ); 206 Loop1->AddLoopTag ( CIFTAG_NDB_SEQ_ALIGN_END_INS_CODE ); 207 Loop1->AddLoopTag ( CIFTAG_NDB_DB_ACCESSION ); 208 Loop1->AddLoopTag ( CIFTAG_DB_ALIGN_BEG ); 209 Loop1->AddLoopTag ( CIFTAG_NDB_DB_ALIGN_BEG_INS_CODE ); 210 Loop1->AddLoopTag ( CIFTAG_DB_ALIGN_END ); 211 Loop1->AddLoopTag ( CIFTAG_NDB_DB_ALIGN_END_INS_CODE ); 212 Loop2->AddLoopTag ( CIFTAG_DB_NAME ); 213 Loop2->AddLoopTag ( CIFTAG_DB_CODE ); 214 } 215 216 Loop1->AddString ( chain->GetEntryID(),true ); 217 Loop1->AddString ( chain->chainID ,true ); 218 Loop1->AddInteger ( seqBeg ); 219 Loop1->AddString ( insBeg ,true ); 220 Loop1->AddInteger ( seqEnd ); 221 Loop1->AddString ( insEnd ,true ); 222 Loop1->AddString ( dbAccession ,true ); 223 Loop1->AddInteger ( dbseqBeg ); 224 Loop1->AddString ( dbinsBeg ,true ); 225 Loop1->AddInteger ( dbseqEnd ); 226 Loop1->AddString ( dbinsEnd ,true ); 227 228 Loop2->AddString ( database,true ); 229 Loop2->AddString ( dbIdCode,true ); 230 231 } 232 GetCIF(mmcif::PData CIF,int & n)233 ERROR_CODE DBReference::GetCIF ( mmcif::PData CIF, int & n ) { 234 // GetCIF(..) must be always run without reference to Chain, 235 // see CModel::GetCIF(..). 236 mmcif::PLoop Loop1,Loop2; 237 mmcif::PStruct Struct2; 238 pstr F; 239 int RC,ref_id1,ref_id2; 240 CIF_MODE CIFMode; 241 ERROR_CODE rc; 242 243 Loop1 = CIF->GetLoop ( CIFCAT_STRUCT_REF_SEQ ); 244 245 if (!Loop1) { 246 n = -1; 247 return Error_EmptyCIF; 248 } 249 250 if (n>=Loop1->GetLoopLength()) { 251 n = -1; 252 return Error_EmptyCIF; 253 } 254 255 256 // Determine the ChainID first and store it locally. It will 257 // be used by CModel for generating chains and placing the 258 // primary structure data BEFORE reading the coordinate section. 259 CIFMode = CIF_NDB; 260 F = Loop1->GetString ( CIFName(TAG_CHAIN_ID,CIFMode),n,RC ); 261 if ((RC) || (!F)) { 262 CIFMode = CIF_PDBX; 263 F = Loop1->GetString ( CIFName(TAG_CHAIN_ID,CIFMode),n,RC ); 264 } 265 if ((!RC) && F) { 266 strcpy_n0 ( chainID,F,sizeof(ChainID)-1 ); 267 Loop1->DeleteField ( CIFName(TAG_CHAIN_ID,CIFMode),n ); 268 } else 269 strcpy ( chainID,"" ); 270 271 272 rc = CIFGetInteger(seqBeg,Loop1,CIFName(TAG_SEQ_ALIGN_BEG,CIFMode),n ); 273 if (rc==Error_NoData) return Error_EmptyCIF; 274 if (rc!=Error_NoError) return rc; 275 CIFGetString ( insBeg,Loop1,CIFName(TAG_SEQ_ALIGN_BEG_INS_CODE,CIFMode), 276 n,sizeof(InsCode),pstr(" ") ); 277 278 rc = CIFGetInteger(seqEnd,Loop1,CIFName(TAG_SEQ_ALIGN_END,CIFMode),n ); 279 if (rc==Error_NoData) return Error_EmptyCIF; 280 if (rc!=Error_NoError) return rc; 281 CIFGetString ( insEnd,Loop1,CIFName(TAG_SEQ_ALIGN_END_INS_CODE,CIFMode), 282 n,sizeof(InsCode),pstr(" ") ); 283 CIFGetString ( dbAccession,Loop1,CIFName(TAG_DB_ACCESSION,CIFMode), 284 n,sizeof(DBAcCode),pstr(" ") ); 285 286 rc = CIFGetInteger(dbseqBeg,Loop1,CIFName(TAG_DB_ALIGN_BEG,CIFMode),n); 287 if (rc==Error_NoData) return Error_EmptyCIF; 288 if (rc!=Error_NoError) return rc; 289 CIFGetString ( dbinsBeg,Loop1,CIFName(TAG_DB_ALIGN_BEG_INS_CODE,CIFMode), 290 n,sizeof(InsCode),pstr(" ") ); 291 292 rc = CIFGetInteger(dbseqEnd,Loop1,CIFName(TAG_DB_ALIGN_END,CIFMode),n); 293 if (rc==Error_NoData) return Error_EmptyCIF; 294 if (rc!=Error_NoError) return rc; 295 CIFGetString ( dbinsEnd,Loop1,CIFName(TAG_DB_ALIGN_END_INS_CODE,CIFMode), 296 n,sizeof(InsCode),pstr(" ") ); 297 298 Loop2 = CIF->GetLoop ( CIFCAT_STRUCT_REF ); 299 if (Loop2) { 300 CIFGetString ( database,Loop2,CIFTAG_DB_NAME,n, 301 sizeof(DBName) ,pstr(" ") ); 302 CIFGetString ( dbIdCode,Loop2,CIFTAG_DB_CODE,n, 303 sizeof(DBIdCode),pstr(" ") ); 304 } else if (CIFMode==CIF_PDBX) { 305 Struct2 = CIF->GetStructure ( CIFCAT_STRUCT_REF ); 306 if (Struct2 && 307 (!CIFGetInteger(ref_id1,Loop1,CIFTAG_REF_ID,n)) && 308 (!CIFGetInteger(ref_id2,Struct2,CIFTAG_ID,false))) { 309 if (ref_id1==ref_id2) { 310 CIFGetString ( database,Struct2,CIFTAG_DB_NAME, 311 sizeof(DBName) ,pstr(" ") ,false ); 312 CIFGetString ( dbIdCode,Struct2,CIFTAG_DB_CODE, 313 sizeof(DBIdCode),pstr(" "),false ); 314 } 315 } 316 } 317 318 n++; 319 320 return Error_NoError; 321 322 } 323 324 ConvertPDBASCII(cpstr S)325 ERROR_CODE DBReference::ConvertPDBASCII ( cpstr S ) { 326 IDCode idCode; 327 if (chain->chainID[0]) { 328 if (S[12]!=chain->chainID[0]) 329 return Error_WrongChainID; 330 } else if (S[12]!=' ') { 331 chain->chainID[0] = S[12]; 332 chain->chainID[1] = char(0); 333 } else 334 chain->chainID[0] = char(0); 335 strcpy ( idCode,chain->GetEntryID() ); 336 if (idCode[0]) { 337 if (strncmp(&(S[7]),idCode,4) && (!ignoreNonCoorPDBErrors)) 338 return Error_WrongEntryID; 339 } else { 340 GetString ( idCode,&(S[7]),4 ); 341 chain->SetEntryID ( idCode ); 342 } 343 GetIntIns ( seqBeg,insBeg,&(S[14]),4 ); 344 GetIntIns ( seqEnd,insEnd,&(S[20]),4 ); 345 strcpy_ncs ( database ,&(S[26]),6 ); 346 strcpy_ncs ( dbAccession ,&(S[33]),8 ); 347 strcpy_ncs ( dbIdCode ,&(S[42]),12 ); 348 GetIntIns ( dbseqBeg,dbinsBeg,&(S[55]),5 ); 349 GetIntIns ( dbseqEnd,dbinsEnd,&(S[62]),5 ); 350 return Error_NoError; 351 } 352 Copy(PContainerClass DBRef)353 void DBReference::Copy ( PContainerClass DBRef ) { 354 355 ContainerChain::Copy ( DBRef ); 356 357 seqBeg = PDBReference(DBRef)->seqBeg; 358 seqEnd = PDBReference(DBRef)->seqEnd; 359 dbseqBeg = PDBReference(DBRef)->dbseqBeg; 360 dbseqEnd = PDBReference(DBRef)->dbseqEnd; 361 strcpy ( insBeg ,PDBReference(DBRef)->insBeg ); 362 strcpy ( insEnd ,PDBReference(DBRef)->insEnd ); 363 strcpy ( database ,PDBReference(DBRef)->database ); 364 strcpy ( dbAccession,PDBReference(DBRef)->dbAccession ); 365 strcpy ( dbIdCode ,PDBReference(DBRef)->dbIdCode ); 366 strcpy ( dbinsBeg ,PDBReference(DBRef)->dbinsBeg ); 367 strcpy ( dbinsEnd ,PDBReference(DBRef)->dbinsEnd ); 368 369 } 370 write(io::RFile f)371 void DBReference::write ( io::RFile f ) { 372 byte Version=1; 373 f.WriteByte ( &Version ); 374 f.WriteInt ( &seqBeg ); 375 f.WriteInt ( &seqEnd ); 376 f.WriteInt ( &dbseqBeg ); 377 f.WriteInt ( &dbseqEnd ); 378 f.WriteTerLine ( insBeg ,false ); 379 f.WriteTerLine ( insEnd ,false ); 380 f.WriteTerLine ( database ,false ); 381 f.WriteTerLine ( dbAccession,false ); 382 f.WriteTerLine ( dbIdCode ,false ); 383 f.WriteTerLine ( dbinsBeg ,false ); 384 f.WriteTerLine ( dbinsEnd ,false ); 385 } 386 read(io::RFile f)387 void DBReference::read ( io::RFile f ) { 388 byte Version; 389 f.ReadByte ( &Version ); 390 f.ReadInt ( &seqBeg ); 391 f.ReadInt ( &seqEnd ); 392 f.ReadInt ( &dbseqBeg ); 393 f.ReadInt ( &dbseqEnd ); 394 f.ReadTerLine ( insBeg ,false ); 395 f.ReadTerLine ( insEnd ,false ); 396 f.ReadTerLine ( database ,false ); 397 f.ReadTerLine ( dbAccession,false ); 398 f.ReadTerLine ( dbIdCode ,false ); 399 f.ReadTerLine ( dbinsBeg ,false ); 400 f.ReadTerLine ( dbinsEnd ,false ); 401 } 402 MakeStreamFunctions(DBReference)403 MakeStreamFunctions(DBReference) 404 405 406 407 // ================ SeqAdv =================== 408 409 SeqAdv::SeqAdv() : ContainerChain() { 410 InitSeqAdv(); 411 } 412 SeqAdv(PChain Chain_Owner)413 SeqAdv::SeqAdv ( PChain Chain_Owner ) 414 : ContainerChain(Chain_Owner) { 415 InitSeqAdv(); 416 } 417 SeqAdv(PChain Chain_Owner,cpstr S)418 SeqAdv::SeqAdv ( PChain Chain_Owner, cpstr S ) 419 : ContainerChain(Chain_Owner) { 420 InitSeqAdv(); 421 ConvertPDBASCII ( S ); 422 } 423 SeqAdv(io::RPStream Object)424 SeqAdv::SeqAdv ( io::RPStream Object ) : ContainerChain(Object) { 425 InitSeqAdv(); 426 } 427 ~SeqAdv()428 SeqAdv::~SeqAdv() { 429 if (conflict) delete[] conflict; 430 } 431 InitSeqAdv()432 void SeqAdv::InitSeqAdv() { 433 strcpy ( resName ,"---" ); 434 seqNum = 0; 435 strcpy ( insCode ,"-" ); 436 strcpy ( database ,"------" ); 437 strcpy ( dbAccession,"---------" ); 438 strcpy ( dbRes ,"---" ); 439 dbSeq = 0; 440 conflict = NULL; 441 CreateCopy ( conflict,pstr(" ") ); 442 } 443 PDBASCIIDump(pstr S,int N)444 void SeqAdv::PDBASCIIDump ( pstr S, int N ) { 445 UNUSED_ARGUMENT(N); 446 // makes the ASCII PDB SEQADV line number N 447 // from the class' data 448 strcpy ( S,"SEQADV" ); 449 PadSpaces ( S,80 ); 450 strcpy_n ( &(S[7]) ,chain->GetEntryID(),4 ); 451 strcpy_n ( &(S[12]),resName ,3 ); 452 if (chain->chainID[0]) S[16] = chain->chainID[0]; 453 PutIntIns ( &(S[18]),seqNum,4,insCode ); 454 strcpy_n ( &(S[24]),database ,4 ); 455 strcpy_n ( &(S[29]),dbAccession,9 ); 456 strcpy_n ( &(S[39]),dbRes ,3 ); 457 PutInteger ( &(S[43]),dbSeq ,5 ); 458 strcpy_n ( &(S[49]),conflict,IMin(strlen(conflict),21) ); 459 } 460 ConvertPDBASCII(cpstr S)461 ERROR_CODE SeqAdv::ConvertPDBASCII ( cpstr S ) { 462 IDCode idCode; 463 if (chain->chainID[0]) { 464 if (S[16]!=chain->chainID[0]) 465 return Error_WrongChainID; 466 } else if (S[16]!=' ') { 467 chain->chainID[0] = S[16]; 468 chain->chainID[1] = char(0); 469 } else 470 chain->chainID[0] = char(0); 471 strcpy ( idCode,chain->GetEntryID() ); 472 if (idCode[0]) { 473 if (strncmp(&(S[7]),idCode,4) && (!ignoreNonCoorPDBErrors)) 474 return Error_WrongEntryID; 475 } else { 476 GetString ( idCode,&(S[7]),4 ); 477 chain->SetEntryID ( idCode ); 478 } 479 strcpy_ncs ( resName ,&(S[12]),3 ); 480 GetIntIns ( seqNum,insCode,&(S[18]),4 ); 481 strcpy_ncs ( database ,&(S[24]),4 ); 482 strcpy_ncs ( dbAccession ,&(S[29]),9 ); 483 strcpy_ncs ( dbRes ,&(S[39]),3 ); 484 GetInteger ( dbSeq,&(S[43]),5 ); 485 CreateCopy ( conflict,&(S[49]) ); 486 CutSpaces ( conflict,SCUTKEY_END ); 487 return Error_NoError; 488 } 489 490 MakeCIF(mmcif::PData CIF,int N)491 void SeqAdv::MakeCIF ( mmcif::PData CIF, int N ) { 492 UNUSED_ARGUMENT(N); 493 mmcif::PLoop Loop; 494 int RC; 495 496 RC = CIF->AddLoop ( CIFCAT_STRUCT_REF_SEQ_DIF,Loop ); 497 498 if (RC!=mmcif::CIFRC_Ok) { 499 // the category was (re)created, provide tags 500 Loop->AddLoopTag ( CIFTAG_NDB_PDB_ID_CODE ); 501 Loop->AddLoopTag ( CIFTAG_MON_ID ); 502 Loop->AddLoopTag ( CIFTAG_NDB_PDB_CHAIN_ID ); 503 Loop->AddLoopTag ( CIFTAG_SEQ_NUM ); 504 Loop->AddLoopTag ( CIFTAG_NDB_PDB_INS_CODE ); 505 Loop->AddLoopTag ( CIFTAG_NDB_SEQ_DB_NAME ); 506 Loop->AddLoopTag ( CIFTAG_NDB_SEQ_DB_ACCESSION_CODE ); 507 Loop->AddLoopTag ( CIFTAG_DB_MON_ID ); 508 Loop->AddLoopTag ( CIFTAG_NDB_SEQ_DB_SEQ_NUM ); 509 Loop->AddLoopTag ( CIFTAG_DETAILS ); 510 } 511 512 Loop->AddString ( chain->GetEntryID(),true ); 513 Loop->AddString ( resName ,true ); 514 Loop->AddString ( chain->chainID ,true ); 515 Loop->AddInteger ( seqNum ); 516 Loop->AddString ( insCode ,true ); 517 Loop->AddString ( database ,true ); 518 Loop->AddString ( dbAccession ,true ); 519 Loop->AddString ( dbRes ,true ); 520 Loop->AddInteger ( dbSeq ); 521 Loop->AddString ( conflict ,true ); 522 523 } 524 GetCIF(mmcif::PData CIF,int & n)525 ERROR_CODE SeqAdv::GetCIF ( mmcif::PData CIF, int & n ) { 526 // GetCIF(..) must be always run without reference to Chain, 527 // see CModel::GetCIF(..). 528 mmcif::PLoop Loop; 529 pstr F; 530 int RC; 531 532 Loop = CIF->GetLoop ( CIFCAT_STRUCT_REF_SEQ_DIF ); 533 if (!Loop) { 534 n = -1; 535 return Error_EmptyCIF; 536 } 537 538 if (n>=Loop->GetLoopLength()) { 539 n = -1; 540 return Error_EmptyCIF; 541 } 542 543 // Determine the ChainID first and store it locally. It will 544 // be used by CModel for generating chains and placing the 545 // primary structure data BEFORE reading the coordinate section. 546 547 F = Loop->GetString ( CIFTAG_NDB_PDB_CHAIN_ID,n,RC ); 548 if ((!RC) && F) { 549 strcpy_n0 ( chainID,F,sizeof(ChainID)-1 ); 550 Loop->DeleteField ( CIFTAG_NDB_PDB_CHAIN_ID,n ); 551 } else 552 strcpy ( chainID,"" ); 553 554 CIFGetString ( resName,Loop,CIFTAG_MON_ID,n,sizeof(ResName), 555 pstr("UNK") ); 556 557 CIFGetIntegerD ( seqNum,Loop,CIFTAG_SEQ_NUM ); 558 559 CIFGetString ( insCode,Loop,CIFTAG_NDB_PDB_INS_CODE, 560 n,sizeof(InsCode),pstr(" ") ); 561 562 CIFGetString ( database,Loop,CIFTAG_NDB_SEQ_DB_NAME,n, 563 sizeof(DBName),pstr(" ") ); 564 565 CIFGetString ( dbAccession,Loop,CIFTAG_NDB_SEQ_DB_ACCESSION_CODE, 566 n,sizeof(DBAcCode),pstr(" ") ); 567 568 CIFGetString ( dbRes,Loop,CIFTAG_DB_MON_ID,n,sizeof(ResName), 569 pstr(" ") ); 570 571 CIFGetIntegerD ( dbSeq,Loop,CIFTAG_NDB_SEQ_DB_SEQ_NUM ); 572 // if (CIFGetInteger1(dbSeq,Loop,CIFTAG_NDB_SEQ_DB_SEQ_NUM,n)) 573 // dbSeq = MinInt4; 574 575 F = Loop->GetString ( CIFTAG_DETAILS,n,RC ); 576 if ((!RC) && F) { 577 CreateCopy ( conflict,F ); 578 Loop->DeleteField ( CIFTAG_DETAILS,n ); 579 } else 580 CreateCopy ( conflict,pstr(" ") ); 581 582 n++; 583 584 return Error_NoError; 585 586 } 587 Copy(PContainerClass SeqAdv)588 void SeqAdv::Copy ( PContainerClass SeqAdv ) { 589 590 ContainerClass::Copy ( SeqAdv ); 591 592 seqNum = PSeqAdv(SeqAdv)->seqNum; 593 dbSeq = PSeqAdv(SeqAdv)->dbSeq; 594 strcpy ( resName ,PSeqAdv(SeqAdv)->resName ); 595 strcpy ( insCode ,PSeqAdv(SeqAdv)->insCode ); 596 strcpy ( database ,PSeqAdv(SeqAdv)->database ); 597 strcpy ( dbAccession,PSeqAdv(SeqAdv)->dbAccession ); 598 strcpy ( dbRes ,PSeqAdv(SeqAdv)->dbRes ); 599 CreateCopy ( conflict,PSeqAdv(SeqAdv)->conflict ); 600 601 } 602 write(io::RFile f)603 void SeqAdv::write ( io::RFile f ) { 604 byte Version=1; 605 f.WriteByte ( &Version ); 606 f.WriteInt ( &seqNum ); 607 f.WriteInt ( &dbSeq ); 608 f.WriteTerLine ( resName ,false ); 609 f.WriteTerLine ( insCode ,false ); 610 f.WriteTerLine ( database ,false ); 611 f.WriteTerLine ( dbAccession,false ); 612 f.WriteTerLine ( dbRes ,false ); 613 f.CreateWrite ( conflict ); 614 } 615 read(io::RFile f)616 void SeqAdv::read ( io::RFile f ) { 617 byte Version; 618 f.ReadByte ( &Version ); 619 f.ReadInt ( &seqNum ); 620 f.ReadInt ( &dbSeq ); 621 f.ReadTerLine ( resName ,false ); 622 f.ReadTerLine ( insCode ,false ); 623 f.ReadTerLine ( database ,false ); 624 f.ReadTerLine ( dbAccession,false ); 625 f.ReadTerLine ( dbRes ,false ); 626 f.CreateRead ( conflict ); 627 } 628 MakeStreamFunctions(SeqAdv)629 MakeStreamFunctions(SeqAdv) 630 631 632 633 // ================ SeqRes =================== 634 635 SeqRes::SeqRes() : io::Stream() { 636 InitSeqRes(); 637 } 638 SeqRes(io::RPStream Object)639 SeqRes::SeqRes ( io::RPStream Object ) : io::Stream(Object) { 640 InitSeqRes(); 641 } 642 ~SeqRes()643 SeqRes::~SeqRes() { 644 FreeMemory(); 645 } 646 SetChain(PChain Chain_Owner)647 void SeqRes::SetChain ( PChain Chain_Owner ) { 648 chain = Chain_Owner; 649 if (chain) strcpy ( chainID,chain->chainID ); 650 else strcpy ( chainID,"" ); 651 } 652 InitSeqRes()653 void SeqRes::InitSeqRes() { 654 chain = NULL; 655 numRes = -1; 656 resName = NULL; 657 serNum = 0; 658 strcpy ( chainID,"" ); 659 } 660 FreeMemory()661 void SeqRes::FreeMemory() { 662 if (resName) delete[] resName; 663 resName = NULL; 664 numRes = -1; 665 serNum = 0; 666 } 667 PDBASCIIDump(io::RFile f)668 void SeqRes::PDBASCIIDump ( io::RFile f ) { 669 // writes the ASCII PDB SEQRES lines into file f 670 char S[100]; 671 int i,k,sN; 672 if (numRes<0) return; 673 strcpy ( S,"SEQRES" ); 674 PadSpaces ( S,80 ); 675 if (chain->chainID[0]) 676 S[11] = chain->chainID[0]; 677 PutInteger ( &(S[13]),numRes,4 ); 678 if (resName) { 679 i = 0; 680 sN = 1; 681 while (i<numRes) { 682 PutInteger ( &(S[7]),sN,3 ); 683 k = 19; 684 while ((i<numRes) && (k<70)) { 685 if (resName[i][0]) 686 strcpy_n ( &(S[k]),resName[i],3 ); 687 else strcpy_n ( &(S[k]),pstr(" "),3 ); 688 i++; 689 k += 4; 690 } 691 while (k<70) { 692 strcpy_n ( &(S[k]),pstr(" "),3 ); 693 k += 4; 694 } 695 f.WriteLine ( S ); 696 sN++; 697 } 698 } else { 699 S[9] = '0'; 700 strcpy_n ( &(S[19]),pstr("UNK"),3 ); 701 f.WriteLine ( S ); 702 } 703 } 704 ConvertPDBASCII(cpstr S)705 ERROR_CODE SeqRes::ConvertPDBASCII ( cpstr S ) { 706 int i,k,sN,nR; 707 if (chain->chainID[0]) { 708 if (S[11]!=chain->chainID[0]) 709 return Error_WrongChainID; 710 } else if (S[11]!=' ') { 711 chain->chainID[0] = S[11]; 712 chain->chainID[1] = char(0); 713 } else 714 chain->chainID[0] = char(0); 715 GetInteger ( sN,&(S[8]) ,3 ); 716 GetInteger ( nR,&(S[13]),4 ); 717 if (sN==0) { 718 FreeMemory(); 719 numRes = nR; 720 } else { 721 serNum++; 722 if (sN!=serNum) 723 return Error_SEQRES_serNum; 724 if (sN==1) { 725 FreeMemory(); 726 resName = new ResName[nR]; 727 for (i=0;i<nR;i++) 728 resName[i][0] = char(0); 729 numRes = nR; 730 serNum = sN; 731 } else if (nR!=numRes) 732 return Error_SEQRES_numRes; 733 i = 0; 734 while ((i<nR) && (resName[i][0])) i++; 735 if (i>=nR) 736 return Error_SEQRES_extraRes; 737 k = 19; 738 while ((i<nR) && (k<70)) { 739 GetString ( resName[i],&(S[k]),3 ); 740 if (!strcmp(resName[i]," ")) resName[i][0] = char(0); 741 else i++; 742 k += 4; 743 } 744 } 745 return Error_NoError; 746 } 747 748 MakeCIF(mmcif::PData CIF)749 void SeqRes::MakeCIF ( mmcif::PData CIF ) { 750 // Note that SeqRes only adds sequence to the CIF loop common 751 // to all chains. Therefore this loop should be wiped off from 752 // CIF structure before putting first sequence into it. 753 mmcif::PLoop Loop; 754 int RC,i; 755 756 if (numRes<0) return; 757 758 RC = CIF->AddLoop ( CIFCAT_NDB_POLY_SEQ_SCHEME,Loop ); 759 if (RC!=mmcif::CIFRC_Ok) { 760 // the category was (re)created, provide tags 761 Loop->AddLoopTag ( CIFTAG_ID ); 762 Loop->AddLoopTag ( CIFTAG_MON_ID ); 763 } 764 765 if (resName) 766 for (i=0;i<numRes;i++) { 767 Loop->AddString ( chain->chainID,true ); 768 Loop->AddString ( resName[i] ,true ); 769 } 770 else 771 for (i=0;i<numRes;i++) { 772 Loop->AddString ( chain->GetEntryID(),true ); 773 Loop->AddString ( pstr("UNK") ,true ); 774 } 775 776 } 777 GetCIF(mmcif::PData CIF)778 ERROR_CODE SeqRes::GetCIF ( mmcif::PData CIF ) { 779 // Tries to get sequence from the CIF structure. A sequence 780 // for first met chain is extracted and then removed from 781 // the CIF structure, so that sequential calls will extract 782 // all sequencies. Chain ID is stored locally in chainID; 783 // reference to parent chain is neither used nor checked. 784 // Returns 0 if sequence was extracted and 1 otherwise. 785 mmcif::PLoop Loop; 786 ResName * rN; 787 ChainID chID; 788 pstr F; 789 cpstr CHAIN_ID; 790 int RC,i,l; 791 CIF_MODE CIFMode; 792 bool isMon; 793 794 FreeMemory(); 795 796 CIFMode = CIF_NDB; 797 Loop = CIF->GetLoop ( CIFName(CAT_POLY_SEQ_SCHEME,CIFMode) ); 798 if (!Loop) { 799 CIFMode = CIF_PDBX; 800 Loop = CIF->GetLoop ( CIFName(CAT_POLY_SEQ_SCHEME,CIFMode) ); 801 if (!Loop) return Error_NoLoop; 802 } 803 804 l = Loop->GetLoopLength(); 805 if (l<=0) return Error_NoLoop; 806 807 rN = new ResName[l]; 808 chainID[0] = char(1); 809 numRes = 0; 810 isMon = false; 811 CHAIN_ID = CIFName(TAG_SEQ_CHAIN_ID,CIFMode); 812 for (i=0;i<l;i++) { 813 F = Loop->GetString ( CHAIN_ID,i,RC ); 814 if (!RC) { 815 if (F) strcpy ( chID,F ); 816 else chID[0] = char(0); 817 if (chainID[0]==char(1)) strcpy ( chainID,chID ); 818 if (!strcmp(chainID,chID)) { 819 CIFGetString ( rN[numRes],Loop,CIFTAG_MON_ID,i, 820 sizeof(ResName),pstr("UNK") ); 821 Loop->DeleteField ( CHAIN_ID,i ); 822 if (strcmp(rN[numRes],"UNK")) isMon = true; 823 numRes++; 824 } 825 } 826 } 827 828 if (numRes==0) { 829 numRes = -1; 830 delete[] rN; 831 return Error_EmptyCIFLoop; 832 } 833 834 if (isMon) { 835 resName = new ResName[numRes]; 836 for (i=0;i<numRes;i++) 837 strcpy ( resName[i],rN[i] ); 838 } 839 840 delete[] rN; 841 842 return Error_NoError; 843 844 } 845 Copy(PSeqRes SeqRes)846 void SeqRes::Copy ( PSeqRes SeqRes ) { 847 int i; 848 849 FreeMemory(); 850 851 numRes = SeqRes->numRes; 852 serNum = SeqRes->serNum; 853 854 if (SeqRes->resName) { 855 resName = new ResName[numRes]; 856 for (i=0;i<numRes;i++) 857 strcpy ( resName[i],SeqRes->resName[i] ); 858 } 859 860 } 861 write(io::RFile f)862 void SeqRes::write ( io::RFile f ) { 863 int i; 864 byte Version=1; 865 f.WriteByte ( &Version ); 866 f.WriteInt ( &numRes ); 867 f.WriteInt ( &serNum ); 868 if (resName) i = 1; 869 else i = 0; 870 f.WriteInt ( &i ); 871 if (resName) 872 for (i=0;i<numRes;i++) 873 f.WriteTerLine ( resName[i],false ); 874 } 875 read(io::RFile f)876 void SeqRes::read ( io::RFile f ) { 877 int i; 878 byte Version; 879 FreeMemory(); 880 f.ReadByte ( &Version ); 881 f.ReadInt ( &numRes ); 882 f.ReadInt ( &serNum ); 883 f.ReadInt ( &i ); 884 if (i) { 885 resName = new ResName[numRes]; 886 for (i=0;i<numRes;i++) 887 f.ReadTerLine ( resName[i],false ); 888 } 889 } 890 891 MakeStreamFunctions(SeqRes)892 MakeStreamFunctions(SeqRes) 893 894 895 896 // ================ ModRes =================== 897 898 ModRes::ModRes() : ContainerChain() { 899 InitModRes(); 900 } 901 ModRes(PChain Chain_Owner)902 ModRes::ModRes ( PChain Chain_Owner ) 903 : ContainerChain(Chain_Owner) { 904 InitModRes(); 905 } 906 ModRes(PChain Chain_Owner,cpstr S)907 ModRes::ModRes ( PChain Chain_Owner, cpstr S ) 908 : ContainerChain(Chain_Owner) { 909 InitModRes(); 910 ConvertPDBASCII ( S ); 911 } 912 ModRes(io::RPStream Object)913 ModRes::ModRes ( io::RPStream Object ) : ContainerChain(Object) { 914 InitModRes(); 915 } 916 ~ModRes()917 ModRes::~ModRes() { 918 if (comment) delete[] comment; 919 } 920 InitModRes()921 void ModRes::InitModRes() { 922 strcpy ( resName,"---" ); 923 seqNum = 0; 924 strcpy ( insCode,"-" ); 925 comment = NULL; 926 CreateCopy ( comment,pstr(" ") ); 927 strcpy ( stdRes ,"---" ); 928 } 929 PDBASCIIDump(pstr S,int N)930 void ModRes::PDBASCIIDump ( pstr S, int N ) { 931 UNUSED_ARGUMENT(N); 932 // makes the ASCII PDB MODRES line number N 933 // from the class' data 934 strcpy ( S,"MODRES" ); 935 PadSpaces ( S,80 ); 936 strcpy_n ( &(S[7]) ,chain->GetEntryID(),4 ); 937 strcpy_n ( &(S[12]),resName ,3 ); 938 if (chain->chainID[0]) S[16] = chain->chainID[0]; 939 PutIntIns ( &(S[18]),seqNum,4,insCode ); 940 strcpy_n ( &(S[24]),stdRes ,3 ); 941 strcpy_n ( &(S[29]),comment,IMin(strlen(comment),41) ); 942 } 943 ConvertPDBASCII(cpstr S)944 ERROR_CODE ModRes::ConvertPDBASCII ( cpstr S ) { 945 IDCode idCode; 946 if (chain->chainID[0]) { 947 if (S[16]!=chain->chainID[0]) 948 return Error_WrongChainID; 949 } else if (S[16]!=' ') { 950 chain->chainID[0] = S[16]; 951 chain->chainID[1] = char(0); 952 } else 953 chain->chainID[0] = char(0); 954 strcpy ( idCode,chain->GetEntryID() ); 955 if (idCode[0]) { 956 if (strncmp(&(S[7]),idCode,4) && (!ignoreNonCoorPDBErrors)) 957 return Error_WrongEntryID; 958 } else { 959 GetString ( idCode,&(S[7]),4 ); 960 chain->SetEntryID ( idCode ); 961 } 962 GetString ( resName ,&(S[12]),3 ); 963 GetIntIns ( seqNum,insCode,&(S[18]),4 ); 964 GetString ( stdRes ,&(S[24]),3 ); 965 CreateCopy ( comment ,&(S[29]) ); 966 CutSpaces ( comment,SCUTKEY_END ); 967 return Error_NoError; 968 } 969 MakeCIF(mmcif::PData CIF,int N)970 void ModRes::MakeCIF ( mmcif::PData CIF, int N ) { 971 UNUSED_ARGUMENT(CIF); 972 UNUSED_ARGUMENT(N); 973 /* -- apparently wrong use of _struct_conn, to be revised 974 mmcif::PLoop Loop; 975 int RC; 976 977 RC = CIF->AddLoop ( CIFCAT_STRUCT_CONN,Loop ); 978 979 if (RC!=mmcif::CIFRC_Ok) { 980 // the category was (re)created, provide tags 981 Loop->AddLoopTag ( CIFTAG_CONN_TYPE_ID ); 982 Loop->AddLoopTag ( CIFTAG_NDB_PDB_ID ); 983 Loop->AddLoopTag ( CIFTAG_PTNR1_LABEL_COMP_ID ); 984 Loop->AddLoopTag ( CIFTAG_PTNR1_LABEL_ASYM_ID ); 985 Loop->AddLoopTag ( CIFTAG_PTNR1_LABEL_SEQ_ID ); 986 Loop->AddLoopTag ( CIFTAG_NDB_PTNR1_LABEL_INS_CODE ); 987 Loop->AddLoopTag ( CIFTAG_NDB_PTNR1_STANDARD_COMP_ID ); 988 Loop->AddLoopTag ( CIFTAG_DETAILS ); 989 } 990 991 Loop->AddString ( pstr("MODRES") ); 992 Loop->AddString ( chain->GetEntryID(),true ); 993 Loop->AddString ( resName ,true ); 994 Loop->AddString ( chain->chainID ,true ); 995 Loop->AddInteger ( seqNum ); 996 Loop->AddString ( insCode ,true ); 997 Loop->AddString ( stdRes ,true ); 998 Loop->AddString ( comment ,true ); 999 1000 */ 1001 1002 } 1003 GetCIF(mmcif::PData CIF,int & n)1004 ERROR_CODE ModRes::GetCIF ( mmcif::PData CIF, int & n ) { 1005 UNUSED_ARGUMENT(CIF); 1006 // GetCIF(..) must be always run without reference to Chain, 1007 // see CModel::GetCIF(..). 1008 1009 /* -- apparently wrong use of _struct_conn, to be revised 1010 mmcif::PLoop Loop; 1011 pstr F; 1012 int l,RC; 1013 1014 Loop = CIF->GetLoop ( CIFCAT_STRUCT_CONN ); 1015 if (!Loop) { 1016 n = -1; 1017 return; 1018 } 1019 1020 l = Loop->GetLoopLength(); 1021 while (n<l) { 1022 F = Loop->GetString ( CIFTAG_CONN_TYPE_ID,n,RC ); 1023 if ((!RC) && F) { 1024 if (!strcmp(F,"MODRES")) break; 1025 } 1026 n++; 1027 } 1028 if (n>=l) { 1029 n = -1; 1030 return; 1031 } 1032 1033 Loop->DeleteField ( CIFTAG_CONN_TYPE_ID,n ); 1034 1035 // Determine the ChainID first and store it locally. It will 1036 // be used by CModel for generating chains and placing the 1037 // primary structure data BEFORE reading the coordinate section. 1038 F = Loop->GetString ( CIFTAG_PTNR1_LABEL_ASYM_ID,n,RC ); 1039 if ((!RC) && F) { 1040 strcpy_n0 ( chainID,F,sizeof(ChainID)-1 ); 1041 Loop->DeleteField ( CIFTAG_PTNR1_LABEL_ASYM_ID,n ); 1042 } else 1043 strcpy ( chainID,"" ); 1044 1045 1046 CIFGetString ( resName,Loop,CIFTAG_PTNR1_LABEL_COMP_ID,n, 1047 sizeof(ResName),pstr("UNK") ); 1048 1049 if (CIFGetInteger(seqNum,Loop,CIFTAG_PTNR1_LABEL_SEQ_ID,n)) 1050 return; 1051 1052 CIFGetString ( insCode,Loop,CIFTAG_NDB_PTNR1_LABEL_INS_CODE, 1053 n,sizeof(InsCode),pstr(" ") ); 1054 1055 CIFGetString ( stdRes,Loop,CIFTAG_NDB_PTNR1_STANDARD_COMP_ID,n, 1056 sizeof(ResName),pstr("UNK") ); 1057 1058 F = Loop->GetString ( CIFTAG_DETAILS,n,RC ); 1059 if ((!RC) && F) { 1060 CreateCopy ( comment,F ); 1061 Loop->DeleteField ( CIFTAG_DETAILS,n ); 1062 } else 1063 CreateCopy ( comment,pstr(" ") ); 1064 1065 n++; 1066 1067 */ 1068 1069 n = -1; 1070 1071 return Error_EmptyCIF; 1072 1073 } 1074 Copy(PContainerClass ModRes)1075 void ModRes::Copy ( PContainerClass ModRes ) { 1076 seqNum = PModRes(ModRes)->seqNum; 1077 strcpy ( resName,PModRes(ModRes)->resName ); 1078 strcpy ( insCode,PModRes(ModRes)->insCode ); 1079 strcpy ( stdRes ,PModRes(ModRes)->stdRes ); 1080 CreateCopy ( comment,PModRes(ModRes)->comment ); 1081 } 1082 write(io::RFile f)1083 void ModRes::write ( io::RFile f ) { 1084 byte Version=1; 1085 f.WriteByte ( &Version ); 1086 f.WriteInt ( &seqNum ); 1087 f.WriteTerLine ( resName,false ); 1088 f.WriteTerLine ( insCode,false ); 1089 f.WriteTerLine ( stdRes ,false ); 1090 f.CreateWrite ( comment ); 1091 } 1092 read(io::RFile f)1093 void ModRes::read ( io::RFile f ) { 1094 byte Version; 1095 f.ReadByte ( &Version ); 1096 f.ReadInt ( &seqNum ); 1097 f.ReadTerLine ( resName,false ); 1098 f.ReadTerLine ( insCode,false ); 1099 f.ReadTerLine ( stdRes ,false ); 1100 f.CreateRead ( comment ); 1101 } 1102 MakeStreamFunctions(ModRes)1103 MakeStreamFunctions(ModRes) 1104 1105 1106 1107 // ================ HetRec ====================== 1108 1109 HetRec::HetRec() : ContainerChain() { 1110 InitHetRec(); 1111 } 1112 HetRec(PChain Chain_Owner)1113 HetRec::HetRec ( PChain Chain_Owner ) 1114 : ContainerChain(Chain_Owner) { 1115 InitHetRec(); 1116 } 1117 HetRec(PChain Chain_Owner,cpstr S)1118 HetRec::HetRec ( PChain Chain_Owner, cpstr S ) 1119 : ContainerChain(Chain_Owner) { 1120 InitHetRec(); 1121 ConvertPDBASCII ( S ); 1122 } 1123 HetRec(io::RPStream Object)1124 HetRec::HetRec ( io::RPStream Object ) : ContainerChain(Object) { 1125 InitHetRec(); 1126 } 1127 ~HetRec()1128 HetRec::~HetRec() { 1129 if (comment) delete[] comment; 1130 } 1131 InitHetRec()1132 void HetRec::InitHetRec() { 1133 strcpy ( hetID ,"---" ); 1134 strcpy ( insCode,"-" ); 1135 seqNum = 0; 1136 numHetAtoms = 0; 1137 comment = NULL; 1138 CreateCopy ( comment,pstr(" ") ); 1139 } 1140 PDBASCIIDump(pstr S,int N)1141 void HetRec::PDBASCIIDump ( pstr S, int N ) { 1142 UNUSED_ARGUMENT(N); 1143 // makes the ASCII PDB MODRES line number N 1144 // from the class' data 1145 strcpy ( S,"HET" ); 1146 PadSpaces ( S,80 ); 1147 strcpy_n ( &(S[7]) ,hetID,3 ); 1148 if (chain->chainID[0]) S[12] = chain->chainID[0]; 1149 PutIntIns ( &(S[13]),seqNum,4,insCode ); 1150 PutInteger ( &(S[20]),numHetAtoms,5 ); 1151 strcpy_n ( &(S[30]),comment,IMin(strlen(comment),40) ); 1152 } 1153 ConvertPDBASCII(cpstr S)1154 ERROR_CODE HetRec::ConvertPDBASCII ( cpstr S ) { 1155 if (chain->chainID[0]) { 1156 if (S[12]!=chain->chainID[0]) 1157 return Error_WrongChainID; 1158 } else if (S[12]!=' ') { 1159 chain->chainID[0] = S[12]; 1160 chain->chainID[1] = char(0); 1161 } else 1162 chain->chainID[0] = char(0); 1163 GetString ( hetID ,&(S[7]) ,3 ); 1164 GetIntIns ( seqNum,insCode,&(S[13]),4 ); 1165 GetInteger ( numHetAtoms ,&(S[20]),5 ); 1166 CreateCopy ( comment ,&(S[30]) ); 1167 CutSpaces ( comment,SCUTKEY_END ); 1168 return Error_NoError; 1169 } 1170 MakeCIF(mmcif::PData CIF,int N)1171 void HetRec::MakeCIF ( mmcif::PData CIF, int N ) { 1172 UNUSED_ARGUMENT(N); 1173 mmcif::PLoop Loop; 1174 int RC; 1175 1176 RC = CIF->AddLoop ( CIFCAT_NDB_NONSTANDARD_LIST,Loop ); 1177 1178 if (RC!=mmcif::CIFRC_Ok) { 1179 // the category was (re)created, provide tags 1180 Loop->AddLoopTag ( CIFTAG_ID ); 1181 Loop->AddLoopTag ( CIFTAG_AUTH_ASYM_ID ); 1182 Loop->AddLoopTag ( CIFTAG_AUTH_SEQ_ID ); 1183 Loop->AddLoopTag ( CIFTAG_INS_CODE ); 1184 Loop->AddLoopTag ( CIFTAG_NUMBER_ATOMS_NH ); 1185 Loop->AddLoopTag ( CIFTAG_DETAILS ); 1186 } 1187 1188 Loop->AddString ( hetID ,true ); 1189 Loop->AddString ( chain->chainID,true ); 1190 Loop->AddInteger ( seqNum ); 1191 Loop->AddString ( insCode ,true ); 1192 Loop->AddInteger ( numHetAtoms ); 1193 Loop->AddString ( comment ,true ); 1194 1195 } 1196 GetCIF(mmcif::PData CIF,int & n)1197 ERROR_CODE HetRec::GetCIF ( mmcif::PData CIF, int & n ) { 1198 // GetCIF(..) must be always run without reference to Chain, 1199 // see CModel::GetCIF(..). 1200 mmcif::PLoop Loop; 1201 pstr F; 1202 int RC; 1203 ERROR_CODE rc; 1204 1205 Loop = CIF->GetLoop ( CIFCAT_NDB_NONSTANDARD_LIST ); 1206 if (!Loop) { 1207 n = -1; 1208 return Error_EmptyCIF; 1209 } 1210 1211 if (n>=Loop->GetLoopLength()) { 1212 n = -1; 1213 return Error_EmptyCIF; 1214 } 1215 1216 // Determine the ChainID first and store it locally. It will 1217 // be used by CModel for generating chains and placing the 1218 // primary structure data BEFORE reading the coordinate section. 1219 F = Loop->GetString ( CIFTAG_AUTH_ASYM_ID,n,RC ); 1220 if ((!RC) && F) { 1221 strcpy_n0 ( chainID,F,sizeof(ChainID)-1 ); 1222 Loop->DeleteField ( CIFTAG_AUTH_ASYM_ID,n ); 1223 } else 1224 strcpy ( chainID,"" ); 1225 1226 1227 CIFGetString ( hetID,Loop,CIFTAG_ID,n,sizeof(ResName), 1228 pstr("UNK") ); 1229 1230 rc = CIFGetInteger ( seqNum,Loop,CIFTAG_AUTH_SEQ_ID,n ); 1231 if (rc==Error_NoData) return Error_EmptyCIF; 1232 if (rc!=Error_NoError) return rc; 1233 1234 CIFGetString ( insCode,Loop,CIFTAG_INS_CODE,n,sizeof(InsCode), 1235 pstr(" ") ); 1236 1237 rc = CIFGetInteger ( numHetAtoms,Loop,CIFTAG_NUMBER_ATOMS_NH,n ); 1238 if (rc==Error_NoData) return Error_EmptyCIF; 1239 if (rc!=Error_NoError) return rc; 1240 1241 F = Loop->GetString ( CIFTAG_DETAILS,n,RC ); 1242 if ((!RC) && F) { 1243 CreateCopy ( comment,F ); 1244 Loop->DeleteField ( CIFTAG_DETAILS,n ); 1245 } else 1246 CreateCopy ( comment,pstr(" ") ); 1247 1248 n++; 1249 1250 return Error_NoError; 1251 1252 } 1253 Copy(PContainerClass Het)1254 void HetRec::Copy ( PContainerClass Het ) { 1255 seqNum = PHetRec(Het)->seqNum; 1256 numHetAtoms = PHetRec(Het)->numHetAtoms; 1257 strcpy ( hetID ,PHetRec(Het)->hetID ); 1258 strcpy ( insCode,PHetRec(Het)->insCode ); 1259 CreateCopy ( comment,PHetRec(Het)->comment ); 1260 } 1261 write(io::RFile f)1262 void HetRec::write ( io::RFile f ) { 1263 byte Version=1; 1264 f.WriteByte ( &Version ); 1265 f.WriteInt ( &seqNum ); 1266 f.WriteInt ( &numHetAtoms ); 1267 f.WriteTerLine ( hetID ,false ); 1268 f.WriteTerLine ( insCode,false ); 1269 f.CreateWrite ( comment ); 1270 } 1271 read(io::RFile f)1272 void HetRec::read ( io::RFile f ) { 1273 byte Version; 1274 f.ReadByte ( &Version ); 1275 f.ReadInt ( &seqNum ); 1276 f.ReadInt ( &numHetAtoms ); 1277 f.ReadTerLine ( hetID ,false ); 1278 f.ReadTerLine ( insCode,false ); 1279 f.CreateRead ( comment ); 1280 } 1281 MakeStreamFunctions(HetRec)1282 MakeStreamFunctions(HetRec) 1283 1284 1285 1286 // ===================== Chain ======================= 1287 1288 Chain::Chain() : UDData() { 1289 InitChain(); 1290 SetChain ( pstr("") ); 1291 } 1292 Chain(PProModel Model,const ChainID chID)1293 Chain::Chain ( PProModel Model, const ChainID chID ) : UDData() { 1294 InitChain(); 1295 SetChain ( chID ); 1296 if (Model) Model->AddChain ( this ); 1297 } 1298 Chain(io::RPStream Object)1299 Chain::Chain ( io::RPStream Object ) : UDData(Object) { 1300 InitChain(); 1301 SetChain ( pstr("") ); 1302 } 1303 InitChain()1304 void Chain::InitChain() { 1305 nResidues = 0; 1306 resLen = 0; 1307 residue = NULL; 1308 model = NULL; 1309 chainID[0] = char(0); 1310 prevChainID[0] = char(0); 1311 nWeights = 0; 1312 Weight = 0.0; 1313 Exclude = true; 1314 } 1315 SetChain(const ChainID chID)1316 void Chain::SetChain ( const ChainID chID ) { 1317 strcpy ( chainID,chID ); 1318 if (chID[0]==' ') chainID[0] = char(0); 1319 DBRef .SetChain ( this ); 1320 seqAdv.SetChain ( this ); 1321 seqRes.SetChain ( this ); 1322 modRes.SetChain ( this ); 1323 Het .SetChain ( this ); 1324 } 1325 SetChainID(const ChainID chID)1326 void Chain::SetChainID ( const ChainID chID ) { 1327 strcpy ( chainID,chID ); 1328 if (chID[0]==' ') chainID[0] = char(0); 1329 } 1330 ~Chain()1331 Chain::~Chain() { 1332 FreeMemory(); 1333 if (model) model->_ExcludeChain ( chainID ); 1334 } 1335 FreeMemory()1336 void Chain::FreeMemory() { 1337 DeleteAllResidues(); 1338 if (residue) delete[] residue; 1339 resLen = 0; 1340 nResidues = 0; 1341 residue = NULL; 1342 FreeAnnotations(); 1343 } 1344 FreeAnnotations()1345 void Chain::FreeAnnotations() { 1346 DBRef .FreeContainer(); 1347 seqAdv.FreeContainer(); 1348 seqRes.FreeMemory (); 1349 modRes.FreeContainer(); 1350 Het .FreeContainer(); 1351 } 1352 SetModel(PProModel Model)1353 void Chain::SetModel ( PProModel Model ) { 1354 model = Model; 1355 } 1356 GetCoordHierarchy()1357 PManager Chain::GetCoordHierarchy() { 1358 if (model) return model->GetCoordHierarchy(); 1359 return NULL; 1360 } 1361 CheckInAtoms()1362 void Chain::CheckInAtoms() { 1363 int i; 1364 if (GetCoordHierarchy()) 1365 for (i=0;i<nResidues;i++) 1366 if (residue[i]) 1367 residue[i]->CheckInAtoms(); 1368 } 1369 ConvertDBREF(cpstr PDBString)1370 ERROR_CODE Chain::ConvertDBREF ( cpstr PDBString ) { 1371 PContainerChain ContainerChain; 1372 ERROR_CODE RC; 1373 ContainerChain = new DBReference(this); 1374 RC = ContainerChain->ConvertPDBASCII ( PDBString ); 1375 if (RC) { 1376 delete ContainerChain; 1377 return RC; 1378 } 1379 DBRef.AddData ( ContainerChain ); 1380 return Error_NoError; 1381 } 1382 ConvertSEQADV(cpstr PDBString)1383 ERROR_CODE Chain::ConvertSEQADV ( cpstr PDBString ) { 1384 PContainerChain ContainerChain; 1385 ERROR_CODE RC; 1386 ContainerChain = new SeqAdv(this); 1387 RC = ContainerChain->ConvertPDBASCII ( PDBString ); 1388 if (RC) { 1389 delete ContainerChain; 1390 return RC; 1391 } 1392 seqAdv.AddData ( ContainerChain ); 1393 return Error_NoError; 1394 } 1395 ConvertSEQRES(cpstr PDBString)1396 ERROR_CODE Chain::ConvertSEQRES ( cpstr PDBString ) { 1397 return seqRes.ConvertPDBASCII ( PDBString ); 1398 } 1399 ConvertMODRES(cpstr PDBString)1400 ERROR_CODE Chain::ConvertMODRES ( cpstr PDBString ) { 1401 PContainerChain ContainerChain; 1402 ERROR_CODE RC; 1403 ContainerChain = new ModRes(this); 1404 RC = ContainerChain->ConvertPDBASCII ( PDBString ); 1405 if (RC) { 1406 delete ContainerChain; 1407 return RC; 1408 } 1409 modRes.AddData ( ContainerChain ); 1410 return Error_NoError; 1411 } 1412 ConvertHET(cpstr PDBString)1413 ERROR_CODE Chain::ConvertHET ( cpstr PDBString ) { 1414 PContainerChain ContainerChain; 1415 ERROR_CODE RC; 1416 ContainerChain = new HetRec(this); 1417 RC = ContainerChain->ConvertPDBASCII ( PDBString ); 1418 if (RC) { 1419 delete ContainerChain; 1420 return RC; 1421 } 1422 Het.AddData ( ContainerChain ); 1423 return Error_NoError; 1424 } 1425 1426 PDBASCIIDump(io::RFile f)1427 void Chain::PDBASCIIDump ( io::RFile f ) { 1428 // this function was for test purposes and is not used 1429 // for normal function of MMDB 1430 DBRef .PDBASCIIDump ( f ); 1431 seqAdv.PDBASCIIDump ( f ); 1432 seqRes.PDBASCIIDump ( f ); 1433 modRes.PDBASCIIDump ( f ); 1434 Het .PDBASCIIDump ( f ); 1435 } 1436 PDBASCIIAtomDump(io::RFile f)1437 void Chain::PDBASCIIAtomDump ( io::RFile f ) { 1438 int i; 1439 for (i=0;i<nResidues;i++) 1440 if (residue[i]) 1441 residue[i]->PDBASCIIAtomDump ( f ); 1442 } 1443 MakeAtomCIF(mmcif::PData CIF)1444 void Chain::MakeAtomCIF ( mmcif::PData CIF ) { 1445 int i; 1446 for (i=0;i<nResidues;i++) 1447 if (residue[i]) 1448 residue[i]->MakeAtomCIF ( CIF ); 1449 } 1450 1451 GetNumberOfResidues()1452 int Chain::GetNumberOfResidues() { 1453 return nResidues; 1454 } 1455 GetResidue(int resNo)1456 PResidue Chain::GetResidue ( int resNo ) { 1457 if ((0<=resNo) && (resNo<nResidues)) 1458 return residue[resNo]; 1459 else return NULL; 1460 } 1461 1462 GetResidueCreate(const ResName resName,int seqNum,const InsCode insCode,bool Enforce)1463 PResidue Chain::GetResidueCreate ( const ResName resName, 1464 int seqNum, 1465 const InsCode insCode, 1466 bool Enforce ) { 1467 // Returns pointer on residue, whose name, sequence number and 1468 // insert code are given in resName, seqNum and insCode, respectively. 1469 // If such a residue is absent in the chain, one is created at 1470 // the end of the chain. 1471 int i; 1472 1473 // check if such a residue is already in the chain 1474 if (insCode[0]) { 1475 for (i=0;i<nResidues;i++) 1476 if (residue[i]) { 1477 if ((seqNum==residue[i]->seqNum) && 1478 (!strcmp(insCode,residue[i]->insCode))) { 1479 if (!strcmp(resName,residue[i]->name)) 1480 return residue[i]; // it is there; just return the pointer 1481 else if (!Enforce) { 1482 // printf ( "1. sno=%i:%i, ic=[%s]:[%s] name=[%s]:[%s]\n", 1483 // seqNum,residue[i]->seqNum, 1484 // insCode,residue[i]->insCode, 1485 // resName,residue[i]->name ); 1486 return NULL; // duplicate seqNum and insCode! 1487 } 1488 } 1489 } 1490 } else { 1491 for (i=0;i<nResidues;i++) 1492 if (residue[i]) { 1493 if ((seqNum==residue[i]->seqNum) && 1494 (!residue[i]->insCode[0])) { 1495 if (!strcmp(resName,residue[i]->name)) 1496 return residue[i]; // it is there; just return the pointer 1497 else if (!Enforce) { 1498 // printf ( "2. sno=%i:%i, ic=[%s]:[%s] name=[%s]:[%s]\n", 1499 // seqNum,residue[i]->seqNum, 1500 // insCode,residue[i]->insCode, 1501 // resName,residue[i]->name ); 1502 return NULL; // duplicate seqNum and insCode! 1503 } 1504 } 1505 } 1506 } 1507 1508 // expand the residue array, if necessary 1509 if (nResidues>=resLen) 1510 ExpandResidueArray ( 100 ); 1511 1512 // create new residue 1513 residue[nResidues] = newResidue(); 1514 residue[nResidues]->SetChain ( this ); 1515 residue[nResidues]->SetResID ( resName,seqNum,insCode ); 1516 residue[nResidues]->index = nResidues; 1517 nResidues++; 1518 1519 return residue[nResidues-1]; 1520 1521 } 1522 ExpandResidueArray(int inc)1523 void Chain::ExpandResidueArray ( int inc ) { 1524 PPResidue Residue1; 1525 int i; 1526 resLen += inc; 1527 Residue1 = new PResidue[resLen]; 1528 for (i=0;i<nResidues;i++) 1529 Residue1[i] = residue[i]; 1530 if (residue) delete[] residue; 1531 residue = Residue1; 1532 for (i=nResidues;i<resLen;i++) 1533 residue[i] = NULL; 1534 } 1535 GetResidue(int seqNum,const InsCode insCode)1536 PResidue Chain::GetResidue ( int seqNum, const InsCode insCode ) { 1537 // Returns pointer on residue, whose sequence number and 1538 // insert code are given in seqNum and insCode, respectively. 1539 // If such a residue is absent in the chain, returns NULL. 1540 int i; 1541 bool isInsCode; 1542 if (insCode) isInsCode = insCode[0]!=char(0); 1543 else isInsCode = false; 1544 if (isInsCode) { 1545 for (i=0;i<nResidues;i++) 1546 if (residue[i]) { 1547 if ((seqNum==residue[i]->seqNum) && 1548 (!strcmp(insCode,residue[i]->insCode))) 1549 return residue[i]; 1550 } 1551 } else { 1552 for (i=0;i<nResidues;i++) 1553 if (residue[i]) { 1554 if ((seqNum==residue[i]->seqNum) && (!residue[i]->insCode[0])) 1555 return residue[i]; 1556 } 1557 } 1558 return NULL; 1559 } 1560 GetResidueNo(int seqNum,const InsCode insCode)1561 int Chain::GetResidueNo ( int seqNum, const InsCode insCode ) { 1562 // GetResidueNo(..) returns the residue number in the chain's 1563 // residues table. Residues are numbered as 0..nres-1 as they appear 1564 // in the coordinate file. 1565 // If residue is not found, the function returns -1. 1566 int i; 1567 bool isInsCode; 1568 if (insCode) isInsCode = insCode[0]!=char(0); 1569 else isInsCode = false; 1570 if (isInsCode) { 1571 for (i=0;i<nResidues;i++) 1572 if (residue[i]) { 1573 if ((seqNum==residue[i]->seqNum) && 1574 (!strcmp(insCode,residue[i]->insCode))) 1575 return i; 1576 } 1577 } else { 1578 for (i=0;i<nResidues;i++) 1579 if (residue[i]) { 1580 if ((seqNum==residue[i]->seqNum) && (!residue[i]->insCode[0])) 1581 return i; 1582 } 1583 } 1584 return -1; 1585 } 1586 GetResidueTable(PPResidue & resTable,int & NumberOfResidues)1587 void Chain::GetResidueTable ( PPResidue & resTable, 1588 int & NumberOfResidues ) { 1589 resTable = residue; 1590 NumberOfResidues = nResidues; 1591 } 1592 _ExcludeResidue(const ResName resName,int seqNum,const InsCode insCode)1593 int Chain::_ExcludeResidue ( const ResName resName, int seqNum, 1594 const InsCode insCode ) { 1595 // ExcludeResidue(..) excludes (but does not dispose!) a residue 1596 // from the chain. Returns 1 if the chain gets empty and 0 otherwise. 1597 int i,k; 1598 1599 if (!Exclude) return 0; 1600 1601 // find the residue 1602 k = -1; 1603 for (i=0;(i<nResidues) && (k<0);i++) 1604 if ((seqNum==residue[i]->seqNum) && 1605 (!strcmp(insCode,residue[i]->insCode)) && 1606 (!strcmp(resName,residue[i]->name))) 1607 k = i; 1608 1609 if (k>=0) { 1610 for (i=k+1;i<nResidues;i++) { 1611 residue[i-1] = residue[i]; 1612 if (residue[i-1]) 1613 residue[i-1]->index = i-1; 1614 } 1615 nResidues--; 1616 residue[nResidues] = NULL; 1617 } 1618 1619 if (nResidues<=0) return 1; 1620 else return 0; 1621 1622 } 1623 1624 GetCoordSequence(pstr & seq)1625 void Chain::GetCoordSequence ( pstr & seq ) { 1626 // GetCoorSequence(...) returns sequence inferred from list 1627 // of residues (which may differ from one in the file header). 1628 // The sequence is returned as a null-terminated string 'seq'. 1629 // On input, 'seq' should be either NULL or allocated (in which 1630 // case the original allocation will be released). 1631 int i,j; 1632 1633 if (seq) delete[] seq; 1634 seq = new char[nResidues+1]; 1635 1636 j = 0; 1637 for (i=0;i<nResidues;i++) 1638 if (residue[i]) 1639 Get1LetterCode ( residue[i]->GetResName(),seq[j++] ); 1640 seq[j] = char(0); 1641 1642 } 1643 1644 1645 // ------------------ Deleting residues -------------------------- 1646 DeleteResidue(int resNo)1647 int Chain::DeleteResidue ( int resNo ) { 1648 if ((0<=resNo) && (resNo<nResidues)) { 1649 if (residue[resNo]) { 1650 Exclude = false; 1651 delete residue[resNo]; 1652 residue[resNo] = NULL; 1653 Exclude = true; 1654 return 1; 1655 } 1656 } 1657 return 0; 1658 } 1659 DeleteResidue(int seqNum,const InsCode insCode)1660 int Chain::DeleteResidue ( int seqNum, const InsCode insCode ) { 1661 int i; 1662 if (insCode[0]) { 1663 for (i=0;i<nResidues;i++) 1664 if (residue[i]) { 1665 if ((seqNum==residue[i]->seqNum) && 1666 (!strcmp(insCode,residue[i]->insCode))) { 1667 Exclude = false; 1668 delete residue[i]; 1669 residue[i] = NULL; 1670 Exclude = true; 1671 return 1; 1672 } 1673 } 1674 } else { 1675 for (i=0;i<nResidues;i++) 1676 if (residue[i]) { 1677 if ((seqNum==residue[i]->seqNum) && (!residue[i]->insCode[0])) { 1678 Exclude = false; 1679 delete residue[i]; 1680 residue[i] = NULL; 1681 Exclude = true; 1682 return 1; 1683 } 1684 } 1685 } 1686 return 0; 1687 } 1688 1689 DeleteAllResidues()1690 int Chain::DeleteAllResidues() { 1691 int i,k; 1692 Exclude = false; 1693 k = 0; 1694 for (i=0;i<nResidues;i++) 1695 if (residue[i]) { 1696 delete residue[i]; 1697 residue[i] = NULL; 1698 k++; 1699 } 1700 nResidues = 0; 1701 Exclude = true; 1702 return k; 1703 } 1704 1705 DeleteSolvent()1706 int Chain::DeleteSolvent() { 1707 int i,k; 1708 Exclude = false; 1709 k = 0; 1710 for (i=0;i<nResidues;i++) 1711 if (residue[i]) { 1712 if (residue[i]->isSolvent()) { 1713 delete residue[i]; 1714 residue[i] = NULL; 1715 k++; 1716 } 1717 } 1718 Exclude = true; 1719 return k; 1720 } 1721 1722 TrimResidueTable()1723 void Chain::TrimResidueTable() { 1724 int i,j; 1725 Exclude = false; 1726 j = 0; 1727 for (i=0;i<nResidues;i++) 1728 if (residue[i]) { 1729 if (residue[i]->nAtoms>0) { 1730 if (j<i) { 1731 residue[j] = residue[i]; 1732 residue[j]->index = j; 1733 residue[i] = NULL; 1734 } 1735 j++; 1736 } else { 1737 delete residue[i]; 1738 residue[i] = NULL; 1739 } 1740 } 1741 nResidues = j; 1742 Exclude = true; 1743 } 1744 AddResidue(PResidue res)1745 int Chain::AddResidue ( PResidue res ) { 1746 // modify both CModel::Copy methods simultaneously! 1747 // 1748 // Copy(PCModel,PPAtom,int&) copies atoms into array 'atom' 1749 // starting from position atom_index. 'atom' should be able to 1750 // accept all new atoms - no checks on the length of 'atom' 1751 // is being made. This function should not be used in applications. 1752 return InsResidue ( res,nResidues ); 1753 } 1754 1755 /* 1756 PCmmdbRoot mmdbRoot; 1757 PChain chain1; 1758 int i; 1759 1760 for (i=0;i<nResidues;i++) 1761 if (residue[i]==res) return -i; // this residue is already there 1762 1763 if (res) { 1764 1765 mmdbRoot = PCmmdbRoot(GetCoordHierarchy()); 1766 1767 // get space for new residue 1768 if (nResidues>=resLen) 1769 ExpandResidueArray ( 100 ); 1770 1771 if (res->GetCoordHierarchy()) { 1772 residue[nResidues] = newResidue(); 1773 residue[nResidues]->SetChain ( this ); 1774 residue[nResidues]->SetResID ( res->name,res->seqNum,res->insCode ); 1775 if (mmdbRoot) { 1776 // get space for new atoms 1777 mmdbRoot->AddAtomArray ( res->GetNumberOfAtoms(true) ); 1778 residue[nResidues]->Copy ( res,mmdbRoot->Atom,mmdbRoot->nAtoms ); 1779 } else { 1780 for (i=0;i<res->nAtoms;i++) 1781 residue[nResidues]->AddAtom ( res->atom[i] ); 1782 } 1783 } else { 1784 residue[nResidues] = res; 1785 chain1 = res->GetChain(); 1786 if (chain1) 1787 for (i=0;i<chain1->nResidues;i++) 1788 if (chain1->residue[i]==res) { 1789 chain1->residue[i] = NULL; 1790 break; 1791 } 1792 residue[nResidues]->SetChain ( this ); 1793 if (mmdbRoot) 1794 residue[nResidues]->CheckInAtoms(); 1795 } 1796 nResidues++; 1797 1798 } 1799 1800 return nResidues; 1801 1802 } 1803 */ 1804 InsResidue(PResidue res,int seqNum,const InsCode insCode)1805 int Chain::InsResidue ( PResidue res, int seqNum, 1806 const InsCode insCode ) { 1807 return InsResidue ( res,GetResidueNo(seqNum,insCode) ); 1808 } 1809 InsResidue(PResidue res,int pos)1810 int Chain::InsResidue ( PResidue res, int pos ) { 1811 // Inserts residue res onto position pos of the chain, 1812 // pos=0..nResidues-1 . Residues pos..nResidues-1 are 1813 // shifted up the chain. 1814 // The function places new atoms on the top of atom 1815 // index. It is advisable to call 1816 // CmmdbRoot::PDBCleanup ( PDBCLEAN_INDEX ) after all 1817 // insertions are done. 1818 PRoot mmdbRoot; 1819 PChain chain1; 1820 int i,pp; 1821 1822 pp = IMax ( 0,IMin(nResidues,pos) ); 1823 1824 for (i=0;i<nResidues;i++) 1825 if (residue[i]==res) return -i; // this residue is already there 1826 1827 if (res) { 1828 1829 mmdbRoot = PRoot(GetCoordHierarchy()); 1830 1831 // get space for new residue 1832 if (nResidues>=resLen) 1833 ExpandResidueArray ( 100 ); 1834 1835 // shift residues to the end of the chain as necessary 1836 for (i=nResidues;i>pp;i--) 1837 residue[i] = residue[i-1]; 1838 1839 // insert the new residue 1840 if (res->GetCoordHierarchy()) { 1841 residue[pp] = newResidue(); 1842 residue[pp]->SetChain ( this ); 1843 residue[pp]->SetResID ( res->name,res->seqNum,res->insCode ); 1844 if (mmdbRoot) { 1845 // get space for new atoms 1846 mmdbRoot->AddAtomArray ( res->GetNumberOfAtoms(true) ); 1847 residue[pp]->_copy ( res,mmdbRoot->atom,mmdbRoot->nAtoms ); 1848 } else { 1849 for (i=0;i<res->nAtoms;i++) 1850 residue[pp]->AddAtom ( res->atom[i] ); 1851 } 1852 } else { 1853 residue[pp] = res; 1854 chain1 = res->GetChain(); 1855 if (chain1) 1856 for (i=0;i<chain1->nResidues;i++) 1857 if (chain1->residue[i]==res) { 1858 chain1->residue[i] = NULL; 1859 break; 1860 } 1861 residue[pp]->SetChain ( this ); 1862 if (mmdbRoot) 1863 residue[pp]->CheckInAtoms(); 1864 } 1865 nResidues++; 1866 1867 } 1868 1869 return nResidues; 1870 1871 } 1872 1873 1874 // -------------------- Extracting atoms ----------------------- 1875 GetNumberOfAtoms(bool countTers)1876 int Chain::GetNumberOfAtoms ( bool countTers ) { 1877 int i,na; 1878 na = 0; 1879 for (i=0;i<nResidues;i++) 1880 if (residue[i]) na += residue[i]->GetNumberOfAtoms ( countTers ); 1881 return na; 1882 } 1883 GetNumberOfAtoms(int seqNo,const InsCode insCode)1884 int Chain::GetNumberOfAtoms ( int seqNo, const InsCode insCode ) { 1885 PResidue res; 1886 res = GetResidue ( seqNo,insCode ); 1887 if (res) return res->nAtoms; 1888 return 0; 1889 } 1890 GetNumberOfAtoms(int resNo)1891 int Chain::GetNumberOfAtoms ( int resNo ) { 1892 if ((0<=resNo) && (resNo<nResidues)) { 1893 if (residue[resNo]) return residue[resNo]->nAtoms; 1894 } 1895 return 0; 1896 } 1897 GetAtom(int seqNo,const InsCode insCode,const AtomName aname,const Element elmnt,const AltLoc aloc)1898 PAtom Chain::GetAtom ( int seqNo, 1899 const InsCode insCode, 1900 const AtomName aname, 1901 const Element elmnt, 1902 const AltLoc aloc ) { 1903 PResidue res; 1904 res = GetResidue ( seqNo,insCode ); 1905 if (res) return res->GetAtom ( aname,elmnt,aloc ); 1906 return NULL; 1907 } 1908 GetAtom(int seqNo,const InsCode insCode,int atomNo)1909 PAtom Chain::GetAtom ( int seqNo, const InsCode insCode, 1910 int atomNo ) { 1911 PResidue res; 1912 res = GetResidue ( seqNo,insCode ); 1913 if (res) { 1914 if ((0<=atomNo) && (atomNo<res->nAtoms)) 1915 return res->atom[atomNo]; 1916 } 1917 return NULL; 1918 } 1919 GetAtom(int resNo,const AtomName aname,const Element elmnt,const AltLoc aloc)1920 PAtom Chain::GetAtom ( int resNo, 1921 const AtomName aname, 1922 const Element elmnt, 1923 const AltLoc aloc ) { 1924 if ((0<=resNo) && (resNo<nResidues)) { 1925 if (residue[resNo]) 1926 return residue[resNo]->GetAtom ( aname,elmnt,aloc ); 1927 } 1928 return NULL; 1929 } 1930 GetAtom(int resNo,int atomNo)1931 PAtom Chain::GetAtom ( int resNo, int atomNo ) { 1932 PResidue res; 1933 if ((0<=resNo) && (resNo<nResidues)) { 1934 res = residue[resNo]; 1935 if (res) { 1936 if ((0<=atomNo) && (atomNo<res->nAtoms)) 1937 return res->atom[atomNo]; 1938 } 1939 } 1940 return NULL; 1941 } 1942 GetAtomTable(int seqNo,const InsCode insCode,PPAtom & atomTable,int & NumberOfAtoms)1943 void Chain::GetAtomTable ( int seqNo, const InsCode insCode, 1944 PPAtom & atomTable, int & NumberOfAtoms ) { 1945 PResidue res; 1946 atomTable = NULL; 1947 NumberOfAtoms = 0; 1948 res = GetResidue ( seqNo,insCode ); 1949 if (res) { 1950 atomTable = res->atom; 1951 NumberOfAtoms = res->nAtoms; 1952 } 1953 } 1954 GetAtomTable(int resNo,PPAtom & atomTable,int & NumberOfAtoms)1955 void Chain::GetAtomTable ( int resNo, PPAtom & atomTable, 1956 int & NumberOfAtoms ) { 1957 PResidue res; 1958 atomTable = NULL; 1959 NumberOfAtoms = 0; 1960 if ((0<=resNo) && (resNo<nResidues)) { 1961 res = residue[resNo]; 1962 if (res) { 1963 atomTable = res->atom; 1964 NumberOfAtoms = res->nAtoms; 1965 } 1966 } 1967 } 1968 1969 GetAtomTable1(int seqNo,const InsCode insCode,PPAtom & atomTable,int & NumberOfAtoms)1970 void Chain::GetAtomTable1 ( int seqNo, const InsCode insCode, 1971 PPAtom & atomTable, int & NumberOfAtoms ) { 1972 PResidue res; 1973 res = GetResidue ( seqNo,insCode ); 1974 if (res) 1975 res->GetAtomTable1 ( atomTable,NumberOfAtoms ); 1976 else { 1977 if (atomTable) delete[] atomTable; 1978 atomTable = NULL; 1979 NumberOfAtoms = 0; 1980 } 1981 } 1982 GetAtomTable1(int resNo,PPAtom & atomTable,int & NumberOfAtoms)1983 void Chain::GetAtomTable1 ( int resNo, PPAtom & atomTable, 1984 int & NumberOfAtoms ) { 1985 PResidue res; 1986 if ((0<=resNo) && (resNo<nResidues)) 1987 res = residue[resNo]; 1988 else res = NULL; 1989 if (res) 1990 res->GetAtomTable1 ( atomTable,NumberOfAtoms ); 1991 else { 1992 if (atomTable) delete[] atomTable; 1993 atomTable = NULL; 1994 NumberOfAtoms = 0; 1995 } 1996 } 1997 DeleteAtom(int seqNo,const InsCode insCode,const AtomName aname,const Element elmnt,const AltLoc aloc)1998 int Chain::DeleteAtom ( int seqNo, 1999 const InsCode insCode, 2000 const AtomName aname, 2001 const Element elmnt, 2002 const AltLoc aloc ) { 2003 PResidue res; 2004 res = GetResidue ( seqNo,insCode ); 2005 if (res) return res->DeleteAtom ( aname,elmnt,aloc ); 2006 return 0; 2007 } 2008 DeleteAtom(int seqNo,const InsCode insCode,int atomNo)2009 int Chain::DeleteAtom ( int seqNo, const InsCode insCode, 2010 int atomNo ) { 2011 PResidue res; 2012 res = GetResidue ( seqNo,insCode ); 2013 if (res) return res->DeleteAtom ( atomNo ); 2014 return 0; 2015 } 2016 DeleteAtom(int resNo,const AtomName aname,const Element elmnt,const AltLoc aloc)2017 int Chain::DeleteAtom ( int resNo, 2018 const AtomName aname, 2019 const Element elmnt, 2020 const AltLoc aloc ) { 2021 if ((0<=resNo) && (resNo<nResidues)) { 2022 if (residue[resNo]) 2023 return residue[resNo]->DeleteAtom ( aname,elmnt,aloc ); 2024 } 2025 return 0; 2026 } 2027 DeleteAtom(int resNo,int atomNo)2028 int Chain::DeleteAtom ( int resNo, int atomNo ) { 2029 if ((0<=resNo) && (resNo<nResidues)) { 2030 if (residue[resNo]) 2031 return residue[resNo]->DeleteAtom ( atomNo ); 2032 } 2033 return 0; 2034 } 2035 2036 DeleteAllAtoms(int seqNo,const InsCode insCode)2037 int Chain::DeleteAllAtoms ( int seqNo, const InsCode insCode ) { 2038 PResidue res; 2039 res = GetResidue ( seqNo,insCode ); 2040 if (res) return res->DeleteAllAtoms(); 2041 return 0; 2042 } 2043 DeleteAllAtoms(int resNo)2044 int Chain::DeleteAllAtoms ( int resNo ) { 2045 if ((0<=resNo) && (resNo<nResidues)) { 2046 if (residue[resNo]) 2047 return residue[resNo]->DeleteAllAtoms(); 2048 } 2049 return 0; 2050 } 2051 DeleteAllAtoms()2052 int Chain::DeleteAllAtoms() { 2053 int i,k; 2054 k = 0; 2055 for (i=0;i<nResidues;i++) 2056 if (residue[i]) 2057 k += residue[i]->DeleteAllAtoms(); 2058 return k; 2059 } 2060 DeleteAltLocs()2061 int Chain::DeleteAltLocs() { 2062 // This function leaves only alternative location with maximal 2063 // occupancy, if those are equal or unspecified, the one with 2064 // "least" alternative location indicator. 2065 // The function returns the number of deleted. All tables remain 2066 // untrimmed, so that explicit trimming or calling FinishStructEdit() 2067 // is required. 2068 int i,n; 2069 2070 n = 0; 2071 for (i=0;i<nResidues;i++) 2072 if (residue[i]) n += residue[i]->DeleteAltLocs(); 2073 2074 return n; 2075 2076 } 2077 2078 AddAtom(int seqNo,const InsCode insCode,PAtom atom)2079 int Chain::AddAtom ( int seqNo, const InsCode insCode, 2080 PAtom atom ) { 2081 PResidue res; 2082 res = GetResidue ( seqNo,insCode ); 2083 if (res) return res->AddAtom ( atom ); 2084 return 0; 2085 } 2086 AddAtom(int resNo,PAtom atom)2087 int Chain::AddAtom ( int resNo, PAtom atom ) { 2088 if ((0<=resNo) && (resNo<nResidues)) { 2089 if (residue[resNo]) 2090 return residue[resNo]->AddAtom ( atom ); 2091 } 2092 return 0; 2093 } 2094 2095 Copy(PChain chain)2096 void Chain::Copy ( PChain chain ) { 2097 // modify both Chain::_copy and Chain::Copy methods simultaneously! 2098 int i; 2099 2100 FreeMemory(); 2101 2102 if (chain) { 2103 2104 CopyAnnotations ( chain ); 2105 2106 nResidues = chain->nResidues; 2107 resLen = nResidues; 2108 if (nResidues>0) { 2109 residue = new PResidue[nResidues]; 2110 for (i=0;i<nResidues;i++) { 2111 residue[i] = newResidue(); 2112 residue[i]->SetChain ( this ); 2113 residue[i]->Copy ( chain->residue[i] ); 2114 } 2115 } 2116 2117 } 2118 2119 } 2120 CopyAnnotations(PChain chain)2121 void Chain::CopyAnnotations ( PChain chain ) { 2122 if (chain) { 2123 strcpy ( chainID ,chain->chainID ); 2124 strcpy ( prevChainID,chain->prevChainID ); 2125 DBRef .Copy ( &(chain->DBRef) ); 2126 seqAdv.Copy ( &(chain->seqAdv) ); // SEQADV records 2127 seqRes.Copy ( &(chain->seqRes) ); // SEQRES data 2128 modRes.Copy ( &(chain->modRes) ); // MODRES records 2129 Het .Copy ( &(chain->Het) ); // HET records 2130 } 2131 } 2132 2133 _copy(PChain chain)2134 void Chain::_copy ( PChain chain ) { 2135 // modify both Chain::_copy and Chain::Copy methods simultaneously! 2136 int i; 2137 2138 FreeMemory(); 2139 2140 strcpy ( chainID ,chain->chainID ); 2141 strcpy ( prevChainID,chain->prevChainID ); 2142 2143 DBRef .Copy ( &(chain->DBRef) ); 2144 seqAdv.Copy ( &(chain->seqAdv) ); // SEQADV records 2145 seqRes.Copy ( &(chain->seqRes) ); // SEQRES data 2146 modRes.Copy ( &(chain->modRes) ); // MODRES records 2147 Het .Copy ( &(chain->Het) ); // HET records 2148 2149 nResidues = chain->nResidues; 2150 resLen = nResidues; 2151 if (nResidues>0) { 2152 residue = new PResidue[nResidues]; 2153 for (i=0;i<nResidues;i++) { 2154 residue[i] = newResidue(); 2155 residue[i]->SetChain ( this ); 2156 residue[i]->_copy ( chain->residue[i] ); 2157 } 2158 } 2159 2160 } 2161 _copy(PChain chain,PPAtom atom,int & atom_index)2162 void Chain::_copy ( PChain chain, PPAtom atom, int & atom_index ) { 2163 // modify both Chain::_copy and Chain::Copy methods simultaneously! 2164 int i; 2165 2166 FreeMemory(); 2167 2168 strcpy ( chainID ,chain->chainID ); 2169 strcpy ( prevChainID,chain->prevChainID ); 2170 2171 DBRef .Copy ( &(chain->DBRef) ); 2172 seqAdv.Copy ( &(chain->seqAdv) ); // SEQADV records 2173 seqRes.Copy ( &(chain->seqRes) ); // SEQRES data 2174 modRes.Copy ( &(chain->modRes) ); // MODRES records 2175 Het .Copy ( &(chain->Het) ); // HET records 2176 2177 nResidues = chain->nResidues; 2178 resLen = nResidues; 2179 if (nResidues>0) { 2180 residue = new PResidue[nResidues]; 2181 for (i=0;i<nResidues;i++) 2182 if (chain->residue[i]) { 2183 residue[i] = newResidue(); 2184 residue[i]->SetChain ( this ); 2185 residue[i]->_copy ( chain->residue[i],atom,atom_index ); 2186 } else 2187 residue[i] = NULL; 2188 } 2189 2190 } 2191 2192 /* 2193 void Chain::Duplicate ( PChain Chain ) { 2194 int i; 2195 2196 FreeMemory(); 2197 2198 strcpy ( chainID ,chain->chainID ); 2199 strcpy ( prevChainID,chain->prevChainID ); 2200 2201 DBReference.Copy ( &(chain->DBReference) ); 2202 SeqAdv .Copy ( &(chain->SeqAdv) ); // SEQADV records 2203 SeqRes .Copy ( &(chain->SeqRes) ); // SEQRES data 2204 ModRes .Copy ( &(chain->ModRes) ); // MODRES records 2205 Het .Copy ( &(chain->Het) ); // HET records 2206 2207 nResidues = chain->nResidues; 2208 resLen = nResidues; 2209 if (nResidues>0) { 2210 Residue = new PResidue[nResidues]; 2211 for (i=0;i<nResidues;i++) { 2212 residue[i] = newResidue(); 2213 residue[i]->SetChain ( this ); 2214 residue[i]->Duplicate ( chain->residue[i] ); 2215 } 2216 } 2217 2218 } 2219 */ 2220 GetEntryID()2221 cpstr Chain::GetEntryID() { 2222 if (model) return model->GetEntryID(); 2223 else return pstr(""); 2224 } 2225 SetEntryID(const IDCode idCode)2226 void Chain::SetEntryID ( const IDCode idCode ) { 2227 if (model) model->SetEntryID ( idCode ); 2228 } 2229 GetModelNum()2230 int Chain::GetModelNum() { 2231 if (model) return model->GetSerNum(); 2232 return 0; 2233 } 2234 GetChainID(pstr ChID)2235 cpstr Chain::GetChainID ( pstr ChID ) { 2236 ChID[0] = char(0); 2237 if (model) 2238 sprintf ( ChID,"/%i/",model->GetSerNum() ); 2239 else strcpy ( ChID,"/-/" ); 2240 strcat ( ChID,chainID ); 2241 return ChID; 2242 } 2243 2244 GetAtomStatistics(RAtomStat AS)2245 void Chain::GetAtomStatistics ( RAtomStat AS ) { 2246 AS.Init(); 2247 CalAtomStatistics ( AS ); 2248 AS.Finish(); 2249 } 2250 CalAtomStatistics(RAtomStat AS)2251 void Chain::CalAtomStatistics ( RAtomStat AS ) { 2252 int i; 2253 for (i=0;i<nResidues;i++) 2254 if (residue[i]) 2255 residue[i]->CalAtomStatistics ( AS ); 2256 } 2257 ApplyTransform(mat44 & TMatrix)2258 void Chain::ApplyTransform ( mat44 & TMatrix ) { 2259 // transforms all coordinates by multiplying with matrix TMatrix 2260 int i; 2261 for (i=0;i<nResidues;i++) 2262 if (residue[i]) residue[i]->ApplyTransform ( TMatrix ); 2263 } 2264 isSolventChain()2265 bool Chain::isSolventChain() { 2266 // returns true if chain contains only solvent molecules 2267 bool B,P; 2268 int i; 2269 B = true; 2270 P = false; 2271 for (i=0;(i<nResidues) && B;i++) 2272 if (residue[i]) { 2273 P = true; 2274 B = residue[i]->isSolvent(); 2275 } 2276 return (B && P); 2277 } 2278 isInSelection(int selHnd)2279 bool Chain::isInSelection ( int selHnd ) { 2280 PRoot mmdbRoot = (PRoot)GetCoordHierarchy(); 2281 PMask mask; 2282 if (mmdbRoot) { 2283 mask = mmdbRoot->GetSelMask ( selHnd ); 2284 if (mask) return CheckMask ( mask ); 2285 } 2286 return false; 2287 } 2288 isAminoacidChain()2289 bool Chain::isAminoacidChain() { 2290 // returns true if chain contains at least one aminoacid residue 2291 bool B,P; 2292 int i; 2293 B = false; 2294 P = false; 2295 for (i=0;(i<nResidues) && (!B);i++) 2296 if (residue[i]) { 2297 P = true; 2298 B = residue[i]->isAminoacid(); 2299 } 2300 return (B && P); 2301 } 2302 isNucleotideChain()2303 bool Chain::isNucleotideChain() { 2304 // returns true if chain contains at least one nucleotide residue 2305 bool B,P; 2306 int i; 2307 B = false; 2308 P = false; 2309 for (i=0;(i<nResidues) && (!B);i++) 2310 if (residue[i]) { 2311 P = true; 2312 B = residue[i]->isNucleotide(); 2313 } 2314 return (B && P); 2315 } 2316 CheckID(const ChainID chID)2317 int Chain::CheckID ( const ChainID chID ) { 2318 if (chID) { 2319 if (!strcmp(chID,chainID)) return 1; 2320 } 2321 return 0; 2322 } 2323 CheckIDS(cpstr CID)2324 int Chain::CheckIDS ( cpstr CID ) { 2325 ChainID chn; 2326 InsCode inscode; 2327 ResName resname; 2328 AtomName atm; 2329 Element elm; 2330 AltLoc aloc; 2331 int mdl,sn,rc; 2332 2333 rc = ParseAtomPath ( CID,mdl,chn,sn,inscode,resname, 2334 atm,elm,aloc,NULL ); 2335 if (rc>=0) { 2336 if (!strcmp(chn,chainID)) return 1; 2337 } 2338 return 0; 2339 2340 } 2341 GetNumberOfDBRefs()2342 int Chain::GetNumberOfDBRefs() { 2343 return DBRef.Length(); 2344 } 2345 GetDBRef(int dbRefNo)2346 PDBReference Chain::GetDBRef ( int dbRefNo ) { 2347 return (PDBReference)DBRef.GetContainerClass ( dbRefNo ); 2348 } 2349 2350 MaskAtoms(PMask mask)2351 void Chain::MaskAtoms ( PMask mask ) { 2352 int i; 2353 for (i=0;i<nResidues;i++) 2354 if (residue[i]) residue[i]->MaskAtoms ( mask ); 2355 } 2356 MaskResidues(PMask mask)2357 void Chain::MaskResidues ( PMask mask ) { 2358 int i; 2359 for (i=0;i<nResidues;i++) 2360 if (residue[i]) residue[i]->SetMask ( mask ); 2361 } 2362 UnmaskAtoms(PMask mask)2363 void Chain::UnmaskAtoms ( PMask mask ) { 2364 int i; 2365 for (i=0;i<nResidues;i++) 2366 if (residue[i]) residue[i]->UnmaskAtoms ( mask ); 2367 } 2368 UnmaskResidues(PMask mask)2369 void Chain::UnmaskResidues ( PMask mask ) { 2370 int i; 2371 for (i=0;i<nResidues;i++) 2372 if (residue[i]) residue[i]->RemoveMask ( mask ); 2373 } 2374 2375 2376 2377 2378 // ------- user-defined data handlers 2379 PutUDData(int UDDhandle,int iudd)2380 int Chain::PutUDData ( int UDDhandle, int iudd ) { 2381 if (UDDhandle & UDRF_CHAIN) 2382 return UDData::putUDData ( UDDhandle,iudd ); 2383 else return UDDATA_WrongUDRType; 2384 } 2385 PutUDData(int UDDhandle,realtype rudd)2386 int Chain::PutUDData ( int UDDhandle, realtype rudd ) { 2387 if (UDDhandle & UDRF_CHAIN) 2388 return UDData::putUDData ( UDDhandle,rudd ); 2389 else return UDDATA_WrongUDRType; 2390 } 2391 PutUDData(int UDDhandle,cpstr sudd)2392 int Chain::PutUDData ( int UDDhandle, cpstr sudd ) { 2393 if (UDDhandle & UDRF_CHAIN) 2394 return UDData::putUDData ( UDDhandle,sudd ); 2395 else return UDDATA_WrongUDRType; 2396 } 2397 GetUDData(int UDDhandle,int & iudd)2398 int Chain::GetUDData ( int UDDhandle, int & iudd ) { 2399 if (UDDhandle & UDRF_CHAIN) 2400 return UDData::getUDData ( UDDhandle,iudd ); 2401 else return UDDATA_WrongUDRType; 2402 } 2403 GetUDData(int UDDhandle,realtype & rudd)2404 int Chain::GetUDData ( int UDDhandle, realtype & rudd ) { 2405 if (UDDhandle & UDRF_CHAIN) 2406 return UDData::getUDData ( UDDhandle,rudd ); 2407 else return UDDATA_WrongUDRType; 2408 } 2409 GetUDData(int UDDhandle,pstr sudd,int maxLen)2410 int Chain::GetUDData ( int UDDhandle, pstr sudd, int maxLen ) { 2411 if (UDDhandle & UDRF_CHAIN) 2412 return UDData::getUDData ( UDDhandle,sudd,maxLen ); 2413 else return UDDATA_WrongUDRType; 2414 } 2415 GetUDData(int UDDhandle,pstr & sudd)2416 int Chain::GetUDData ( int UDDhandle, pstr & sudd ) { 2417 if (UDDhandle & UDRF_CHAIN) 2418 return UDData::getUDData ( UDDhandle,sudd ); 2419 else return UDDATA_WrongUDRType; 2420 } 2421 2422 2423 // ------------------------------------------------------------------- 2424 2425 DefineClass(SortResidues) 2426 2427 class QSortResidues : public QuickSort { 2428 public : QSortResidues()2429 QSortResidues() : QuickSort() {} 2430 int Compare ( int i, int j ); 2431 void Swap ( int i, int j ); 2432 void Sort ( PPResidue res, int nresidues ); 2433 }; 2434 Compare(int i,int j)2435 int QSortResidues::Compare ( int i, int j ) { 2436 int diff; 2437 diff = ((PPResidue)data)[i]->seqNum - ((PPResidue)data)[j]->seqNum; 2438 if (diff==0) 2439 diff = strcmp( (PPResidue(data))[i]->insCode, 2440 (PPResidue(data))[j]->insCode ); 2441 if (diff>0) return 1; 2442 if (diff<0) return -1; 2443 return 0; 2444 } 2445 Swap(int i,int j)2446 void QSortResidues::Swap ( int i, int j ) { 2447 PResidue res; 2448 res = ((PPResidue)data)[i]; 2449 ((PPResidue)data)[i] = ((PPResidue)data)[j]; 2450 ((PPResidue)data)[j] = res; 2451 } 2452 Sort(PPResidue res,int nresidues)2453 void QSortResidues::Sort ( PPResidue res, int nresidues ) { 2454 QuickSort::Sort ( &(res[0]),nresidues ); 2455 } 2456 SortResidues()2457 void Chain::SortResidues() { 2458 QSortResidues SR; 2459 TrimResidueTable(); 2460 SR.Sort ( residue,nResidues ); 2461 } 2462 GetNofModResidues()2463 int Chain::GetNofModResidues() { 2464 return modRes.Length(); 2465 } 2466 GetModResidue(int modResNo)2467 PModRes Chain::GetModResidue ( int modResNo ) { 2468 return PModRes(modRes.GetContainerClass(modResNo)); 2469 } 2470 write(io::RFile f)2471 void Chain::write ( io::RFile f ) { 2472 int i; 2473 byte Version=2; 2474 bool compactBinary = false; 2475 2476 PManager M = GetCoordHierarchy(); 2477 if (M) 2478 compactBinary = M->isCompactBinary(); 2479 2480 f.WriteByte ( &Version ); 2481 f.WriteBool ( &compactBinary ); 2482 f.WriteTerLine ( chainID,false ); 2483 2484 f.WriteInt ( &nResidues ); 2485 for (i=0;i<nResidues;i++) 2486 residue[i]->write ( f ); 2487 2488 if (!compactBinary) { 2489 2490 UDData::write ( f ); 2491 2492 f.WriteTerLine ( prevChainID,false ); 2493 2494 DBRef .write ( f ); // Database reference 2495 seqAdv.write ( f ); // SEQADV records 2496 seqRes.write ( f ); // SEQRES data 2497 modRes.write ( f ); // MODRES records 2498 Het .write ( f ); // HET records 2499 2500 } 2501 2502 } 2503 read(io::RFile f)2504 void Chain::read ( io::RFile f ) { 2505 // The Atom array in CmmdbRoot must be already read 2506 // prior to calling this function! 2507 int i; 2508 byte Version; 2509 bool compactBinary; 2510 2511 FreeMemory(); 2512 2513 f.ReadByte ( &Version ); 2514 f.ReadBool ( &compactBinary ); 2515 f.ReadTerLine ( chainID,false ); 2516 2517 SetChain ( chainID ); 2518 2519 f.ReadInt ( &nResidues ); 2520 resLen = nResidues; 2521 if (nResidues>0) { 2522 residue = new PResidue[nResidues]; 2523 for (i=0;i<nResidues;i++) { 2524 residue[i] = newResidue(); 2525 residue[i]->SetChain ( this ); 2526 residue[i]->read ( f ); 2527 } 2528 } 2529 2530 if (!compactBinary) { 2531 2532 UDData::read ( f ); 2533 2534 f.ReadTerLine ( prevChainID,false ); 2535 2536 DBRef .read ( f ); // Database reference 2537 seqAdv.read ( f ); // SEQADV records 2538 seqRes.read ( f ); // SEQRES data 2539 modRes.read ( f ); // MODRES records 2540 Het .read ( f ); // HET records 2541 2542 } 2543 2544 } 2545 2546 2547 MakeFactoryFunctions(Chain) 2548 2549 } // namespace mmdb 2550 2551 2552 // =================================================================== 2553 2554 /* 2555 void TestChain() { 2556 // reads from 'in.chain', writes into 2557 // 'out.chain' and 'abin.chain' 2558 CFile f; 2559 char S[81]; 2560 PChain Chain; 2561 2562 Chain = newChain(); 2563 2564 f.assign ( "in.chain",true ); 2565 if (f.reset()) { 2566 while (!f.FileEnd()) { 2567 f.ReadLine ( S,sizeof(S) ); 2568 chain->ConvertPDBString ( S ); 2569 } 2570 f.shut(); 2571 } else { 2572 printf ( " Can't open input file 'in.chain' \n" ); 2573 delete Chain; 2574 return; 2575 } 2576 2577 f.assign ( "out.chain",true ); 2578 if (f.rewrite()) { 2579 chain->PDBASCIIDump ( f ); 2580 f.shut(); 2581 } else { 2582 printf ( " Can't open output file 'out.chain' \n" ); 2583 delete Chain; 2584 return; 2585 } 2586 2587 2588 f.assign ( "mmdb.chain.bin",false ); 2589 if (f.rewrite()) { 2590 chain->write ( f ); 2591 f.shut(); 2592 } else { 2593 printf ( " Can't open binary chain file for writing.\n" ); 2594 delete Chain; 2595 return; 2596 } 2597 2598 delete Chain; 2599 printf ( " Chain deleted.\n" ); 2600 2601 Chain = newChain(); 2602 if (f.reset()) { 2603 chain->read ( f ); 2604 f.shut(); 2605 } else { 2606 printf ( " Can't open binary chain file for reading.\n" ); 2607 delete Chain; 2608 return; 2609 } 2610 2611 f.assign ( "abin.chain",true ); 2612 if (f.rewrite()) { 2613 chain->PDBASCIIDump ( f ); 2614 f.shut(); 2615 } else 2616 printf ( " Can't open output file 'abin.chain' \n" ); 2617 2618 delete Chain; 2619 2620 } 2621 */ 2622