double CalcAlignmentRMSD(MultipleAlignment *ma) { double total = 0; int i, j, k; if (ma->numChains <= 1) return ma->rmsd = 0; for (i=0; i<ma->numResidues; i++) { double weights = 0; double sum = 0; for (j=0; j<ma->numChains; j++) { if (ma->residues[j].res[i].hasCoords) { for (k=j+1; k<ma->numChains; k++) { if (ma->residues[k].res[i].hasCoords) { /* double w = residues[j].weight * residues[k].weight; */ double w = 1; Vector v; sum += w * lengthSquaredVect(subVect(&v, &ma->residues[j].res[i].coords, &ma->residues[k].res[i].coords)); weights += w; } } } } sum /= weights; total += sum; } ma->rmsd = sqrt(total/ma->numResidues); return ma->rmsd; }
int GetEntries(void ** out, OctTreeNode *node, const Vector *coords, double radius) { int count = 0; Vector diff; subVect(&diff, coords, &node->center); if (lengthSquaredVect(&diff) > (node->radius+radius)*(node->radius+radius)) { return 0; } if (!node->numVertices) { if (diff.x < radius) { if (diff.y < radius) { if (node->children[0] && diff.z < radius) { count += GetEntries(out, node->children[0], coords, radius); } if (node->children[4] && diff.z >= -radius) { count += GetEntries(out+count, node->children[4], coords, radius); } } if (diff.y >= -radius) { if (node->children[2] && diff.z < radius) { count += GetEntries(out+count, node->children[2], coords, radius); } if (node->children[6] && diff.z >= -radius) { count += GetEntries(out+count, node->children[6], coords, radius); } } } if (diff.x >= -radius) { if (diff.y < radius) { if (node->children[1] && diff.z < radius) { count += GetEntries(out+count, node->children[1], coords, radius); } if (node->children[5] && diff.z >= -radius) { count += GetEntries(out+count, node->children[5], coords, radius); } } if (diff.y >= -radius) { if (node->children[3] && diff.z < radius) { count += GetEntries(out+count, node->children[3], coords, radius); } if (node->children[7] && diff.z >= -radius) { count += GetEntries(out+count, node->children[7], coords, radius); } } } return count; } else { int i; for (i=node->numVertices-1; i>=0; i--) { out[i] = node->vertices[i]; } return node->numVertices; } }
void KalmanFilter::getX(double** K) { double* img = imgMatrix(H,X,2,3); double* subV = subVect(Y,img,2); free(img); img = imgMatrix(K,subV,3,2); free(subV); subV = NULL; double* tmp = addVect(X,img,3); free(img); img = NULL; free(X); X = tmp; tmp = NULL; }
MatchedBlockPair *FindBestSet (MatchedBlockPair *matches, int numMatches, MultipleAlignment *a1, MultipleAlignment *a2, ScoreData *s) { Vector min, max = {0.0,0.0,0.0}; MemoryManagementInfo info = {0,0}; MatchedBlockPair **list = (MatchedBlockPair **) malloc(numMatches * sizeof(MatchedBlockPair *)); double displacementRange = s->displacement * 2; int best = 0; int i; int pos; OctTreeNode *trees = (OctTreeNode *) malloc(a2->numResidues * sizeof(OctTreeNode)); double maxBonus = MAX_BONUS; double maxPosBonus = MAX_POS_BONUS; if (!numMatches) return 0; for (i=0; i<a1->numResidues; i++) { /* Currently allow missing positions only in single-structure "alignments." * May allow farther on or remove them altogether. Currently no benefit from * not just removing residues with no alpha carbon coordinates. */ if (a1->numChains > 1 || a1->residues[0].res[i].exists) { max = a1->averages[i++]; break; } } min = max; for (; i<a1->numResidues; i++) { /* Safety check. */ if (a1->numChains == 1 && !a1->residues[0].res[i].exists) continue; if (a1->averages[i].x < min.x) { min.x = a1->averages[i].x; } else if (a1->averages[i].x > max.x) { max.x = a1->averages[i].x; } if (a1->averages[i].y < min.y) { min.y = a1->averages[i].y; } else if (a1->averages[i].y > max.y) { max.y = a1->averages[i].y; } if (a1->averages[i].z < min.z) { min.z = a1->averages[i].z; } else if (a1->averages[i].z > max.z) { max.z = a1->averages[i].z; } } for (i=0; i<a2->numResidues; i++) { InitOctTreeNode(&trees[i], &min, &max); } for (i=0; i<numMatches; i++) { Vector v, first; MatchedBlockPair *match = &matches[i]; match->bestPreviousMatch = -1; /* In this case, don't allow it to be added without a previous strand, * unless it's the first strand. */ if (s->firstStrandLocked) { if (i) { match->bestAssembledScore = -5000; } else { /* Otherwise, keep previous assembled score. Means I can * just insert into old alignments without changing scores. */ match->bestAssembledScore -= match->score; } } else match->bestAssembledScore = 0; transformVect(&first, &match->m, &a2->averages[match->p2]); for (pos=4; pos<match->p2; pos++) { int hits, j; transformVect(&v, &match->m, &a2->averages[pos]); hits = GetEntries((void**)list, &trees[pos], &v, displacementRange); for (j=0; j < hits; j++) { Vector v1, v2; MatchedBlockPair *match2 = list[j]; double score, invCosHalfTest, angle, displacement; if (match2->p1 + match2->len > match->p1) { continue; } if (match2->p2 + match2->len > a2->conflictMap[match->p2][0]) { if (match2->p2 + match2->len-1 == a2->conflictMap[match->p2][0] || a2->conflictMap[match->p2][match2->p2 + match2->len-1 - a2->conflictMap[match->p2][0]]) continue; } if (match2->p1 + match2->len > a1->conflictMap[match->p1][0]) { if (match2->p1 + match2->len-1 == a1->conflictMap[match->p1][0] || a1->conflictMap[match->p1][match2->p1 + match2->len-1 - a1->conflictMap[match->p1][0]]) continue; } score = match2->bestAssembledScore; if (score + maxBonus < match->bestAssembledScore) continue; invCosHalfTest = invHalfCosQuat(&match->q, &match2->q); if (invCosHalfTest < s->angleCos) continue; angle = 0; if (invCosHalfTest<1) angle = 2*acos(invCosHalfTest); score += AngleScore(angle); if (score + maxPosBonus < match->bestAssembledScore) continue; subVect(&v1, &match2->last, &v); transformVect(&v2, &match2->m, &a2->averages[match->p2]); subVect(&v2, &first, &v2); displacement = (lengthVect(&v1) + lengthVect(&v2))/2; if (displacement > s->displacement) continue; score += DisplacementScore(displacement); if (score < match->bestAssembledScore) continue; match->bestAssembledScore = (float) score; match->bestPreviousMatch = (int)(match2 - matches); } } if (match->bestAssembledScore < 0) continue; match->bestAssembledScore += match->score; if (match->bestAssembledScore > matches[best].bestAssembledScore) best = i; pos = match->p2 + match->len-1; AddEntry(&trees[pos], &match->last, &info); } FreeAllMemory(&info); free(trees); free(list); if (!s->lastStrandLocked) return &matches[best]; else return &matches[numMatches-1]; }
/* Note: Doesn't handle non-existant residues. */ double AlignAlignmentBlocks(int p1, int p2, int count1, int count2, WeightedResiduePositions *r1, WeightedResiduePositions *r2, int len, Matrix *m, double minScore) { Matrix A = {0,0,0,0,0,0,0,0,0,0,0,0}; Matrix m1, m2, m3, m4; Vector com1 = {0,0,0}, com2 = {0,0,0}; double E0 = 0; double rmsd; int i, j, k; double *normalized1; double *normalized2; double buffer[2000]; /* * Only malloc when needed, which isn't often. */ if (len <= 1000) { normalized1 = buffer; } else { normalized1 = (double*) malloc(len * sizeof(double) * 2); } normalized2 = normalized1+len; for (i=0; i<len; i++) { Vector v; Vector com1delta = {0,0,0}, com2delta = {0,0,0}; normalized1[i] = 0; normalized2[i] = 0; for (j=0; j<count1; j++) { if (!r1[j].res[p1+i].exists) { /* Shouldn't ever happen. */ return -5; } normalized1[i] += r1[j].weight; addVect(&com1delta, &com1delta, mulVect(&v, &r1[j].res[p1+i].coords, r1[j].weight)); } for (j=0; j<count2; j++) { if (!r2[j].res[p2+i].exists) { /* Shouldn't ever happen. */ return -5; } normalized2[i] += r2[j].weight; addVect(&com2delta, &com2delta, mulVect(&v, &r2[j].res[p2+i].coords, r2[j].weight)); } addVect(&com1, &com1, divVect(&com1delta, &com1delta, normalized1[i])); addVect(&com2, &com2, divVect(&com2delta, &com2delta, normalized2[i])); } divVect(&com1, &com1, len); divVect(&com2, &com2, len); for (i=0; i<len; i++) { if (normalized1[i] != 0 && normalized2[i] != 0) { Vector moved1 = {0,0,0}; Vector moved2 = {0,0,0}; double E0delta1 = 0; double E0delta2 = 0; for (j=0; j<count1; j++) { if (r1[j].res[p1+i].exists) { Vector temp1, temp2; subVect(&temp1, &r1[j].res[p1+i].coords, &com1); mulVect(&temp2, &temp1, r1[j].weight); addVect(&moved1, &moved1, &temp2); E0delta1 += dotVect(&temp1, &temp2); } } E0delta1 /= normalized1[i]; divVect(&moved1, &moved1, normalized1[i]); for (j=0; j<count2; j++) { if (r2[j].res[p2+i].exists) { Vector temp1, temp2; subVect(&temp1, &r2[j].res[p2+i].coords, &com2); mulVect(&temp2, &temp1, r2[j].weight); addVect(&moved2, &moved2, &temp2); E0delta2 += dotVect(&temp1, &temp2); } } E0delta2 /= normalized2[i]; divVect(&moved2, &moved2, normalized2[i]); E0 += E0delta1 + E0delta2; for (j=0; j<3; j++) { for (k=0; k<3; k++) A.M[j][k] += moved2.v[k] * moved1.v[j]; } } } E0/=2; if (minScore > 0) { Matrix ATA; rmsd = CalcRMSD(&ATA, &A, E0, len); if (RMSDScoreSimple(rmsd, len) < minScore) { /* Don't bother with rotation. */ return rmsd; } rmsd = CalcRotation(&m3, &A, &ATA, E0, len); } else { rmsd = CalcRMSDAndRotation(&m3, &A, E0, len); } m3.M[0][3] = 0; m3.M[1][3] = 0; m3.M[2][3] = 0; m2 = m1 = identity; m2.M[0][3] = -com2.v[0]; m2.M[1][3] = -com2.v[1]; m2.M[2][3] = -com2.v[2]; m1.M[0][3] = com1.v[0]; m1.M[1][3] = com1.v[1]; m1.M[2][3] = com1.v[2]; mulMat(&m4, &m3, &m2); mulMat(m, &m1, &m4); if (normalized1 != buffer) free(normalized1); return rmsd; }
void AddEntry(OctTreeNode *node, Vector *coords, MemoryManagementInfo *info) { Vector diff; double r3; subVect(&diff, coords, &node->center); r3 = lengthSquaredVect(&diff); if (r3 > node->radius * node->radius) node->radius = sqrt(r3); if (!node->numVertices) { int add = (diff.x>=0) + ((diff.y>=0) << 1) + ((diff.z>=0) << 2); if (!node->children[add]) { Vector c[2]; c[0] = node->center; c[1] = node->center; if (add & 1) { c[1].x = node->corners[1].x; } else { c[0].x = node->corners[0].x; } if (add & 2) { c[1].y = node->corners[1].y; } else { c[0].y = node->corners[0].y; } if (add & 4) { c[1].z = node->corners[1].z; } else { c[0].z = node->corners[0].z; } node->children[add] = (OctTreeNode*) GetMemory(info, sizeof(OctTreeNode)); InitOctTreeNode(node->children[add], c, c+1); node->children[add]->numVertices = 1; node->children[add]->vertices[0] = coords; subVect(&diff, coords, &node->children[add]->center); node->children[add]->radius = lengthVect(&diff); } else AddEntry(node->children[add], coords, info); } else if (node->numVertices == MAX_OCT_TREE_VERTICES) { int i; Vector *vertices[MAX_OCT_TREE_VERTICES]; for (i=MAX_OCT_TREE_VERTICES-1; i>=0; i--) { vertices[i] = node->vertices[i]; node->vertices[i] = 0; } node->numVertices = 0; AddEntry(node, coords, info); for (i=MAX_OCT_TREE_VERTICES-1; i>=0; i--) { AddEntry(node, vertices[i], info); } } else { node->vertices[node->numVertices++] = coords; } }