source: tags/ms_r16q2/MERGE/MG_species.cxx

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