1 // $Id: mmdb_utils.cpp $ 2 // ================================================================= 3 // 4 // CCP4 Coordinate Library: support of coordinate-related 5 // functionality in protein crystallography applications. 6 // 7 // Copyright (C) Eugene Krissinel 2000-2008. 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 // 27.02.17 <-- Date of Last Modification. 26 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 // ----------------------------------------------------------------- 28 // 29 // **** Module : MMDBF_Utils <implementation> 30 // ~~~~~~~~~ 31 // **** Project : MacroMolecular Data Base (MMDB) 32 // ~~~~~~~~~ 33 // 34 // **** Classes : mmdb::ContainerClass ( containered class template ) 35 // ~~~~~~~~~ mmdb::ContString ( containered string ) 36 // mmdb::ClassContainer ( container of classes ) 37 // mmdb::AtomPath ( atom path ID ) 38 // mmdb::QuickSort ( quick sort of integers ) 39 // 40 // **** Functions : Date9to11 ( DD-MMM-YY -> DD-MMM-YYYY ) 41 // ~~~~~~~~~~~ Date11to9 ( DD-MMM-YYYY -> DD-MMM-YY ) 42 // Date9toCIF ( DD-MMM-YY -> YYYY-MM-DD ) 43 // Date11toCIF( DD-MMM-YYYY -> YYYY-MM-DD ) 44 // DateCIFto9 ( YYYY-MM-DD -> DD-MMM-YY ) 45 // DateCIFto11( YYYY-MM-DD -> DD-MMM-YYYY ) 46 // GetInteger ( reads integer from a string ) 47 // GetReal ( reads real from a string ) 48 // GetIntIns ( reads integer and insert code ) 49 // PutInteger ( writes integer into a string ) 50 // PutRealF ( writes real in F-form into a string ) 51 // PutIntIns ( writes integer and insert code ) 52 // CIFGetInteger ( reads and deletes int from CIF ) 53 // CIFGetReal ( reads and deletes real from CIF ) 54 // CIFGetString ( reads and deletes string from CIF) 55 // CIFGetInteger1 (reads and del-s int from CIF loop) 56 // CIFGetReal1 (reads and del-s int from CIF loop) 57 // Mat4Inverse ( inversion of 4x4 matrices ) 58 // GetErrorDescription (ascii line to an Error_XXXXX) 59 // ParseAtomID ( parses atom ID line ) 60 // ParseResID ( parses residue ID line ) 61 // ParseAtomPath ( parses full atom path ) 62 // 63 // (C) E. Krissinel 2000-2017 64 // 65 // ================================================================= 66 // 67 68 #include <string.h> 69 #include <math.h> 70 #include <stdlib.h> 71 72 #include "mmdb_utils.h" 73 #include "hybrid_36.h" 74 75 namespace mmdb { 76 77 // ====================== Date functions ======================= 78 79 static cpstr Month[12] = { 80 "JAN", "FEB", "MAR", "APR", "MAY", "JUN", 81 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" 82 }; 83 84 static cpstr nMonth[12] = { 85 "01", "02", "03", "04", "05", "06", 86 "07", "08", "09", "10", "11", "12" 87 }; 88 Date9to11(cpstr Date9,pstr Date11)89 void Date9to11 ( cpstr Date9, pstr Date11 ) { 90 // converts DD-MMM-YY to DD-MMM-YYYY 91 int i; 92 i = 0; 93 while ((i<12) && (strncmp(Month[i],&(Date9[3]),3))) i++; 94 if (i<12) { // DD-MMM-YY -> DD-MMM-YYYY 95 strncpy ( Date11,Date9,7 ); 96 if (Date9[7]!='0') strncpy ( &(Date11[7]),"19",2 ); 97 else strncpy ( &(Date11[7]),"20",2 ); 98 strncpy ( &(Date11[9]),&(Date9[7]),2 ); 99 Date11[2] = '-'; 100 Date11[6] = '-'; 101 Date11[11] = char(0); 102 } else { // DD-MM-YY -> DD-MMM-YYYY 103 strncpy ( Date11,Date9,3 ); 104 i = 0; 105 while ((i<12) && (strncmp(nMonth[i],&(Date9[3]),2))) i++; 106 if (i<12) { 107 strncpy ( &(Date11[3]),Month[i],3 ); 108 if (Date9[6]!='0') strncpy ( &(Date11[7]),"19",2 ); 109 else strncpy ( &(Date11[7]),"20",2 ); 110 strncpy ( &(Date11[9]),&(Date9[6]),2 ); 111 Date11[2] = '-'; 112 Date11[6] = '-'; 113 Date11[11] = char(0); 114 } else 115 strcpy ( Date11," " ); 116 } 117 } 118 Date11to9(cpstr Date11,pstr Date9)119 void Date11to9 ( cpstr Date11, pstr Date9 ) { 120 // converts DD-MMM-YYYY to DD-MMM-YY 121 int i; 122 i = 0; 123 while ((i<12) && (strncmp(Month[i],&(Date11[3]),3))) i++; 124 if (i<12) { // DD-MMM-YYYY -> DD-MMM-YY 125 strncpy ( Date9,Date11,7 ); 126 strncpy ( &(Date9[7]),&(Date11[9]),2 ); 127 Date9[2] = '-'; 128 Date9[6] = '-'; 129 } else { // DD-MM-YYYY -> DD-MMM-YY 130 strncpy ( Date9,Date11,3 ); 131 i = 0; 132 while ((i<12) && (strncmp(nMonth[i],&(Date11[3]),2))) i++; 133 if (i<12) { 134 strncpy ( &(Date9[3]),Month[i],3 ); 135 strncpy ( &(Date9[7]),&(Date11[8]),2 ); 136 Date9[2] = '-'; 137 Date9[6] = '-'; 138 } else 139 strcpy ( Date9," " ); 140 } 141 } 142 Date9toCIF(cpstr Date9,pstr DateCIF)143 void Date9toCIF ( cpstr Date9, pstr DateCIF ) { 144 // DD-MMM-YY -> YYYY-MM-DD ) 145 int i; 146 i = 0; 147 while ((i<12) && (strncmp(Month[i],&(Date9[3]),3))) i++; 148 if (i<12) { // DD-MMM-YY -> YYYY-MM-DD 149 if (Date9[7]!='0') strcpy ( DateCIF,"19" ); 150 else strcpy ( DateCIF,"20" ); 151 strncpy ( &(DateCIF[2]),&(Date9[7]),2 ); 152 strncpy ( &(DateCIF[5]),nMonth[i],2 ); 153 } else { // DD-MM-YY -> YYYY-MM-DD 154 if (Date9[6]!='0') strcpy ( DateCIF,"19" ); 155 else strcpy ( DateCIF,"20" ); 156 strncpy ( &(DateCIF[2]),&(Date9[6]),2 ); 157 strncpy ( &(DateCIF[5]),&(Date9[3]),2 ); 158 } 159 DateCIF[4] = '-'; 160 DateCIF[7] = '-'; 161 strncpy ( &(DateCIF[8]),Date9,2 ); 162 DateCIF[10] = char(0); 163 } 164 Date11toCIF(cpstr Date11,pstr DateCIF)165 void Date11toCIF ( cpstr Date11, pstr DateCIF ) { 166 // DD-MMM-YYYY -> YYYY-MM-DD 167 int i; 168 i = 0; 169 while ((i<12) && (strncmp(Month[i],&(Date11[3]),3))) i++; 170 if (i<12) { 171 strncpy ( DateCIF,&(Date11[7]),4 ); 172 strncpy ( &(DateCIF[5]),nMonth[i],2 ); 173 } else { 174 strncpy ( DateCIF,&(Date11[6]),4 ); 175 strncpy ( &(DateCIF[5]),&(Date11[3]),2 ); 176 } 177 DateCIF[4] = '-'; 178 DateCIF[7] = '-'; 179 strncpy ( &(DateCIF[8]),Date11,2 ); 180 DateCIF[10] = char(0); 181 } 182 DateCIFto9(cpstr DateCIF,pstr Date9)183 void DateCIFto9 ( cpstr DateCIF, pstr Date9 ) { 184 // YYYY-MM-DD -> DD-MMM-YY 185 int i; 186 strncpy ( Date9,&(DateCIF[8]),2 ); 187 Date9[2] = '-'; 188 i = 0; 189 while ((i<12) && (strncmp(nMonth[i],&(DateCIF[5]),2))) i++; 190 if (i<12) strncpy ( &(Date9[3]),Month[i],3 ); 191 else { 192 strncpy ( &(Date9[3]),&(DateCIF[5]),2 ); 193 Date9[5] = 'X'; 194 } 195 Date9[6] = '-'; 196 strncpy ( &(Date9[7]),&(DateCIF[2]),2 ); 197 // DateCIF[9] = char(0); 198 } 199 DateCIFto11(cpstr DateCIF,pstr Date11)200 void DateCIFto11 ( cpstr DateCIF, pstr Date11 ) { 201 // YYYY-MM-DD -> DD-MMM-YYYY 202 int i; 203 strncpy ( Date11,&(DateCIF[8]),2 ); 204 Date11[2] = '-'; 205 i = 0; 206 while ((i<12) && (strncmp(nMonth[i],&(DateCIF[5]),2))) i++; 207 if (i<12) strncpy ( &(Date11[3]),Month[i],3 ); 208 else { 209 strncpy ( &(Date11[3]),&(DateCIF[5]),2 ); 210 Date11[5] = 'X'; 211 } 212 Date11[6] = '-'; 213 strncpy ( &(Date11[7]),DateCIF,4 ); 214 // DateCIF[11] = char(0); 215 } 216 217 218 // =============== Format functions =================== 219 GetInteger(int & N,cpstr S,int M)220 bool GetInteger ( int & N, cpstr S, int M ) { 221 // Returns true if S contains an integer number in its 222 // first M characters. This number is returned in N. 223 // The return is false if no integer number may be 224 // recognized. In this case, N is assigned MinInt4 value. 225 pstr endptr; 226 char L[50]; 227 strncpy ( L,S,M ); 228 L[M] = char(0); 229 N = mround(strtod(L,&endptr)); 230 if ((N==0) && (endptr==L)) { 231 N = MinInt4; // no number 232 return false; 233 } else 234 return true; 235 } 236 GetReal(realtype & R,cpstr S,int M)237 bool GetReal ( realtype & R, cpstr S, int M ) { 238 // Returns true if S contains a real number in its 239 // first M characters. This number is returned in R. 240 // The return is false if no real number may be 241 // recognized. In this case, R is assigned -MaxReal value. 242 pstr endptr; 243 char L[50]; 244 strncpy ( L,S,M ); 245 L[M] = char(0); 246 R = strtod(L,&endptr); 247 if ((R==0.0) && (endptr==L)) { 248 R = -MaxReal; // no number 249 return false; 250 } else 251 return true; 252 } 253 GetIntIns(int & N,pstr ins,cpstr S,int M)254 bool GetIntIns ( int & N, pstr ins, cpstr S, int M ) { 255 // Returns true if S contains an integer number in its 256 // first M characters. This number is returned in N. In addition 257 // to that, GetIntIns() retrieves the insertion code which may 258 // follow the integer and returns it in "ins" (1 character + 259 // terminating 0). 260 // The return is false if no integer number may be 261 // recognized. In this case, N is assigned MinInt4 value, 262 // "ins" just returns (M+1)th symbol of S (+terminating 0). 263 pstr endptr; 264 char L[50]; 265 266 if (S[M]!=' ') { 267 ins[0] = S[M]; 268 ins[1] = char(0); 269 } else 270 ins[0] = char(0); 271 272 strncpy ( L,S,M ); 273 L[M] = char(0); 274 if ((M==4) && ((S[0]>='A') || ((S[0]=='-') && (S[1]>='A')))) 275 hy36decode ( M,L,M,&N); 276 else { 277 endptr = NULL; 278 N = mround(strtod(L,&endptr)); 279 if ((N==0) && (endptr==L)) { 280 N = MinInt4; // no number 281 return false; 282 } 283 } 284 285 return true; 286 287 } 288 PutInteger(pstr S,int N,int M)289 void PutInteger ( pstr S, int N, int M ) { 290 // Integer N is converted into ASCII string of length M 291 // and pasted onto first M characters of string S. No 292 // terminating zero is added. 293 // If N is set to MinInt4, then first M characters of 294 // string S are set to the space character. 295 char L[50]; 296 int i; 297 if (N==MinInt4) 298 for (i=0;i<M;i++) 299 S[i] = ' '; 300 else { 301 sprintf ( L,"%*i",M,N ); 302 strncpy ( S,L,M ); 303 } 304 } 305 PutRealF(pstr S,realtype R,int M,int L)306 void PutRealF ( pstr S, realtype R, int M, int L ) { 307 // Real R is converted into ASCII string of length M 308 // and pasted onto first M characters of string S. No 309 // terminating zero is added. The conversion is done 310 // according to fixed format FM.L 311 // If R is set to -MaxReal, then first M characters of 312 // string S are set to the space character. 313 char N[50]; 314 int i; 315 if (R==-MaxReal) 316 for (i=0;i<M;i++) 317 S[i] = ' '; 318 else { 319 sprintf ( N,"%*.*f",M,L,R ); 320 strncpy ( S,N,M ); 321 } 322 } 323 CIFGetIntegerD(int & I,mmcif::PLoop Loop,cpstr Tag,int defValue)324 ERROR_CODE CIFGetIntegerD ( int & I, mmcif::PLoop Loop, cpstr Tag, 325 int defValue ) { 326 int Signal; 327 ERROR_CODE RC; 328 Signal = 0; 329 RC = CIFGetInteger ( I,Loop,Tag,Signal ); 330 if (RC) 331 I = defValue; 332 return RC; 333 } 334 CIFGetInteger(int & I,mmcif::PLoop Loop,cpstr Tag,int & Signal)335 ERROR_CODE CIFGetInteger ( int & I, mmcif::PLoop Loop, cpstr Tag, 336 int & Signal ) { 337 pstr F; 338 int RC; 339 RC = Loop->GetInteger ( I,Tag,Signal,true ); 340 if (RC==mmcif::CIFRC_WrongFormat) { 341 F = Loop->GetString ( Tag,Signal,RC ); 342 if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", 343 Loop->GetCategoryName(),Tag,Signal,F ); 344 else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", 345 Loop->GetCategoryName(),Tag,Signal ); 346 Signal = -Error_UnrecognizedInteger-1; 347 return Error_UnrecognizedInteger; 348 } 349 if (RC==mmcif::CIFRC_WrongIndex) { 350 Signal = -1; 351 return Error_NoData; 352 } 353 if (RC) { 354 F = Loop->GetString ( Tag,Signal,RC ); 355 if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", 356 Loop->GetCategoryName(),Tag,Signal,F ); 357 else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", 358 Loop->GetCategoryName(),Tag,Signal ); 359 Signal = -Error_NoData-1; 360 return Error_NoData; 361 } 362 return Error_NoError; 363 } 364 365 CIFGetInteger1(int & I,mmcif::PLoop Loop,cpstr Tag,int nrow)366 ERROR_CODE CIFGetInteger1 ( int & I, mmcif::PLoop Loop, cpstr Tag, 367 int nrow ) { 368 pstr F; 369 int RC; 370 RC = Loop->GetInteger ( I,Tag,nrow,true ); 371 if (RC==mmcif::CIFRC_WrongFormat) { 372 F = Loop->GetString ( Tag,nrow,RC ); 373 if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", 374 Loop->GetCategoryName(),Tag,nrow,F ); 375 else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", 376 Loop->GetCategoryName(),Tag,nrow ); 377 return Error_UnrecognizedInteger; 378 } 379 if (RC==mmcif::CIFRC_WrongIndex) 380 return Error_NoData; 381 if (RC) { 382 F = Loop->GetString ( Tag,nrow,RC ); 383 if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", 384 Loop->GetCategoryName(),Tag,nrow,F ); 385 else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", 386 Loop->GetCategoryName(),Tag,nrow ); 387 return Error_NoData; 388 } 389 return Error_NoError; 390 } 391 392 CIFGetReal(realtype & R,mmcif::PLoop Loop,cpstr Tag,int & Signal)393 ERROR_CODE CIFGetReal ( realtype & R, mmcif::PLoop Loop, cpstr Tag, 394 int & Signal ) { 395 pstr F; 396 int RC; 397 RC = Loop->GetReal ( R,Tag,Signal,true ); 398 if (RC==mmcif::CIFRC_WrongFormat) { 399 F = Loop->GetString ( Tag,Signal,RC ); 400 if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", 401 Loop->GetCategoryName(),Tag,Signal,F ); 402 else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", 403 Loop->GetCategoryName(),Tag,Signal ); 404 Signal = -Error_UnrecognizedReal-1; 405 return Error_UnrecognizedReal; 406 } 407 if (RC==mmcif::CIFRC_WrongIndex) { 408 Signal = -1; 409 return Error_NoData; 410 } 411 if (RC) { 412 F = Loop->GetString ( Tag,Signal,RC ); 413 if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", 414 Loop->GetCategoryName(),Tag,Signal,F ); 415 else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", 416 Loop->GetCategoryName(),Tag,Signal ); 417 Signal = -Error_NoData-1; 418 return Error_NoData; 419 } 420 return Error_NoError; 421 } 422 423 CIFGetReal1(realtype & R,mmcif::PLoop Loop,cpstr Tag,int nrow)424 ERROR_CODE CIFGetReal1 ( realtype & R, mmcif::PLoop Loop, cpstr Tag, 425 int nrow ) { 426 pstr F; 427 int RC; 428 RC = Loop->GetReal ( R,Tag,nrow,true ); 429 if (RC==mmcif::CIFRC_WrongFormat) { 430 F = Loop->GetString ( Tag,nrow,RC ); 431 if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", 432 Loop->GetCategoryName(),Tag,nrow,F ); 433 else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", 434 Loop->GetCategoryName(),Tag,nrow ); 435 return Error_UnrecognizedReal; 436 } 437 if (RC==mmcif::CIFRC_WrongIndex) 438 return Error_NoData; 439 if (RC) { 440 F = Loop->GetString ( Tag,nrow,RC ); 441 if (F) sprintf ( CIFErrorLocation,"loop %s.%s row %i data %s", 442 Loop->GetCategoryName(),Tag,nrow,F ); 443 else sprintf ( CIFErrorLocation,"loop %s.%s row %i data [NULL]", 444 Loop->GetCategoryName(),Tag,nrow ); 445 return Error_NoData; 446 } 447 return Error_NoError; 448 } 449 450 CIFGetString(pstr S,mmcif::PLoop Loop,cpstr Tag,int row,int SLen,cpstr DefS)451 ERROR_CODE CIFGetString ( pstr S, mmcif::PLoop Loop, cpstr Tag, 452 int row, int SLen, cpstr DefS ) { 453 pstr F; 454 int RC; 455 F = Loop->GetString ( Tag,row,RC ); 456 if ((!RC) && F) { 457 strncpy ( S,F,SLen-1 ); 458 Loop->DeleteField ( Tag,row ); 459 return Error_NoError; 460 } else { 461 strcpy ( S,DefS ); 462 return Error_EmptyCIFLoop; 463 } 464 } 465 466 CIFGetInteger(int & I,mmcif::PStruct Struct,cpstr Tag,bool Remove)467 ERROR_CODE CIFGetInteger ( int & I, mmcif::PStruct Struct, cpstr Tag, 468 bool Remove ) { 469 pstr F; 470 int RC; 471 RC = Struct->GetInteger ( I,Tag,Remove ); 472 if (RC==mmcif::CIFRC_WrongFormat) { 473 F = Struct->GetString ( Tag,RC ); 474 if (F) sprintf ( CIFErrorLocation,"structure %s.%s data %s", 475 Struct->GetCategoryName(),Tag,F ); 476 else sprintf ( CIFErrorLocation,"structure %s.%s data [NULL]", 477 Struct->GetCategoryName(),Tag ); 478 return Error_UnrecognizedInteger; 479 } 480 if (RC) { 481 F = Struct->GetString ( Tag,RC ); 482 if (F) sprintf ( CIFErrorLocation,"structure %s.%s data %s", 483 Struct->GetCategoryName(),Tag,F ); 484 else sprintf ( CIFErrorLocation,"structure %s.%s data [NULL]", 485 Struct->GetCategoryName(),Tag ); 486 return Error_NoData; 487 } 488 return Error_NoError; 489 } 490 CIFGetReal(realtype & R,mmcif::PStruct Struct,cpstr Tag,bool Remove)491 ERROR_CODE CIFGetReal ( realtype & R, mmcif::PStruct Struct, cpstr Tag, 492 bool Remove ) { 493 pstr F; 494 int RC; 495 RC = Struct->GetReal ( R,Tag,Remove ); 496 if (RC==mmcif::CIFRC_WrongFormat) { 497 F = Struct->GetString ( Tag,RC ); 498 if (F) sprintf ( CIFErrorLocation,"structure %s.%s data %s", 499 Struct->GetCategoryName(),Tag,F ); 500 else sprintf ( CIFErrorLocation,"structure %s.%s data [NULL]", 501 Struct->GetCategoryName(),Tag ); 502 return Error_UnrecognizedReal; 503 } 504 if (RC) { 505 F = Struct->GetString ( Tag,RC ); 506 if (F) sprintf ( CIFErrorLocation,"structure %s.%s data %s", 507 Struct->GetCategoryName(),Tag,F ); 508 else sprintf ( CIFErrorLocation,"structure %s.%s data [NULL]", 509 Struct->GetCategoryName(),Tag ); 510 return Error_NoData; 511 } 512 return Error_NoError; 513 } 514 CIFGetString(pstr S,mmcif::PStruct Struct,cpstr Tag,int SLen,cpstr DefS,bool Remove)515 ERROR_CODE CIFGetString ( pstr S, mmcif::PStruct Struct, cpstr Tag, 516 int SLen, cpstr DefS, bool Remove ) { 517 pstr F; 518 int RC; 519 F = Struct->GetString ( Tag,RC ); 520 if ((!RC) && F) { 521 strcpy_n0 ( S,F,SLen-1 ); 522 if (Remove) Struct->DeleteField ( Tag ); 523 return Error_NoError; 524 } else { 525 strcpy ( S,DefS ); 526 return Error_EmptyCIFStruct; 527 } 528 } 529 530 PutIntIns(pstr S,int N,int M,cpstr ins)531 void PutIntIns ( pstr S, int N, int M, cpstr ins ) { 532 // Integer N is converted into ASCII string of length M 533 // and pasted onto first M characters of string S. No 534 // terminating zero is added. The insert code ins is put 535 // immediately after the integer. 536 // If N is set to MinInt4, then first M+1 characters of 537 // string S are set to space, and no insert code are 538 // appended. 539 char L[50]; 540 int i; 541 542 if (N==MinInt4) { 543 for (i=0;i<=M;i++) 544 S[i] = ' '; 545 } else { 546 if ((M!=4) || ((N>=-999) && (N<=9999))) 547 sprintf ( L,"%*i",M,N ); 548 else hy36encode ( M,N,L ); 549 strcpy_n1 ( S,L,M ); 550 if (ins[0]) S[M] = ins[0]; 551 } 552 553 } 554 555 Mat4Inverse(const mat44 & A,mat44 & AI)556 void Mat4Inverse ( const mat44 & A, mat44 & AI ) { 557 // *** FORMER RBRINV(A,AI) *** 558 // Function to invert 4*4 matrices (AI=A^{-1}) 559 mat44 c; 560 mat33 x; 561 realtype s,s1; 562 int ii,jj,i,i1,j,j1; 563 564 // ---- Get cofactors of 'a' in array 'c' 565 566 s1 = 1.0; 567 for (ii=0;ii<4;ii++) { 568 s = s1; 569 for (jj=0;jj<4;jj++) { 570 i = -1; 571 for (i1=0;i1<4;i1++) 572 if (i1!=ii) { 573 i++; 574 j = -1; 575 for (j1=0;j1<4;j1++) 576 if (j1!=jj) { 577 j++; 578 x[i][j] = A[i1][j1]; 579 } 580 } 581 c[ii][jj] = s*(x[0][0]*(x[1][1]*x[2][2]-x[1][2]*x[2][1]) + 582 x[0][1]*(x[1][2]*x[2][0]-x[1][0]*x[2][2]) + 583 x[0][2]*(x[1][0]*x[2][1]-x[1][1]*x[2][0])); 584 s = -s; 585 } 586 s1 = -s1; 587 } 588 589 // ---- Calculate determinant 590 591 s = 0.0; 592 for (i=0;i<4;i++) 593 s += A[i][0]*c[i][0]; 594 595 // ---- Get inverse matrix 596 597 if (s!=0.0) 598 for (i=0;i<4;i++) 599 for (j=0;j<4;j++) 600 AI[i][j] = c[j][i]/s; 601 602 } 603 Mat3Inverse(const mat33 & A,mat33 & AI)604 realtype Mat3Inverse ( const mat33 & A, mat33 & AI ) { 605 mat33 c,x; 606 realtype s; 607 int ii,jj,i,i1,j,j1; 608 609 // Get cofactors of 'a' in array 'c' 610 611 s = 1.0; 612 for (ii=0;ii<3;ii++) 613 for (jj=0;jj<3;jj++) { 614 i = -1; 615 for (i1=0;i1<3;i1++) 616 if (i1!=ii) { 617 i++; 618 j = -1; 619 for (j1=0;j1<3;j1++) 620 if (j1!=jj) { 621 j++; 622 x[i][j] = A[i1][j1]; 623 } 624 } 625 c[ii][jj] = s*(x[0][0]*x[1][1]-x[0][1]*x[1][0]); 626 s = -s; 627 } 628 629 // Calculate determinant 630 631 s = 0.0; 632 for (i=0;i<3;i++) 633 s += A[i][0]*c[i][0]; 634 635 // Get inverse matrix 636 637 if (s!=0.0) 638 for (i=0;i<3;i++) 639 for (j=0;j<3;j++) 640 AI[i][j] = c[j][i]/s; 641 642 return s; 643 644 } 645 Mat4Mult(mat44 & A,const mat44 & B,const mat44 & C)646 void Mat4Mult ( mat44 & A, const mat44 & B, const mat44 & C ) { 647 // Calculates A=B*C 648 int i,j,k; 649 for (i=0;i<4;i++) 650 for (j=0;j<4;j++) { 651 A[i][j] = 0.0; 652 for (k=0;k<4;k++) 653 A[i][j] += B[i][k]*C[k][j]; 654 } 655 } 656 Mat4Div1(mat44 & A,const mat44 & B,const mat44 & C)657 void Mat4Div1 ( mat44 & A, const mat44 & B, const mat44 & C ) { 658 // Calculates A=B^{-1}*C 659 mat44 B1; 660 int i,j,k; 661 B1[0][0] = 1.0; // in order to supress warnings from some 662 // stupid compilers 663 Mat4Inverse ( B,B1 ); 664 for (i=0;i<4;i++) 665 for (j=0;j<4;j++) { 666 A[i][j] = 0.0; 667 for (k=0;k<4;k++) 668 A[i][j] += B1[i][k]*C[k][j]; 669 } 670 } 671 Mat4Div2(mat44 & A,const mat44 & B,const mat44 & C)672 void Mat4Div2 ( mat44 & A, const mat44 & B, const mat44 & C ) { 673 // Calculates A=B*C^{-1} 674 mat44 C1; 675 int i,j,k; 676 C1[0][0] = 1.0; // in order to supress warnings from some 677 // stupid compilers 678 Mat4Inverse ( C,C1 ); 679 for (i=0;i<4;i++) 680 for (j=0;j<4;j++) { 681 A[i][j] = 0.0; 682 for (k=0;k<4;k++) 683 A[i][j] += B[i][k]*C1[k][j]; 684 } 685 } 686 Mat4Init(mat44 & A)687 void Mat4Init ( mat44 & A ) { 688 int i,j; 689 for (i=0;i<4;i++) { 690 for (j=0;j<4;j++) 691 A[i][j] = 0.0; 692 A[i][i] = 1.0; 693 } 694 } 695 Mat4RotDet(const mat44 & T)696 realtype Mat4RotDet ( const mat44 & T ) { 697 // returns determinant of the rotation part 698 return T[0][0]*T[1][1]*T[2][2] + 699 T[0][1]*T[1][2]*T[2][0] + 700 T[1][0]*T[2][1]*T[0][2] - 701 T[0][2]*T[1][1]*T[2][0] - 702 T[0][0]*T[1][2]*T[2][1] - 703 T[2][2]*T[0][1]*T[1][0]; 704 } 705 isMat4Unit(const mat44 & A,realtype eps,bool rotOnly)706 bool isMat4Unit ( const mat44 & A, realtype eps, bool rotOnly ) { 707 // returns true if A is a unit 4x4 matrix 708 int i,j,k; 709 bool B; 710 711 if (rotOnly) k = 3; 712 else k = 4; 713 714 B = true; 715 for (i=0;(i<k) && B;i++) 716 for (j=0;(j<k) && B;j++) 717 if (i==j) B = (fabs(1.0-A[i][j])<eps); 718 else B = (fabs(A[i][j])<eps); 719 720 return B; 721 722 } 723 Mat3Init(mat33 & A)724 void Mat3Init ( mat33 & A ) { 725 int i,j; 726 for (i=0;i<3;i++) { 727 for (j=0;j<3;j++) 728 A[i][j] = 0.0; 729 A[i][i] = 1.0; 730 } 731 } 732 Mat4Copy(const mat44 & A,mat44 & ACopy)733 void Mat4Copy ( const mat44 & A, mat44 & ACopy ) { 734 int i,j; 735 for (i=0;i<4;i++) 736 for (j=0;j<4;j++) 737 ACopy[i][j] = A[i][j]; 738 } 739 Mat3Copy(const mat33 & A,mat33 & ACopy)740 void Mat3Copy ( const mat33 & A, mat33 & ACopy ) { 741 int i,j; 742 for (i=0;i<3;i++) 743 for (j=0;j<3;j++) 744 ACopy[i][j] = A[i][j]; 745 } 746 isMat4Eq(const mat44 & A,const mat44 & B,realtype eps,bool rotOnly)747 bool isMat4Eq ( const mat44 & A, const mat44 & B, realtype eps, 748 bool rotOnly ) { 749 // returns true if A is equal to B within precision eps 750 int i,j,k; 751 bool Eq; 752 753 if (rotOnly) k = 3; 754 else k = 4; 755 756 Eq = true; 757 for (i=0;(i<k) && Eq;i++) 758 for (j=0;(j<k) && Eq;j++) 759 Eq = (fabs(A[i][j]-B[i][j])<eps); 760 761 return Eq; 762 763 } 764 765 TransformXYZ(const mat44 & T,realtype & X,realtype & Y,realtype & Z)766 void TransformXYZ ( const mat44 & T, realtype & X, realtype & Y, 767 realtype & Z ) { 768 realtype x1,y1,z1; 769 x1 = T[0][0]*X + T[0][1]*Y + T[0][2]*Z + T[0][3]; 770 y1 = T[1][0]*X + T[1][1]*Y + T[1][2]*Z + T[1][3]; 771 z1 = T[2][0]*X + T[2][1]*Y + T[2][2]*Z + T[2][3]; 772 X = x1; 773 Y = y1; 774 Z = z1; 775 } 776 TransformX(const mat44 & T,realtype X,realtype Y,realtype Z)777 realtype TransformX ( const mat44 & T, realtype X, realtype Y, 778 realtype Z ) { 779 return T[0][0]*X + T[0][1]*Y + T[0][2]*Z + T[0][3]; 780 } 781 TransformY(const mat44 & T,realtype X,realtype Y,realtype Z)782 realtype TransformY ( const mat44 & T, realtype X, realtype Y, 783 realtype Z ) { 784 return T[1][0]*X + T[1][1]*Y + T[1][2]*Z + T[1][3]; 785 } 786 TransformZ(const mat44 & T,realtype X,realtype Y,realtype Z)787 realtype TransformZ ( const mat44 & T, realtype X, realtype Y, 788 realtype Z ) { 789 return T[2][0]*X + T[2][1]*Y + T[2][2]*Z + T[2][3]; 790 } 791 792 793 794 795 char CIFErrorLocation[200] = "no error"; 796 797 static cpstr msWrongSection = 798 "Wrong section. The sections in PDB file may be put in wrong order."; 799 static cpstr msWrongChainID = 800 "Wrong chain ID. The input may have changed to another chain."; 801 static cpstr msWrongEntryID = 802 "Entry ID does not match the header."; 803 804 static cpstr msSEQRES_serNum = 805 "Serial numbers of SEQRES records do not increment by 1."; 806 static cpstr msSEQRES_numRes = 807 "Different SEQRES records show different numbers of residues."; 808 static cpstr msSEQRES_extraRes = 809 "SEQRES records contain more residues than specified."; 810 811 static cpstr msNCSM_Unrecognized = 812 "Unrecognized numerical input in MTRIXn."; 813 static cpstr msNCSM_AlreadySet = 814 "Duplicate MTRIXn record."; 815 static cpstr msNCSM_WrongSerial = 816 "Serial number in MTRIXn record is wrong."; 817 static cpstr msNCSM_UnmatchIG = 818 "Different MTRIXn record show different iGiven flag."; 819 820 static cpstr msATOM_Unrecognized = 821 "Numerical information in ATOM record is not recognized."; 822 static cpstr msATOM_AlreadySet = 823 "Atom is already in the system."; 824 static cpstr msATOM_NoResidue = 825 "No residue is found for atom."; 826 static cpstr msATOM_Unmatch = 827 "Unmatch in different records for the same atom."; 828 829 static cpstr msCantOpenFile = "File can not be opened."; 830 static cpstr msUnrecognizedInteger = 831 "Wrong ASCII format of an integer."; 832 static cpstr msWrongModelNo = "Wrong model number."; 833 static cpstr msDuplicatedModel = "Duplicate model number."; 834 static cpstr msNoModel = "No model defined."; 835 static cpstr msForeignFile = 836 "Attempt to read unknown-type file."; 837 static cpstr msWrongEdition = 838 "Attempt to read a higher-version file."; 839 840 static cpstr msNoData = "Expected data field not found."; 841 static cpstr msUnrecognizedReal = "Wrong ASCII format of a real."; 842 static cpstr msNotACIFFile = 843 "Not a CIF file ('data_' missing)."; 844 static cpstr msUnrecognCIFItems = 845 "Unrecognized item(s) in CIF file."; 846 static cpstr msMissingCIFField = "Expected CIF item(s) missing."; 847 static cpstr msEmptyCIFLoop = "Empty CIF loop encountered."; 848 static cpstr msUnexpEndOfCIF = "Unexpected end of CIF file."; 849 static cpstr msMissgCIFLoopField = "Inconsistent CIF loop."; 850 static cpstr msNotACIFStructure = 851 "Wrong use of CIF structure (as a loop?)."; 852 static cpstr msNotACIFLoop = 853 "Wrong use of CIF loop (as a structure?)."; 854 855 static cpstr msNoSheetID = "No Sheet ID on PDB ASCII card."; 856 static cpstr msWrongSheetID = "Wrong Sheet ID."; 857 static cpstr msWrongStrandNo = 858 "Wrong Strand number on PDB SHEET card."; 859 860 static cpstr msWrongNumberOfStrands = 861 "Wrong number of strands in CIF file."; 862 static cpstr msWrongSheetOrder = "Incomplete _struct_sheet_order."; 863 static cpstr msHBondInconsistency = 864 "Inconsistency in _struct_sheet_hbond."; 865 866 static cpstr msEmptyResidueName = 867 "No residue name on PDB ATOM or TER card."; 868 static cpstr msDuplicateSeqNum = 869 "Duplicate sequence number and insertion code."; 870 871 static cpstr msEmptyFile = "Non-existent or empty file."; 872 873 static cpstr msNoLogicalName = "Logical file name not found."; 874 875 GetErrorDescription(ERROR_CODE ErrorCode)876 cpstr GetErrorDescription ( ERROR_CODE ErrorCode ) { 877 878 switch (ErrorCode) { 879 880 case Error_NoError : return "No errors."; 881 882 case Error_WrongSection : return msWrongSection; 883 case Error_WrongChainID : return msWrongChainID; 884 case Error_WrongEntryID : return msWrongEntryID; 885 886 case Error_SEQRES_serNum : return msSEQRES_serNum; 887 case Error_SEQRES_numRes : return msSEQRES_numRes; 888 case Error_SEQRES_extraRes : return msSEQRES_extraRes; 889 890 case Error_NCSM_Unrecognized : return msNCSM_Unrecognized; 891 case Error_NCSM_AlreadySet : return msNCSM_AlreadySet; 892 case Error_NCSM_WrongSerial : return msNCSM_WrongSerial; 893 case Error_NCSM_UnmatchIG : return msNCSM_UnmatchIG; 894 895 case Error_ATOM_Unrecognized : return msATOM_Unrecognized; 896 case Error_ATOM_AlreadySet : return msATOM_AlreadySet; 897 case Error_ATOM_NoResidue : return msATOM_NoResidue; 898 case Error_ATOM_Unmatch : return msATOM_Unmatch; 899 900 case Error_CantOpenFile : return msCantOpenFile; 901 case Error_UnrecognizedInteger : return msUnrecognizedInteger; 902 case Error_WrongModelNo : return msWrongModelNo; 903 case Error_DuplicatedModel : return msDuplicatedModel; 904 case Error_NoModel : return msNoModel; 905 case Error_ForeignFile : return msForeignFile; 906 case Error_WrongEdition : return msWrongEdition; 907 908 case Error_NoData : return msNoData; 909 case Error_UnrecognizedReal : return msUnrecognizedReal; 910 case Error_NotACIFFile : return msNotACIFFile; 911 case Error_UnrecognCIFItems : return msUnrecognCIFItems; 912 case Error_MissingCIFField : return msMissingCIFField; 913 case Error_EmptyCIFLoop : return msEmptyCIFLoop; 914 case Error_UnexpEndOfCIF : return msUnexpEndOfCIF; 915 case Error_MissgCIFLoopField : return msMissgCIFLoopField; 916 case Error_NotACIFStructure : return msNotACIFStructure; 917 case Error_NotACIFLoop : return msNotACIFLoop; 918 919 case Error_NoSheetID : return msNoSheetID; 920 case Error_WrongSheetID : return msWrongSheetID; 921 case Error_WrongStrandNo : return msWrongStrandNo; 922 923 case Error_WrongNumberOfStrands : return msWrongNumberOfStrands; 924 case Error_WrongSheetOrder : return msWrongSheetOrder; 925 case Error_HBondInconsistency : return msHBondInconsistency; 926 927 case Error_EmptyResidueName : return msEmptyResidueName; 928 case Error_DuplicateSeqNum : return msDuplicateSeqNum; 929 930 case Error_EmptyFile : return msEmptyFile; 931 932 case Error_NoLogicalName : return msNoLogicalName; 933 934 default : return "Unknown error."; 935 936 } 937 } 938 939 940 // ============== ContainerClass ==================== 941 ContainerClass()942 ContainerClass::ContainerClass() : io::Stream() { 943 ContinuationNo = 0; 944 } 945 ContainerClass(io::RPStream Object)946 ContainerClass::ContainerClass ( io::RPStream Object ) 947 : io::Stream(Object) { 948 ContinuationNo = 0; 949 } 950 Append(PContainerClass CC)951 bool ContainerClass::Append ( PContainerClass CC ) { 952 return (CC->ContinuationNo>1); 953 } 954 955 956 // =================== ContString ===================== 957 ContString()958 ContString::ContString() : ContainerClass() { 959 InitString(); 960 } 961 ContString(cpstr S)962 ContString::ContString ( cpstr S ) : ContainerClass() { 963 InitString(); 964 ConvertPDBASCII ( S ); 965 } 966 ContString(io::RPStream Object)967 ContString::ContString ( io::RPStream Object ) 968 : ContainerClass(Object) { 969 InitString(); 970 } 971 ~ContString()972 ContString::~ContString() { 973 if (Line) delete[] Line; 974 if (CIFCategory) delete[] CIFCategory; 975 if (CIFTag) delete[] CIFTag; 976 } 977 InitString()978 void ContString::InitString() { 979 Line = NULL; 980 CIFCategory = NULL; 981 CIFTag = NULL; 982 } 983 ConvertPDBASCII(cpstr S)984 ERROR_CODE ContString::ConvertPDBASCII ( cpstr S ) { 985 CreateCopy ( Line,S ); 986 return Error_NoError; 987 } 988 PDBASCIIDump(pstr S,int)989 void ContString::PDBASCIIDump ( pstr S, int ) { 990 if (Line) strcpy ( S,Line ); 991 else strcpy ( S,"" ); 992 } 993 PDBASCIIDump1(io::RFile f)994 bool ContString::PDBASCIIDump1 ( io::RFile f ) { 995 if (Line) f.WriteLine ( Line ); 996 else f.LF(); 997 return true; 998 } 999 1000 /* 1001 void ContString::GetCIF1 ( mmcif::PData CIF, ERROR_CODE & Signal, 1002 int & pos ) { 1003 pstr F; 1004 int i,RC; 1005 char c; 1006 if ((!CIFCategory) || (!CIFTag)) { 1007 Signal = Error_EmptyCIF; 1008 return; 1009 } 1010 F = CIF->GetString ( CIFCategory,CIFTag,RC ); 1011 if (RC || (!F)) { 1012 Signal = Error_EmptyCIF; 1013 return; 1014 } 1015 if (Signal>=(int)strlen(F)) { 1016 CIF->DeleteField ( CIFCategory,CIFTag ); 1017 Signal = Error_EmptyCIF; 1018 return; 1019 } 1020 // i = Signal; 1021 // while (F[i] && (F[i]!='\n') && (F[i]!='\r')) i++; 1022 // if ((Signal==0) && (i==0)) { 1023 // i++; 1024 // if (((F[Signal]=='\n') && (F[i]=='\r')) || 1025 // ((F[Signal]=='\r') && (F[i]=='\n'))) i++; 1026 // Signal = i; 1027 // while (F[i] && (F[i]!='\n') && (F[i]!='\r')) i++; 1028 // } 1029 // c = F[i]; 1030 // F[i] = char(0); 1031 // CreateCopy ( Line,&(F[Signal]) ); 1032 // if (c) { 1033 // F[i] = c; 1034 // Signal = i+1; 1035 // if (((c=='\n') && (F[Signal]=='\r')) || 1036 // ((c=='\r') && (F[Signal]=='\n'))) Signal++; 1037 // } else 1038 // CIF->DeleteField ( CIFCategory,CIFTag ); 1039 i = pos; 1040 while (F[i] && (F[i]!='\n') && (F[i]!='\r')) i++; 1041 if ((pos==0) && (i==0)) { 1042 i++; 1043 if (((F[pos]=='\n') && (F[i]=='\r')) || 1044 ((F[pos]=='\r') && (F[i]=='\n'))) i++; 1045 pos = i; 1046 while (F[i] && (F[i]!='\n') && (F[i]!='\r')) i++; 1047 } 1048 c = F[i]; 1049 F[i] = char(0); 1050 CreateCopy ( Line,&(F[pos]) ); 1051 if (c) { 1052 F[i] = c; 1053 pos = i+1; 1054 if (((c=='\n') && (F[pos]=='\r')) || 1055 ((c=='\r') && (F[pos]=='\n'))) pos++; 1056 } else 1057 CIF->DeleteField ( CIFCategory,CIFTag ); 1058 } 1059 */ 1060 MakeCIF(mmcif::PData CIF,int N)1061 void ContString::MakeCIF ( mmcif::PData CIF, int N ) { 1062 pstr S; 1063 if ((!CIFCategory) || (!CIFTag)) return; 1064 S = new char[strlen(Line)+5]; 1065 strcpy ( S,"\n" ); 1066 strcat ( S,Line ); 1067 CIF->PutString ( S,CIFCategory,CIFTag,(N!=0) ); 1068 delete[] S; 1069 } 1070 Append(PContainerClass CC)1071 bool ContString::Append ( PContainerClass CC ) { 1072 if (ContainerClass::Append(CC)) { 1073 if (!Line) { 1074 Line = PContString(CC)->Line; 1075 PContString(CC)->Line = NULL; 1076 } else 1077 CreateConcat ( Line,pstr("\n"),PContString(CC)->Line ); 1078 return true; 1079 } 1080 return false; 1081 } 1082 Copy(PContainerClass CString)1083 void ContString::Copy ( PContainerClass CString ) { 1084 CreateCopy ( Line,PContString(CString)->Line ); 1085 } 1086 write(io::RFile f)1087 void ContString::write ( io::RFile f ) { 1088 byte Version=1; 1089 f.WriteByte ( &Version ); 1090 f.CreateWrite ( Line ); 1091 f.CreateWrite ( CIFCategory ); 1092 f.CreateWrite ( CIFTag ); 1093 } 1094 read(io::RFile f)1095 void ContString::read ( io::RFile f ) { 1096 byte Version; 1097 f.ReadByte ( &Version ); 1098 f.CreateRead ( Line ); 1099 f.CreateRead ( CIFCategory ); 1100 f.CreateRead ( CIFTag ); 1101 } 1102 1103 MakeStreamFunctions(ContString) 1104 1105 1106 1107 // ============== ClassContainer ==================== 1108 MakeStreamFunctions(ContainerClass)1109 MakeStreamFunctions(ContainerClass) 1110 1111 ClassContainer::ClassContainer() : io::Stream() { 1112 Init(); 1113 } 1114 ClassContainer(io::RPStream Object)1115 ClassContainer::ClassContainer ( io::RPStream Object ) 1116 : io::Stream(Object) { 1117 Init(); 1118 } 1119 Init()1120 void ClassContainer::Init() { 1121 length = 0; 1122 Container = NULL; 1123 } 1124 ~ClassContainer()1125 ClassContainer::~ClassContainer() { 1126 FreeContainer(); 1127 } 1128 FreeContainer()1129 void ClassContainer::FreeContainer() { 1130 int i; 1131 if (Container) { 1132 for (i=0;i<length;i++) 1133 if (Container[i]) 1134 delete Container[i]; 1135 delete[] Container; 1136 } 1137 Container = NULL; 1138 length = 0; 1139 } 1140 AddData(PContainerClass Data)1141 void ClassContainer::AddData ( PContainerClass Data ) { 1142 int i; 1143 PPContainerClass C1; 1144 if (!Data) return; 1145 if (length>0) { 1146 i = length-1; 1147 while (i>=0) { 1148 if (!Container[i]) i--; 1149 else if (Container[i]->GetClassID()!=Data->GetClassID()) i--; 1150 else break; 1151 } 1152 if (i>=0) { 1153 if (Container[i]->Append(Data)) { 1154 delete Data; 1155 return; 1156 } 1157 } 1158 } 1159 C1 = new PContainerClass[length+1]; 1160 for (i=0;i<length;i++) 1161 C1[i] = Container[i]; 1162 C1[length] = Data; 1163 if (Container) delete[] Container; 1164 Container = C1; 1165 length++; 1166 } 1167 PDBASCIIDump(io::RFile f)1168 void ClassContainer::PDBASCIIDump ( io::RFile f ) { 1169 char S[500]; 1170 int i,j; 1171 for (i=0;i<length;i++) 1172 if (Container[i]) { 1173 if (!Container[i]->PDBASCIIDump1(f)) { 1174 Container[i]->PDBASCIIDump ( S,i ); 1175 j = strlen(S); 1176 while (j<80) S[j++] = ' '; 1177 S[80] = char(0); 1178 f.WriteLine ( S ); 1179 } 1180 } 1181 } 1182 GetCIF(mmcif::PData CIF,int ClassID)1183 ERROR_CODE ClassContainer::GetCIF ( mmcif::PData CIF, int ClassID ) { 1184 PContainerClass ContainerClass; 1185 int n; 1186 ERROR_CODE rc; 1187 n = -1; 1188 do { 1189 ContainerClass = MakeContainerClass ( ClassID ); 1190 rc = ContainerClass->GetCIF ( CIF,n ); 1191 if (rc==Error_NoError) 1192 AddData ( ContainerClass ); 1193 } while (rc==Error_NoError); 1194 delete ContainerClass; 1195 if (rc==Error_EmptyCIF) 1196 rc = Error_NoError; 1197 return rc; 1198 } 1199 MakeCIF(mmcif::PData CIF)1200 void ClassContainer::MakeCIF ( mmcif::PData CIF ) { 1201 int i; 1202 for (i=0;i<length;i++) 1203 if (Container[i]) 1204 Container[i]->MakeCIF ( CIF,i ); 1205 } 1206 write(io::RFile f)1207 void ClassContainer::write ( io::RFile f ) { 1208 int i,ClassID; 1209 byte Version=1; 1210 f.WriteByte ( &Version ); 1211 f.WriteInt ( &length ); 1212 for (i=0;i<length;i++) 1213 if (Container[i]) { 1214 ClassID = Container[i]->GetClassID(); 1215 f.WriteInt ( &ClassID ); 1216 Container[i]->write ( f ); 1217 } else { 1218 ClassID = -1; 1219 f.WriteInt ( &ClassID ); 1220 } 1221 } 1222 MakeContainerClass(int ClassID)1223 PContainerClass ClassContainer::MakeContainerClass ( int ClassID ) { 1224 if (ClassID==ClassID_String) return new ContString(); 1225 return new ContainerClass(); 1226 } 1227 GetContainerClass(int ContClassNo)1228 PContainerClass ClassContainer::GetContainerClass (int ContClassNo) { 1229 if ((ContClassNo<0) || (ContClassNo>=length)) return NULL; 1230 return Container[ContClassNo]; 1231 } 1232 Copy(PClassContainer CContainer)1233 void ClassContainer::Copy ( PClassContainer CContainer ) { 1234 int i; 1235 FreeContainer(); 1236 if (CContainer) { 1237 length = CContainer->length; 1238 if (length>0) { 1239 Container = new PContainerClass[length]; 1240 for (i=0;i<length;i++) 1241 if (CContainer->Container[i]) { 1242 Container[i] = MakeContainerClass ( 1243 CContainer->Container[i]->GetClassID() ); 1244 Container[i]->Copy ( CContainer->Container[i] ); 1245 } else 1246 Container[i] = NULL; 1247 } 1248 } 1249 } 1250 read(io::RFile f)1251 void ClassContainer::read ( io::RFile f ) { 1252 int i,ClassID; 1253 byte Version; 1254 FreeContainer(); 1255 f.ReadByte ( &Version ); 1256 f.ReadInt ( &length ); 1257 if (length>0) { 1258 Container = new PContainerClass[length]; 1259 for (i=0;i<length;i++) { 1260 f.ReadInt ( &ClassID ); 1261 if (ClassID>=0) { 1262 Container[i] = MakeContainerClass ( ClassID ); 1263 Container[i]->read ( f ); 1264 } else 1265 Container[i] = NULL; 1266 } 1267 } 1268 } 1269 MakeStreamFunctions(ClassContainer)1270 MakeStreamFunctions(ClassContainer) 1271 1272 1273 1274 // ====================== ID parsers ========================== 1275 1276 1277 AtomPath::AtomPath() : io::Stream() { 1278 InitAtomPath(); 1279 } 1280 AtomPath(cpstr ID)1281 AtomPath::AtomPath ( cpstr ID ) : io::Stream() { 1282 InitAtomPath(); 1283 SetPath ( ID ); 1284 } 1285 AtomPath(io::RPStream Object)1286 AtomPath::AtomPath ( io::RPStream Object ) : io::Stream(Object) { 1287 InitAtomPath(); 1288 } 1289 ~AtomPath()1290 AtomPath::~AtomPath() {} 1291 InitAtomPath()1292 void AtomPath::InitAtomPath() { 1293 modelNo = 0; 1294 chainID [0] = char(0); 1295 seqNum = MinInt4; 1296 insCode [0] = char(0); 1297 resName [0] = char(0); 1298 atomName[0] = char(0); 1299 element [0] = char(0); 1300 altLoc [0] = char(0); 1301 isSet = 0; 1302 } 1303 SetPath(cpstr ID)1304 int AtomPath::SetPath ( cpstr ID ) { 1305 // 1. If ID starts with '/': 1306 // /mdl/chn/seq(res).i/atm[elm]:a 1307 // 1308 // 2. If ID starts with a letter: 1309 // chn/seq(res).i/atm[elm]:a 1310 // 1311 // 3. If ID starts with a number: 1312 // seq(res).i/atm[elm]:a 1313 // 1314 // 4. If ID contains colon ':' then 1315 // it may be just 1316 // atm[elm]:a 1317 // 1318 // All spaces are ignored. isSet 1319 // sets bit for each element present. 1320 // Any element may be a wildcard '*'. 1321 // Wildcard for model will set modelNo=0, 1322 // for sequence number will set 1323 // seqNum=MinInt4. 1324 // 1325 // Returns: 1326 // 0 <-> Ok 1327 // -1 <-> wrong numerical format for model 1328 // -2 <-> wrong numerical format for sequence number 1329 // 1330 char N[100]; 1331 pstr p,p1; 1332 int i,k; 1333 1334 isSet = 0; // clear all bits. 1335 1336 p = pstr(ID); 1337 while (*p==' ') p++; 1338 1339 if (!(*p)) return 0; 1340 1341 if (*p=='/') { 1342 // model number 1343 p++; 1344 i = 0; 1345 while ((*p) && (*p!='/')) { 1346 if (*p!=' ') N[i++] = *p; 1347 p++; 1348 } 1349 N[i] = char(0); 1350 if ((!N[0]) || (N[0]=='*')) modelNo = 0; 1351 else { 1352 modelNo = mround(strtod(N,&p1)); 1353 if ((modelNo==0) && (p1==N)) return -1; 1354 } 1355 isSet |= APATH_ModelNo; 1356 if (*p!='/') return 0; 1357 p++; 1358 while (*p==' ') p++; 1359 } 1360 1361 if ((*p<'0') || (*p>'9')) { 1362 // chain ID 1363 i = 0; 1364 k = sizeof(ChainID)-1; 1365 while ((*p) && (*p!='/')) { 1366 if ((*p!=' ') && (i<k)) chainID[i++] = *p; 1367 p++; 1368 } 1369 chainID[i] = char(0); 1370 if (!chainID[0]) { 1371 chainID[0] = '*'; 1372 chainID[1] = char(0); 1373 } 1374 isSet |= APATH_ChainID; 1375 if (*p!='/') return 0; 1376 p++; 1377 while (*p==' ') p++; 1378 } 1379 1380 if (((*p>='0') && (*p<='9')) || (*p=='-') || 1381 (*p=='(') || (*p=='.')) { 1382 // sequence number, residue name and insertion code 1383 i = 0; 1384 while ((*p) && (*p!='/')) { 1385 if (*p!=' ') N[i++] = *p; 1386 p++; 1387 } 1388 N[i] = char(0); 1389 i = ParseResID ( N,seqNum,insCode,resName ); 1390 if (i==2) return -2; 1391 isSet |= APATH_SeqNum | APATH_InsCode | APATH_ResName; 1392 if (*p!='/') return 0; 1393 p++; 1394 while (*p==' ') p++; 1395 } 1396 1397 if (FirstOccurence(p,':') || FirstOccurence(p,'[')) { 1398 // atom name, chemical element and alternative location 1399 i = 0; 1400 while (*p) { 1401 if (*p!=' ') N[i++] = *p; 1402 p++; 1403 } 1404 N[i] = char(0); 1405 ParseAtomID ( N,atomName,element,altLoc ); 1406 isSet |= APATH_AtomName | APATH_Element | APATH_AltLoc; 1407 } 1408 1409 return 0; 1410 1411 } 1412 write(io::RFile f)1413 void AtomPath::write ( io::RFile f ) { 1414 byte Version=1; 1415 f.WriteByte ( &Version ); 1416 io::Stream::write ( f ); 1417 f.WriteInt ( &modelNo ); 1418 f.WriteInt ( &seqNum ); 1419 f.WriteInt ( &isSet ); 1420 f.WriteTerLine ( chainID ,false ); 1421 f.WriteTerLine ( insCode ,false ); 1422 f.WriteTerLine ( resName ,false ); 1423 f.WriteTerLine ( atomName,false ); 1424 f.WriteTerLine ( element ,false ); 1425 f.WriteTerLine ( altLoc ,false ); 1426 } 1427 read(io::RFile f)1428 void AtomPath::read ( io::RFile f ) { 1429 byte Version; 1430 f.ReadByte ( &Version ); 1431 io::Stream::read ( f ); 1432 f.ReadInt ( &modelNo ); 1433 f.ReadInt ( &seqNum ); 1434 f.ReadInt ( &isSet ); 1435 f.ReadTerLine ( chainID ,false ); 1436 f.ReadTerLine ( insCode ,false ); 1437 f.ReadTerLine ( resName ,false ); 1438 f.ReadTerLine ( atomName,false ); 1439 f.ReadTerLine ( element ,false ); 1440 f.ReadTerLine ( altLoc ,false ); 1441 } 1442 1443 MakeStreamFunctions(AtomPath)1444 MakeStreamFunctions(AtomPath) 1445 1446 1447 1448 // -------------------------------------------------------- 1449 1450 QuickSort::QuickSort() : io::Stream() { 1451 selSortLimit = 15; 1452 data = NULL; 1453 dlen = 0; 1454 } 1455 QuickSort(io::RPStream Object)1456 QuickSort::QuickSort ( io::RPStream Object ) 1457 : io::Stream(Object) { 1458 selSortLimit = 15; 1459 data = NULL; 1460 dlen = 0; 1461 } 1462 Compare(int i,int j)1463 int QuickSort::Compare ( int i, int j ) { 1464 // sort by increasing data[i] 1465 if (((ivector)data)[i]<((ivector)data)[j]) return -1; 1466 if (((ivector)data)[i]>((ivector)data)[j]) return 1; 1467 return 0; 1468 } 1469 Swap(int i,int j)1470 void QuickSort::Swap ( int i, int j ) { 1471 int b; 1472 b = ((ivector)data)[i]; 1473 ((ivector)data)[i] = ((ivector)data)[j]; 1474 ((ivector)data)[j] = b; 1475 } 1476 SelectionSort(int left,int right)1477 void QuickSort::SelectionSort ( int left, int right ) { 1478 int i,j,imin; 1479 for (i=left;i<right;i++) { 1480 imin = i; 1481 for (j=i+1;j<=right;j++) 1482 if (Compare(j,imin)<0) imin = j; 1483 Swap ( i,imin ); 1484 } 1485 } 1486 Partition(int left,int right)1487 int QuickSort::Partition ( int left, int right ) { 1488 int lv = left; 1489 int lm = left-1; 1490 int rm = right+1; 1491 do { 1492 do 1493 rm--; 1494 while ((rm>0) && (Compare(rm,lv)>0)); 1495 do 1496 lm++; 1497 while ((lm<dlen) && (Compare(lm,lv)<0)); 1498 if (lm<rm) { 1499 if (lv==lm) lv = rm; 1500 else if (lv==rm) lv = lm; 1501 Swap ( lm,rm ); 1502 } 1503 } while (lm<rm); 1504 return rm; 1505 } 1506 Quicksort(int left,int right)1507 void QuickSort::Quicksort ( int left, int right ) { 1508 int split_pt; 1509 if (left<(right-selSortLimit)) { 1510 split_pt = Partition ( left,right ); 1511 Quicksort ( left,split_pt ); 1512 Quicksort ( split_pt+1,right ); 1513 } else 1514 SelectionSort ( left,right ); 1515 } 1516 Sort(void * sortdata,int data_len)1517 void QuickSort::Sort ( void * sortdata, int data_len ) { 1518 data = sortdata; 1519 dlen = data_len-1; 1520 if (data) Quicksort ( 0,data_len-1 ); 1521 } 1522 1523 // -------------------------------------------------------- 1524 takeWord(pstr & p,pstr wrd,cpstr ter,int l)1525 void takeWord ( pstr & p, pstr wrd, cpstr ter, int l ) { 1526 pstr p1; 1527 int i; 1528 p1 = strpbrk ( p,ter ); 1529 if (!p1) 1530 p1 = p + strlen(p); 1531 i = 0; 1532 while ((p!=p1) && (i<l)) { 1533 wrd[i++] = *p; 1534 p++; 1535 } 1536 if (i>=l) i = l-1; 1537 wrd[i] = char(0); 1538 p = p1; 1539 } 1540 1541 ParseAtomID(cpstr ID,AtomName aname,Element elname,AltLoc aloc)1542 void ParseAtomID ( cpstr ID, AtomName aname, Element elname, 1543 AltLoc aloc ) { 1544 pstr p; 1545 1546 p = pstr(ID); 1547 while (*p==' ') p++; 1548 1549 strcpy ( aname ,"*" ); 1550 strcpy ( elname,"*" ); 1551 if (*p) aloc[0] = char(0); 1552 else strcpy ( aloc,"*" ); 1553 1554 takeWord ( p,aname,pstr("[: "),sizeof(AtomName) ); 1555 1556 if (*p=='[') { 1557 p++; 1558 takeWord ( p,elname,pstr("]: "),sizeof(Element) ); 1559 if (*p==']') p++; 1560 } 1561 1562 if (*p==':') { 1563 p++; 1564 takeWord ( p,aloc,pstr(" "),sizeof(AltLoc) ); 1565 } 1566 1567 } 1568 ParseResID(cpstr ID,int & sn,InsCode inscode,ResName resname)1569 int ParseResID ( cpstr ID, int & sn, InsCode inscode, 1570 ResName resname ) { 1571 int RC; 1572 pstr p,p1; 1573 char N[100]; 1574 1575 RC = 0; 1576 1577 p = pstr(ID); 1578 while (*p==' ') p++; 1579 1580 sn = ANY_RES; 1581 strcpy ( inscode,"*" ); 1582 strcpy ( resname,"*" ); 1583 1584 N[0] = char(0); 1585 takeWord ( p,N,pstr("(./ "),sizeof(N) ); 1586 if ((!N[0]) || (N[0]=='*')) { 1587 sn = ANY_RES; 1588 RC = 1; 1589 } 1590 if (!RC) { 1591 sn = mround(strtod(N,&p1)); 1592 if (p1==N) RC = 2; 1593 else inscode[0] = char(0); 1594 } 1595 1596 if (*p=='(') { 1597 p++; 1598 takeWord ( p,resname,pstr(")./ "),sizeof(ResName) ); 1599 if (*p==')') p++; 1600 } 1601 1602 if (*p=='.') { 1603 p++; 1604 takeWord ( p,inscode,pstr("/ "),sizeof(InsCode) ); 1605 } 1606 1607 return RC; 1608 1609 } 1610 ParseAtomPath(cpstr ID,int & mdl,ChainID chn,int & sn,InsCode ic,ResName res,AtomName atm,Element elm,AltLoc aloc,PAtomPath DefPath)1611 int ParseAtomPath ( cpstr ID, 1612 int & mdl, 1613 ChainID chn, 1614 int & sn, 1615 InsCode ic, 1616 ResName res, 1617 AtomName atm, 1618 Element elm, 1619 AltLoc aloc, 1620 PAtomPath DefPath ) { 1621 // /mdl/chn/seq(res).i/atm[elm]:a, may be partial 1622 char N[100]; 1623 pstr p,p1; 1624 int i,RC; 1625 bool wasRes; 1626 1627 wasRes = false; 1628 1629 RC = 0; 1630 1631 p = pstr(ID); 1632 while (*p==' ') p++; 1633 1634 mdl = 0; 1635 if (*p=='/') { 1636 p++; 1637 N[0] = char(0); 1638 takeWord ( p,N,pstr("/"),sizeof(N) ); 1639 if ((!N[0]) || (N[0]=='*')) mdl = 0; 1640 else { 1641 mdl = mround(strtod(N,&p1)); 1642 if ((mdl==0) && (p1==N)) return -1; 1643 } 1644 } else if (DefPath) { 1645 if (DefPath->isSet & APATH_ModelNo) 1646 mdl = DefPath->modelNo; 1647 } 1648 1649 strcpy ( chn,"*" ); 1650 if ((*p<'0') || (*p>'9') || (*p=='/')) { 1651 if (*p=='/') p++; 1652 p1 = p; 1653 chn[0] = char(0); 1654 takeWord ( p,chn,pstr("/"),sizeof(ChainID) ); 1655 if (strpbrk(chn,"(.[:-")) { // this was not a chain ID! 1656 if (DefPath) { 1657 if (DefPath->isSet & APATH_ChainID) 1658 strcpy ( chn,DefPath->chainID ); 1659 } else 1660 strcpy ( chn,"*" ); 1661 p = p1; 1662 } 1663 } else if (DefPath) { 1664 if (DefPath->isSet & APATH_ChainID) 1665 strcpy ( chn,DefPath->chainID ); 1666 } 1667 1668 if (*p=='/') p++; 1669 sn = ANY_RES; 1670 strcpy ( ic ,"*" ); 1671 strcpy ( res,"*" ); 1672 if (((*p>='0') && (*p<='9')) || (*p=='-') || 1673 (*p=='(') || (*p=='.')) { 1674 wasRes = true; 1675 N[0] = char(0); 1676 takeWord ( p,N,pstr("/"),sizeof(N) ); 1677 i = ParseResID ( N,sn,ic,res ); 1678 if (i==2) return -2; 1679 } else if (DefPath) { 1680 wasRes = (*p=='/'); 1681 if (DefPath->isSet & APATH_SeqNum) 1682 sn = DefPath->seqNum; 1683 if (DefPath->isSet & APATH_InsCode) 1684 strcpy ( ic,DefPath->insCode ); 1685 if (DefPath->isSet & APATH_ResName) 1686 strcpy ( res,DefPath->resName ); 1687 } 1688 1689 if (*p=='/') p++; 1690 strcpy ( atm ,"*" ); 1691 strcpy ( elm ,"*" ); 1692 strcpy ( aloc,"*" ); 1693 if (wasRes || FirstOccurence(p,':') || FirstOccurence(p,'[')) { 1694 ParseAtomID ( p,atm,elm,aloc ); 1695 } else if (DefPath) { 1696 if (DefPath->isSet & APATH_AtomName) 1697 strcpy ( atm,DefPath->atomName ); 1698 if (DefPath->isSet & APATH_Element) 1699 strcpy ( elm,DefPath->element ); 1700 if (DefPath->isSet & APATH_ResName) 1701 strcpy ( aloc,DefPath->altLoc ); 1702 } 1703 1704 if (mdl<=0) RC |= APATH_WC_ModelNo; 1705 if (chn[0]=='*') RC |= APATH_WC_ChainID; 1706 if (sn==ANY_RES) RC |= APATH_WC_SeqNum; 1707 if (ic[0]=='*') RC |= APATH_WC_InsCode; 1708 if (res[0]=='*') RC |= APATH_WC_ResName; 1709 if (atm[0]=='*') RC |= APATH_WC_AtomName; 1710 if (elm[0]=='*') RC |= APATH_WC_Element; 1711 if (aloc[0]=='*') RC |= APATH_WC_AltLoc; 1712 1713 if (RC & (APATH_WC_ModelNo | APATH_WC_ChainID | 1714 APATH_WC_SeqNum | APATH_WC_InsCode | 1715 APATH_WC_AtomName | APATH_WC_AltLoc)) 1716 RC |= APATH_Incomplete; 1717 1718 return RC; 1719 1720 } 1721 1722 ParseSelectionPath(cpstr CID,int & iModel,pstr Chains,int & sNum1,InsCode ic1,int & sNum2,InsCode ic2,pstr RNames,pstr ANames,pstr Elements,pstr altLocs)1723 int ParseSelectionPath ( 1724 cpstr CID, 1725 int & iModel, 1726 pstr Chains, 1727 int & sNum1, 1728 InsCode ic1, 1729 int & sNum2, 1730 InsCode ic2, 1731 pstr RNames, 1732 pstr ANames, 1733 pstr Elements, 1734 pstr altLocs 1735 ) { 1736 int l,j; 1737 pstr p,p1; 1738 pstr N; 1739 int seqNum [2]; 1740 InsCode insCode[2]; 1741 pstr ID; 1742 bool wasModel,wasChain,wasRes,haveNeg; 1743 1744 l = IMax(10,strlen(CID))+1; 1745 ID = new char[l]; 1746 N = new char[l]; 1747 1748 p = pstr(CID); 1749 p1 = ID; 1750 while (*p) { 1751 if (*p!=' ') { 1752 *p1 = *p; 1753 p1++; 1754 } 1755 p++; 1756 } 1757 *p1 = char(0); 1758 1759 p = ID; 1760 1761 iModel = 0; 1762 strcpy ( Chains,"*" ); 1763 seqNum[0] = ANY_RES; 1764 seqNum[1] = ANY_RES; 1765 strcpy ( insCode[0],"*" ); 1766 strcpy ( insCode[1],"*" ); 1767 strcpy ( RNames ,"*" ); 1768 strcpy ( ANames ,"*" ); 1769 strcpy ( Elements ,"*" ); 1770 strcpy ( altLocs ,"*" ); 1771 1772 wasModel = false; 1773 wasChain = false; 1774 wasRes = false; 1775 1776 if (*p=='/') { 1777 // CID starts with the slash -- take model number first 1778 p++; 1779 N[0] = char(0); 1780 takeWord ( p,N,pstr("/"),l ); 1781 if ((!N[0]) || (N[0]=='*')) iModel = 0; 1782 else { 1783 iModel = mround(strtod(N,&p1)); 1784 if ((iModel==0) && (p1==N)) return -1; 1785 } 1786 if (*p=='/') p++; 1787 wasModel = true; 1788 } 1789 1790 if ((*p) && (wasModel || (*p<'0') || (*p>'9'))) { 1791 p1 = p; 1792 Chains[0] = char(0); 1793 takeWord ( p,Chains,pstr("/"),l ); 1794 if (strpbrk(Chains,"(.[:-")) { // this was not a chain ID! 1795 strcpy ( Chains,"*" ); 1796 p = p1; 1797 } else 1798 wasChain = true; 1799 if (*p=='/') p++; 1800 } 1801 1802 if ((*p) && (wasChain || ((*p>='0') && (*p<='9')) || (*p=='-') || 1803 (*p=='(') || (*p=='.') || (*p=='*'))) { 1804 j = 0; 1805 do { 1806 // take the sequence number 1807 haveNeg = false; 1808 if (*p=='-') { 1809 haveNeg = true; 1810 p++; 1811 } 1812 N[0] = char(0); 1813 takeWord ( p,N,pstr("(.-/"),l ); 1814 if ((!N[0]) || (N[0]=='*')) 1815 seqNum[j] = ANY_RES; 1816 else { 1817 seqNum[j] = mround(strtod(N,&p1)); 1818 if (p1==N) return -2; 1819 if (haveNeg) seqNum[j] = - seqNum[j]; 1820 } 1821 // take the residue list 1822 if (*p=='(') { 1823 p++; 1824 takeWord ( p,RNames,pstr(").-/"),l ); 1825 if (*p==')') p++; 1826 } 1827 // take the insertion code 1828 if (seqNum[j]!=ANY_RES) 1829 insCode[j][0] = char(0); 1830 if (*p=='.') { 1831 p++; 1832 takeWord ( p,insCode[j],pstr("-/"),sizeof(InsCode) ); 1833 } 1834 if (*p=='-') { 1835 p++; 1836 j++; 1837 } else { 1838 if (j==0) { 1839 seqNum[1] = seqNum[0]; 1840 strcpy ( insCode[1],insCode[0] ); 1841 } 1842 j = 10; 1843 } 1844 } while (j<2); 1845 wasRes = true; 1846 } else 1847 wasRes = (*p=='/'); 1848 1849 if (*p=='/') p++; 1850 if ((*p) && (wasRes || FirstOccurence(p,':') || FirstOccurence(p,'['))) { 1851 if (*p) altLocs[0] = char(0); 1852 takeWord ( p,ANames,pstr("[:"),l ); 1853 if (!ANames[0]) strcpy ( ANames,"*" ); 1854 if (*p=='[') { 1855 p++; 1856 takeWord ( p,Elements,pstr("]:"),l ); 1857 if (*p==']') p++; 1858 } 1859 if (*p==':') { 1860 p++; 1861 takeWord ( p,altLocs,pstr(" "),l ); 1862 } 1863 } 1864 1865 /* 1866 printf ( " iModel = %i\n" 1867 " Chains = '%s'\n" 1868 " seqNum1 = %i\n" 1869 " insCode1 = '%s'\n" 1870 " seqNum2 = %i\n" 1871 " insCode2 = '%s'\n" 1872 " RNames = '%s'\n" 1873 " ANames = '%s'\n" 1874 " Elements = '%s'\n" 1875 " altLocs = '%s'\n", 1876 iModel,Chains,seqNum[0],insCode[0], 1877 seqNum[1],insCode[1],RNames,ANames, 1878 Elements,altLocs ); 1879 */ 1880 1881 sNum1 = seqNum[0]; 1882 sNum2 = seqNum[1]; 1883 strcpy ( ic1,insCode[0] ); 1884 strcpy ( ic2,insCode[1] ); 1885 1886 delete[] ID; 1887 delete[] N; 1888 1889 return 0; 1890 1891 } 1892 1893 MakeSelectionPath(pstr CID,int iModel,cpstr Chains,int sNum1,const InsCode ic1,int sNum2,const InsCode ic2,cpstr RNames,cpstr ANames,cpstr Elements,cpstr altLocs)1894 void MakeSelectionPath ( 1895 pstr CID, 1896 int iModel, 1897 cpstr Chains, 1898 int sNum1, 1899 const InsCode ic1, 1900 int sNum2, 1901 const InsCode ic2, 1902 cpstr RNames, 1903 cpstr ANames, 1904 cpstr Elements, 1905 cpstr altLocs 1906 ) { 1907 char S[100]; 1908 int k; 1909 1910 if (iModel>0) { 1911 sprintf ( CID,"/%i",iModel ); 1912 k = 1; 1913 } else { 1914 CID[0] = char(0); 1915 k = 0; 1916 } 1917 1918 if (Chains[0]!='*') { 1919 if (k>0) strcat ( CID,"/" ); 1920 strcat ( CID,Chains ); 1921 k = 2; 1922 } 1923 1924 if ((sNum1!=-MaxInt4) || (ic1[0]!='*')) { 1925 if (k>0) { 1926 if (k<2) strcat ( CID,"/*" ); 1927 strcat ( CID,"/" ); 1928 } 1929 if (sNum1>-MaxInt4) sprintf ( S,"%i",sNum1 ); 1930 else strcpy ( S,"*" ); 1931 if (ic1[0]!='*') { 1932 strcat ( S,"." ); 1933 strcat ( S,ic1 ); 1934 } 1935 strcat ( CID,S ); 1936 1937 if ((sNum2!=-MaxInt4) || (ic2[0]!='*')) { 1938 strcat ( CID,"-" ); 1939 if (sNum1>-MaxInt4) sprintf ( S,"%i",sNum2 ); 1940 else strcpy ( S,"*" ); 1941 if (ic2[0]!='*') { 1942 strcat ( S,"." ); 1943 strcat ( S,ic2 ); 1944 } 1945 strcat ( CID,S ); 1946 } 1947 1948 k = 3; 1949 1950 } 1951 1952 if (RNames[0]!='*') { 1953 if (k<1) strcat ( CID,"(" ); 1954 else if (k<2) strcat ( CID,"*/*(" ); 1955 else if (k<3) strcat ( CID,"/*(" ); 1956 strcat ( CID,RNames ); 1957 strcat ( CID,")" ); 1958 k = 4; 1959 } 1960 1961 if (ANames[0]!='*') { 1962 if (k<1) strcat ( CID,"/*/*/*/" ); // full path 1963 else if (k<2) strcat ( CID,"/*/*/" ); // /mdl + /*/*/ 1964 else if (k<3) strcat ( CID,"/*/" ); // /mdl/chn + /*/ 1965 else if (k<4) strcat ( CID,"/" ); // /mdl/chn/res + / 1966 strcat ( CID,ANames ); 1967 strcat ( CID,")" ); 1968 k = 5; 1969 } 1970 1971 if (Elements[0]!='*') { 1972 if (k<1) strcat ( CID,"[" ); 1973 else if (k<2) strcat ( CID,"/*/*/*[" ); 1974 else if (k<3) strcat ( CID,"/*/*[" ); 1975 else if (k<4) strcat ( CID,"/*[" ); 1976 else if (k<5) strcat ( CID,"[" ); 1977 strcat ( CID,Elements ); 1978 strcat ( CID,"]" ); 1979 k = 6; 1980 } 1981 1982 if (altLocs[0]!='*') { 1983 if (k<1) strcat ( CID,":" ); 1984 else if (k<2) strcat ( CID,"/*/*/*:" ); 1985 else if (k<3) strcat ( CID,"/*/*:" ); 1986 else if (k<4) strcat ( CID,"/*:" ); 1987 else if (k<6) strcat ( CID,":" ); 1988 strcat ( CID,altLocs ); 1989 } 1990 1991 } 1992 1993 } // namespace mmdb 1994 1995