GLYLIB
0.3.0b
|
00001 #include <mylib.h> 00002 #include <molecules.h> 00003 00004 00005 /** \file add_structure-X_to_structure-Y.c Functions for combining structures. 00006 00007 Begun on 20100203 by BLFoley and expanded, as per usual, on a crisis to 00008 crisis basis... 00009 */ 00010 00011 /******************** add_assembly_to_ensemble() *********************/ 00012 /* Function add_assembly_to_ensemble(assembly *A, ensemble *E) will add 00013 the contents of the assembly pointed to by A to the ensemble pointed to 00014 by E. Assuming the internal accounting in E has been done properly, the 00015 contents of A will not overwrite any preexisting data in E. 00016 00017 The function will set assembly pointers from within the ensemble. 00018 00019 Please carefully read the notes below. 00020 00021 This function does NOT update molecular weight, COM, etc., because the 00022 programmer needs to specify which mass info, etc., should be used. You 00023 have to use other functions to set those values. 00024 00025 *** NOTE *** A should *NOT* already be a member of E. If A is already 00026 a member of E, unexpected things might happen in your programs. See the 00027 next note for more info. 00028 00029 *** NOTE *** If you use some sort of weird numbering in your molindex 00030 elements, you need to copy those elsewhere (say to an ensi). This function 00031 will (re)set the moli's to be what it needs. 00032 00033 *** NOTE *** The **a and **r entries in A should ONLY BE POINTING to data 00034 in the normal m.r.a structures in **m. Any data that has copied to 00035 those locations might not be freed, which is bad for your data management. 00036 (risky to free here without knowing -- can't free empty space.) 00037 00038 *** A VERY IMPORTANT NOTE *** 00039 00040 DO NOT FREE THE ASSEMBLY. You can reset the assembly pointer to 00041 go somewhere else, but do not free the memory. If you do, you will 00042 be freeing part of the ensemble. 00043 00044 Here is what the function does: 00045 00046 1. Allocates and/or reallocates E so that it can accomodate the 00047 information found in A. 00048 2. Copies atom information in A into the relevant locations in E. 00049 * If A's information is not arranged in M.r.a format, the 00050 function will currently complain and exit. 00051 3. Make a list of the molecule indices for each atom in the double- 00052 pointed atom and residue lists of A. Also records the offset 00053 between A's m.r.a sets and E's. The molecules are all added 00054 in the order encountered, so detailed indices are not required. 00055 * Before proceeding, the program will reset all molecule 00056 indices in the m.r.a structures. If the atom and residue 00057 pointers do not point there, results may be unexpected. 00058 4. Frees all the molecule space within A. 00059 5. Resets the a** and r** pointers to the appropriate locations in E. 00060 Locations are based on the molecule indices saved earlier. 00061 6. Sets a new assembly double-pointer inside E to point to A[0]. 00062 00063 This is also why A should not already be a member of E. If you 00064 want to duplicate an assembly, this is not the function to use. 00065 */ 00066 00067 void add_assembly_to_ensemble( 00068 assembly *A, ///< pointer to the assembly being added (see docs) 00069 ensemble *E ///< pointer to the ensemble being grown 00070 ){ 00071 int i; ///< generic counter 00072 int j; ///< generic counter 00073 int mi; ///< molecule counter 00074 int ri; ///< residue counter 00075 int ai; ///< atom counter 00076 int Enmi; ///< the initial value of nm in E 00077 molindex *rmoli; ///< list of direct indices for A's **r pointers 00078 molindex *amoli; ///< list of direct indices for A's **a pointers 00079 00080 00081 // check sanity of the Assembly for our purposes 00082 // while we're in here, set all molecule indices to what we need them to be 00083 // If A's information is not arranged in M.r.a format, the function will currently complain and exit. 00084 if(A[0].nm==0) mywhine("add_assembly_to_ensemble: cannot add assembly with no molecules to an ensemble"); 00085 i=j=0; 00086 for(mi=0;mi<A[0].nm;mi++){ 00087 i+=A[0].m[mi][0].nr; // get a count of all residues 00088 for(ri=0;ri<A[0].m[mi][0].nr;ri++){ 00089 // Before proceeding, the program will reset all molecule indices in the m.r.a structures. 00090 A[0].m[mi][0].r[ri].moli.i=-1; 00091 A[0].m[mi][0].r[ri].moli.m=mi; 00092 A[0].m[mi][0].r[ri].moli.r=ri; 00093 A[0].m[mi][0].r[ri].moli.a=-1; 00094 j+=A[0].m[mi][0].r[ri].na; // get a count of all atoms 00095 for(ai=0;ai<A[0].m[mi][0].r[ri].na;ai++){ // set molecule indices for the atoms 00096 A[0].m[mi][0].r[ri].a[ai].moli.i=-1; 00097 A[0].m[mi][0].r[ri].a[ai].moli.m=mi; 00098 A[0].m[mi][0].r[ri].a[ai].moli.r=ri; 00099 A[0].m[mi][0].r[ri].a[ai].moli.a=ai; 00100 } 00101 } 00102 } 00103 // If A's information is not arranged in M.r.a format, the function will currently complain and exit. 00104 if(i==0) mywhine("add_assembly_to_ensemble: all molecules in assemnly have no residues; cannot add to ensemble"); 00105 if(j==0) mywhine("add_assembly_to_ensemble: all residues in assemnly have no atoms; cannot add to ensemble"); 00106 00107 // Make a list of the molecule indices for each atom in the double-pointed atom and residue lists of A. 00108 if(A[0].nr!=0){ 00109 if(A[0].nr!=i){printf("add_assembly_to_ensemble: raw residue count does not equal A[0].nr (for **r). Ignoring.\n");} 00110 if(A[0].nr>i){printf("add_assembly_to_ensemble WARNING: raw residue count is LESS than A[0].nr (for **r). Ignoring.\n");} 00111 rmoli=(molindex *)calloc(A[0].nr,sizeof(molindex)); 00112 for(ri=0;ri<A[0].nr;ri++){rmoli[ri]=A[0].r[ri][0].moli;} 00113 } 00114 if(A[0].na!=0){ 00115 if(A[0].na!=j){printf("add_assembly_to_ensemble: raw atom count does not equal A[0].na (for **a). Ignoring.\n");} 00116 if(A[0].na>j){printf("add_assembly_to_ensemble WARNING: raw atom count is LESS than A[0].na (for **a). Ignoring.\n");} 00117 amoli=(molindex*)calloc(A[0].na,sizeof(molindex)); 00118 for(ai=0;ai<A[0].na;ai++){amoli[ai]=A[0].a[ai][0].moli;} 00119 } 00120 00121 // record the offset between A's m.r.a sets and E's. 00122 Enmi=E[0].nm; 00123 // Allocates and/or reallocates E so that it can accomodate the information found in A. 00124 if(E[0].nm==0) E[0].m=(molecule*)calloc(1,sizeof(molecule)); // initialize if empty 00125 E[0].nm+=A[0].nm; // increment E[0].nm to accomodate new molecules 00126 E[0].m=(molecule*)realloc(E[0].m,E[0].nm*sizeof(molecule)); 00127 00128 //printf("Enmi is %d; E[0].nm is %d\n",Enmi,E[0].nm); 00129 00130 // Copy atom information in A into the relevant locations in E. 00131 // The molecules are all added in the order encountered, so detailed indices are not required. 00132 for(mi=Enmi;mi<E[0].nm;mi++){ 00133 E[0].m[mi]=A[0].m[mi-Enmi][0]; // copy whole molecule over 00134 // Free this molecule space within A. 00135 free(A[0].m[mi-Enmi]); 00136 A[0].m[mi-Enmi]=&E[0].m[mi]; 00137 // reset molecule indicies for residues and atoms 00138 for(ri=0;ri<E[0].m[mi].nr;ri++){ 00139 E[0].m[mi].r[ri].moli.m+=Enmi; 00140 for(ai=0;ai<E[0].m[mi].r[ri].na;ai++){ 00141 E[0].m[mi].r[ri].a[ai].moli.m+=Enmi; 00142 } 00143 } 00144 } 00145 00146 // Reset the a** and r** pointers to the appropriate locations in E. 00147 // It bases the locations on the molecule indices it saved earlier. 00148 for(ri=0;ri<A[0].nr;ri++){ A[0].r[ri]=&E[0].m[rmoli[ri].m].r[rmoli[ri].r]; } 00149 for(ai=0;ai<A[0].na;ai++){ A[0].a[ai]=&E[0].m[amoli[ai].m].r[amoli[ai].r].a[amoli[ai].a]; } 00150 00151 // Set a new assembly double-pointer inside E to point to A[0]. 00152 E[0].nA++; 00153 if(E[0].nA==1) E[0].A=(assembly**)calloc(1,sizeof(assembly*)); // initialize if empty 00154 else E[0].A=(assembly**)realloc(E[0].A,E[0].nA*sizeof(assembly*)); 00155 E[0].A[E[0].nA-1]=&A[0]; 00156 00157 free(rmoli); 00158 free(amoli); 00159 00160 return; 00161 }