/// \brief Return the second dimensions size of a test matrix /// /// \pre Matrix cannot be empty (ie first dimension size must be > 0) else an invalid_argument_exception will be thrown /// /// \pre Matrix must have a consistent size of the second dimension else an invalid_argument_exception will be thrown /// /// \returns The size of the second dimension static size_t get_second_dimension_size(const bool_deq_vec &arg_test_matrix ///< The test matrix to query ) { if (arg_test_matrix.empty()) { BOOST_THROW_EXCEPTION(invalid_argument_exception("Cannot get second dimension size for empty test matrix")); } const bool_deq::size_type second_dimension_size = arg_test_matrix.front().size(); for (const bool_deq &entry : arg_test_matrix) { if (second_dimension_size != entry.size()) { BOOST_THROW_EXCEPTION(invalid_argument_exception("Test matrix does not have a consistent second dimension size")); } } return second_dimension_size; }
/// \brief Check that get_window_start_a_for_b() and get_window_stop_a_for_b() recreate the values in the matrix for the specified window size void check_windowed_matrix(const bool_deq_vec &arg_test_matrix, ///< The test matrix to check const size_t &arg_window_size ///< The window size to use ) const { const size_t first_dimension_size = arg_test_matrix.size(); const size_t second_dimension_size = get_second_dimension_size(arg_test_matrix); for (size_t entry_ctr = 0; entry_ctr < first_dimension_size; ++entry_ctr) { const bool_deq &entry = arg_test_matrix[entry_ctr]; const size_size_pair first_and_last = get_indices_of_first_and_last_trues(entry); const size_t &first_true_index = first_and_last.first; const size_t &last_true_index = first_and_last.second; BOOST_CHECK_EQUAL( first_true_index + 1, get_window_start_a_for_b__offset_1( second_dimension_size, first_dimension_size, arg_window_size, entry_ctr + 1 ) ); BOOST_CHECK_EQUAL( last_true_index + 1, get_window_stop_a_for_b__offset_1( second_dimension_size, first_dimension_size, arg_window_size, entry_ctr + 1 ) ); if (first_true_index > 0 && last_true_index + 1 < second_dimension_size) { if (first_dimension_size != second_dimension_size) { BOOST_CHECK_EQUAL( arg_window_size, last_true_index - first_true_index + 1 ); } } } }
/// \brief Checks that residue_name_aligner::residue_name_align() does the correct thing for all permutations of the residue lists. /// /// This should be accessed via check_residue_name_aligner_results() or check_residue_name_aligner_throws() /// /// This subroutine is mostly ready to handle more than two lists. /// /// \todo modify the actual call to residue_name_aligner::residue_name_align() to handle multiple lists /// (after that subroutine has been altered to handle multiple lists) void do_check_residue_name_aligner(const residue_name_vec_vec &arg_residue_lists, const bool_deq_vec &arg_correct_presence_lists, const size_vec_vec &arg_correct_answer_lists, const bool &arg_should_throw ) { const size_t num_lists = arg_residue_lists.size(); BOOST_REQUIRE_EQUAL(num_lists, 2_z); /// This code isn't yet able to process more than two at a time if (!arg_should_throw) { BOOST_REQUIRE_EQUAL(num_lists, arg_correct_presence_lists.size()); BOOST_REQUIRE_EQUAL(num_lists, arg_correct_answer_lists.size()); } // Construct a vector containing the indices of the lists size_vec permutation_indices(num_lists, 0); for (size_t index_ctr = 0; index_ctr < num_lists; ++index_ctr) { permutation_indices[index_ctr] = index_ctr; } // Loop over the permutations of the indices do { // If these residue lists should cause residue_name_aligner::residue_name_align() to throw then check they do if (arg_should_throw) { BOOST_CHECK_THROW( residue_name_aligner::residue_name_align( { arg_residue_lists[ permutation_indices[ 0 ] ], arg_residue_lists[ permutation_indices[ 1 ] ] } ), invalid_argument_exception ); } // Otherwise check the results from residue_name_aligner::residue_name_align() else { // Construct an alignment from this permutation of residue lists const alignment my_alignment = residue_name_aligner::residue_name_align( { arg_residue_lists[permutation_indices[ 0 ]], arg_residue_lists[permutation_indices[ 1 ]] } ); const alignment::size_type num_positions = my_alignment.length(); // Check each of the alignment entries in turn for (size_t index_ctr = 0; index_ctr < num_lists; ++index_ctr) { // Grab the correct answer list under the current permutation const size_t permutation_index = permutation_indices[index_ctr]; const bool_deq &correct_presence_list = arg_correct_presence_lists[permutation_index]; const size_vec &correct_answer_list = arg_correct_answer_lists[permutation_index]; const size_t correct_answer_size = correct_answer_list.size(); // Check that the number of positions match BOOST_CHECK_EQUAL(correct_answer_size, num_positions); // Check that each of the positions in the alignment match what is expected for (size_t position_ctr = 0; position_ctr < min(correct_answer_size, num_positions); ++position_ctr) { const aln_posn_opt position = my_alignment.position_of_entry_of_index( index_ctr, position_ctr ); const bool has_position = static_cast<bool>( position ); BOOST_CHECK_EQUAL( correct_presence_list[position_ctr], has_position ); if ( position ) { BOOST_CHECK_EQUAL(correct_answer_list[position_ctr], *position ); } } } } } while ( next_permutation( permutation_indices ) ); }