source: tags/cvs_2_svn/NTREE/NT_concatenate.cxx

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