source: branches/port5/NTREE/NT_concatenate.cxx

Last change on this file was 6143, checked in by westram, 16 years ago
  • backport [6141] (parts changing code, but only strings and comments)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 41.5 KB
Line 
1/*=======================================================================================*/
2/*                                                                                       */
3/*    File       : NT_concatenate.cxx                                                    */
4/*    Purpose    : 1.Concatenatenation of sequences or alignments                        */
5/*                 2.Merging the fields of similar species and creating a new species    */
6/*    Author     : Yadhu Kumar (yadhu@mikro.biologie.tu-muenchen.de)                     */
7/*    web site   : http://www.arb-home.de/                                               */
8/*                                                                                       */
9/*        Copyright Department of Microbiology (Technical University Munich)             */
10/*                                                                                       */
11/*=======================================================================================*/
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
16#include <time.h>
17#include <string.h>
18#include <memory.h>
19#include <iostream>
20
21#include <arbdb.h>
22#include <arbdbt.h>
23#include <aw_root.hxx>
24#include <aw_device.hxx>
25#include <aw_window.hxx>
26#include <aw_awars.hxx>
27#include <awt.hxx>
28#include <AW_rename.hxx>
29#include <awt_tree.hxx>
30#include <awt_canvas.hxx>
31#include <awt_item_sel_list.hxx>
32#include <awt_sel_boxes.hxx>
33#include "awtlocal.hxx"
34#include <aw_question.hxx>
35#include "nt_internal.h"
36#include <nt_sort.hxx>   // for sorting database entries
37
38#ifndef ARB_ASSERT_H
39#include <arb_assert.h>
40#endif
41#define nt_assert(bed) arb_assert(bed)
42
43using namespace std;
44
45#define AWAR_CON_SEQUENCE_TYPE       "tmp/concat/sequence_type"
46#define AWAR_CON_NEW_ALIGNMENT_NAME  "tmp/concat/new_alignment_name"
47#define AWAR_CON_ALIGNMENT_SEPARATOR "tmp/concat/alignment_separator"
48#define AWAR_CON_DB_ALIGNS           "tmp/concat/database_alignments"
49#define AWAR_CON_CONCAT_ALIGNS       "tmp/concat/concatenating_alignments"
50#define AWAR_CON_DUMMY               "tmp/concat/dummy"
51#define AWAR_CON_MERGE_FIELD         "tmp/concat/merge_field"
52#define AWAR_CON_STORE_SIM_SP_NO     "tmp/concat/store_sim_sp_no"
53
54#define MERGE_SIMILAR_CONCATENATE_ALIGNMENTS 1
55#define MOVE_DOWN  0
56#define MOVE_UP    1
57
58struct conAlignStruct{
59    GBDATA            *gb_main;
60    AW_window         *aws;
61    AW_root           *awr;
62    AW_selection_list *db_id;
63    AW_selection_list *con_id;
64    char              *seqType;
65};
66
67struct SPECIES_ConcatenateList {
68    GBDATA *species;
69    char   *species_name;
70    struct SPECIES_ConcatenateList *next;
71};
72typedef struct SPECIES_ConcatenateList *speciesConcatenateList;
73
74extern GBDATA               *GLOBAL_gb_main;
75static AW_selection_list    *con_alignment_list;
76static AW_selection_list    *db_alignment_list;
77
78/*--------------------------creating and initializing AWARS----------------------------------------*/
79void NT_createConcatenationAwars(AW_root *aw_root, AW_default aw_def) {
80    aw_root->awar_string( AWAR_CON_SEQUENCE_TYPE,      "ami" ,                        aw_def);
81    aw_root->awar_string( AWAR_CON_NEW_ALIGNMENT_NAME, "ali_concat" ,                 aw_def);
82    aw_root->awar_string( AWAR_CON_ALIGNMENT_SEPARATOR,"XXX",                         aw_def);
83    aw_root->awar_string( AWAR_CON_MERGE_FIELD,        "full_name" ,                  aw_def);
84    aw_root->awar_string( AWAR_CON_STORE_SIM_SP_NO,    "merged_species" ,             aw_def);
85    aw_root->awar_string( AWAR_CON_DB_ALIGNS,          "" ,                           aw_def);
86    aw_root->awar_string( AWAR_CON_CONCAT_ALIGNS,      "" ,                           aw_def);
87    aw_root->awar_string( AWAR_CON_DUMMY,              "" ,                           aw_def);
88}
89
90/*------------------------Selecting alignments from the database for concatenation----------------------*/
91void createSelectionList_callBack(struct conAlignStruct *cas){
92    GBDATA *gb_alignment;
93    GBDATA *gb_alignment_name;
94    GBDATA *gb_alignment_type;
95    char   *alignment_name;
96    char   *alignment_type;
97
98    GB_push_transaction(GLOBAL_gb_main);  //opening a transaction if not opened yet
99
100    AW_root *aw_root = cas->aws->get_root();
101    char *ali_type   = aw_root->awar(AWAR_CON_SEQUENCE_TYPE)->read_string();
102    ali_type         = GBS_global_string_copy("%s=", ali_type);
103
104    cas->aws->clear_selection_list(cas->db_id); //clearing the selection list
105
106    for (gb_alignment = GB_search(GLOBAL_gb_main,"presets/alignment",GB_FIND);
107         gb_alignment;
108         gb_alignment = GB_nextEntry(gb_alignment))
109        {
110            gb_alignment_type = GB_entry(gb_alignment,"alignment_type");
111            gb_alignment_name = GB_entry(gb_alignment,"alignment_name");
112            alignment_type    = GB_read_string(gb_alignment_type);
113            alignment_name    = GB_read_string(gb_alignment_name);
114
115            char *str = GBS_string_eval(alignment_type, ali_type, 0);   //selecting the alignments of the selected sequence type
116            if (!*str){
117                cas->aws->insert_selection( cas->db_id, alignment_name, alignment_name );   //inserting to the selection list
118            }
119            free(str);
120            free(alignment_type);
121            free(alignment_name);
122        }
123    cas->aws->insert_default_selection( cas->db_id, "????", "????" );
124    cas->aws->update_selection_list( cas->db_id );
125
126    GB_pop_transaction(GLOBAL_gb_main); //closing a transaction
127    free(ali_type);
128}
129
130static void createSelectionList_callBack_gb(GBDATA*,int *cl_cas, GB_CB_TYPE cbtype) {
131    if (cbtype == GB_CB_CHANGED) {
132        struct conAlignStruct *cas = (struct conAlignStruct*)cl_cas;
133        createSelectionList_callBack(cas);
134    }
135}
136
137static void createSelectionList_callBack_awar(AW_root *IF_DEBUG(aw_root), AW_CL cl_cas) {
138    struct conAlignStruct *cas = (struct conAlignStruct*)cl_cas;
139    gb_assert(aw_root==cas->aws->get_root());
140    createSelectionList_callBack(cas);
141    //clear the selected alignments and set default to ????
142    cas->aws->clear_selection_list(con_alignment_list);
143    cas->aws->insert_default_selection(con_alignment_list,"????", "????" );
144    cas->aws->update_selection_list(con_alignment_list);
145}
146
147
148conAlignStruct* createSelectionList(GBDATA *gb_main,AW_window *aws, const char *awarName){
149
150#ifdef DEBUG
151    static bool ran=false;
152    gb_assert(!ran);
153    ran=true;                 //prevents calling this function for the second time
154#endif
155
156    GBDATA *gb_presets;
157    AW_root *aw_root  = aws->get_root();
158    char    *ali_type = aw_root->awar(AWAR_CON_SEQUENCE_TYPE)->read_string();  //reading sequence type from the concatenation window
159    ali_type          = GBS_global_string_copy("%s=", ali_type);               // copying the awar with '=' appended to it
160
161    db_alignment_list = aws->create_selection_list(awarName,0,"",10,20);
162
163    conAlignStruct *cas = 0;
164    cas          = new conAlignStruct; // don't free (used in callback)
165    cas->aws     = aws;
166    cas->gb_main = gb_main;
167    cas->db_id   = db_alignment_list;
168    cas->seqType  = 0; if (ali_type) cas->seqType = strdup(ali_type);  //assigning the sequence type to struct cas
169
170    createSelectionList_callBack(cas); // calling callback to get the alignments in the database
171
172    GB_push_transaction(gb_main);
173    gb_presets = GB_search(gb_main,"presets",GB_CREATE_CONTAINER);
174    GB_add_callback(gb_presets, GB_CB_CHANGED, createSelectionList_callBack_gb, (int *)cas);
175    GB_pop_transaction(gb_main);
176
177    free(ali_type);
178    return cas;
179
180}
181
182void selectAlignment(AW_window *aws){
183    AW_root *aw_root            = aws->get_root();
184    char    *selected_alignment = aw_root->awar(AWAR_CON_DB_ALIGNS)->read_string();
185
186    if (selected_alignment && selected_alignment[0] != 0 && selected_alignment[0] != '?') {
187        int  left_index  = aws->get_index_of_element(db_alignment_list, selected_alignment);
188        bool entry_found = false;
189
190        // browse thru the entries and insert the selection if not in the selected list
191        for (const char *listEntry = con_alignment_list->first_element();
192             !entry_found && listEntry;
193             listEntry = con_alignment_list->next_element())
194        {
195            if (strcmp(listEntry, selected_alignment) == 0) {
196                entry_found = true; // entry does already exist in right list
197            }
198        }
199
200        if (!entry_found) { // if not yet in right list
201            aws->insert_selection(con_alignment_list, selected_alignment, selected_alignment);
202            aws->update_selection_list(con_alignment_list);
203        }
204
205        aws->select_index(db_alignment_list, AWAR_CON_DB_ALIGNS, left_index+1); // go down 1 position on left side
206        aw_root->awar(AWAR_CON_CONCAT_ALIGNS)->write_string(selected_alignment); // position right side to newly added or already existing alignment
207    }
208    free(selected_alignment);
209}
210
211
212void selectAllAlignments(AW_window *aws){
213    const char *listEntry = db_alignment_list->first_element();
214    aws->clear_selection_list(con_alignment_list);
215
216    while (listEntry) {
217        aws->insert_selection(con_alignment_list, listEntry, listEntry);
218        listEntry = db_alignment_list->next_element();
219    }
220    aws->insert_default_selection(con_alignment_list,"????", "????" );
221    aws->update_selection_list(con_alignment_list);
222}
223
224void clearAlignmentList(AW_window *aws){
225    aws->clear_selection_list(con_alignment_list);
226    aws->insert_default_selection(con_alignment_list,"????", "????" );
227    aws->update_selection_list(con_alignment_list);
228}
229
230void removeAlignment(AW_window *aws){
231    AW_root *aw_root = aws->get_root();
232    char *selected_alignment = aw_root->awar(AWAR_CON_CONCAT_ALIGNS)->read_string();
233
234    if (selected_alignment && selected_alignment[0] != 0) {
235        int index = aws->get_index_of_element(con_alignment_list, selected_alignment); // save old position
236        aws->delete_selection_from_list(con_alignment_list, selected_alignment);
237        aws->insert_default_selection(con_alignment_list,"????", "????" );
238        aws->update_selection_list(con_alignment_list);
239
240        aws->select_index(con_alignment_list, AWAR_CON_CONCAT_ALIGNS, index); // restore old position
241        aw_root->awar(AWAR_CON_DB_ALIGNS)->write_string(selected_alignment); // set left selection to deleted alignment
242    }
243    free(selected_alignment);
244}
245
246void shiftAlignment(AW_window *aws, long int direction){
247    AW_root *aw_root = aws->get_root();
248    AW_selection_list *temp_list = aws->create_selection_list(AWAR_CON_DUMMY,0,"",0,0);
249    char *selected_alignment = aw_root->awar(AWAR_CON_CONCAT_ALIGNS)->read_string();
250
251    if (!selected_alignment || !selected_alignment[0] || selected_alignment[0] == '?') {
252        free(selected_alignment);
253        return;
254    }
255
256    int curr_index             = 0;
257    int sel_element_index      = aws->get_index_of_element(con_alignment_list, selected_alignment);
258    const char *listEntry      = con_alignment_list->first_element();
259    const char *temp_listEntry = 0;
260
261    aws->clear_selection_list(temp_list);
262
263    while(listEntry){
264        switch(direction) {
265        case MOVE_UP:       //shifting alignments upwards
266            if (sel_element_index == curr_index+1){
267                aws->insert_selection(temp_list, selected_alignment, selected_alignment);
268                temp_listEntry = aws->get_element_of_index(con_alignment_list, curr_index++);
269                if (temp_listEntry) aws->insert_selection(temp_list, temp_listEntry, temp_listEntry);
270            }
271            else {
272                temp_listEntry = aws->get_element_of_index(con_alignment_list, curr_index);
273                if (temp_listEntry) aws->insert_selection(temp_list, temp_listEntry, temp_listEntry);
274            }
275            curr_index++;
276            break;
277
278        case MOVE_DOWN:    //shifting alignments downwards
279            if (sel_element_index == curr_index){
280                temp_listEntry = aws->get_element_of_index(con_alignment_list, ++curr_index);
281                if (temp_listEntry) aws->insert_selection(temp_list, temp_listEntry, temp_listEntry);
282                aws->insert_selection(temp_list, selected_alignment, selected_alignment);
283            }
284            else {
285                temp_listEntry = aws->get_element_of_index(con_alignment_list, curr_index);
286                if (temp_listEntry) aws->insert_selection(temp_list, temp_listEntry, temp_listEntry);
287            }
288            curr_index++;
289            break;
290        }
291        listEntry = con_alignment_list->next_element();
292    }
293
294    aws->clear_selection_list(con_alignment_list);
295    listEntry = temp_list->first_element();
296
297    while (listEntry) {
298        aws->insert_selection(con_alignment_list, listEntry, listEntry);
299        listEntry = temp_list->next_element();
300    }
301    aws->insert_default_selection(con_alignment_list,"????", "????" );
302    aws->update_selection_list(con_alignment_list);
303    free(selected_alignment);
304}
305
306/*----------  Create SAI to display alignments that were concatenated --------------*/
307
308GB_ERROR displayAlignmentInfo(GBDATA *gb_main, GB_ERROR error, char *new_ali_name, char *alignment_separator){
309    GBDATA        *gb_extended    = GBT_find_or_create_SAI(gb_main,"Alignment Information");
310    GBDATA        *gb_data        = GBT_add_data(gb_extended, new_ali_name,"data", GB_STRING);
311    GBS_strstruct *ali_str        = GBS_stropen(GBT_get_alignment_len(gb_main,new_ali_name));
312    const char    *const_ali_name = con_alignment_list->first_element();
313
314    while (const_ali_name){
315        int alignment_len = GBT_get_alignment_len(gb_main,const_ali_name);
316        int ali_str_len   = strlen(const_ali_name);
317        for (int pos = 0; pos<alignment_len; pos++) {
318            if (pos<5)  GBS_strcat(ali_str,"<");
319            else if (pos >= (alignment_len-5))  GBS_strcat(ali_str,">");
320            else if (pos == (alignment_len/2 - ali_str_len/2)) { GBS_strcat(ali_str,const_ali_name); pos+=ali_str_len-1;}
321            else  GBS_strcat(ali_str,"=");
322        }
323        const_ali_name = con_alignment_list->next_element();
324        if (const_ali_name) GBS_strcat(ali_str,alignment_separator);
325    }
326
327    char *ali_info_SAI = GBS_strclose(ali_str);
328    if(!error) error   = GB_write_string(gb_data,ali_info_SAI);
329    free(ali_info_SAI);
330    return error;
331}
332
333/*---------------------------------------- Concatenation function ----------------------------------*/
334void concatenateAlignments(AW_window *aws) {
335
336    GB_push_transaction(GLOBAL_gb_main);
337    AW_root  *aw_root = aws->get_root();
338
339    int no_of_sel_alignments = aws->get_no_of_entries(con_alignment_list); //getting number of selected alignments
340    int found[no_of_sel_alignments], missing[no_of_sel_alignments];
341    for (int j = 0; j<no_of_sel_alignments; j++) { found[j] = 0; missing[j] = 0; }  //initializing found and missing alis
342
343    const char *const_ali_name = con_alignment_list->first_element();
344    long new_alignment_len     = 0;
345
346    while(const_ali_name){   //computing the length for the new concatenated alignment
347        new_alignment_len += GBT_get_alignment_len(GLOBAL_gb_main, const_ali_name);
348        const_ali_name     = con_alignment_list->next_element();
349    }
350
351    char *new_ali_name = aw_root->awar(AWAR_CON_NEW_ALIGNMENT_NAME)->read_string();
352    GB_ERROR error     = GBT_check_alignment_name(new_ali_name);
353
354    if (!error) { /// handle error
355        GBDATA *gb_presets          = GB_search(GLOBAL_gb_main, "presets", GB_CREATE_CONTAINER);
356        GBDATA *gb_alignment_exists = GB_find_string(gb_presets, "alignment_name", new_ali_name, GB_IGNORE_CASE, down_2_level);
357        GBDATA *gb_new_alignment    = 0;
358        char   *seq_type            = aw_root->awar(AWAR_CON_SEQUENCE_TYPE)->read_string();
359
360        if (gb_alignment_exists) {    // check wheather new alignment exists or not, if yes prompt user to overwrite the existing alignment; if no create an empty alignment
361            bool overwrite = aw_ask_sure(GBS_global_string("Existing data in alignment \"%s\" may be overwritten. Do you want to continue?", new_ali_name));
362            if (!overwrite) {
363                error = "Alignment exists! Quitting function...";
364            }
365            else {
366                gb_new_alignment             = GBT_get_alignment(GLOBAL_gb_main,new_ali_name);
367                if (!gb_new_alignment) error = GB_await_error();
368            }
369        }
370        else {
371            gb_new_alignment             = GBT_create_alignment(GLOBAL_gb_main,new_ali_name,new_alignment_len,0,0,seq_type);
372            if (!gb_new_alignment) error = GB_await_error();
373        }
374
375        if (!error && !con_alignment_list->first_element())     error = "No alignments were selected to concatenate!";
376        else if (!error && !con_alignment_list->next_element()) error ="Select more than 1 alignment to concatenate!";
377
378        if (!error) {
379            char *alignment_separator = aw_root->awar(AWAR_CON_ALIGNMENT_SEPARATOR)->read_string();
380            AW_repeated_question ask_about_missing_alignment;
381
382            for (GBDATA *gb_species = GBT_first_marked_species(GLOBAL_gb_main); gb_species; gb_species = GBT_next_marked_species(gb_species)){
383                GBS_strstruct *str_seq = GBS_stropen(new_alignment_len+1000); /* create output stream */
384                int            ali_len = 0;
385                int            ali_ctr = 0;
386
387                const_ali_name = con_alignment_list->first_element();
388
389                while(const_ali_name){             // concatenation of the selected alignments in the database
390                    GBDATA *gb_seq_data = GBT_read_sequence(gb_species, const_ali_name);
391                    if (gb_seq_data) {
392                        const char *str_data = GB_read_char_pntr(gb_seq_data);
393                        GBS_strcat(str_seq,str_data);
394                        ++found[ali_ctr];
395                    }
396                    else {
397                        char *speciesName = GB_read_string(GB_entry(gb_species, "full_name"));
398                        char *question    = GBS_global_string_copy("\"%s\" alignment doesn't exist in \"%s\"!", const_ali_name, speciesName);
399                        int skip_ali      = ask_about_missing_alignment.get_answer(question, "Insert Gaps for Missing Alignment,Skip Missing Alignment", "all", true);
400                        if (!skip_ali) {
401                            ali_len = GBT_get_alignment_len(GLOBAL_gb_main, const_ali_name);
402                            for ( int j = 0; j<ali_len; j++) {  GBS_strcat(str_seq,"."); }
403                        }
404                        ++missing[ali_ctr];
405                        free(question);
406                        free(speciesName);
407                    }
408                    const_ali_name = con_alignment_list->next_element(); ali_ctr++;
409                    if (const_ali_name) GBS_strcat(str_seq,alignment_separator);
410                }
411
412                {
413                    char *concatenated_ali_seq_data;
414                    concatenated_ali_seq_data = GBS_strclose(str_seq);
415                    GBDATA *gb_data = GBT_add_data(gb_species, new_ali_name, "data", GB_STRING);
416                    GB_write_string(gb_data, concatenated_ali_seq_data);
417                    free(concatenated_ali_seq_data);
418                }
419            }
420
421            {    /*............. print missing alignments...........*/
422                aw_message(GBS_global_string("Concatenation of Alignments was performed for %ld species.",GBT_count_marked_species(GLOBAL_gb_main)));
423                const_ali_name = con_alignment_list->first_element(); int i = 0;
424                while (const_ali_name) {
425                    aw_message(GBS_global_string("%s : Found in %d species & Missing in %d species.",const_ali_name,found[i],missing[i]));
426                    const_ali_name = con_alignment_list->next_element();
427                    i++;
428                }
429            }
430
431            error = displayAlignmentInfo(GLOBAL_gb_main,error,new_ali_name,alignment_separator);
432            free(alignment_separator);
433        }
434        free(seq_type);
435    }
436
437    if (!error) {
438        char *nfield = GBS_global_string_copy("%s/data",new_ali_name);
439        error        = GBT_add_new_changekey(GLOBAL_gb_main, nfield, GB_STRING);
440        free(nfield);
441    }
442    GB_end_transaction_show_error(GLOBAL_gb_main, error, aw_message);
443    free(new_ali_name);
444}
445
446static void addSpeciesToConcatenateList(speciesConcatenateList *sclp, GB_CSTR species_name) {
447
448    GBDATA *gb_species_data = GB_search(GLOBAL_gb_main, "species_data",  GB_CREATE_CONTAINER);
449    GBDATA *gb_species      = GBT_find_species_rel_species_data(gb_species_data, species_name);
450
451    if (gb_species) {
452        speciesConcatenateList scl = new SPECIES_ConcatenateList;
453        scl->species               = gb_species;
454        scl->species_name          = strdup(species_name);
455        scl->next                  = *sclp;
456        *sclp                      = scl;
457    }
458}
459
460static void freeSpeciesConcatenateList(speciesConcatenateList scl){
461    while (scl) {
462        speciesConcatenateList next = scl->next;
463        free(scl->species_name);
464        delete scl;
465        scl = next;
466    }
467}
468
469GB_ERROR checkAndMergeFields( GBDATA *gb_new_species, GB_ERROR error, speciesConcatenateList scl) {
470
471    char *doneFields = strdup(";name;"); // all fields which are already merged
472    int   doneLen    = strlen(doneFields);
473    speciesConcatenateList sl = scl;
474    int  sl_length = 0; while (scl) { sl_length++; scl=scl->next; } //counting no. of similar species stored in the list
475    int *fieldStat = new int[sl_length]; // 0 = not used yet ; -1 = doesn't have field ; 1..n = field content (same number means same content)
476
477    while (sl && !error) { // with all species do..
478        char *newFields  = GB_get_subfields(sl->species);
479        char *fieldStart = newFields; // points to ; before next field
480
481        while (fieldStart[1] && !error) { // with all subfields of the species do..
482            char *fieldEnd = strchr(fieldStart+1, ';');
483            gb_assert(fieldEnd);
484            char behind = fieldEnd[1]; fieldEnd[1] = 0;
485
486            if (strstr(doneFields, fieldStart)==0) { // field is not merged yet
487                char *fieldName = fieldStart+1;
488                int   fieldLen  = int(fieldEnd-fieldName);
489
490                gb_assert(fieldEnd[0]==';');
491                fieldEnd[0] = 0;
492
493                GBDATA *gb_field = GB_search(sl->species, fieldName, GB_FIND);
494                gb_assert(gb_field); // field has to exist, cause it was found before
495                int type = gb_field->flags.type; //GB_TYPE(gb_field);
496
497                if (type==GB_STRING) { // we only merge string fields
498                    int i; int doneSpecies = 0; int nextStat = 1;
499
500                    for (i=0; i<sl_length; i++) { fieldStat[i] = 0;} // clear field status
501
502                    while (doneSpecies<sl_length) { // since all species in list were handled
503                        speciesConcatenateList sl2 = sl; i = 0;
504
505                        while (sl2) {
506                            if (fieldStat[i]==0) {
507                                gb_field = GB_search(sl2->species, fieldName, GB_FIND);
508                                if (gb_field) {
509                                    char *content = GB_read_as_string(gb_field);
510                                    speciesConcatenateList sl3 = sl2->next;
511                                    fieldStat[i] = nextStat;
512                                    int j = i+1; doneSpecies++;
513
514                                    while (sl3) {
515                                        if (fieldStat[j]==0) {
516                                            gb_field = GB_search(sl3->species, fieldName, GB_FIND);
517                                            if (gb_field) {
518                                                char *content2 = GB_read_as_string(gb_field);
519                                                if (strcmp(content, content2)==0) { // if contents are the same, they get the same status
520                                                    fieldStat[j] = nextStat;
521                                                    doneSpecies++;
522                                                }
523                                                free(content2);
524                                            } else {
525                                                fieldStat[j] = -1;
526                                                doneSpecies++;
527                                            }
528                                        }
529                                        sl3 = sl3->next; j++;
530                                    }
531                                    free(content); nextStat++;
532                                } else {
533                                    fieldStat[i] = -1; // field does not exist here
534                                    doneSpecies++;
535                                }
536                            }
537                            sl2 = sl2->next; i++;
538                        }
539                        if (!sl2) break;
540                    }
541                    gb_assert(nextStat!=1); // this would mean that none of the species contained the field
542                    {
543                        char *new_content     = 0;
544                        int   new_content_len = 0;
545
546                        if (nextStat==2) { // all species contain same field content or do not have the field
547                            speciesConcatenateList sl2 = sl;
548                            while (sl2) {
549                                gb_field = GB_search(sl2->species, fieldName, GB_FIND);
550                                if (gb_field) {
551                                    new_content = GB_read_as_string(gb_field);
552                                    new_content_len = strlen(new_content);
553                                    break;
554                                }
555                                sl2 = sl2->next;
556                            }
557                        }
558                        else { // different field contents
559                            int actualStat;
560                            for (actualStat=1; actualStat<nextStat; actualStat++) {
561                                int names_len = 1; // open bracket
562                                speciesConcatenateList sl2 = sl;
563                                char *content = 0; i = 0;
564
565                                while (sl2) {
566                                    if (fieldStat[i]==actualStat) {
567                                        names_len += strlen(sl2->species_name)+1;
568                                        if (!content) {
569                                            gb_field = GB_search(sl2->species, fieldName, GB_FIND);
570                                            gb_assert(gb_field);
571                                            content = GB_read_as_string(gb_field);
572                                        }
573                                    }
574                                    sl2 = sl2->next; i++;
575                                }
576                                gb_assert(content);
577                                int add_len = names_len+1+strlen(content);
578                                char *whole = (char*)malloc(new_content_len+1+add_len+1);
579                                gb_assert(whole);
580                                char *add = new_content ? whole+sprintf(whole, "%s ", new_content) : whole;
581                                sl2 = sl; i = 0;
582                                int first = 1;
583                                while (sl2) {
584                                    if (fieldStat[i]==actualStat) {
585                                        add += sprintf(add, "%c%s", first ? '{' : ';', sl2->species_name);
586                                        first = 0;
587                                    }
588                                    sl2 = sl2->next; i++;
589                                }
590                                add += sprintf(add, "} %s", content);
591
592                                free(content);
593                                freeset(new_content, whole);
594                                new_content_len = strlen(new_content);
595                            }
596                        }
597
598                        if (new_content) {
599                            error = GBT_write_string(gb_new_species, fieldName, new_content);
600                            free(new_content);
601                        }
602                    }
603                }
604
605                // mark field as done:
606                char *new_doneFields = (char*)malloc(doneLen+fieldLen+1+1);
607                sprintf(new_doneFields, "%s%s;", doneFields, fieldName);
608                doneLen += fieldLen+1;
609                freeset(doneFields, new_doneFields);
610                fieldEnd[0] = ';';
611            }
612            fieldEnd[1] = behind;
613            fieldStart = fieldEnd;
614        }
615        free(newFields);
616        sl = sl->next;
617    }
618    free(doneFields);
619    delete [] fieldStat;
620
621    return error;
622}
623
624GBDATA *concatenateFieldsCreateNewSpecies(AW_window *, GBDATA *gb_species, speciesConcatenateList scl){
625    GB_push_transaction(GLOBAL_gb_main);
626
627    GB_ERROR  error           = 0;
628    GBDATA   *gb_species_data = GB_search(GLOBAL_gb_main, "species_data",  GB_CREATE_CONTAINER);
629
630    // data needed for name generation
631    char *full_name = 0;
632    char *acc       = 0;
633    char *addid     = 0;
634
635    /*--------------------getting the species related data --------------------*/
636
637    GBDATA *gb_new_species = 0;
638
639    if (!error) {
640        // copy species to create a new species
641        gb_new_species = GB_create_container(gb_species_data, "species");
642        error          = gb_new_species ? GB_copy(gb_new_species, gb_species) : GB_await_error();
643
644        if (!error) { // write dummy-name (real name written below)
645            error = GBT_write_string(gb_new_species, "name", "$currcat$");
646        }
647    }
648
649    if (!error) { // copy full name
650        full_name             = GBT_read_string(gb_species, "full_name");
651        if (!full_name) error = GB_await_error();
652        else error            = GBT_write_string(gb_new_species, "full_name", full_name);
653    }
654
655    if (!error) {
656        char **ali_names = GBT_get_alignment_names(GLOBAL_gb_main);
657        long   id        = 0;
658
659        for (speciesConcatenateList speciesList = scl; speciesList; speciesList = speciesList->next) {
660            for (int no_of_alignments = 0; ali_names[no_of_alignments]!=0; no_of_alignments++) {
661                GBDATA *gb_seq_data = GBT_read_sequence(speciesList->species, ali_names[no_of_alignments]);
662                if (gb_seq_data) {
663                    const char *seq_data  = GB_read_char_pntr(gb_seq_data);
664                    GBDATA *gb_data = GBT_add_data(gb_new_species, ali_names[no_of_alignments], "data", GB_STRING);
665                    error           = GB_write_string(gb_data, seq_data);
666                    if (!error) id += GBS_checksum(seq_data,1,".-");  //creating checksum of the each aligned sequence to generate new accession number
667                }
668                if (error) error = GB_export_errorf("Can't create alignment '%s'", ali_names[no_of_alignments]);
669            }
670        }
671
672        if (!error) {
673            acc   = GBS_global_string_copy("ARB_%lX", id); // create new accession number
674            error = GBT_write_string(gb_new_species, "acc", acc);
675        }
676
677        GBT_free_names(ali_names);
678    }
679
680    if (!error) error = checkAndMergeFields(gb_new_species, error, scl);
681
682    // now generate new name
683    if (!error) {
684        char *new_species_name = 0;
685       
686        const char *add_field = AW_get_nameserver_addid(GLOBAL_gb_main);
687        GBDATA     *gb_addid  = add_field[0] ? GB_entry(gb_new_species, add_field) : 0;
688        if (gb_addid) addid   = GB_read_string(gb_addid);
689
690        error = AWTC_generate_one_name(GLOBAL_gb_main, full_name, acc, addid, new_species_name, false, true);
691        if (!error) {   // name was created
692            if (GBT_find_species_rel_species_data(gb_species_data, new_species_name) != 0) {
693                // if the name is not unique -> create unique name
694                UniqueNameDetector und(gb_species_data);
695                freeset(new_species_name, AWTC_makeUniqueShortName(new_species_name, und));
696                if (!new_species_name) error = GB_await_error();
697            }
698        }
699
700        if (!error) error = GBT_write_string(gb_new_species, "name", new_species_name); // insert new 'name'
701
702        free(new_species_name);
703    }
704
705    error = GB_end_transaction(GLOBAL_gb_main, error);
706    if (error) {
707        gb_new_species = 0;
708        aw_popup_ok(error);
709    }
710
711    free(addid);
712    free(acc);
713    free(full_name);
714
715    return gb_new_species;
716}
717
718GB_ERROR checkAndCreateNewField(GBDATA *gb_main, char *new_field_name){
719    GB_ERROR error    = GB_check_key(new_field_name);
720
721    if (error) return error;
722    else {
723        error = GBT_add_new_changekey(gb_main,new_field_name,GB_STRING);
724        if (error) {
725            bool overwrite = aw_ask_sure(GBS_global_string("\"%s\" field exists! Do you want to overwrite the existing field?",new_field_name));
726            if (!overwrite) return error;
727        }
728    }
729    return 0;
730}
731
732static void mergeSimilarSpecies(AW_window *aws, AW_CL cl_mergeSimilarConcatenateAlignments) {
733    AW_root *aw_root          = aws->get_root();
734    char    *merge_field_name = aw_root->awar(AWAR_CON_MERGE_FIELD)->read_string();
735    char    *new_field_name   = aw_root->awar(AWAR_CON_STORE_SIM_SP_NO)->read_string();
736
737    speciesConcatenateList scl            = 0; // to build list of similar species
738    speciesConcatenateList newSpeciesList = 0;  // new SPECIES_ConcatenateList;
739
740    GB_begin_transaction(GLOBAL_gb_main);       //open database for transaction
741
742    GB_ERROR error = checkAndCreateNewField(GLOBAL_gb_main, new_field_name);
743
744    for (GBDATA * gb_species = GBT_first_marked_species(GLOBAL_gb_main);
745         gb_species && !error;
746         gb_species = GBT_next_marked_species(gb_species))
747    {
748        GBDATA     *gb_species_field = GB_entry(gb_species, merge_field_name);
749        const char *name             = GBT_read_name(gb_species);
750
751        if (!gb_species_field) {
752            // exit if species doesn't have any data in the selected field
753            error = GBS_global_string("Species '%s' does not contain data in selected field '%s'", name, merge_field_name);
754        }
755        else {
756            char *gb_species_field_content = GB_read_string(gb_species_field);
757            int   similar_species          = 0;
758
759            for (GBDATA * gb_species_next = GBT_next_marked_species(gb_species);
760                 gb_species_next && !error;
761                 gb_species_next = GBT_next_marked_species(gb_species_next))
762            {
763                GBDATA     *gb_next_species_field = GB_entry(gb_species_next, merge_field_name);
764                const char *next_name             = GBT_read_name(gb_species_next);
765
766                if (!gb_next_species_field) {
767                    // exit if species doesn't have any data in the selected field
768                    error = GBS_global_string("Species '%s' does not contain data in selected field '%s'", next_name, merge_field_name);
769                }
770                else {
771                    char *gb_next_species_field_content = GB_read_string(gb_next_species_field);
772
773                    if (strcmp(gb_species_field_content, gb_next_species_field_content) == 0) {
774                        addSpeciesToConcatenateList(&scl, next_name);
775                        GB_write_flag(gb_species_next, 0);
776                        ++similar_species;
777                    }
778                    free(gb_next_species_field_content);
779                }
780            }
781
782            if (similar_species > 0 && !error) {
783                addSpeciesToConcatenateList(&scl, name);
784                GB_write_flag(gb_species, 0);
785
786                GBDATA *new_species_created = concatenateFieldsCreateNewSpecies(aws, gb_species, scl);
787
788                gb_assert(new_species_created);
789                if (new_species_created) {      // create a list of newly created species
790                    addSpeciesToConcatenateList(&newSpeciesList, GBT_read_name(new_species_created));
791                }
792
793                error = GBT_write_int(new_species_created, new_field_name, ++similar_species);
794            }
795
796            freeSpeciesConcatenateList(scl); scl = 0;
797            free(gb_species_field_content);
798        }
799    }
800
801    if (!error) {
802        GBT_mark_all(GLOBAL_gb_main, 0);        //unmark all species in the database
803        int newSpeciesCount = 0;
804
805        for (; newSpeciesList; newSpeciesList = newSpeciesList->next) { //mark only newly created species
806            GB_write_flag(newSpeciesList->species, 1);
807            newSpeciesCount++;
808        }
809        aw_message(GBS_global_string("%i new species were created by taking \"%s\" as a criterion!", newSpeciesCount, merge_field_name));
810        freeSpeciesConcatenateList(newSpeciesList);
811    }
812
813    free(merge_field_name);
814    free(new_field_name);
815
816    GB_end_transaction_show_error(GLOBAL_gb_main, error, aw_message);
817
818    // Concatenate alignments of the merged species if cl_mergeSimilarConcatenateAlignments = MERGE_SIMILAR_CONCATENATE_ALIGNMENTS
819    if (int (cl_mergeSimilarConcatenateAlignments) && !error) concatenateAlignments(aws);
820}
821
822
823/*----------------------------Creating concatenation window-----------------------------------------*/
824AW_window *NT_createConcatenationWindow(AW_root *aw_root) {
825    AW_window_simple *aws = new AW_window_simple;
826
827    aws->init( aw_root, "CONCATENATE_ALIGNMENTS", "CONCATENATION WINDOW");
828    aws->load_xfig("concatenate.fig");
829
830    aws->button_length(8);
831
832    aws->callback( AW_POPUP_HELP,(AW_CL)"concatenate.hlp");
833    aws->at("help");
834    aws->create_button("HELP","HELP","H");
835
836    aws->at("close");
837    aws->callback((AW_CB0)AW_POPDOWN);
838    aws->create_button("CLOSE","CLOSE","C");
839
840    aws->at("dbAligns");
841    conAlignStruct *cas = createSelectionList(GLOBAL_gb_main, (AW_window *)aws, AWAR_CON_DB_ALIGNS);
842
843    aws->at("concatAligns");
844    con_alignment_list = aws->create_selection_list(AWAR_CON_CONCAT_ALIGNS, "concatAligns","N");
845    aws->insert_default_selection(con_alignment_list, "????","????");
846    aws->update_selection_list(con_alignment_list);
847
848    aws->at("type");
849    aws->create_option_menu(AWAR_CON_SEQUENCE_TYPE);
850    aws->insert_option("DNA","d","dna");
851    aws->insert_option("RNA","r","rna");
852    aws->insert_default_option("PROTEIN","p","ami");
853    aws->update_option_menu();
854    aw_root->awar(AWAR_CON_SEQUENCE_TYPE)->add_callback(createSelectionList_callBack_awar, (AW_CL)cas); //associating selection list callback to sequence type awar
855
856    aws->at("add");
857    aws->button_length(6);
858    aws->callback(selectAlignment);
859    aws->create_button("ADD","#moveRight.bitmap");
860
861    aws->at("addAll");
862    aws->button_length(6);
863    aws->callback(selectAllAlignments);
864    aws->create_button("ADDALL","#moveAll.bitmap");
865
866    aws->at("remove");
867    aws->button_length(6);
868    aws->callback(removeAlignment);
869    aws->create_button("REMOVE","#moveLeft.bitmap");
870
871    aws->at("up");
872    aws->button_length(0);
873    aws->callback(shiftAlignment, 1); //passing 1 as argument to shift the alignment upwards
874    aws->create_button("up","#moveUp.bitmap",0);
875
876    aws->at("down");
877    aws->button_length(0);
878    aws->callback(shiftAlignment, 0); //passing 0 as argument to shift the alignment downwards
879    aws->create_button("down","#moveDown.bitmap",0);
880
881    aws->at("clearList");
882    aws->callback(clearAlignmentList);
883    aws->create_button("CLEAR","CLEAR LIST","R");
884
885    aws->at("aliName");
886    aws->label_length(15);
887    aws->create_input_field(AWAR_CON_NEW_ALIGNMENT_NAME,20);
888
889    aws->at("aliSeparator");
890    aws->label_length(5);
891    aws->create_input_field(AWAR_CON_ALIGNMENT_SEPARATOR,5);
892
893    aws->at("concatenate");
894    aws->callback((AW_CB0)concatenateAlignments);
895    aws->create_button("CONCATENATE","CONCATENATE","A");
896
897    aws->at("merge_species");
898    aws->callback(AW_POPUP, (AW_CL)NT_createMergeSimilarSpeciesWindow, 0);
899    aws->create_button("MERGE_SPECIES","MERGE SIMILAR SPECIES","M");
900
901    aws->at("merge_concatenate");
902    aws->callback(AW_POPUP, (AW_CL)NT_createMergeSimilarSpeciesAndConcatenateWindow, 0);
903    aws->create_button("MERGE_CONCATENATE","MERGE and CONCATENATE","S");
904
905    aws->show();
906    return (AW_window *)aws;
907}
908
909static AW_window *createMergeSimilarSpeciesWindow(AW_root *aw_root, int option) {
910    AW_window_simple *aws = new AW_window_simple;
911
912    {
913        char *window_id = GBS_global_string_copy("MERGE_SPECIES_%i", option);
914        aws->init(aw_root, window_id, "MERGE SPECIES WINDOW" );
915        free(window_id);
916    }
917    aws->load_xfig("merge_species.fig");
918
919    aws->callback( AW_POPUP_HELP,(AW_CL)"merge_species.hlp");
920    aws->at("help");
921    aws->create_button("HELP","HELP","H");
922
923    aws->at("field_select");
924    aws->auto_space(0,0);
925    aws->callback(AW_POPDOWN);
926    awt_create_selection_list_on_scandb(GLOBAL_gb_main, aws,
927                                        AWAR_CON_MERGE_FIELD,
928                                        AWT_NDS_FILTER,
929                                        "field_select",
930                                        0,
931                                        &AWT_species_selector,
932                                        20, 30,
933                                        awt_selected_fields(AWT_SF_PSEUDO|AWT_SF_HIDDEN),
934                                        "sel_merge_field");
935
936    aws->at("store_sp_no");
937    aws->label_length(20);
938    aws->create_input_field(AWAR_CON_STORE_SIM_SP_NO,20);
939
940    aws->at("merge");
941    aws->callback(mergeSimilarSpecies, option);
942    aws->create_button("MERGE_SIMILAR_SPECIES","MERGE SIMILAR SPECIES","M");
943
944    aws->at("close");
945    aws->callback(AW_POPDOWN);
946    aws->create_button("CLOSE","CLOSE","C");
947
948    return (AW_window *)aws;
949}
950
951AW_window *NT_createMergeSimilarSpeciesWindow(AW_root *aw_root) {
952    static AW_window *aw = 0;
953   
954    if (!aw) aw = createMergeSimilarSpeciesWindow(aw_root, 0);
955    return aw;
956}
957
958AW_window *NT_createMergeSimilarSpeciesAndConcatenateWindow(AW_root *aw_root) {
959    static AW_window *aw = 0;
960   
961    if (!aw) aw = createMergeSimilarSpeciesWindow(aw_root, MERGE_SIMILAR_CONCATENATE_ALIGNMENTS);
962    return aw;
963}
964
965/*-------------------------------------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.