source: tags/svn.1.5.4/NTREE/AP_cprofile.cxx

Last change on this file was 8356, checked in by westram, 13 years ago
  • removed unused default-param from AW_repeated_question
  • use AW_repeated_question in GDE-reimport (used similar inline code)
  • replaced a few more uses by aw_message / aw_ask_sure
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 61.6 KB
Line 
1/* -----------------------------------------------------------------
2 * Project:                       ARB
3 *
4 * Module:                        conservation profile [abbrev.: CPRO]
5 *
6 * Exported Classes:              x
7 *
8 * Global Functions:              x
9 *
10 * Global Variables:
11 *                                  AWARS
12 *               AW_STRING, "cpro/alignment" : name of alignment
13 *               AW_STRING, "cpro/which_species" : all/marked
14 *               AW_STRING, "cpro/countgaps" : if off, drop gaps
15 *               AW_FLOAT, "cpro/rateofgroup" : how to rate, when two
16 *                 characters belong to the same group [ 0.0 means don't rate ]
17 *               AW_INT, AWAR_CURSOR_POSITION:
18 *                           column shown in func. CPRO_drawstatistic_cb
19 *
20 * Global Structures:             CPRO
21 *
22 * Private Classes:               .
23 *
24 * Private Functions:             .
25 *
26 * Private Variables:             .
27 *
28 * Dependencies:             Needs cprofile.fig, CPROdraw.fig, CPROdens.fig
29 *                                 CPROxpert.fig CPROcalc.fig
30 *
31 * Description:                   x
32 *
33 * Integration Notes: The main function using this module must have a
34 *                    callback to the function
35 *                    AW_window *AP_open_cprofile_window( AW_root *aw_root)
36 *                    and the function void AP_create_consensus_var
37 *                    (AW_root *aw_root, AW_default aw_def) has to be called.
38 *
39 * -----------------------------------------------------------------
40 */
41
42#include <awt_sel_boxes.hxx>
43
44#include <aw_awars.hxx>
45#include <aw_file.hxx>
46#include <aw_window.hxx>
47#include <aw_msg.hxx>
48#include <arb_progress.h>
49#include <aw_root.hxx>
50#include <aw_question.hxx>
51#include <aw_device.hxx>
52
53#include <arbdbt.h>
54#include <arb_defs.h>
55
56#include <iostream>
57#include <cmath>
58
59#define ap_assert(cond) arb_assert(cond)
60
61typedef GB_UINT4  STATTYPE;
62extern GBDATA    *GLOBAL_gb_main;
63enum {
64    GAP = 1,
65    BAS_A = 2,
66    BAS_C = 3,
67    BAS_G = 4,
68    BAS_T = 5,
69    MAX_BASES = 6,
70    MAX_AMINOS = 27+GAP
71};
72#define GC_black 7
73#define GC_blue 6
74#define GC_green 5
75#define GC_grid 4
76
77
78struct CPRO_result_struct {
79    STATTYPE **statistic;
80    long maxalignlen;          // length of longest sequence
81    long resolution;           // resolution of statistic table
82    float ratio;               // ratio between transitions and transversion
83    long maxaccu;              // highest number of compares per distance
84    long memneeded;            // memory required for this statistic
85    char which_species[20];    // "marked vs all" , ...
86    char drawmode;             // smoothing
87    char alignname[80];        // name of alignment
88    char statisticexists;      // was there yet a statistic calculated/loaded ?
89    long leastcompares;        // if less overlap between two sequences
90                               // comparison doesn't contribute to statistic
91    long countgaps;            // if 0, comparisons with gaps are not counted
92};
93
94struct CPRO_struct {
95    long numspecies;           // number of species
96    long maxresneeded;         // not yet used (max distance of calculation)
97    long partition;            // size of partition in matrix of compares
98    long leastaccu;            // if less compares per distance don't show
99    char *agonist;             // list of species that contribute to statistic
100    char *antagonist;          // -^-
101    char convtable[256];         // converts character to a token
102    char grouptable[MAX_AMINOS]; // gives number of group, in which token is
103                                 // member
104    float grouprate;           // ratio between transitions and transversions
105    float distancecorrection;  // results out of grouprate
106    long column;               // column of alignment that is shown [1..N]
107    float maxdistance;         // statistic shows up to this point of distance
108    long gridhorizontal;       // grid over statistic
109    long gridvertical;         // -^-
110    float Z_it_group;          // last value , needed for smoothing
111    float Z_it_equal;          // -^-
112    struct CPRO_result_struct result[2]; // info needed for each statistic
113};
114
115static CPRO_struct CPRO;
116
117/* -----------------------------------------------------------------
118 * Function:                     CPRO_readandallocate
119 *
120 * Arguments:                    char versus,char *align (name of alignment)
121 *
122 * Returns:                      modifies:
123 *                               char **&speciesdata,GBDATA **&speciesdatabase
124 *
125 * Description:     Memory for 'statistic', 'speciesdata', 'speciesdatabase',
126 *                  'agonist' and 'antagonist' is allocated.
127 *                  Pointers to the sequences in the database are
128 *                  read into array 'speciesdatabase'.
129 *
130 *
131 * NOTE:                         .
132 *
133 * Global Variables referenced:  .
134 *
135 * Global Variables modified:    CPRO.agonist,CPRO.antagonist,CPRO.numspecies
136 *
137 * AWARs referenced:             .
138 *
139 * AWARs modified:               x
140 *
141 * Dependencies:                 .
142 * -----------------------------------------------------------------
143 */
144static void CPRO_readandallocate(char **&speciesdata, GBDATA **&speciesdatabase,
145                                 char versus, char *align)
146{
147    GBDATA *gb_species_data = GB_search(GLOBAL_gb_main, "species_data", GB_FIND);
148    GBDATA *gb_species;
149
150    {
151        long nrofspecies=0;
152        gb_species = GBT_first_species_rel_species_data(gb_species_data);
153        while (gb_species)
154        {
155            if (GBT_read_sequence(gb_species, align)) {
156                nrofspecies++; }
157            gb_species = GBT_next_species(gb_species);
158        }
159        CPRO.numspecies=nrofspecies;
160    }
161
162    speciesdata=(char **)calloc((size_t)CPRO.numspecies, sizeof(char *));
163    CPRO.agonist=(char *)calloc((size_t)CPRO.numspecies, sizeof(char));
164    CPRO.antagonist=(char *)calloc((size_t)CPRO.numspecies, sizeof(char));
165    speciesdatabase=(GBDATA **)calloc((size_t)CPRO.numspecies+1, sizeof(GBDATA *)); // Null terminated
166    GBDATA *alidata;
167
168    long countspecies=0;
169    gb_species = GBT_first_species_rel_species_data(gb_species_data);
170    while (gb_species) {
171        if ((alidata=GBT_read_sequence(gb_species, align))) {
172            speciesdatabase[countspecies++] = alidata;
173        }
174        gb_species = GBT_next_species(gb_species);
175    }
176
177    for (long i=0; i<CPRO.numspecies; i++)
178    {
179        CPRO.agonist[i]=1;
180        CPRO.antagonist[i]=1;
181    }
182
183    if (versus!=0)
184    {
185        for (long j=0; j<CPRO.numspecies; j++)
186        {
187            CPRO.antagonist[j]=0;
188            if (GB_read_flag(GB_get_grandfather(speciesdatabase[j])))
189                CPRO.antagonist[j]=(char)1;
190        }
191    }
192    if (versus==1)
193    {
194        long j;
195        for (j=0; j<CPRO.numspecies; j++) CPRO.agonist[j]=CPRO.antagonist[j];
196    }
197}
198
199// frees memory allocated by function CPRO_readandallocate
200static void CPRO_deallocate(char **&speciesdata, GBDATA **&speciesdatabase)
201{
202    for (long i=0; i<CPRO.numspecies; i++) freenull(speciesdata[i]);
203    freenull(speciesdata);
204
205    free(speciesdatabase);
206    free(CPRO.agonist);
207    free(CPRO.antagonist);
208    // 'CPRO.statistic' must not be freed, because it is needed in
209    // function CPRO_drawstatistic
210}
211
212static void CPRO_allocstatistic(unsigned char which_statistic)
213{
214    CPRO.result[which_statistic].statistic=(STATTYPE **)calloc((size_t)CPRO.result[which_statistic].resolution*3+3, sizeof(STATTYPE *));
215    for (long i=0; i<CPRO.result[which_statistic].resolution*3; i++) {
216        CPRO.result[which_statistic].statistic[i]=(STATTYPE *)calloc((size_t)CPRO.result[which_statistic].maxalignlen, sizeof(STATTYPE));
217    }
218}
219
220static void CPRO_freestatistic(unsigned char which_statistic)
221{
222    for (long j=0; j<CPRO.result[which_statistic].resolution*3; j++) {
223        freenull(CPRO.result[which_statistic].statistic[j]);
224    }
225    freenull(CPRO.result[which_statistic].statistic);
226}
227
228// memory not used is given back to system
229static void CPRO_workupstatistic(unsigned char which_statistic)
230{
231    long base;
232    long column, memneeded=0;
233    long sum, hits, different, group;
234    long hitsc, diffc, groupc;
235    CPRO.maxresneeded=0;
236    CPRO.result[which_statistic].maxaccu=0;
237    for (long res=0; res<CPRO.result[which_statistic].resolution; res++)
238    {
239        base=res*3;
240        hits=0; different=0; group=0;
241        for (column=0; column<CPRO.result[which_statistic].maxalignlen; column++)
242        {
243            hitsc=(long)CPRO.result[which_statistic].statistic[base+0][column];
244            groupc=(long)CPRO.result[which_statistic].statistic[base+1][column];
245            diffc=(long)CPRO.result[which_statistic].statistic[base+2][column];
246            sum=hitsc+groupc+diffc;
247            hits+=hitsc; group+=groupc; different+=diffc;
248
249            if (sum) CPRO.maxresneeded=res+1;
250            if (sum>CPRO.result[which_statistic].maxaccu)
251            {
252                CPRO.result[which_statistic].maxaccu=sum;
253            }
254        }
255        if (hits) memneeded += CPRO.result[which_statistic].maxalignlen;
256        else freenull(CPRO.result[which_statistic].statistic[base+0]);
257
258        if (group) memneeded += CPRO.result[which_statistic].maxalignlen;
259        else freenull(CPRO.result[which_statistic].statistic[base+1]);
260
261        if (different) memneeded += CPRO.result[which_statistic].maxalignlen;
262        else freenull(CPRO.result[which_statistic].statistic[base+2]);
263    }
264    if (!CPRO.result[which_statistic].maxaccu) CPRO.result[which_statistic].maxaccu=1;
265    CPRO.result[which_statistic].memneeded=memneeded;
266}
267
268
269/* -----------------------------------------------------------------
270 * Function:          CPRO_maketables
271 *
272 * Arguments:         char isamino
273 *
274 * Returns:           modifies: char *CPRO.convtable,
275 *                              char *CPRO.grouptable
276 *
277 * Description:       Fills tables CPRO.convtable and CPRO.grouptable, that are
278 *                    used later, when making the statistic. Meaning of tables:
279 *                    E.g. CPRO.convtable['a']=BAS_A means that char. 'a' is
280 *                    converted into number BAS_A. Then CPRO.grouptable[BAS_A]=1
281 *                    and CPRO.grouptable[BAS_G]=1 means, that characters 'a'
282 *                   and 'g' are both members of group 1.
283 *
284 * NOTE:                         .
285 *
286 * Global Variables referenced:  .
287 *
288 * Global Variables modified:    char *CPRO.convtable, char *CPRO.grouptable
289 *
290 * AWARs referenced:             .
291 *
292 * AWARs modified:               x
293 *
294 * Dependencies:                 .
295 * -----------------------------------------------------------------
296 */
297static void CPRO_maketables(char isamino, char countgaps)
298{
299    long i;
300    for (i=0; i<256; i++) {
301        CPRO.convtable[i]=0; }
302    if (!isamino)
303    {
304        if (countgaps) CPRO.convtable[(unsigned char)'-']=GAP;
305        CPRO.convtable[(unsigned char)'a']=BAS_A;  CPRO.convtable[(unsigned char)'A']=BAS_A;
306        CPRO.convtable[(unsigned char)'c']=BAS_C;  CPRO.convtable[(unsigned char)'C']=BAS_C;
307        CPRO.convtable[(unsigned char)'g']=BAS_G;  CPRO.convtable[(unsigned char)'G']=BAS_G;
308        CPRO.convtable[(unsigned char)'t']=BAS_T;  CPRO.convtable[(unsigned char)'T']=BAS_T;
309        CPRO.convtable[(unsigned char)'u']=BAS_T;  CPRO.convtable[(unsigned char)'U']=BAS_T;
310
311        for (i=0; i<MAX_AMINOS; i++) {
312            CPRO.grouptable[i]=0;
313        }
314        CPRO.grouptable[BAS_A]=1;   CPRO.grouptable[BAS_G]=1;
315        CPRO.grouptable[BAS_C]=2;   CPRO.grouptable[BAS_T]=2;
316    }
317    else
318    {
319        if (countgaps) CPRO.convtable[(unsigned char)'-'] = GAP;
320        for (i=0; i<MAX_AMINOS; i++)
321        {
322            CPRO.convtable[(unsigned char)'a'+i] = i+1+GAP;
323            CPRO.convtable[(unsigned char)'A'+i] = i+1+GAP;
324        }
325        CPRO.convtable[(unsigned char)'*'] = 10+GAP;    // 'J'
326
327        for (i=0; i<MAX_AMINOS; i++) CPRO.grouptable[i] = 0;
328
329#define SC(x, P) CPRO.grouptable[(unsigned char)P-(unsigned char)'A'+1+GAP] = x
330        SC(1, 'P'); SC(1, 'A'); SC(1, 'G'); SC(1, 'S'); SC(1, 'T'); // PAGST
331        SC(2, 'Q'); SC(2, 'N'); SC(2, 'E'); SC(2, 'D'); SC(2, 'B'); SC(2, 'Z'); // QNEDBZ
332        SC(3, 'H'); SC(3, 'K'); SC(3, 'R'); // HKR
333        SC(4, 'L'); SC(4, 'I'); SC(4, 'V'); SC(4, 'M'); // LIVM
334        SC(5, 'F'); SC(5, 'Y'); SC(5, 'W'); // FYW
335#undef SC
336    }
337}
338
339
340static void CPRO_entryinstatistic(char **speciesdata, long elemx, long elemy, unsigned char which_statistic)
341{
342    unsigned char  value1, value2 = 0;
343    char          *firstseq       = speciesdata[elemx];
344    char          *secondseq      = speciesdata[elemy];
345    float          rate           = 0.0;
346    long           numofcolumns   = 0;
347    float          distance       = 0.0;
348
349
350    if (elemx==elemy) return;
351    if (!(CPRO.agonist[elemx])) return;
352    if (!(CPRO.antagonist[elemy])) return;
353    if ((CPRO.agonist[elemy])&&(CPRO.antagonist[elemx])&&(elemy<elemx)) return;
354
355    // add similarities (added 1.0 means equal, 0.0 means different)
356    long counter;
357    for (counter=0; counter<CPRO.result[which_statistic].maxalignlen; counter++)
358    {
359        if ((value1=*firstseq)&&(value2=*secondseq))
360        {
361            numofcolumns++;
362            if (value1==value2) {
363                rate=rate+1.0; }
364            else if (CPRO.grouptable[value1]==CPRO.grouptable[value2]) {
365                rate=rate+CPRO.grouprate; } // add transition weighted
366            // between 1.0 and 0.0
367        }
368        firstseq++;
369        secondseq++;
370    }
371
372    if (numofcolumns<CPRO.result[which_statistic].leastcompares) return;
373    distance=((float)numofcolumns-rate)/(float)numofcolumns;
374    distance=distance*CPRO.distancecorrection;
375
376    long column=(long)(distance*CPRO.result[which_statistic].resolution);
377
378    if (column < 0 || column >= CPRO.result[which_statistic].resolution) return;
379
380    STATTYPE *equalentry     = CPRO.result[which_statistic].statistic[3*column];
381    STATTYPE *samegroupentry = CPRO.result[which_statistic].statistic[3*column+1];
382    STATTYPE *differententry = CPRO.result[which_statistic].statistic[3*column+2];
383
384    firstseq  = speciesdata[elemx];
385    secondseq = speciesdata[elemy];
386
387    for (counter=0; counter<CPRO.result[which_statistic].maxalignlen; counter++)
388    {
389        if ((value1=*firstseq)&&(value2=*secondseq))
390            // when gap or unaligned base goto next position
391        {
392            if (value1==value2) { (*equalentry)++; }
393            else if (CPRO.grouptable[value1]==CPRO.grouptable[value2]) {
394                (*samegroupentry)++; }
395            else { (*differententry)++; }
396        }
397        firstseq++;
398        secondseq++;
399        equalentry++;
400        samegroupentry++;
401        differententry++;
402    }
403
404
405
406}
407
408// is used by function CPRO_makestatistic
409// reads sequences of a segment into memory, converts them
410// and frees older sequences
411static void CPRO_readneededdata(char **speciesdata, GBDATA **speciesdatabase,
412                                long elemx1, long elemx2, long elemy1, long elemy2, unsigned char which_statistic)
413{
414    long i=0, j=0;
415    const char *tempdata;
416    for (i=0; i<CPRO.numspecies; i++) {
417        if ((speciesdata[i]) && (i<elemy1) && (i>elemy2) && (i<elemx1) && (i>elemx2)) {
418            delete(speciesdata[i]); speciesdata[i]=0;
419        }
420    }
421
422    if (elemx1<CPRO.numspecies) {
423        for (i=elemx1; (i<=elemx2 && i<CPRO.numspecies); i++) {
424            if ((CPRO.agonist[i])&&(!(speciesdata[i]))) {
425                tempdata=GB_read_char_pntr(speciesdatabase[i]);
426                speciesdata[i]=(char*)calloc((unsigned int) CPRO.result[which_statistic].maxalignlen, 1);
427                for (j=0; j<CPRO.result[which_statistic].maxalignlen; j++) {
428                    speciesdata[i][j]=CPRO.convtable[(unsigned char)tempdata[j]];
429                }
430            }
431        }
432    }
433    if (elemy1<CPRO.numspecies) {
434        for (i=elemy1; (i<=elemy2 && i<CPRO.numspecies); i++) {
435            if ((CPRO.antagonist[i])&&(!(speciesdata[i]))) {
436                tempdata=GB_read_char_pntr(speciesdatabase[i]);
437                speciesdata[i]=(char*)calloc((unsigned int) CPRO.result[which_statistic].maxalignlen, 1);
438                for (j=0; j<CPRO.result[which_statistic].maxalignlen; j++) {
439                    speciesdata[i][j]=CPRO.convtable[(unsigned char)tempdata[j]];
440                }
441            }
442        }
443    }
444}
445
446
447/* -----------------------------------------------------------------
448 * Function:                     CPRO_makestatistic
449 *
450 * Arguments:                    char **speciesdata,
451 *                               GBDATA **speciesdatabase
452 *
453 * Returns:                      1 if successful, 0 if user abort
454 *                                   (without consequences)
455 *
456 * Description:    This function compares every sequence with every sequence.
457 *                 It divides the matrix into segments and goes through each
458 *                 segment. Width of a segment depends on CPRO.partition.
459 *                 MAX_MEMORY/2 is available.
460 *                 When a new segment is entered, the corresponding
461 *                 sequences are loaded into array 'speciesdata' by the function
462 *                 CPRO_readneededdata. 'speciesdatabase' contains pointers of
463 *                 sequences to the database. Comparison and evaluation of two
464 *                 sequences is done by function CPRO_entryinstatistic.
465 *
466 * NOTE:                         .
467 *
468 * Global Variables referenced:
469 *      CPRO.numspecies,CPRO.result[which_statistic].maxalignlen
470 *
471 * Global Variables modified:    x
472 *
473 * AWARs referenced:             .
474 *
475 * AWARs modified:          CPRO.result[which_statistic].statistic  is modified
476 *
477 * Dependencies:                 CPRO_entryinstatistic , CPRO_readneededdata
478 * -----------------------------------------------------------------
479 */
480static char CPRO_makestatistic(char **speciesdata, GBDATA **speciesdatabase, unsigned char which_statistic)
481{
482    long widthmatrix    = CPRO.partition;
483    long n              = CPRO.numspecies;
484    long comparesneeded = n*n;
485    long numofsegments  = CPRO.numspecies/widthmatrix + 1;
486
487    if (CPRO.result[which_statistic].statisticexists) {
488        CPRO_freestatistic(which_statistic);
489    }
490    else CPRO.result[which_statistic].statisticexists=1;
491
492    CPRO_allocstatistic(which_statistic);
493
494    arb_progress progress("calculating matrix", comparesneeded);
495    bool         aborted = false;
496
497    for (long segmentx=0; segmentx<numofsegments && !aborted; segmentx++) {
498        long elemx1 = widthmatrix*segmentx;
499        long elemx2 = widthmatrix*(segmentx+1)-1;
500
501        for (long segmenty=0; segmenty<numofsegments && !aborted; segmenty++) {
502            long elemy1 = widthmatrix*segmenty;
503            long elemy2 = widthmatrix*(segmenty+1)-1;
504           
505            CPRO_readneededdata(speciesdata, speciesdatabase, elemx1, elemx2, elemy1, elemy2, which_statistic);
506            for (long elemx=elemx1; elemx<=elemx2 && !aborted; elemx++) {
507                for (long elemy=elemy1; elemy<=elemy2 && !aborted; elemy++) {
508                    if ((elemy<CPRO.numspecies)&&(elemx<CPRO.numspecies)) {
509                        CPRO_entryinstatistic(speciesdata, elemx, elemy, which_statistic);
510                        ++progress;
511                        aborted = progress.aborted();
512                    }
513                }
514            }
515        }
516    }
517    return (1);
518}
519
520
521
522/* -----------------------------------------------------------------
523 * Function:                     CPRO_calculate_cb
524 *
525 * Arguments:                    .
526 *
527 * Returns:                      .
528 *
529 * Description:          main callback
530 *                       This function calculates the conservative profile.
531 *                       Function CPRO_readandallocate allocates memory and
532 *                       reads necessary data. Calculation of the statistic
533 *                       is done in function CPRO_makestatistic.
534 *                       Allocated memory is freed in function CPRO_deallocate.
535 *
536 * NOTE:                         .
537 *
538 * Global Variables referenced:  .
539 *
540 * Global Variables modified:    x
541 *
542 * AWARs referenced:             cpro/alignment , cpro/which_species
543 *                               cpro/countgaps , cpro/rateofgroups
544 *
545 * AWARs modified:               x
546 *
547 * Dependencies:   CPRO_readandallocate , CPRO_makestatistic , CPRO_deallocate
548 * -----------------------------------------------------------------
549 */
550
551static void CPRO_memrequirement_cb(AW_root *aw_root); // prototype
552
553static void CPRO_calculate_cb(AW_window *aw, AW_CL which_statistic)
554{
555    AW_root *awr=aw->get_root();
556    char *align=awr->awar("cpro/alignment")->read_string();
557    char *marked=awr->awar("cpro/which_species")->read_string();
558    char versus=0; // all vs all
559    if (!(strcmp("marked", marked))) versus=1; // marked vs marked
560    if (!(strcmp("markedall", marked))) versus=2; // marked vs all
561    GB_ERROR faultmessage;
562    free(marked);
563
564    if (CPRO.result[which_statistic].statisticexists)
565    {
566        CPRO_freestatistic((char)which_statistic);
567        CPRO.result[which_statistic].statisticexists=0;
568    }
569
570    strcpy(CPRO.result[which_statistic].alignname, align);
571    CPRO.result[which_statistic].resolution=awr->awar("cpro/resolution")->read_int();
572    if (CPRO.result[which_statistic].resolution<=0)
573        CPRO.result[which_statistic].resolution=1;
574    CPRO.result[which_statistic].leastcompares=
575        awr->awar("cpro/leastcompares")->read_int();
576    if (CPRO.result[which_statistic].leastcompares<=0) CPRO.result[which_statistic].leastcompares=1;
577
578    if (versus==1) strcpy(CPRO.result[which_statistic].which_species, "m vs m");
579    else if (versus==2) strcpy(CPRO.result[which_statistic].which_species, "m vs all");
580    else strcpy(CPRO.result[which_statistic].which_species, "all vs all");
581
582    if ((faultmessage=GB_push_transaction(GLOBAL_gb_main))) {
583        aw_message(faultmessage);
584        free(align);
585        return;
586    }
587
588    CPRO.result[which_statistic].maxalignlen = GBT_get_alignment_len(GLOBAL_gb_main, align);
589    if (CPRO.result[which_statistic].maxalignlen<=0) {
590        GB_clear_error();
591        GB_pop_transaction(GLOBAL_gb_main);
592        aw_message("Error: Select an alignment !");
593        delete   align;
594        return;
595    }
596
597    char isamino = GBT_is_alignment_protein(GLOBAL_gb_main, align);
598    arb_progress progress("Calculating conservation profile");
599
600    GBDATA **speciesdatabase; // array of GBDATA-pointers to the species
601    char **speciesdata; // array of pointers to strings that hold data of species
602
603    // allocate memory for 'CPRO.statistic','speciesdata' and fill
604    //                'speciesdatabase','agonist' and 'antagonist'
605    CPRO_readandallocate(speciesdata, speciesdatabase, versus, align);
606
607    char *countgapsstring=awr->awar("cpro/countgaps")->read_string();
608    char countgaps=1;
609    if (strcmp("on", countgapsstring)) countgaps=0;
610    free(countgapsstring);
611    CPRO.result[which_statistic].countgaps=(long)countgaps;
612
613    // create convtable and grouptable
614    CPRO_maketables(isamino, countgaps);
615    CPRO.result[which_statistic].ratio=awr->awar("cpro/transratio")->read_float();
616    CPRO.grouprate=1-(0.5/CPRO.result[which_statistic].ratio);
617    CPRO.distancecorrection=(CPRO.result[which_statistic].ratio+1)*2.0/3.0;
618
619    // fill the CPRO.statistic table
620    CPRO_makestatistic(speciesdata, speciesdatabase, (char)which_statistic);
621    // GBUSE(success);
622    CPRO_workupstatistic((char)which_statistic);
623
624    CPRO_deallocate(speciesdata, speciesdatabase);
625    free(align);
626    if ((faultmessage=GB_pop_transaction(GLOBAL_gb_main))) {
627        aw_message(faultmessage);
628        return;
629    }
630
631    CPRO_memrequirement_cb(awr);
632
633}
634
635static void CPRO_memrequirement_cb(AW_root *aw_root)
636{
637    CPRO.partition  = aw_root->awar("cpro/partition")->read_int();
638    long resolution = aw_root->awar("cpro/resolution")->read_int();
639
640    if (CPRO.partition<=0) CPRO.partition = 1;
641    if (resolution<=0) resolution         = 1;
642
643    char buf[80];
644
645    aw_root->awar("tmp/cpro/which1")->write_string(CPRO.result[0].which_species);
646    aw_root->awar("tmp/cpro/which2")->write_string(CPRO.result[1].which_species);
647
648    sprintf(buf, "%5ld", CPRO.result[0].resolution); aw_root->awar("tmp/cpro/nowres1")->write_string(buf);
649    sprintf(buf, "%5ld", CPRO.result[1].resolution); aw_root->awar("tmp/cpro/nowres2")->write_string(buf);
650
651    if (!(CPRO.result[0].statisticexists)) {
652        aw_root->awar("tmp/cpro/memfor1")->write_string("0KB");
653    }
654    else
655    {
656        sprintf(buf, "%ldKB", CPRO.result[0].memneeded/1024);
657        aw_root->awar("tmp/cpro/memfor1")->write_string(buf);
658    }
659
660    if (!(CPRO.result[1].statisticexists)) {
661        aw_root->awar("tmp/cpro/memfor2")->write_string("0KB");
662    }
663    else
664    {
665        sprintf(buf, "%ldKB", CPRO.result[1].memneeded/1024);
666        aw_root->awar("tmp/cpro/memfor2")->write_string(buf);
667    }
668
669    long len;
670    {
671        GB_transaction ta(GLOBAL_gb_main);
672        char *align  = aw_root->awar("cpro/alignment")->read_string();
673   
674        len = GBT_get_alignment_len(GLOBAL_gb_main, align);
675        free(align);
676    }
677
678    if (len<=0) {
679        GB_clear_error();
680        aw_root->awar("tmp/cpro/mempartition")->write_string("???");
681        aw_root->awar("tmp/cpro/memstatistic")->write_string("???");
682    }
683    else {
684        long mem;
685
686        mem=CPRO.partition*len*2;    // *2, because of row and column in matrix
687        sprintf(buf, "%li KB", long(mem/1024));
688        aw_root->awar("tmp/cpro/mempartition")->write_string(buf);
689
690        mem+=resolution*3*sizeof(STATTYPE)*len;
691        sprintf(buf, "%li KB", long(mem/1024));
692        aw_root->awar("tmp/cpro/memstatistic")->write_string(buf);
693    }
694}
695
696void create_cprofile_var(AW_root *aw_root, AW_default aw_def)
697{
698    aw_root->awar_string("cpro/alignment", "", aw_def);
699    aw_root->awar_string("cpro/which_species", "marked", aw_def);
700    aw_root->awar_string("cpro/which_result", "transversion", aw_def);
701    aw_root->awar_string("cpro/countgaps", "", aw_def);
702    aw_root->awar_string("cpro/condensename", "PVD", aw_def);
703    aw_root->awar_float("cpro/transratio", 0.5, aw_def);
704    aw_root->awar_int(AWAR_CURSOR_POSITION, info2bio(0), GLOBAL_gb_main);
705    aw_root->awar_int("cpro/maxdistance", 100, aw_def);
706    aw_root->awar_int("cpro/resolution", 100, aw_def);
707    aw_root->awar_int("cpro/partition", 100, aw_def);
708    aw_root->awar_int("cpro/drawmode0", 0, aw_def);
709    aw_root->awar_int("cpro/drawmode1", 0, aw_def);
710    aw_root->awar_int("cpro/leastaccu", 3, aw_def);
711    aw_root->awar_int("cpro/leastmax", 50, aw_def);
712    aw_root->awar_int("cpro/firsttoreach", 50, aw_def);
713    aw_root->awar_int("cpro/firstreachedstep", 4, aw_def);
714    aw_root->awar_int("cpro/leastcompares", 300, aw_def);
715    aw_root->awar_string("tmp/cpro/mempartition", "", aw_def);
716    aw_root->awar_int("cpro/gridhorizontal", 20, aw_def);
717    aw_root->awar_int("cpro/gridvertical", 20, aw_def);
718    aw_root->awar_string("tmp/cpro/which1", "", aw_def);
719    aw_root->awar_string("tmp/cpro/which2", "", aw_def);
720    aw_root->awar_string("tmp/cpro/nowres1", "", aw_def);
721    aw_root->awar_string("tmp/cpro/nowres2", "", aw_def);
722    aw_root->awar_string("tmp/cpro/memstatistic", "", aw_def);
723    aw_root->awar_string("tmp/cpro/memfor1", "", aw_def);
724    aw_root->awar_string("tmp/cpro/memfor2", "", aw_def);
725
726    AW_create_fileselection_awars(aw_root, "cpro/save", ".", ".cpr", "", aw_def);
727    AW_create_fileselection_awars(aw_root, "cpro/load", ".", ".cpr", "", aw_def);
728    memset((char *)&CPRO, 0, sizeof(CPRO_struct));
729
730}
731
732static float CPRO_statisticaccumulation(long res, long column, unsigned char which_statistic)
733{
734    STATTYPE hits=0, sum=0, group=0, different=0;
735    long base=3*res;
736
737    if (!(CPRO.result[which_statistic].statistic[base+0])) hits=0;
738    else hits=CPRO.result[which_statistic].statistic[base+0][column];
739
740    if (!(CPRO.result[which_statistic].statistic[base+1])) group=0;
741    else group=CPRO.result[which_statistic].statistic[base+1][column];
742
743    if (!(CPRO.result[which_statistic].statistic[base+2])) different=0;
744    else different=CPRO.result[which_statistic].statistic[base+2][column];
745
746    sum=hits+group+different;
747
748    return ((float)sum);
749}
750
751
752// reports how many equal,group and differ entries are at a certain distance
753// at a certain column; mode=1 means smoothing is on.
754static void CPRO_getfromstatistic(float &equal, float &ingroup, long res, long column, unsigned char which_statistic, char mode)
755{
756    STATTYPE hits=0, sum=0, group=0, different=0;
757    long base=3*res;
758
759    if (!(CPRO.result[which_statistic].statistic[base+0])) hits=0;
760    else hits=CPRO.result[which_statistic].statistic[base+0][column];
761
762    if (!(CPRO.result[which_statistic].statistic[base+1])) group=0;
763    else group=CPRO.result[which_statistic].statistic[base+1][column];
764
765    if (!(CPRO.result[which_statistic].statistic[base+2])) different=0;
766    else different=CPRO.result[which_statistic].statistic[base+2][column];
767
768    sum=hits+group+different;
769
770    if (!(mode))
771    {
772        if (sum)
773        {
774            equal=(float)hits/(float)sum;
775            ingroup=((float)hits+(float)group)/(float)sum;
776        }
777        else
778        {
779            equal=1.0;
780            ingroup=1.0;
781        }
782        return;
783    }
784    else
785    {
786        float accu=pow(sum/(float)CPRO.result[which_statistic].maxaccu, 0.0675);
787        float distance=(float)CPRO.result[which_statistic].drawmode*.01*
788            CPRO.result[which_statistic].resolution;
789        float alpha=0.0;   // alpha=0.0 no smoothing; alpha=0.99 high smoothing
790        if (distance>0.0000001)
791        {
792            alpha=1.0-accu/distance;
793            if (alpha<0) alpha=0;
794        }
795
796        if (res==0)
797        {
798            CPRO.Z_it_group=1.0;
799            CPRO.Z_it_equal=1.0;
800        }
801        if (sum)
802        {
803            equal=(float)hits/(float)sum;
804            ingroup=((float)hits+(float)group)/(float)sum;
805            equal=(1-alpha)*equal+alpha*CPRO.Z_it_equal;
806            ingroup=(1-alpha)*ingroup+alpha*CPRO.Z_it_group;
807        }
808        else
809        {
810            equal=CPRO.Z_it_equal;
811            ingroup=CPRO.Z_it_group;
812        }
813        CPRO.Z_it_equal=equal;
814        CPRO.Z_it_group=ingroup;
815    }
816
817}
818
819static void CPRO_box(AW_device *device, int gc, float l, float t, float width, float high) {
820    device->box(gc, false, l, t, width, high, 1);
821}
822
823static float CPRO_confidinterval(long res, long column, unsigned char which_statistic, char mode)
824{
825    STATTYPE hits=0, sum=0, group=0, different=0;
826    long base=3*res;
827
828    if (!(CPRO.result[which_statistic].statistic[base+0])) hits=0;
829    else hits=CPRO.result[which_statistic].statistic[base+0][column];
830
831    if (!(CPRO.result[which_statistic].statistic[base+1])) group=0;
832    else group=CPRO.result[which_statistic].statistic[base+1][column];
833
834    if (!(CPRO.result[which_statistic].statistic[base+2])) different=0;
835    else different=CPRO.result[which_statistic].statistic[base+2][column];
836
837    sum=hits+group+different;
838    if (!(mode)) return (1/sqrt((float)sum)/2.0);
839    else return (0.0);
840}
841
842static void CPRO_drawstatistic (AW_device *device, unsigned char which_statistic)
843{
844    float topdistance=70.0, leftdistance=40.0;
845    float rightdistance=20.0, bottomdistance=10.0;
846    float betweendistance=30.0;
847    float firstavailable=.65;
848    float secondavailable=.35;
849    // points are in the areas and without the frame
850    float topfirst, leftfirst, widthfirst, highfirst;
851    float topsecond, leftsecond, widthsecond, highsecond;
852    float highboth;
853    float equal, ingroup;
854    char mode=CPRO.result[which_statistic].drawmode;
855
856    const AW_screen_area& rect = device->get_area_size();
857    device->reset();
858    device->clear(-1);
859
860    topfirst=39.0;
861    leftfirst=20.0;
862    widthfirst=(rect.r-rect.l)-leftdistance-1-rightdistance;
863    widthsecond=(rect.r-rect.l)-leftdistance-1-rightdistance;
864    highboth=(rect.b-rect.t)-topdistance-bottomdistance-betweendistance-4;
865    if ((highboth<12.0)||(widthfirst<10.0)) return;
866
867    highfirst=(float)(long)(highboth*firstavailable);
868    highsecond=(float)(long)(highboth*secondavailable)+1;
869
870    topfirst=topdistance+1;
871    leftfirst=leftdistance;
872    topsecond=rect.b-bottomdistance-highsecond;
873    leftsecond=leftdistance+1;
874
875    CPRO_box(device, GC_black, leftfirst-1, topfirst-1,
876             widthfirst+2, highfirst+2);
877    CPRO_box(device, GC_black, leftsecond-1, topsecond-1,
878             widthsecond+2, highsecond+2);
879
880    device->text(GC_black, "column", leftdistance+82, 14, 0, 1, 0);
881
882    // draw grid and inscribe axes
883    char buf[30];
884    long gridx, gridy;
885    float xpos=leftdistance, ypos;
886    sprintf(buf, " character difference");
887    device->text(GC_black, buf, leftdistance-40, topdistance-7, 0, 1, 0);
888    device->text(GC_black, "  0%", leftdistance-26, topdistance+4+highfirst, 0, 1, 0);
889
890    for (gridy=CPRO.gridhorizontal; gridy<100; gridy+=CPRO.gridhorizontal)
891    {
892        ypos=topdistance+1+(1.0-(float)gridy*0.01)*(highfirst-1);
893        device->line(GC_grid, xpos, ypos, xpos+widthfirst, ypos, AW_SCREEN);
894        sprintf(buf, "%3ld%%", gridy);
895        device->text(GC_black, buf, xpos-27, ypos+4, 0, 1, 0);
896    }
897    device->text(GC_black, "100%", leftdistance-26, topdistance+5, 0, 1, 0);
898
899    device->text(GC_black, "sequence distance", leftdistance+widthfirst-95, topdistance+highfirst+25, 0, 1, 0);
900    device->text(GC_black, "  0%", leftdistance-11, topdistance+14+highfirst, 0, 1, 0);
901    ypos=topdistance+1;
902
903    for (gridx=CPRO.gridvertical; (float)gridx<=100.0*CPRO.maxdistance;
904        gridx+=CPRO.gridvertical)
905    {
906        xpos=leftdistance+1+(float)gridx*0.01/CPRO.maxdistance*widthfirst;
907        if ((float)gridx*0.01<1.0*CPRO.maxdistance) {
908            device->line(GC_grid, xpos, ypos, xpos, ypos+highfirst, AW_SCREEN);
909        }
910        sprintf(buf, "%3ld%%", gridx);
911        device->text(GC_black, buf, xpos-12, ypos+13+highfirst, 0, 1, 0);
912    }
913
914    if (!CPRO.result[which_statistic].statisticexists) return;
915    if ((CPRO.column<1)||(CPRO.column>CPRO.result[which_statistic].maxalignlen))
916        return;
917
918    // fill first box
919    float accu, confidinterval;
920    float step=widthfirst/CPRO.result[which_statistic].resolution;
921    float linelength=step/CPRO.maxdistance;
922    float ytop, ybottom;
923
924    long firstx;
925    for (firstx=0;
926         firstx<CPRO.result[which_statistic].resolution*CPRO.maxdistance;
927         firstx++)
928    {
929        CPRO_getfromstatistic(equal, ingroup, (long)firstx, bio2info(CPRO.column), which_statistic, mode);
930        accu = CPRO_statisticaccumulation((long)firstx, bio2info(CPRO.column), which_statistic);
931        if (accu>=(float)CPRO.leastaccu) {
932            xpos=(float)firstx*step/CPRO.maxdistance+leftfirst;
933            ypos=topfirst+equal*highfirst;
934
935            // do not draw outside canvas-box
936            if (xpos+linelength > leftfirst+widthfirst+1) continue;
937
938            confidinterval = highfirst * CPRO_confidinterval(firstx, bio2info(CPRO.column), which_statistic, mode);
939
940            ytop      = ypos-confidinterval;
941            if (ytop>=topfirst) device->line(GC_blue, xpos, ytop, xpos+linelength, ytop, AW_SCREEN);
942            else ytop = topfirst;
943            device->line(GC_blue, xpos+linelength/2, ytop, xpos+linelength/2, ypos, AW_SCREEN);
944
945            ybottom      = ypos+confidinterval;
946            if (ybottom<topfirst+highfirst) device->line(GC_blue, xpos, ybottom, xpos+linelength, ybottom, AW_SCREEN);
947            else ybottom = topfirst+highfirst-1;
948            device->line(GC_blue, xpos+linelength/2, ybottom, xpos+linelength/2, ypos, AW_SCREEN);
949
950            ypos      = topfirst+ingroup*highfirst;
951            ytop      = ypos-confidinterval;
952            if (ytop>=topfirst) device->line(GC_green, xpos, ytop, xpos+linelength, ytop, AW_SCREEN);
953            else ytop = topfirst;
954            device->line(GC_green, xpos+linelength/2, ytop, xpos+linelength/2, ypos, AW_SCREEN);
955
956            ybottom      = ypos+confidinterval;
957            if (ybottom<topfirst+highfirst) device->line(GC_green, xpos, ybottom, xpos+linelength, ybottom, AW_SCREEN);
958            else ybottom = topfirst+highfirst-1;
959            device->line(GC_green, xpos+linelength/2, ybottom, xpos+linelength/2, ypos, AW_SCREEN);
960        }
961    }
962
963    float resaccu;
964    float rate;
965    sprintf(buf, " %5ld", CPRO.result[which_statistic].maxaccu);
966    device->text(GC_black, "   max", leftsecond-50, topsecond, 0, 1, 0);
967    device->text(GC_black, buf, leftsecond-43, topsecond+10*1, 0, 1, 0);
968    device->text(GC_black, "  pairs", leftsecond-50, topsecond+10*3, 0, 1, 0);
969
970    // fill second box
971    for (firstx=0; firstx<(long)widthsecond; firstx++) {
972        long res = firstx*CPRO.result[which_statistic].resolution /widthsecond*CPRO.maxdistance;
973        resaccu  = CPRO_statisticaccumulation(res, bio2info(CPRO.column), which_statistic);
974        rate     = 1.0-(sqrt(resaccu)/sqrt(CPRO.result[which_statistic].maxaccu));
975        device->line(GC_black, firstx+leftsecond, topsecond+rate*highsecond, firstx+leftsecond, topsecond+highsecond, AW_SCREEN);
976    }
977}
978
979static void CPRO_resize_cb(AW_window *aws, AW_CL which_statistic, AW_CL)
980{
981    AW_root *awr=aws->get_root();
982    CPRO.column=awr->awar(AWAR_CURSOR_POSITION)->read_int();
983    CPRO.gridvertical=(long)awr->awar("cpro/gridvertical")->read_int();
984    CPRO.gridhorizontal=(long)awr->awar("cpro/gridhorizontal")->read_int();
985    CPRO.leastaccu=awr->awar("cpro/leastaccu")->read_int();
986    if (CPRO.leastaccu<=0) CPRO.leastaccu=1;
987
988    AW_device *device=aws->get_device(AW_INFO_AREA);
989    device->reset();
990    CPRO_drawstatistic(device, (char)which_statistic);
991}
992
993static void CPRO_expose_cb(AW_window *aws, AW_CL which_statistic, AW_CL)
994{
995    AW_root *awr=aws->get_root();
996    CPRO.column=awr->awar(AWAR_CURSOR_POSITION)->read_int();
997    char buf[80];
998    sprintf(buf, "cpro/drawmode%d", (int)which_statistic);
999    CPRO.result[which_statistic].drawmode=(char)awr->awar(buf)->read_int();
1000    CPRO.gridvertical=(long)awr->awar("cpro/gridvertical")->read_int();
1001    CPRO.gridhorizontal=(long)awr->awar("cpro/gridhorizontal")->read_int();
1002    CPRO.leastaccu=awr->awar("cpro/leastaccu")->read_int();
1003    if (CPRO.leastaccu<=0) CPRO.leastaccu=1;
1004
1005    long maxd=awr->awar("cpro/maxdistance")->read_int();
1006    if ((maxd>0)&&(maxd<101))CPRO.maxdistance=(float)maxd/100.0;
1007
1008    AW_device *device=aws->get_device (AW_INFO_AREA);
1009    CPRO_drawstatistic(device, (char)which_statistic);
1010}
1011
1012static void CPRO_column_cb(AW_root *awr, AW_window *aws, AW_CL which_statistic)
1013{
1014    char buf[80];
1015    sprintf(buf, "cpro/drawmode%d", (int)which_statistic);
1016    CPRO.result[which_statistic].drawmode=(char)awr->awar(buf)->read_int();
1017    CPRO_expose_cb(aws, which_statistic, 0);
1018}
1019
1020static void CPRO_columnminus_cb(AW_window *aws) {
1021    if (CPRO.column>1) {
1022        aws->get_root()->awar(AWAR_CURSOR_POSITION)->write_int(CPRO.column-1);
1023    }
1024}
1025
1026static void CPRO_columnplus_cb(AW_window *aws, AW_CL /* which_statistic */, AW_CL) {
1027    aws->get_root()->awar(AWAR_CURSOR_POSITION)->write_int(CPRO.column+1);
1028}
1029
1030static void CPRO_savestatistic_cb(AW_window *aw, AW_CL which_statistic)
1031{
1032    AW_root  *awr      = aw->get_root();
1033    char     *filename = awr->awar("cpro/save/file_name")->read_string();
1034    GB_ERROR  error    = 0;
1035
1036    if (!filename) {
1037        error = "no filename";
1038    }
1039    else {
1040        const CPRO_result_struct& curr_stat = CPRO.result[which_statistic];
1041        if (!(curr_stat.statisticexists)) {
1042            error = "calculate first!";
1043        }
1044        else {
1045            GBDATA *newbase     = GB_open(filename, "wc");
1046            if (!newbase) error = GB_await_error();
1047            else {
1048                error = GB_begin_transaction(newbase);
1049
1050                if (!error) error = GBT_write_int   (newbase, "cpro_resolution",    curr_stat.resolution);
1051                if (!error) error = GBT_write_int   (newbase, "cpro_maxalignlen",   curr_stat.maxalignlen);
1052                if (!error) error = GBT_write_int   (newbase, "cpro_maxaccu",       curr_stat.maxaccu);
1053                if (!error) error = GBT_write_int   (newbase, "cpro_memneeded",     curr_stat.memneeded);
1054                if (!error) error = GBT_write_string(newbase, "cpro_alignname",     curr_stat.alignname);
1055                if (!error) error = GBT_write_string(newbase, "cpro_which_species", curr_stat.which_species);
1056                if (!error) error = GBT_write_float (newbase, "cpro_ratio",         curr_stat.ratio);
1057                if (!error) error = GBT_write_int   (newbase, "cpro_gaps",          curr_stat.countgaps);
1058
1059                if (!error) {
1060                    long maxalignlen = curr_stat.maxalignlen;
1061
1062                    for (long column = 0; column<curr_stat.resolution && !error; column++) {
1063                        GBDATA   *gb_colrescontainer = GB_create_container(newbase, "column");
1064                        GBDATA   *gb_colentry;
1065                        GB_UINT4 *pointer;
1066
1067                        if (!error && (pointer = curr_stat.statistic[column*3+0])) {
1068                            gb_colentry = GB_create(gb_colrescontainer, "equal", GB_INTS);
1069                            error       = GB_write_ints(gb_colentry, pointer, maxalignlen);
1070                        }
1071                        if (!error && (pointer = curr_stat.statistic[column*3+1])) {
1072                            gb_colentry = GB_create(gb_colrescontainer, "group", GB_INTS);
1073                            error       = GB_write_ints(gb_colentry, pointer, maxalignlen);
1074                        }
1075                        if (!error && (pointer = curr_stat.statistic[column*3+2])) {
1076                            gb_colentry = GB_create(gb_colrescontainer, "different", GB_INTS);
1077                            error       = GB_write_ints(gb_colentry, pointer, maxalignlen);
1078                        }
1079                    }
1080                }
1081                error = GB_end_transaction(newbase, error);
1082                if (!error) error = GB_save(newbase, (char*)0, "b");
1083            }
1084
1085            GB_close(newbase);
1086        }
1087    }
1088
1089    free(filename);
1090    aw->hide_or_notify(error);
1091}
1092
1093static void CPRO_loadstatistic_cb(AW_window *aw, AW_CL which_statistic)
1094{
1095    AW_root  *awr      = aw->get_root();
1096    char     *filename = awr->awar("cpro/load/file_name")->read_string();
1097    GB_ERROR  error    = 0;
1098
1099    if (!filename) {
1100        error = "missing filename";
1101    }
1102    else {
1103        GBDATA *oldbase = GB_open(filename, "r");
1104
1105        if (!oldbase) {
1106            error = GBS_global_string("can't read DB '%s'", filename);
1107        }
1108        else {
1109            error = GB_begin_transaction(oldbase);
1110            if (!error) {
1111                if (CPRO.result[which_statistic].statisticexists) {
1112                    CPRO_freestatistic((char)which_statistic);
1113                }
1114
1115                GBDATA *gb_param     = GB_search(oldbase, "cpro_resolution", GB_FIND);
1116                if (!gb_param) error = "not a valid statistic";
1117                else {
1118                    CPRO.result[which_statistic].resolution = GB_read_int(gb_param);
1119
1120                    gb_param             = GB_search(oldbase, "cpro_maxalignlen", GB_FIND);
1121                    CPRO.result[which_statistic].maxalignlen = GB_read_int(gb_param);
1122
1123                    gb_param=GB_search(oldbase, "cpro_maxaccu", GB_FIND);
1124                    CPRO.result[which_statistic].maxaccu=GB_read_int(gb_param);
1125
1126                    gb_param=GB_search(oldbase, "cpro_memneeded", GB_FIND);
1127                    CPRO.result[which_statistic].memneeded=GB_read_int(gb_param);
1128
1129                    gb_param=GB_search(oldbase, "cpro_alignname", GB_FIND);
1130                    strcpy(CPRO.result[which_statistic].alignname, GB_read_char_pntr(gb_param));
1131
1132                    gb_param=GB_search(oldbase, "cpro_which_species", GB_FIND);
1133                    if (gb_param) strcpy(CPRO.result[which_statistic].which_species, GB_read_char_pntr(gb_param));
1134
1135                    CPRO.result[which_statistic].statistic=(STATTYPE **)calloc((size_t)CPRO.result[which_statistic].resolution*3+3, sizeof(STATTYPE *));
1136
1137                    GBDATA *gb_colrescontainer = GB_entry(oldbase, "column");
1138                    for (long column=0; column<CPRO.result[which_statistic].resolution; column++) {
1139                        const char *field[] = { "equal", "group", "different" };
1140                        for (int i = 0; i<3; i++) {
1141                            GBDATA *gb_colentry = GB_entry(gb_colrescontainer, field[i]);
1142                            if (gb_colentry) {
1143                                CPRO.result[which_statistic].statistic[column*3+i] = (STATTYPE*)GB_read_ints(gb_colentry);
1144                            }
1145                        }
1146                        gb_colrescontainer = GB_nextEntry(gb_colrescontainer);
1147                    }
1148
1149                    CPRO.result[which_statistic].statisticexists = 1;
1150                    CPRO_memrequirement_cb(awr);
1151                }
1152            }
1153            error = GB_end_transaction(oldbase, error);
1154        }
1155        GB_close(oldbase);
1156    }
1157
1158    aw->hide_or_notify(error);
1159    free(filename);
1160}
1161
1162static AW_window *CPRO_savestatisticwindow_cb(AW_root *aw_root, AW_CL cl_which_statistic) {
1163    static AW_window *aw[2] = { 0, 0 };             // one window for each value of 'which_statistic'
1164
1165    int which_statistic = int(cl_which_statistic);
1166    ap_assert(which_statistic >= 0 && which_statistic <= 1);
1167
1168    if (!aw[which_statistic]) {
1169        AW_window_simple *aws       = new AW_window_simple;
1170        char             *window_id = GBS_global_string_copy("SAVE_CPRO_STATISTIC_%i", which_statistic);
1171
1172        aws->init(aw_root, window_id, "SAVE STATISTIC");
1173        aws->load_xfig("sel_box.fig");
1174
1175        aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
1176        aws->create_button("CLOSE", "CLOSE", "C");
1177
1178        aws->at("save"); aws->callback(CPRO_savestatistic_cb, which_statistic);
1179        aws->create_button("SAVE", "SAVE", "S");
1180
1181        aws->callback((AW_CB0)AW_POPDOWN);
1182        aws->at("cancel");
1183        aws->create_button("CANCEL", "CANCEL", "C");
1184
1185        AW_create_fileselection(aws, "cpro/save");
1186
1187        free(window_id);
1188
1189        aw[which_statistic] = aws;
1190    }
1191    return aw[which_statistic];
1192}
1193
1194static AW_window *CPRO_loadstatisticwindow_cb(AW_root *aw_root, AW_CL cl_which_statistic) {
1195    static AW_window *aw[2] = { 0, 0 };             // one window for each value of 'which_statistic'
1196
1197    int which_statistic = int(cl_which_statistic);
1198    ap_assert(which_statistic >= 0 && which_statistic <= 1);
1199
1200    if (!aw[which_statistic]) {
1201        AW_window_simple *aws       = new AW_window_simple;
1202        char             *window_id = GBS_global_string_copy("LOAD_CPRO_STATISTIC_%i", which_statistic);
1203
1204        aws->init(aw_root, window_id, "LOAD STATISTIC");
1205        aws->load_xfig("sel_box.fig");
1206
1207        aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
1208        aws->create_button("CLOSE", "CLOSE", "C");
1209
1210        aws->at("save"); aws->callback(CPRO_loadstatistic_cb, which_statistic);
1211        aws->create_button("LOAD", "LOAD", "S");
1212
1213        AW_create_fileselection(aws, "cpro/load");
1214
1215        free(window_id);
1216
1217        aw[which_statistic] = aws;
1218    }
1219
1220    return aw[which_statistic];
1221}
1222
1223// search point of resolution when half maximum if reached (for condense)
1224static float CPRO_gethalfmaximum(long column, float maximum, float firsttoreach,
1225                          char transversion, unsigned char which_statistic, char mode)
1226{
1227    float equal, ingroup, interest;
1228    float interval, sum;
1229    float halfmax=0.0;
1230    long res;
1231    for (res=0; res<CPRO.result[which_statistic].resolution; res++)
1232    {
1233        sum=CPRO_statisticaccumulation(res, column, which_statistic);
1234        if ((long)sum>=CPRO.leastaccu)
1235        {
1236            CPRO_getfromstatistic(equal, ingroup, res, column,
1237                                  which_statistic, mode);
1238            if (transversion) interest=1.0-ingroup;
1239            else interest=1.0-equal;
1240            interval=CPRO_confidinterval(res, column, which_statistic, mode);
1241            if (interest-interval>=maximum*firsttoreach)
1242            {
1243                res++;
1244                break;
1245            }
1246        }
1247    }
1248    halfmax=(float)res/(float)CPRO.result[which_statistic].resolution;
1249    return (halfmax-(float)CPRO.result[which_statistic].drawmode*0.01);
1250    // delay depending on drawmode
1251}
1252
1253// search maximum distance in character (for condense)
1254static float CPRO_getmaximum(long column, char transversion,
1255                      unsigned char which_statistic, char mode)
1256{
1257    float maximum=-101.0, equal, ingroup, interest, sum, interval;
1258    for (long res=0; res<CPRO.result[which_statistic].resolution; res++)
1259    {
1260        sum=CPRO_statisticaccumulation(res, column, which_statistic);
1261        if ((long)sum>=CPRO.leastaccu)
1262        {
1263            CPRO_getfromstatistic(equal, ingroup, res, column,
1264                                  which_statistic, mode);
1265            if (transversion) interest=1.0-ingroup;
1266            else interest=1.0-equal;
1267            interval=CPRO_confidinterval(res, column, which_statistic, mode);
1268            if (interest-interval>maximum) maximum=interest-interval;
1269        }
1270    }
1271    return (maximum);
1272}
1273
1274static void CPRO_condense_cb(AW_window *aw, AW_CL which_statistic)
1275{
1276    AW_root *aw_root = aw->get_root();
1277    char mode=CPRO.result[which_statistic].drawmode;
1278    if (!(CPRO.result[which_statistic].statisticexists))
1279    {
1280        aw_message("statistic doesn't exist !");
1281        return;
1282    }
1283    float leastmax=(float)(aw_root->awar("cpro/leastmax")->read_int())/100.0;
1284    CPRO.leastaccu = aw_root->awar("cpro/leastaccu")->read_int();
1285    float firsttoreach=(float)(aw_root->awar("cpro/firsttoreach")->read_int())/100.0;
1286    float firstreachedstep=(float)
1287        (aw_root->awar("cpro/firstreachedstep")->read_int())/100.0;
1288    char *transversionstring=aw_root->awar("cpro/which_result")->read_string();
1289    char transversion=1;
1290    if (strcmp(transversionstring, "transversions")) transversion=0;
1291    free(transversionstring);
1292    long maxcol=CPRO.result[which_statistic].maxalignlen;
1293
1294    char *savename=aw_root->awar("cpro/condensename")->read_string();
1295    if (savename[0]==0)
1296    {
1297        free(savename);
1298        return;
1299    }
1300
1301    arb_progress progress("condense statistic", maxcol);
1302
1303    char *result=(char *)calloc((unsigned int)maxcol+1, 1);
1304
1305    float maximum;
1306    float reachedhalf;
1307    char steps;
1308    for (long column=0; column<maxcol; column++)
1309    {
1310        maximum=CPRO_getmaximum(column, transversion, (char)which_statistic, mode);
1311        if (maximum<-100.0) result[column]='.';
1312        else if (maximum<=0.0) result[column]='-';
1313        else
1314        {
1315            if (maximum>=leastmax) result[column]='A';
1316            else result[column]='a';
1317            reachedhalf=CPRO_gethalfmaximum(column, maximum, firsttoreach,
1318                                            transversion, (char)which_statistic, mode);
1319            for (steps=0; (reachedhalf>firstreachedstep)&&(steps<'Y'-'A'); steps++)
1320                reachedhalf-=firstreachedstep;
1321            result[column]+=steps;
1322        }
1323        ++progress;
1324    }
1325
1326    GB_ERROR error = 0;
1327    char *align=CPRO.result[which_statistic].alignname;
1328
1329    GB_begin_transaction(GLOBAL_gb_main);
1330
1331    GBDATA *gb_extended = GBT_find_or_create_SAI(GLOBAL_gb_main, savename);
1332
1333    GBDATA *gb_param;
1334    const char *typestring = GBS_global_string("RATES BY DISTANCE:  [%s] [UPPER_CASE%% %li]"
1335                                               " [ INTERREST%% %li] [STEP/CHAR %li]",
1336                                               (transversion) ? "transversion" : "all differences",
1337                                               (long)(leastmax*100.0),
1338                                               (long)(firsttoreach*100.0),
1339                                               (long)(firstreachedstep*100.0));
1340
1341    gb_param=GBT_add_data(gb_extended, align, "_TYPE", GB_STRING);
1342    error=GB_write_string(gb_param, typestring);
1343
1344    GBDATA *gb_data = GBT_add_data(gb_extended, align, "data", GB_STRING);
1345
1346    error = GB_write_string(gb_data, result);
1347    GB_end_transaction_show_error(GLOBAL_gb_main, error, aw_message);
1348
1349    free(result);
1350    free(savename);
1351}
1352
1353static AW_window *CPRO_condensewindow_cb(AW_root *aw_root, AW_CL which_statistic)
1354{
1355    char buf[30];
1356    sprintf(buf, "CONDENSE STATISTIC %ld", (long)which_statistic+1);
1357
1358    AW_window_simple *aws = new AW_window_simple;
1359    aws->init(aw_root, buf, buf);
1360    aws->load_xfig("cpro/condense.fig");
1361    aws->button_length(8);
1362
1363    aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
1364    aws->create_button("CLOSE", "CLOSE", "C");
1365
1366    aws->at("which_result");
1367    aws->create_toggle_field("cpro/which_result", NULL, "");
1368    aws->insert_default_toggle("      all\ndifferences",   "1", "diffs");
1369    aws->insert_toggle("     only\ntransversions", "1", "transversions");
1370    aws->update_toggle_field();
1371
1372    aws->button_length(11);
1373    aws->at("begin"); aws->callback(CPRO_condense_cb, which_statistic);
1374    aws->create_button("CONDENSE_AND_EXPORT", "CONDENSE\nAND EXPORT", "E");
1375
1376    aws->at("name"); aws->create_input_field("cpro/condensename", 11);
1377
1378    aws->at("save_box");
1379    awt_create_selection_list_on_extendeds(GLOBAL_gb_main, aws, "cpro/condensename");
1380
1381    return (AW_window *)aws;
1382}
1383
1384static AW_window *CPRO_xpert_cb(AW_root *aw_root)
1385{
1386    static AW_window *expertwindow = 0;
1387    if (expertwindow) return (expertwindow);
1388
1389    AW_window_simple *aws = new AW_window_simple;
1390    aws->init(aw_root, "CPRO_EXPERT_PROPS", "EXPERT PROPERTIES");
1391    aws->load_xfig("cpro/expert.fig");
1392    aws->button_length(8);
1393
1394    aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
1395    aws->create_button("CLOSE", "CLOSE", "C");
1396
1397    aws->at("partition");
1398    aws->create_input_field("cpro/partition", 6);
1399
1400    aws->at("leastaccu");
1401    aws->create_input_field("cpro/leastaccu", 3);
1402
1403    aws->at("leastcompares");
1404    aws->create_input_field("cpro/leastcompares", 6);
1405
1406    aws->at("gridvertical");
1407    aws->create_input_field("cpro/gridvertical", 3);
1408
1409    aws->at("gridhorizontal");
1410    aws->create_input_field("cpro/gridhorizontal", 3);
1411
1412    aws->at("leastmax");
1413    aws->create_input_field("cpro/leastmax", 3);
1414
1415    aws->at("firsttoreach");
1416    aws->create_input_field("cpro/firsttoreach", 3);
1417
1418    aws->at("firstreachedstep");
1419    aws->create_input_field("cpro/firstreachedstep", 3);
1420
1421    aws->label_length(8);
1422    aws->button_length(8);
1423    aws->at("mempartition"); aws->create_button(0, "tmp/cpro/mempartition");
1424
1425    return expertwindow=(AW_window *)aws;
1426}
1427
1428static AW_window *CPRO_showstatistic_cb(AW_root *aw_root, AW_CL which_statistic)
1429{
1430    char buf[20];
1431    sprintf(buf, "SHOW STATISTIC %d\n", (int)which_statistic+1);
1432    AW_window_simple *aws=new AW_window_simple;
1433    aws->init(aw_root, buf, buf);
1434    aws->load_xfig("cpro/show.fig");
1435    aws->button_length(6);
1436
1437    aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
1438    aws->create_button("CLOSE", "CLOSE", "C");
1439
1440    aws->at("column");
1441    aws->create_input_field(AWAR_CURSOR_POSITION, 4);
1442
1443    aws->button_length(3);
1444    aws->at("d"); aws->callback((AW_CB0)CPRO_columnminus_cb);
1445    aws->create_button(0, "-", "1");
1446    aws->at("u"); aws->callback((AW_CB2)CPRO_columnplus_cb, which_statistic, 0);
1447    aws->create_button(0, "+", "2");
1448
1449    sprintf(buf, "cpro/drawmode%d", (int)which_statistic);
1450    aws->at("drawmode"); aws->create_option_menu(buf);
1451    aws->insert_option("no smoothing", "n", 0);
1452    aws->insert_option("smoothing 1", "1", 1);
1453    aws->insert_option("smoothing 2", "2", 2);
1454    aws->insert_option("smoothing 3", "3", 3);
1455    aws->insert_option("smoothing 5", "5", 5);
1456    aws->insert_option("smoothing 10", "6", 10);
1457    aws->insert_option("smoothing 15", "7", 15);
1458    aws->update_option_menu();
1459
1460    aw_root->awar(buf)->add_callback((AW_RCB)CPRO_column_cb, (AW_CL)aws, which_statistic);
1461    aw_root->awar("cpro/gridhorizontal")->add_callback((AW_RCB)CPRO_column_cb, (AW_CL)aws, which_statistic);
1462    aw_root->awar("cpro/gridvertical")->add_callback((AW_RCB)CPRO_column_cb, (AW_CL)aws, which_statistic);
1463
1464    aws->at("maxdistance");
1465    aws->create_input_field("cpro/maxdistance", 3);
1466
1467    aws->set_resize_callback (AW_INFO_AREA, CPRO_resize_cb, which_statistic, 0);
1468    aws->set_expose_callback (AW_INFO_AREA, CPRO_expose_cb, which_statistic, 0);
1469    aw_root->awar(AWAR_CURSOR_POSITION)->add_callback((AW_RCB)CPRO_column_cb, (AW_CL)aws, which_statistic);
1470    aw_root->awar("cpro/maxdistance")->add_callback((AW_RCB)CPRO_column_cb, (AW_CL)aws, which_statistic);
1471    aw_root->awar("cpro/maxdistance")->add_callback((AW_RCB)CPRO_column_cb, (AW_CL)aws, which_statistic);
1472    aws->button_length(6);
1473
1474    AW_device *device=aws->get_device (AW_INFO_AREA);
1475    device->reset();
1476
1477    device->new_gc(GC_black);
1478    device->set_line_attributes(GC_black, 1, AW_SOLID);
1479    device->set_foreground_color(GC_black, AW_WINDOW_FG);
1480    device->set_font(GC_black, 0, 10, 0);
1481    device->new_gc(GC_blue);
1482    device->set_line_attributes(GC_blue, 1, AW_SOLID);
1483    device->set_foreground_color(GC_blue, AW_WINDOW_C1);
1484    device->new_gc(GC_green);
1485    device->set_line_attributes(GC_green, 1, AW_SOLID);
1486    device->set_foreground_color(GC_green, AW_WINDOW_C2);
1487    device->new_gc(GC_grid);
1488    device->set_line_attributes(GC_grid, 1, AW_DASHED);
1489    device->set_foreground_color(GC_grid, AW_WINDOW_C3);
1490
1491    return (AW_window *)aws;
1492}
1493
1494static AW_window *CPRO_calculatewin_cb(AW_root *aw_root, AW_CL which_statistic)
1495{
1496    char buf[30];
1497    sprintf(buf, "CALCULATE STATISTIC %ld", (long)which_statistic+1);
1498    AW_window_simple *aws = new AW_window_simple;
1499    aws->init(aw_root, buf, buf);
1500    aws->load_xfig("cpro/calc.fig");
1501    aws->button_length(10);
1502
1503    aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
1504    aws->create_button("CLOSE", "CLOSE", "C");
1505
1506    aws->at("resolution");
1507    aws->create_input_field("cpro/resolution", 8);
1508
1509    aws->at("transratio");
1510    aws->create_input_field("cpro/transratio", 8);
1511
1512    aws->at("which_alignment");
1513    awt_create_selection_list_on_alignments(GLOBAL_gb_main, (AW_window *)aws, "cpro/alignment", "*=");
1514
1515    aws->button_length(10);
1516    aws->at("xpert"); aws->callback(AW_POPUP, (AW_CL)CPRO_xpert_cb, 0);
1517    aws->create_button("EXPERT_OPTIONS", "expert...", "x");
1518
1519    aws->at("calculate");
1520    aws->callback(CPRO_calculate_cb, (AW_CL)which_statistic);
1521    aws->create_button("CALCULATE", "CALCULATE", "A");
1522
1523    aws->at("which_species");
1524    aws->create_toggle_field("cpro/which_species", NULL, "");
1525    aws->insert_toggle("all vs all", "1", "all");
1526    aws->insert_toggle("marked vs marked",   "1", "marked");
1527    aws->insert_default_toggle("marked vs all",   "1", "markedall");
1528    aws->update_toggle_field();
1529
1530    aws->at("countgaps");
1531    aws->create_toggle_field("cpro/countgaps", NULL, "");
1532    aws->insert_toggle("on", "1", "on");
1533    aws->insert_default_toggle("off",   "1", "off");
1534    aws->update_toggle_field();
1535
1536    aws->label_length(8);
1537    aws->button_length(8);
1538    aws->at("memstatistic");
1539    aws->create_button(0, "tmp/cpro/memstatistic");
1540
1541    return aws;
1542}
1543
1544/* -----------------------------------------------------------------
1545 * Function:                 AP_open_cprofile_window
1546 *
1547 * Arguments:                    .
1548 *
1549 * Returns:                      .
1550 *
1551 * Description:      Draws window, initializes callback for most important
1552 *                   function, CPRO_begin_cb
1553 *
1554 * NOTE:                         .
1555 *
1556 * Global Variables referenced:  .
1557 *
1558 * Global Variables modified:    x
1559 *
1560 * AWARs referenced:             .
1561 *
1562 * AWARs modified:               x
1563 *
1564 * Dependencies:      Needs xfig file cprofile.fig
1565 * -----------------------------------------------------------------
1566 */
1567AW_window *
1568AP_open_cprofile_window(AW_root *aw_root)
1569{
1570    AW_window_simple *aws = new AW_window_simple;
1571    aws->init(aw_root, "CPR_MAIN", "Conservation Profile: Distance Matrix");
1572    aws->load_xfig("cpro/main.fig");
1573    aws->button_length(10);
1574
1575    GB_push_transaction(GLOBAL_gb_main);
1576
1577    aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
1578    aws->create_button("CLOSE", "CLOSE", "C");
1579
1580    aws->at("help"); aws->callback(AW_POPUP_HELP, (AW_CL)"pos_variability.ps");
1581    aws->create_button("HELP", "HELP", "H");
1582
1583    aws->button_length(10);
1584    aws->at("xpert"); aws->callback(AW_POPUP, (AW_CL)CPRO_xpert_cb, 0);
1585    aws->create_button("EXPERT_OPTIONS", "expert...", "x");
1586
1587    // start action by button
1588    aws->button_length(17);
1589    aws->at("calculate1"); aws->callback(AW_POPUP, (AW_CL)CPRO_calculatewin_cb, 0);
1590    aws->create_button("GO_STAT_1", "calculate as\nstatistic 1 ...", "c");
1591    aws->at("calculate2"); aws->callback(AW_POPUP, (AW_CL)CPRO_calculatewin_cb, 1);
1592    aws->create_button("GO_STAT_2", "calculate as\nstatistic 2 ...", "a");
1593
1594    aws->button_length(17);
1595    aws->at("save1"); aws->callback(AW_POPUP, (AW_CL)CPRO_savestatisticwindow_cb, 0);
1596    aws->create_button("SAVE_STAT_1", "save\nstatistic 1 ...", "s");
1597    aws->at("save2"); aws->callback(AW_POPUP, (AW_CL)CPRO_savestatisticwindow_cb, 1);
1598    aws->create_button("SAVE_STAT_2", "save\nstatistic 2 ...", "v");
1599
1600    aws->button_length(17);
1601    aws->at("show1"); aws->callback(AW_POPUP, (AW_CL)CPRO_showstatistic_cb, 0);
1602    aws->create_button("SHOW_STAT_!", "show\ngraph 1 ...", "h");
1603    aws->at("show2"); aws->callback(AW_POPUP, (AW_CL)CPRO_showstatistic_cb, 1);
1604    aws->create_button("SHOW_STAT_2", "show\ngraph 2 ...", "w");
1605
1606    aws->button_length(17);
1607    aws->at("load1"); aws->callback(AW_POPUP, (AW_CL)CPRO_loadstatisticwindow_cb, 0);
1608    aws->create_button("LOAD_STAT_1", "load\nstatistic 1 ... ", "l");
1609    aws->at("load2"); aws->callback(AW_POPUP, (AW_CL)CPRO_loadstatisticwindow_cb, 1);
1610    aws->create_button("LOAD_STAT_2", "load\nstatistic 2 ...", "d");
1611
1612    aws->at("condense1"); aws->callback(AW_POPUP,   (AW_CL)CPRO_condensewindow_cb, 0);
1613    aws->create_button("CONDENSE_STAT_1", "condense\nstatistic 1 ...", "o");
1614    aws->at("condense2"); aws->callback(AW_POPUP,   (AW_CL)CPRO_condensewindow_cb, 1);
1615    aws->create_button("CONDENSE_STAT_2",   "condense\nstatistic 2 ...", "n");
1616
1617    aws->at("memfor1"); aws->create_button(0, "tmp/cpro/memfor1");
1618    aws->at("memfor2"); aws->create_button(0, "tmp/cpro/memfor2");
1619    aws->at("which1"); aws->create_button(0, "tmp/cpro/which1");
1620    aws->at("which2"); aws->create_button(0, "tmp/cpro/which2");
1621    aws->at("resolution1"); aws->create_button(0, "tmp/cpro/nowres1");
1622    aws->at("resolution2"); aws->create_button(0, "tmp/cpro/nowres2");
1623
1624    aw_root->awar("cpro/alignment")->add_callback(CPRO_memrequirement_cb);
1625    aw_root->awar("cpro/partition")->add_callback(CPRO_memrequirement_cb);
1626    aw_root->awar("cpro/resolution")->add_callback(CPRO_memrequirement_cb);
1627    aw_root->awar("cpro/which_species")->add_callback(CPRO_memrequirement_cb);
1628
1629    GB_pop_transaction(GLOBAL_gb_main);
1630
1631    CPRO_memrequirement_cb(aw_root);
1632
1633    return (AW_window *)aws;
1634}
Note: See TracBrowser for help on using the repository browser.