source: tags/arb-6.0.5/MERGE/MG_species.cxx

Last change on this file was 12267, checked in by westram, 11 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.9 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : MG_species.cxx                                    //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "merge.hxx"
12#include "MG_adapt_ali.hxx"
13
14#include <AW_rename.hxx>
15#include <db_query.h>
16#include <db_scanner.hxx>
17#include <item_sel_list.h>
18#include <aw_awars.hxx>
19#include <aw_msg.hxx>
20#include <arb_progress.h>
21#include <aw_root.hxx>
22#include <aw_question.hxx>
23#include <arb_str.h>
24#include <arb_strbuf.h>
25
26#define AWAR_SPECIES_SRC AWAR_MERGE_TMP_SRC "name"
27#define AWAR_FIELD_SRC   AWAR_MERGE_TMP_SRC "field"
28#define AWAR_TAG_SRC     AWAR_MERGE_TMP_SRC "tag"
29
30#define AWAR_SPECIES_DST AWAR_MERGE_TMP_DST "name"
31#define AWAR_FIELD_DST   AWAR_MERGE_TMP_DST "field"
32#define AWAR_TAG_DST     AWAR_MERGE_TMP_DST "tag"
33
34#define AWAR_TAG_DEL AWAR_MERGE_TMP "tagdel"
35#define AWAR_APPEND  AWAR_MERGE_TMP "append"
36
37static DbScanner *scanner_src = 0;
38static DbScanner *scanner_dst = 0;
39
40const char *MG_left_AWAR_SPECIES_NAME() { return AWAR_SPECIES_SRC; }
41
42void MG_create_species_awars(AW_root *aw_root, AW_default aw_def) {
43    aw_root->awar_string(AWAR_SPECIES_SRC, "", aw_def);
44    aw_root->awar_string(AWAR_SPECIES_DST, "", aw_def);
45    aw_root->awar_string(AWAR_FIELD_SRC,   "", aw_def);
46    aw_root->awar_int(AWAR_APPEND);
47}
48
49static void MG_map_species(AW_root *aw_root, int db_nr) {
50    GBDATA     *gb_main   = get_gb_main(db_nr);
51    const char *awar_name = db_nr == 1 ? AWAR_SPECIES_SRC : AWAR_SPECIES_DST;
52    DbScanner  *scanner   = db_nr == 1 ? scanner_src : scanner_dst;
53
54    GB_transaction ta(gb_main);
55    char   *selected_species = aw_root->awar(awar_name)->read_string();
56    GBDATA *gb_species       = GBT_find_species(gb_main, selected_species);
57    if (gb_species) map_db_scanner(scanner, gb_species, awar_name);
58    free(selected_species);
59}
60
61static GB_ERROR MG_transfer_fields_info(char *fieldname = NULL) {
62    GBDATA   *gb_key_data = GB_search(GLOBAL_gb_src, CHANGE_KEY_PATH, GB_CREATE_CONTAINER);
63    GB_ERROR  error       = 0;
64
65    if (!gb_key_data) error = GB_await_error();
66    else {
67        if (!GB_search(GLOBAL_gb_dst, CHANGE_KEY_PATH, GB_CREATE_CONTAINER)) error = GB_await_error();
68        else {
69            for (GBDATA *gb_key = GB_entry(gb_key_data, CHANGEKEY);
70                 gb_key && !error;
71                 gb_key = GB_nextEntry(gb_key))
72            {
73                GBDATA *gb_key_name = GB_entry(gb_key, CHANGEKEY_NAME);
74                if (gb_key_name) {
75                    GBDATA *gb_key_type = GB_entry(gb_key, CHANGEKEY_TYPE);
76                    if (gb_key_type) {
77                        char *name = GB_read_string(gb_key_name);
78
79                        if (!fieldname || strcmp(fieldname, name) == 0) {
80                            error = GBT_add_new_changekey(GLOBAL_gb_dst, name, (int)GB_read_int(gb_key_type));
81                        }
82                        free(name);
83                    }
84                }
85            }
86        }
87    }
88    return error;
89}
90
91static GB_ERROR MG_transfer_one_species(AW_root *aw_root, MG_remaps& remap,
92                                        GBDATA *gb_src_species_data, GBDATA *gb_dst_species_data,
93                                        bool src_is_genome, bool dst_is_genome,
94                                        GBDATA  *gb_src_species, const char *src_name,
95                                        GB_HASH *source_organism_hash, GB_HASH *dest_species_hash,
96                                        GB_HASH *error_suppressor)
97{
98    // copies one species from source to destination DB
99    //
100    // either 'gb_src_species' or 'src_name' (and 'gb_src_species_data') has to be given
101    // 'source_organism_hash' may be NULL, otherwise it's used to search for source organisms (when merging from genome DB)
102    // 'dest_species_hash' may be NULL, otherwise created species is stored there
103
104    GB_ERROR error = 0;
105    if (gb_src_species) {
106        src_name = GBT_read_name(gb_src_species);
107    }
108    else {
109        mg_assert(src_name);
110        gb_src_species = GBT_find_species_rel_species_data(gb_src_species_data, src_name);
111        if (!gb_src_species) {
112            error = GBS_global_string("Could not find species '%s'", src_name);
113        }
114    }
115
116    bool transfer_fields = false;
117    if (src_is_genome) {
118        if (dst_is_genome) { // genome -> genome
119            if (GEN_is_pseudo_gene_species(gb_src_species)) {
120                const char *origin        = GEN_origin_organism(gb_src_species);
121                GBDATA     *dest_organism = dest_species_hash
122                    ? (GBDATA*)GBS_read_hash(dest_species_hash, origin)
123                    : GEN_find_organism(GLOBAL_gb_dst, origin);
124
125                if (dest_organism) transfer_fields = true;
126                else {
127                    error = GBS_global_string("Destination DB does not contain '%s's origin-organism '%s'",
128                                              src_name, origin);
129                }
130            }
131            // else: merge organism ok
132        }
133        else { // genome -> non-genome
134            if (GEN_is_pseudo_gene_species(gb_src_species)) transfer_fields = true;
135            else {
136                error = GBS_global_string("You can't merge organisms (%s) into a non-genome DB.\n"
137                                          "Only pseudo-species are possible", src_name);
138            }
139        }
140    }
141    else {
142        if (dst_is_genome) { // non-genome -> genome
143            error = GBS_global_string("You can't merge non-genome species (%s) into a genome DB", src_name);
144        }
145        // else: non-genome -> non-genome ok
146    }
147
148    GBDATA *gb_dst_species = 0;
149    if (!error) {
150        gb_dst_species = dest_species_hash
151            ? (GBDATA*)GBS_read_hash(dest_species_hash, src_name)
152            : GBT_find_species_rel_species_data(gb_dst_species_data, src_name);
153
154        if (gb_dst_species) error = GB_delete(gb_dst_species);
155    }
156    if (!error) {
157        gb_dst_species = GB_create_container(gb_dst_species_data, "species");
158        if (!gb_dst_species) error = GB_await_error();
159    }
160    if (!error) error = GB_copy(gb_dst_species, gb_src_species);
161    if (!error && transfer_fields) {
162        mg_assert(src_is_genome);
163        error = MG_export_fields(aw_root, gb_src_species, gb_dst_species, error_suppressor, source_organism_hash);
164    }
165    if (!error) GB_write_flag(gb_dst_species, 1);
166    if (!error) error = MG_transfer_all_alignments(&remap, gb_src_species, gb_dst_species);
167    if (!error && dest_species_hash) GBS_write_hash(dest_species_hash, src_name, (long)gb_dst_species);
168
169    return error;
170}
171
172static const char *get_reference_species_names(AW_root *awr) {
173    return awr->awar(AWAR_REMAP_SPECIES_LIST)->read_char_pntr();
174}
175static bool adaption_enabled(AW_root *awr) {
176    return awr->awar(AWAR_REMAP_ENABLE)->read_int() != 0;
177}
178
179static void MG_transfer_selected_species(AW_window *aww) {
180    if (MG_copy_and_check_alignments() != 0) return;
181
182    AW_root  *aw_root  = aww->get_root();
183    char     *src_name = aw_root->awar(AWAR_SPECIES_SRC)->read_string();
184    GB_ERROR  error    = NULL;
185
186    if (!src_name || !src_name[0]) {
187        error = "Please select a species in the left list";
188    }
189    else {
190        arb_progress progress("Transferring selected species");
191
192        error             = GB_begin_transaction(GLOBAL_gb_src);
193        if (!error) error = GB_begin_transaction(GLOBAL_gb_dst);
194
195        if (!error) {
196            MG_remaps rm(GLOBAL_gb_src, GLOBAL_gb_dst, adaption_enabled(aw_root), get_reference_species_names(aw_root));
197
198            GBDATA *gb_src_species_data = GBT_get_species_data(GLOBAL_gb_src);
199            GBDATA *gb_dst_species_data = GBT_get_species_data(GLOBAL_gb_dst);
200
201            bool src_is_genome = GEN_is_genome_db(GLOBAL_gb_src, -1);
202            bool dst_is_genome = GEN_is_genome_db(GLOBAL_gb_dst, -1);
203
204            error = MG_transfer_one_species(aw_root, rm,
205                                            gb_src_species_data, gb_dst_species_data,
206                                            src_is_genome, dst_is_genome,
207                                            NULL, src_name,
208                                            NULL, NULL,
209                                            NULL);
210        }
211
212        if (!error) error = MG_transfer_fields_info();
213
214        error = GB_end_transaction(GLOBAL_gb_src, error);
215        error = GB_end_transaction(GLOBAL_gb_dst, error);
216    }
217
218    if (error) aw_message(error);
219}
220
221static void MG_transfer_species_list(AW_window *aww) {
222    if (MG_copy_and_check_alignments() != 0) return;
223
224    GB_ERROR error = NULL;
225    GB_begin_transaction(GLOBAL_gb_src);
226    GB_begin_transaction(GLOBAL_gb_dst);
227
228    bool src_is_genome = GEN_is_genome_db(GLOBAL_gb_src, -1);
229    bool dst_is_genome = GEN_is_genome_db(GLOBAL_gb_dst, -1);
230
231    GB_HASH *error_suppressor     = GBS_create_hash(50, GB_IGNORE_CASE);
232    GB_HASH *dest_species_hash    = GBT_create_species_hash(GLOBAL_gb_dst);
233    GB_HASH *source_organism_hash = src_is_genome ? GBT_create_organism_hash(GLOBAL_gb_src) : 0;
234
235    AW_root   *aw_root = aww->get_root();
236    MG_remaps  rm(GLOBAL_gb_src, GLOBAL_gb_dst, adaption_enabled(aw_root), get_reference_species_names(aw_root));
237
238    GBDATA *gb_src_species;
239    arb_progress progress("Transferring listed species", mg_count_queried(GLOBAL_gb_src));
240   
241    for (gb_src_species = GBT_first_species(GLOBAL_gb_src);
242         gb_src_species;
243         gb_src_species = GBT_next_species(gb_src_species))
244    {
245        if (IS_QUERIED_SPECIES(gb_src_species)) {
246            GBDATA *gb_dst_species_data = GBT_get_species_data(GLOBAL_gb_dst);
247
248            error = MG_transfer_one_species(aw_root, rm,
249                                            NULL, gb_dst_species_data,
250                                            src_is_genome, dst_is_genome,
251                                            gb_src_species, NULL,
252                                            source_organism_hash, dest_species_hash,
253                                            error_suppressor);
254
255            progress.inc_and_check_user_abort(error);
256        }
257    }
258
259    GBS_free_hash(dest_species_hash);
260    if (source_organism_hash) GBS_free_hash(source_organism_hash);
261    GBS_free_hash(error_suppressor);
262
263    if (!error) error = MG_transfer_fields_info();
264
265    error = GB_end_transaction(GLOBAL_gb_src, error);
266    GB_end_transaction_show_error(GLOBAL_gb_dst, error, aw_message);
267}
268
269static void MG_transfer_fields_cb(AW_window *aww) {
270    if (MG_copy_and_check_alignments() != 0) return;
271
272    char     *field  = aww->get_root()->awar(AWAR_FIELD_SRC)->read_string();
273    long      append = aww->get_root()->awar(AWAR_APPEND)->read_int();
274    GB_ERROR  error  = 0;
275
276    if (field[0] == 0) {
277        error = "Please select a field you want to transfer";
278    }
279    else if (strcmp(field, "name") == 0) {
280        error = "Transferring the 'name' field is forbidden";
281    }
282    else {
283        GB_begin_transaction(GLOBAL_gb_src);
284        GB_begin_transaction(GLOBAL_gb_dst);
285
286        GBDATA *gb_dest_species_data  = GBT_get_species_data(GLOBAL_gb_dst);
287        bool    transfer_of_alignment = GBS_string_matches(field, "ali_*/data", GB_MIND_CASE);
288
289        arb_progress progress("Transferring fields of listed", mg_count_queried(GLOBAL_gb_src));
290
291        AW_root   *aw_root = aww->get_root();
292        MG_remaps  rm(GLOBAL_gb_src, GLOBAL_gb_dst, adaption_enabled(aw_root), get_reference_species_names(aw_root));
293
294        for (GBDATA *gb_src_species = GBT_first_species(GLOBAL_gb_src);
295             gb_src_species && !error;
296             gb_src_species = GBT_next_species(gb_src_species))
297        {
298            if (IS_QUERIED_SPECIES(gb_src_species)) {
299                const char *src_name       = GBT_read_name(gb_src_species);
300                GBDATA     *gb_dst_species = GB_find_string(gb_dest_species_data, "name", src_name, GB_IGNORE_CASE, SEARCH_GRANDCHILD);
301
302                if (!gb_dst_species) {
303                    gb_dst_species             = GB_create_container(gb_dest_species_data, "species");
304                    if (!gb_dst_species) error = GB_await_error();
305                    else error                 = GBT_write_string(gb_dst_species, "name", src_name);
306                }
307                else {
308                    gb_dst_species = GB_get_father(gb_dst_species);
309                }
310
311                if (!error) {
312                    GBDATA *gb_src_field = GB_search(gb_src_species, field, GB_FIND);
313                    GBDATA *gb_dst_field = GB_search(gb_dst_species, field, GB_FIND);
314                    bool    use_copy     = true;
315
316                    if (gb_dst_field && gb_src_field) {
317                        GB_TYPES src_type = GB_read_type(gb_src_field);
318                        GB_TYPES dst_type = GB_read_type(gb_dst_field);
319
320                        if ((src_type==dst_type) && (GB_DB != src_type)) {
321                            if (append && src_type == GB_STRING) {
322                                char *src_val = GB_read_string(gb_src_field);
323                                char *dst_val = GB_read_string(gb_dst_field);
324
325                                if (!src_val || !dst_val) error = GB_await_error();
326                                else {
327                                    if (!GBS_find_string(dst_val, src_val, 0)) {
328                                        error = GB_write_string(gb_dst_field, GBS_global_string("%s %s", dst_val, src_val));
329                                        if (!error) GB_write_flag(gb_dst_species, 1);
330                                    }
331                                }
332
333                                free(src_val);
334                                free(dst_val);
335                            }
336                            else { // not GB_STRING
337                                error = GB_copy(gb_dst_field, gb_src_field);
338                                if (!error) GB_write_flag(gb_dst_species, 1);
339                                if (transfer_of_alignment && !error) {
340                                    error = MG_transfer_all_alignments(&rm, gb_src_species, gb_dst_species);
341                                }
342                            }
343                            use_copy = false;
344                        }
345                    }
346
347                    if (use_copy) {
348                        if (gb_dst_field) {
349                            if (gb_src_field && !append) error = GB_delete(gb_dst_field);
350                        }
351                        if (gb_src_field && !error) {
352                            GB_TYPES src_type        = GB_read_type(gb_src_field);
353                            gb_dst_field             = GB_search(gb_dst_species, field, src_type);
354                            if (!gb_dst_field) error = GB_await_error();
355                            else     error           = GB_copy(gb_dst_field, gb_src_field);
356                        }
357                    }
358                }
359                progress.inc_and_check_user_abort(error);
360            }
361        }
362
363        if (!error) error = MG_transfer_fields_info(field);
364
365        error = GB_end_transaction(GLOBAL_gb_src, error);
366        error = GB_end_transaction(GLOBAL_gb_dst, error);
367    }
368
369    if (error) aw_message(error);
370    free(field);
371}
372
373static AW_window *MG_create_transfer_fields_window(AW_root *aw_root) {
374    GB_transaction    ta(GLOBAL_gb_src);
375    AW_window_simple *aws = new AW_window_simple;
376
377    aws->init(aw_root, "MERGE_TRANSFER_FIELD", "TRANSFER FIELD");
378    aws->load_xfig("merge/mg_transfield.fig");
379    aws->button_length(13);
380
381    aws->callback(AW_POPDOWN);
382    aws->at("close");
383    aws->create_button("CLOSE", "CLOSE", "C");
384
385    aws->at("go");
386    aws->callback(MG_transfer_fields_cb);
387    aws->create_button("GO", "GO");
388
389    aws->at("help");
390    aws->callback(makeHelpCallback("mg_spec_sel_field.hlp"));
391    aws->create_button("HELP", "HELP");
392
393    aws->at("append");
394    aws->create_toggle(AWAR_APPEND);
395
396    create_selection_list_on_itemfields(GLOBAL_gb_src, aws, AWAR_FIELD_SRC, true, FIELD_FILTER_NDS, "scandb", "rescandb", SPECIES_get_selector(), 20, 10, SF_STANDARD, NULL);
397
398    return (AW_window*)aws;
399}
400
401static void MG_move_field_cb(AW_window *aww) {
402    if (MG_copy_and_check_alignments() != 0) return;
403
404    AW_root  *aw_root = aww->get_root();
405    char     *field   = aww->get_root()->awar(AWAR_FIELD_SRC)->read_string();
406    GB_ERROR  error   = 0;
407
408    if (field[0] == 0) {
409        error = "Please select a field to transfer";
410    }
411    else if (strcmp(field, "name") == 0) {
412        error = "You are not allowed to transfer the 'name' field";
413    }
414    else {
415        arb_progress progress("Cross Move field");
416        error             = GB_begin_transaction(GLOBAL_gb_src);
417        if (!error) error = GB_begin_transaction(GLOBAL_gb_dst);
418
419        if (!error) {
420            GBDATA *gb_src_species;
421            GBDATA *gb_dst_species;
422            {
423                char *src_name = aw_root->awar(AWAR_SPECIES_SRC)->read_string();
424                char *dst_name = aw_root->awar(AWAR_SPECIES_DST)->read_string();
425
426                gb_src_species = GBT_find_species(GLOBAL_gb_src, src_name);
427                gb_dst_species = GBT_find_species(GLOBAL_gb_dst, dst_name);
428
429                free(dst_name);
430                free(src_name);
431            }
432
433            if (!gb_src_species) error = "Please select a species in left hitlist";
434            if (!gb_dst_species) error = "Please select a species in right hitlist";
435
436            if (!error) {
437                GBDATA *gb_src_field = GB_search(gb_src_species, field, GB_FIND);
438                if (!gb_src_field) error = GBS_global_string("Species 1 has no field '%s'", field);
439
440                if (!error) {
441                    GB_TYPES  src_type     = GB_read_type(gb_src_field);
442                    GBDATA   *gb_dst_field = GB_search(gb_dst_species, field, GB_FIND);
443
444                    if (gb_dst_field) {
445                        int dst_type = GB_read_type(gb_dst_field);
446
447                        if ((src_type==dst_type) && (GB_DB != src_type)) {
448                            error = GB_copy(gb_dst_field, gb_src_field);
449                        }
450                        else { // remove dest. if type mismatch or container
451                            error        = GB_delete(gb_dst_field);
452                            gb_dst_field = 0; // trigger copy
453                        }
454                    }
455
456                    if (!error && !gb_dst_field) { // destination missing or removed
457                        gb_dst_field             = GB_search(gb_dst_species, field, src_type);
458                        if (!gb_dst_field) error = GB_await_error();
459                        else error               = GB_copy(gb_dst_field, gb_src_field);
460                    }
461                }
462                if (!error) GB_write_flag(gb_dst_species, 1);
463            }
464        }
465        if (!error) error = MG_transfer_fields_info(field);
466
467        error = GB_end_transaction(GLOBAL_gb_src, error);
468        error = GB_end_transaction(GLOBAL_gb_dst, error);
469    }
470
471    if (error) aw_message(error);
472
473    free(field);
474}
475
476static AW_window *create_mg_move_fields_window(AW_root *aw_root) {
477    GB_transaction ta(GLOBAL_gb_src);
478
479    AW_window_simple *aws = new AW_window_simple;
480    aws->init(aw_root, "MERGE_CROSS_MOVE_FIELD", "CROSS MOVE FIELD");
481    aws->load_xfig("merge/mg_movefield.fig");
482    aws->button_length(13);
483
484    aws->callback(AW_POPDOWN);
485    aws->at("close");
486    aws->create_button("CLOSE", "CLOSE", "C");
487
488    aws->at("go");
489    aws->callback(MG_move_field_cb);
490    aws->create_button("GO", "GO");
491
492    aws->at("help");
493    aws->callback(makeHelpCallback("movefield.hlp"));
494    aws->create_button("HELP", "HELP");
495
496
497    create_selection_list_on_itemfields(GLOBAL_gb_src, aws, AWAR_FIELD_SRC, true, FIELD_FILTER_NDS, "scandb", "rescandb", SPECIES_get_selector(), 20, 10, SF_STANDARD, NULL);
498
499    return (AW_window*)aws;
500}
501
502static void MG_merge_tagged_field_cb(AW_window *aww) {
503    GB_transaction ta_merge(GLOBAL_gb_src);
504    GB_ERROR       error = GB_begin_transaction(GLOBAL_gb_dst);
505
506    if (!error) {
507        AW_root *awr = aww->get_root();
508
509        char *src_field = awr->awar(AWAR_FIELD_SRC)->read_string();
510        char *dst_field = awr->awar(AWAR_FIELD_DST)->read_string();
511        char *src_tag   = awr->awar(AWAR_TAG_SRC)->read_string();
512        char *dst_tag   = awr->awar(AWAR_TAG_DST)->read_string();
513        char *del_tag   = awr->awar(AWAR_TAG_DEL)->read_string();
514
515        arb_progress progress("Merging tagged fields", mg_count_queried(GLOBAL_gb_src));
516
517        GBDATA *gb_dest_species_data     = GBT_get_species_data(GLOBAL_gb_dst);
518        if (!gb_dest_species_data) error = GB_await_error();
519        else {
520            for (GBDATA *gb_src_species = GBT_first_species(GLOBAL_gb_src);
521                 gb_src_species && !error;
522                 gb_src_species = GBT_next_species(gb_src_species))
523            {
524                if (IS_QUERIED_SPECIES(gb_src_species)) {
525                    char *name       = GBT_read_string(gb_src_species, "name");
526                    if (!name) error = GB_await_error();
527                    else {
528                        GBDATA *gb_dst_species     = GBT_find_or_create_species_rel_species_data(gb_dest_species_data, name);
529                        if (!gb_dst_species) error = GB_await_error();
530                        else {
531                            char *src_val = GBT_readOrCreate_string(gb_src_species, src_field, "");
532                            char *dst_val = GBT_readOrCreate_string(gb_dst_species, dst_field, "");
533
534                            if (!src_val || !dst_val) error = GB_await_error();
535                            else {
536                                char *sum = GBS_merge_tagged_strings(src_val, src_tag, del_tag,
537                                                                     dst_val, dst_tag, del_tag);
538
539                                if (!sum) error = GB_await_error();
540                                else error      = GBT_write_string(gb_dst_species, dst_field, sum);
541                                free(sum);
542                            }
543                            free(dst_val);
544                            free(src_val);
545                        }
546                    }
547                    free(name);
548                    progress.inc_and_check_user_abort(error);
549                }
550            }
551        }
552
553        free(del_tag);
554        free(dst_tag);
555        free(src_tag);
556        free(dst_field);
557        free(src_field);
558    }
559    GB_end_transaction_show_error(GLOBAL_gb_dst, error, aw_message);
560}
561
562static AW_window *create_mg_merge_tagged_fields_window(AW_root *aw_root) {
563    static AW_window_simple *aws = 0;
564    if (aws) return aws;
565
566    GB_transaction ta(GLOBAL_gb_src);
567
568    aw_root->awar_string(AWAR_FIELD_SRC, "full_name");
569    aw_root->awar_string(AWAR_FIELD_DST, "full_name");
570
571    aw_root->awar_string(AWAR_TAG_SRC, "S");
572    aw_root->awar_string(AWAR_TAG_DST, "D");
573
574    aw_root->awar_string(AWAR_TAG_DEL, "S*");
575
576    aws = new AW_window_simple;
577    aws->init(aw_root, "MERGE_TAGGED_FIELDS", "MERGE TAGGED FIELDS");
578    aws->load_xfig("merge/mg_mergetaggedfield.fig");
579    aws->button_length(13);
580
581    aws->callback(AW_POPDOWN);
582    aws->at("close");
583    aws->create_button("CLOSE", "CLOSE", "C");
584
585    aws->at("go");
586    aws->callback(MG_merge_tagged_field_cb);
587    aws->create_button("GO", "GO");
588
589    aws->at("help");
590    aws->callback(makeHelpCallback("mergetaggedfield.hlp"));
591    aws->create_button("HELP", "HELP");
592
593    aws->at("tag1");    aws->create_input_field(AWAR_TAG_SRC, 5);
594    aws->at("tag2");    aws->create_input_field(AWAR_TAG_DST, 5);
595
596    aws->at("del1");    aws->create_input_field(AWAR_TAG_DEL, 5);
597
598    create_selection_list_on_itemfields(GLOBAL_gb_src, aws, AWAR_FIELD_SRC, true, FIELD_FILTER_NDS, "fields1", 0, SPECIES_get_selector(), 20, 10, SF_STANDARD, NULL);
599    create_selection_list_on_itemfields(GLOBAL_gb_dst, aws, AWAR_FIELD_DST, true, FIELD_FILTER_NDS, "fields2", 0, SPECIES_get_selector(), 20, 10, SF_STANDARD, NULL);
600
601    return (AW_window*)aws;
602}
603
604static GB_ERROR MG_equal_alignments(bool autoselect_equal_alignment_name) {
605    //! Make the alignment names equal
606    ConstStrArray S_alignment_names;
607    ConstStrArray D_alignment_names;
608    GBT_get_alignment_names(S_alignment_names, GLOBAL_gb_src);
609    GBT_get_alignment_names(D_alignment_names, GLOBAL_gb_dst);
610
611    GB_ERROR error = 0;
612    if (S_alignment_names[0] == 0) {
613        error =  GB_export_error("No source sequences found");
614    }
615    else {
616        char       *src_type = GBT_get_alignment_type_string(GLOBAL_gb_src, S_alignment_names[0]);
617        const char *dest     = 0;
618
619        for (int d = D_alignment_names.size()-1; d>0; --d) {
620            char *dst_type = GBT_get_alignment_type_string(GLOBAL_gb_dst, D_alignment_names[d]);
621            if (strcmp(src_type, dst_type) != 0) D_alignment_names.remove(d--);
622            free(dst_type);
623        }
624
625        int d = D_alignment_names.size();
626        switch (d) {
627            case 0:
628                error = GB_export_errorf("Cannot find a target alignment with a type of '%s'\n"
629                                         "You should create one first or select a different alignment type\n"
630                                         "during sequence import", src_type);
631                break;
632            case 1:
633                dest = D_alignment_names[0];
634                break;
635
636            default:
637                if (autoselect_equal_alignment_name) {
638                    for (int i = 0; i<d; ++i) {
639                        if (ARB_stricmp(S_alignment_names[0], D_alignment_names[i]) == 0) {
640                            dest = D_alignment_names[i];
641                            break;
642                        }
643                    }
644                }
645
646                if (!dest) {
647                    GBS_strstruct *str = GBS_stropen(100);
648
649                    for (int i=0; i<d; i++) {
650                        GBS_strcat(str, D_alignment_names[i]);
651                        GBS_chrcat(str, ',');
652                    }
653                    GBS_strcat(str, "ABORT");
654
655                    char *b = GBS_strclose(str);
656                    int aliid = aw_question(NULL,
657                                            "There are more than one possible alignment targets\n"
658                                            "Choose one destination alignment or ABORT", b);
659                    free(b);
660
661                    if (aliid >= d) {
662                        error = "Operation Aborted";
663                        break;
664                    }
665                    dest = D_alignment_names[aliid];
666                }
667                break;
668        }
669        if (!error && dest && strcmp(S_alignment_names[0], dest) != 0) {
670            error = GBT_rename_alignment(GLOBAL_gb_src, S_alignment_names[0], dest, 1, 1);
671            if (error) {
672                error = GBS_global_string("Failed to rename alignment '%s' to '%s' (Reason: %s)",
673                                          S_alignment_names[0], dest, error);
674            }
675            else {
676                GBT_add_new_changekey(GLOBAL_gb_src, GBS_global_string("%s/data", dest), GB_STRING);
677            }
678        }
679        free(src_type);
680    }
681
682    return error;
683}
684
685GB_ERROR MERGE_sequences_simple(AW_root *awr) {
686    //! Merge the sequences of two databases
687
688    static char *s_name = 0;
689
690    GB_HASH *D_species_hash = 0;
691
692    GB_push_my_security(GLOBAL_gb_src);
693    GB_push_my_security(GLOBAL_gb_dst);
694    GB_begin_transaction(GLOBAL_gb_src);
695    GB_begin_transaction(GLOBAL_gb_dst);
696
697    GB_ERROR error = MG_equal_alignments(true);
698    if (!error) {
699        GBDATA *S_species_data = GBT_get_species_data(GLOBAL_gb_src);
700        GBDATA *D_species_data = GBT_get_species_data(GLOBAL_gb_dst);
701
702        freenull(s_name);
703
704        {
705            long S_species_count = GB_number_of_subentries(S_species_data);
706            long D_species_count = GB_number_of_subentries(D_species_data);
707
708            // create hash containing all species from gb_dst,
709            // but sized to hold all species from both DBs:
710            D_species_hash = GBT_create_species_hash_sized(GLOBAL_gb_dst, S_species_count+D_species_count);
711        }
712
713        bool overwriteall  = false;
714        bool autorenameall = false;
715       
716        for (GBDATA *S_species = GB_entry(S_species_data, "species"); S_species; S_species = GB_nextEntry(S_species)) {
717            GBDATA *S_name = GB_search(S_species, "name", GB_STRING);
718
719            freeset(s_name, GB_read_string(S_name));
720
721            int  count = 1;
722            bool retry;
723            do {
724                retry = false;
725                count++;
726
727                GBDATA *D_species = (GBDATA*)GBS_read_hash(D_species_hash, s_name);
728                if (D_species) {
729                    if (overwriteall) {
730                        error = GB_delete(D_species);
731                    }
732                    else if (autorenameall) {
733                        GB_ERROR  dummy;
734                        char     *newname = AWTC_create_numbered_suffix(D_species_hash, s_name, dummy);
735
736                        mg_assert(newname);
737                        freeset(s_name, newname);
738                    }
739                    else {
740                        switch (aw_question("merge_existing_species",
741                                            GBS_global_string("Warning: There is an ID conflict for species '%s'\n"
742                                                              "  You may:\n"
743                                                              "  - Overwrite existing species\n"
744                                                              "  - Overwrite all species with ID conflicts\n"
745                                                              "  - Not import species\n"
746                                                              "  - Enter ID for imported species\n"
747                                                              "  - Automatically create unique species IDs (append .NUM)\n"
748                                                              "  - Abort everything", s_name),
749                                            "overwrite, overwrite all, don't import, create ID, auto-create IDs, abort")) {
750                            case 1:
751                                overwriteall = true;
752                            case 0:
753                                GB_delete(D_species);
754                                break;
755
756                            case 2:
757                                continue;
758
759                            case 3: {
760                                GB_ERROR  warning;          // duplicated species warning (does not apply here)
761                                char     *autoname = AWTC_create_numbered_suffix(D_species_hash, s_name, warning);
762
763                                if (!autoname) autoname = strdup(s_name);
764                                freeset(s_name, aw_input("Species ID", "Enter new species ID", autoname));
765                                free(autoname);
766                                retry = true;
767                                break;
768                            }
769                            case 4:
770                                autorenameall = true;
771                                retry = true;
772                                break;
773
774                            case 5:
775                                error = "Operation aborted";
776                                break;
777                        }
778                    }
779                }
780            } while (retry);
781
782            if (!error) {
783                GBDATA *D_species     = GB_create_container(D_species_data, "species");
784                if (!D_species) error = GB_await_error();
785                else {
786                    error = GB_copy_with_protection(D_species, S_species, true);
787
788                    if (!error) {
789                        GB_write_flag(D_species, 1);          // mark species
790                        GB_set_user_flag(D_species, GB_USERFLAG_QUERY); // put in search&query hitlist
791                        error = GBT_write_string(D_species, "name", s_name);
792                    }
793                }
794
795                GBS_write_hash(D_species_hash, s_name, (long)D_species);
796            }
797
798            if (error) break;
799        }
800    }
801
802    if (D_species_hash) GBS_free_hash(D_species_hash);
803
804    if (!error) error = MG_transfer_fields_info();
805    if (!error) awr->awar(AWAR_SPECIES_NAME)->write_string(s_name);
806
807    error = GB_end_transaction(GLOBAL_gb_src, error);
808    GB_end_transaction_show_error(GLOBAL_gb_dst, error, aw_message);
809
810    GB_pop_my_security(GLOBAL_gb_src);
811    GB_pop_my_security(GLOBAL_gb_dst);
812
813    return error;
814}
815
816// -----------------------------
817//      MG_species_selector
818
819static void mg_select_species1(GBDATA*,  AW_root *aw_root, const char *item_name) {
820    aw_root->awar(AWAR_SPECIES_SRC)->write_string(item_name);
821}
822static void mg_select_species2(GBDATA*,  AW_root *aw_root, const char *item_name) {
823    aw_root->awar(AWAR_SPECIES_DST)->write_string(item_name);
824}
825
826static GBDATA *mg_get_first_species_data1(GBDATA *, AW_root *, QUERY_RANGE) {
827    return GBT_get_species_data(GLOBAL_gb_src);
828}
829static GBDATA *mg_get_first_species_data2(GBDATA *, AW_root *, QUERY_RANGE) {
830    return GBT_get_species_data(GLOBAL_gb_dst);
831}
832
833static GBDATA *mg_get_selected_species1(GBDATA * /* gb_main */, AW_root *aw_root) {
834    GB_transaction ta(GLOBAL_gb_src);
835    char   *species_name            = aw_root->awar(AWAR_SPECIES_SRC)->read_string();
836    GBDATA *gb_species              = 0;
837    if (species_name[0]) gb_species = GBT_find_species(GLOBAL_gb_src, species_name);
838    free(species_name);
839    return gb_species;
840}
841static GBDATA *mg_get_selected_species2(GBDATA * /* gb_main */, AW_root *aw_root) {
842    GB_transaction ta(GLOBAL_gb_dst);
843    char   *species_name            = aw_root->awar(AWAR_SPECIES_DST)->read_string();
844    GBDATA *gb_species              = 0;
845    if (species_name[0]) gb_species = GBT_find_species(GLOBAL_gb_dst, species_name);
846    free(species_name);
847    return gb_species;
848}
849
850static MutableItemSelector MG_species_selector[2];
851
852static void mg_initialize_species_selectors() {
853    static int initialized = 0;
854    if (!initialized) {
855        MG_species_selector[0] = MG_species_selector[1] = SPECIES_get_selector();
856
857        for (int s = 0; s <= 1; ++s) {
858            MutableItemSelector& sel = MG_species_selector[s];
859
860            sel.update_item_awars        = s ? mg_select_species2 : mg_select_species1;
861            sel.get_first_item_container = s ? mg_get_first_species_data2 : mg_get_first_species_data1;
862            sel.get_selected_item = s ? mg_get_selected_species2 : mg_get_selected_species1;
863        }
864
865        initialized = 1;
866    }
867}
868
869AW_window *MG_create_merge_species_window(AW_root *awr, bool dst_is_new) {
870    GB_ERROR error = MG_expect_renamed();
871    if (error) {
872        aw_message(error);
873        return NULL; // deny to open window before user has renamed species
874    }
875
876    awr->awar_string(AWAR_REMAP_SPECIES_LIST, "ecoli", GLOBAL_gb_dst);
877    awr->awar_int(AWAR_REMAP_ENABLE, 0, GLOBAL_gb_dst);
878
879    AW_window_simple_menu *aws = new AW_window_simple_menu;
880    aws->init(awr, "MERGE_TRANSFER_SPECIES", "TRANSFER SPECIES");
881    aws->load_xfig("merge/species.fig");
882
883    aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
884    aws->create_button("CLOSE", "CLOSE", "C");
885
886    aws->at("help");
887    aws->callback(makeHelpCallback("mg_species.hlp"));
888    aws->create_button("HELP", "HELP", "H");
889
890    mg_initialize_species_selectors();
891
892    {
893        QUERY::query_spec awtqs(MG_species_selector[0]);
894        aws->create_menu("Source-DB", "S");
895
896        awtqs.gb_main                = GLOBAL_gb_src;
897        awtqs.gb_ref                 = GLOBAL_gb_dst;
898        awtqs.expect_hit_in_ref_list = false;
899        awtqs.species_name           = AWAR_SPECIES_SRC;
900        awtqs.tree_name              = 0;               // no selected tree here -> can't use tree related ACI commands without specifying a tree
901        awtqs.select_bit             = GB_USERFLAG_QUERY;
902        awtqs.ere_pos_fig            = "ere1";
903        awtqs.by_pos_fig             = "by1";
904        awtqs.qbox_pos_fig           = "qbox1";
905        awtqs.rescan_pos_fig         = "rescan1";
906        awtqs.key_pos_fig            = 0;
907        awtqs.query_pos_fig          = "content1";
908        awtqs.result_pos_fig         = "result1";
909        awtqs.count_pos_fig          = "count1";
910        awtqs.do_query_pos_fig       = "doquery1";
911        awtqs.config_pos_fig         = "doconfig1";
912        awtqs.do_mark_pos_fig        = 0;
913        awtqs.do_unmark_pos_fig      = 0;
914        awtqs.do_delete_pos_fig      = "dodelete1";
915        awtqs.do_set_pos_fig         = "doset1";
916        awtqs.do_refresh_pos_fig     = "dorefresh1";
917        awtqs.open_parser_pos_fig    = "openparser1";
918        awtqs.use_menu               = 1;
919
920        create_query_box(aws, &awtqs, "db1");
921
922        DbScanner *scanner = create_db_scanner(GLOBAL_gb_src, aws, "box1", 0, 0, 0, DB_SCANNER, 0, 0, FIELD_FILTER_NDS, awtqs.get_queried_itemtype());
923        scanner_src = scanner;
924        aws->get_root()->awar(AWAR_SPECIES_SRC)->add_callback(makeRootCallback(MG_map_species, 1));
925    }
926    {
927        QUERY::query_spec awtqs(MG_species_selector[1]);
928        aws->create_menu("Target-DB", "T");
929
930        awtqs.gb_main                = GLOBAL_gb_dst;
931        awtqs.gb_ref                 = GLOBAL_gb_src;
932        awtqs.expect_hit_in_ref_list = true;
933        awtqs.species_name           = AWAR_SPECIES_DST;
934        awtqs.select_bit             = GB_USERFLAG_QUERY;
935        awtqs.ere_pos_fig            = "ere2";
936        awtqs.by_pos_fig             = "by2";
937        awtqs.qbox_pos_fig           = "qbox2";
938        awtqs.rescan_pos_fig         = "rescan2";
939        awtqs.key_pos_fig            = 0;
940        awtqs.query_pos_fig          = "content2";
941        awtqs.result_pos_fig         = "result2";
942        awtqs.count_pos_fig          = "count2";
943        awtqs.do_query_pos_fig       = "doquery2";
944        awtqs.config_pos_fig         = "doconfig2";
945        awtqs.do_mark_pos_fig        = 0;
946        awtqs.do_unmark_pos_fig      = 0;
947        awtqs.do_delete_pos_fig      = "dodelete2";
948        awtqs.do_set_pos_fig         = "doset2";
949        awtqs.do_refresh_pos_fig     = "dorefresh2";
950        awtqs.open_parser_pos_fig    = "openparser2";
951        awtqs.use_menu               = 1;
952
953        create_query_box(aws, &awtqs, "db2");
954
955        DbScanner *scanner = create_db_scanner(GLOBAL_gb_dst, aws, "box2", 0, 0, 0, DB_SCANNER, 0, 0, FIELD_FILTER_NDS, awtqs.get_queried_itemtype());
956        scanner_dst = scanner;
957        aws->get_root()->awar(AWAR_SPECIES_DST)->add_callback(makeRootCallback(MG_map_species, 2));
958    }
959
960    // big transfer buttons:
961    aws->button_length(13);
962    {
963        aws->shadow_width(3);
964
965        aws->at("transsspec");
966        aws->callback(MG_transfer_selected_species);
967        aws->create_button("TRANSFER_SELECTED_DELETE_DUPLICATED",
968                           "Transfer\nselected\nspecies\n\nDelete\nduplicate\nin target DB", "T");
969
970        aws->at("translspec");
971        aws->callback(MG_transfer_species_list);
972        aws->create_button("TRANSFER_LISTED_DELETE_DUPLI",
973                           "Transfer\nlisted\nspecies\n\nDelete\nduplicates\nin target DB", "T");
974
975        aws->at("transfield");
976        aws->callback(MG_create_transfer_fields_window);
977        aws->create_button("TRANSFER_FIELD_OF_LISTED_DELETE_DUPLI",
978                           "Transfer\nfield\nof listed\nspecies\n\nDelete\nduplicates\nin target DB", "T");
979
980        aws->shadow_width(1);
981    }
982
983    // adapt alignments
984    {
985        if (dst_is_new) {
986            aws->sens_mask(AWM_DISABLED); // if dest DB is new = > adaption impossible
987            awr->awar(AWAR_REMAP_ENABLE)->write_int(0); // disable adaption
988        }
989
990        aws->button_length(7);
991        aws->at("adapt");
992        aws->create_toggle(AWAR_REMAP_ENABLE);
993
994        aws->at("reference");
995        aws->create_text_field(AWAR_REMAP_SPECIES_LIST);
996
997        aws->at("pres_sel");
998        aws->callback(MG_create_preserves_selection_window);
999        aws->create_button("SELECT", "SELECT", "S");
1000
1001        aws->sens_mask(AWM_ALL);
1002    }
1003
1004    // top icon
1005    aws->button_length(0);
1006    aws->at("icon");
1007    aws->callback(makeHelpCallback("mg_species.hlp"));
1008    aws->create_button("HELP_MERGE", "#merge/icon.xpm");
1009
1010    aws->create_menu("Source->Target", "g");
1011    aws->insert_menu_topic("compare_field_of_listed",   "Compare a field of listed species ...", "C", "checkfield.hlp", AWM_ALL, create_mg_check_fields_window);
1012    aws->insert_menu_topic("move_field_of_selected",    "Move one field of selected source species to same field of selected target species", "M",
1013                            "movefield.hlp", AWM_ALL, create_mg_move_fields_window);
1014    aws->insert_menu_topic("merge_field_of_listed_to_new_field", "Merge field of listed species of source-DB with different fields of same species in target-DB ", "D",
1015                            "mergetaggedfield.hlp", AWM_ALL, create_mg_merge_tagged_fields_window);
1016
1017    aws->sep______________();
1018    aws->insert_menu_topic("def_gene_species_field_xfer", "Define field transfer for gene-species", "g", "gene_species_field_transfer.hlp",
1019                           AWM_ALL, MG_gene_species_create_field_transfer_def_window);
1020
1021    return aws;
1022}
1023
Note: See TracBrowser for help on using the repository browser.