{"action":"created","comment":{"url":"https://api.github.com/repos/seqan/seqan3/pulls/comments/181702068","pull_request_review_id":112374696,"id":181702068,"diff_hunk":"@@ -1,175 +1,911 @@\n+// ============================================================================\n+//                 SeqAn - The Library for Sequence Analysis\n+// ============================================================================\n+//\n+// Copyright (c) 2006-2018, Knut Reinert & Freie Universitaet Berlin\n+// Copyright (c) 2016-2018, Knut Reinert & MPI Molekulare Genetik\n+// All rights reserved.\n+//\n+// Redistribution and use in source and binary forms, with or without\n+// modification, are permitted provided that the following conditions are met:\n+//\n+//     * Redistributions of source code must retain the above copyright\n+//       notice, this list of conditions and the following disclaimer.\n+//     * Redistributions in binary form must reproduce the above copyright\n+//       notice, this list of conditions and the following disclaimer in the\n+//       documentation and/or other materials provided with the distribution.\n+//     * Neither the name of Knut Reinert or the FU Berlin nor the names of\n+//       its contributors may be used to endorse or promote products derived\n+//       from this software without specific prior written permission.\n+//\n+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE\n+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\n+// DAMAGE.\n+//\n+// ============================================================================\n+\n+/*!\\file\n+ * \\brief Provides seqan3::sequence_file_in and corresponding traits classes.\n+ * \\author Hannes Hauswedell <hannes.hauswedell AT fu-berlin.de>\n+ */\n+\n #pragma once\n \n+#include <cassert>\n+#include <fstream>\n #include <string>\n #include <variant>\n #include <vector>\n \n-#if 0\n-//TODO(rrahn): this is a prototype and needs more refinement, disabling for now\n-//!\\cond\n+#include <range/v3/algorithm/equal.hpp>\n+\n+#include <seqan3/alphabet/adaptation/char.hpp>\n+#include <seqan3/alphabet/nucleotide/all.hpp>\n+#include <seqan3/alphabet/aminoacid/aa27.hpp>\n+#include <seqan3/alphabet/quality/illumina18.hpp>\n+#include <seqan3/alphabet/quality/quality_composition.hpp>\n+#include <seqan3/core/metafunction/basic.hpp>\n+#include <seqan3/io/concept.hpp>\n+#include <seqan3/io/filesystem.hpp>\n+#include <seqan3/io/exception.hpp>\n+#include <seqan3/io/record.hpp>\n+#include <seqan3/io/detail/record.hpp>\n+#include <seqan3/io/detail/in_file_iterator.hpp>\n+#include <seqan3/io/sequence/sequence_file_format_concept.hpp>\n+#include <seqan3/io/sequence/sequence_file_format_fasta.hpp>\n+#include <seqan3/range/container/concatenated_sequences.hpp>\n \n namespace seqan3\n {\n \n-// ==================================================================\n-// sequence_file_in_traits\n-// ==================================================================\n+// ----------------------------------------------------------------------------\n+// sequence_file_in_traits_concept\n+// ----------------------------------------------------------------------------\n \n+/*!\\interface seqan3::sequence_file_in_traits_concept <>\n+ * \\brief The requirements a traits_type for seqan3::sequence_file_in must meet.\n+ * \\ingroup sequence\n+ */\n+/*!\\name Requirements for seqan3::sequence_file_in_traits_concept\n+ * \\brief You can expect these **member types** of all types that satisfy seqan3::sequence_file_in_traits_concept.\n+ * \\memberof seqan3::sequence_file_in_traits_concept\n+ *\n+ * \\details\n+ *\n+ * Note that the alphabet type of the seqan3::field::SEQ_QUAL cannot be specified directly, it is always\n+ * seqan3::qualified<sequence_alphabet, quality_alphabet> and the container type templates for\n+ * the field are those of seqan3::field::SEQ.\n+ *\n+ * \\{\n+ */\n+/*!\\typedef using sequence_alphabet\n+ * \\memberof seqan3::sequence_file_in_traits_concept\n+ * \\brief Alphabet of the characters for the seqan3::field::SEQ; must satisfy seqan3::alphabet_concept.\n+ */\n+/*!\\typedef using sequence_legal_alphabet\n+ * \\memberof seqan3::sequence_file_in_traits_concept\n+ * \\brief Intermediate alphabet for seqan3::field::SEQ; must satisfy seqan3::alphabet_concept and be convertible to\n+ * `sequence_alphabet`.\n+ *\n+ * \\details\n+ *\n+ * This alphabet can be a superset of `sequence_alphabet` to allow conversion of some characters\n+ * without producing an error, e.g. if this is set to seqan3::dna15 and `sequence_alphabet` is set to seqan3::dna5,\n+ * 'M' will be an accepted character and automatically converted to 'N', while 'Z' will still be an illegal\n+ * character and produce an error.\n+ */\n+/*!\\typedef using sequence_container\n+ * \\memberof seqan3::sequence_file_in_traits_concept\n+ * \\brief Type template of the seqan3::field::SEQ, a container template over `sequence_alphabet`;\n+ * must satisfy seqan3::sequence_concept.\n+ */\n+/*!\\typedef using sequence_container_container\n+ * \\memberof seqan3::sequence_file_in_traits_concept\n+ * \\brief Type template of a column of seqan3::field::SEQ, a container template that can hold multiple\n+ * `sequence_container`; must satisfy seqan3::sequence_concept.\n+ */\n+/*!\\typedef using id_alphabet\n+ * \\memberof seqan3::sequence_file_in_traits_concept\n+ * \\brief Alphabet of the characters for the seqan3::field::ID; must satisfy seqan3::alphabet_concept.\n+ */\n+/*!\\typedef using id_container\n+ * \\memberof seqan3::sequence_file_in_traits_concept\n+ * \\brief Type template of the seqan3::field::ID, a container template over `id_alphabet`;\n+ * must satisfy seqan3::sequence_concept.\n+ */\n+/*!\\typedef using id_container_container\n+ * \\memberof seqan3::sequence_file_in_traits_concept\n+ * \\brief Type template of a column of seqan3::field::ID, a container template that can hold multiple\n+ * `id_container`; must satisfy seqan3::sequence_concept.\n+ */\n+/*!\\typedef using quality_alphabet\n+ * \\memberof seqan3::sequence_file_in_traits_concept\n+ * \\brief Alphabet of the characters for the seqan3::field::QUAL; must satisfy seqan3::quality_concept.\n+ */\n+/*!\\typedef using quality_container\n+ * \\memberof seqan3::sequence_file_in_traits_concept\n+ * \\brief Type template of the seqan3::field::QUAL, a container template over `quality_alphabet`;\n+ * must satisfy seqan3::sequence_concept.\n+ */\n+/*!\\typedef using quality_container_container\n+ * \\memberof seqan3::sequence_file_in_traits_concept\n+ * \\brief Type template of a column of seqan3::field::QUAL, a container template that can hold multiple\n+ * `quality_container`; must satisfy seqan3::sequence_concept.\n+ */\n+//!\\}\n+//!\\cond\n template <typename t>\n concept bool sequence_file_in_traits_concept = requires (t v)\n {\n-    t::stream_type;\n-    t::valid_formats;\n-    requires detail::meets_concept_sequence_file_format<0, typename t::valid_formats>();\n+    requires alphabet_concept<typename t::sequence_alphabet>;\n+    requires alphabet_concept<typename t::sequence_legal_alphabet>;\n+    requires sequence_concept<typename t::template sequence_container<typename t::sequence_alphabet>>;\n+    requires sequence_concept<typename t::template sequence_container_container<\n+        typename t::template sequence_container<typename t::sequence_alphabet>>>;\n+\n+    requires alphabet_concept<typename t::id_alphabet>;\n+    requires sequence_concept<typename t::template id_container<typename t::id_alphabet>>;\n+    requires sequence_concept<typename t::template id_container_container<typename t::template id_container<\n+        typename t::id_alphabet>>>;\n \n-    t::valid_compression_formats;\n+    requires quality_concept<typename t::quality_alphabet>;\n+    requires sequence_concept<typename t::template quality_container<typename t::quality_alphabet>>;\n+    requires sequence_concept<typename t::template quality_container_container<\n+        typename t::template quality_container<typename t::quality_alphabet>>>;\n };\n+//!\\endcond\n+\n+// ----------------------------------------------------------------------------\n+// sequence_file_in_default_traits\n+// ----------------------------------------------------------------------------\n \n-struct sequence_file_in_default_traits\n+/*!\\brief The default traits for seqan3::sequence_file_in\n+ * \\implements sequence_file_in_traits_concept\n+ * \\ingroup sequence\n+ *\n+ * \\details\n+ *\n+ * If you wish to change a single or a few types from the default, just inherit from this class and\n+ * \"overwrite\" the respective type definitions.\n+ *\n+ * This example will make the file read into a smaller alphabet and a compressed container:\n+ *\n+ * ```cpp\n+ * struct my_traits : sequence_file_in_default_traits_dna\n+ * {\n+ *     using sequence_alphabet = dna4;                        // instead of dna5\n+ *\n+ *     template <typename alph>\n+ *     using sequence_container = bitcompressed_vector<alph>; // must be defined as a template!\n+ * };\n+ *\n+ * sequence_file_in<my_traits> fin{\"/tmp/my.fasta\"};\n+ *\n+ * //...\n+ * ```\n+ */\n+struct sequence_file_in_default_traits_dna\n {\n-    using stream_type = std::ofstream;\n-    using valid_formats = std::variant<sequence_file_format_fasta<stream_type>,\n-                                       sequence_file_format_fastq<stream_type>,\n-                                       sequence_file_format_embl<stream_type>,\n-                                       sequence_file_format_genbank<stream_type>,\n-                                       sequence_file_format_raw<stream_type>>;\n-    static constexpr std::vector<std::pair<std::string, void>> valid_compression_formats{};\n+    /*!\\name Member types\n+     * \\brief Definitions to satisfy seqan3::sequence_file_in_traits_concept.\n+     * \\{\n+     */\n+    using sequence_alphabet                 = dna5;\n+    using sequence_legal_alphabet           = dna15;\n+    template <typename _sequence_alphabet>\n+    using sequence_container                = std::vector<_sequence_alphabet>;\n+    template <typename _sequence_container>\n+    using sequence_container_container      = concatenated_sequences<_sequence_container>;\n+\n+    using id_alphabet                       = char;\n+    template <typename _id_alphabet>\n+    using id_container                      = std::basic_string<_id_alphabet>;\n+    template <typename _id_container>\n+    using id_container_container            = concatenated_sequences<_id_container>;\n+\n+    using quality_alphabet                  = illumina18;\n+    template <typename _quality_alphabet>\n+    using quality_container                 = std::vector<_quality_alphabet>;\n+    template <typename _quality_container>\n+    using quality_container_container       = concatenated_sequences<_quality_container>;\n+    //!\\}\n };\n \n-// ==================================================================\n+//!\\brief A traits type that specifies input as amino acids.\n+//!\\ingroup sequence\n+struct sequence_file_in_default_traits_aa : sequence_file_in_default_traits_dna\n+{\n+    /*!\\name Member types\n+     * \\brief Definitions to satisfy seqan3::sequence_file_in_traits_concept.\n+     * \\{\n+     */\n+    using sequence_alphabet = aa27;\n+    using sequence_legal_alphabet = aa27;\n+    //!\\}\n+};\n+\n+// ----------------------------------------------------------------------------\n // sequence_file_in\n-// ==================================================================\n+// ----------------------------------------------------------------------------\n+\n+/*!\\brief A class for reading sequence files, e.g. FASTA, FASTQ ...\n+ * \\ingroup sequence\n+ * \\tparam traits_type An auxiliary type that defines certain member type and constants, must satisfy\n+ * seqan3::sequence_file_in_traits_concept.\n+ * \\tparam stream_type The type of the stream, must satisfy seqan3::istream_concept.\n+ * \\tparam selected_field_ids A \\ref fields type with the list and order of desired record entries; all fields\n+ * must be in \\ref field_ids.\n+ *\n+ * \\details\n+ *\n+ * ### Introduction\n+ *\n+ * Sequence files are the most generic and common biological files. Well-known formats include\n+ * FastA and FastQ, but some may also be interested in treating SAM or BAM files as sequence\n+ * files, discarding the alignment.\n+ *\n+ * The Sequence file abstraction supports reading four different fields:\n+ *\n+ *   1. seqan3::field::SEQ\n+ *   2. seqan3::field::ID\n+ *   3. seqan3::field::QUAL\n+ *   4. seqan3::field::SEQ_QUAL (sequence and qualities in one range)\n+ *\n+ * The first three fields are retrieved by default (and in that order). The last field may be selected to have\n+ * sequence and qualities directly stored in a more memory-efficient combined container. If you select the last\n+ * field you may not select seqan3::field::SEQ or seqan3::field::QUAL for obvious reasons.\n+ *\n+ * ### Construction and specialisation\n+ *\n+ * This class comes with two constructors, one for construction from a file name and one for construction from\n+ * an existing stream and a known format. The first one automatically picks the format based on the extension\n+ * of the file name. The second can be used if you have a non-file stream, like std::cin or std::istringstream,\n+ * that you want to read from and/or if you cannot use file-extension based detection, but know that your input\n+ * file has a certain format.\n+ *\n+ * In most cases the template parameters are deduced completely automatically:\n+ *\n+ * ```cpp\n+ * sequence_file_in fin{\"/tmp/my.fasta\"}; // FastA with DNA sequences assumed, regular std::ifstream taken as stream\n+ * ```\n+ * Reading from an std::istringstream:\n+ * ```cpp\n+ * std::string input\n+ * {\n+ *     \"> TEST1\\n\"\n+ *     \"ACGT\\n\"\n+ *     \"> Test2\\n\"\n+ *     \"AGGCTGN\\n\"\n+ *     \"> Test3\\n\"\n+ *     \"GGAGTATAATATATATATATATAT\\n\"\n+ * };\n+ *\n+ * std::istringstream iss(input);\n+ *\n+ * sequence_file_in fin{std::move(iss), sequence_file_format_fasta{}};\n+ * //              ^ no need to specify the template arguments\n+ * ```\n+ *\n+ * Note that this is not the same as writing `sequence_file_in<>` (with angle brackets). In the latter case they are\n+ * explicitly set to their default values, in the former case\n+ * [automatic deduction](http://en.cppreference.com/w/cpp/language/class_template_argument_deduction) happens which\n+ * chooses different parameters depending on the constructor arguments. For opening from file, `sequence_file_in<>`\n+ * would have also worked, but for opening from stream it would not have.\n+ *\n+ * In some cases, you do need to specify the arguments, e.g. if you want to read amino acids:\n+ *\n+ * ```cpp\n+ * sequence_file_in<seqeuence_file_default_traits_aa> fin{\"/tmp/my.fasta\"};\n+ * ```\n+ *\n+ * You can define your own traits type to further customise the types used by and returned by this class, see\n+ * seqan3::seqeuence_file_default_traits_dna for more details. As mentioned above, specifying at least one\n+ * template parameter yourself means that you loose automatic deduction so if you want to read amino acids **and**\n+ * want to read from a string stream you need to give all types yourself:\n+ *\n+ * ```cpp\n+ *\n+ *  // ... input had amino acid sequences\n+ * std::istringstream iss(input);\n+ *\n+ * sequence_file_in<seqeuence_file_default_traits_aa,\n+ *                  fields<field::SEQ, field::ID, field::QUAL>,\n+ *                  type_list<sequence_file_format_fasta>,\n+ *                  std::istringstream> fin{std::move(iss), sequence_file_format_fasta{}};\n+ * ```\n+ *\n+ * ### Reading record-wise\n+ *\n+ * You can iterate over this file record-wise:\n+ *\n+ * ```cpp\n+ * sequence_file_in fin{\"/tmp/my.fasta\"};\n+ *\n+ * for (auto & rec : fin)\n+ * {\n+ *     std::cout << \"ID:  \" << get<field::ID>(rec) << '\\n';\n+ *     std::cout << \"SEQ: \" << (get<field::SEQ>(rec) | view::to_char) << '\\n'; // sequence is converted to char on-the-fly\n+ * }\n+ * ```\n+ *\n+ * In the above example, rec has the type \\ref record_type which is a specialisation of seqan3::record and behaves\n+ * like an std::tuple (that's why we can access it via get). Instead of using the seqan3::field based interface on\n+ * the record, you could also use `std::get<0>` or even `std::get<dna4_vector>` to retrieve the sequence, but it is\n+ * not recommended, because it is more error-prone.\n+ *\n+ * *Note:* It is important to write `auto &` and not just `auto`, otherwise you will copy the record on every iteration.\n+ * Since the buffer gets \"refilled\" on every iteration, you can also move the data out of the record if you want\n+ * to store it somewhere without copying:\n+ *\n+ * ```cpp\n+ * sequence_file_in fin{\"/tmp/my.fasta\"};\n+ *\n+ * using record_type = typename decltype(fin)::record_type;\n+ * std::vector<record_type> records;\n+ *\n+ * for (auto & rec : fin)\n+ *     records.push_back(std::move(rec));\n+ * ```\n+ *\n+ * ### Reading record-wise (decomposed records)\n+ *\n+ * Instead of using `get` on the record, you can also use\n+ * [structured bindings](http://en.cppreference.com/w/cpp/language/structured_binding)\n+ * to decompose the record into its elements:\n+ *\n+ * ```cpp\n+ * sequence_file_in fin{\"/tmp/my.fasta\"};\n+ *\n+ * for (auto & [ seq, id ] : fin)\n+ * {\n+ *     std::cout << \"ID:  \" << id << '\\n';\n+ *     std::cout << \"SEQ: \" << (seq | view::to_char) << '\\n'; // sequence is converted to char on-the-fly\n+ * }\n+ * ```\n+ *\n+ * In this case you immediately get the two elements of the tuple: `seq` of \\ref sequence_type and `id` of\n+ * \\ref id_type. **But beware: with structured bindings you do need to get the order of elements correctly!**\n+ *\n+ * ### Reading record-wise (custom fields)\n+ *\n+ * If you don't wish to extract certain fields from the record, you can just choose not do so, however it may be more\n+ * efficient to tell the sequence_file to never actually read them. Or you may want to choose a combined field for SEQ\n+ * and QUAL (see above). You can do so by setting the fields (template) parameter:\n+ *\n+ * ```cpp\n+ * sequence_file_in fin{\"/tmp/my.fasta\", fields<field::ID, field::SEQ_QUAL>{}};\n+ *\n+ * for (auto & [ id, seq_qual ] : fin) // note that the order is now different, \"id\" comes first\n+ * {\n+ *     std::cout << \"ID:  \" << id << '\\n';\n+ *     // sequence and qualities are part of the same vector, of type std::vector<dna5q>\n+ *     std::cout << \"SEQ: \"  << (seq | view::get<0> | view::to_char) << '\\n'; // sequence string is extracted and converted to char  on-the-fly\n+ *     std::cout << \"QUAL: \" << (seq | view::get<1> | view::to_char) << '\\n'; // quality string is extracted and converted to char  on-the-fly\n+ * }\n+ * ```\n+ *\n+ * When reading a file, all fields not present in the file (but requested implicitly or via the `selected_field_ids`\n+ * parameter) are ignored.\n+ *\n+ * ### Views on files\n+ *\n+ * Since SeqAn files are ranges, you can also create views over files. A useful example is to filter the records\n+ * based on certain criteria, e.g. minimum length of the sequence field:\n+ *\n+ * ```cpp\n+ * sequence_file_in fin{\"/tmp/my.fasta\"};\n+ *\n+ * auto minimum_length5_filter = ranges::view::filter([] (auto const & rec)\n+ * {\n+ *     return size(get<field::SEQ>(rec)) >= 5;\n+ * });\n+ *\n+ * for (auto & rec : fin | minimum_length5_filter) // only record with sequence length >= 5 will \"appear\"\n+ * {\n+ *     // ...\n+ * }\n+ * ```\n+ *\n+ * ### End of file\n+ *\n+ * You can check whether a file is at end by comparing begin() and end() (if they are the same, the file is at end).\n+ *\n+ * ### Column-based reading\n+ *\n+ * The record-based interface treats the file as a range of tuples (the records), but in certain situations it\n+ * is desirable to read the file by field, i.e. column wise (tuple-of-ranges, instead of range-of-tuples).\n+ *\n+ * This interface is less flexible, but can save you copy operations in certain scenarios:\n+ *\n+ * ```cpp\n+ *\n+ * struct data_storage_t\n+ * {\n+ *     concatenated_sequences<dna5_vector>  sequences;\n+ *     concatenated_sequences<std::string>  ids;\n+ * };\n+ *\n+ * data_storage_t data_storage; // a global or globally used variable in your program\n+ *\n+ * // ... in your file reading function:\n+ *\n+ * sequence_file_in fin{\"/tmp/my.fasta\"};\n+ *\n+ * data_storage.sequences = std::move(get<field::SEQ>(fin)); // we move the buffer directly into our storage\n+ * data_storage.ids = std::move(get<field::ID>(fin)); // we move the buffer directly into our storage\n+ * ```\n+ *\n+ * Note that for this to make sense, your storage data types need to be identical to the corresponding column types\n+ * of the file. If you require different column types you can specify you own traits, see\n+ * seqan3::sequence_file_in_traits_concept.\n+ *\n+ * ### Formats\n+ *\n+ * TODO give overview of formats, once they are all implemented\n+ */\n \n-template <typename sequence_file_in_traits = sequence_file_in_traits_default>\n-    requires sequence_file_in_traits_concept<sequence_file_in_traits>\n+template <sequence_file_in_traits_concept                    traits_type_        = sequence_file_in_default_traits_dna,\n+          detail::fields_concept                             selected_field_ids_ = fields<field::SEQ,","path":"include/seqan3/io/sequence/sequence_file_in.hpp","position":478,"original_position":478,"commit_id":"9f7202b86663c9ff75c3920faa6a2841b73600f2","original_commit_id":"9f7202b86663c9ff75c3920faa6a2841b73600f2","user":{"login":"h-2","id":2996863,"avatar_url":"https://avatars2.githubusercontent.com/u/2996863?v=4","gravatar_id":"","url":"https://api.github.com/users/h-2","html_url":"https://github.com/h-2","followers_url":"https://api.github.com/users/h-2/followers","following_url":"https://api.github.com/users/h-2/following{/other_user}","gists_url":"https://api.github.com/users/h-2/gists{/gist_id}","starred_url":"https://api.github.com/users/h-2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/h-2/subscriptions","organizations_url":"https://api.github.com/users/h-2/orgs","repos_url":"https://api.github.com/users/h-2/repos","events_url":"https://api.github.com/users/h-2/events{/privacy}","received_events_url":"https://api.github.com/users/h-2/received_events","type":"User","site_admin":false},"body":"These don't really appear in the doc in any meaningful way and the verbose requirements are actuallly stated so I would prefer to keep them in detail.","created_at":"2018-04-16T11:28:19Z","updated_at":"2018-04-16T11:28:20Z","html_url":"https://github.com/seqan/seqan3/pull/225#discussion_r181702068","pull_request_url":"https://api.github.com/repos/seqan/seqan3/pulls/225","author_association":"OWNER","_links":{"self":{"href":"https://api.github.com/repos/seqan/seqan3/pulls/comments/181702068"},"html":{"href":"https://github.com/seqan/seqan3/pull/225#discussion_r181702068"},"pull_request":{"href":"https://api.github.com/repos/seqan/seqan3/pulls/225"}},"in_reply_to_id":181388853},"pull_request":{"url":"https://api.github.com/repos/seqan/seqan3/pulls/225","id":178407789,"html_url":"https://github.com/seqan/seqan3/pull/225","diff_url":"https://github.com/seqan/seqan3/pull/225.diff","patch_url":"https://github.com/seqan/seqan3/pull/225.patch","issue_url":"https://api.github.com/repos/seqan/seqan3/issues/225","number":225,"state":"open","locked":false,"title":"sequence io","user":{"login":"h-2","id":2996863,"avatar_url":"https://avatars2.githubusercontent.com/u/2996863?v=4","gravatar_id":"","url":"https://api.github.com/users/h-2","html_url":"https://github.com/h-2","followers_url":"https://api.github.com/users/h-2/followers","following_url":"https://api.github.com/users/h-2/following{/other_user}","gists_url":"https://api.github.com/users/h-2/gists{/gist_id}","starred_url":"https://api.github.com/users/h-2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/h-2/subscriptions","organizations_url":"https://api.github.com/users/h-2/orgs","repos_url":"https://api.github.com/users/h-2/repos","events_url":"https://api.github.com/users/h-2/events{/privacy}","received_events_url":"https://api.github.com/users/h-2/received_events","type":"User","site_admin":false},"body":"supersedes #183 ","created_at":"2018-03-29T18:36:06Z","updated_at":"2018-04-16T11:28:20Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3c58d837f3b1c24aac195ad2d5c37ec633fabc4a","assignee":{"login":"rrahn","id":1529364,"avatar_url":"https://avatars2.githubusercontent.com/u/1529364?v=4","gravatar_id":"","url":"https://api.github.com/users/rrahn","html_url":"https://github.com/rrahn","followers_url":"https://api.github.com/users/rrahn/followers","following_url":"https://api.github.com/users/rrahn/following{/other_user}","gists_url":"https://api.github.com/users/rrahn/gists{/gist_id}","starred_url":"https://api.github.com/users/rrahn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rrahn/subscriptions","organizations_url":"https://api.github.com/users/rrahn/orgs","repos_url":"https://api.github.com/users/rrahn/repos","events_url":"https://api.github.com/users/rrahn/events{/privacy}","received_events_url":"https://api.github.com/users/rrahn/received_events","type":"User","site_admin":false},"assignees":[{"login":"rrahn","id":1529364,"avatar_url":"https://avatars2.githubusercontent.com/u/1529364?v=4","gravatar_id":"","url":"https://api.github.com/users/rrahn","html_url":"https://github.com/rrahn","followers_url":"https://api.github.com/users/rrahn/followers","following_url":"https://api.github.com/users/rrahn/following{/other_user}","gists_url":"https://api.github.com/users/rrahn/gists{/gist_id}","starred_url":"https://api.github.com/users/rrahn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rrahn/subscriptions","organizations_url":"https://api.github.com/users/rrahn/orgs","repos_url":"https://api.github.com/users/rrahn/repos","events_url":"https://api.github.com/users/rrahn/events{/privacy}","received_events_url":"https://api.github.com/users/rrahn/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"smehringer","id":7955878,"avatar_url":"https://avatars3.githubusercontent.com/u/7955878?v=4","gravatar_id":"","url":"https://api.github.com/users/smehringer","html_url":"https://github.com/smehringer","followers_url":"https://api.github.com/users/smehringer/followers","following_url":"https://api.github.com/users/smehringer/following{/other_user}","gists_url":"https://api.github.com/users/smehringer/gists{/gist_id}","starred_url":"https://api.github.com/users/smehringer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/smehringer/subscriptions","organizations_url":"https://api.github.com/users/smehringer/orgs","repos_url":"https://api.github.com/users/smehringer/repos","events_url":"https://api.github.com/users/smehringer/events{/privacy}","received_events_url":"https://api.github.com/users/smehringer/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":{"url":"https://api.github.com/repos/seqan/seqan3/milestones/7","html_url":"https://github.com/seqan/seqan3/milestone/7","labels_url":"https://api.github.com/repos/seqan/seqan3/milestones/7/labels","id":3212936,"number":7,"title":"Feature Pre-release (June)","description":"","creator":{"login":"h-2","id":2996863,"avatar_url":"https://avatars2.githubusercontent.com/u/2996863?v=4","gravatar_id":"","url":"https://api.github.com/users/h-2","html_url":"https://github.com/h-2","followers_url":"https://api.github.com/users/h-2/followers","following_url":"https://api.github.com/users/h-2/following{/other_user}","gists_url":"https://api.github.com/users/h-2/gists{/gist_id}","starred_url":"https://api.github.com/users/h-2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/h-2/subscriptions","organizations_url":"https://api.github.com/users/h-2/orgs","repos_url":"https://api.github.com/users/h-2/repos","events_url":"https://api.github.com/users/h-2/events{/privacy}","received_events_url":"https://api.github.com/users/h-2/received_events","type":"User","site_admin":false},"open_issues":7,"closed_issues":0,"state":"open","created_at":"2018-03-23T17:42:49Z","updated_at":"2018-04-12T18:16:06Z","due_on":"2018-06-14T07:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/seqan/seqan3/pulls/225/commits","review_comments_url":"https://api.github.com/repos/seqan/seqan3/pulls/225/comments","review_comment_url":"https://api.github.com/repos/seqan/seqan3/pulls/comments{/number}","comments_url":"https://api.github.com/repos/seqan/seqan3/issues/225/comments","statuses_url":"https://api.github.com/repos/seqan/seqan3/statuses/9f7202b86663c9ff75c3920faa6a2841b73600f2","head":{"label":"h-2:feature/sequence_io2","ref":"feature/sequence_io2","sha":"9f7202b86663c9ff75c3920faa6a2841b73600f2","user":{"login":"h-2","id":2996863,"avatar_url":"https://avatars2.githubusercontent.com/u/2996863?v=4","gravatar_id":"","url":"https://api.github.com/users/h-2","html_url":"https://github.com/h-2","followers_url":"https://api.github.com/users/h-2/followers","following_url":"https://api.github.com/users/h-2/following{/other_user}","gists_url":"https://api.github.com/users/h-2/gists{/gist_id}","starred_url":"https://api.github.com/users/h-2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/h-2/subscriptions","organizations_url":"https://api.github.com/users/h-2/orgs","repos_url":"https://api.github.com/users/h-2/repos","events_url":"https://api.github.com/users/h-2/events{/privacy}","received_events_url":"https://api.github.com/users/h-2/received_events","type":"User","site_admin":false},"repo":{"id":86586114,"name":"seqan3","full_name":"h-2/seqan3","owner":{"login":"h-2","id":2996863,"avatar_url":"https://avatars2.githubusercontent.com/u/2996863?v=4","gravatar_id":"","url":"https://api.github.com/users/h-2","html_url":"https://github.com/h-2","followers_url":"https://api.github.com/users/h-2/followers","following_url":"https://api.github.com/users/h-2/following{/other_user}","gists_url":"https://api.github.com/users/h-2/gists{/gist_id}","starred_url":"https://api.github.com/users/h-2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/h-2/subscriptions","organizations_url":"https://api.github.com/users/h-2/orgs","repos_url":"https://api.github.com/users/h-2/repos","events_url":"https://api.github.com/users/h-2/events{/privacy}","received_events_url":"https://api.github.com/users/h-2/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/h-2/seqan3","description":"The modern C++ library for sequence analysis. Contains version 3 of the library and API docs.","fork":true,"url":"https://api.github.com/repos/h-2/seqan3","forks_url":"https://api.github.com/repos/h-2/seqan3/forks","keys_url":"https://api.github.com/repos/h-2/seqan3/keys{/key_id}","collaborators_url":"https://api.github.com/repos/h-2/seqan3/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/h-2/seqan3/teams","hooks_url":"https://api.github.com/repos/h-2/seqan3/hooks","issue_events_url":"https://api.github.com/repos/h-2/seqan3/issues/events{/number}","events_url":"https://api.github.com/repos/h-2/seqan3/events","assignees_url":"https://api.github.com/repos/h-2/seqan3/assignees{/user}","branches_url":"https://api.github.com/repos/h-2/seqan3/branches{/branch}","tags_url":"https://api.github.com/repos/h-2/seqan3/tags","blobs_url":"https://api.github.com/repos/h-2/seqan3/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/h-2/seqan3/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/h-2/seqan3/git/refs{/sha}","trees_url":"https://api.github.com/repos/h-2/seqan3/git/trees{/sha}","statuses_url":"https://api.github.com/repos/h-2/seqan3/statuses/{sha}","languages_url":"https://api.github.com/repos/h-2/seqan3/languages","stargazers_url":"https://api.github.com/repos/h-2/seqan3/stargazers","contributors_url":"https://api.github.com/repos/h-2/seqan3/contributors","subscribers_url":"https://api.github.com/repos/h-2/seqan3/subscribers","subscription_url":"https://api.github.com/repos/h-2/seqan3/subscription","commits_url":"https://api.github.com/repos/h-2/seqan3/commits{/sha}","git_commits_url":"https://api.github.com/repos/h-2/seqan3/git/commits{/sha}","comments_url":"https://api.github.com/repos/h-2/seqan3/comments{/number}","issue_comment_url":"https://api.github.com/repos/h-2/seqan3/issues/comments{/number}","contents_url":"https://api.github.com/repos/h-2/seqan3/contents/{+path}","compare_url":"https://api.github.com/repos/h-2/seqan3/compare/{base}...{head}","merges_url":"https://api.github.com/repos/h-2/seqan3/merges","archive_url":"https://api.github.com/repos/h-2/seqan3/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/h-2/seqan3/downloads","issues_url":"https://api.github.com/repos/h-2/seqan3/issues{/number}","pulls_url":"https://api.github.com/repos/h-2/seqan3/pulls{/number}","milestones_url":"https://api.github.com/repos/h-2/seqan3/milestones{/number}","notifications_url":"https://api.github.com/repos/h-2/seqan3/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/h-2/seqan3/labels{/name}","releases_url":"https://api.github.com/repos/h-2/seqan3/releases{/id}","deployments_url":"https://api.github.com/repos/h-2/seqan3/deployments","created_at":"2017-03-29T13:34:49Z","updated_at":"2018-04-15T07:31:58Z","pushed_at":"2018-04-12T12:54:07Z","git_url":"git://github.com/h-2/seqan3.git","ssh_url":"git@github.com:h-2/seqan3.git","clone_url":"https://github.com/h-2/seqan3.git","svn_url":"https://github.com/h-2/seqan3","homepage":"http://www.seqan.de","size":814,"stargazers_count":1,"watchers_count":1,"language":"C++","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"seqan:master","ref":"master","sha":"add94a8d80f4001a0ab8ee7908bbb0739ea62f23","user":{"login":"seqan","id":1752144,"avatar_url":"https://avatars2.githubusercontent.com/u/1752144?v=4","gravatar_id":"","url":"https://api.github.com/users/seqan","html_url":"https://github.com/seqan","followers_url":"https://api.github.com/users/seqan/followers","following_url":"https://api.github.com/users/seqan/following{/other_user}","gists_url":"https://api.github.com/users/seqan/gists{/gist_id}","starred_url":"https://api.github.com/users/seqan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seqan/subscriptions","organizations_url":"https://api.github.com/users/seqan/orgs","repos_url":"https://api.github.com/users/seqan/repos","events_url":"https://api.github.com/users/seqan/events{/privacy}","received_events_url":"https://api.github.com/users/seqan/received_events","type":"Organization","site_admin":false},"repo":{"id":55410078,"name":"seqan3","full_name":"seqan/seqan3","owner":{"login":"seqan","id":1752144,"avatar_url":"https://avatars2.githubusercontent.com/u/1752144?v=4","gravatar_id":"","url":"https://api.github.com/users/seqan","html_url":"https://github.com/seqan","followers_url":"https://api.github.com/users/seqan/followers","following_url":"https://api.github.com/users/seqan/following{/other_user}","gists_url":"https://api.github.com/users/seqan/gists{/gist_id}","starred_url":"https://api.github.com/users/seqan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seqan/subscriptions","organizations_url":"https://api.github.com/users/seqan/orgs","repos_url":"https://api.github.com/users/seqan/repos","events_url":"https://api.github.com/users/seqan/events{/privacy}","received_events_url":"https://api.github.com/users/seqan/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/seqan/seqan3","description":"The modern C++ library for sequence analysis. Contains version 3 of the library and API docs.","fork":false,"url":"https://api.github.com/repos/seqan/seqan3","forks_url":"https://api.github.com/repos/seqan/seqan3/forks","keys_url":"https://api.github.com/repos/seqan/seqan3/keys{/key_id}","collaborators_url":"https://api.github.com/repos/seqan/seqan3/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/seqan/seqan3/teams","hooks_url":"https://api.github.com/repos/seqan/seqan3/hooks","issue_events_url":"https://api.github.com/repos/seqan/seqan3/issues/events{/number}","events_url":"https://api.github.com/repos/seqan/seqan3/events","assignees_url":"https://api.github.com/repos/seqan/seqan3/assignees{/user}","branches_url":"https://api.github.com/repos/seqan/seqan3/branches{/branch}","tags_url":"https://api.github.com/repos/seqan/seqan3/tags","blobs_url":"https://api.github.com/repos/seqan/seqan3/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/seqan/seqan3/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/seqan/seqan3/git/refs{/sha}","trees_url":"https://api.github.com/repos/seqan/seqan3/git/trees{/sha}","statuses_url":"https://api.github.com/repos/seqan/seqan3/statuses/{sha}","languages_url":"https://api.github.com/repos/seqan/seqan3/languages","stargazers_url":"https://api.github.com/repos/seqan/seqan3/stargazers","contributors_url":"https://api.github.com/repos/seqan/seqan3/contributors","subscribers_url":"https://api.github.com/repos/seqan/seqan3/subscribers","subscription_url":"https://api.github.com/repos/seqan/seqan3/subscription","commits_url":"https://api.github.com/repos/seqan/seqan3/commits{/sha}","git_commits_url":"https://api.github.com/repos/seqan/seqan3/git/commits{/sha}","comments_url":"https://api.github.com/repos/seqan/seqan3/comments{/number}","issue_comment_url":"https://api.github.com/repos/seqan/seqan3/issues/comments{/number}","contents_url":"https://api.github.com/repos/seqan/seqan3/contents/{+path}","compare_url":"https://api.github.com/repos/seqan/seqan3/compare/{base}...{head}","merges_url":"https://api.github.com/repos/seqan/seqan3/merges","archive_url":"https://api.github.com/repos/seqan/seqan3/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/seqan/seqan3/downloads","issues_url":"https://api.github.com/repos/seqan/seqan3/issues{/number}","pulls_url":"https://api.github.com/repos/seqan/seqan3/pulls{/number}","milestones_url":"https://api.github.com/repos/seqan/seqan3/milestones{/number}","notifications_url":"https://api.github.com/repos/seqan/seqan3/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/seqan/seqan3/labels{/name}","releases_url":"https://api.github.com/repos/seqan/seqan3/releases{/id}","deployments_url":"https://api.github.com/repos/seqan/seqan3/deployments","created_at":"2016-04-04T12:39:15Z","updated_at":"2018-04-12T18:21:04Z","pushed_at":"2018-04-12T19:36:45Z","git_url":"git://github.com/seqan/seqan3.git","ssh_url":"git@github.com:seqan/seqan3.git","clone_url":"https://github.com/seqan/seqan3.git","svn_url":"https://github.com/seqan/seqan3","homepage":"http://www.seqan.de","size":721,"stargazers_count":25,"watchers_count":25,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":22,"mirror_url":null,"archived":false,"open_issues_count":67,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":22,"open_issues":67,"watchers":25,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/seqan/seqan3/pulls/225"},"html":{"href":"https://github.com/seqan/seqan3/pull/225"},"issue":{"href":"https://api.github.com/repos/seqan/seqan3/issues/225"},"comments":{"href":"https://api.github.com/repos/seqan/seqan3/issues/225/comments"},"review_comments":{"href":"https://api.github.com/repos/seqan/seqan3/pulls/225/comments"},"review_comment":{"href":"https://api.github.com/repos/seqan/seqan3/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/seqan/seqan3/pulls/225/commits"},"statuses":{"href":"https://api.github.com/repos/seqan/seqan3/statuses/9f7202b86663c9ff75c3920faa6a2841b73600f2"}},"author_association":"OWNER"}}
{"actor":{"display_login":"h-2"}}