diff --git a/src/swcio.cpp b/src/swcio.cpp index f6a328956af2469a278b3be357f15bb239b1bd5e..98db848e2b4768d59399a3340c0d3611104fb4e9 100644 --- a/src/swcio.cpp +++ b/src/swcio.cpp @@ -11,9 +11,9 @@ namespace mc { namespace io { // -// cell_record implementation +// swc_record implementation // -void cell_record::renumber(id_type new_id, std::map<id_type, id_type> &idmap) +void swc_record::renumber(id_type new_id, std::map<id_type, id_type> &idmap) { auto old_id = id_; id_ = new_id; @@ -28,12 +28,12 @@ void cell_record::renumber(id_type new_id, std::map<id_type, id_type> &idmap) idmap.insert(std::make_pair(old_id, new_id)); } -void cell_record::check_consistency() const +void swc_record::check_consistency() const { - // Check cell type as well; enum's do not offer complete type safety, + // Check record type as well; enum's do not offer complete type safety, // since you can cast anything that fits to its underlying type if (type_ < 0 || type_ > custom) { - throw std::invalid_argument("unknown cell type"); + throw std::invalid_argument("unknown record type"); } if (id_ < 0) { @@ -53,24 +53,24 @@ void cell_record::check_consistency() const } } -std::istream &operator>>(std::istream &is, cell_record &cell) +std::istream &operator>>(std::istream &is, swc_record &record) { swc_parser parser; - parser.parse_record(is, cell); + parser.parse_record(is, record); return is; } -std::ostream &operator<<(std::ostream &os, const cell_record &cell) +std::ostream &operator<<(std::ostream &os, const swc_record &record) { // output in one-based indexing - os << cell.id_+1 << " " - << cell.type_ << " " - << std::setprecision(7) << cell.x_ << " " - << std::setprecision(7) << cell.y_ << " " - << std::setprecision(7) << cell.z_ << " " - << std::setprecision(7) << cell.r_ << " " - << ((cell.parent_id_ == -1) ? cell.parent_id_ : cell.parent_id_+1); + os << record.id_+1 << " " + << record.type_ << " " + << std::setprecision(7) << record.x_ << " " + << std::setprecision(7) << record.y_ << " " + << std::setprecision(7) << record.z_ << " " + << std::setprecision(7) << record.r_ << " " + << ((record.parent_id_ == -1) ? record.parent_id_ : record.parent_id_+1); return os; } @@ -103,22 +103,22 @@ T parse_value_strict(std::istream &is, const swc_parser &parser) return val; } -// specialize parsing for cell types +// specialize parsing for record types template<> -cell_record::kind parse_value_strict(std::istream &is, const swc_parser &parser) +swc_record::kind parse_value_strict(std::istream &is, const swc_parser &parser) { - cell_record::id_type val; + swc_record::id_type val; check_parse_status(is >> val, parser); - // Let cell_record's constructor check for the type validity - return static_cast<cell_record::kind>(val); + // Let swc_record's constructor check for the type validity + return static_cast<swc_record::kind>(val); } // // swc_parser implementation // -std::istream &swc_parser::parse_record(std::istream &is, cell_record &cell) +std::istream &swc_parser::parse_record(std::istream &is, swc_record &record) { while (!is.eof() && !is.bad()) { // consume empty and comment lines first @@ -145,7 +145,7 @@ std::istream &swc_parser::parse_record(std::istream &is, cell_record &cell) std::istringstream line(linebuff_); try { - cell = parse_record(line); + record = parse_record(line); } catch (std::invalid_argument &e) { // Rethrow as a parse error throw swc_parse_error(e.what(), lineno_); @@ -154,34 +154,34 @@ std::istream &swc_parser::parse_record(std::istream &is, cell_record &cell) return is; } -cell_record swc_parser::parse_record(std::istringstream &is) +swc_record swc_parser::parse_record(std::istringstream &is) { auto id = parse_value_strict<int>(is, *this); - auto type = parse_value_strict<cell_record::kind>(is, *this); + auto type = parse_value_strict<swc_record::kind>(is, *this); auto x = parse_value_strict<float>(is, *this); auto y = parse_value_strict<float>(is, *this); auto z = parse_value_strict<float>(is, *this); auto r = parse_value_strict<float>(is, *this); - auto parent_id = parse_value_strict<cell_record::id_type>(is, *this); + auto parent_id = parse_value_strict<swc_record::id_type>(is, *this); // Convert to zero-based, leaving parent_id as-is if -1 if (parent_id != -1) { parent_id--; } - return cell_record(type, id-1, x, y, z, r, parent_id); + return swc_record(type, id-1, x, y, z, r, parent_id); } -cell_record_range_clean::cell_record_range_clean(std::istream &is) +swc_record_range_clean::swc_record_range_clean(std::istream &is) { - std::unordered_set<cell_record::id_type> ids; + std::unordered_set<swc_record::id_type> ids; std::size_t num_trees = 0; - cell_record::id_type last_id = -1; + swc_record::id_type last_id = -1; bool needsort = false; - cell_record curr_cell; + swc_record curr_record; for (auto c : swc_get_records<swc_io_raw>(is)) { if (c.parent() == -1 && ++num_trees > 1) { // only a single tree is allowed @@ -190,8 +190,8 @@ cell_record_range_clean::cell_record_range_clean(std::istream &is) auto inserted = ids.insert(c.id()); if (inserted.second) { - // not a duplicate; insert cell - cells_.push_back(c); + // not a duplicate; insert record + records_.push_back(c); if (!needsort && c.id() < last_id) { needsort = true; } @@ -201,13 +201,13 @@ cell_record_range_clean::cell_record_range_clean(std::istream &is) } if (needsort) { - std::sort(cells_.begin(), cells_.end()); + std::sort(records_.begin(), records_.end()); } - // Renumber cells if necessary - std::map<cell_record::id_type, cell_record::id_type> idmap; - cell_record::id_type next_id = 0; - for (auto &c : cells_) { + // Renumber records if necessary + std::map<swc_record::id_type, swc_record::id_type> idmap; + swc_record::id_type next_id = 0; + for (auto &c : records_) { if (c.id() != next_id) { c.renumber(next_id, idmap); } diff --git a/src/swcio.hpp b/src/swcio.hpp index 45e83f741cb30455e9607bf82df5d97ced37f083..0486a2b511e7afcb13fbc13f7a5977fa4f4db6a4 100644 --- a/src/swcio.hpp +++ b/src/swcio.hpp @@ -10,7 +10,7 @@ namespace nest { namespace mc { namespace io { -class cell_record +class swc_record { public: using id_type = int; @@ -30,8 +30,8 @@ public: custom }; - // cell records assume zero-based indexing; root's parent remains -1 - cell_record(kind type, int id, + // swc records assume zero-based indexing; root's parent remains -1 + swc_record(kind type, int id, float x, float y, float z, float r, int parent_id) : type_(type) @@ -45,8 +45,8 @@ public: check_consistency(); } - cell_record() - : type_(cell_record::undefined) + swc_record() + : type_(swc_record::undefined) , id_(0) , x_(0) , y_(0) @@ -55,10 +55,10 @@ public: , parent_id_(-1) { } - cell_record(const cell_record &other) = default; - cell_record &operator=(const cell_record &other) = default; + swc_record(const swc_record &other) = default; + swc_record &operator=(const swc_record &other) = default; - bool strict_equals(const cell_record &other) const + bool strict_equals(const swc_record &other) const { return id_ == other.id_ && x_ == other.x_ && @@ -69,43 +69,43 @@ public: } // Equality and comparison operators - friend bool operator==(const cell_record &lhs, - const cell_record &rhs) + friend bool operator==(const swc_record &lhs, + const swc_record &rhs) { return lhs.id_ == rhs.id_; } - friend bool operator<(const cell_record &lhs, - const cell_record &rhs) + friend bool operator<(const swc_record &lhs, + const swc_record &rhs) { return lhs.id_ < rhs.id_; } - friend bool operator<=(const cell_record &lhs, - const cell_record &rhs) + friend bool operator<=(const swc_record &lhs, + const swc_record &rhs) { return (lhs < rhs) || (lhs == rhs); } - friend bool operator!=(const cell_record &lhs, - const cell_record &rhs) + friend bool operator!=(const swc_record &lhs, + const swc_record &rhs) { return !(lhs == rhs); } - friend bool operator>(const cell_record &lhs, - const cell_record &rhs) + friend bool operator>(const swc_record &lhs, + const swc_record &rhs) { return !(lhs < rhs) && (lhs != rhs); } - friend bool operator>=(const cell_record &lhs, - const cell_record &rhs) + friend bool operator>=(const swc_record &lhs, + const swc_record &rhs) { return !(lhs < rhs); } - friend std::ostream &operator<<(std::ostream &os, const cell_record &cell); + friend std::ostream &operator<<(std::ostream &os, const swc_record &record); kind type() const { @@ -152,11 +152,11 @@ public: private: void check_consistency() const; - kind type_; // cell type - id_type id_; // cell id - float x_, y_, z_; // cell coordinates - float r_; // cell radius - id_type parent_id_; // cell parent's id + kind type_; // record type + id_type id_; // record id + float x_, y_, z_; // record coordinates + float r_; // record radius + id_type parent_id_; // record parent's id }; @@ -203,11 +203,11 @@ public: return lineno_; } - std::istream &parse_record(std::istream &is, cell_record &cell); + std::istream &parse_record(std::istream &is, swc_record &record); private: // Read the record from a string stream; will be treated like a single line - cell_record parse_record(std::istringstream &is); + swc_record parse_record(std::istringstream &is); std::string delim_; std::string comment_prefix_; @@ -216,15 +216,15 @@ private: }; -std::istream &operator>>(std::istream &is, cell_record &cell); +std::istream &operator>>(std::istream &is, swc_record &record); -class cell_record_stream_iterator : - public std::iterator<std::forward_iterator_tag, cell_record> +class swc_record_stream_iterator : + public std::iterator<std::forward_iterator_tag, swc_record> { public: struct eof_tag { }; - cell_record_stream_iterator(std::istream &is) + swc_record_stream_iterator(std::istream &is) : is_(is) , eof_(false) { @@ -233,19 +233,19 @@ public: read_next_record(); } - cell_record_stream_iterator(std::istream &is, eof_tag) + swc_record_stream_iterator(std::istream &is, eof_tag) : is_(is) , eof_(true) { } - cell_record_stream_iterator(const cell_record_stream_iterator &other) + swc_record_stream_iterator(const swc_record_stream_iterator &other) : is_(other.is_) , parser_(other.parser_) , curr_record_(other.curr_record_) , eof_(other.eof_) { } - cell_record_stream_iterator &operator++() + swc_record_stream_iterator &operator++() { if (eof_) { throw std::out_of_range("attempt to read past eof"); @@ -255,14 +255,14 @@ public: return *this; } - cell_record_stream_iterator operator++(int) + swc_record_stream_iterator operator++(int) { - cell_record_stream_iterator ret(*this); + swc_record_stream_iterator ret(*this); operator++(); return ret; } - value_type operator*() + value_type operator*() const { if (eof_) { throw std::out_of_range("attempt to read past eof"); @@ -271,7 +271,7 @@ public: return curr_record_; } - bool operator==(const cell_record_stream_iterator &other) const + bool operator==(const swc_record_stream_iterator &other) const { if (eof_ && other.eof_) { return true; @@ -280,13 +280,13 @@ public: } } - bool operator!=(const cell_record_stream_iterator &other) + bool operator!=(const swc_record_stream_iterator &other) const { return !(*this == other); } friend std::ostream &operator<<(std::ostream &os, - const cell_record_stream_iterator &iter) + const swc_record_stream_iterator &iter) { os << "{ is_.tellg(): " << iter.is_.tellg() << ", " << "curr_record_: " << iter.curr_record_ << ", " @@ -306,7 +306,7 @@ private: std::istream &is_; swc_parser parser_; - cell_record curr_record_; + swc_record curr_record_; // indicator of eof; we need a way to define an end() iterator without // seeking to the end of file @@ -314,28 +314,33 @@ private: }; -class cell_record_range_raw +class swc_record_range_raw { public: - using value_type = cell_record; - using reference = value_type &; - using const_referene = const value_type &; - using iterator = cell_record_stream_iterator; - using const_iterator = const cell_record_stream_iterator; + using value_type = swc_record; + using reference = value_type &; + using const_reference = const value_type &; + using iterator = swc_record_stream_iterator; + using const_iterator = const swc_record_stream_iterator; - cell_record_range_raw(std::istream &is) + swc_record_range_raw(std::istream &is) : is_(is) { } - iterator begin() + iterator begin() const { - return cell_record_stream_iterator(is_); + return swc_record_stream_iterator(is_); } - iterator end() + iterator end() const { iterator::eof_tag eof; - return cell_record_stream_iterator(is_, eof); + return swc_record_stream_iterator(is_, eof); + } + + bool empty() const + { + return begin() == end(); } private: @@ -343,57 +348,62 @@ private: }; // -// Reads cells from an input stream until an eof is encountered and returns a -// cleaned sequence of cell records. +// Reads records from an input stream until an eof is encountered and returns a +// cleaned sequence of swc records. // // For more information check here: // https://github.com/eth-cscs/cell_algorithms/wiki/SWC-file-parsing // -class cell_record_range_clean +class swc_record_range_clean { public: - using value_type = cell_record; + using value_type = swc_record; using reference = value_type &; using const_referene = const value_type &; - using iterator = std::vector<cell_record>::iterator; - using const_iterator = std::vector<cell_record>::const_iterator; + using iterator = std::vector<swc_record>::iterator; + using const_iterator = std::vector<swc_record>::const_iterator; - cell_record_range_clean(std::istream &is); + swc_record_range_clean(std::istream &is); iterator begin() { - return cells_.begin(); + return records_.begin(); } iterator end() { - return cells_.end(); + return records_.end(); } std::size_t size() { - return cells_.size(); + return records_.size(); + } + + bool empty() const + { + return records_.empty(); } private: - std::vector<cell_record> cells_; + std::vector<swc_record> records_; }; struct swc_io_raw { - using cell_range_type = cell_record_range_raw; + using record_range_type = swc_record_range_raw; }; struct swc_io_clean { - using cell_range_type = cell_record_range_clean; + using record_range_type = swc_record_range_clean; }; template<typename T = swc_io_clean> - typename T::cell_range_type swc_get_records(std::istream &is) + typename T::record_range_type swc_get_records(std::istream &is) { - return typename T::cell_range_type(is); + return typename T::record_range_type(is); } } // namespace io diff --git a/tests/test_swcio.cpp b/tests/test_swcio.cpp index 96405e4f155ef210b53af6cee757aa7110051fc3..3de060ed4a69c446167d07c372ee0c872255ee30 100644 --- a/tests/test_swcio.cpp +++ b/tests/test_swcio.cpp @@ -10,8 +10,8 @@ #include <swcio.hpp> // SWC tests -void expect_cell_equals(const nest::mc::io::cell_record &expected, - const nest::mc::io::cell_record &actual) +void expect_record_equals(const nest::mc::io::swc_record &expected, + const nest::mc::io::swc_record &actual) { EXPECT_EQ(expected.id(), actual.id()); EXPECT_EQ(expected.type(), actual.type()); @@ -22,85 +22,85 @@ void expect_cell_equals(const nest::mc::io::cell_record &expected, EXPECT_EQ(expected.parent(), actual.parent()); } -TEST(cell_record, construction) +TEST(swc_record, construction) { using namespace nest::mc::io; { // force an invalid type - cell_record::kind invalid_type = static_cast<cell_record::kind>(100); - EXPECT_THROW(cell_record cell(invalid_type, 7, 1., 1., 1., 1., 5), + swc_record::kind invalid_type = static_cast<swc_record::kind>(100); + EXPECT_THROW(swc_record record(invalid_type, 7, 1., 1., 1., 1., 5), std::invalid_argument); } { // invalid id - EXPECT_THROW(cell_record cell( - cell_record::custom, -3, 1., 1., 1., 1., 5), + EXPECT_THROW(swc_record record( + swc_record::custom, -3, 1., 1., 1., 1., 5), std::invalid_argument); } { // invalid parent id - EXPECT_THROW(cell_record cell( - cell_record::custom, 0, 1., 1., 1., 1., -5), + EXPECT_THROW(swc_record record( + swc_record::custom, 0, 1., 1., 1., 1., -5), std::invalid_argument); } { // invalid radius - EXPECT_THROW(cell_record cell( - cell_record::custom, 0, 1., 1., 1., -1., -1), + EXPECT_THROW(swc_record record( + swc_record::custom, 0, 1., 1., 1., -1., -1), std::invalid_argument); } { // parent_id > id - EXPECT_THROW(cell_record cell( - cell_record::custom, 0, 1., 1., 1., 1., 2), + EXPECT_THROW(swc_record record( + swc_record::custom, 0, 1., 1., 1., 1., 2), std::invalid_argument); } { // parent_id == id - EXPECT_THROW(cell_record cell( - cell_record::custom, 0, 1., 1., 1., 1., 0), + EXPECT_THROW(swc_record record( + swc_record::custom, 0, 1., 1., 1., 1., 0), std::invalid_argument); } { // check standard construction by value - cell_record cell(cell_record::custom, 0, 1., 1., 1., 1., -1); - EXPECT_EQ(cell.id(), 0); - EXPECT_EQ(cell.type(), cell_record::custom); - EXPECT_EQ(cell.x(), 1.); - EXPECT_EQ(cell.y(), 1.); - EXPECT_EQ(cell.z(), 1.); - EXPECT_EQ(cell.radius(), 1.); - EXPECT_EQ(cell.diameter(), 2*1.); - EXPECT_EQ(cell.parent(), -1); + swc_record record(swc_record::custom, 0, 1., 1., 1., 1., -1); + EXPECT_EQ(record.id(), 0); + EXPECT_EQ(record.type(), swc_record::custom); + EXPECT_EQ(record.x(), 1.); + EXPECT_EQ(record.y(), 1.); + EXPECT_EQ(record.z(), 1.); + EXPECT_EQ(record.radius(), 1.); + EXPECT_EQ(record.diameter(), 2*1.); + EXPECT_EQ(record.parent(), -1); } { // check copy constructor - cell_record cell_orig(cell_record::custom, 0, 1., 1., 1., 1., -1); - cell_record cell(cell_orig); - expect_cell_equals(cell_orig, cell); + swc_record record_orig(swc_record::custom, 0, 1., 1., 1., 1., -1); + swc_record record(record_orig); + expect_record_equals(record_orig, record); } } -TEST(cell_record, comparison) +TEST(swc_record, comparison) { using namespace nest::mc::io; { // check comparison operators - cell_record cell0(cell_record::custom, 0, 1., 1., 1., 1., -1); - cell_record cell1(cell_record::custom, 0, 2., 3., 4., 5., -1); - cell_record cell2(cell_record::custom, 1, 2., 3., 4., 5., -1); - EXPECT_EQ(cell0, cell1); - EXPECT_LT(cell0, cell2); - EXPECT_GT(cell2, cell1); + swc_record record0(swc_record::custom, 0, 1., 1., 1., 1., -1); + swc_record record1(swc_record::custom, 0, 2., 3., 4., 5., -1); + swc_record record2(swc_record::custom, 1, 2., 3., 4., 5., -1); + EXPECT_EQ(record0, record1); + EXPECT_LT(record0, record2); + EXPECT_GT(record2, record1); } } @@ -112,24 +112,24 @@ TEST(swc_parser, invalid_input) { // check incomplete lines; missing parent std::istringstream is("1 1 14.566132 34.873772 7.857000 0.717830\n"); - cell_record cell; - EXPECT_THROW(is >> cell, swc_parse_error); + swc_record record; + EXPECT_THROW(is >> record, swc_parse_error); } { // Check non-parsable values std::istringstream is( "1a 1 14.566132 34.873772 7.857000 0.717830 -1\n"); - cell_record cell; - EXPECT_THROW(is >> cell, swc_parse_error); + swc_record record; + EXPECT_THROW(is >> record, swc_parse_error); } { - // Check invalid cell type + // Check invalid record type std::istringstream is( "1 10 14.566132 34.873772 7.857000 0.717830 -1\n"); - cell_record cell; - EXPECT_THROW(is >> cell, swc_parse_error); + swc_record record; + EXPECT_THROW(is >> record, swc_parse_error); } } @@ -139,58 +139,58 @@ TEST(swc_parser, valid_input) using namespace nest::mc::io; { - // check empty file; no cell may be parsed - cell_record cell, cell_orig; + // check empty file; no record may be parsed + swc_record record, record_orig; std::istringstream is(""); - EXPECT_NO_THROW(is >> cell); - expect_cell_equals(cell_orig, cell); + EXPECT_NO_THROW(is >> record); + expect_record_equals(record_orig, record); } { // check comment-only file not ending with a newline; - // no cell may be parsed - cell_record cell, cell_orig; + // no record may be parsed + swc_record record, record_orig; std::istringstream is("#comment\n#comment"); - EXPECT_NO_THROW(is >> cell); - expect_cell_equals(cell_orig, cell); + EXPECT_NO_THROW(is >> record); + expect_record_equals(record_orig, record); } { // check last line case (no newline at the end) std::istringstream is("1 1 14.566132 34.873772 7.857000 0.717830 -1"); - cell_record cell; - EXPECT_NO_THROW(is >> cell); - EXPECT_EQ(0, cell.id()); // zero-based indexing - EXPECT_EQ(cell_record::soma, cell.type()); - EXPECT_FLOAT_EQ(14.566132, cell.x()); - EXPECT_FLOAT_EQ(34.873772, cell.y()); - EXPECT_FLOAT_EQ( 7.857000, cell.z()); - EXPECT_FLOAT_EQ( 0.717830, cell.radius()); - EXPECT_FLOAT_EQ( -1, cell.parent()); + swc_record record; + EXPECT_NO_THROW(is >> record); + EXPECT_EQ(0, record.id()); // zero-based indexing + EXPECT_EQ(swc_record::soma, record.type()); + EXPECT_FLOAT_EQ(14.566132, record.x()); + EXPECT_FLOAT_EQ(34.873772, record.y()); + EXPECT_FLOAT_EQ( 7.857000, record.z()); + EXPECT_FLOAT_EQ( 0.717830, record.radius()); + EXPECT_FLOAT_EQ( -1, record.parent()); } { // check valid input with a series of records - std::vector<cell_record> cells_orig = { - cell_record(cell_record::soma, 0, + std::vector<swc_record> records_orig = { + swc_record(swc_record::soma, 0, 14.566132, 34.873772, 7.857000, 0.717830, -1), - cell_record(cell_record::dendrite, 1, + swc_record(swc_record::dendrite, 1, 14.566132+1, 34.873772+1, 7.857000+1, 0.717830+1, -1) }; std::stringstream swc_input; swc_input << "# this is a comment\n"; swc_input << "# this is a comment\n"; - for (auto c : cells_orig) + for (auto c : records_orig) swc_input << c << "\n"; swc_input << "# this is a final comment\n"; std::size_t nr_records = 0; - for (auto cell : swc_get_records<swc_io_raw>(swc_input)) { - ASSERT_LT(nr_records, cells_orig.size()); - expect_cell_equals(cells_orig[nr_records], cell); + for (auto record : swc_get_records<swc_io_raw>(swc_input)) { + ASSERT_LT(nr_records, records_orig.size()); + expect_record_equals(records_orig[nr_records], record); ++nr_records; } } @@ -207,8 +207,8 @@ TEST(swc_parser, from_allen_db) return; } - // load the cell records into a std::vector - std::vector<io::cell_record> nodes; + // load the record records into a std::vector + std::vector<io::swc_record> nodes; for (auto node : io::swc_get_records<io::swc_io_raw>(fid)) { nodes.push_back(std::move(node)); } @@ -240,8 +240,8 @@ TEST(swc_parser, input_cleaning) is << "3 1 14.566132 34.873772 7.857000 0.717830 -1\n"; is << "4 1 14.566132 34.873772 7.857000 0.717830 1\n"; - auto cells = swc_get_records(is); - EXPECT_EQ(2u, cells.size()); + auto records = swc_get_records(is); + EXPECT_EQ(2u, records.size()); } { @@ -252,7 +252,7 @@ TEST(swc_parser, input_cleaning) is << "4 1 14.566132 34.873772 7.857000 0.717830 1\n"; is << "1 1 14.566132 34.873772 7.857000 0.717830 -1\n"; - std::array<cell_record::id_type, 4> expected_id_list = {{ 0, 1, 2, 3 }}; + std::array<swc_record::id_type, 4> expected_id_list = {{ 0, 1, 2, 3 }}; auto expected_id = expected_id_list.cbegin(); for (auto c : swc_get_records(is)) { @@ -274,9 +274,9 @@ TEST(swc_parser, input_cleaning) is << "51 1 14.566132 34.873772 7.857000 0.717830 1\n"; is << "61 1 14.566132 34.873772 7.857000 0.717830 51\n"; - std::array<cell_record::id_type, 6> expected_id_list = + std::array<swc_record::id_type, 6> expected_id_list = {{ 0, 1, 2, 3, 4, 5 }}; - std::array<cell_record::id_type, 6> expected_parent_list = + std::array<swc_record::id_type, 6> expected_parent_list = {{ -1, 0, 1, 1, 0, 4 }}; auto expected_id = expected_id_list.cbegin(); @@ -294,7 +294,7 @@ TEST(swc_parser, input_cleaning) } } -TEST(cell_record_ranges, raw) +TEST(swc_record_ranges, raw) { using namespace nest::mc::io; @@ -306,17 +306,17 @@ TEST(cell_record_ranges, raw) is << "3 1 14.566132 34.873772 7.857000 0.717830 1\n"; is << "4 1 14.566132 34.873772 7.857000 0.717830 1\n"; - std::vector<cell_record> cells; + std::vector<swc_record> records; for (auto c : swc_get_records<swc_io_raw>(is)) { - cells.push_back(c); + records.push_back(c); } - EXPECT_EQ(4u, cells.size()); + EXPECT_EQ(4u, records.size()); bool entered = false; - auto citer = cells.begin(); + auto citer = records.begin(); for (auto c : swc_get_records<swc_io_raw>(is)) { - expect_cell_equals(c, *citer++); + expect_record_equals(c, *citer++); entered = true; } @@ -343,7 +343,7 @@ TEST(cell_record_ranges, raw) auto iter = swc_get_records<swc_io_raw>(is).begin(); auto iend = swc_get_records<swc_io_raw>(is).end(); - cell_record c; + swc_record c; EXPECT_NO_THROW(c = *iter++); EXPECT_EQ(-1, c.parent()); EXPECT_EQ(iend, iter); @@ -360,10 +360,10 @@ TEST(cell_record_ranges, raw) is << "3 10 14.566132 34.873772 7.857000 0.717830 1\n"; is << "4 1 14.566132 34.873772 7.857000 0.717830 1\n"; - std::vector<cell_record> cells; + std::vector<swc_record> records; try { for (auto c : swc_get_records<swc_io_raw>(is)) { - cells.push_back(c); + records.push_back(c); } ADD_FAILURE() << "expected an exception\n"; @@ -371,4 +371,11 @@ TEST(cell_record_ranges, raw) EXPECT_EQ(3u, e.lineno()); } } + + { + // Test empty range + std::stringstream is(""); + EXPECT_TRUE(swc_get_records<swc_io_raw>(is).empty()); + EXPECT_TRUE(swc_get_records<swc_io_clean>(is).empty()); + } }