source: tags/arb_5.1/DIST/DI_mldist.cxx

Last change on this file was 6100, checked in by westram, 15 years ago
  • fix warning "format not a string literal and no format arguments"
    • GB_export_error → GB_export_error/GB_export_errorf
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <memory.h>
4// #include <malloc.h>
5#include <string.h>
6
7#include <math.h>
8
9#include <arbdb.h>
10#include <arbdbt.h>
11
12#include <aw_root.hxx>
13#include <aw_device.hxx>
14#include <aw_window.hxx>
15#include <aw_preset.hxx>
16#include <awt.hxx>
17
18#include <awt_tree.hxx>
19#include "dist.hxx"
20#include <awt_csp.hxx>
21
22#include "di_matr.hxx"
23#include "di_mldist.hxx"
24
25#define epsilon         0.000001/* a small number */
26
27
28void di_mldist::givens(di_ml_matrix a,long i,long j,long n,double ctheta,double stheta,GB_BOOL left)
29{
30    /* Givens transform at i,j for 1..n with angle theta */
31    long            k;
32    double          d;
33
34    for (k = 0; k < n; k++) {
35        if (left) {
36            d = ctheta * a[i - 1][k] + stheta * a[j - 1][k];
37            a[j - 1][k] = ctheta * a[j - 1][k] - stheta * a[i - 1][k];
38            a[i - 1][k] = d;
39        } else {
40            d = ctheta * a[k][i - 1] + stheta * a[k][j - 1];
41            a[k][j - 1] = ctheta * a[k][j - 1] - stheta * a[k][i - 1];
42            a[k][i - 1] = d;
43        }
44    }
45}                               /* givens */
46
47void di_mldist::coeffs(double x,double y,double *c,double *s,double accuracy)
48{
49    /* compute cosine and sine of theta */
50    double          root;
51
52    root = sqrt(x * x + y * y);
53    if (root < accuracy) {
54        *c = 1.0;
55        *s = 0.0;
56    } else {
57        *c = x / root;
58        *s = y / root;
59    }
60}                               /* coeffs */
61
62void di_mldist::tridiag(di_ml_matrix a,long n,double accuracy)
63{
64    /* Givens tridiagonalization */
65    long            i, j;
66    double          s, c;
67
68    for (i = 2; i < n; i++) {
69        for (j = i + 1; j <= n; j++) {
70            coeffs(a[i - 2][i - 1], a[i - 2][j - 1], &c, &s, accuracy);
71            givens(a, i, j, n, c, s, GB_TRUE);
72            givens(a, i, j, n, c, s, GB_FALSE);
73            givens(eigvecs, i, j, n, c, s, GB_TRUE);
74        }
75    }
76}                               /* tridiag */
77
78void di_mldist::shiftqr(di_ml_matrix a, long n, double accuracy)
79{
80    /* QR eigenvalue-finder */
81    long            i, j;
82    double          approx, s, c, d, TEMP, TEMP1;
83
84    for (i = n; i >= 2; i--) {
85        do {
86            TEMP = a[i - 2][i - 2] - a[i - 1][i - 1];
87            TEMP1 = a[i - 1][i - 2];
88            d = sqrt(TEMP * TEMP + TEMP1 * TEMP1);
89            approx = a[i - 2][i - 2] + a[i - 1][i - 1];
90            if (a[i - 1][i - 1] < a[i - 2][i - 2])
91                approx = (approx - d) / 2.0;
92            else
93                approx = (approx + d) / 2.0;
94            for (j = 0; j < i; j++)
95                a[j][j] -= approx;
96            for (j = 1; j < i; j++) {
97                coeffs(a[j - 1][j - 1], a[j][j - 1], &c, &s, accuracy);
98                givens(a, j, j + 1, i, c, s, GB_TRUE);
99                givens(a, j, j + 1, i, c, s, GB_FALSE);
100                givens(eigvecs, j, j + 1, n, c, s, GB_TRUE);
101            }
102            for (j = 0; j < i; j++)
103                a[j][j] += approx;
104        } while (fabs(a[i - 1][i - 2]) > accuracy);
105    }
106}                               /* shiftqr */
107
108
109void di_mldist::qreigen(di_ml_matrix proba,long n)
110{
111    /* QR eigenvector/eigenvalue method for symmetric matrix */
112    double          accuracy;
113    long            i, j;
114
115    accuracy = 1.0e-6;
116    for (i = 0; i < n; i++) {
117        for (j = 0; j < n; j++)
118            eigvecs[i][j] = 0.0;
119        eigvecs[i][i] = 1.0;
120    }
121    tridiag(proba, n, accuracy);
122    shiftqr(proba, n, accuracy);
123    for (i = 0; i < n; i++)
124        eig[i] = proba[i][i];
125    for (i = 0; i < n_states; i++) {
126        for (j = 0; j < n_states; j++)
127            proba[i][j] = sqrt(pi[j]) * eigvecs[i][j];
128    }
129    /* proba[i][j] is the value of U' times pi^(1/2) */
130}                               /* qreigen */
131
132
133/* pameigen */
134
135void di_mldist::build_exptteig(double tt){
136    int m;
137    for (m = 0; m < n_states; m++) {
138        exptteig[m] = exp(tt * eig[m]);
139    }
140}
141
142void di_mldist::predict(double /*tt*/, long nb1,long  nb2)
143{
144    /* make contribution to prediction of this aa pair */
145    long            m;
146    double          q;
147    double          TEMP;
148    for (m = n_states-1; m >=0; m--) {
149        q = prob[m][nb1] * prob[m][nb2] * exptteig[m];
150        p += q;
151        TEMP = eig[m];
152        dp += TEMP * q;
153        d2p += TEMP * TEMP * q;
154    }
155}                               /* predict */
156
157void            di_mldist::build_predikt_table(int pos){
158    int             b1, b2;
159    double tt = pos_2_tt(pos);
160    build_exptteig(tt);
161    akt_slopes = slopes[pos] = (di_pml_matrix *) calloc(sizeof(di_pml_matrix), 1);
162    akt_curves = curves[pos] = (di_pml_matrix *) calloc(sizeof(di_pml_matrix), 1);
163    akt_infs = infs[pos] = (di_bool_matrix *) calloc(sizeof(di_bool_matrix), 1);
164
165    for (b1 = 0; b1 < this->n_states; b1++) {
166        for (b2 = 0; b2 <= b1; b2++) {
167            p = 0.0;
168            dp = 0.0;
169            d2p = 0.0;
170            predict(tt, b1, b2);
171
172            if (p > 0.0){
173                double ip = 1.0/p;
174                akt_slopes[0][b1][b2] = dp * ip;
175                akt_curves[0][b1][b2] = d2p * ip - dp * dp * (ip * ip);
176                akt_infs[0][b1][b2] = 0;
177                akt_slopes[0][b2][b1] = akt_slopes[0][b1][b2];
178                akt_curves[0][b2][b1] = akt_curves[0][b1][b2];
179                akt_infs[0][b2][b1] = 0;
180            }else{
181                akt_infs[0][b1][b2] = 1;
182                akt_infs[0][b2][b1] = 1;
183            }
184        }
185    }
186}
187
188int di_mldist::tt_2_pos(double tt) {
189    int pos = (int)(tt * fracchange * DI_ML_RESOLUTION);
190    if (pos >= DI_ML_RESOLUTION * DI_ML_MAX_DIST )
191        pos = DI_ML_RESOLUTION * DI_ML_MAX_DIST - 1;
192    if (pos < 0)
193        pos = 0;
194    return pos;
195}
196
197double di_mldist::pos_2_tt(int pos) {
198    double tt =  pos / (fracchange * DI_ML_RESOLUTION);
199    return tt+epsilon;
200}
201
202void            di_mldist::build_akt_predikt(double tt)
203{
204    /* take an aktual slope from the hash table, else calculate a new one */
205    int             pos = tt_2_pos(tt);
206    if (!slopes[pos]){
207        build_predikt_table(pos);
208    }
209    akt_slopes = slopes[pos];
210    akt_curves = curves[pos];
211    akt_infs = infs[pos];
212    return;
213
214}
215
216const char *di_mldist::makedists()
217{
218    /* compute the distances */
219    long            i, j, k, iterations;
220    double          delta, slope, curv;
221    int             b1=0, b2=0;
222    double              tt=0;
223    int         pos;
224
225    for (i = 0; i < spp; i++) {
226        matrix->set(i,i,0.0);
227        {
228            double gauge = (double)i/(double)spp;
229            if (aw_status(gauge*gauge)) return "Aborted";
230        }
231        {
232            /* move all unknown characters to del */
233            ap_pro *seq1 = entries[i]->sequence_protein->sequence;
234            for (k = 0; k <chars ; k++) {
235                b1 = seq1[k];
236                if (b1 <=val) continue;
237                if (b1 == asx || b1 == glx) continue;
238                seq1[k] = del;
239            }
240        }
241
242        for (j = 0; j < i ; j++) {
243            tt = 1.0;
244            delta = tt / 2.0;
245            iterations = 0;
246            do {
247                slope = 0.0;
248                curv = 0.0;
249                pos = tt_2_pos(tt);
250                tt = pos_2_tt(pos);
251                build_akt_predikt(tt);
252                ap_pro *seq1 = entries[i]->sequence_protein->sequence;
253                ap_pro *seq2 = entries[j]->sequence_protein->sequence;
254                for (k = chars; k >0; k--) {
255                    b1 = *(seq1++);
256                    b2 = *(seq2++);
257                    if (predict_infinity(b1,b2)){
258                        break;
259                    }
260                    slope += predict_slope(b1,b2);
261                    curv += predict_curve(b1,b2);
262                }
263                iterations++;
264                if (!predict_infinity(b1,b2)) {
265                    if (curv < 0.0) {
266                        tt -= slope / curv;
267                        if (tt > 10000.0) {
268                            aw_message(GB_export_errorf("INFINITE DISTANCE BETWEEN SPECIES %ld AND %ld; -1.0 WAS WRITTEN\n", i, j));
269                            tt = -1.0 / fracchange;
270                            break;
271                        }
272                        int npos = tt_2_pos(tt);
273                        int d = npos - pos; if (d<0) d=-d;
274                        if (d<=1){  // cannot optimize
275                            break;
276                        }
277
278                    } else {
279                        if ((slope > 0.0 && delta < 0.0) || (slope < 0.0 && delta > 0.0))
280                            delta /= -2;
281                        if (tt + delta < 0 && tt<= epsilon) {
282                            break;
283                        }
284                        tt += delta;
285                    }
286                } else {
287                    delta /= -2;
288                    tt += delta;
289                    if (tt < 0) tt = 0;
290                }
291            } while (iterations < 20);
292        }
293        matrix->set(i,j,fracchange * tt);
294    }
295    return 0;
296}                               /* makedists */
297
298
299void di_mldist::clean_slopes(){
300    int i;
301    if (slopes) {
302        for (i=0;i<DI_ML_RESOLUTION*DI_ML_MAX_DIST;i++) {
303            delete slopes[i]; slopes[i] = 0;
304            delete curves[i]; curves[i] = 0;
305            delete infs[i]; infs[i] = 0;
306        }
307    }
308    akt_slopes = 0;
309    akt_curves = 0;
310    akt_infs = 0;
311}
312
313di_mldist::~di_mldist(){
314    clean_slopes();
315}
316
317di_mldist::di_mldist(long nentries, DI_ENTRY     **entriesi, long seq_len, AP_smatrix *matrixi){
318    memset((char *)this,0,sizeof(di_mldist));
319    entries = entriesi;
320    matrix = matrixi;
321
322    spp = nentries;
323    chars = seq_len;
324
325    //maketrans();
326    qreigen(prob, 20L);
327}
Note: See TracBrowser for help on using the repository browser.