source: tags/ms_r16q2/MULTI_PROBE/MP_sonde.cxx

Last change on this file was 14498, checked in by westram, 8 years ago
  • globally add explicit casts (either long or double) for all numeric ellipse arguments of aisc_put, aisc_nput and aisc_create
    • errors caused by just changing the type of a passed variable are far too subtle
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.0 KB
Line 
1// ============================================================= //
2//                                                               //
3//   File      : MP_sonde.cxx                                    //
4//   Purpose   :                                                 //
5//                                                               //
6//   Institute of Microbiology (Technical University Munich)     //
7//   http://www.arb-home.de/                                     //
8//                                                               //
9// ============================================================= //
10
11#include "MP_externs.hxx"
12#include "MultiProbe.hxx"
13
14#include <aw_msg.hxx>
15#include <arbdbt.h>
16#include <client.h>
17
18#include <cmath>
19
20Sonde::Sonde(char* bezeichner, int allowed_mis, double outside_mis)
21{
22    kennung = strdup(bezeichner);
23    bitkennung = NULL;
24    // fuer Basissonden haben die Bitvektoren noch nicht die Volle laenge, da noch nicht bekannt ist, wieviele Sonden eingetragen werden
25    hitliste = NULL;
26    length_hitliste = 0;
27    minelem = 0;
28    maxelem = 0;
29    int anzahl_sonden = mp_gl_awars.no_of_probes;
30
31    Allowed_Mismatch = new long[anzahl_sonden];
32    Outside_Mismatch = new double[anzahl_sonden];
33    for (int i=0; i<anzahl_sonden; i++)
34    {
35        Allowed_Mismatch[i]=0;
36        Outside_Mismatch[i]=0;
37    }
38
39    Allowed_Mismatch[0] = allowed_mis;
40    Outside_Mismatch[0] = outside_mis;
41
42
43}
44
45Sonde::~Sonde()
46{
47    int i;
48
49    free(kennung);
50
51    for (i=0; i<length_hitliste;  i++) {
52        delete hitliste[i];             // Hits loeschen
53    }
54    delete [] hitliste;
55
56    delete [] Allowed_Mismatch;
57    delete [] Outside_Mismatch;
58    delete bitkennung;
59}
60
61void Sonde::print()
62{
63    printf("\nSonde %s\n------------------------------------------------\n", kennung);
64    bitkennung->print();
65    printf("Laenge hitliste %ld mit minelem %ld und maxelem %ld\n", length_hitliste, minelem, maxelem);
66    printf("Far %ld, Mor %ld, AllMM %ld, OutMM %f\n\n", kombi_far, kombi_mor, *Allowed_Mismatch, *Outside_Mismatch);
67}
68
69
70MO_Mismatch** Sonde::get_matching_species(bool match_kompl, int match_weight, int match_mis, char *match_seq, MO_Liste *convert, long *number_of_species)
71{
72    MO_Mismatch **ret_list   = NULL;
73    const char   *servername = MP_probe_pt_look_for_server();
74
75    if (servername) {
76        char           *match_name, *match_mismatches, *match_wmismatches;
77        char            toksep[2];
78        T_PT_MATCHLIST  match_list;
79        char           *probe      = NULL;
80        char           *locs_error = 0;
81        long            match_list_cnt;
82        bytestring      bs;
83        int             i          = 0;
84
85        GB_ERROR openerr = NULL;
86        mp_pd_gl.link    = aisc_open(servername, mp_pd_gl.com, AISC_MAGIC_NUMBER, &openerr);
87        mp_pd_gl.locs.clear();
88
89        if (openerr) {
90            aw_message(openerr);
91            return NULL;
92        }
93        if (!mp_pd_gl.link) {
94            aw_message("Cannot contact Probe bank server ");
95            return NULL;
96        }
97        if (MP_init_local_com_struct()) {
98            aw_message ("Cannot contact Probe bank server (2)");
99            return NULL;
100        }
101
102        if (aisc_put(mp_pd_gl.link, PT_LOCS, mp_pd_gl.locs,
103                     LOCS_MATCH_REVERSED,       (long)match_kompl, // Komplement
104                     LOCS_MATCH_SORT_BY,        (long)match_weight, // Weighted
105                     LOCS_MATCH_COMPLEMENT,     (long)0,  // ???
106                     LOCS_MATCH_MAX_MISMATCHES, (long)match_mis, // Mismatches
107                     LOCS_SEARCHMATCH,          match_seq, // Sequence
108                     NULL)) {
109            free(probe);
110            aw_message ("Connection to PT_SERVER lost (4)");
111            return NULL;
112        }
113
114        bs.data = 0;
115        aisc_get(mp_pd_gl.link, PT_LOCS, mp_pd_gl.locs,
116                 LOCS_MATCH_LIST,      match_list.as_result_param(),
117                 LOCS_MATCH_LIST_CNT,  &match_list_cnt,
118                 LOCS_MP_MATCH_STRING, &bs,
119                 LOCS_ERROR,           &locs_error,
120                 NULL);
121
122        if (locs_error[0]) aw_message(locs_error);
123        free(locs_error);
124
125        toksep[0] = 1;
126        toksep[1] = 0;
127        if (bs.data)
128        {
129            ret_list = new MO_Mismatch*[match_list_cnt];
130
131            match_name = strtok(bs.data, toksep);
132            match_mismatches = strtok(0, toksep);
133            match_wmismatches = strtok(0, toksep);
134
135            while (match_name && match_mismatches && match_wmismatches)
136            {
137                ret_list[i] = new MO_Mismatch;
138                ret_list[i]->nummer = convert->get_index_by_entry(match_name);
139                if (match_weight == NON_WEIGHTED)
140                    ret_list[i]->mismatch = atof(match_mismatches);
141                else                            // WEIGHTED und WEIGHTED_PLUS_POS
142                    ret_list[i]->mismatch = atof(match_wmismatches);
143
144
145                match_name = strtok(0, toksep);
146                match_mismatches = strtok(0, toksep);
147                match_wmismatches = strtok(0, toksep);
148
149                i++;
150            }
151        }
152        else
153            aw_message("No matching species found.");
154
155        *number_of_species = match_list_cnt;
156
157        aisc_close(mp_pd_gl.link, mp_pd_gl.com);
158        free(bs.data);
159
160    }
161    return ret_list;
162}
163
164
165double Sonde::check_for_min(long k, MO_Mismatch** probebacts, long laenge)
166{
167    long    i = k+1;
168    double  min;
169
170    min = probebacts[k]->mismatch;                  // min ist gleich mismatch des ersten MOs
171    while ((i<laenge) && (probebacts[k]->nummer == probebacts[i]->nummer))
172    {
173        if (min > probebacts[i]->mismatch)              // wenn min groesser ist als mismatch des naechsten MOs
174            min = probebacts[i]->mismatch;              // setze min uf groesse des naechsten
175        i++;                                // checke naechsten MO
176    }
177    return min;
178}
179
180
181
182int Sonde::gen_Hitliste(MO_Liste *Bakterienliste)
183    // Angewandt auf eine frische Sonde generiert diese Methode die Hitliste durch eine Anfrage an die Datenbank, wobei
184    // der Name der Sonde uebergeben wird
185{
186    MO_Mismatch**   probebacts;
187    long        i, k;           // Zaehlervariable
188    long        laenge = 0;
189    double      mm_to_search = 0;
190    int         mm_int_to_search = 0;
191
192
193    // DATENBANKAUFRUF
194    mm_to_search = mp_gl_awars.greyzone + mp_gl_awars.outside_mismatches_difference + get_Allowed_Mismatch_no(0);
195    if (mm_to_search > (int) mm_to_search)
196        mm_int_to_search = (int) mm_to_search + 1;
197    else
198        mm_int_to_search = (int) mm_to_search;
199
200    probebacts = get_matching_species(mp_gl_awars.complement,
201                                      mp_gl_awars.weightedmismatches,
202                                      mm_int_to_search,
203                                      kennung,
204                                      Bakterienliste,
205                                      &laenge);
206
207
208    // ACHTUNG probebacts mit laenge enthaelt nur laenge-1 Eintraege von 0 bis laenge -2
209    if (!laenge || !probebacts)
210    {
211        if (!laenge)
212            aw_message("This probe matches no species!");
213        if (!probebacts)
214        {
215            aw_message("This probe matches no species!");
216            return 11;
217        }
218        return 1;
219    }
220
221    // Ptrliste ist Nullterminiert
222    // Sortieren des Baktnummernfeldes:
223
224    heapsort(laenge, probebacts);
225
226    double min_mm;          // Minimaler Mismatch
227    // laenge ist die Anzahl der Eintraege in probebact
228    // Korrekturschleife, um Mehrfachtreffer auf das gleiche Bakterium abzufangen
229
230    for (k=0;  k < laenge-1;  k++)
231    {
232        if (probebacts[k]->nummer == probebacts[k+1]->nummer)
233        {
234            min_mm = check_for_min(k, probebacts, laenge);
235            probebacts[k]->mismatch = min_mm;
236            while ((k<laenge-1) && (probebacts[k]->nummer == probebacts[k+1]->nummer))
237            {
238                probebacts[k+1]->mismatch = min_mm;
239                k++;
240            }
241        }
242    }
243
244    // Das hier funktioniert, da Liste sortiert ist
245    minelem = probebacts[0]->nummer;
246    maxelem = probebacts[laenge-1]->nummer;
247
248    // Probebacts besteht aus eintraegen der Art (Nummer, Mismatch)
249    hitliste = new Hit*[laenge+1];
250    for (i=0; i<laenge+1; i++)
251        hitliste[i]=NULL;
252
253    for (i=0; i<laenge; i++)
254    {
255        hitliste[i] = new Hit(probebacts[i]->nummer);
256        hitliste[i]->set_mismatch_at_pos(0, probebacts[i]->mismatch);
257    }
258    length_hitliste = laenge;
259
260    // Loesche hitflags wieder
261    long bl_index = 0;
262    Bakt_Info** baktliste = Bakterienliste->get_mo_liste();
263    Bakt_Info** bl_elem = baktliste+1;
264    while (bl_elem[bl_index])
265    {
266        bl_elem[bl_index]->kill_flag();
267        bl_index++;
268    }
269    // Loeschen der Temps
270    for (i=0; i<laenge; i++)
271    {
272        delete probebacts[i];
273    }
274    delete [] probebacts;
275    return 0;
276}
277
278
279
280Hit* Sonde::get_hitdata_by_number(long index)
281{
282    // Gibt Zeiger auf ein Hit Element zurueck, welches an Stelle index steht, vorerst nur zur Ausgabe gedacht
283    if (hitliste && (index < length_hitliste))
284        return hitliste[index];
285    else
286        return NULL;
287}
288
289
290
291
292void Sonde::heapsort(long feldlaenge, MO_Mismatch** Nr_Mm_Feld)
293    // Heapsortfunktion, benutzt sink(), sortiert Feld von longs
294{
295    long        m=0, i=0;
296    MO_Mismatch*    tmpmm;
297
298    for (i=(feldlaenge-1)/2; i>-1; i--)
299        sink(i, feldlaenge-1, Nr_Mm_Feld);
300    for (m=feldlaenge-1; m>0; m--)
301    {
302        tmpmm =  Nr_Mm_Feld[0];
303        Nr_Mm_Feld[0] =  Nr_Mm_Feld[m];
304        Nr_Mm_Feld[m] = tmpmm;
305
306        sink(0, m-1, Nr_Mm_Feld);
307    }
308}
309
310void Sonde::sink(long i, long t, MO_Mismatch** A)
311    // Algorithmus fuer den Heapsort
312{
313    long        j, k;
314    MO_Mismatch*    tmpmm;
315
316    j = 2*i;
317    k = j+1;
318    if (j <= t)
319    {
320        if (A[i]->nummer >= A[j]->nummer)
321            j = i;
322        if (k <= t)
323            if (A[k]->nummer > A[j]->nummer)
324                j = k;
325        if (i != j)
326        {
327            tmpmm = A[i]; A[i] = A[j]; A[j] = tmpmm;
328            sink(j, t, A);
329        }
330    }
331}
332
333void Sonde::set_bitkennung(Bitvector* bv)
334{
335    bitkennung = bv;
336}
337
338
339
340// ########################################################################################################
341/* Bakt_Info haengt in der MO_Liste drinnen. Hier werden u.a. die Hitflags gespeichert
342 */
343// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Methoden Bakt_Info~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
344
345Bakt_Info::Bakt_Info(const char* n)
346{
347    name = strdup(n);                       // MEL  (match_name in mo_liste)
348    hit_flag = 0;
349}
350
351Bakt_Info::~Bakt_Info()
352{
353    free(name);
354    hit_flag = 0;
355}
356
357
358// ##########################################################################################################
359// Hit speichert die  Trefferinformation
360// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Methoden Hit
361
362Hit::Hit(long baktnummer)
363{
364    // Mismatch Array mit Laenge = anzahl Sonden in Experiment
365    int i=0;
366    mismatch = new double[mp_gl_awars.no_of_probes+1];
367    for (i=0; i<mp_gl_awars.no_of_probes+1; i++)
368        mismatch[i]=101;
369
370    baktid = baktnummer;
371}
372
373Hit::~Hit()
374{
375    delete [] mismatch;
376}
377
378// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Note: See TracBrowser for help on using the repository browser.