1 // $Id: mmdb_model.cpp $ 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 // 11.09.15 <-- Date of Last Modification. 26 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 // ----------------------------------------------------------------- 28 // 29 // **** Module : MMDB_Model <implementation> 30 // ~~~~~~~~~ 31 // **** Project : MacroMolecular Data Base (MMDB) 32 // ~~~~~~~~~ 33 // **** Classes : mmdb::HetCompound ( description of het compounds ) 34 // ~~~~~~~~~ mmdb::HetCompounds (HETNAM, HETSYN, FORMULA records) 35 // mmdb::SSContainer (container for helixes and turns) 36 // mmdb::Helix ( helix info ) 37 // mmdb::Strand ( strand info ) 38 // mmdb::Sheet ( sheet info ) 39 // mmdb::Sheets ( container for sheets ) 40 // mmdb::Turn ( turn info ) 41 // mmdb::LinkContainer ( container for link data ) 42 // mmdb::Link ( link data ) 43 // mmdb::LinkRContainer ( container for refmac link ) 44 // mmdb::LinkR ( link data ) 45 // mmdb::CisPepContainer ( container for CisPep data ) 46 // mmdb::CisPep ( CisPep data ) 47 // mmdb::Model ( PDB model ) 48 // 49 // Copyright (C) E. Krissinel 2000-2015 50 // 51 // ================================================================= 52 // 53 54 #include <string.h> 55 #include <stdlib.h> 56 57 #include "mmdb_model.h" 58 #include "mmdb_manager.h" 59 #include "mmdb_cifdefs.h" 60 61 namespace mmdb { 62 63 // =================== HetCompound ========================= 64 HetCompound(cpstr HetName)65 HetCompound::HetCompound ( cpstr HetName ) : io::Stream() { 66 InitHetCompound ( HetName ); 67 } 68 HetCompound(io::RPStream Object)69 HetCompound::HetCompound ( io::RPStream Object ) : io::Stream(Object) { 70 InitHetCompound ( pstr("---") ); 71 } 72 ~HetCompound()73 HetCompound::~HetCompound() { 74 FreeMemory(); 75 } 76 InitHetCompound(cpstr HetName)77 void HetCompound::InitHetCompound ( cpstr HetName ) { 78 strcpy_n0 ( hetID,HetName,sizeof(ResName) ); 79 comment = NULL; 80 nSynonyms = 0; 81 hetSynonym = NULL; 82 compNum = MinInt4; 83 wc = ' '; 84 Formula = NULL; 85 } 86 FreeMemory()87 void HetCompound::FreeMemory() { 88 int i; 89 if (comment) { 90 delete[] comment; 91 comment = NULL; 92 } 93 if (hetSynonym) { 94 for (i=0;i<nSynonyms;i++) 95 if (hetSynonym[i]) delete[] hetSynonym[i]; 96 delete[] hetSynonym; 97 hetSynonym = NULL; 98 } 99 nSynonyms = 0; 100 if (Formula) { 101 delete[] Formula; 102 Formula = NULL; 103 } 104 } 105 AddKeyWord(cpstr W,bool Closed)106 void HetCompound::AddKeyWord ( cpstr W, bool Closed ) { 107 psvector HS1; 108 int i; 109 if (Closed || (!hetSynonym)) { 110 // first synonym orthe previous synonym was closed by semicolon 111 // -- add a new one 112 HS1 = new pstr[nSynonyms+1]; 113 for (i=0;i<nSynonyms;i++) 114 HS1[i] = hetSynonym[i]; 115 if (hetSynonym) delete[] hetSynonym; 116 hetSynonym = HS1; 117 hetSynonym[nSynonyms] = NULL; 118 CreateCopy ( hetSynonym[nSynonyms],W ); 119 nSynonyms++; 120 } else { 121 // just add W to the last synonym 122 CreateConcat ( hetSynonym[nSynonyms-1],pstr(" "),W ); 123 } 124 } 125 126 HETNAM_PDBDump(io::RFile f)127 void HetCompound::HETNAM_PDBDump ( io::RFile f ) { 128 char S[100]; 129 pstr p1,p2; 130 char c; 131 int N,i; 132 133 if (!comment) return; 134 135 c = ' '; 136 N = 0; 137 p1 = comment; 138 do { 139 N++; 140 if (N==1) sprintf ( S,"HETNAM %3s " ,hetID ); 141 else sprintf ( S,"HETNAM %2i %3s ",N,hetID ); 142 while (*p1==' ') p1++; 143 p2 = FirstOccurence(p1,'\n'); 144 if (p2) { 145 c = *p2; 146 *p2 = char(0); 147 } else if (strlen(p1)>53) { 148 i = 0; 149 while (p1[i] && (i<53) && (p1[i]!=' ')) i++; 150 p2 = &(p1[i]); 151 c = *p2; 152 *p2 = char(0); 153 } 154 if (*p1) { 155 strcat ( S,p1 ); 156 PadSpaces ( S,80 ); 157 f.WriteLine ( S ); 158 } else 159 N--; 160 if (p2) { 161 *p2 = c; 162 if (c) p1 = p2+1; 163 else p2 = NULL; 164 } 165 } while (p2); 166 167 } 168 169 HETSYN_PDBDump(io::RFile f)170 void HetCompound::HETSYN_PDBDump ( io::RFile f ) { 171 char S[100]; 172 pstr p; 173 char c; 174 int N,k,i,l; 175 if (!hetSynonym) return; 176 N = 0; 177 k = 0; 178 p = &(hetSynonym[0][0]); 179 do { 180 N++; 181 if (N==1) sprintf ( S,"HETSYN %3s " ,hetID ); 182 else sprintf ( S,"HETSYN %2i %3s ",N,hetID ); 183 i = 0; 184 do { 185 l = strlen(p)+2; 186 if (i+l<54) { 187 strcat ( S,p ); 188 if (k<nSynonyms-1) strcat ( S,"; " ); 189 k++; 190 i += l; 191 if (k<nSynonyms) p = &(hetSynonym[k][0]); 192 else i = 60; // break loop 193 } else { 194 if (i==0) { 195 // too long synonym, has to be split over several lines 196 i = l-3; 197 while (i>51) { 198 i--; 199 while ((i>0) && (p[i]!=' ')) i--; 200 } 201 if (i<2) i = 51; // no spaces! 202 c = p[i]; 203 p[i] = char(0); 204 strcat ( S,p ); 205 p[i] = c; 206 p = &(p[i]); 207 while (*p==' ') p++; 208 } 209 i = 60; // break loop 210 } 211 } while (i<54); 212 PadSpaces ( S,80 ); 213 f.WriteLine ( S ); 214 } while (k<nSynonyms); 215 } 216 217 FORMUL_PDBDump(io::RFile f)218 void HetCompound::FORMUL_PDBDump ( io::RFile f ) { 219 char S[100]; 220 pstr p1,p2; 221 char c; 222 int N,i; 223 if (!Formula) return; 224 N = 0; 225 p1 = Formula; 226 do { 227 N++; 228 if (compNum>MinInt4) { 229 if (N==1) sprintf ( S,"FORMUL %2i %3s " ,compNum,hetID ); 230 else sprintf ( S,"FORMUL %2i %3s %2i ",compNum,hetID,N ); 231 } else { 232 if (N==1) sprintf ( S,"FORMUL %3s " ,hetID ); 233 else sprintf ( S,"FORMUL %3s %2i ",hetID,N ); 234 } 235 S[18] = wc; 236 p2 = FirstOccurence(p1,'\n'); 237 if (p2) { 238 c = *p2; 239 *p2 = char(0); 240 } else if (strlen(p1)>50) { 241 while (*p1==' ') p1++; 242 i = 0; 243 while (p1[i] && (i<50) && (p1[i]!=' ')) i++; 244 p2 = &(p1[i]); 245 c = *p2; 246 *p2 = char(0); 247 } 248 strcat ( S,p1 ); 249 if (p2) { 250 *p2 = c; 251 p1 = p2+1; 252 } 253 PadSpaces ( S,80 ); 254 f.WriteLine ( S ); 255 } while (p2); 256 } 257 258 FormComString(pstr & F)259 void HetCompound::FormComString ( pstr & F ) { 260 pstr p; 261 int i; 262 if (F) { 263 delete[] F; 264 F = NULL; 265 } 266 if (comment) { 267 CreateCopy ( F,comment ); 268 i = 0; 269 p = comment; 270 while (*p) { 271 p++; 272 if (*p=='\n') i = 0; 273 else i++; 274 if (i>68) { 275 F[i] = char(0); 276 CreateConcat ( F,pstr("\n"),p ); 277 i = 0; 278 } 279 } 280 } 281 } 282 283 FormSynString(pstr & F)284 void HetCompound::FormSynString ( pstr & F ) { 285 pstr p; 286 char c; 287 int i,k,l; 288 if (F) { 289 delete[] F; 290 F = NULL; 291 } 292 if (hetSynonym) { 293 CreateCopy ( F,pstr(" ") ); 294 k = 0; 295 p = &(hetSynonym[0][0]); 296 do { 297 l = strlen(p)+2; 298 if (l<=60) { 299 if (k<nSynonyms-1) CreateConcat ( F,p,pstr(";\n ") ); 300 else CreateConcat ( F,p ); 301 k++; 302 if (k<nSynonyms) p = &(hetSynonym[k][0]); 303 } else { 304 // too long synonym, has to be split over several lines 305 i = l-3; 306 while (i>60) { 307 i--; 308 while ((i>0) && (p[i]!=' ')) i--; 309 } 310 if (i<2) i = 60; // no spaces! 311 c = p[i]; 312 p[i] = char(0); 313 CreateConcat ( F,p,pstr("\n ") ); 314 p[i] = c; 315 p = &(p[i]); 316 while (*p==' ') p++; 317 } 318 } while (k<nSynonyms); 319 } 320 } 321 FormForString(pstr & F)322 void HetCompound::FormForString ( pstr & F ) { 323 pstr p; 324 int i; 325 if (F) { 326 delete[] F; 327 F = NULL; 328 } 329 if (Formula) { 330 CreateCopy ( F,Formula ); 331 i = 0; 332 p = &(Formula[0]); 333 while (*p) { 334 p++; 335 if (*p=='\n') i = 0; 336 else i++; 337 if (i>68) { 338 F[i] = char(0); 339 CreateConcat ( F,pstr("\n"),p ); 340 i = 0; 341 } 342 } 343 } 344 } 345 346 Copy(PHetCompound hetCompound)347 void HetCompound::Copy ( PHetCompound hetCompound ) { 348 int i; 349 FreeMemory (); 350 strcpy ( hetID ,hetCompound->hetID ); 351 CreateCopy ( comment,hetCompound->comment ); 352 nSynonyms = hetCompound->nSynonyms; 353 if (nSynonyms>0) { 354 hetSynonym = new pstr[nSynonyms]; 355 for (i=0;i<nSynonyms;i++) { 356 hetSynonym[i] = NULL; 357 CreateCopy ( hetSynonym[i],hetCompound->hetSynonym[i] ); 358 } 359 } 360 compNum = hetCompound->compNum; 361 wc = hetCompound->wc; 362 CreateCopy ( Formula,hetCompound->Formula ); 363 } 364 write(io::RFile f)365 void HetCompound::write ( io::RFile f ) { 366 int i; 367 byte Version=1; 368 f.WriteByte ( &Version ); 369 f.WriteTerLine ( hetID,false ); 370 f.CreateWrite ( comment ); 371 f.WriteInt ( &nSynonyms ); 372 for (i=0;i<nSynonyms;i++) 373 f.CreateWrite ( hetSynonym[i] ); 374 f.WriteInt ( &compNum ); 375 f.WriteFile ( &wc,sizeof(wc) ); 376 f.CreateWrite ( Formula ); 377 } 378 read(io::RFile f)379 void HetCompound::read ( io::RFile f ) { 380 int i; 381 byte Version; 382 FreeMemory(); 383 f.ReadByte ( &Version ); 384 f.ReadTerLine ( hetID,false ); 385 f.CreateRead ( comment ); 386 f.ReadInt ( &nSynonyms ); 387 if (nSynonyms>0) { 388 hetSynonym = new pstr[nSynonyms]; 389 for (i=0;i<nSynonyms;i++) { 390 hetSynonym[i] = NULL; 391 f.CreateRead ( hetSynonym[i] ); 392 } 393 } 394 f.ReadInt ( &compNum ); 395 f.ReadFile ( &wc,sizeof(wc) ); 396 f.CreateRead ( Formula ); 397 } 398 MakeStreamFunctions(HetCompound)399 MakeStreamFunctions(HetCompound) 400 401 402 // ==================== HetCompounds ======================= 403 404 405 HetCompounds::HetCompounds() : io::Stream() { 406 InitHetCompounds(); 407 } 408 HetCompounds(io::RPStream Object)409 HetCompounds::HetCompounds ( io::RPStream Object ) 410 : io::Stream(Object) { 411 InitHetCompounds(); 412 } 413 ~HetCompounds()414 HetCompounds::~HetCompounds() { 415 FreeMemory(); 416 } 417 InitHetCompounds()418 void HetCompounds::InitHetCompounds() { 419 nHets = 0; 420 hetCompound = NULL; 421 Closed = false; 422 } 423 FreeMemory()424 void HetCompounds::FreeMemory() { 425 int i; 426 if (hetCompound) { 427 for (i=0;i<nHets;i++) 428 if (hetCompound[i]) delete hetCompound[i]; 429 delete[] hetCompound; 430 hetCompound = NULL; 431 } 432 nHets = 0; 433 } 434 ConvertHETNAM(cpstr S)435 void HetCompounds::ConvertHETNAM ( cpstr S ) { 436 ResName hetID; 437 char L[100]; 438 int l,i; 439 l = strlen(S); 440 if (l>12) { 441 strcpy_n0 ( hetID,&(S[11]),3 ); 442 i = AddHetName ( hetID ); 443 if (l>15) { 444 if (hetCompound[i]->comment) strcpy ( L,"\n" ); 445 else L[0] = char(0); 446 strcat ( L,&(S[15]) ); 447 CutSpaces ( L,SCUTKEY_END ); 448 CreateConcat ( hetCompound[i]->comment,L ); 449 } 450 } 451 } 452 ConvertHETSYN(cpstr S)453 void HetCompounds::ConvertHETSYN ( cpstr S ) { 454 ResName hetID; 455 char L[100]; 456 int l,i,j,k; 457 l = strlen(S); 458 if (l>12) { 459 strcpy_n0 ( hetID,&(S[11]),3 ); 460 i = AddHetName ( hetID ); 461 if (l>15) { 462 j = 15; 463 do { 464 while (S[j]==' ') j++; 465 k = 0; 466 if (S[j]) { 467 while (S[j] && (S[j]!=';')) 468 L[k++] = S[j++]; 469 L[k--] = char(0); 470 while ((k>0) && (L[k]==' ')) L[k--] = char(0); 471 if (L[0]) { 472 hetCompound[i]->AddKeyWord ( L,Closed ); 473 Closed = (S[j]==';'); 474 } 475 if (S[j]) j++; 476 } 477 } while (S[j]); 478 /* 479 p1 = &(S[15]); 480 do { 481 p2 = FirstOccurence ( p1,';' ); 482 if (p2) { 483 c = *p2; 484 *p2 = char(0); 485 } 486 strcpy_css ( L,p1 ); 487 if (L[0]) 488 hetCompound[i]->AddKeyWord ( L,Closed ); 489 if (p2) { 490 if (L[0]) Closed = true; 491 *p2 = c; 492 p1 = p2+1; 493 } else if (L[0]) 494 Closed = false; 495 } while (p2); 496 */ 497 } 498 } 499 } 500 ConvertFORMUL(cpstr S)501 void HetCompounds::ConvertFORMUL ( cpstr S ) { 502 ResName hetID; 503 char L[100]; 504 int l,i; 505 l = strlen(S); 506 if (l>13) { 507 strcpy_n0 ( hetID,&(S[12]),3 ); 508 i = AddHetName ( hetID ); 509 if (l>18) { 510 GetInteger ( hetCompound[i]->compNum,&(S[9]),2 ); 511 hetCompound[i]->wc = S[18]; 512 if (strlen(S)>19) { 513 if (hetCompound[i]->Formula) strcpy ( L,"\n" ); 514 else L[0] = char(0); 515 strcat ( L,&(S[19]) ); 516 CutSpaces ( L,SCUTKEY_END ); 517 CreateConcat ( hetCompound[i]->Formula,L ); 518 } 519 } 520 } 521 } AddHetName(cpstr H)522 int HetCompounds::AddHetName ( cpstr H ) { 523 PPHetCompound HC1; 524 int i; 525 i = 0; 526 while (i<nHets) { 527 if (hetCompound[i]) { 528 if (!strcmp(hetCompound[i]->hetID,H)) break; 529 } 530 i++; 531 } 532 if (i>=nHets) { 533 HC1 = new PHetCompound[nHets+1]; 534 for (i=0;i<nHets;i++) 535 HC1[i] = hetCompound[i]; 536 if (hetCompound) delete[] hetCompound; 537 hetCompound = HC1; 538 hetCompound[nHets] = new HetCompound ( H ); 539 i = nHets; 540 nHets++; 541 } 542 return i; 543 } 544 PDBASCIIDump(io::RFile f)545 void HetCompounds::PDBASCIIDump ( io::RFile f ) { 546 int i; 547 548 for (i=0;i<nHets;i++) 549 if (hetCompound[i]) 550 hetCompound[i]->HETNAM_PDBDump ( f ); 551 552 for (i=0;i<nHets;i++) 553 if (hetCompound[i]) 554 hetCompound[i]->HETSYN_PDBDump ( f ); 555 556 for (i=0;i<nHets;i++) 557 if (hetCompound[i]) 558 hetCompound[i]->FORMUL_PDBDump ( f ); 559 560 } 561 562 MakeCIF(mmcif::PData CIF)563 void HetCompounds::MakeCIF ( mmcif::PData CIF ) { 564 mmcif::PLoop Loop; 565 pstr F; 566 int RC; 567 int i; 568 569 if (!hetCompound) return; 570 571 RC = CIF->AddLoop ( CIFCAT_CHEM_COMP,Loop ); 572 if (RC!=mmcif::CIFRC_Ok) { 573 Loop->AddLoopTag ( CIFTAG_ID ); 574 Loop->AddLoopTag ( CIFTAG_NAME ); 575 Loop->AddLoopTag ( CIFTAG_NDB_SYNONYMS ); 576 Loop->AddLoopTag ( CIFTAG_NDB_COMPONENT_NO ); 577 Loop->AddLoopTag ( CIFTAG_FORMULA ); 578 } 579 580 F = NULL; 581 for (i=0;i<nHets;i++) 582 if (hetCompound[i]) { 583 Loop->AddString ( hetCompound[i]->hetID ); 584 hetCompound[i]->FormComString ( F ); 585 Loop->AddString ( F ); 586 hetCompound[i]->FormSynString ( F ); 587 Loop->AddString ( F ); 588 if (hetCompound[i]->compNum>MinInt4) 589 Loop->AddInteger ( hetCompound[i]->compNum ); 590 else Loop->AddNoData ( mmcif::CIF_NODATA_QUESTION ); 591 hetCompound[i]->FormForString ( F ); 592 Loop->AddString ( F ); 593 } 594 595 if (F) delete[] F; 596 597 } 598 GetCIF(mmcif::PData CIF)599 ERROR_CODE HetCompounds::GetCIF ( mmcif::PData CIF ) { 600 mmcif::PLoop Loop; 601 char L[100]; 602 ResName hetID; 603 pstr F,p1,p2; 604 char c; 605 int RC,i,l,k; 606 607 FreeMemory(); 608 c = char(0); // only to supress compiler warnings 609 610 Loop = CIF->GetLoop ( CIFCAT_CHEM_COMP ); 611 if (!Loop) return Error_NoError; 612 613 l = Loop->GetLoopLength(); 614 F = NULL; 615 616 for (i=0;i<l;i++) { 617 CIFGetString ( hetID,Loop,CIFTAG_ID,i,sizeof(hetID), 618 pstr("---") ); 619 k = AddHetName ( hetID ); 620 Loop->GetString ( hetCompound[k]->comment,CIFTAG_NAME,i,true ); 621 RC = Loop->GetInteger ( hetCompound[k]->compNum, 622 CIFTAG_NDB_COMPONENT_NO,i,true ); 623 if (RC) hetCompound[i]->compNum = MinInt4; 624 Loop->GetString ( hetCompound[k]->Formula,CIFTAG_FORMULA,i,true ); 625 RC = Loop->GetString ( F,CIFTAG_NDB_SYNONYMS,i,true ); 626 if ((!RC) && F ) { 627 p1 = &(F[0]); 628 while (*p1) { 629 if (*p1=='\n') *p1 = ' '; 630 p1++; 631 } 632 p1 = &(F[0]); 633 do { 634 p2 = FirstOccurence ( p1,';' ); 635 if (p2) { 636 c = *p2; 637 *p2 = char(0); 638 } 639 strcpy_css ( L,p1 ); 640 hetCompound[i]->AddKeyWord ( L,true ); 641 if (p2) { 642 *p2 = c; 643 p1 = p2+1; 644 } 645 } while (p2); 646 } 647 hetCompound[i]->wc = ' '; 648 } 649 650 // CIF->DeleteLoop ( CIFCAT_CHEM_COMP ); 651 652 if (F) delete[] F; 653 654 return Error_NoError; 655 656 } 657 Copy(PHetCompounds HetCompounds)658 void HetCompounds::Copy ( PHetCompounds HetCompounds ) { 659 int i; 660 FreeMemory(); 661 nHets = HetCompounds->nHets; 662 if (nHets>0) { 663 hetCompound = new PHetCompound[nHets]; 664 for (i=0;i<nHets;i++) { 665 hetCompound[i] = new HetCompound ( "" ); 666 hetCompound[i]->Copy ( HetCompounds->hetCompound[i] ); 667 } 668 } 669 } 670 write(io::RFile f)671 void HetCompounds::write ( io::RFile f ) { 672 int i; 673 byte Version=1; 674 f.WriteByte ( &Version ); 675 f.WriteInt ( &nHets ); 676 for (i=0;i<nHets;i++) 677 hetCompound[i]->write ( f ); 678 } 679 read(io::RFile f)680 void HetCompounds::read ( io::RFile f ) { 681 int i; 682 byte Version; 683 FreeMemory(); 684 f.ReadByte ( &Version ); 685 f.ReadInt ( &nHets ); 686 if (nHets>0) { 687 hetCompound = new PHetCompound[nHets]; 688 for (i=0;i<nHets;i++) { 689 hetCompound[i] = new HetCompound ( "---" ); 690 hetCompound[i]->read ( f ); 691 } 692 } 693 } 694 MakeStreamFunctions(HetCompounds)695 MakeStreamFunctions(HetCompounds) 696 697 698 699 // ==================== SSContainer ========================= 700 701 PContainerClass SSContainer::MakeContainerClass ( int ClassID ) { 702 switch (ClassID) { 703 default : 704 case ClassID_Template : return 705 ClassContainer::MakeContainerClass(ClassID); 706 case ClassID_Helix : return new Helix(); 707 case ClassID_Turn : return new Turn (); 708 } 709 } 710 MakeStreamFunctions(SSContainer)711 MakeStreamFunctions(SSContainer) 712 713 714 // ================ Helix =================== 715 716 Helix::Helix() : ContainerClass() { 717 InitHelix(); 718 } 719 Helix(cpstr S)720 Helix::Helix ( cpstr S ) : ContainerClass() { 721 InitHelix(); 722 ConvertPDBASCII ( S ); 723 } 724 Helix(io::RPStream Object)725 Helix::Helix ( io::RPStream Object ) : ContainerClass(Object) { 726 InitHelix(); 727 } 728 ~Helix()729 Helix::~Helix() { 730 if (comment) delete[] comment; 731 } 732 InitHelix()733 void Helix::InitHelix() { 734 735 serNum = 0; // serial number 736 strcpy ( helixID ,"---" ); // helix ID 737 strcpy ( initResName,"---" ); // name of the helix's initial residue 738 strcpy ( initChainID,"" ); // chain ID for the chain 739 // containing the helix 740 initSeqNum = 0; // sequence number of the initial 741 // residue 742 strcpy ( initICode ,"" ); // insertion code of the initial 743 // residue 744 strcpy ( endResName ,"---" ); // name of the helix's terminal residue 745 strcpy ( endChainID ,"" ); // chain ID for the chain 746 // containing the helix 747 endSeqNum = 0; // sequence number of the terminal 748 // residue 749 strcpy ( endICode ,"" ); // insertion code of the terminal 750 // residue 751 helixClass = 0; // helix class 752 comment = NULL; // comment about the helix 753 length = 0; // length of the helix 754 755 } 756 PDBASCIIDump(pstr S,int N)757 void Helix::PDBASCIIDump ( pstr S, int N ) { 758 UNUSED_ARGUMENT(N); 759 // makes the ASCII PDB OBSLTE line number N 760 // from the class' data 761 strcpy ( S,"HELIX" ); 762 PadSpaces ( S,80 ); 763 PutInteger ( &(S[7]) ,serNum ,3 ); 764 strcpy_n1 ( &(S[11]),helixID ,3 ); 765 strcpy_n1 ( &(S[15]),initResName,3 ); 766 if (initChainID[0]) S[19] = initChainID[0]; 767 PutIntIns ( &(S[21]),initSeqNum ,4,initICode ); 768 strcpy_n1 ( &(S[27]),endResName ,3 ); 769 if (endChainID[0]) S[31] = endChainID[0]; 770 PutIntIns ( &(S[33]),endSeqNum ,4,endICode ); 771 PutInteger ( &(S[38]),helixClass ,2 ); 772 if (comment) 773 strcpy_n ( &(S[40]),comment ,30 ); 774 PutInteger ( &(S[71]),length ,5 ); 775 } 776 AddStructConfTags(mmcif::PLoop Loop)777 void AddStructConfTags ( mmcif::PLoop Loop ) { 778 Loop->AddLoopTag ( CIFTAG_CONF_TYPE_ID ); 779 Loop->AddLoopTag ( CIFTAG_ID ); 780 Loop->AddLoopTag ( CIFTAG_PDB_ID ); 781 Loop->AddLoopTag ( CIFTAG_BEG_LABEL_COMP_ID ); 782 Loop->AddLoopTag ( CIFTAG_BEG_LABEL_ASYM_ID ); 783 Loop->AddLoopTag ( CIFTAG_BEG_LABEL_SEQ_ID ); 784 Loop->AddLoopTag ( CIFTAG_NDB_BEG_LABEL_INS_CODE_PDB ); 785 Loop->AddLoopTag ( CIFTAG_END_LABEL_COMP_ID ); 786 Loop->AddLoopTag ( CIFTAG_END_LABEL_ASYM_ID ); 787 Loop->AddLoopTag ( CIFTAG_END_LABEL_SEQ_ID ); 788 Loop->AddLoopTag ( CIFTAG_NDB_END_LABEL_INS_CODE_PDB ); 789 Loop->AddLoopTag ( CIFTAG_NDB_HELIX_CLASS_PDB ); 790 Loop->AddLoopTag ( CIFTAG_DETAILS ); 791 Loop->AddLoopTag ( CIFTAG_NDB_LENGTH ); 792 } 793 794 #define HelixTypeID "HELX_P" 795 MakeCIF(mmcif::PData CIF,int N)796 void Helix::MakeCIF ( mmcif::PData CIF, int N ) { 797 UNUSED_ARGUMENT(N); 798 mmcif::PLoop Loop; 799 int RC; 800 RC = CIF->AddLoop ( CIFCAT_STRUCT_CONF,Loop ); 801 if (RC!=mmcif::CIFRC_Ok) 802 // the category was (re)created, provide tags 803 AddStructConfTags ( Loop ); 804 Loop->AddString ( pstr(HelixTypeID) ); 805 Loop->AddInteger ( serNum ); 806 Loop->AddString ( helixID ); 807 Loop->AddString ( initResName ); 808 Loop->AddString ( initChainID ); 809 Loop->AddInteger ( initSeqNum ); 810 Loop->AddString ( initICode,true ); 811 Loop->AddString ( endResName ); 812 Loop->AddString ( endChainID ); 813 Loop->AddInteger ( endSeqNum ); 814 Loop->AddString ( endICode ,true ); 815 Loop->AddInteger ( helixClass ); 816 Loop->AddString ( comment ); 817 Loop->AddInteger ( length ); 818 } 819 ConvertPDBASCII(cpstr S)820 ERROR_CODE Helix::ConvertPDBASCII ( cpstr S ) { 821 char L[100]; 822 GetInteger ( serNum ,&(S[7]) ,3 ); 823 strcpy_ncss ( helixID ,&(S[11]),3 ); 824 strcpy_ncss ( initResName,&(S[15]),3 ); 825 strcpy_ncss ( initChainID,&(S[19]),1 ); 826 GetIntIns ( initSeqNum,initICode,&(S[21]),4 ); 827 strcpy_ncss ( endResName ,&(S[27]),3 ); 828 strcpy_ncss ( endChainID ,&(S[31]),1 ); 829 GetIntIns ( endSeqNum ,endICode ,&(S[33]),4 ); 830 GetInteger ( helixClass ,&(S[38]),2 ); 831 strcpy_ncss ( L ,&(S[40]),30 ); 832 CreateCopy ( comment ,L ); 833 GetInteger ( length ,&(S[71]),5 ); 834 return Error_NoError; 835 } 836 GetCIF(mmcif::PData CIF,int & n)837 ERROR_CODE Helix::GetCIF ( mmcif::PData CIF, int & n ) { 838 mmcif::PLoop Loop; 839 int RC,l; 840 pstr F; 841 bool Done; 842 ERROR_CODE rc; 843 844 Loop = CIF->GetLoop ( CIFCAT_STRUCT_CONF ); 845 if (!Loop) { 846 n = -1; // signal to finish processing of this structure 847 return Error_EmptyCIF; 848 } 849 850 l = Loop->GetLoopLength(); 851 Done = n>=l; 852 while (!Done) { 853 F = Loop->GetString ( CIFTAG_CONF_TYPE_ID,n,RC ); 854 if ((!RC) && F) Done = (strcmp(F,HelixTypeID)==0); 855 else Done = false; 856 if (!Done) { 857 n++; 858 Done = n>=l; 859 } 860 } 861 862 if (n>=l) { 863 n = -1; // finish processing of Helix 864 return Error_EmptyCIF; 865 } 866 867 Loop->DeleteField ( CIFTAG_CONF_TYPE_ID,n ); 868 869 rc = CIFGetInteger ( serNum,Loop,CIFTAG_ID,n ); 870 if (rc==Error_NoData) return Error_EmptyCIF; 871 if (rc!=Error_NoError) return rc; 872 873 CIFGetString ( helixID ,Loop,CIFTAG_PDB_ID, 874 n,sizeof(helixID),pstr(" ") ); 875 876 CIFGetString ( initResName,Loop,CIFTAG_BEG_LABEL_COMP_ID, 877 n,sizeof(initResName),pstr(" ") ); 878 CIFGetString ( initChainID,Loop,CIFTAG_BEG_LABEL_ASYM_ID, 879 n,sizeof(initChainID),pstr("") ); 880 CIFGetString ( initICode ,Loop,CIFTAG_NDB_BEG_LABEL_INS_CODE_PDB, 881 n,sizeof(initICode),pstr("") ); 882 if (CIFGetInteger(initSeqNum,Loop,CIFTAG_BEG_LABEL_SEQ_ID,n)) 883 if (rc==Error_NoData) return Error_EmptyCIF; 884 if (rc!=Error_NoError) return rc; 885 886 CIFGetString ( endResName,Loop,CIFTAG_END_LABEL_COMP_ID, 887 n,sizeof(endResName),pstr(" ") ); 888 CIFGetString ( endChainID,Loop,CIFTAG_END_LABEL_ASYM_ID, 889 n,sizeof(endChainID),pstr("") ); 890 CIFGetString ( endICode ,Loop,CIFTAG_NDB_END_LABEL_INS_CODE_PDB, 891 n,sizeof(endICode),pstr("") ); 892 rc = CIFGetInteger(endSeqNum,Loop,CIFTAG_END_LABEL_SEQ_ID,n ); 893 if (rc==Error_NoData) return Error_EmptyCIF; 894 if (rc!=Error_NoError) return rc; 895 896 rc = CIFGetInteger(helixClass,Loop,CIFTAG_NDB_HELIX_CLASS_PDB,n ); 897 if (rc==Error_NoData) return Error_EmptyCIF; 898 if (rc!=Error_NoError) return rc; 899 900 CreateCopy ( comment,Loop->GetString(CIFTAG_DETAILS,n,RC)); 901 Loop->DeleteField ( CIFTAG_DETAILS,n ); 902 rc = CIFGetInteger ( length,Loop,CIFTAG_NDB_LENGTH,n ); 903 if (rc==Error_NoData) return Error_EmptyCIF; 904 if (rc!=Error_NoError) return rc; 905 906 n++; 907 908 return Error_NoError; 909 910 } 911 Copy(PContainerClass Helix)912 void Helix::Copy ( PContainerClass Helix ) { 913 serNum = PHelix(Helix)->serNum; 914 initSeqNum = PHelix(Helix)->initSeqNum; 915 endSeqNum = PHelix(Helix)->endSeqNum; 916 helixClass = PHelix(Helix)->helixClass; 917 length = PHelix(Helix)->length; 918 strcpy ( helixID ,PHelix(Helix)->helixID ); 919 strcpy ( initResName,PHelix(Helix)->initResName ); 920 strcpy ( initChainID,PHelix(Helix)->initChainID ); 921 strcpy ( initICode ,PHelix(Helix)->initICode ); 922 strcpy ( endResName ,PHelix(Helix)->endResName ); 923 strcpy ( endChainID ,PHelix(Helix)->endChainID ); 924 strcpy ( endICode ,PHelix(Helix)->endICode ); 925 CreateCopy ( comment,PHelix(Helix)->comment ); 926 } 927 write(io::RFile f)928 void Helix::write ( io::RFile f ) { 929 byte Version=1; 930 f.WriteByte ( &Version ); 931 f.WriteInt ( &serNum ); 932 f.WriteInt ( &initSeqNum ); 933 f.WriteInt ( &endSeqNum ); 934 f.WriteInt ( &helixClass ); 935 f.WriteInt ( &length ); 936 f.WriteTerLine ( helixID ,false ); 937 f.WriteTerLine ( initResName,false ); 938 f.WriteTerLine ( initChainID,false ); 939 f.WriteTerLine ( initICode ,false ); 940 f.WriteTerLine ( endResName ,false ); 941 f.WriteTerLine ( endChainID ,false ); 942 f.WriteTerLine ( endICode ,false ); 943 f.CreateWrite ( comment ); 944 } 945 read(io::RFile f)946 void Helix::read ( io::RFile f ) { 947 byte Version; 948 f.ReadByte ( &Version ); 949 f.ReadInt ( &serNum ); 950 f.ReadInt ( &initSeqNum ); 951 f.ReadInt ( &endSeqNum ); 952 f.ReadInt ( &helixClass ); 953 f.ReadInt ( &length ); 954 f.ReadTerLine ( helixID ,false ); 955 f.ReadTerLine ( initResName,false ); 956 f.ReadTerLine ( initChainID,false ); 957 f.ReadTerLine ( initICode ,false ); 958 f.ReadTerLine ( endResName ,false ); 959 f.ReadTerLine ( endChainID ,false ); 960 f.ReadTerLine ( endICode ,false ); 961 f.CreateRead ( comment ); 962 } 963 MakeStreamFunctions(Helix)964 MakeStreamFunctions(Helix) 965 966 967 968 // ================ Strand ===================== 969 970 Strand::Strand () : io::Stream() { 971 InitStrand(); 972 } 973 Strand(io::RPStream Object)974 Strand::Strand ( io::RPStream Object ) : io::Stream(Object) { 975 InitStrand(); 976 } 977 ~Strand()978 Strand::~Strand() { 979 } 980 InitStrand()981 void Strand::InitStrand() { 982 initSeqNum = MinInt4; 983 endSeqNum = MinInt4; 984 sense = 0; 985 curResSeq = MinInt4; 986 prevResSeq = MinInt4; 987 strandNo = 0; 988 strcpy ( sheetID ,"sheet_0" ); 989 strcpy ( initResName," " ); 990 strcpy ( initChainID,"" ); 991 strcpy ( initICode ,"" ); 992 strcpy ( endResName ," " ); 993 strcpy ( endChainID ,"" ); 994 strcpy ( endICode ,"" ); 995 strcpy ( curAtom ," " ); 996 strcpy ( curResName ," " ); 997 strcpy ( curChainID ,"" ); 998 strcpy ( curICode ,"" ); 999 strcpy ( prevAtom ," " ); 1000 strcpy ( prevResName," " ); 1001 strcpy ( prevChainID,"" ); 1002 strcpy ( prevICode ,"" ); 1003 } 1004 PDBASCIIDump(pstr S)1005 void Strand::PDBASCIIDump ( pstr S ) { 1006 // Finishes making the ASCII PDB SHEET line number N 1007 // from the class' data. Making is initiated by Sheet. 1008 1009 strcpy_n1 ( &(S[17]),initResName,3 ); 1010 if (initChainID[0]) S[21] = initChainID[0]; 1011 PutIntIns ( &(S[22]),initSeqNum ,4,initICode ); 1012 1013 strcpy_n1 ( &(S[28]),endResName ,3 ); 1014 if (endChainID[0]) S[32] = endChainID[0]; 1015 PutIntIns ( &(S[33]),endSeqNum ,4,endICode ); 1016 1017 PutInteger ( &(S[38]),sense ,2 ); 1018 1019 strcpy_n1 ( &(S[41]),curAtom ,4 ); 1020 strcpy_n1 ( &(S[45]),curResName ,3 ); 1021 if (curChainID[0]) S[49] = curChainID[0]; 1022 PutIntIns ( &(S[50]),curResSeq ,4,curICode ); 1023 1024 strcpy_n1 ( &(S[56]),prevAtom ,4 ); 1025 strcpy_n1 ( &(S[60]),prevResName,3 ); 1026 if (prevChainID[0]) S[64] = prevChainID[0]; 1027 PutIntIns ( &(S[65]),prevResSeq ,4,prevICode ); 1028 1029 } 1030 1031 MakeCIF(mmcif::PData CIF)1032 void Strand::MakeCIF ( mmcif::PData CIF ) { 1033 mmcif::PLoop Loop; 1034 int RC; 1035 1036 RC = CIF->AddLoop ( CIFCAT_STRUCT_SHEET_RANGE,Loop ); 1037 if (RC!=mmcif::CIFRC_Ok) { 1038 // the category was (re)created, provide tags 1039 Loop->AddLoopTag ( CIFTAG_SHEET_ID ); 1040 Loop->AddLoopTag ( CIFTAG_ID ); 1041 Loop->AddLoopTag ( CIFTAG_BEG_LABEL_COMP_ID ); 1042 Loop->AddLoopTag ( CIFTAG_BEG_LABEL_ASYM_ID ); 1043 Loop->AddLoopTag ( CIFTAG_BEG_LABEL_SEQ_ID ); 1044 Loop->AddLoopTag ( CIFTAG_NDB_BEG_LABEL_INS_CODE_PDB ); 1045 Loop->AddLoopTag ( CIFTAG_END_LABEL_COMP_ID ); 1046 Loop->AddLoopTag ( CIFTAG_END_LABEL_ASYM_ID ); 1047 Loop->AddLoopTag ( CIFTAG_END_LABEL_SEQ_ID ); 1048 Loop->AddLoopTag ( CIFTAG_NDB_END_LABEL_INS_CODE_PDB ); 1049 } 1050 Loop->AddString ( sheetID ); 1051 Loop->AddInteger ( strandNo ); 1052 Loop->AddString ( initResName ); 1053 Loop->AddString ( initChainID ); 1054 Loop->AddInteger ( initSeqNum ); 1055 Loop->AddString ( initICode,true ); 1056 Loop->AddString ( endResName ); 1057 Loop->AddString ( endChainID ); 1058 Loop->AddInteger ( endSeqNum ); 1059 Loop->AddString ( endICode ,true ); 1060 1061 } 1062 1063 ConvertPDBASCII(cpstr S)1064 ERROR_CODE Strand::ConvertPDBASCII ( cpstr S ) { 1065 1066 GetInteger ( strandNo ,&(S[7]) ,3 ); 1067 strcpy_ncss ( sheetID ,&(S[11]) ,3 ); 1068 1069 strcpy_ncss ( initResName,&(S[17]) ,3 ); 1070 strcpy_ncss ( initChainID,&(S[21]) ,1 ); 1071 GetIntIns ( initSeqNum ,initICode,&(S[22]),4 ); 1072 1073 strcpy_ncss ( endResName ,&(S[28]) ,3 ); 1074 strcpy_ncss ( endChainID ,&(S[32]) ,1 ); 1075 GetIntIns ( endSeqNum ,endICode ,&(S[33]),4 ); 1076 1077 GetInteger ( sense ,&(S[38]) ,2 ); 1078 1079 GetString ( curAtom ,&(S[41]) ,4 ); 1080 strcpy_ncss ( curResName ,&(S[45]) ,3 ); 1081 strcpy_ncss ( curChainID ,&(S[49]) ,1 ); 1082 GetIntIns ( curResSeq ,curICode ,&(S[50]),4 ); 1083 1084 GetString ( prevAtom ,&(S[56]) ,4 ); 1085 strcpy_ncss ( prevResName,&(S[60]) ,3 ); 1086 strcpy_ncss ( prevChainID,&(S[64]) ,1 ); 1087 GetIntIns ( prevResSeq ,prevICode,&(S[65]),4 ); 1088 1089 return Error_NoError; 1090 1091 } 1092 GetCIF(mmcif::PData CIF,cpstr sheet_id)1093 int Strand::GetCIF ( mmcif::PData CIF, cpstr sheet_id ) { 1094 mmcif::PLoop Loop; 1095 int RC,l,i,sNo; 1096 pstr F; 1097 1098 Loop = CIF->GetLoop ( CIFCAT_STRUCT_SHEET_RANGE ); 1099 if (Loop) { 1100 l = Loop->GetLoopLength(); 1101 i = 0; 1102 while (i<l) { 1103 F = Loop->GetString ( CIFTAG_SHEET_ID,i,RC ); 1104 if (F && (!RC)) { 1105 if (!strcmp(F,sheet_id)) { 1106 strcpy ( sheetID,sheet_id ); 1107 if (CIFGetInteger(sNo,Loop,CIFTAG_ID,i)) return i; 1108 if (sNo==strandNo) { 1109 CIFGetString ( initResName,Loop,CIFTAG_BEG_LABEL_COMP_ID, 1110 i,sizeof(initResName),pstr(" ") ); 1111 CIFGetString ( initChainID,Loop,CIFTAG_BEG_LABEL_ASYM_ID, 1112 i,sizeof(initChainID),pstr("") ); 1113 CIFGetString ( initICode,Loop, 1114 CIFTAG_NDB_BEG_LABEL_INS_CODE_PDB, 1115 i,sizeof(initICode),pstr("") ); 1116 if (CIFGetInteger(initSeqNum,Loop, 1117 CIFTAG_BEG_LABEL_SEQ_ID,i)) 1118 return i; 1119 CIFGetString ( endResName,Loop,CIFTAG_END_LABEL_COMP_ID, 1120 i,sizeof(endResName),pstr(" ") ); 1121 CIFGetString ( endChainID,Loop,CIFTAG_END_LABEL_ASYM_ID, 1122 i,sizeof(endChainID),pstr("") ); 1123 CIFGetString ( endICode ,Loop, 1124 CIFTAG_NDB_END_LABEL_INS_CODE_PDB, 1125 i,sizeof(endICode),pstr("") ); 1126 if (CIFGetInteger(endSeqNum,Loop, 1127 CIFTAG_END_LABEL_SEQ_ID,i)) 1128 return i; 1129 Loop->DeleteRow ( i ); 1130 i = l+100; // break the loop 1131 } 1132 } 1133 } 1134 i++; 1135 } 1136 } 1137 1138 return 0; 1139 1140 } 1141 Copy(PStrand Strand)1142 void Strand::Copy ( PStrand Strand ) { 1143 initSeqNum = Strand->initSeqNum; 1144 endSeqNum = Strand->endSeqNum; 1145 sense = Strand->sense; 1146 curResSeq = Strand->curResSeq; 1147 prevResSeq = Strand->prevResSeq; 1148 strcpy ( initResName,Strand->initResName ); 1149 strcpy ( initChainID,Strand->initChainID ); 1150 strcpy ( initICode ,Strand->initICode ); 1151 strcpy ( endResName ,Strand->endResName ); 1152 strcpy ( endChainID ,Strand->endChainID ); 1153 strcpy ( endICode ,Strand->endICode ); 1154 strcpy ( curAtom ,Strand->curAtom ); 1155 strcpy ( curResName ,Strand->curResName ); 1156 strcpy ( curChainID ,Strand->curChainID ); 1157 strcpy ( curICode ,Strand->curICode ); 1158 strcpy ( prevAtom ,Strand->prevAtom ); 1159 strcpy ( prevResName,Strand->prevResName ); 1160 strcpy ( prevChainID,Strand->prevChainID ); 1161 strcpy ( prevICode ,Strand->prevICode ); 1162 } 1163 write(io::RFile f)1164 void Strand::write ( io::RFile f ) { 1165 byte Version=1; 1166 f.WriteByte ( &Version ); 1167 f.WriteInt ( &initSeqNum ); 1168 f.WriteInt ( &endSeqNum ); 1169 f.WriteInt ( &sense ); 1170 f.WriteInt ( &curResSeq ); 1171 f.WriteInt ( &prevResSeq ); 1172 f.WriteTerLine ( initResName,false ); 1173 f.WriteTerLine ( initChainID,false ); 1174 f.WriteTerLine ( initICode ,false ); 1175 f.WriteTerLine ( endResName ,false ); 1176 f.WriteTerLine ( endChainID ,false ); 1177 f.WriteTerLine ( endICode ,false ); 1178 f.WriteTerLine ( curAtom ,false ); 1179 f.WriteTerLine ( curResName ,false ); 1180 f.WriteTerLine ( curChainID ,false ); 1181 f.WriteTerLine ( curICode ,false ); 1182 f.WriteTerLine ( prevAtom ,false ); 1183 f.WriteTerLine ( prevResName,false ); 1184 f.WriteTerLine ( prevChainID,false ); 1185 f.WriteTerLine ( prevICode ,false ); 1186 } 1187 read(io::RFile f)1188 void Strand::read ( io::RFile f ) { 1189 byte Version; 1190 f.ReadByte ( &Version ); 1191 f.ReadInt ( &initSeqNum ); 1192 f.ReadInt ( &endSeqNum ); 1193 f.ReadInt ( &sense ); 1194 f.ReadInt ( &curResSeq ); 1195 f.ReadInt ( &prevResSeq ); 1196 f.ReadTerLine ( initResName,false ); 1197 f.ReadTerLine ( initChainID,false ); 1198 f.ReadTerLine ( initICode ,false ); 1199 f.ReadTerLine ( endResName ,false ); 1200 f.ReadTerLine ( endChainID ,false ); 1201 f.ReadTerLine ( endICode ,false ); 1202 f.ReadTerLine ( curAtom ,false ); 1203 f.ReadTerLine ( curResName ,false ); 1204 f.ReadTerLine ( curChainID ,false ); 1205 f.ReadTerLine ( curICode ,false ); 1206 f.ReadTerLine ( prevAtom ,false ); 1207 f.ReadTerLine ( prevResName,false ); 1208 f.ReadTerLine ( prevChainID,false ); 1209 f.ReadTerLine ( prevICode ,false ); 1210 } 1211 MakeStreamFunctions(Strand)1212 MakeStreamFunctions(Strand) 1213 1214 1215 1216 1217 // ================ Sheet =================== 1218 1219 Sheet::Sheet() : io::Stream() { 1220 InitSheet(); 1221 } 1222 Sheet(io::RPStream Object)1223 Sheet::Sheet ( io::RPStream Object ) : io::Stream(Object) { 1224 InitSheet(); 1225 } 1226 ~Sheet()1227 Sheet::~Sheet() { 1228 FreeMemory(); 1229 } 1230 InitSheet()1231 void Sheet::InitSheet() { 1232 nStrands = 0; 1233 sheetID[0] = char(0); 1234 strand = NULL; 1235 } 1236 FreeMemory()1237 void Sheet::FreeMemory() { 1238 int i; 1239 if (strand) { 1240 for (i=0;i<nStrands;i++) 1241 if (strand[i]) delete strand[i]; 1242 delete[] strand; 1243 strand = NULL; 1244 } 1245 nStrands = 0; 1246 sheetID[0] = char(0); 1247 } 1248 PDBASCIIDump(io::RFile f)1249 void Sheet::PDBASCIIDump ( io::RFile f ) { 1250 char S[100]; 1251 int i; 1252 if (strand) 1253 for (i=0;i<nStrands;i++) 1254 if (strand[i]) { 1255 strcpy ( S,"SHEET" ); 1256 PadSpaces ( S,80 ); 1257 PutInteger ( &(S[7]) ,i+1 ,3 ); 1258 strcpy_n1 ( &(S[11]),sheetID ,3 ); 1259 PutInteger ( &(S[14]),nStrands,2 ); 1260 strand[i]->PDBASCIIDump ( S ); 1261 f.WriteLine ( S ); 1262 } 1263 } 1264 OrderSheet()1265 void Sheet::OrderSheet() { 1266 int i,k; 1267 PPStrand strand1; 1268 k = 0; 1269 for (i=0;i<nStrands;i++) 1270 if (strand[i]) k++; 1271 if (k<nStrands) { 1272 strand1 = new PStrand[k]; 1273 k = 0; 1274 for (i=0;i<nStrands;i++) 1275 if (strand[i]) strand1[k++] = strand[i]; 1276 if (strand) delete[] strand; 1277 strand = strand1; 1278 nStrands = k; 1279 } 1280 } 1281 MakeCIF(mmcif::PData CIF)1282 void Sheet::MakeCIF ( mmcif::PData CIF ) { 1283 mmcif::PLoop Loop; 1284 int RC; 1285 int i; 1286 bool isSense; 1287 1288 OrderSheet(); 1289 1290 RC = CIF->AddLoop ( CIFCAT_STRUCT_SHEET,Loop ); 1291 if (RC!=mmcif::CIFRC_Ok) { 1292 // the category was (re)created, provide tags 1293 Loop->AddLoopTag ( CIFTAG_SHEET_ID ); 1294 Loop->AddLoopTag ( CIFTAG_NUMBER_STRANDS ); 1295 } 1296 Loop->AddString ( sheetID ); 1297 Loop->AddInteger ( nStrands ); 1298 1299 for (i=0;i<nStrands;i++) { 1300 strand[i]->MakeCIF ( CIF ); 1301 if (strand[i]->sense!=0) isSense = true; 1302 } 1303 1304 if (nStrands>1) { 1305 1306 if (isSense) { 1307 RC = CIF->AddLoop ( CIFCAT_STRUCT_SHEET_ORDER,Loop ); 1308 if (RC!=mmcif::CIFRC_Ok) { 1309 // the category was (re)created, provide tags 1310 Loop->AddLoopTag ( CIFTAG_SHEET_ID ); 1311 Loop->AddLoopTag ( CIFTAG_RANGE_ID_1 ); 1312 Loop->AddLoopTag ( CIFTAG_RANGE_ID_2 ); 1313 Loop->AddLoopTag ( CIFTAG_SENSE ); 1314 } 1315 for (i=1;i<nStrands;i++) { 1316 Loop->AddString ( sheetID ); 1317 Loop->AddInteger ( strand[i-1]->strandNo ); 1318 Loop->AddInteger ( strand[i] ->strandNo ); 1319 if (strand[i]->sense>0) 1320 Loop->AddString ( pstr("parallel") ); 1321 else Loop->AddString ( pstr("anti-parallel") ); 1322 } 1323 } 1324 1325 RC = CIF->AddLoop ( CIFCAT_STRUCT_SHEET_HBOND,Loop ); 1326 if (RC!=mmcif::CIFRC_Ok) { 1327 // the category was (re)created, provide tags 1328 Loop->AddLoopTag ( CIFTAG_SHEET_ID ); 1329 Loop->AddLoopTag ( CIFTAG_RANGE_ID_1 ); 1330 Loop->AddLoopTag ( CIFTAG_RANGE_ID_2 ); 1331 Loop->AddLoopTag ( CIFTAG_RANGE_1_BEG_LABEL_ATOM_ID ); 1332 Loop->AddLoopTag ( CIFTAG_NDB_RANGE_1_BEG_LABEL_COMP_ID ); 1333 Loop->AddLoopTag ( CIFTAG_NDB_RANGE_1_BEG_LABEL_ASYM_ID ); 1334 Loop->AddLoopTag ( CIFTAG_RANGE_1_BEG_LABEL_SEQ_ID ); 1335 Loop->AddLoopTag ( CIFTAG_NDB_RANGE_1_BEG_LABEL_INS_CODE ); 1336 Loop->AddLoopTag ( CIFTAG_RANGE_1_END_LABEL_ATOM_ID ); 1337 Loop->AddLoopTag ( CIFTAG_NDB_RANGE_1_END_LABEL_COMP_ID ); 1338 Loop->AddLoopTag ( CIFTAG_NDB_RANGE_1_END_LABEL_ASYM_ID ); 1339 Loop->AddLoopTag ( CIFTAG_RANGE_1_END_LABEL_SEQ_ID ); 1340 Loop->AddLoopTag ( CIFTAG_NDB_RANGE_1_END_LABEL_INS_CODE ); 1341 } 1342 for (i=1;i<nStrands;i++) { 1343 Loop->AddString ( sheetID ); 1344 Loop->AddInteger ( strand[i-1]->strandNo ); 1345 Loop->AddInteger ( strand[i]->strandNo ); 1346 Loop->AddString ( strand[i]->curAtom ); 1347 Loop->AddString ( strand[i]->curResName ); 1348 Loop->AddString ( strand[i]->curChainID ); 1349 Loop->AddInteger ( strand[i]->curResSeq ); 1350 Loop->AddString ( strand[i]->curICode ,true ); 1351 Loop->AddString ( strand[i]->prevAtom ); 1352 Loop->AddString ( strand[i]->prevResName ); 1353 Loop->AddString ( strand[i]->prevChainID ); 1354 Loop->AddInteger ( strand[i]->prevResSeq ); 1355 Loop->AddString ( strand[i]->prevICode,true ); 1356 } 1357 } 1358 1359 } 1360 1361 ConvertPDBASCII(cpstr S)1362 ERROR_CODE Sheet::ConvertPDBASCII ( cpstr S ) { 1363 int i,k,ns; 1364 SheetID SID; 1365 PPStrand strand1; 1366 1367 GetInteger ( k ,&(S[7]) ,3 ); 1368 strcpy_ncss ( SID,&(S[11]),3 ); 1369 GetInteger ( ns ,&(S[14]),2 ); 1370 1371 // if (!SID[0]) return Error_NoSheetID; 1372 if (!sheetID[0]) strcpy ( sheetID,SID ); 1373 else if (strcmp(sheetID,SID)) 1374 return Error_WrongSheetID; 1375 1376 if (k<=0) return Error_WrongStrandNo; 1377 1378 ns = IMax(k,ns); 1379 if (!strand) { 1380 strand = new PStrand[ns]; 1381 for (i=0;i<ns;i++) 1382 strand[i] = NULL; 1383 } else if (ns>nStrands) { 1384 strand1 = new PStrand[ns]; 1385 for (i=0;i<nStrands;i++) 1386 strand1[i] = strand[i]; 1387 for (i=nStrands;i<ns;i++) 1388 strand1[i] = NULL; 1389 if (strand) delete[] strand; 1390 strand = strand1; 1391 } 1392 nStrands = ns; 1393 1394 k--; 1395 if (!strand[k]) strand[k] = new Strand(); 1396 1397 return strand[k]->ConvertPDBASCII ( S ); 1398 1399 } 1400 TryStrand(int strand_no)1401 void Sheet::TryStrand ( int strand_no ) { 1402 int i,k; 1403 PPStrand strand1; 1404 k = -1; 1405 for (i=0;(i<nStrands) && (k<0);i++) 1406 if (strand[i]) 1407 if (strand[i]->strandNo==strand_no) k = i; 1408 if (k<0) { 1409 strand1 = new PStrand[nStrands+1]; 1410 for (i=0;i<nStrands;i++) 1411 strand1[i] = strand[i]; 1412 if (strand) delete[] strand; 1413 strand = strand1; 1414 strand[nStrands] = new Strand(); 1415 strand[nStrands]->strandNo = strand_no; 1416 nStrands++; 1417 } 1418 } 1419 1420 CIFFindStrands(mmcif::PData CIF,cpstr Category)1421 void Sheet::CIFFindStrands ( mmcif::PData CIF, cpstr Category ) { 1422 // just look for all strands mentioned for the sheet 1423 mmcif::PLoop Loop; 1424 pstr F; 1425 int RC,i,l,sNo; 1426 Loop = CIF->GetLoop ( Category ); 1427 if (Loop) { 1428 l = Loop->GetLoopLength(); 1429 for (i=0;i<l;i++) { 1430 F = Loop->GetString ( CIFTAG_SHEET_ID,i,RC ); 1431 if (F && (!RC)) { 1432 if (!strcmp(F,sheetID)) { 1433 if (!Loop->GetInteger(sNo,CIFTAG_ID,i)) 1434 TryStrand ( sNo ); 1435 if (!Loop->GetInteger(sNo,CIFTAG_RANGE_ID_1,i)) 1436 TryStrand ( sNo ); 1437 if (!Loop->GetInteger(sNo,CIFTAG_RANGE_ID_2,i)) 1438 TryStrand ( sNo ); 1439 } 1440 } 1441 } 1442 } 1443 } 1444 GetStrand(int strand_no)1445 int Sheet::GetStrand ( int strand_no ) { 1446 int i; 1447 for (i=0;i<nStrands;i++) 1448 if (strand[i]) { 1449 if (strand[i]->strandNo==strand_no) 1450 return i; 1451 } 1452 return -1; 1453 } 1454 GetCIF(mmcif::PData CIF)1455 int Sheet::GetCIF ( mmcif::PData CIF ) { 1456 mmcif::PLoop Loop; 1457 int i,ns,l,k,k2,RC,sNo; 1458 pstr F; 1459 ivector pair; 1460 bool Ok; 1461 1462 pair = NULL; 1463 1464 // First find all strands and create 1465 // the corresponding classes. The CIF fields 1466 // are not removed at this stage. 1467 1468 CIFFindStrands ( CIF,CIFCAT_STRUCT_SHEET_ORDER ); 1469 CIFFindStrands ( CIF,CIFCAT_STRUCT_SHEET_RANGE ); 1470 CIFFindStrands ( CIF,CIFCAT_STRUCT_SHEET_HBOND ); 1471 1472 // Check number of strands 1473 Loop = CIF->GetLoop ( CIFCAT_STRUCT_SHEET ); 1474 if (Loop) { 1475 l = Loop->GetLoopLength(); 1476 i = 0; 1477 while (i<l) { 1478 F = Loop->GetString ( CIFTAG_SHEET_ID,i,RC ); 1479 if (F && (!RC)) { 1480 if (!strcmp(F,sheetID)) { 1481 RC = CIFGetInteger1 ( ns,Loop,CIFTAG_NUMBER_STRANDS,i ); 1482 if ((!RC) && (ns!=nStrands)) 1483 return Error_WrongNumberOfStrands; 1484 Loop->DeleteRow ( i ); 1485 i = l+100; // break loop 1486 } 1487 } 1488 i++; 1489 } 1490 } 1491 1492 // Read each strand 1493 RC = 0; 1494 for (i=0;(i<nStrands) && (!RC);i++) 1495 RC = strand[i]->GetCIF ( CIF,sheetID ); 1496 1497 if (RC) return RC; 1498 1499 if (nStrands>1) { 1500 1501 GetVectorMemory ( pair,nStrands,0 ); 1502 for (i=0;i<nStrands;i++) 1503 pair[i] = -1; 1504 1505 Loop = CIF->GetLoop ( CIFCAT_STRUCT_SHEET_ORDER ); 1506 if (Loop) { 1507 Ok = true; 1508 l = Loop->GetLoopLength(); 1509 for (i=0;(i<l) && Ok;i++) { 1510 F = Loop->GetString ( CIFTAG_SHEET_ID,i,RC ); 1511 if (F && (!RC)) { 1512 if (!strcmp(F,sheetID)) { 1513 if (!Loop->GetInteger(sNo,CIFTAG_RANGE_ID_1,i)) { 1514 k = GetStrand ( sNo ); 1515 if ((k>=0) && 1516 (!Loop->GetInteger(sNo,CIFTAG_RANGE_ID_2,i))) { 1517 pair[k] = GetStrand ( sNo ); 1518 if (pair[k]>=0) { 1519 F = Loop->GetString ( CIFTAG_SENSE,i,RC ); 1520 if (F && (!RC)) { 1521 if (!strcasecmp(F,"anti-parallel")) 1522 strand[pair[k]]->sense = -1; 1523 else if (!strcasecmp(F,"parallel")) 1524 strand[pair[k]]->sense = 1; 1525 } 1526 Loop->DeleteRow ( i ); 1527 } else 1528 Ok = false; 1529 } else 1530 Ok = false; 1531 } else 1532 Ok = false; 1533 } 1534 } 1535 } 1536 if (!Ok) { 1537 FreeVectorMemory ( pair,0 ); 1538 return Error_WrongSheetOrder; 1539 } 1540 } 1541 1542 Loop = CIF->GetLoop ( CIFCAT_STRUCT_SHEET_HBOND ); 1543 if (Loop) { 1544 Ok = true; 1545 l = Loop->GetLoopLength(); 1546 for (i=0;(i<l) && Ok;i++) { 1547 F = Loop->GetString ( CIFTAG_SHEET_ID,i,RC ); 1548 if (F && (!RC)) { 1549 if (!strcmp(F,sheetID)) { 1550 if (!Loop->GetInteger(sNo,CIFTAG_RANGE_ID_1,i)) { 1551 k = GetStrand ( sNo ); 1552 if ((k>=0) && 1553 (!Loop->GetInteger(sNo,CIFTAG_RANGE_ID_1,i))) { 1554 k2 = GetStrand ( sNo ); 1555 if (k2>=0) { 1556 if (pair[k]==k2) { 1557 CIFGetString ( strand[k2]->curAtom,Loop, 1558 CIFTAG_RANGE_1_BEG_LABEL_ATOM_ID, 1559 i,sizeof(strand[k2]->curAtom), 1560 pstr(" ") ); 1561 CIFGetString ( strand[k2]->curResName,Loop, 1562 CIFTAG_NDB_RANGE_1_BEG_LABEL_COMP_ID, 1563 i,sizeof(strand[k2]->curResName), 1564 pstr(" ") ); 1565 CIFGetString ( strand[k2]->curChainID,Loop, 1566 CIFTAG_NDB_RANGE_1_BEG_LABEL_ASYM_ID, 1567 i,sizeof(strand[k2]->curChainID), 1568 pstr(" ") ); 1569 if (CIFGetInteger(strand[k2]->curResSeq,Loop, 1570 CIFTAG_RANGE_1_BEG_LABEL_SEQ_ID,i)) { 1571 FreeVectorMemory ( pair,0 ); 1572 return i; 1573 } 1574 CIFGetString ( strand[k2]->curICode,Loop, 1575 CIFTAG_NDB_RANGE_1_BEG_LABEL_INS_CODE, 1576 i,sizeof(strand[k2]->curICode), 1577 pstr(" ") ); 1578 CIFGetString ( strand[k2]->prevAtom,Loop, 1579 CIFTAG_RANGE_1_END_LABEL_ATOM_ID, 1580 i,sizeof(strand[k2]->prevAtom), 1581 pstr(" ") ); 1582 CIFGetString ( strand[k2]->prevResName,Loop, 1583 CIFTAG_NDB_RANGE_1_END_LABEL_COMP_ID, 1584 i,sizeof(strand[k2]->prevResName), 1585 pstr(" ") ); 1586 CIFGetString ( strand[k2]->prevChainID,Loop, 1587 CIFTAG_NDB_RANGE_1_END_LABEL_ASYM_ID, 1588 i,sizeof(strand[k2]->prevChainID), 1589 pstr(" ") ); 1590 if (CIFGetInteger(strand[k2]->prevResSeq,Loop, 1591 CIFTAG_RANGE_1_END_LABEL_SEQ_ID,i)) { 1592 FreeVectorMemory ( pair,0 ); 1593 return i; 1594 } 1595 CIFGetString ( strand[k2]->prevICode,Loop, 1596 CIFTAG_NDB_RANGE_1_END_LABEL_INS_CODE, 1597 i,sizeof(strand[k2]->prevICode), 1598 pstr(" ") ); 1599 Loop->DeleteRow ( i ); 1600 } else 1601 Ok = false; 1602 } else 1603 Ok = false; 1604 } else 1605 Ok = false; 1606 } else 1607 Ok = false; 1608 } 1609 } 1610 } 1611 if (!Ok) { 1612 FreeVectorMemory ( pair,0 ); 1613 return Error_HBondInconsistency; 1614 } 1615 } 1616 } 1617 1618 FreeVectorMemory ( pair,0 ); 1619 1620 return 0; 1621 1622 } 1623 1624 Copy(PSheet Sheet)1625 void Sheet::Copy ( PSheet Sheet ) { 1626 int i; 1627 FreeMemory(); 1628 nStrands = Sheet->nStrands; 1629 if (nStrands>0) { 1630 strand = new PStrand[nStrands]; 1631 for (i=0;i<nStrands;i++) 1632 if (Sheet->strand[i]) { 1633 strand[i] = new Strand(); 1634 strand[i]->Copy ( Sheet->strand[i] ); 1635 } else 1636 strand[i] = NULL; 1637 } 1638 strcpy ( sheetID,Sheet->sheetID ); 1639 } 1640 write(io::RFile f)1641 void Sheet::write ( io::RFile f ) { 1642 int i; 1643 byte Version=1; 1644 f.WriteByte ( &Version ); 1645 f.WriteInt ( &nStrands ); 1646 for (i=0;i<nStrands;i++) 1647 StreamWrite ( f,strand[i] ); 1648 f.WriteTerLine ( sheetID,false ); 1649 } 1650 read(io::RFile f)1651 void Sheet::read ( io::RFile f ) { 1652 int i; 1653 byte Version; 1654 FreeMemory(); 1655 f.ReadByte ( &Version ); 1656 f.ReadInt ( &nStrands ); 1657 if (nStrands>0) { 1658 strand = new PStrand[nStrands]; 1659 for (i=0;i<nStrands;i++) { 1660 strand[i] = NULL; 1661 StreamRead ( f,strand[i] ); 1662 } 1663 } 1664 f.ReadTerLine ( sheetID,false ); 1665 } 1666 MakeStreamFunctions(Sheet)1667 MakeStreamFunctions(Sheet) 1668 1669 1670 1671 // ==================== Sheets ============================ 1672 1673 1674 Sheets::Sheets() : io::Stream() { 1675 InitSheets(); 1676 } 1677 1678 Sheets(io::RPStream Object)1679 Sheets::Sheets ( io::RPStream Object ) : io::Stream ( Object ) { 1680 InitSheets(); 1681 } 1682 1683 ~Sheets()1684 Sheets::~Sheets() { 1685 FreeMemory(); 1686 } 1687 1688 InitSheets()1689 void Sheets::InitSheets() { 1690 nSheets = 0; 1691 sheet = NULL; 1692 } 1693 1694 FreeMemory()1695 void Sheets::FreeMemory() { 1696 int i; 1697 if (sheet) { 1698 for (i=0;i<nSheets;i++) 1699 if (sheet[i]) delete sheet[i]; 1700 delete[] sheet; 1701 sheet = NULL; 1702 } 1703 nSheets = 0; 1704 } 1705 1706 PDBASCIIDump(io::RFile f)1707 void Sheets::PDBASCIIDump ( io::RFile f ) { 1708 int i; 1709 if (sheet) 1710 for (i=0;i<nSheets;i++) 1711 if (sheet[i]) sheet[i]->PDBASCIIDump ( f ); 1712 } 1713 1714 MakeCIF(mmcif::PData CIF)1715 void Sheets::MakeCIF ( mmcif::PData CIF ) { 1716 int i; 1717 if (sheet) 1718 for (i=0;i<nSheets;i++) 1719 if (sheet[i]) sheet[i]->MakeCIF ( CIF ); 1720 } 1721 1722 ConvertPDBASCII(cpstr S)1723 ERROR_CODE Sheets::ConvertPDBASCII ( cpstr S ) { 1724 PPSheet sheet1; 1725 SheetID sheetID; 1726 int i,k; 1727 strcpy_ncss ( sheetID,&(S[11]),3 ); 1728 // if (!sheetID[0]) return Error_NoSheetID; 1729 k = -1; 1730 for (i=0;i<nSheets;i++) 1731 if (sheet[i]) { 1732 if (!strcmp(sheetID,sheet[i]->sheetID)) { 1733 k = i; 1734 break; 1735 } 1736 } 1737 if (k<0) { 1738 sheet1 = new PSheet[nSheets+1]; 1739 for (i=0;i<nSheets;i++) 1740 sheet1[i] = sheet[i]; 1741 if (sheet) delete[] sheet; 1742 sheet = sheet1; 1743 sheet[nSheets] = new Sheet(); 1744 k = nSheets; 1745 nSheets++; 1746 } 1747 return sheet[k]->ConvertPDBASCII ( S ); 1748 } 1749 1750 CIFFindSheets(mmcif::PData CIF,cpstr Category)1751 void Sheets::CIFFindSheets ( mmcif::PData CIF, cpstr Category ) { 1752 mmcif::PLoop Loop; 1753 int RC,i,j,k,l; 1754 pstr F; 1755 PPSheet sheet1; 1756 Loop = CIF->GetLoop ( Category ); 1757 if (Loop) { 1758 l = Loop->GetLoopLength(); 1759 for (i=0;i<l;i++) { 1760 F = Loop->GetString ( CIFTAG_SHEET_ID,i,RC ); 1761 if (F && (!RC)) { 1762 k = -1; 1763 j = 0; 1764 while ((j<nSheets) && (k<0)) { 1765 if (sheet[j]) { 1766 if (!strcmp(F,sheet[j]->sheetID)) k = j; 1767 } 1768 j++; 1769 } 1770 if (k<0) { 1771 sheet1 = new PSheet[nSheets+1]; 1772 for (i=0;i<nSheets;i++) 1773 sheet1[i] = sheet[i]; 1774 if (sheet) delete[] sheet; 1775 sheet = sheet1; 1776 sheet[nSheets] = new Sheet(); 1777 strcpy ( sheet[nSheets]->sheetID,F ); 1778 nSheets++; 1779 } 1780 } 1781 } 1782 } 1783 } 1784 GetCIF(mmcif::PData CIF)1785 int Sheets::GetCIF ( mmcif::PData CIF ) { 1786 int i,RC; 1787 1788 FreeMemory(); 1789 1790 // First find all sheet names and create 1791 // the corresponding classes. The CIF fields 1792 // are not removed at this stage. 1793 1794 CIFFindSheets ( CIF,CIFCAT_STRUCT_SHEET ); 1795 CIFFindSheets ( CIF,CIFCAT_STRUCT_SHEET_ORDER ); 1796 CIFFindSheets ( CIF,CIFCAT_STRUCT_SHEET_RANGE ); 1797 CIFFindSheets ( CIF,CIFCAT_STRUCT_SHEET_HBOND ); 1798 1799 // Read each sheet 1800 i = 0; 1801 RC = 0; 1802 while ((i<nSheets) && (!RC)) { 1803 RC = sheet[i]->GetCIF ( CIF ); 1804 i++; 1805 } 1806 1807 return RC; 1808 1809 } 1810 1811 Copy(PSheets Sheets)1812 void Sheets::Copy ( PSheets Sheets ) { 1813 int i; 1814 FreeMemory(); 1815 if (Sheets->nSheets>0) { 1816 nSheets = Sheets->nSheets; 1817 sheet = new PSheet[nSheets]; 1818 for (i=0;i<nSheets;i++) 1819 if (Sheets->sheet[i]) { 1820 sheet[i] = new Sheet(); 1821 sheet[i]->Copy ( Sheets->sheet[i] ); 1822 } else 1823 sheet[i] = NULL; 1824 } 1825 } 1826 1827 write(io::RFile f)1828 void Sheets::write ( io::RFile f ) { 1829 int i; 1830 byte Version=1; 1831 f.WriteByte ( &Version ); 1832 f.WriteInt ( &nSheets ); 1833 for (i=0;i<nSheets;i++) 1834 StreamWrite ( f,sheet[i] ); 1835 } 1836 1837 read(io::RFile f)1838 void Sheets::read ( io::RFile f ) { 1839 int i; 1840 byte Version; 1841 FreeMemory(); 1842 f.ReadByte ( &Version ); 1843 f.ReadInt ( &nSheets ); 1844 if (nSheets>0) { 1845 sheet = new PSheet[nSheets]; 1846 for (i=0;i<nSheets;i++) { 1847 sheet[i] = NULL; 1848 StreamRead ( f,sheet[i] ); 1849 } 1850 } 1851 } 1852 1853 MakeStreamFunctions(Sheets)1854 MakeStreamFunctions(Sheets) 1855 1856 1857 1858 // ================ Turn =================== 1859 1860 Turn::Turn() : ContainerClass() { 1861 InitTurn(); 1862 } 1863 Turn(cpstr S)1864 Turn::Turn ( cpstr S ) : ContainerClass() { 1865 InitTurn(); 1866 ConvertPDBASCII ( S ); 1867 } 1868 Turn(io::RPStream Object)1869 Turn::Turn ( io::RPStream Object ) : ContainerClass(Object) { 1870 InitTurn(); 1871 } 1872 ~Turn()1873 Turn::~Turn() { 1874 if (comment) delete[] comment; 1875 } 1876 InitTurn()1877 void Turn::InitTurn() { 1878 serNum = 0; // serial number 1879 strcpy ( turnID ,"---" ); // turn ID 1880 strcpy ( initResName,"---" ); // name of the turn's initial residue 1881 strcpy ( initChainID," " ); // chain ID for the chain 1882 // containing the turn 1883 initSeqNum = 0; // sequence number of the initial 1884 // residue 1885 strcpy ( initICode ," " ); // insertion code of the initial 1886 // residue 1887 strcpy ( endResName ,"---" ); // name of the turn's terminal residue 1888 strcpy ( endChainID ," " ); // chain ID for the chain 1889 // containing the turn 1890 endSeqNum = 0; // sequence number of the terminal 1891 // residue 1892 strcpy ( endICode ," " ); // insertion code of the terminal 1893 // residue 1894 comment = NULL; // comment about the helix 1895 } 1896 PDBASCIIDump(pstr S,int N)1897 void Turn::PDBASCIIDump ( pstr S, int N ) { 1898 UNUSED_ARGUMENT(N); 1899 // makes the ASCII PDB OBSLTE line number N 1900 // from the class' data 1901 strcpy ( S,"TURN" ); 1902 PadSpaces ( S,80 ); 1903 PutInteger ( &(S[7]) ,serNum ,3 ); 1904 strcpy_n1 ( &(S[11]),turnID ,3 ); 1905 strcpy_n1 ( &(S[15]),initResName,3 ); 1906 strcpy_n1 ( &(S[19]),initChainID,1 ); 1907 PutIntIns ( &(S[20]),initSeqNum ,4,initICode ); 1908 strcpy_n1 ( &(S[26]),endResName ,3 ); 1909 strcpy_n1 ( &(S[30]),endChainID ,1 ); 1910 PutIntIns ( &(S[31]),endSeqNum ,4,endICode ); 1911 if (comment) 1912 strcpy_n ( &(S[40]),comment ,30 ); 1913 } 1914 1915 1916 #define TurnTypeID "TURN_P" 1917 MakeCIF(mmcif::PData CIF,int N)1918 void Turn::MakeCIF ( mmcif::PData CIF, int N ) { 1919 UNUSED_ARGUMENT(N); 1920 mmcif::PLoop Loop; 1921 int RC; 1922 RC = CIF->AddLoop ( CIFCAT_STRUCT_CONF,Loop ); 1923 if (RC!=mmcif::CIFRC_Ok) 1924 // the category was (re)created, provide tags 1925 AddStructConfTags ( Loop ); 1926 Loop->AddString ( pstr(TurnTypeID) ); 1927 Loop->AddInteger ( serNum ); 1928 Loop->AddString ( turnID ); 1929 Loop->AddString ( initResName ); 1930 Loop->AddString ( initChainID ); 1931 Loop->AddInteger ( initSeqNum ); 1932 Loop->AddString ( initICode,true ); 1933 Loop->AddString ( endResName ); 1934 Loop->AddString ( endChainID ); 1935 Loop->AddInteger ( endSeqNum ); 1936 Loop->AddString ( endICode ,true ); 1937 Loop->AddNoData ( mmcif::CIF_NODATA_QUESTION ); 1938 Loop->AddString ( comment ); 1939 Loop->AddNoData ( mmcif::CIF_NODATA_QUESTION ); 1940 } 1941 ConvertPDBASCII(cpstr S)1942 ERROR_CODE Turn::ConvertPDBASCII ( cpstr S ) { 1943 char L[100]; 1944 GetInteger ( serNum ,&(S[7]) ,3 ); 1945 strcpy_ncss ( turnID ,&(S[11]),3 ); 1946 strcpy_ncss ( initResName,&(S[15]),3 ); 1947 strcpy_ncss ( initChainID,&(S[19]),1 ); 1948 GetIntIns ( initSeqNum,initICode,&(S[20]),4 ); 1949 strcpy_ncss ( endResName ,&(S[26]),3 ); 1950 strcpy_ncss ( endChainID ,&(S[30]),1 ); 1951 GetIntIns ( endSeqNum ,endICode ,&(S[31]),4 ); 1952 strcpy_ncss ( L ,&(S[40]),30 ); 1953 CreateCopy ( comment ,L ); 1954 return Error_NoError; 1955 } 1956 GetCIF(mmcif::PData CIF,int & n)1957 ERROR_CODE Turn::GetCIF ( mmcif::PData CIF, int & n ) { 1958 mmcif::PLoop Loop; 1959 int RC,l; 1960 pstr F; 1961 bool Done; 1962 ERROR_CODE rc; 1963 1964 Loop = CIF->GetLoop ( CIFCAT_STRUCT_CONF ); 1965 if (!Loop) { 1966 n = -1; // signal to finish processing of this structure 1967 return Error_EmptyCIF; 1968 } 1969 1970 l = Loop->GetLoopLength(); 1971 Done = n>=l; 1972 while (!Done) { 1973 F = Loop->GetString ( CIFTAG_CONF_TYPE_ID,n,RC ); 1974 if ((!RC) && F) Done = (strcmp(F,TurnTypeID)==0); 1975 else Done = false; 1976 if (!Done) { 1977 n++; 1978 Done = n>=l; 1979 } 1980 } 1981 1982 if (n>=l) { 1983 n = -1; // finish processing of Turn 1984 return Error_EmptyCIF; 1985 } 1986 1987 Loop->DeleteField ( CIFTAG_CONF_TYPE_ID,n ); 1988 1989 rc = CIFGetInteger ( serNum,Loop,CIFTAG_ID,n ); 1990 if (rc==Error_NoData) return Error_EmptyCIF; 1991 if (rc!=Error_NoError) return rc; 1992 1993 CIFGetString ( turnID,Loop,CIFTAG_PDB_ID,n, 1994 sizeof(turnID),pstr(" ") ); 1995 1996 CIFGetString ( initResName,Loop,CIFTAG_BEG_LABEL_COMP_ID, 1997 n,sizeof(initResName),pstr(" ") ); 1998 CIFGetString ( initChainID,Loop,CIFTAG_BEG_LABEL_ASYM_ID, 1999 n,sizeof(initChainID),pstr(" ") ); 2000 CIFGetString ( initICode ,Loop,CIFTAG_NDB_BEG_LABEL_INS_CODE_PDB, 2001 n,sizeof(initICode),pstr(" ") ); 2002 rc = CIFGetInteger ( initSeqNum,Loop,CIFTAG_BEG_LABEL_SEQ_ID,n ); 2003 if (rc==Error_NoData) return Error_EmptyCIF; 2004 if (rc!=Error_NoError) return rc; 2005 2006 CIFGetString ( endResName,Loop,CIFTAG_END_LABEL_COMP_ID, 2007 n,sizeof(endResName),pstr(" ") ); 2008 CIFGetString ( endChainID,Loop,CIFTAG_END_LABEL_ASYM_ID, 2009 n,sizeof(endChainID),pstr(" ") ); 2010 CIFGetString ( endICode ,Loop,CIFTAG_NDB_END_LABEL_INS_CODE_PDB, 2011 n,sizeof(endICode),pstr(" ") ); 2012 rc = CIFGetInteger ( endSeqNum,Loop,CIFTAG_END_LABEL_SEQ_ID,n ); 2013 if (rc==Error_NoData) return Error_EmptyCIF; 2014 if (rc!=Error_NoError) return rc; 2015 2016 CreateCopy ( comment,Loop->GetString(CIFTAG_DETAILS,n,RC)); 2017 Loop->DeleteField ( CIFTAG_DETAILS,n ); 2018 2019 n++; 2020 2021 return Error_NoError; 2022 2023 } 2024 Copy(PContainerClass Turn)2025 void Turn::Copy ( PContainerClass Turn ) { 2026 serNum = PTurn(Turn)->serNum; 2027 initSeqNum = PTurn(Turn)->initSeqNum; 2028 endSeqNum = PTurn(Turn)->endSeqNum; 2029 strcpy ( turnID ,PTurn(Turn)->turnID ); 2030 strcpy ( initResName,PTurn(Turn)->initResName ); 2031 strcpy ( initChainID,PTurn(Turn)->initChainID ); 2032 strcpy ( initICode ,PTurn(Turn)->initICode ); 2033 strcpy ( endResName ,PTurn(Turn)->endResName ); 2034 strcpy ( endChainID ,PTurn(Turn)->endChainID ); 2035 strcpy ( endICode ,PTurn(Turn)->endICode ); 2036 CreateCopy ( comment,PTurn(Turn)->comment ); 2037 } 2038 write(io::RFile f)2039 void Turn::write ( io::RFile f ) { 2040 byte Version=1; 2041 f.WriteByte ( &Version ); 2042 f.WriteInt ( &serNum ); 2043 f.WriteInt ( &initSeqNum ); 2044 f.WriteInt ( &endSeqNum ); 2045 f.WriteTerLine ( turnID ,false ); 2046 f.WriteTerLine ( initResName,false ); 2047 f.WriteTerLine ( initChainID,false ); 2048 f.WriteTerLine ( initICode ,false ); 2049 f.WriteTerLine ( endResName ,false ); 2050 f.WriteTerLine ( endChainID ,false ); 2051 f.WriteTerLine ( endICode ,false ); 2052 f.CreateWrite ( comment ); 2053 } 2054 read(io::RFile f)2055 void Turn::read ( io::RFile f ) { 2056 byte Version; 2057 f.ReadByte ( &Version ); 2058 f.ReadInt ( &serNum ); 2059 f.ReadInt ( &initSeqNum ); 2060 f.ReadInt ( &endSeqNum ); 2061 f.ReadTerLine ( turnID ,false ); 2062 f.ReadTerLine ( initResName,false ); 2063 f.ReadTerLine ( initChainID,false ); 2064 f.ReadTerLine ( initICode ,false ); 2065 f.ReadTerLine ( endResName ,false ); 2066 f.ReadTerLine ( endChainID ,false ); 2067 f.ReadTerLine ( endICode ,false ); 2068 f.CreateRead ( comment ); 2069 } 2070 MakeStreamFunctions(Turn)2071 MakeStreamFunctions(Turn) 2072 2073 2074 // =================== LinkContainer ======================== 2075 2076 PContainerClass LinkContainer::MakeContainerClass ( int ClassID ) { 2077 switch (ClassID) { 2078 default : 2079 case ClassID_Template : return 2080 ClassContainer::MakeContainerClass(ClassID); 2081 case ClassID_Link : return new Link(); 2082 } 2083 } 2084 MakeStreamFunctions(LinkContainer)2085 MakeStreamFunctions(LinkContainer) 2086 2087 2088 2089 // ======================== Link =========================== 2090 2091 Link::Link() : ContainerClass() { 2092 InitLink(); 2093 } 2094 Link(cpstr S)2095 Link::Link ( cpstr S ) : ContainerClass() { 2096 InitLink(); 2097 ConvertPDBASCII ( S ); 2098 } 2099 Link(io::RPStream Object)2100 Link::Link ( io::RPStream Object ) : ContainerClass(Object) { 2101 InitLink(); 2102 } 2103 ~Link()2104 Link::~Link() {} 2105 InitLink()2106 void Link::InitLink() { 2107 strcpy ( atName1 ,"----" ); // name of 1st linked atom 2108 strcpy ( aloc1 ," " ); // alternative location of 1st atom 2109 strcpy ( resName1,"---" ); // residue name of 1st linked atom 2110 strcpy ( chainID1," " ); // chain ID of 1st linked atom 2111 seqNum1 = 0; // sequence number of 1st linked atom 2112 strcpy ( insCode1," " ); // insertion code of 1st linked atom 2113 strcpy ( atName2 ,"----" ); // name of 2nd linked atom 2114 strcpy ( aloc2 ," " ); // alternative location of 2nd atom 2115 strcpy ( resName2,"---" ); // residue name of 2nd linked atom 2116 strcpy ( chainID2," " ); // chain ID of 2nd linked atom 2117 seqNum2 = 0; // sequence number of 2nd linked atom 2118 strcpy ( insCode2," " ); // insertion code of 2nd linked atom 2119 s1 = 1; // sym id of 1st atom 2120 i1 = 5; 2121 j1 = 5; 2122 k1 = 5; 2123 s2 = 1; // sym id of 2nd atom 2124 i2 = 5; 2125 j2 = 5; 2126 k2 = 5; 2127 dist = -1.0; // no distance 2128 } 2129 2130 PDBASCIIDump(pstr S,int N)2131 void Link::PDBASCIIDump ( pstr S, int N ) { 2132 UNUSED_ARGUMENT(N); 2133 // makes the ASCII PDB OBSLTE line number N 2134 // from the class' data 2135 2136 strcpy ( S,"LINK" ); 2137 PadSpaces ( S,80 ); 2138 2139 strcpy_n1 ( &(S[12]),atName1 ,4 ); 2140 strcpy_n1 ( &(S[16]),aloc1 ,1 ); 2141 strcpy_n1 ( &(S[17]),resName1,3 ); 2142 strcpy_n1 ( &(S[21]),chainID1,1 ); 2143 PutIntIns ( &(S[22]),seqNum1 ,4,insCode1 ); 2144 2145 strcpy_n1 ( &(S[42]),atName2 ,4 ); 2146 strcpy_n1 ( &(S[46]),aloc2 ,1 ); 2147 strcpy_n1 ( &(S[47]),resName2,3 ); 2148 strcpy_n1 ( &(S[51]),chainID2,1 ); 2149 PutIntIns ( &(S[52]),seqNum2 ,4,insCode2 ); 2150 2151 PutInteger ( &(S[59]),s1,3 ); 2152 PutInteger ( &(S[62]),i1,1 ); 2153 PutInteger ( &(S[63]),j1,1 ); 2154 PutInteger ( &(S[64]),k1,1 ); 2155 2156 PutInteger ( &(S[66]),s2,3 ); 2157 PutInteger ( &(S[69]),i2,1 ); 2158 PutInteger ( &(S[70]),j2,1 ); 2159 PutInteger ( &(S[71]),k2,1 ); 2160 2161 if (dist>0.0) 2162 PutRealF ( &(S[73]),dist,5,3 ); 2163 2164 } 2165 2166 2167 #define LinkTypeID "LINK" 2168 AddStructConnTags(mmcif::PLoop Loop)2169 void AddStructConnTags ( mmcif::PLoop Loop ) { 2170 2171 Loop->AddLoopTag ( CIFTAG_ID ); 2172 Loop->AddLoopTag ( CIFTAG_CONN_TYPE_ID ); 2173 2174 Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_ATOM_ID ); 2175 Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR1_AUTH_ALT_ID ); 2176 Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_COMP_ID ); 2177 Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_ASYM_ID ); 2178 Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_SEQ_ID ); 2179 Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR1_PDB_INS_CODE ); 2180 2181 Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_ATOM_ID ); 2182 Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR2_AUTH_ALT_ID ); 2183 Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_COMP_ID ); 2184 Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_ASYM_ID ); 2185 Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_SEQ_ID ); 2186 Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR2_PDB_INS_CODE ); 2187 2188 Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_SYMMETRY ); 2189 Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_SYMMETRY ); 2190 2191 Loop->AddLoopTag ( CIFTAG_CONN_DIST ); 2192 2193 } 2194 2195 MakeCIF(mmcif::PData CIF,int N)2196 void Link::MakeCIF ( mmcif::PData CIF, int N ) { 2197 UNUSED_ARGUMENT(N); 2198 mmcif::PLoop Loop; 2199 char S[100]; 2200 int RC; 2201 2202 RC = CIF->AddLoop ( CIFCAT_STRUCT_CONN,Loop ); 2203 if (RC!=mmcif::CIFRC_Ok) // the category was (re)created, provide tags 2204 AddStructConnTags ( Loop ); 2205 2206 Loop->AddString ( "1" ); // should be a counter 2207 Loop->AddString ( pstr(LinkTypeID) ); 2208 2209 Loop->AddString ( atName1 ); 2210 Loop->AddString ( aloc1 ); 2211 Loop->AddString ( resName1 ); 2212 Loop->AddString ( chainID1 ); 2213 Loop->AddInteger ( seqNum1 ); 2214 Loop->AddString ( insCode1 ); 2215 2216 Loop->AddString ( atName2 ); 2217 Loop->AddString ( aloc2 ); 2218 Loop->AddString ( resName2 ); 2219 Loop->AddString ( chainID2 ); 2220 Loop->AddInteger ( seqNum2 ); 2221 Loop->AddString ( insCode2 ); 2222 2223 sprintf ( S,"%i%i%i%i",s1,i1,j1,k1 ); 2224 Loop->AddString ( S ); 2225 sprintf ( S,"%i%i%i%i",s2,i2,j2,k2 ); 2226 Loop->AddString ( S ); 2227 2228 Loop->AddReal ( dist ); 2229 2230 } 2231 ConvertPDBASCII(cpstr S)2232 ERROR_CODE Link::ConvertPDBASCII ( cpstr S ) { 2233 2234 GetString ( atName1 ,&(S[12]),4 ); 2235 strcpy_ncss ( aloc1 ,&(S[16]),1 ); 2236 strcpy_ncss ( resName1,&(S[17]),3 ); 2237 strcpy_ncss ( chainID1,&(S[21]),1 ); 2238 GetIntIns ( seqNum1,insCode1,&(S[22]),4 ); 2239 2240 GetString ( atName2 ,&(S[42]),4 ); 2241 strcpy_ncss ( aloc2 ,&(S[46]),1 ); 2242 strcpy_ncss ( resName2,&(S[47]),3 ); 2243 strcpy_ncss ( chainID2,&(S[51]),1 ); 2244 GetIntIns ( seqNum2,insCode2,&(S[52]),4 ); 2245 2246 GetInteger ( s1,&(S[59]),3 ); 2247 GetInteger ( i1,&(S[62]),1 ); 2248 GetInteger ( j1,&(S[63]),1 ); 2249 GetInteger ( k1,&(S[64]),1 ); 2250 2251 GetInteger ( s2,&(S[66]),3 ); 2252 GetInteger ( i2,&(S[69]),1 ); 2253 GetInteger ( j2,&(S[70]),1 ); 2254 GetInteger ( k2,&(S[71]),1 ); 2255 2256 if (!GetReal(dist,&(S[73]),5)) dist = -1.0; 2257 2258 return Error_NoError; 2259 2260 } 2261 GetCIF(mmcif::PData CIF,int & n)2262 ERROR_CODE Link::GetCIF ( mmcif::PData CIF, int & n ) { 2263 mmcif::PLoop Loop; 2264 pstr F; 2265 char S[100]; 2266 int RC,l; 2267 bool Done; 2268 ERROR_CODE rc; 2269 2270 Loop = CIF->GetLoop ( CIFCAT_STRUCT_CONN ); 2271 if (!Loop) { 2272 n = -1; // signal to finish processing of this structure 2273 return Error_EmptyCIF; 2274 } 2275 2276 l = Loop->GetLoopLength(); 2277 Done = (n>=l); 2278 while (!Done) { 2279 F = Loop->GetString ( CIFTAG_CONN_TYPE_ID,n,RC ); 2280 if ((!RC) && F) Done = (strcmp(F,LinkTypeID)==0); 2281 else Done = false; 2282 if (!Done) { 2283 n++; 2284 Done = (n>=l); 2285 } 2286 } 2287 2288 if (n>=l) { 2289 n = -1; // finish processing of Turn 2290 return Error_EmptyCIF; 2291 } 2292 2293 Loop->DeleteField ( CIFTAG_CONN_TYPE_ID,n ); 2294 2295 // CIFGetInteger ( l,Loop,CIFTAG_ID,n ); 2296 2297 CIFGetString ( atName1,Loop,CIFTAG_CONN_PTNR1_AUTH_ATOM_ID,n, 2298 sizeof(atName1),pstr(" ") ); 2299 CIFGetString ( aloc1,Loop,CIFTAG_CONN_PDBX_PTNR1_AUTH_ALT_ID,n, 2300 sizeof(aloc1),pstr(" ") ); 2301 CIFGetString ( resName1,Loop,CIFTAG_CONN_PTNR1_AUTH_COMP_ID,n, 2302 sizeof(resName1),pstr(" ") ); 2303 CIFGetString ( chainID1,Loop,CIFTAG_CONN_PTNR1_AUTH_ASYM_ID,n, 2304 sizeof(chainID1),pstr(" ") ); 2305 rc = CIFGetInteger ( seqNum1,Loop,CIFTAG_CONN_PTNR1_AUTH_SEQ_ID,n ); 2306 if (rc==Error_NoData) return Error_EmptyCIF; 2307 if (rc!=Error_NoError) return rc; 2308 2309 CIFGetString ( insCode1,Loop,CIFTAG_CONN_PDBX_PTNR1_PDB_INS_CODE, 2310 n,sizeof(insCode1),pstr(" ") ); 2311 2312 CIFGetString ( atName2,Loop,CIFTAG_CONN_PTNR2_AUTH_ATOM_ID,n, 2313 sizeof(atName2),pstr(" ") ); 2314 CIFGetString ( aloc2,Loop,CIFTAG_CONN_PDBX_PTNR2_AUTH_ALT_ID,n, 2315 sizeof(aloc2),pstr(" ") ); 2316 CIFGetString ( resName2,Loop,CIFTAG_CONN_PTNR2_AUTH_COMP_ID,n, 2317 sizeof(resName2),pstr(" ") ); 2318 CIFGetString ( chainID2,Loop,CIFTAG_CONN_PTNR2_AUTH_ASYM_ID,n, 2319 sizeof(chainID2),pstr(" ") ); 2320 rc = CIFGetInteger ( seqNum2,Loop,CIFTAG_CONN_PTNR2_AUTH_SEQ_ID,n ); 2321 if (rc==Error_NoData) return Error_EmptyCIF; 2322 if (rc!=Error_NoError) return rc; 2323 2324 CIFGetString ( insCode2,Loop,CIFTAG_CONN_PDBX_PTNR2_PDB_INS_CODE, 2325 n,sizeof(insCode2),pstr(" ") ); 2326 2327 CIFGetString ( S,Loop,CIFTAG_CONN_PTNR1_SYMMETRY,n, 2328 sizeof(S),pstr("") ); 2329 if (S[0]) { 2330 l = strlen(S)-1; 2331 k1 = int(S[l--]) - int('0'); 2332 j1 = int(S[l--]) - int('0'); 2333 i1 = int(S[l--]) - int('0'); 2334 S[l] = char(0); 2335 s1 = atoi(S); 2336 } 2337 2338 CIFGetString ( S,Loop,CIFTAG_CONN_PTNR2_SYMMETRY,n, 2339 sizeof(S),pstr("") ); 2340 if (S[0]) { 2341 l = strlen(S)-1; 2342 k2 = int(S[l--]) - int('0'); 2343 j2 = int(S[l--]) - int('0'); 2344 i2 = int(S[l--]) - int('0'); 2345 S[l] = char(0); 2346 s2 = atoi(S); 2347 } 2348 2349 rc = CIFGetReal ( dist,Loop,CIFTAG_CONN_DIST,n ); 2350 if (rc==Error_NoData) return Error_EmptyCIF; 2351 if (rc!=Error_NoError) return rc; 2352 2353 n++; 2354 2355 return Error_NoError; 2356 2357 } 2358 Copy(PContainerClass Link)2359 void Link::Copy ( PContainerClass Link ) { 2360 2361 strcpy ( atName1 ,PLink(Link)->atName1 ); 2362 strcpy ( aloc1 ,PLink(Link)->aloc1 ); 2363 strcpy ( resName1,PLink(Link)->resName1 ); 2364 strcpy ( chainID1,PLink(Link)->chainID1 ); 2365 seqNum1 = PLink(Link)->seqNum1; 2366 strcpy ( insCode1,PLink(Link)->insCode1 ); 2367 2368 strcpy ( atName2 ,PLink(Link)->atName2 ); 2369 strcpy ( aloc2 ,PLink(Link)->aloc2 ); 2370 strcpy ( resName2,PLink(Link)->resName2 ); 2371 strcpy ( chainID2,PLink(Link)->chainID2 ); 2372 seqNum2 = PLink(Link)->seqNum2; 2373 strcpy ( insCode2,PLink(Link)->insCode2 ); 2374 2375 s1 = PLink(Link)->s1; 2376 i1 = PLink(Link)->i1; 2377 j1 = PLink(Link)->j1; 2378 k1 = PLink(Link)->k1; 2379 2380 s2 = PLink(Link)->s2; 2381 i2 = PLink(Link)->i2; 2382 j2 = PLink(Link)->j2; 2383 k2 = PLink(Link)->k2; 2384 2385 dist = PLink(Link)->dist; 2386 2387 } 2388 write(io::RFile f)2389 void Link::write ( io::RFile f ) { 2390 byte Version=2; 2391 2392 f.WriteByte ( &Version ); 2393 2394 f.WriteTerLine ( atName1 ,false ); 2395 f.WriteTerLine ( aloc1 ,false ); 2396 f.WriteTerLine ( resName1,false ); 2397 f.WriteTerLine ( chainID1,false ); 2398 f.WriteInt ( &seqNum1 ); 2399 f.WriteTerLine ( insCode1,false ); 2400 2401 f.WriteTerLine ( atName2 ,false ); 2402 f.WriteTerLine ( aloc2 ,false ); 2403 f.WriteTerLine ( resName2,false ); 2404 f.WriteTerLine ( chainID2,false ); 2405 f.WriteInt ( &seqNum2 ); 2406 f.WriteTerLine ( insCode2,false ); 2407 2408 f.WriteInt ( &s1 ); 2409 f.WriteInt ( &i1 ); 2410 f.WriteInt ( &j1 ); 2411 f.WriteInt ( &k1 ); 2412 2413 f.WriteInt ( &s2 ); 2414 f.WriteInt ( &i2 ); 2415 f.WriteInt ( &j2 ); 2416 f.WriteInt ( &k2 ); 2417 2418 f.WriteReal ( &dist ); 2419 2420 } 2421 read(io::RFile f)2422 void Link::read ( io::RFile f ) { 2423 byte Version; 2424 2425 f.ReadByte ( &Version ); 2426 2427 f.ReadTerLine ( atName1 ,false ); 2428 f.ReadTerLine ( aloc1 ,false ); 2429 f.ReadTerLine ( resName1,false ); 2430 f.ReadTerLine ( chainID1,false ); 2431 f.ReadInt ( &seqNum1 ); 2432 f.ReadTerLine ( insCode1,false ); 2433 2434 f.ReadTerLine ( atName2 ,false ); 2435 f.ReadTerLine ( aloc2 ,false ); 2436 f.ReadTerLine ( resName2,false ); 2437 f.ReadTerLine ( chainID2,false ); 2438 f.ReadInt ( &seqNum2 ); 2439 f.ReadTerLine ( insCode2,false ); 2440 2441 f.ReadInt ( &s1 ); 2442 f.ReadInt ( &i1 ); 2443 f.ReadInt ( &j1 ); 2444 f.ReadInt ( &k1 ); 2445 2446 f.ReadInt ( &s2 ); 2447 f.ReadInt ( &i2 ); 2448 f.ReadInt ( &j2 ); 2449 f.ReadInt ( &k2 ); 2450 2451 if (Version>1) 2452 f.ReadReal ( &dist ); 2453 2454 } 2455 MakeStreamFunctions(Link)2456 MakeStreamFunctions(Link) 2457 2458 2459 // =================== LinkRContainer ======================= 2460 2461 PContainerClass LinkRContainer::MakeContainerClass ( int ClassID ) { 2462 switch (ClassID) { 2463 default : 2464 case ClassID_Template : return 2465 ClassContainer::MakeContainerClass(ClassID); 2466 case ClassID_LinkR : return new LinkR(); 2467 } 2468 } 2469 MakeStreamFunctions(LinkRContainer)2470 MakeStreamFunctions(LinkRContainer) 2471 2472 2473 // ======================== LinkR =========================== 2474 2475 LinkR::LinkR() : ContainerClass() { 2476 InitLinkR(); 2477 } 2478 LinkR(cpstr S)2479 LinkR::LinkR ( cpstr S ) : ContainerClass() { 2480 InitLinkR(); 2481 ConvertPDBASCII ( S ); 2482 } 2483 LinkR(io::RPStream Object)2484 LinkR::LinkR ( io::RPStream Object ) : ContainerClass(Object) { 2485 InitLinkR(); 2486 } 2487 ~LinkR()2488 LinkR::~LinkR() {} 2489 InitLinkR()2490 void LinkR::InitLinkR() { 2491 strcpy ( linkRID ,"----" ); // link name 2492 strcpy ( atName1 ,"----" ); // name of 1st linked atom 2493 strcpy ( aloc1 ," " ); // alternative location of 1st atom 2494 strcpy ( resName1,"---" ); // residue name of 1st linked atom 2495 strcpy ( chainID1," " ); // chain ID of 1st linked atom 2496 seqNum1 = 0; // sequence number of 1st linked atom 2497 strcpy ( insCode1," " ); // insertion code of 1st linked atom 2498 strcpy ( atName2 ,"----" ); // name of 2nd linked atom 2499 strcpy ( aloc2 ," " ); // alternative location of 2nd atom 2500 strcpy ( resName2,"---" ); // residue name of 2nd linked atom 2501 strcpy ( chainID2," " ); // chain ID of 2nd linked atom 2502 seqNum2 = 0; // sequence number of 2nd linked atom 2503 strcpy ( insCode2," " ); // insertion code of 2nd linked atom 2504 dist = 0.0; // link distance 2505 } 2506 2507 /* 2508 LINK LYS A 27 PLP A 255 PLPLYS 2509 LINK MAN S 3 MAN S 4 BETA1-4 2510 LINK C6 BBEN B 1 O1 BMAF S 2 BEN-MAF 2511 LINK OE2 AGLU A 320 C1 AMAF S 2 GLU-MAF 2512 LINK OE2 GLU A 67 1.895 ZN ZN R 5 GLU-ZN 2513 LINK NE2 HIS A 71 2.055 ZN ZN R 5 HIS-ZN 2514 LINK O ARG A 69 2.240 NA NA R 9 ARG-NA 2515 012345678901234567890123456789012345678901234567890123456789012345678901234567890 2516 1 2 3 4 5 6 7 2517 */ 2518 PDBASCIIDump(pstr S,int N)2519 void LinkR::PDBASCIIDump ( pstr S, int N ) { 2520 UNUSED_ARGUMENT(N); 2521 // makes the ASCII PDB OBSLTE line number N 2522 // from the class' data 2523 2524 strcpy ( S,"LINKR" ); 2525 PadSpaces ( S,80 ); 2526 2527 strcpy_n1 ( &(S[12]),atName1 ,4 ); 2528 strcpy_n1 ( &(S[16]),aloc1 ,1 ); 2529 strcpy_n1 ( &(S[17]),resName1,3 ); 2530 strcpy_n1 ( &(S[21]),chainID1,1 ); 2531 PutIntIns ( &(S[22]),seqNum1 ,4,insCode1 ); 2532 2533 if (dist>0.0) 2534 PutRealF ( &(S[32]),dist,7,3 ); 2535 2536 strcpy_n1 ( &(S[42]),atName2 ,4 ); 2537 strcpy_n1 ( &(S[46]),aloc2 ,1 ); 2538 strcpy_n1 ( &(S[47]),resName2,3 ); 2539 strcpy_n1 ( &(S[51]),chainID2,1 ); 2540 PutIntIns ( &(S[52]),seqNum2 ,4,insCode2 ); 2541 2542 strcpy_ns ( &(S[72]),linkRID,8 ); 2543 2544 } 2545 2546 2547 #define LinkRTypeID "LINKR" 2548 AddStructConnLinkRTags(mmcif::PLoop Loop)2549 void AddStructConnLinkRTags ( mmcif::PLoop Loop ) { 2550 2551 Loop->AddLoopTag ( CIFTAG_ID ); 2552 Loop->AddLoopTag ( CIFTAG_CONN_TYPE_ID ); 2553 2554 Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_ATOM_ID ); 2555 Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR1_AUTH_ALT_ID ); 2556 Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_COMP_ID ); 2557 Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_ASYM_ID ); 2558 Loop->AddLoopTag ( CIFTAG_CONN_PTNR1_AUTH_SEQ_ID ); 2559 Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR1_PDB_INS_CODE ); 2560 2561 Loop->AddLoopTag ( CIFTAG_CONN_DIST ); 2562 2563 Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_ATOM_ID ); 2564 Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR2_AUTH_ALT_ID ); 2565 Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_COMP_ID ); 2566 Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_ASYM_ID ); 2567 Loop->AddLoopTag ( CIFTAG_CONN_PTNR2_AUTH_SEQ_ID ); 2568 Loop->AddLoopTag ( CIFTAG_CONN_PDBX_PTNR2_PDB_INS_CODE ); 2569 2570 Loop->AddLoopTag ( CIFTAG_CONN_NAME ); 2571 2572 } 2573 MakeCIF(mmcif::PData CIF,int N)2574 void LinkR::MakeCIF ( mmcif::PData CIF, int N ) { 2575 UNUSED_ARGUMENT(N); 2576 mmcif::PLoop Loop; 2577 int RC; 2578 2579 RC = CIF->AddLoop ( CIFCAT_STRUCT_LINKR,Loop ); 2580 if (RC!=mmcif::CIFRC_Ok) // the category was (re)created, provide tags 2581 AddStructConnLinkRTags ( Loop ); 2582 2583 Loop->AddString ( "1" ); // should be a counter 2584 Loop->AddString ( pstr(LinkTypeID) ); 2585 2586 Loop->AddString ( atName1 ); 2587 Loop->AddString ( aloc1 ); 2588 Loop->AddString ( resName1 ); 2589 Loop->AddString ( chainID1 ); 2590 Loop->AddInteger ( seqNum1 ); 2591 Loop->AddString ( insCode1 ); 2592 2593 Loop->AddReal ( dist ); 2594 2595 Loop->AddString ( atName2 ); 2596 Loop->AddString ( aloc2 ); 2597 Loop->AddString ( resName2 ); 2598 Loop->AddString ( chainID2 ); 2599 Loop->AddInteger ( seqNum2 ); 2600 Loop->AddString ( insCode2 ); 2601 2602 Loop->AddString ( linkRID ); 2603 2604 } 2605 ConvertPDBASCII(cpstr S)2606 ERROR_CODE LinkR::ConvertPDBASCII ( cpstr S ) { 2607 2608 GetString ( atName1 ,&(S[12]),4 ); 2609 strcpy_ncss ( aloc1 ,&(S[16]),1 ); 2610 strcpy_ncss ( resName1,&(S[17]),3 ); 2611 strcpy_ncss ( chainID1,&(S[21]),1 ); 2612 GetIntIns ( seqNum1,insCode1,&(S[22]),4 ); 2613 2614 if (!GetReal(dist,&(S[32]),7)) dist = 0.0; 2615 2616 GetString ( atName2 ,&(S[42]),4 ); 2617 strcpy_ncss ( aloc2 ,&(S[46]),1 ); 2618 strcpy_ncss ( resName2,&(S[47]),3 ); 2619 strcpy_ncss ( chainID2,&(S[51]),1 ); 2620 GetIntIns ( seqNum2,insCode2,&(S[52]),4 ); 2621 2622 strcpy_ncss ( linkRID,&(S[72]),8 ); 2623 2624 return Error_NoError ; 2625 2626 } 2627 GetCIF(mmcif::PData CIF,int & n)2628 ERROR_CODE LinkR::GetCIF ( mmcif::PData CIF, int & n ) { 2629 mmcif::PLoop Loop; 2630 pstr F; 2631 int RC,l; 2632 bool Done; 2633 ERROR_CODE rc; 2634 2635 Loop = CIF->GetLoop ( CIFCAT_STRUCT_CONN ); 2636 if (!Loop) { 2637 n = -1; // signal to finish processing of this structure 2638 return Error_EmptyCIF; 2639 } 2640 2641 l = Loop->GetLoopLength(); 2642 Done = (n>=l); 2643 while (!Done) { 2644 F = Loop->GetString ( CIFTAG_CONN_TYPE_ID,n,RC ); 2645 if ((!RC) && F) Done = (strcmp(F,LinkTypeID)==0); 2646 else Done = false; 2647 if (!Done) { 2648 n++; 2649 Done = (n>=l); 2650 } 2651 } 2652 2653 if (n>=l) { 2654 n = -1; // finish processing of Turn 2655 return Error_EmptyCIF; 2656 } 2657 2658 Loop->DeleteField ( CIFTAG_CONN_TYPE_ID,n ); 2659 2660 // CIFGetInteger ( l,Loop,CIFTAG_ID,n ); 2661 2662 CIFGetString ( atName1,Loop,CIFTAG_CONN_PTNR1_AUTH_ATOM_ID,n, 2663 sizeof(atName1),pstr(" ") ); 2664 CIFGetString ( aloc1,Loop,CIFTAG_CONN_PDBX_PTNR1_AUTH_ALT_ID,n, 2665 sizeof(aloc1),pstr(" ") ); 2666 CIFGetString ( resName1,Loop,CIFTAG_CONN_PTNR1_AUTH_COMP_ID,n, 2667 sizeof(resName1),pstr(" ") ); 2668 CIFGetString ( chainID1,Loop,CIFTAG_CONN_PTNR1_AUTH_ASYM_ID,n, 2669 sizeof(chainID1),pstr(" ") ); 2670 rc = CIFGetInteger ( seqNum1,Loop,CIFTAG_CONN_PTNR1_AUTH_SEQ_ID,n ); 2671 if (rc==Error_NoData) return Error_EmptyCIF; 2672 if (rc!=Error_NoError) return rc; 2673 2674 CIFGetString ( insCode1,Loop,CIFTAG_CONN_PDBX_PTNR1_PDB_INS_CODE, 2675 n,sizeof(insCode1),pstr(" ") ); 2676 2677 rc = CIFGetReal ( dist,Loop,CIFTAG_CONN_DIST,n ); 2678 if (rc==Error_NoData) return Error_EmptyCIF; 2679 if (rc!=Error_NoError) return rc; 2680 2681 CIFGetString ( atName2,Loop,CIFTAG_CONN_PTNR2_AUTH_ATOM_ID,n, 2682 sizeof(atName2),pstr(" ") ); 2683 CIFGetString ( aloc2,Loop,CIFTAG_CONN_PDBX_PTNR2_AUTH_ALT_ID,n, 2684 sizeof(aloc2),pstr(" ") ); 2685 CIFGetString ( resName2,Loop,CIFTAG_CONN_PTNR2_AUTH_COMP_ID,n, 2686 sizeof(resName2),pstr(" ") ); 2687 CIFGetString ( chainID2,Loop,CIFTAG_CONN_PTNR2_AUTH_ASYM_ID,n, 2688 sizeof(chainID2),pstr(" ") ); 2689 rc = CIFGetInteger ( seqNum2,Loop,CIFTAG_CONN_PTNR2_AUTH_SEQ_ID,n ); 2690 if (rc==Error_NoData) return Error_EmptyCIF; 2691 if (rc!=Error_NoError) return rc; 2692 2693 CIFGetString ( insCode2,Loop,CIFTAG_CONN_PDBX_PTNR2_PDB_INS_CODE, 2694 n,sizeof(insCode2),pstr(" ") ); 2695 2696 CIFGetString ( linkRID,Loop,CIFTAG_CONN_NAME,n, 2697 sizeof(linkRID),pstr(" ") ); 2698 2699 n++; 2700 2701 return Error_NoError; 2702 2703 } 2704 Copy(PContainerClass LinkR)2705 void LinkR::Copy ( PContainerClass LinkR ) { 2706 2707 strcpy ( atName1 ,PLinkR(LinkR)->atName1 ); 2708 strcpy ( aloc1 ,PLinkR(LinkR)->aloc1 ); 2709 strcpy ( resName1,PLinkR(LinkR)->resName1 ); 2710 strcpy ( chainID1,PLinkR(LinkR)->chainID1 ); 2711 seqNum1 = PLinkR(LinkR)->seqNum1; 2712 strcpy ( insCode1,PLinkR(LinkR)->insCode1 ); 2713 2714 dist = PLinkR(LinkR)->dist; 2715 2716 strcpy ( atName2 ,PLinkR(LinkR)->atName2 ); 2717 strcpy ( aloc2 ,PLinkR(LinkR)->aloc2 ); 2718 strcpy ( resName2,PLinkR(LinkR)->resName2 ); 2719 strcpy ( chainID2,PLinkR(LinkR)->chainID2 ); 2720 seqNum2 = PLinkR(LinkR)->seqNum2; 2721 strcpy ( insCode2,PLinkR(LinkR)->insCode2 ); 2722 2723 strcpy ( linkRID,PLinkR(LinkR)->linkRID ); 2724 2725 } 2726 write(io::RFile f)2727 void LinkR::write ( io::RFile f ) { 2728 byte Version=1; 2729 2730 f.WriteByte ( &Version ); 2731 2732 f.WriteTerLine ( atName1 ,false ); 2733 f.WriteTerLine ( aloc1 ,false ); 2734 f.WriteTerLine ( resName1,false ); 2735 f.WriteTerLine ( chainID1,false ); 2736 f.WriteInt ( &seqNum1 ); 2737 f.WriteTerLine ( insCode1,false ); 2738 2739 f.WriteReal ( &dist ); 2740 2741 f.WriteTerLine ( atName2 ,false ); 2742 f.WriteTerLine ( aloc2 ,false ); 2743 f.WriteTerLine ( resName2,false ); 2744 f.WriteTerLine ( chainID2,false ); 2745 f.WriteInt ( &seqNum2 ); 2746 f.WriteTerLine ( insCode2,false ); 2747 2748 f.WriteTerLine ( linkRID,false ); 2749 2750 } 2751 read(io::RFile f)2752 void LinkR::read ( io::RFile f ) { 2753 byte Version; 2754 2755 f.ReadByte ( &Version ); 2756 2757 f.ReadTerLine ( atName1 ,false ); 2758 f.ReadTerLine ( aloc1 ,false ); 2759 f.ReadTerLine ( resName1,false ); 2760 f.ReadTerLine ( chainID1,false ); 2761 f.ReadInt ( &seqNum1 ); 2762 f.ReadTerLine ( insCode1,false ); 2763 2764 f.ReadReal ( &dist ); 2765 2766 f.ReadTerLine ( atName2 ,false ); 2767 f.ReadTerLine ( aloc2 ,false ); 2768 f.ReadTerLine ( resName2,false ); 2769 f.ReadTerLine ( chainID2,false ); 2770 f.ReadInt ( &seqNum2 ); 2771 f.ReadTerLine ( insCode2,false ); 2772 2773 f.ReadTerLine ( linkRID,false ); 2774 2775 } 2776 MakeStreamFunctions(LinkR)2777 MakeStreamFunctions(LinkR) 2778 2779 2780 // =================== CisPepContainer ====================== 2781 2782 PContainerClass CisPepContainer::MakeContainerClass ( int ClassID ) { 2783 switch (ClassID) { 2784 default : 2785 case ClassID_Template : return 2786 ClassContainer::MakeContainerClass(ClassID); 2787 case ClassID_CisPep : return new CisPep(); 2788 } 2789 } 2790 MakeStreamFunctions(CisPepContainer)2791 MakeStreamFunctions(CisPepContainer) 2792 2793 2794 // ======================== CisPep ========================== 2795 2796 CisPep::CisPep() : ContainerClass() { 2797 InitCisPep(); 2798 } 2799 CisPep(cpstr S)2800 CisPep::CisPep ( cpstr S ) : ContainerClass() { 2801 InitCisPep(); 2802 ConvertPDBASCII ( S ); 2803 } 2804 CisPep(io::RPStream Object)2805 CisPep::CisPep ( io::RPStream Object ) : ContainerClass(Object) { 2806 InitCisPep(); 2807 } 2808 ~CisPep()2809 CisPep::~CisPep() {} 2810 InitCisPep()2811 void CisPep::InitCisPep() { 2812 serNum = 1; // record serial number 2813 strcpy ( pep1 ,"---" ); // residue name 2814 strcpy ( chainID1," " ); // chain identifier 1 2815 seqNum1 = 0; // residue sequence number 1 2816 strcpy ( icode1 ," " ); // insertion code 1 2817 strcpy ( pep2 ,"---" ); // residue name 2 2818 strcpy ( chainID2," " ); // chain identifier 2 2819 seqNum2 = 0; // residue sequence number 2 2820 strcpy ( icode2 ," " ); // insertion code 2 2821 modNum = 0; // model number 2822 measure = 0.0; // measure of the angle in degrees. 2823 } 2824 PDBASCIIDump(pstr S,int N)2825 void CisPep::PDBASCIIDump ( pstr S, int N ) { 2826 UNUSED_ARGUMENT(N); 2827 2828 strcpy ( S,"CISPEP" ); 2829 PadSpaces ( S,80 ); 2830 2831 PutInteger ( &(S[7]),serNum,3 ); 2832 2833 strcpy_n1 ( &(S[11]),pep1 ,3 ); 2834 strcpy_n1 ( &(S[15]),chainID1,1 ); 2835 PutIntIns ( &(S[17]),seqNum1 ,4,icode1 ); 2836 2837 strcpy_n1 ( &(S[25]),pep2 ,3 ); 2838 strcpy_n1 ( &(S[29]),chainID2,1 ); 2839 PutIntIns ( &(S[31]),seqNum2 ,4,icode1 ); 2840 2841 PutInteger ( &(S[43]),modNum,3 ); 2842 PutRealF ( &(S[53]),measure,6,2 ); 2843 2844 } 2845 2846 ConvertPDBASCII(cpstr S)2847 ERROR_CODE CisPep::ConvertPDBASCII ( cpstr S ) { 2848 2849 GetInteger ( serNum ,&(S[7]) ,3 ); 2850 2851 strcpy_ncss ( pep1 ,&(S[11]),3 ); 2852 strcpy_ncss ( chainID1,&(S[15]),1 ); 2853 GetIntIns ( seqNum1,icode1,&(S[17]),4 ); 2854 2855 strcpy_ncss ( pep2 ,&(S[25]),3 ); 2856 strcpy_ncss ( chainID2,&(S[29]),1 ); 2857 GetIntIns ( seqNum2,icode2,&(S[31]),4 ); 2858 2859 GetInteger ( modNum ,&(S[43]),3 ); 2860 GetReal ( measure ,&(S[53]),6 ); 2861 2862 return Error_NoError; 2863 2864 } 2865 2866 Copy(PContainerClass CisPep)2867 void CisPep::Copy ( PContainerClass CisPep ) { 2868 2869 serNum = PCisPep(CisPep)->serNum; 2870 2871 strcpy ( pep1 ,PCisPep(CisPep)->pep1 ); 2872 strcpy ( chainID1,PCisPep(CisPep)->chainID1 ); 2873 seqNum1 = PCisPep(CisPep)->seqNum1; 2874 strcpy ( icode1 ,PCisPep(CisPep)->icode1 ); 2875 2876 strcpy ( pep2 ,PCisPep(CisPep)->pep2 ); 2877 strcpy ( chainID2,PCisPep(CisPep)->chainID2 ); 2878 seqNum2 = PCisPep(CisPep)->seqNum2; 2879 strcpy ( icode2 ,PCisPep(CisPep)->icode2 ); 2880 2881 modNum = PCisPep(CisPep)->modNum; 2882 measure = PCisPep(CisPep)->measure; 2883 2884 } 2885 write(io::RFile f)2886 void CisPep::write ( io::RFile f ) { 2887 byte Version=1; 2888 2889 f.WriteByte ( &Version ); 2890 2891 f.WriteInt ( &serNum ); 2892 2893 f.WriteTerLine ( pep1 ,false ); 2894 f.WriteTerLine ( chainID1,false ); 2895 f.WriteInt ( &seqNum1 ); 2896 f.WriteTerLine ( icode1 ,false ); 2897 2898 f.WriteTerLine ( pep2 ,false ); 2899 f.WriteTerLine ( chainID2,false ); 2900 f.WriteInt ( &seqNum2 ); 2901 f.WriteTerLine ( icode2 ,false ); 2902 2903 f.WriteInt ( &modNum ); 2904 f.WriteReal ( &measure ); 2905 2906 } 2907 read(io::RFile f)2908 void CisPep::read ( io::RFile f ) { 2909 byte Version; 2910 2911 f.ReadByte ( &Version ); 2912 2913 f.ReadInt ( &serNum ); 2914 2915 f.ReadTerLine ( pep1 ,false ); 2916 f.ReadTerLine ( chainID1,false ); 2917 f.ReadInt ( &seqNum1 ); 2918 f.ReadTerLine ( icode1 ,false ); 2919 2920 f.ReadTerLine ( pep2 ,false ); 2921 f.ReadTerLine ( chainID2,false ); 2922 f.ReadInt ( &seqNum2 ); 2923 f.ReadTerLine ( icode2 ,false ); 2924 2925 f.ReadInt ( &modNum ); 2926 f.ReadReal ( &measure ); 2927 2928 } 2929 MakeStreamFunctions(CisPep)2930 MakeStreamFunctions(CisPep) 2931 2932 2933 2934 // ===================== Model ======================= 2935 2936 Model::Model() : ProModel() { 2937 InitModel(); 2938 } 2939 Model(PManager MMDBM,int serialNum)2940 Model::Model ( PManager MMDBM, int serialNum ) : ProModel() { 2941 InitModel(); 2942 manager = MMDBM; 2943 serNum = serialNum; 2944 } 2945 Model(io::RPStream Object)2946 Model::Model ( io::RPStream Object ) : ProModel(Object) { 2947 InitModel(); 2948 } 2949 InitModel()2950 void Model::InitModel() { 2951 serNum = 0; 2952 nChains = 0; 2953 nChainsAlloc = 0; 2954 chain = NULL; 2955 manager = NULL; 2956 Exclude = true; 2957 } 2958 ~Model()2959 Model::~Model() { 2960 FreeMemory(); 2961 if (manager) manager->_ExcludeModel ( serNum ); 2962 } 2963 FreeMemory()2964 void Model::FreeMemory() { 2965 2966 DeleteAllChains(); 2967 if (chain) delete[] chain; 2968 chain = NULL; 2969 nChains = 0; 2970 nChainsAlloc = 0; 2971 2972 RemoveSecStructure(); 2973 RemoveHetInfo (); 2974 RemoveLinks (); 2975 RemoveLinkRs (); 2976 RemoveCisPeps (); 2977 2978 } 2979 2980 SetMMDBManager(PManager MMDBM,int serialNum)2981 void Model::SetMMDBManager ( PManager MMDBM, int serialNum ) { 2982 manager = MMDBM; 2983 serNum = serialNum; 2984 } 2985 CheckInAtoms()2986 void Model::CheckInAtoms() { 2987 int i; 2988 if (manager) 2989 for (i=0;i<nChains;i++) 2990 if (chain[i]) 2991 chain[i]->CheckInAtoms(); 2992 } 2993 2994 GetNumberOfAtoms(bool countTers)2995 int Model::GetNumberOfAtoms ( bool countTers ) { 2996 // returns number of atoms in the model 2997 int i,na; 2998 na = 0; 2999 for (i=0;i<nChains;i++) 3000 if (chain[i]) na += chain[i]->GetNumberOfAtoms ( countTers ); 3001 return na; 3002 } 3003 GetNumberOfResidues()3004 int Model::GetNumberOfResidues() { 3005 // returns number of residues in the model 3006 PChain chn; 3007 int ic,ir,nr; 3008 nr = 0; 3009 for (ic=0;ic<nChains;ic++) { 3010 chn = chain[ic]; 3011 if (chn) 3012 for (ir=0;ir<chn->nResidues;ir++) 3013 if (chn->residue[ir]) nr++; 3014 } 3015 return nr; 3016 } 3017 3018 3019 // ---------------- Extracting chains -------------------------- 3020 GetNumberOfChains()3021 int Model::GetNumberOfChains() { 3022 return nChains; 3023 } 3024 GetChain(int chainNo)3025 PChain Model::GetChain ( int chainNo ) { 3026 if ((0<=chainNo) && (chainNo<nChains)) 3027 return chain[chainNo]; 3028 else return NULL; 3029 } 3030 3031 ExpandChainArray(int nOfChains)3032 void Model::ExpandChainArray ( int nOfChains ) { 3033 PPChain chain1; 3034 int i; 3035 if (nOfChains>=nChainsAlloc) { 3036 nChainsAlloc = nOfChains+10; 3037 chain1 = new PChain[nChainsAlloc]; 3038 for (i=0;i<nChains;i++) 3039 chain1[i] = chain[i]; 3040 for (i=nChains;i<nChainsAlloc;i++) 3041 chain1[i] = NULL; 3042 if (chain) delete[] chain; 3043 chain = chain1; 3044 } 3045 } 3046 GetChainCreate(const ChainID chID,bool enforceUniqueChainID)3047 PChain Model::GetChainCreate ( const ChainID chID, 3048 bool enforceUniqueChainID ) { 3049 // Returns pointer on chain, whose identifier is 3050 // given in chID. If such a chain is absent in the 3051 // model, it is created. 3052 PChain chn; 3053 ChainID chainID; 3054 int i,k; 3055 3056 // check if such a chain is already in the model 3057 chn = NULL; 3058 if (enforceUniqueChainID) { 3059 k = 0; 3060 for (i=0;i<nChains;i++) 3061 if (chain[i]) { 3062 // here we check only first letter as it is kept in all 3063 // derived names 3064 if (chID[0]==chain[i]->chainID[0]) { 3065 chn = chain[i]; 3066 if (chn->GetNumberOfResidues()>0) k++; 3067 } 3068 } 3069 if (k) sprintf ( chainID,"%s%i",chID,k-1 ); 3070 else if (!chn) strcpy ( chainID,chID ); // chain is absent 3071 else return chn; // the only empty chain 3072 } else { 3073 if (chID[0]) { 3074 for (i=0;(i<nChains) && (!chn);i++) 3075 if (chain[i]) { 3076 if (!strcmp(chID,chain[i]->chainID)) 3077 chn = chain[i]; // it is there; just return the pointer 3078 } 3079 } else { 3080 for (i=0;(i<nChains) && (!chn);i++) 3081 if (chain[i]) { 3082 if (!chain[i]->chainID[0]) 3083 chn = chain[i]; // it is there; just return the pointer 3084 } 3085 } 3086 if (chn) return chn; 3087 strcpy ( chainID,chID ); 3088 } 3089 3090 ExpandChainArray ( nChains ); 3091 3092 // create new chain 3093 chain[nChains] = newChain(); 3094 chain[nChains]->SetChain ( chainID ); 3095 chain[nChains]->SetModel ( this ); 3096 nChains++; 3097 3098 return chain[nChains-1]; 3099 3100 } 3101 CreateChain(const ChainID chID)3102 PChain Model::CreateChain ( const ChainID chID ) { 3103 // CreateChain() creates a new chain with chain ID regardless 3104 // the presence of same-ID chains in the model. This function 3105 // was introduced only for compatibility with older CCP4 3106 // applications and using it in any new developments should be 3107 // strictly discouraged. 3108 3109 ExpandChainArray ( nChains ); 3110 3111 // create new chain 3112 chain[nChains] = newChain(); 3113 chain[nChains]->SetChain ( chID ); 3114 chain[nChains]->SetModel ( this ); 3115 nChains++; 3116 3117 return chain[nChains-1]; 3118 3119 } 3120 3121 GetChainTable(PPChain & chainTable,int & NumberOfChains)3122 void Model::GetChainTable ( PPChain & chainTable, 3123 int & NumberOfChains ) { 3124 chainTable = chain; 3125 NumberOfChains = nChains; 3126 } 3127 GetNewChainID(ChainID chID,int length)3128 bool Model::GetNewChainID ( ChainID chID, int length ) { 3129 int i,k; 3130 bool found; 3131 3132 memset ( chID,0,sizeof(ChainID) ); 3133 chID[0] = 'A'; 3134 3135 do { 3136 found = false; 3137 for (i=0;(i<nChains) && (!found);i++) 3138 if (chain[i]) 3139 found = (!strcmp(chID,chain[i]->chainID)); 3140 if (found) { 3141 k = 0; 3142 while (k<length) 3143 if (!chID[k]) { 3144 chID[k] = 'A'; 3145 break; 3146 } else if (chID[k]<'Z') { 3147 chID[k]++; 3148 break; 3149 } else { 3150 chID[k] = 'A'; 3151 k++; 3152 } 3153 } else 3154 k = 0; 3155 } while (found && (k<length)); 3156 3157 if (found) { 3158 k = strlen(chID); 3159 while (k<length) 3160 chID[k++] = 'A'; 3161 } 3162 3163 return (!found); 3164 3165 } 3166 3167 GetChain(const ChainID chID)3168 PChain Model::GetChain ( const ChainID chID ) { 3169 // Returns pointer on chain, whose identifier is 3170 // given in chID. If such a chain is absent in the 3171 // model, returns NULL. 3172 int i; 3173 bool isChainID; 3174 if (chID) isChainID = (chID[0]!=char(0)); 3175 else isChainID = false; 3176 if (isChainID) { 3177 for (i=0;i<nChains;i++) 3178 if (chain[i]) { 3179 if (!strcmp(chID,chain[i]->chainID)) 3180 return chain[i]; // it is there; just return the pointer 3181 } 3182 } else { 3183 for (i=0;i<nChains;i++) 3184 if (chain[i]) { 3185 if (!chain[i]->chainID[0]) 3186 return chain[i]; // it is there; just return the pointer 3187 } 3188 } 3189 return NULL; 3190 } 3191 3192 3193 // ------------------ Deleting chains -------------------------- 3194 DeleteChain(int chainNo)3195 int Model::DeleteChain ( int chainNo ) { 3196 if ((0<=chainNo) && (chainNo<nChains)) { 3197 if (chain[chainNo]) { 3198 Exclude = false; 3199 delete chain[chainNo]; 3200 chain[chainNo] = NULL; 3201 Exclude = true; 3202 return 1; 3203 } 3204 } 3205 return 0; 3206 } 3207 DeleteChain(const ChainID chID)3208 int Model::DeleteChain ( const ChainID chID ) { 3209 int i; 3210 if (chID[0]) { 3211 for (i=0;i<nChains;i++) 3212 if (chain[i]) { 3213 if (!strcmp(chID,chain[i]->chainID)) { 3214 Exclude = false; 3215 delete chain[i]; 3216 chain[i] = NULL; 3217 Exclude = true; 3218 return 1; 3219 } 3220 } 3221 } else { 3222 for (i=0;i<nChains;i++) 3223 if (chain[i]) { 3224 if (!chain[i]->chainID[0]) { 3225 Exclude = false; 3226 delete chain[i]; 3227 chain[i] = NULL; 3228 Exclude = true; 3229 return 1; 3230 } 3231 } 3232 } 3233 return 0; 3234 } 3235 3236 DeleteAllChains()3237 int Model::DeleteAllChains() { 3238 int i,k; 3239 Exclude = false; 3240 k = 0; 3241 for (i=0;i<nChains;i++) 3242 if (chain[i]) { 3243 delete chain[i]; 3244 chain[i] = NULL; 3245 k++; 3246 } 3247 nChains = 0; 3248 Exclude = true; 3249 return k; 3250 } 3251 DeleteSolventChains()3252 int Model::DeleteSolventChains() { 3253 int i,k; 3254 Exclude = false; 3255 k = 0; 3256 for (i=0;i<nChains;i++) 3257 if (chain[i]) { 3258 if (chain[i]->isSolventChain()) { 3259 delete chain[i]; 3260 chain[i] = NULL; 3261 k++; 3262 } 3263 } 3264 Exclude = true; 3265 return k; 3266 } 3267 TrimChainTable()3268 void Model::TrimChainTable() { 3269 int i,j; 3270 Exclude = false; 3271 j = 0; 3272 for (i=0;i<nChains;i++) 3273 if (chain[i]) { 3274 if (chain[i]->nResidues>0) { 3275 if (j<i) { 3276 chain[j] = chain[i]; 3277 chain[i] = NULL; 3278 } 3279 j++; 3280 } else { 3281 delete chain[i]; 3282 chain[i] = NULL; 3283 } 3284 } 3285 nChains = j; 3286 Exclude = true; 3287 } 3288 3289 GetNumberOfResidues(const ChainID chainID)3290 int Model::GetNumberOfResidues ( const ChainID chainID ) { 3291 PChain chn; 3292 chn = GetChain ( chainID ); 3293 if (chn) return chn->nResidues; 3294 return 0; 3295 } 3296 GetNumberOfResidues(int chainNo)3297 int Model::GetNumberOfResidues ( int chainNo ) { 3298 if ((0<=chainNo) && (chainNo<nChains)) { 3299 if (chain[chainNo]) 3300 return chain[chainNo]->nResidues; 3301 } 3302 return 0; 3303 } 3304 GetResidue(const ChainID chainID,int seqNo,const InsCode insCode)3305 PResidue Model::GetResidue ( const ChainID chainID, int seqNo, 3306 const InsCode insCode ) { 3307 PChain chn; 3308 chn = GetChain ( chainID ); 3309 if (chn) 3310 return chn->GetResidue ( seqNo,insCode ); 3311 return NULL; 3312 } 3313 GetResidue(const ChainID chainID,int resNo)3314 PResidue Model::GetResidue ( const ChainID chainID, int resNo ) { 3315 PChain chn; 3316 chn = GetChain ( chainID ); 3317 if (chn) { 3318 if ((0<=resNo) && (resNo<chn->nResidues)) 3319 return chn->residue[resNo]; 3320 } 3321 return NULL; 3322 } 3323 GetResidue(int chainNo,int seqNo,const InsCode insCode)3324 PResidue Model::GetResidue ( int chainNo, int seqNo, 3325 const InsCode insCode ) { 3326 if ((0<=chainNo) && (chainNo<nChains)) { 3327 if (chain[chainNo]) 3328 return chain[chainNo]->GetResidue ( seqNo,insCode ); 3329 } 3330 return NULL; 3331 } 3332 GetResidue(int chainNo,int resNo)3333 PResidue Model::GetResidue ( int chainNo, int resNo ) { 3334 if ((0<=chainNo) && (chainNo<nChains)) { 3335 if (chain[chainNo]) { 3336 if ((0<=resNo) && (resNo<chain[chainNo]->nResidues)) 3337 return chain[chainNo]->residue[resNo]; 3338 } 3339 } 3340 return NULL; 3341 } 3342 GetResidueNo(const ChainID chainID,int seqNo,const InsCode insCode)3343 int Model::GetResidueNo ( const ChainID chainID, int seqNo, 3344 const InsCode insCode ) { 3345 PChain chn; 3346 chn = GetChain ( chainID ); 3347 if (chn) 3348 return chn->GetResidueNo ( seqNo,insCode ); 3349 return -2; 3350 } 3351 GetResidueNo(int chainNo,int seqNo,const InsCode insCode)3352 int Model::GetResidueNo ( int chainNo, int seqNo, 3353 const InsCode insCode ) { 3354 if ((0<=chainNo) && (chainNo<nChains)) { 3355 if (chain[chainNo]) 3356 return chain[chainNo]->GetResidueNo ( seqNo,insCode ); 3357 } 3358 return -2; 3359 } 3360 3361 GetResidueTable(PPResidue & resTable,int & NumberOfResidues)3362 void Model::GetResidueTable ( PPResidue & resTable, 3363 int & NumberOfResidues ) { 3364 // resTable has to be NULL or it will be reallocated. The application 3365 // is responsible for deallocating the resTable (but not of its 3366 // residues!). This does not apply to other GetResidueTable 3367 // functions. 3368 PPChain chn; 3369 PPResidue res; 3370 int i,j,k,nChns,nResidues; 3371 3372 if (resTable) { 3373 delete[] resTable; 3374 resTable = NULL; 3375 } 3376 3377 NumberOfResidues = 0; 3378 GetChainTable ( chn,nChns ); 3379 for (i=0;i<nChns;i++) 3380 if (chn[i]) { 3381 chn[i]->GetResidueTable ( res,nResidues ); 3382 NumberOfResidues += nResidues; 3383 } 3384 3385 if (NumberOfResidues>0) { 3386 resTable = new PResidue[NumberOfResidues]; 3387 k = 0; 3388 GetChainTable ( chn,nChns ); 3389 for (i=0;i<nChns;i++) 3390 if (chn[i]) { 3391 chn[i]->GetResidueTable ( res,nResidues ); 3392 for (j=0;j<nResidues;j++) 3393 if (res[j]) resTable[k++] = res[j]; 3394 } 3395 NumberOfResidues = k; 3396 } 3397 3398 } 3399 GetResidueTable(const ChainID chainID,PPResidue & resTable,int & NumberOfResidues)3400 void Model::GetResidueTable ( const ChainID chainID, 3401 PPResidue & resTable, 3402 int & NumberOfResidues ) { 3403 PChain chn; 3404 resTable = NULL; 3405 NumberOfResidues = 0; 3406 chn = GetChain ( chainID ); 3407 if (chn) { 3408 resTable = chn->residue; 3409 NumberOfResidues = chn->nResidues; 3410 } 3411 } 3412 GetResidueTable(int chainNo,PPResidue & resTable,int & NumberOfResidues)3413 void Model::GetResidueTable ( int chainNo, PPResidue & resTable, 3414 int & NumberOfResidues ) { 3415 resTable = NULL; 3416 NumberOfResidues = 0; 3417 if ((0<=chainNo) && (chainNo<nChains)) { 3418 if (chain[chainNo]) { 3419 resTable = chain[chainNo]->residue; 3420 NumberOfResidues = chain[chainNo]->nResidues; 3421 } 3422 } 3423 } 3424 3425 DeleteResidue(const ChainID chainID,int seqNo,const InsCode insCode)3426 int Model::DeleteResidue ( const ChainID chainID, int seqNo, 3427 const InsCode insCode ) { 3428 PChain chn; 3429 chn = GetChain ( chainID ); 3430 if (chn) return chn->DeleteResidue ( seqNo,insCode ); 3431 return 0; 3432 } 3433 DeleteResidue(const ChainID chainID,int resNo)3434 int Model::DeleteResidue ( const ChainID chainID, int resNo ) { 3435 PChain chn; 3436 chn = GetChain ( chainID ); 3437 if (chn) return chn->DeleteResidue ( resNo ); 3438 return 0; 3439 } 3440 DeleteResidue(int chainNo,int seqNo,const InsCode insCode)3441 int Model::DeleteResidue ( int chainNo, int seqNo, 3442 const InsCode insCode ) { 3443 if ((0<=chainNo) && (chainNo<nChains)) { 3444 if (chain[chainNo]) 3445 return chain[chainNo]->DeleteResidue ( seqNo,insCode ); 3446 } 3447 return 0; 3448 } 3449 DeleteResidue(int chainNo,int resNo)3450 int Model::DeleteResidue ( int chainNo, int resNo ) { 3451 if ((0<=chainNo) && (chainNo<nChains)) { 3452 if (chain[chainNo]) 3453 return chain[chainNo]->DeleteResidue ( resNo ); 3454 } 3455 return 0; 3456 } 3457 DeleteAllResidues(const ChainID chainID)3458 int Model::DeleteAllResidues ( const ChainID chainID ) { 3459 PChain chn; 3460 chn = GetChain ( chainID ); 3461 if (chn) return chn->DeleteAllResidues(); 3462 return 0; 3463 } 3464 DeleteAllResidues(int chainNo)3465 int Model::DeleteAllResidues ( int chainNo ) { 3466 if ((0<=chainNo) && (chainNo<nChains)) { 3467 if (chain[chainNo]) 3468 return chain[chainNo]->DeleteAllResidues(); 3469 } 3470 return 0; 3471 } 3472 DeleteAllResidues()3473 int Model::DeleteAllResidues() { 3474 int i,k; 3475 k = 0; 3476 for (i=0;i<nChains;i++) 3477 if (chain[i]) 3478 k += chain[i]->DeleteAllResidues(); 3479 return k; 3480 } 3481 3482 DeleteSolvent()3483 int Model::DeleteSolvent() { 3484 int i,k; 3485 Exclude = false; 3486 k = 0; 3487 for (i=0;i<nChains;i++) 3488 if (chain[i]) { 3489 k += chain[i]->DeleteSolvent(); 3490 chain[i]->TrimResidueTable(); 3491 if (chain[i]->nResidues<=0) { 3492 delete chain[i]; 3493 chain[i] = NULL; 3494 } 3495 } 3496 Exclude = true; 3497 return k; 3498 } 3499 3500 AddResidue(const ChainID chainID,PResidue res)3501 int Model::AddResidue ( const ChainID chainID, PResidue res ) { 3502 PChain chn; 3503 chn = GetChain ( chainID ); 3504 if (chn) return chn->AddResidue ( res ); 3505 return 0; 3506 } 3507 AddResidue(int chainNo,PResidue res)3508 int Model::AddResidue ( int chainNo, PResidue res ) { 3509 if ((0<=chainNo) && (chainNo<nChains)) { 3510 if (chain[chainNo]) 3511 return chain[chainNo]->AddResidue ( res ); 3512 } 3513 return 0; 3514 } 3515 3516 _ExcludeChain(const ChainID chainID)3517 int Model::_ExcludeChain ( const ChainID chainID ) { 3518 // _ExcludeChain(..) excludes (but does not dispose!) a chain 3519 // from the model. Returns 1 if the model gets empty and 0 otherwise. 3520 int i,k; 3521 3522 if (!Exclude) return 0; 3523 3524 // find the chain 3525 k = -1; 3526 for (i=0;(i<nChains) && (k<0);i++) 3527 if (!strcmp(chainID,chain[i]->chainID)) 3528 k = i; 3529 3530 if (k>=0) { 3531 for (i=k+1;i<nChains;i++) 3532 chain[i-1] = chain[i]; 3533 nChains--; 3534 chain[nChains] = NULL; 3535 } 3536 3537 if (nChains<=0) return 1; 3538 else return 0; 3539 3540 } 3541 3542 3543 // -------------------- Sort chains ---------------------------- 3544 3545 DefineClass(QSortChains) 3546 3547 class QSortChains : public QuickSort { 3548 public : QSortChains()3549 QSortChains() : QuickSort() { sKey = 0; } 3550 int Compare ( int i, int j ); 3551 void Swap ( int i, int j ); 3552 void Sort ( PPChain chain, int nChains, int sortKey ); 3553 private : 3554 int sKey; 3555 }; 3556 Compare(int i,int j)3557 int QSortChains::Compare ( int i, int j ) { 3558 int diff; 3559 3560 diff = strcmp ( (PPChain(data))[i]->GetChainID(), 3561 (PPChain(data))[j]->GetChainID() ); 3562 if (diff>0) diff = 1; 3563 if (diff<0) diff = -1; 3564 3565 if (sKey==SORT_CHAIN_ChainID_Desc) return -diff; 3566 3567 return diff; 3568 3569 } 3570 Swap(int i,int j)3571 void QSortChains::Swap ( int i, int j ) { 3572 PChain chn; 3573 chn = ((PPChain)data)[i]; 3574 ((PPChain)data)[i] = ((PPChain)data)[j]; 3575 ((PPChain)data)[j] = chn; 3576 } 3577 Sort(PPChain chain,int nChains,int sortKey)3578 void QSortChains::Sort ( PPChain chain, int nChains, int sortKey ) { 3579 sKey = sortKey; 3580 QuickSort::Sort ( &(chain[0]),nChains ); 3581 } 3582 SortChains(int sortKey)3583 void Model::SortChains ( int sortKey ) { 3584 QSortChains SC; 3585 TrimChainTable(); 3586 SC.Sort ( chain,nChains,sortKey ); 3587 } 3588 3589 3590 // -------------------- Extracting atoms ----------------------- 3591 3592 GetNumberOfAtoms(const ChainID chainID,int seqNo,const InsCode insCode)3593 int Model::GetNumberOfAtoms ( const ChainID chainID, int seqNo, 3594 const InsCode insCode ) { 3595 PChain chn; 3596 PResidue res; 3597 chn = GetChain ( chainID ); 3598 if (chn) { 3599 res = chn->GetResidue ( seqNo,insCode ); 3600 if (res) return res->nAtoms; 3601 } 3602 return 0; 3603 } 3604 GetNumberOfAtoms(int chainNo,int seqNo,const InsCode insCode)3605 int Model::GetNumberOfAtoms ( int chainNo, int seqNo, 3606 const InsCode insCode ) { 3607 PChain chn; 3608 PResidue res; 3609 chn = GetChain ( chainNo ); 3610 if (chn) { 3611 res = chn->GetResidue ( seqNo,insCode ); 3612 if (res) return res->nAtoms; 3613 } 3614 return 0; 3615 } 3616 GetNumberOfAtoms(const ChainID chainID,int resNo)3617 int Model::GetNumberOfAtoms ( const ChainID chainID, int resNo ) { 3618 PChain chn; 3619 PResidue res; 3620 chn = GetChain ( chainID ); 3621 if (chn) { 3622 if ((0<=resNo) && (resNo<chn->nResidues)) { 3623 res = chn->residue[resNo]; 3624 if (res) return res->nAtoms; 3625 } 3626 } 3627 return 0; 3628 } 3629 GetNumberOfAtoms(int chainNo,int resNo)3630 int Model::GetNumberOfAtoms ( int chainNo, int resNo ) { 3631 PChain chn; 3632 PResidue res; 3633 if ((0<=chainNo) && (chainNo<nChains)) { 3634 chn = chain[chainNo]; 3635 if (chn) { 3636 if ((0<=resNo) && (resNo<chn->nResidues)) { 3637 res = chn->residue[resNo]; 3638 if (res) return res->nAtoms; 3639 } 3640 } 3641 } 3642 return 0; 3643 } 3644 GetAtom(const ChainID chID,int seqNo,const InsCode insCode,const AtomName aname,const Element elmnt,const AltLoc aloc)3645 PAtom Model::GetAtom ( const ChainID chID, 3646 int seqNo, 3647 const InsCode insCode, 3648 const AtomName aname, 3649 const Element elmnt, 3650 const AltLoc aloc 3651 ) { 3652 PChain chn; 3653 PResidue res; 3654 chn = GetChain ( chID ); 3655 if (chn) { 3656 res = chn->GetResidue ( seqNo,insCode ); 3657 if (res) 3658 return res->GetAtom ( aname,elmnt,aloc ); 3659 } 3660 return NULL; 3661 } 3662 GetAtom(const ChainID chID,int seqNo,const InsCode insCode,int atomNo)3663 PAtom Model::GetAtom ( const ChainID chID, int seqNo, 3664 const InsCode insCode, int atomNo ) { 3665 PChain chn; 3666 PResidue res; 3667 chn = GetChain ( chID ); 3668 if (chn) { 3669 res = chn->GetResidue ( seqNo,insCode ); 3670 if (res) { 3671 if ((0<=atomNo) && (atomNo<res->nAtoms)) 3672 return res->atom[atomNo]; 3673 } 3674 } 3675 return NULL; 3676 } 3677 GetAtom(const ChainID chID,int resNo,const AtomName aname,const Element elmnt,const AltLoc aloc)3678 PAtom Model::GetAtom ( const ChainID chID, 3679 int resNo, 3680 const AtomName aname, 3681 const Element elmnt, 3682 const AltLoc aloc ) { 3683 PChain chn; 3684 PResidue res; 3685 chn = GetChain ( chID ); 3686 if (chn) { 3687 if ((0<=resNo) && (resNo<chn->nResidues)) { 3688 res = chn->residue[resNo]; 3689 if (res) 3690 return res->GetAtom ( aname,elmnt,aloc ); 3691 } 3692 } 3693 return NULL; 3694 } 3695 GetAtom(const ChainID chID,int resNo,int atomNo)3696 PAtom Model::GetAtom ( const ChainID chID, int resNo, int atomNo ) { 3697 PChain chn; 3698 PResidue res; 3699 chn = GetChain ( chID ); 3700 if (chn) { 3701 if ((0<=resNo) && (resNo<chn->nResidues)) { 3702 res = chn->residue[resNo]; 3703 if (res) { 3704 if ((0<=atomNo) && (atomNo<res->nAtoms)) 3705 return res->atom[atomNo]; 3706 } 3707 } 3708 } 3709 return NULL; 3710 } 3711 GetAtom(int chNo,int seqNo,const InsCode insCode,const AtomName aname,const Element elmnt,const AltLoc aloc)3712 PAtom Model::GetAtom ( int chNo, int seqNo, 3713 const InsCode insCode, 3714 const AtomName aname, 3715 const Element elmnt, 3716 const AltLoc aloc ) { 3717 PResidue res; 3718 if ((0<=chNo) && (chNo<nChains)) { 3719 if (chain[chNo]) { 3720 res = chain[chNo]->GetResidue ( seqNo,insCode ); 3721 if (res) 3722 return res->GetAtom ( aname,elmnt,aloc ); 3723 } 3724 } 3725 return NULL; 3726 } 3727 GetAtom(int chNo,int seqNo,const InsCode insCode,int atomNo)3728 PAtom Model::GetAtom ( int chNo, int seqNo, const InsCode insCode, 3729 int atomNo ) { 3730 PResidue res; 3731 if ((0<=chNo) && (chNo<nChains)) { 3732 if (chain[chNo]) { 3733 res = chain[chNo]->GetResidue ( seqNo,insCode ); 3734 if (res) { 3735 if ((0<=atomNo) && (atomNo<res->nAtoms)) 3736 return res->atom[atomNo]; 3737 } 3738 } 3739 } 3740 return NULL; 3741 } 3742 GetAtom(int chNo,int resNo,const AtomName aname,const Element elmnt,const AltLoc aloc)3743 PAtom Model::GetAtom ( int chNo, int resNo, 3744 const AtomName aname, 3745 const Element elmnt, 3746 const AltLoc aloc ) { 3747 PResidue res; 3748 if ((0<=chNo) && (chNo<nChains)) { 3749 if (chain[chNo]) { 3750 if ((0<=resNo) && (resNo<chain[chNo]->nResidues)) { 3751 res = chain[chNo]->residue[resNo]; 3752 if (res) 3753 return res->GetAtom ( aname,elmnt,aloc ); 3754 } 3755 } 3756 } 3757 return NULL; 3758 } 3759 GetAtom(int chNo,int resNo,int atomNo)3760 PAtom Model::GetAtom ( int chNo, int resNo, int atomNo ) { 3761 PResidue res; 3762 if ((0<=chNo) && (chNo<nChains)) { 3763 if (chain[chNo]) { 3764 if ((0<=resNo) && (resNo<chain[chNo]->nResidues)) { 3765 res = chain[chNo]->residue[resNo]; 3766 if (res) { 3767 if ((0<=atomNo) && (atomNo<res->nAtoms)) 3768 return res->atom[atomNo]; 3769 } 3770 } 3771 } 3772 } 3773 return NULL; 3774 } 3775 3776 GetAtomTable(const ChainID chainID,int seqNo,const InsCode insCode,PPAtom & atomTable,int & NumberOfAtoms)3777 void Model::GetAtomTable ( const ChainID chainID, int seqNo, 3778 const InsCode insCode, 3779 PPAtom & atomTable, 3780 int & NumberOfAtoms ) { 3781 PResidue res; 3782 atomTable = NULL; 3783 NumberOfAtoms = 0; 3784 res = GetResidue ( chainID,seqNo,insCode ); 3785 if (res) { 3786 atomTable = res->atom; 3787 NumberOfAtoms = res->nAtoms; 3788 } 3789 } 3790 GetAtomTable(int chainNo,int seqNo,const InsCode insCode,PPAtom & atomTable,int & NumberOfAtoms)3791 void Model::GetAtomTable ( int chainNo, int seqNo, 3792 const InsCode insCode, 3793 PPAtom & atomTable, 3794 int & NumberOfAtoms ) { 3795 PResidue res; 3796 atomTable = NULL; 3797 NumberOfAtoms = 0; 3798 res = GetResidue ( chainNo,seqNo,insCode ); 3799 if (res) { 3800 atomTable = res->atom; 3801 NumberOfAtoms = res->nAtoms; 3802 } 3803 } 3804 GetAtomTable(const ChainID chainID,int resNo,PPAtom & atomTable,int & NumberOfAtoms)3805 void Model::GetAtomTable ( const ChainID chainID, int resNo, 3806 PPAtom & atomTable, 3807 int & NumberOfAtoms ) { 3808 PResidue res; 3809 atomTable = NULL; 3810 NumberOfAtoms = 0; 3811 res = GetResidue ( chainID,resNo ); 3812 if (res) { 3813 atomTable = res->atom; 3814 NumberOfAtoms = res->nAtoms; 3815 } 3816 } 3817 GetAtomTable(int chainNo,int resNo,PPAtom & atomTable,int & NumberOfAtoms)3818 void Model::GetAtomTable ( int chainNo, int resNo, 3819 PPAtom & atomTable, 3820 int & NumberOfAtoms ) { 3821 PResidue res; 3822 atomTable = NULL; 3823 NumberOfAtoms = 0; 3824 res = GetResidue ( chainNo,resNo ); 3825 if (res) { 3826 atomTable = res->atom; 3827 NumberOfAtoms = res->nAtoms; 3828 } 3829 } 3830 3831 GetAtomTable1(const ChainID chainID,int seqNo,const InsCode insCode,PPAtom & atomTable,int & NumberOfAtoms)3832 void Model::GetAtomTable1 ( const ChainID chainID, int seqNo, 3833 const InsCode insCode, 3834 PPAtom & atomTable, 3835 int & NumberOfAtoms ) { 3836 PResidue res; 3837 res = GetResidue ( chainID,seqNo,insCode ); 3838 if (res) 3839 res->GetAtomTable1 ( atomTable,NumberOfAtoms ); 3840 else { 3841 if (atomTable) delete[] atomTable; 3842 atomTable = NULL; 3843 NumberOfAtoms = 0; 3844 } 3845 } 3846 GetAtomTable1(int chainNo,int seqNo,const InsCode insCode,PPAtom & atomTable,int & NumberOfAtoms)3847 void Model::GetAtomTable1 ( int chainNo, int seqNo, 3848 const InsCode insCode, 3849 PPAtom & atomTable, 3850 int & NumberOfAtoms ) { 3851 PResidue res; 3852 res = GetResidue ( chainNo,seqNo,insCode ); 3853 if (res) 3854 res->GetAtomTable1 ( atomTable,NumberOfAtoms ); 3855 else { 3856 if (atomTable) delete[] atomTable; 3857 atomTable = NULL; 3858 NumberOfAtoms = 0; 3859 } 3860 } 3861 GetAtomTable1(const ChainID chainID,int resNo,PPAtom & atomTable,int & NumberOfAtoms)3862 void Model::GetAtomTable1 ( const ChainID chainID, int resNo, 3863 PPAtom & atomTable, 3864 int & NumberOfAtoms ) { 3865 PResidue res; 3866 res = GetResidue ( chainID,resNo ); 3867 if (res) 3868 res->GetAtomTable1 ( atomTable,NumberOfAtoms ); 3869 else { 3870 if (atomTable) delete[] atomTable; 3871 atomTable = NULL; 3872 NumberOfAtoms = 0; 3873 } 3874 } 3875 GetAtomTable1(int chainNo,int resNo,PPAtom & atomTable,int & NumberOfAtoms)3876 void Model::GetAtomTable1 ( int chainNo, int resNo, 3877 PPAtom & atomTable, 3878 int & NumberOfAtoms ) { 3879 PResidue res; 3880 res = GetResidue ( chainNo,resNo ); 3881 if (res) 3882 res->GetAtomTable1 ( atomTable,NumberOfAtoms ); 3883 else { 3884 if (atomTable) delete[] atomTable; 3885 atomTable = NULL; 3886 NumberOfAtoms = 0; 3887 } 3888 } 3889 3890 3891 DeleteAtom(const ChainID chID,int seqNo,const InsCode insCode,const AtomName aname,const Element elmnt,const AltLoc aloc)3892 int Model::DeleteAtom ( const ChainID chID, 3893 int seqNo, 3894 const InsCode insCode, 3895 const AtomName aname, 3896 const Element elmnt, 3897 const AltLoc aloc 3898 ) { 3899 PChain chn; 3900 chn = GetChain ( chID ); 3901 if (chn) 3902 return chn->DeleteAtom ( seqNo,insCode,aname,elmnt,aloc ); 3903 return 0; 3904 } 3905 DeleteAtom(const ChainID chID,int seqNo,const InsCode insCode,int atomNo)3906 int Model::DeleteAtom ( const ChainID chID, int seqNo, 3907 const InsCode insCode, int atomNo ) { 3908 PChain chn; 3909 chn = GetChain ( chID ); 3910 if (chn) return chn->DeleteAtom ( seqNo,insCode,atomNo ); 3911 return 0; 3912 } 3913 DeleteAtom(const ChainID chID,int resNo,const AtomName aname,const Element elmnt,const AltLoc aloc)3914 int Model::DeleteAtom ( const ChainID chID, 3915 int resNo, 3916 const AtomName aname, 3917 const Element elmnt, 3918 const AltLoc aloc ) { 3919 PChain chn; 3920 chn = GetChain ( chID ); 3921 if (chn) return chn->DeleteAtom ( resNo,aname,elmnt,aloc ); 3922 return 0; 3923 } 3924 DeleteAtom(const ChainID chID,int resNo,int atomNo)3925 int Model::DeleteAtom ( const ChainID chID, int resNo, int atomNo ) { 3926 PChain chn; 3927 chn = GetChain ( chID ); 3928 if (chn) return chn->DeleteAtom ( resNo,atomNo ); 3929 return 0; 3930 } 3931 DeleteAtom(int chNo,int seqNo,const InsCode insCode,const AtomName aname,const Element elmnt,const AltLoc aloc)3932 int Model::DeleteAtom ( int chNo, int seqNo, 3933 const InsCode insCode, 3934 const AtomName aname, 3935 const Element elmnt, 3936 const AltLoc aloc ) { 3937 if ((0<=chNo) && (chNo<nChains)) { 3938 if (chain[chNo]) 3939 return chain[chNo]->DeleteAtom ( seqNo,insCode,aname, 3940 elmnt,aloc ); 3941 } 3942 return 0; 3943 } 3944 DeleteAtom(int chNo,int seqNo,const InsCode insCode,int atomNo)3945 int Model::DeleteAtom ( int chNo, int seqNo, const InsCode insCode, 3946 int atomNo ) { 3947 if ((0<=chNo) && (chNo<nChains)) { 3948 if (chain[chNo]) 3949 return chain[chNo]->DeleteAtom ( seqNo,insCode,atomNo ); 3950 } 3951 return 0; 3952 } 3953 DeleteAtom(int chNo,int resNo,const AtomName aname,const Element elmnt,const AltLoc aloc)3954 int Model::DeleteAtom ( int chNo, int resNo, 3955 const AtomName aname, 3956 const Element elmnt, 3957 const AltLoc aloc ) { 3958 if ((0<=chNo) && (chNo<nChains)) { 3959 if (chain[chNo]) 3960 return chain[chNo]->DeleteAtom ( resNo,aname,elmnt,aloc ); 3961 } 3962 return 0; 3963 } 3964 DeleteAtom(int chNo,int resNo,int atomNo)3965 int Model::DeleteAtom ( int chNo, int resNo, int atomNo ) { 3966 if ((0<=chNo) && (chNo<nChains)) { 3967 if (chain[chNo]) 3968 return chain[chNo]->DeleteAtom ( resNo,atomNo ); 3969 } 3970 return 0; 3971 } 3972 DeleteAllAtoms(const ChainID chID,int seqNo,const InsCode insCode)3973 int Model::DeleteAllAtoms ( const ChainID chID, int seqNo, 3974 const InsCode insCode ) { 3975 PChain chn; 3976 chn = GetChain ( chID ); 3977 if (chn) return chn->DeleteAllAtoms ( seqNo,insCode ); 3978 return 0; 3979 } 3980 DeleteAllAtoms(const ChainID chID,int resNo)3981 int Model::DeleteAllAtoms ( const ChainID chID, int resNo ) { 3982 PChain chn; 3983 chn = GetChain ( chID ); 3984 if (chn) return chn->DeleteAllAtoms ( resNo ); 3985 return 0; 3986 } 3987 DeleteAllAtoms(const ChainID chID)3988 int Model::DeleteAllAtoms ( const ChainID chID ) { 3989 PChain chn; 3990 chn = GetChain ( chID ); 3991 if (chn) return chn->DeleteAllAtoms(); 3992 return 0; 3993 } 3994 DeleteAllAtoms(int chNo,int seqNo,const InsCode insCode)3995 int Model::DeleteAllAtoms ( int chNo, int seqNo, 3996 const InsCode insCode ) { 3997 if ((0<=chNo) && (chNo<nChains)) { 3998 if (chain[chNo]) 3999 return chain[chNo]->DeleteAllAtoms ( seqNo,insCode ); 4000 } 4001 return 0; 4002 } 4003 DeleteAllAtoms(int chNo,int resNo)4004 int Model::DeleteAllAtoms ( int chNo, int resNo ) { 4005 if ((0<=chNo) && (chNo<nChains)) { 4006 if (chain[chNo]) 4007 return chain[chNo]->DeleteAllAtoms ( resNo ); 4008 } 4009 return 0; 4010 } 4011 DeleteAllAtoms(int chNo)4012 int Model::DeleteAllAtoms ( int chNo ) { 4013 if ((0<=chNo) && (chNo<nChains)) { 4014 if (chain[chNo]) 4015 return chain[chNo]->DeleteAllAtoms(); 4016 } 4017 return 0; 4018 } 4019 DeleteAllAtoms()4020 int Model::DeleteAllAtoms() { 4021 int i,k; 4022 k = 0; 4023 for (i=0;i<nChains;i++) 4024 if (chain[i]) k += chain[i]->DeleteAllAtoms(); 4025 return k; 4026 } 4027 DeleteAltLocs()4028 int Model::DeleteAltLocs() { 4029 // This function leaves only alternative location with maximal 4030 // occupancy, if those are equal or unspecified, the one with 4031 // "least" alternative location indicator. 4032 // The function returns the number of deleted. All tables remain 4033 // untrimmed, so that explicit trimming or calling FinishStructEdit() 4034 // is required. 4035 int i,n; 4036 4037 n = 0; 4038 for (i=0;i<nChains;i++) 4039 if (chain[i]) n += chain[i]->DeleteAltLocs(); 4040 4041 return n; 4042 4043 } 4044 4045 AddAtom(const ChainID chID,int seqNo,const InsCode insCode,PAtom atom)4046 int Model::AddAtom ( const ChainID chID, int seqNo, 4047 const InsCode insCode, 4048 PAtom atom ) { 4049 PChain chn; 4050 chn = GetChain ( chID ); 4051 if (chn) return chn->AddAtom ( seqNo,insCode,atom ); 4052 return 0; 4053 } 4054 AddAtom(const ChainID chID,int resNo,PAtom atom)4055 int Model::AddAtom ( const ChainID chID, int resNo, PAtom atom ) { 4056 PChain chn; 4057 chn = GetChain ( chID ); 4058 if (chn) return chn->AddAtom ( resNo,atom ); 4059 return 0; 4060 } 4061 AddAtom(int chNo,int seqNo,const InsCode insCode,PAtom atom)4062 int Model::AddAtom ( int chNo, int seqNo, const InsCode insCode, 4063 PAtom atom ) { 4064 if ((0<=chNo) && (chNo<nChains)) { 4065 if (chain[chNo]) 4066 return chain[chNo]->AddAtom ( seqNo,insCode,atom ); 4067 } 4068 return 0; 4069 } 4070 AddAtom(int chNo,int resNo,PAtom atom)4071 int Model::AddAtom ( int chNo, int resNo, PAtom atom ) { 4072 if ((0<=chNo) && (chNo<nChains)) { 4073 if (chain[chNo]) 4074 return chain[chNo]->AddAtom ( resNo,atom ); 4075 } 4076 return 0; 4077 } 4078 4079 4080 GetAtomStatistics(RAtomStat AS)4081 void Model::GetAtomStatistics ( RAtomStat AS ) { 4082 AS.Init(); 4083 CalAtomStatistics ( AS ); 4084 AS.Finish(); 4085 } 4086 CalAtomStatistics(RAtomStat AS)4087 void Model::CalAtomStatistics ( RAtomStat AS ) { 4088 int i; 4089 for (i=0;i<nChains;i++) 4090 if (chain[i]) chain[i]->CalAtomStatistics ( AS ); 4091 } 4092 4093 4094 ConvertPDBString(pstr PDBString)4095 ERROR_CODE Model::ConvertPDBString ( pstr PDBString ) { 4096 // Interprets PDB records DBREF, SEQADV, SEQRES, MODRES. 4097 // Returns zero if the line was converted, otherwise returns a 4098 // non-negative value of Error_XXXX. 4099 // PDBString must be not shorter than 81 characters. 4100 ChainID chainID; 4101 PChain chn; 4102 PHelix helix; 4103 PTurn turn; 4104 PLink link; 4105 PLinkR linkR; 4106 PCisPep cispep; 4107 ERROR_CODE RC; 4108 4109 // pad input line with spaces, if necessary 4110 PadSpaces ( PDBString,80 ); 4111 4112 chainID[0] = char(0); 4113 chainID[1] = char(0); 4114 4115 if (!strncmp(PDBString,"DBREF ",6)) { 4116 4117 if (PDBString[12]!=' ') chainID[0] = PDBString[12]; 4118 chn = GetChainCreate ( chainID,false ); 4119 return chn->ConvertDBREF ( PDBString ); 4120 4121 } else if (!strncmp(PDBString,"SEQADV",6)) { 4122 4123 if (PDBString[16]!=' ') chainID[0] = PDBString[16]; 4124 chn = GetChainCreate ( chainID,false ); 4125 return chn->ConvertSEQADV ( PDBString ); 4126 4127 } else if (!strncmp(PDBString,"SEQRES",6)) { 4128 4129 if (PDBString[11]!=' ') chainID[0] = PDBString[11]; 4130 chn = GetChainCreate ( chainID,false ); 4131 return chn->ConvertSEQRES ( PDBString ); 4132 4133 } else if (!strncmp(PDBString,"MODRES",6)) { 4134 4135 if (PDBString[16]!=' ') chainID[0] = PDBString[16]; 4136 chn = GetChainCreate ( chainID,false ); 4137 return chn->ConvertMODRES ( PDBString ); 4138 4139 } else if (!strncmp(PDBString,"HET ",6)) { 4140 4141 if (PDBString[12]!=' ') chainID[0] = PDBString[12]; 4142 chn = GetChainCreate ( chainID,false ); 4143 return chn->ConvertHET ( PDBString ); 4144 4145 } else if (!strncmp(PDBString,"HETNAM",6)) { 4146 4147 hetCompounds.ConvertHETNAM ( PDBString ); 4148 return Error_NoError; 4149 4150 } else if (!strncmp(PDBString,"HETSYN",6)) { 4151 4152 hetCompounds.ConvertHETSYN ( PDBString ); 4153 return Error_NoError; 4154 4155 } else if (!strncmp(PDBString,"FORMUL",6)) { 4156 4157 hetCompounds.ConvertFORMUL ( PDBString ); 4158 return Error_NoError; 4159 4160 } else if (!strncmp(PDBString,"HELIX ",6)) { 4161 4162 helix = new Helix(); 4163 RC = helix->ConvertPDBASCII(PDBString); 4164 if (RC==0) helices.AddData ( helix ); 4165 else delete helix; 4166 return RC; 4167 4168 } else if (!strncmp(PDBString,"SHEET ",6)) { 4169 4170 return sheets.ConvertPDBASCII ( PDBString ); 4171 4172 } else if (!strncmp(PDBString,"TURN ",6)) { 4173 4174 turn = new Turn(); 4175 RC = turn->ConvertPDBASCII(PDBString); 4176 if (RC==0) turns.AddData ( turn ); 4177 else delete turn; 4178 return RC; 4179 4180 } else if (!strncmp(PDBString,"LINK ",6)) { 4181 4182 link = new Link(); 4183 RC = link->ConvertPDBASCII(PDBString); 4184 if (RC==0) links.AddData ( link ); 4185 else delete link; 4186 return RC; 4187 4188 4189 } else if (!strncmp(PDBString,"LINKR ",6)) { 4190 4191 linkR = new LinkR(); 4192 RC = linkR->ConvertPDBASCII(PDBString); 4193 if (RC==0) linkRs.AddData ( linkR ); 4194 else delete linkR; 4195 return RC; 4196 4197 } else if (!strncmp(PDBString,"CISPEP",6)) { 4198 4199 cispep = new CisPep(); 4200 RC = cispep->ConvertPDBASCII(PDBString); 4201 if (RC==0) cisPeps.AddData ( cispep ); 4202 else delete cispep; 4203 return RC; 4204 4205 } else 4206 return Error_WrongSection; 4207 4208 } 4209 4210 PDBASCIIDumpPS(io::RFile f)4211 void Model::PDBASCIIDumpPS ( io::RFile f ) { 4212 int i; 4213 4214 for (i=0;i<nChains;i++) 4215 if (chain[i]) 4216 chain[i]->DBRef.PDBASCIIDump ( f ); 4217 4218 for (i=0;i<nChains;i++) 4219 if (chain[i]) 4220 chain[i]->seqAdv.PDBASCIIDump ( f ); 4221 4222 for (i=0;i<nChains;i++) 4223 if (chain[i]) 4224 chain[i]->seqRes.PDBASCIIDump ( f ); 4225 4226 for (i=0;i<nChains;i++) 4227 if (chain[i]) 4228 chain[i]->modRes.PDBASCIIDump ( f ); 4229 4230 for (i=0;i<nChains;i++) 4231 if (chain[i]) 4232 chain[i]->Het.PDBASCIIDump ( f ); 4233 4234 hetCompounds.PDBASCIIDump ( f ); 4235 helices .PDBASCIIDump ( f ); 4236 sheets .PDBASCIIDump ( f ); 4237 turns .PDBASCIIDump ( f ); 4238 links .PDBASCIIDump ( f ); 4239 linkRs .PDBASCIIDump ( f ); 4240 4241 } 4242 PDBASCIIDumpCP(io::RFile f)4243 void Model::PDBASCIIDumpCP ( io::RFile f ) { 4244 cisPeps.PDBASCIIDump ( f ); 4245 } 4246 PDBASCIIDump(io::RFile f)4247 void Model::PDBASCIIDump ( io::RFile f ) { 4248 char S[100]; 4249 int i; 4250 bool singleModel = true; 4251 4252 if (manager) 4253 singleModel = (manager->nModels<=1); 4254 4255 if (!singleModel) { 4256 strcpy ( S,"MODEL " ); 4257 PadSpaces ( S,80 ); 4258 PutInteger ( &(S[10]),serNum,4 ); 4259 f.WriteLine ( S ); 4260 } 4261 4262 for (i=0;i<nChains;i++) 4263 if (chain[i]) 4264 chain[i]->PDBASCIIAtomDump ( f ); 4265 4266 if (!singleModel) { 4267 strcpy ( S,"ENDMDL" ); 4268 PadSpaces ( S,80 ); 4269 f.WriteLine ( S ); 4270 } 4271 4272 } 4273 4274 MakeAtomCIF(mmcif::PData CIF)4275 void Model::MakeAtomCIF ( mmcif::PData CIF ) { 4276 int i; 4277 for (i=0;i<nChains;i++) 4278 if (chain[i]) 4279 chain[i]->MakeAtomCIF ( CIF ); 4280 } 4281 4282 MakePSCIF(mmcif::PData CIF)4283 void Model::MakePSCIF ( mmcif::PData CIF ) { 4284 int i; 4285 4286 for (i=0;i<nChains;i++) 4287 if (chain[i]) 4288 chain[i]->DBRef.MakeCIF ( CIF ); 4289 4290 for (i=0;i<nChains;i++) 4291 if (chain[i]) 4292 chain[i]->seqAdv.MakeCIF ( CIF ); 4293 4294 for (i=0;i<nChains;i++) 4295 if (chain[i]) 4296 chain[i]->seqRes.MakeCIF ( CIF ); 4297 4298 for (i=0;i<nChains;i++) 4299 if (chain[i]) 4300 chain[i]->modRes.MakeCIF ( CIF ); 4301 4302 for (i=0;i<nChains;i++) 4303 if (chain[i]) 4304 chain[i]->Het.MakeCIF ( CIF ); 4305 4306 hetCompounds.MakeCIF ( CIF ); 4307 helices .MakeCIF ( CIF ); 4308 sheets .MakeCIF ( CIF ); 4309 turns .MakeCIF ( CIF ); 4310 links .MakeCIF ( CIF ); 4311 linkRs .MakeCIF ( CIF ); 4312 4313 } 4314 GetCIFPSClass(mmcif::PData CIF,int ClassID)4315 ERROR_CODE Model::GetCIFPSClass ( mmcif::PData CIF, int ClassID ) { 4316 ChainContainer PSClass; 4317 PChainContainer Dest; 4318 ERROR_CODE RC; 4319 cpstr chainID; 4320 PChain chn; 4321 PSClass.SetChain ( NULL ); 4322 RC = PSClass.GetCIF ( CIF,ClassID ); 4323 if (RC!=Error_NoError) return RC; 4324 chainID = PSClass.Get1stChainID(); 4325 while (chainID) { 4326 chn = GetChainCreate ( chainID,false ); 4327 switch (ClassID) { 4328 case ClassID_DBReference : Dest = &(chn->DBRef); break; 4329 case ClassID_SeqAdv : Dest = &(chn->seqAdv); break; 4330 case ClassID_ModRes : Dest = &(chn->modRes); break; 4331 case ClassID_Het : Dest = &(chn->Het); break; 4332 default : Dest = NULL; 4333 } 4334 if (Dest) { 4335 PSClass.MoveByChainID ( chainID,Dest ); 4336 Dest->SetChain ( chn ); 4337 } else 4338 printf ( " **** PROGRAM ERROR: wrong call to" 4339 " Model::GetCIFPSClass(..)\n" ); 4340 chainID = PSClass.Get1stChainID(); 4341 } 4342 return Error_NoError; 4343 } 4344 GetCIF(mmcif::PData CIF)4345 ERROR_CODE Model::GetCIF ( mmcif::PData CIF ) { 4346 SeqRes seqRes; 4347 ERROR_CODE RC; 4348 PChain chn; 4349 4350 RC = GetCIFPSClass ( CIF,ClassID_DBReference ); 4351 if (RC!=Error_NoError) return RC; 4352 4353 RC = GetCIFPSClass ( CIF,ClassID_SeqAdv ); 4354 if (RC!=Error_NoError) return RC; 4355 4356 RC = seqRes.GetCIF ( CIF ); 4357 while (RC==Error_NoError) { 4358 chn = GetChainCreate ( seqRes.chainID,false ); 4359 chn->seqRes.Copy ( &seqRes ); 4360 RC = seqRes.GetCIF ( CIF ); 4361 } 4362 4363 RC = GetCIFPSClass ( CIF,ClassID_ModRes ); 4364 if (RC!=Error_NoError) return RC; 4365 4366 RC = GetCIFPSClass ( CIF,ClassID_Het ); 4367 if (RC!=Error_NoError) return RC; 4368 4369 hetCompounds.GetCIF ( CIF ); 4370 helices .GetCIF ( CIF,ClassID_Helix ); 4371 sheets .GetCIF ( CIF ); 4372 turns .GetCIF ( CIF,ClassID_Turn ); 4373 links .GetCIF ( CIF,ClassID_Link ); 4374 linkRs .GetCIF ( CIF,ClassID_LinkR ); 4375 4376 return RC; 4377 4378 } 4379 GetEntryID()4380 cpstr Model::GetEntryID() { 4381 if (manager) return manager->title.idCode; 4382 else return pstr(""); 4383 } 4384 SetEntryID(const IDCode idCode)4385 void Model::SetEntryID ( const IDCode idCode ) { 4386 if (manager) 4387 manager->SetEntryID ( idCode ); 4388 } 4389 GetNumberOfAllAtoms()4390 int Model::GetNumberOfAllAtoms() { 4391 if (manager) return manager->nAtoms; 4392 else return 0; 4393 } 4394 GetSerNum()4395 int Model::GetSerNum() { 4396 return serNum; 4397 } 4398 GetAllAtoms()4399 PAtom * Model::GetAllAtoms() { 4400 if (manager) return manager->atom; 4401 else return NULL; 4402 } 4403 4404 GetModelID(pstr modelID)4405 cpstr Model::GetModelID ( pstr modelID ) { 4406 modelID[0] = char(0); 4407 sprintf ( modelID,"/%i",serNum ); 4408 return modelID; 4409 } 4410 GetNumberOfModels()4411 int Model::GetNumberOfModels() { 4412 if (manager) return manager->nModels; 4413 else return 0; 4414 } 4415 4416 Copy(PModel model)4417 void Model::Copy ( PModel model ) { 4418 // modify both Model::_copy and Model::Copy methods simultaneously! 4419 int i; 4420 4421 FreeMemory(); 4422 4423 if (model) { 4424 4425 serNum = model->serNum; 4426 nChains = model->nChains; 4427 nChainsAlloc = nChains; 4428 if (nChains>0) { 4429 chain = new PChain[nChainsAlloc]; 4430 for (i=0;i<nChains;i++) { 4431 if (model->chain[i]) { 4432 chain[i] = newChain(); 4433 chain[i]->SetModel ( this ); 4434 chain[i]->Copy ( model->chain[i] ); 4435 } else 4436 chain[i] = NULL; 4437 } 4438 } 4439 4440 hetCompounds.Copy ( &(model->hetCompounds) ); 4441 helices .Copy ( &(model->helices) ); 4442 sheets .Copy ( &(model->sheets) ); 4443 turns .Copy ( &(model->turns) ); 4444 links .Copy ( &(model->links) ); 4445 linkRs .Copy ( &(model->linkRs) ); 4446 cisPeps .Copy ( &(model->cisPeps) ); 4447 4448 } 4449 4450 } 4451 CopyHets(PModel model)4452 void Model::CopyHets ( PModel model ) { 4453 if (model) hetCompounds.Copy ( &(model->hetCompounds) ); 4454 } 4455 CopySecStructure(PModel model)4456 void Model::CopySecStructure ( PModel model ) { 4457 if (model) { 4458 helices.Copy ( &(model->helices) ); 4459 sheets .Copy ( &(model->sheets) ); 4460 turns .Copy ( &(model->turns) ); 4461 } 4462 } 4463 CopyLinks(PModel model)4464 void Model::CopyLinks ( PModel model ) { 4465 if (model)links.Copy ( &(model->links) ); 4466 } 4467 CopyLinkRs(PModel model)4468 void Model::CopyLinkRs ( PModel model ) { 4469 if (model) linkRs.Copy ( &(model->linkRs) ); 4470 } 4471 CopyCisPeps(PModel model)4472 void Model::CopyCisPeps ( PModel model ) { 4473 if (model) cisPeps.Copy ( &(model->cisPeps) ); 4474 } 4475 _copy(PModel model)4476 void Model::_copy ( PModel model ) { 4477 // modify both Model::_copy and Model::Copy methods simultaneously! 4478 int i; 4479 4480 FreeMemory(); 4481 4482 if (model) { 4483 4484 serNum = model->serNum; 4485 nChains = model->nChains; 4486 nChainsAlloc = nChains; 4487 if (nChains>0) { 4488 chain = new PChain[nChainsAlloc]; 4489 for (i=0;i<nChains;i++) { 4490 if (model->chain[i]) { 4491 chain[i] = newChain(); 4492 chain[i]->SetModel ( this ); 4493 chain[i]->_copy ( model->chain[i] ); 4494 } else 4495 chain[i] = NULL; 4496 } 4497 } 4498 4499 hetCompounds.Copy ( &(model->hetCompounds) ); 4500 helices .Copy ( &(model->helices) ); 4501 sheets .Copy ( &(model->sheets) ); 4502 turns .Copy ( &(model->turns) ); 4503 links .Copy ( &(model->links) ); 4504 linkRs .Copy ( &(model->linkRs) ); 4505 cisPeps .Copy ( &(model->cisPeps) ); 4506 4507 } 4508 4509 } 4510 4511 _copy(PModel model,PPAtom atom,int & atom_index)4512 void Model::_copy ( PModel model, PPAtom atom, int & atom_index ) { 4513 // modify both Model::_copy and Model::Copy methods simultaneously! 4514 // 4515 // _copy(PModel,PPAtom,int&) does copy atoms into array 'atom' 4516 // starting from position atom_index. 'atom' should be able to 4517 // accept all new atoms - no checks on the length of 'atom' 4518 // is being made. This function should not be used in applications. 4519 int i; 4520 4521 FreeMemory(); 4522 4523 if (model) { 4524 4525 serNum = model->serNum; 4526 nChains = model->nChains; 4527 nChainsAlloc = nChains; 4528 if (nChains>0) { 4529 chain = new PChain[nChainsAlloc]; 4530 for (i=0;i<nChains;i++) { 4531 if (model->chain[i]) { 4532 chain[i] = newChain(); 4533 chain[i]->SetModel ( this ); 4534 chain[i]->_copy ( model->chain[i],atom,atom_index ); 4535 } else 4536 chain[i] = NULL; 4537 } 4538 } 4539 4540 hetCompounds.Copy ( &(model->hetCompounds) ); 4541 helices .Copy ( &(model->helices) ); 4542 sheets .Copy ( &(model->sheets) ); 4543 turns .Copy ( &(model->turns) ); 4544 links .Copy ( &(model->links) ); 4545 linkRs .Copy ( &(model->linkRs) ); 4546 4547 } 4548 4549 } 4550 4551 AddChain(PChain chn)4552 int Model::AddChain ( PChain chn ) { 4553 // modify both Model::Copy methods simultaneously! 4554 // 4555 // Copy(PModel,PPAtom,int&) copies atoms into array 'atom' 4556 // starting from position atom_index. 'atom' should be able to 4557 // accept all new atoms - no checks on the length of 'atom' 4558 // is being made. This function should not be used in applications. 4559 PModel model1; 4560 int i; 4561 4562 for (i=0;i<nChains;i++) 4563 if (chain[i]==chn) return -i; // this chain is already there 4564 4565 if (chn) { 4566 4567 // get space for new chain 4568 ExpandChainArray ( nChains ); 4569 4570 if (chn->GetCoordHierarchy()) { 4571 // The chain is associated with a coordinate hierarchy. It should 4572 // remain there, therefore we physically copy all its residues 4573 // and atoms. 4574 chain[nChains] = newChain(); 4575 chain[nChains]->SetModel ( this ); 4576 if (manager) { 4577 // get space for new atoms 4578 manager->AddAtomArray ( chn->GetNumberOfAtoms(true) ); 4579 chain[nChains]->_copy ( chn,manager->atom,manager->nAtoms ); 4580 } else { 4581 for (i=0;i<chn->nResidues;i++) 4582 chain[nChains]->AddResidue ( chn->residue[i] ); 4583 } 4584 } else { 4585 // The chain is not associated with a coordinate hierarchy. Such 4586 // unregistered objects are simply taken over, i.e. moved into 4587 // the new destination (model). 4588 chain[nChains] = chn; 4589 // remove chain from its model: 4590 model1 = chn->GetModel(); 4591 if (model1) 4592 for (i=0;i<model1->nChains;i++) 4593 if (model1->chain[i]==chn) { 4594 model1->chain[i] = NULL; 4595 break; 4596 } 4597 chain[nChains]->SetModel ( this ); 4598 if (manager) 4599 chain[nChains]->CheckInAtoms(); 4600 } 4601 4602 nChains++; 4603 4604 } 4605 4606 return nChains; 4607 4608 } 4609 4610 MoveChain(PChain & m_chain,PPAtom m_atom,PPAtom atom,int & atom_index,int chain_ext)4611 void Model::MoveChain ( PChain & m_chain, PPAtom m_atom, 4612 PPAtom atom, int & atom_index, 4613 int chain_ext ) { 4614 // MoveChain(..) adds chain m_chain on the top Chain array. 4615 // The pointer on chain is then set to NULL (m_chain=NULL). 4616 // If chain_ext is greater than 0, the moved chain will be 4617 // forcefully renamed; the new name is composed as the previous 4618 // one + underscore + chain_ext (e.g. A_1). If thus generated 4619 // name duplicates any of existing chain IDs, or if chain_ext 4620 // was set to 0 and there is a duplication of chain IDs, the 4621 // name is again modified as above, with the extension number 4622 // generated automatically (this may result in IDs like 4623 // A_1_10). 4624 // m_atom must give pointer to the Atom array, from which 4625 // the atoms belonging to m_chain, are moved to Atom array 4626 // given by 'atom', starting from poisition 'atom_index'. 4627 // 'atom_index' is then automatically updated to the next 4628 // free position in 'atom'. 4629 // Note1: the moved atoms will occupy a continuous range 4630 // in 'atom' array; no checks on whether the corresponding 4631 // cells are occupied or not, are performed. 4632 // Note2: the 'atom_index' is numbered from 0 on, i.e. 4633 // it is equal to atom[atom_index]->index-1; atom[]->index 4634 // is assigned automatically. 4635 ChainID chainID; 4636 int i,j,k,Ok; 4637 PPChain chain1; 4638 PResidue crRes; 4639 4640 if (!m_chain) return; 4641 4642 // modify chain ID with the extension given 4643 if (chain_ext>0) 4644 sprintf ( chainID,"%s_%i",m_chain->chainID,chain_ext ); 4645 else strcpy ( chainID,m_chain->chainID ); 4646 4647 // Choose the chain ID. If a chain with such ID is 4648 // already present in the model, it will be assigned 4649 // a new ID 'ID_n', where 'ID' stands for the original 4650 // chain ID and 'n' is the minimum (integer) number 4651 // chosen such that 'name_n' represents a new chain ID 4652 // (in the model). 4653 k = 0; 4654 do { 4655 Ok = true; 4656 for (i=0;(i<nChains) && (Ok);i++) 4657 if (chain[i]) 4658 if (!strcmp(chainID,chain[i]->chainID)) Ok = false; 4659 if (!Ok) { 4660 k++; 4661 if (chain_ext>0) 4662 sprintf ( chainID,"%s_%i_%i",m_chain->chainID, 4663 chain_ext,k ); 4664 else sprintf ( chainID,"%s_%i",m_chain->chainID,k ); 4665 } 4666 } while (!Ok); 4667 4668 // add chain on the top of Chain array. 4669 strcpy ( m_chain->chainID,chainID ); 4670 if (nChains>=nChainsAlloc) { 4671 nChainsAlloc = nChains+10; 4672 chain1 = new PChain[nChainsAlloc]; 4673 k = 0; 4674 for (i=0;i<nChains;i++) 4675 if (chain[i]) chain1[k++] = chain[i]; 4676 for (i=k;i<nChainsAlloc;i++) 4677 chain1[i] = NULL; 4678 if (chain) delete[] chain; 4679 chain = chain1; 4680 } 4681 chain[nChains] = m_chain; 4682 chain[nChains]->SetModel ( this ); 4683 nChains++; 4684 4685 // Move all atoms of the chain. While residues belong 4686 // atoms belong to the chain's manager class. Therefore 4687 // they should be moved from one manager to another. 4688 for (i=0;i<m_chain->nResidues;i++) { 4689 crRes = m_chain->residue[i]; 4690 if (crRes) 4691 for (j=0;j<crRes->nAtoms;j++) 4692 if (crRes->atom[j]) { 4693 k = crRes->atom[j]->index-1; 4694 atom[atom_index] = m_atom[k]; 4695 atom[atom_index]->index = atom_index+1; 4696 atom_index++; 4697 m_atom[k] = NULL; // moved! 4698 } 4699 } 4700 4701 m_chain = NULL; // moved! 4702 4703 } 4704 GetAIndexRange(int & i1,int & i2)4705 void Model::GetAIndexRange ( int & i1, int & i2 ) { 4706 PChain chn; 4707 PResidue res; 4708 int ic,ir,ia; 4709 i1 = MaxInt4; 4710 i2 = MinInt4; 4711 for (ic=0;ic<nChains;ic++) { 4712 chn = chain[ic]; 4713 if (chn) { 4714 for (ir=0;ir<chn->nResidues;ir++) { 4715 res = chn->residue[ir]; 4716 if (res) { 4717 for (ia=0;ia<res->nAtoms;ia++) 4718 if (res->atom[ia]) { 4719 if (res->atom[ia]->index<i1) i1 = res->atom[ia]->index; 4720 if (res->atom[ia]->index>i2) i2 = res->atom[ia]->index; 4721 } 4722 } 4723 } 4724 } 4725 } 4726 4727 } 4728 4729 MaskAtoms(PMask Mask)4730 void Model::MaskAtoms ( PMask Mask ) { 4731 int i; 4732 for (i=0;i<nChains;i++) 4733 if (chain[i]) chain[i]->MaskAtoms ( Mask ); 4734 } 4735 MaskResidues(PMask Mask)4736 void Model::MaskResidues ( PMask Mask ) { 4737 int i; 4738 for (i=0;i<nChains;i++) 4739 if (chain[i]) chain[i]->MaskResidues ( Mask ); 4740 } 4741 MaskChains(PMask Mask)4742 void Model::MaskChains ( PMask Mask ) { 4743 int i; 4744 for (i=0;i<nChains;i++) 4745 if (chain[i]) chain[i]->SetMask ( Mask ); 4746 } 4747 UnmaskAtoms(PMask Mask)4748 void Model::UnmaskAtoms ( PMask Mask ) { 4749 int i; 4750 for (i=0;i<nChains;i++) 4751 if (chain[i]) chain[i]->UnmaskAtoms ( Mask ); 4752 } 4753 UnmaskResidues(PMask Mask)4754 void Model::UnmaskResidues ( PMask Mask ) { 4755 int i; 4756 for (i=0;i<nChains;i++) 4757 if (chain[i]) chain[i]->UnmaskResidues ( Mask ); 4758 } 4759 UnmaskChains(PMask Mask)4760 void Model::UnmaskChains ( PMask Mask ) { 4761 int i; 4762 for (i=0;i<nChains;i++) 4763 if (chain[i]) chain[i]->RemoveMask ( Mask ); 4764 } 4765 4766 4767 // ------ Getting Secondary Structure Elements 4768 GetNumberOfHelices()4769 int Model::GetNumberOfHelices() { 4770 return helices.Length(); 4771 } 4772 GetNumberOfSheets()4773 int Model::GetNumberOfSheets() { 4774 return sheets.nSheets; 4775 } 4776 GetHelix(int serialNum)4777 PHelix Model::GetHelix ( int serialNum ) { 4778 return (PHelix)helices.GetContainerClass ( serialNum-1 ); 4779 } 4780 GetSheetID(int serialNum,SheetID sheetID)4781 void Model::GetSheetID ( int serialNum, SheetID sheetID ) { 4782 if ((1<=serialNum) && (serialNum<=sheets.nSheets)) { 4783 if (sheets.sheet[serialNum-1]) { 4784 strcpy ( sheetID,sheets.sheet[serialNum-1]->sheetID ); 4785 return; 4786 } 4787 } 4788 sheetID[0] = char(0); 4789 } 4790 GetSheet(int serialNum)4791 PSheet Model::GetSheet ( int serialNum ) { 4792 if ((1<=serialNum) && (serialNum<=sheets.nSheets)) 4793 return sheets.sheet[serialNum-1]; 4794 else return NULL; 4795 } 4796 GetSheet(const SheetID sheetID)4797 PSheet Model::GetSheet ( const SheetID sheetID ) { 4798 int i; 4799 for (i=0;i<sheets.nSheets;i++) 4800 if (sheets.sheet[i]) { 4801 if (!strcmp(sheets.sheet[i]->sheetID,sheetID)) 4802 return sheets.sheet[i]; 4803 } 4804 return NULL; 4805 } 4806 GetNumberOfStrands(int sheetSerNum)4807 int Model::GetNumberOfStrands ( int sheetSerNum ) { 4808 if ((1<=sheetSerNum) && (sheetSerNum<=sheets.nSheets)) { 4809 if (sheets.sheet[sheetSerNum-1]) 4810 return sheets.sheet[sheetSerNum-1]->nStrands; 4811 } 4812 return 0; 4813 } 4814 GetNumberOfStrands(const SheetID sheetID)4815 int Model::GetNumberOfStrands ( const SheetID sheetID ) { 4816 int i; 4817 for (i=0;i<sheets.nSheets;i++) 4818 if (sheets.sheet[i]) { 4819 if (!strcmp(sheets.sheet[i]->sheetID,sheetID)) 4820 return sheets.sheet[i]->nStrands; 4821 } 4822 return 0; 4823 } 4824 GetStrand(int sheetSerNum,int strandSerNum)4825 PStrand Model::GetStrand ( int sheetSerNum, int strandSerNum ) { 4826 PSheet sheet; 4827 if ((1<=sheetSerNum) && (sheetSerNum<=sheets.nSheets)) { 4828 sheet = sheets.sheet[sheetSerNum-1]; 4829 if (sheet) { 4830 if ((1<=strandSerNum) && (strandSerNum<=sheet->nStrands)) 4831 return sheet->strand[strandSerNum-1]; 4832 } 4833 } 4834 return NULL; 4835 } 4836 GetStrand(const SheetID sheetID,int strandSerNum)4837 PStrand Model::GetStrand ( const SheetID sheetID, 4838 int strandSerNum ) { 4839 int i; 4840 PSheet sheet; 4841 for (i=0;i<sheets.nSheets;i++) 4842 if (sheets.sheet[i]) { 4843 if (!strcmp(sheets.sheet[i]->sheetID,sheetID)) { 4844 sheet = sheets.sheet[i]; 4845 if (sheet) { 4846 if ((1<=strandSerNum) && (strandSerNum<=sheet->nStrands)) 4847 return sheet->strand[strandSerNum-1]; 4848 } 4849 } 4850 } 4851 return NULL; 4852 } 4853 RemoveSecStructure()4854 void Model::RemoveSecStructure() { 4855 helices.FreeContainer(); 4856 sheets .FreeMemory (); 4857 turns .FreeContainer(); 4858 } 4859 RemoveHetInfo()4860 void Model::RemoveHetInfo() { 4861 hetCompounds.FreeMemory(); 4862 } 4863 4864 GetNumberOfLinks()4865 int Model::GetNumberOfLinks() { 4866 return links.Length(); 4867 } 4868 GetLink(int serialNum)4869 PLink Model::GetLink ( int serialNum ) { 4870 return (PLink)links.GetContainerClass ( serialNum-1 ); 4871 } 4872 RemoveLinks()4873 void Model::RemoveLinks() { 4874 links.FreeContainer(); 4875 } 4876 AddLink(PLink link)4877 void Model::AddLink ( PLink link ) { 4878 links.AddData ( link ); 4879 } 4880 4881 GetNumberOfLinkRs()4882 int Model::GetNumberOfLinkRs() { 4883 return linkRs.Length(); 4884 } 4885 GetLinkR(int serialNum)4886 PLinkR Model::GetLinkR ( int serialNum ) { 4887 return (PLinkR)linkRs.GetContainerClass ( serialNum-1 ); 4888 } 4889 RemoveLinkRs()4890 void Model::RemoveLinkRs() { 4891 linkRs.FreeContainer(); 4892 } 4893 AddLinkR(PLinkR linkR)4894 void Model::AddLinkR ( PLinkR linkR ) { 4895 linkRs.AddData ( linkR ); 4896 } 4897 4898 4899 GetNumberOfCisPeps()4900 int Model::GetNumberOfCisPeps() { 4901 return cisPeps.Length(); 4902 } 4903 GetCisPep(int CisPepNum)4904 PCisPep Model::GetCisPep ( int CisPepNum ) { 4905 return (PCisPep)cisPeps.GetContainerClass ( CisPepNum-1 ); 4906 } 4907 RemoveCisPeps()4908 void Model::RemoveCisPeps() { 4909 cisPeps.FreeContainer(); 4910 } 4911 AddCisPep(PCisPep cisPep)4912 void Model::AddCisPep ( PCisPep cisPep ) { 4913 cisPeps.AddData ( cisPep ); 4914 } 4915 4916 ApplyTransform(mat44 & TMatrix)4917 void Model::ApplyTransform ( mat44 & TMatrix ) { 4918 // transforms all coordinates by multiplying with matrix TMatrix 4919 int i; 4920 for (i=0;i<nChains;i++) 4921 if (chain[i]) chain[i]->ApplyTransform ( TMatrix ); 4922 } 4923 isInSelection(int selHnd)4924 bool Model::isInSelection ( int selHnd ) { 4925 PMask mask; 4926 if (manager) { 4927 mask = PRoot(manager)->GetSelMask ( selHnd ); 4928 if (mask) return CheckMask ( mask ); 4929 } 4930 return false; 4931 } 4932 4933 4934 4935 // ------- user-defined data handlers 4936 PutUDData(int UDDhandle,int iudd)4937 int Model::PutUDData ( int UDDhandle, int iudd ) { 4938 if (UDDhandle & UDRF_MODEL) 4939 return UDData::putUDData ( UDDhandle,iudd ); 4940 else return UDDATA_WrongUDRType; 4941 } 4942 PutUDData(int UDDhandle,realtype rudd)4943 int Model::PutUDData ( int UDDhandle, realtype rudd ) { 4944 if (UDDhandle & UDRF_MODEL) 4945 return UDData::putUDData ( UDDhandle,rudd ); 4946 else return UDDATA_WrongUDRType; 4947 } 4948 PutUDData(int UDDhandle,cpstr sudd)4949 int Model::PutUDData ( int UDDhandle, cpstr sudd ) { 4950 if (UDDhandle & UDRF_MODEL) 4951 return UDData::putUDData ( UDDhandle,sudd ); 4952 else return UDDATA_WrongUDRType; 4953 } 4954 GetUDData(int UDDhandle,int & iudd)4955 int Model::GetUDData ( int UDDhandle, int & iudd ) { 4956 if (UDDhandle & UDRF_MODEL) 4957 return UDData::getUDData ( UDDhandle,iudd ); 4958 else return UDDATA_WrongUDRType; 4959 } 4960 GetUDData(int UDDhandle,realtype & rudd)4961 int Model::GetUDData ( int UDDhandle, realtype & rudd ) { 4962 if (UDDhandle & UDRF_MODEL) 4963 return UDData::getUDData ( UDDhandle,rudd ); 4964 else return UDDATA_WrongUDRType; 4965 } 4966 GetUDData(int UDDhandle,pstr sudd,int maxLen)4967 int Model::GetUDData ( int UDDhandle, pstr sudd, int maxLen ) { 4968 if (UDDhandle & UDRF_MODEL) 4969 return UDData::getUDData ( UDDhandle,sudd,maxLen ); 4970 else return UDDATA_WrongUDRType; 4971 } 4972 GetUDData(int UDDhandle,pstr & sudd)4973 int Model::GetUDData ( int UDDhandle, pstr & sudd ) { 4974 if (UDDhandle & UDRF_MODEL) 4975 return UDData::getUDData ( UDDhandle,sudd ); 4976 else return UDDATA_WrongUDRType; 4977 } 4978 4979 4980 // ------- calculation of Secondary Structure 4981 4982 CalcSecStructure(bool flagBulge,int aminoSelHnd)4983 int Model::CalcSecStructure ( bool flagBulge, int aminoSelHnd ) { 4984 // This function is contributed by Liz Potterton, University of York 4985 //------------------------------------------------------------------ 4986 // Define a secondary structure type of each amino acid residue in the 4987 // structure. 4988 // Procedure: 4989 // Find all amino acids 4990 // Find all pairs of amino acids which have inter-Ca distance < 10.0A 4991 // Test for hydrogen bonds between the main chain N and O of the close 4992 // residues and store the information in the hbonds matrix 4993 // Analyse the info in hbonds matrix to assign secondary structure to 4994 // secstr vector 4995 PPResidue Res; 4996 PPAtom Ca; 4997 PChain chn; 4998 PContact contact; 4999 imatrix hbonds; 5000 PPAtom * hbond_atoms; 5001 int nres, ncontacts; 5002 int ir1,ir2, irdif; 5003 int i,j,k,l; 5004 5005 // 1a. Get protein residues from selection handle 5006 5007 if (aminoSelHnd>=0) { 5008 5009 manager->GetSelIndex(aminoSelHnd,Res,nres); 5010 if (nres<=0) return SSERC_noResidues; 5011 5012 } else { 5013 5014 // 1b. Get all protein residues 5015 5016 nres = 0; 5017 for (i=0;i<nChains;i++) 5018 if (chain[i]) 5019 nres += chain[i]->nResidues; 5020 5021 if (nres<=0) return SSERC_noResidues; 5022 5023 Res = new PResidue[nres]; 5024 nres = 0; 5025 for (i=0;i<nChains;i++) { 5026 chn = chain[i]; 5027 if (chn) { 5028 k = chn->nResidues; 5029 for (j=0;j<k;j++) 5030 Res[nres++] = chn->residue[j]; 5031 } 5032 } 5033 5034 5035 if (nres<=0) { 5036 delete[] Res; 5037 return SSERC_noResidues; 5038 } 5039 5040 } 5041 5042 // 2. Get C-alphas of all aminoacids 5043 5044 Ca = new PAtom[nres]; 5045 k = 0; 5046 for (i=0;i<nres;i++) 5047 if (Res[i]) { 5048 if (aminoSelHnd>=0 || Res[i]->isAminoacid()) { 5049 Ca[i] = Res[i]->GetAtom("CA", " C", "*"); 5050 k++; 5051 } else 5052 Ca[i] = NULL; 5053 Res[i]->SSE = SSE_None; 5054 } else 5055 Ca[i] = NULL; 5056 5057 if (k<=0) { 5058 delete[] Res; 5059 delete[] Ca; 5060 return SSERC_noAminoacids; 5061 } 5062 5063 5064 // 3. Find all close Calphas - i.e. find the contacts between 5065 // the two equivalent sets of Ca atoms 5066 5067 contact = NULL; 5068 ncontacts = 0; 5069 manager->SeekContacts ( Ca,nres, Ca,nres, 2.0,10.0, 2, 5070 contact,ncontacts,0 ); 5071 manager->RemoveBricks(); 5072 if (ncontacts<=0) { 5073 delete[] Res; 5074 delete[] Ca; 5075 if (contact) delete[] contact; 5076 return SSERC_noSSE; 5077 } 5078 5079 5080 // 4. Get and initialize memory for analysing the SSE 5081 5082 GetMatrixMemory ( hbonds,nres,3,0,0 ); 5083 hbond_atoms = new PPAtom[nres]; 5084 for (i=0;i<nres;i++) { 5085 hbond_atoms[i] = new PAtom[6]; 5086 for (j=0;j<6;j++) hbond_atoms[i][j] = NULL; 5087 for (j=0;j<3;j++) hbonds [i][j] = 0; 5088 } 5089 5090 5091 // 5. Loop over all close (in space) residues - excluding those 5092 // that are close in sequence 5093 5094 for (i=0;i<ncontacts;i++) { 5095 ir1 = contact[i].id2; 5096 ir2 = contact[i].id1; 5097 irdif = ir1 - ir2; 5098 if (irdif>2) { 5099 // test if there is donor Hbond from residue ir1 5100 if (Res[ir1]->isMainchainHBond(Res[ir2])) { 5101 k = 0; 5102 while ((hbonds[ir1][k]!=0) && (k<2)) k++; 5103 hbonds [ir1][k] = -irdif; 5104 hbond_atoms[ir1][k] = Res[ir1]->GetAtom ( "N" ); 5105 hbond_atoms[ir1][k+3] = Res[ir2]->GetAtom ( "O" ); 5106 } 5107 // test if there is donor Hbond from residue ir2 5108 if (Res[ir2]->isMainchainHBond(Res[ir1])) { 5109 k = 0; 5110 while ((hbonds[ir2][k]!=0) && (k<2)) k++; 5111 hbonds [ir2][k] = irdif; 5112 hbond_atoms[ir2][k] = Res[ir2]->GetAtom ( "N" ); 5113 hbond_atoms[ir2][k+3] = Res[ir1]->GetAtom ( "O" ); 5114 } 5115 } 5116 } 5117 5118 // 6. Assign the turns - if there is bifurcated bond then the 4-turn 5119 // takes precedence - read the paper to make sense of this 5120 5121 for (i=0;i<nres;i++) { 5122 k = 0; 5123 while ((k<=2) && (hbonds[i][k]!=0)) { 5124 if (hbonds[i][k]==-5) { 5125 Res[i-1]->SSE = SSE_5Turn; 5126 Res[i-2]->SSE = SSE_5Turn; 5127 Res[i-3]->SSE = SSE_5Turn; 5128 Res[i-4]->SSE = SSE_5Turn; 5129 } 5130 if (hbonds[i][k]==-3) { 5131 Res[i-1]->SSE = SSE_3Turn; 5132 Res[i-2]->SSE = SSE_3Turn; 5133 } 5134 k++; 5135 } 5136 } 5137 for (i=0;i<nres;i++) { 5138 k = 0; 5139 while ((k<=2) && (hbonds[i][k]!=0)) { 5140 if (hbonds[i][k]==-4) { 5141 Res[i-1]->SSE = SSE_4Turn; 5142 Res[i-2]->SSE = SSE_4Turn; 5143 Res[i-3]->SSE = SSE_4Turn; 5144 } 5145 k++; 5146 } 5147 } 5148 5149 5150 // 7. Look for consecutive 4-turns which make alpha helix 5151 5152 for (i=1;i<nres-3;i++) { 5153 if (((Res[i ]->SSE==SSE_Helix) || (Res[i ]->SSE==SSE_4Turn)) && 5154 ((Res[i+1]->SSE==SSE_Helix) || (Res[i+1]->SSE==SSE_4Turn)) && 5155 ((Res[i+2]->SSE==SSE_Helix) || (Res[i+2]->SSE==SSE_4Turn)) && 5156 ((Res[i+3]->SSE==SSE_Helix) || (Res[i+3]->SSE==SSE_4Turn))) 5157 for (j=i;j<=i+3;j++) Res[j]->SSE = SSE_Helix; 5158 } 5159 5160 for (i=0;i<nres;i++) { 5161 5162 k = 0; 5163 while ((k<=2) && (hbonds[i][k]!=0)) { 5164 5165 irdif = hbonds[i][k]; 5166 // Test for 'close' hbond 5167 j = i + irdif; 5168 l = 0; 5169 while ((l<=2) && (hbonds[j][l]!=0)) { 5170 // Antiparallel strands 5171 if (hbonds[j][l]==-irdif) { 5172 Res[i]->SSE = SSE_Strand; 5173 Res[j]->SSE = SSE_Strand; 5174 } 5175 // Parallel strand 5176 if (hbonds[j][l]==-irdif-2) { 5177 Res[i-1]->SSE = SSE_Strand; 5178 Res[j ]->SSE = SSE_Strand; 5179 } 5180 // Parallel beta bulge 5181 if (hbonds[j][l]==-irdif-3) { 5182 if (flagBulge) { 5183 if (Res[i-1]->SSE==SSE_None) Res[i-1]->SSE = SSE_Bulge; 5184 if (Res[i-2]->SSE==SSE_None) Res[i-2]->SSE = SSE_Bulge; 5185 if (Res[j ]->SSE==SSE_None) Res[j ]->SSE = SSE_Bulge; 5186 } else { 5187 if (Res[i-1]->SSE==SSE_None) Res[i-1]->SSE = SSE_Strand; 5188 if (Res[i-2]->SSE==SSE_None) Res[i-2]->SSE = SSE_Strand; 5189 if (Res[j ]->SSE==SSE_None) Res[j ]->SSE = SSE_Strand; 5190 } 5191 } 5192 l++; 5193 } 5194 // Test for 'wide' hbond 5195 j = i + hbonds[i][k] + 2; 5196 if (j<nres) { 5197 l = 0; 5198 while ((l<=2) && (hbonds[j][l]!=0)) { 5199 // Antiaprallel strands 5200 if (hbonds[j][l]==-irdif-4) { 5201 Res[i-1]->SSE = SSE_Strand; 5202 Res[j-1]->SSE = SSE_Strand; 5203 } 5204 // Parallel strands 5205 if (hbonds[j][l]==-irdif-2) { 5206 Res[i ]->SSE = SSE_Strand; 5207 Res[j-1]->SSE = SSE_Strand; 5208 } 5209 l++; 5210 } 5211 } 5212 5213 // test for anti-parallel B-bulge between 'close' hbonds 5214 j = i + hbonds[i][k] - 1; 5215 if (j>=0) { 5216 l = 0; 5217 while ((l<=2) && (hbonds[j][l]!=0)) { 5218 if (hbonds[j][l]==-irdif+1) { 5219 if (flagBulge) { 5220 if (Res[i ]->SSE==SSE_None) Res[i ]->SSE = SSE_Bulge; 5221 if (Res[j+1]->SSE==SSE_None) Res[j+1]->SSE = SSE_Bulge; 5222 if (Res[j ]->SSE==SSE_None) Res[j ]->SSE = SSE_Bulge; 5223 } else { 5224 if (Res[i ]->SSE==SSE_None) Res[i ]->SSE = SSE_Strand; 5225 if (Res[j+1]->SSE==SSE_None) Res[j+1]->SSE = SSE_Strand; 5226 if (Res[j ]->SSE==SSE_None) Res[j ]->SSE = SSE_Strand; 5227 } 5228 } 5229 l++; 5230 } 5231 } 5232 5233 // test for anti-parallel B-bulge between 'wide' hbonds 5234 j = i + hbonds[i][k] + 3; 5235 if (j<nres) { 5236 l = 0; 5237 while ((l<=2) && (hbonds[j][l]!=0)) { 5238 if ((hbonds[j][l]==-irdif+5) && (i>0)) { 5239 if (flagBulge) { 5240 if (Res[i-1]->SSE==SSE_None) Res[i-1]->SSE = SSE_Bulge; 5241 if (Res[j-1]->SSE==SSE_None) Res[j-1]->SSE = SSE_Bulge; 5242 if (Res[j-2]->SSE==SSE_None) Res[j-2]->SSE = SSE_Bulge; 5243 } else { 5244 if (Res[i-1]->SSE==SSE_None) Res[i-1]->SSE = SSE_Strand; 5245 if (Res[j-1]->SSE==SSE_None) Res[j-1]->SSE = SSE_Strand; 5246 if (Res[j-2]->SSE==SSE_None) Res[j-2]->SSE = SSE_Strand; 5247 } 5248 } else if (hbonds[j][l]==-irdif-3) { 5249 // and bulge in parallel strand 5250 if (flagBulge) { 5251 if (Res[i ]->SSE==SSE_None) Res[i ]->SSE = SSE_Bulge; 5252 if (Res[j-1]->SSE==SSE_None) Res[j-1]->SSE = SSE_Bulge; 5253 if (Res[j-2]->SSE==SSE_None) Res[j-2]->SSE = SSE_Bulge; 5254 } 5255 else { 5256 if (Res[i ]->SSE==SSE_None) Res[i ]->SSE = SSE_Strand; 5257 if (Res[j-1]->SSE==SSE_None) Res[j-1]->SSE = SSE_Strand; 5258 if (Res[j-2]->SSE==SSE_None) Res[j-2]->SSE = SSE_Strand; 5259 } 5260 } 5261 l++; 5262 } 5263 } 5264 k++; 5265 5266 } // Finish looping over Hbonds for residue (k loop) 5267 5268 } // Finish looping over residues ( i loop) 5269 5270 5271 // 8. Free memory 5272 5273 if (hbond_atoms) { 5274 for (i=0;i<nres;i++) 5275 if (hbond_atoms[i]) delete[] hbond_atoms[i]; 5276 delete[] hbond_atoms; 5277 } 5278 FreeMatrixMemory ( hbonds,nres,0,0 ); 5279 if (contact) delete[] contact; 5280 if (Res && aminoSelHnd<0) delete[] Res; 5281 if (Ca) delete[] Ca; 5282 5283 return SSERC_Ok; 5284 5285 } 5286 5287 5288 // ------- streaming 5289 write(io::RFile f)5290 void Model::write ( io::RFile f ) { 5291 int i,k; 5292 byte Version=4; 5293 bool compactBinary = false; 5294 5295 PManager M = GetCoordHierarchy(); 5296 if (M) 5297 compactBinary = M->isCompactBinary(); 5298 5299 f.WriteByte ( &Version ); 5300 f.WriteBool ( &compactBinary ); 5301 5302 f.WriteInt ( &serNum ); 5303 f.WriteInt ( &nChains ); 5304 5305 for (i=0;i<nChains;i++) { 5306 if (chain[i]) k = 1; 5307 else k = 0; 5308 f.WriteInt ( &k ); 5309 if (chain[i]) chain[i]->write ( f ); 5310 } 5311 5312 if (!compactBinary) { 5313 5314 ProModel::write ( f ); 5315 5316 hetCompounds.write ( f ); 5317 helices .write ( f ); 5318 sheets .write ( f ); 5319 turns .write ( f ); 5320 links .write ( f ); 5321 linkRs .write ( f ); 5322 5323 } 5324 5325 } 5326 read(io::RFile f)5327 void Model::read ( io::RFile f ) { 5328 int i,k; 5329 byte Version; 5330 bool compactBinary; 5331 5332 FreeMemory(); 5333 5334 f.ReadByte ( &Version ); 5335 f.ReadBool ( &compactBinary ); 5336 5337 f.ReadInt ( &serNum ); 5338 f.ReadInt ( &nChains ); 5339 nChainsAlloc = nChains; 5340 if (nChains>0) { 5341 chain = new PChain[nChainsAlloc]; 5342 for (i=0;i<nChains;i++) { 5343 f.ReadInt ( &k ); 5344 if (k) { 5345 chain[i] = newChain(); 5346 chain[i]->SetModel ( this ); 5347 chain[i]->read ( f ); 5348 } 5349 } 5350 } 5351 5352 if (!compactBinary) { 5353 5354 ProModel::read ( f ); 5355 5356 hetCompounds.read ( f ); 5357 helices .read ( f ); 5358 sheets .read ( f ); 5359 turns .read ( f ); 5360 links .read ( f ); 5361 linkRs .read ( f ); 5362 5363 } 5364 5365 } 5366 5367 MakeFactoryFunctions(Model) 5368 5369 } // namespace mmdb 5370