root/trunk/ARBDB/adname.cxx

Revision 8607, 10.5 KB (checked in by westram, 5 weeks ago)

merge from e4fix [8135] [8136] [8137] [8138] [8139] [8140] [8141] [8142] [8143] [8144] [8222]
this revives the reverted patches [8129] [8130] [8131] [8132]

  • fixes
    • some free/delete mismatches
    • wrong definition of ORF objects (Level was no bit value)
    • amino consensus (failed for columns only containing 'C')
  • rename
    • AA_sequence_term -> orf_term
    • ED4_sequence_terminal_basic -> ED4_abstract_sequence_terminal
  • cleaned up hierarchy dumps
  • tweaked is_terminal()/to_terminal()
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : adname.cxx                                        //
4//   Purpose   : species names                                     //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "gb_local.h"
12
13#include <ad_config.h>
14#include <arbdbt.h>
15
16#include <arb_progress.h>
17#include <arb_strbuf.h>
18#include <arb_strarray.h>
19
20#include <cctype>
21
22struct gbt_renamed {
23    int     used_by;
24    char    data[1];
25};
26
27static struct {
28    GB_HASH *renamed_hash;
29    GB_HASH *old_species_hash;
30    GBDATA  *gb_main;
31    GBDATA  *gb_species_data;
32    int      all_flag;
33} NameSession;
34
35#if defined(WARN_TODO)
36#warning change all_flag into estimated number of renames ( == 0 shall mean all)
37#endif
38
39GB_ERROR GBT_begin_rename_session(GBDATA *gb_main, int all_flag) {
40    /* Starts a rename session (to rename one or many species)
41     * all_flag == 1 -> rename all species in DB
42     * Call GBT_abort_rename_session() or GBT_commit_rename_session() to close the session.
43     */
44
45    GB_ERROR error = GB_push_transaction(gb_main);
46    if (!error) {
47        NameSession.gb_main         = gb_main;
48        NameSession.gb_species_data = GBT_get_species_data(gb_main);
49
50        if (!all_flag) { // this is meant to be used for single or few species
51            int hash_size = 128;
52
53            NameSession.renamed_hash     = GBS_create_dynaval_hash(hash_size, GB_MIND_CASE, GBS_dynaval_free);
54            NameSession.old_species_hash = 0;
55        }
56        else {
57            NameSession.renamed_hash     = GBS_create_dynaval_hash(GBT_get_species_count(gb_main), GB_MIND_CASE, GBS_dynaval_free);
58            NameSession.old_species_hash = GBT_create_species_hash(gb_main);
59        }
60        NameSession.all_flag = all_flag;
61    }
62    return error;
63}
64
65GB_ERROR GBT_rename_species(const char *oldname, const  char *newname, bool ignore_protection)
66{
67    GBDATA   *gb_species;
68    GBDATA   *gb_name;
69    GB_ERROR  error;
70
71    if (strcmp(oldname, newname) == 0)
72        return 0;
73
74#if defined(DEBUG) && 1
75    if (isdigit(oldname[0])) {
76        printf("oldname='%s' newname='%s'\n", oldname, newname);
77    }
78#endif
79
80    if (NameSession.all_flag) {
81        gb_assert(NameSession.old_species_hash);
82        gb_species = (GBDATA *)GBS_read_hash(NameSession.old_species_hash, oldname);
83    }
84    else {
85        GBDATA *gb_found_species;
86
87        gb_assert(NameSession.old_species_hash == 0);
88        gb_found_species = GBT_find_species_rel_species_data(NameSession.gb_species_data, newname);
89        gb_species       = GBT_find_species_rel_species_data(NameSession.gb_species_data, oldname);
90
91        if (gb_found_species && gb_species != gb_found_species) {
92            return GB_export_errorf("A species named '%s' already exists.", newname);
93        }
94    }
95
96    if (!gb_species) {
97        return GB_export_errorf("Expected that a species named '%s' exists (maybe there are duplicate species, database might be corrupt)", oldname);
98    }
99
100    gb_name = GB_entry(gb_species, "name");
101    if (ignore_protection) GB_push_my_security(NameSession.gb_main);
102    error   = GB_write_string(gb_name, newname);
103    if (ignore_protection) GB_pop_my_security(NameSession.gb_main);
104
105    if (!error) {
106        if (NameSession.old_species_hash) {
107            GBS_write_hash(NameSession.old_species_hash, oldname, 0);
108        }
109        gbt_renamed *rns = (gbt_renamed *)GB_calloc(strlen(newname) + sizeof (gbt_renamed), sizeof(char));
110        strcpy(&rns->data[0], newname);
111        GBS_write_hash(NameSession.renamed_hash, oldname, (long)rns);
112    }
113    return error;
114}
115
116static void gbt_free_rename_session_data() {
117    if (NameSession.renamed_hash) {
118        GBS_free_hash(NameSession.renamed_hash);
119        NameSession.renamed_hash = 0;
120    }
121    if (NameSession.old_species_hash) {
122        GBS_free_hash(NameSession.old_species_hash);
123        NameSession.old_species_hash = 0;
124    }
125}
126
127GB_ERROR GBT_abort_rename_session() {
128    gbt_free_rename_session_data();
129    return GB_abort_transaction(NameSession.gb_main);
130}
131
132static const char *currentTreeName = 0;
133
134static GB_ERROR gbt_rename_tree_rek(GBT_TREE *tree, int tree_index) {
135    char buffer[256];
136    static int counter = 0;
137    if (!tree) return 0;
138    if (tree->is_leaf) {
139        if (tree->name) {
140            gbt_renamed *rns = (gbt_renamed *)GBS_read_hash(NameSession.renamed_hash, tree->name);
141            if (rns) {
142                char *newname;
143                if (rns->used_by == tree_index) { // species more than once in the tree
144                    sprintf(buffer, "%s_%i", rns->data, counter++);
145                    GB_warningf("Species '%s' more than once in '%s', creating zombie '%s'",
146                                tree->name, currentTreeName, buffer);
147                    newname = buffer;
148                }
149                else {
150                    newname = &rns->data[0];
151                }
152                freedup(tree->name, newname);
153                rns->used_by = tree_index;
154            }
155        }
156    }
157    else {
158        gbt_rename_tree_rek(tree->leftson, tree_index);
159        gbt_rename_tree_rek(tree->rightson, tree_index);
160    }
161    return 0;
162}
163
164GB_ERROR GBT_commit_rename_session() { // goes to header: __ATTR__USERESULT
165    arb_progress commit_progress("Renaming name references", 3);
166    commit_progress.allow_title_reuse();
167
168    GB_ERROR error = 0;
169
170    // rename species in trees
171    {
172        ConstStrArray tree_names;
173        GBT_get_tree_names(tree_names, NameSession.gb_main, false);
174
175        if (!tree_names.empty()) {
176            int          tree_count = tree_names.size();
177            arb_progress progress(GBS_global_string("Renaming species in %i tree%c", tree_count, "s"[tree_count<2]),
178                                  tree_count*3);
179
180            for (int count = 0; count<tree_count && !error; ++count) {
181                const char *tname = tree_names[count];
182                GBT_TREE   *tree  = GBT_read_tree(NameSession.gb_main, tname, -sizeof(GBT_TREE));
183                ++progress;
184
185                if (tree) {
186                    currentTreeName = tname; // provide tree name (used for error message)
187                    gbt_rename_tree_rek(tree, count+1);
188                    currentTreeName = 0;
189
190                    ++progress;
191
192                    GBT_write_tree(NameSession.gb_main, 0, tname, tree);
193                    GBT_delete_tree(tree);
194                   
195                    progress.inc_and_check_user_abort(error);
196                }
197                else {
198                    ++progress;
199                    ++progress;
200                }
201            }
202        }
203        commit_progress.inc_and_check_user_abort(error);
204    }
205    // rename configurations
206    if (!error) {
207        ConstStrArray config_names;
208        GBT_get_configuration_names(config_names, NameSession.gb_main);
209
210        if (!config_names.empty()) {
211            int          config_count = config_names.size();
212            arb_progress progress(GBS_global_string("Renaming species in %i config%c", config_count, "s"[config_count<2]), config_count);
213
214            for (int count = 0; !error && count<config_count; ++count) {
215                GBT_config *config = GBT_load_configuration_data(NameSession.gb_main, config_names[count], &error);
216                if (!error) {
217                    int need_save = 0;
218                    int mode;
219
220                    for (mode = 0; !error && mode<2; ++mode) {
221                        char              **configStrPtr = (mode == 0 ? &config->top_area : &config->middle_area);
222                        GBT_config_parser  *parser       = GBT_start_config_parser(*configStrPtr);
223                        GBT_config_item    *item         = GBT_create_config_item();
224                        GBS_strstruct      *strstruct    = GBS_stropen(1000);
225
226                        error = GBT_parse_next_config_item(parser, item);
227                        while (!error && item->type != CI_END_OF_CONFIG) {
228                            if (item->type == CI_SPECIES) {
229                                gbt_renamed *rns = (gbt_renamed *)GBS_read_hash(NameSession.renamed_hash, item->name);
230                                if (rns) { // species was renamed
231                                    freedup(item->name, rns->data);
232                                    need_save = 1;
233                                }
234                            }
235                            GBT_append_to_config_string(item, strstruct);
236                            error = GBT_parse_next_config_item(parser, item);
237                        }
238
239                        if (!error) freeset(*configStrPtr, GBS_strclose(strstruct));
240                        else {
241                            error = GBS_global_string("Failed to parse configuration '%s' (Reason: %s)", config_names[count], error);
242                        }
243
244                        GBT_free_config_item(item);
245                        GBT_free_config_parser(parser);
246                    }
247
248                    if (!error && need_save) {
249                        error = GBT_save_configuration_data(config, NameSession.gb_main, config_names[count]);
250                    }
251                }
252                progress.inc_and_check_user_abort(error);
253            }
254        }
255    }
256    commit_progress.inc_and_check_user_abort(error);
257
258    // rename links in pseudo-species
259    if (!error && GEN_is_genome_db(NameSession.gb_main, -1)) {
260        GBDATA *gb_pseudo;
261        for (gb_pseudo = GEN_first_pseudo_species(NameSession.gb_main);
262             gb_pseudo && !error;
263             gb_pseudo = GEN_next_pseudo_species(gb_pseudo))
264        {
265            GBDATA *gb_origin_organism = GB_entry(gb_pseudo, "ARB_origin_species");
266            if (gb_origin_organism) {
267                const char  *origin = GB_read_char_pntr(gb_origin_organism);
268                gbt_renamed *rns    = (gbt_renamed *)GBS_read_hash(NameSession.renamed_hash, origin);
269                if (rns) {          // species was renamed
270                    const char *newname = &rns->data[0];
271                    error               = GB_write_string(gb_origin_organism, newname);
272                }
273            }
274        }
275    }
276    commit_progress.inc_and_check_user_abort(error);
277
278    gbt_free_rename_session_data();
279
280    error = GB_end_transaction(NameSession.gb_main, error);
281    return error;
282}
Note: See TracBrowser for help on using the browser.