source: tags/ms_r16q2/TOOLS/arb_export_sequences.cxx

Last change on this file was 13197, checked in by westram, 9 years ago
  • delete sub-mergeinfo accidentally introduced with [13191]
File size: 12.3 KB
Line 
1#include <stdio.h> // needed for arbdb.h
2#include <string.h>
3#include <unistd.h>
4
5#include <arbdb.h>
6#include <arbdbt.h>
7#include <arb_file.h>
8#include <AP_filter.hxx>
9#include <seqio.hxx>
10#include <insdel.h>
11
12#include <string>
13#include <vector>
14#include <fstream>
15#include <map>
16#include <iostream>
17#include <sstream>
18#include <set>
19#include <iterator>
20#include <algorithm>
21
22using std::cerr;
23using std::endl;
24using std::clog;
25using std::cout;
26using std::string;
27using std::map;
28using std::ifstream;
29using std::ofstream;
30using std::vector;
31using std::stringstream;
32using std::getline;
33using std::set;
34
35template<typename T>
36struct equals {
37    const T& t;
38    equals(const T& _t) : t(_t) {}
39    bool operator()(const T& _t) { return _t == t; }
40};
41
42/* fake aw_message/aw_status functions */
43
44static void aw_status(double d) {
45    cerr << "aw_status_fraction: " << d << endl;
46    cerr.flush();
47}
48
49/*  generic writer class */
50class Writer : virtual Noncopyable {
51    string err_state;
52protected:
53    virtual void set_error(const char *error) {
54        arb_assert(error);
55        if (!err_state.empty()) {
56            cerr << "ERROR: " << err_state << endl;
57        }
58        err_state = error;
59    }
60
61public:
62    virtual ~Writer() {}
63
64    virtual void addSequence(GBDATA*) = 0;
65    virtual void finish() {}
66
67    const char *get_error() const {
68        return err_state.empty() ? NULL : err_state.c_str();
69    }
70    bool ok() const { return !get_error(); }
71};
72
73class MultiFastaWriter : public Writer { // derived from Noncopyable
74    ofstream file;
75    string default_ali;
76    double count, count_max;
77public:
78    MultiFastaWriter(string s, const char* a, int c)
79        : file(s.c_str()),
80          default_ali(a),
81          count(0), count_max(c)
82    {
83    }
84
85    string readString(GBDATA* spec, const char* key) {
86        GBDATA *gbd = GB_find(spec, key, SEARCH_CHILD);
87        if (!gbd) return string("<empty>");
88        char *str= GB_read_as_string(gbd);
89        if (!str) return string("<empty>");
90        string rval = str;
91        free(str);
92        return rval;
93    }
94
95    string readData(GBDATA* spec) {
96        GBDATA *gbd    = GB_find(spec, default_ali.c_str(), SEARCH_CHILD);
97        if (!gbd) return string("<empty>");
98        string  result = readString(gbd, "data");
99        GB_release(gbd);
100        return result;
101    }
102
103    void addSequence(GBDATA* spec) OVERRIDE {
104        file << ">"
105             << readString(spec, "acc") << "."
106             << readString(spec, "start") << "."
107             << readString(spec, "stop") << " | "
108             << readString(spec, "full_name") << "\n";
109
110        string tmp = readData(spec);
111        std::replace_if(tmp.begin(),tmp.end(),equals<char>('.'),'-');
112
113        unsigned int i;
114        for (i=0; i+70<tmp.size(); i+=70)
115            file << tmp.substr(i,70) << "\n";
116        file << tmp.substr(i) << "\n";
117        aw_status(++count/count_max);
118    }
119};
120
121class ArbWriter : public Writer { // derived from Noncopyable
122    string  template_arb;
123    string  filename;
124    double  count, count_max;
125    GBDATA *gbdst, *gbdst_spec;
126
127    void close() {
128        if (gbdst) {
129            GB_close(gbdst);
130            gbdst = NULL;
131        }
132    }
133
134    void set_error(const char *error) OVERRIDE {
135        Writer::set_error(error);
136        close();
137    }
138
139public:
140    ArbWriter(string ta, string f, int c)
141        : template_arb(ta),
142          filename(f),
143          count(0),
144          count_max(c)
145    {
146        gbdst = GB_open(template_arb.c_str(), "rw");
147        if (!gbdst) set_error("Unable to open template file");
148        else {
149            if (GB_request_undo_type(gbdst, GB_UNDO_NONE)) {
150                cerr << "WARN: Unable to disable undo buffer";
151            }
152
153            GB_begin_transaction(gbdst);
154            gbdst_spec = GB_search(gbdst, "species_data", GB_CREATE_CONTAINER);
155            GB_commit_transaction(gbdst);
156
157            GB_ERROR error = GB_save_as(gbdst, filename.c_str(), "b");
158            if (error) set_error(GBS_global_string("Unable to open output file (Reason: %s)", error));
159        }
160    }
161    ~ArbWriter() {
162        close();
163        if (!ok()) {
164            unlink(filename.c_str());
165        }
166    }
167
168    void addSequence(GBDATA* gbspec) OVERRIDE {
169        if (gbdst) {
170            GB_transaction  ta(gbdst);
171            GBDATA         *gbnew = GB_create_container(gbdst_spec, "species");
172            GB_ERROR        error = NULL;
173            if (!gbnew) {
174                error = GB_await_error();
175            }
176            else {
177                error             = GB_copy(gbnew, gbspec);
178                if (!error) error = GB_release(gbnew);
179            }
180            if (error) set_error(error);
181        }
182        aw_status(++count/count_max);
183    }
184
185    void finish() OVERRIDE {
186        GB_ERROR error = NULL;
187        if (gbdst) {
188            cerr << "Compressing..." << endl;
189            GB_transaction  trans(gbdst);
190            char           *ali = GBT_get_default_alignment(gbdst);
191            if (!ali) {
192                error = "Your template DB has no default alignment";
193            }
194            else {
195                error            = ARB_format_alignment(gbdst, ali);
196                if (error) error = GBS_global_string("Failed to format alignments (Reason: %s)", error);
197                free(ali);
198            }
199        }
200
201        if (!error && GB_save_as(gbdst, filename.c_str(), "b")) {
202            error = "Unable to save to output file";
203        }
204
205        if (error) set_error(error);
206    }
207};
208
209class AwtiExportWriter : public Writer { // derived from Noncopyable
210    GBDATA *gbmain;
211    const char *dbname;
212    const char *formname;
213    const char *outname;
214    const int compress;
215
216public:
217    AwtiExportWriter(GBDATA *_gbmain, const char *_dbname, const char* eft,
218                     const char* out, int c)
219        : gbmain(_gbmain), dbname(_dbname), formname(eft), outname(out), compress(c)
220    {
221        GBT_mark_all(gbmain, 0);
222    }
223    void addSequence(GBDATA *gbspec) OVERRIDE {
224        GB_write_flag(gbspec, 1);
225    }
226
227    void finish() OVERRIDE {
228        const int marked_only = 1;
229        const int cut_stop_codon = 0;
230        const int multiple = 0;
231
232        char      *aliname      = GBT_get_default_alignment(gbmain);
233        AP_filter  filter(GBT_get_alignment_len(gbmain, aliname));
234        char      *real_outname = 0;
235
236        GB_ERROR err = SEQIO_export_by_format(gbmain, marked_only, &filter,
237                                              cut_stop_codon, compress, dbname,
238                                              formname, outname, multiple, &real_outname);
239        if (err) set_error(err);
240
241        free(real_outname);
242        free(aliname);
243    }
244};
245
246
247
248static void help() {
249    cerr <<
250        "Exports sequences from an ARB database."
251        "\n"
252        "Parameters:\n"
253        " --source <FILE>        source file\n"
254        " --dest <FILE>          destination file\n"
255        " --format <ARG>         'ARB', 'FASTA' or path to ARB EFT file\n"
256        " --accs <FILE>          export only sequences matching these accessions\n"
257        "\n"
258        "only for EFT output format:\n"
259        " --eft-compress-gaps <ARG>  'none', 'vertical' or 'all' (default none)\n"
260        "\n"
261        "required for ARB output format:\n"
262        " --arb-template <FILE>      template (empty) arb file\n"
263
264         << endl;;
265}
266
267static set<string> read_accession_file(const char* file) {
268    set<string> accessions;
269    ifstream ifs(file);
270    string linestring;
271
272    do {
273        getline(ifs,linestring);
274        if (!linestring.empty()) {
275            stringstream line(linestring);
276            string item;
277            do {
278                getline(line,item,',');
279                item.erase(item.find_last_not_of(" \n,\t")+1);
280                item.erase(0,item.find_first_not_of(" \n,\t"));
281                if (!item.empty())
282                    accessions.insert(item);
283            } while(line.good());
284        }
285    } while(ifs.good());
286
287    return accessions;
288}
289
290int main(int argc, char** argv) {
291    enum {
292        FMT_ARB,
293        FMT_FASTA,
294        FMT_EFT,
295        FMT_NONE
296    } format = FMT_NONE;
297    char* src = 0;
298    char* dest = 0;
299    char* tmpl = 0;
300    char* accs = 0;
301    char* eft = 0;
302    int compress = 0;
303    GB_shell shell;
304
305    if (argc <2) {
306        help();
307        return 0;
308    }
309
310    for (int i = 1; i < argc; i++) {
311        if (argc > i+1) {
312            if (!strcmp(argv[i], "--source")) {
313                src = argv[++i];
314            } else if (!strcmp(argv[i], "--dest")) {
315                dest = argv[++i];
316            } else if (!strcmp(argv[i], "--arb-template")) {
317                tmpl = argv[++i];
318            } else if (!strcmp(argv[i], "--accs")) {
319                accs = argv[++i];
320            } else if (!strcmp(argv[i], "--format")) {
321                if (!strcmp(argv[++i], "ARB")) {
322                    format = FMT_ARB;
323                } else if (!strcmp(argv[i], "FASTA")) {
324                    format = FMT_FASTA;
325                } else {
326                    format = FMT_EFT;
327                    eft = argv[i];
328                }
329            } else if (!strcmp(argv[i], "--eft-compress-gaps")) {
330                if (!strcmp(argv[++i], "none")) {
331                    compress = 0;
332                } else if (!strcmp(argv[i], "vertical")) {
333                    compress = 1;
334                } else if (!strcmp(argv[i], "all")) {
335                    compress = 2;
336                } else {
337                    cerr << "missing argument to --eft-compress-gaps?";
338                    i--;
339                }
340            } else {
341                cerr << "ignoring malformed argument: '" << argv[i] << "'" << endl;
342            }
343        } else {
344            cerr << "ignoring malformed argument: '" << argv[i] << "'" << endl;
345        }
346    }
347
348    if (!src) {
349        cerr << "need '--source' parameter" << endl;
350        return 1;
351    }
352    if (!dest) {
353        cerr << "need '--dest' parameter" << endl;
354        return 1;
355    }
356    if (format == FMT_NONE) {
357        cerr << "need '--format' parameter" << endl;
358        return 1;
359    }
360    if (format == FMT_ARB && !tmpl) {
361        cerr << "need '--arb-template' parameter for output type ARB'" << endl;
362        return 1;
363    }
364
365    set<string> accessions;
366    if (accs) {
367        if (!GB_is_regularfile(accs)) {
368            cerr << "unable to open accession number file '" << accs << '\'' << endl;
369            return 1;
370        }
371        accessions = read_accession_file(accs);
372    }
373
374    GB_ERROR error    = NULL;
375    int      exitcode = 0;
376
377    GBDATA *gbsrc = GB_open(src, "r");
378    if (!gbsrc) {
379        error    = "unable to open source file";
380        exitcode = 1;
381    }
382
383    if (!error) {
384        GB_transaction trans(gbsrc);
385
386        int count_max = 0;
387        if (accs) {
388            count_max = accessions.size();
389        } else {
390            for (GBDATA *gbspec = GBT_first_species(gbsrc);
391                 gbspec; gbspec = GBT_next_species(gbspec)) {
392                count_max++;
393            }
394        }
395
396        // create writer for target type
397        Writer *writer = 0;
398        switch(format) {
399        case FMT_ARB:
400            writer = new ArbWriter(tmpl, dest, count_max);
401            break;
402        case FMT_FASTA: {
403            char *default_ali = GBT_get_default_alignment(gbsrc);
404            writer            = new MultiFastaWriter(dest, default_ali, count_max);
405            free(default_ali);
406            break;
407        }
408        case FMT_EFT:
409            writer = new AwtiExportWriter(gbsrc, src, eft, dest, compress);
410            break;
411
412        case FMT_NONE:
413            error    = "internal error";
414            exitcode = 2;
415            break;
416        }
417
418        if (writer) {
419            // generate file
420            for (GBDATA *gbspec = GBT_first_species(gbsrc);
421                 gbspec && writer->ok();
422                 gbspec = GBT_next_species(gbspec))
423            {
424                GBDATA *gbname = GB_find(gbspec, "acc", SEARCH_CHILD);
425                string name(GB_read_char_pntr(gbname));
426
427                if (!accs || accessions.count(name))  {
428                    writer->addSequence(gbspec);
429                }
430                GB_release(gbspec);
431            }
432
433            if (writer->ok()) writer->finish();
434           
435            if (!writer->ok()) {
436                error    = GBS_static_string(writer->get_error());
437                exitcode = 5;
438            }
439            delete writer;
440        }
441    }
442    if (gbsrc) GB_close(gbsrc);
443
444    if (error) cerr << "ERROR: " << error << endl;
445    return exitcode;
446}
447
Note: See TracBrowser for help on using the repository browser.