From 8ee85c30058868a4b36996e569f6efe196ae0a23 Mon Sep 17 00:00:00 2001 From: Celine Mercier Date: Tue, 12 Jul 2016 14:54:11 +0200 Subject: [PATCH] A first version of predicate functions that are checked when a new view is saved and closed --- src/obiview.c | 248 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/obiview.h | 40 ++++---- 2 files changed, 262 insertions(+), 26 deletions(-) diff --git a/src/obiview.c b/src/obiview.c index da23357..98ac2f9 100644 --- a/src/obiview.c +++ b/src/obiview.c @@ -129,7 +129,7 @@ OBIDMS_column_p clone_column_in_view(Obiview_p view, const char* column_name); /** - * Internal function preparing to set a value in a column, in the context of a view. + * @brief Internal function preparing to set a value in a column, in the context of a view. * * The function checks that the view is not read-only, clones the column or all columns if needed, * and updates the line count if needed. @@ -148,7 +148,7 @@ int prepare_to_set_value_in_column(Obiview_p view, OBIDMS_column_p* column_pp, i /** - * Internal function preparing to get a value from a column, in the context of a view. + * @brief Internal function preparing to get a value from a column, in the context of a view. * * The function checks that the line index is not beyond the current line count of the view, * and modifies it if there is a line selection associated with the view. @@ -165,6 +165,116 @@ int prepare_to_set_value_in_column(Obiview_p view, OBIDMS_column_p* column_pp, i int prepare_to_get_value_from_column(Obiview_p view, index_t* line_nb_p); +/****** PREDICATE FUNCTIONS *******/ + +/** + * @brief Internal function checking if a view has a NUC_SEQUENCE_COLUMN column. + * + * The function checks that the view has a column with the name attributed to obligatory + * nucleotide sequence columns. + * + * @param view The view. + * + * @returns A boolean value indicating whether the view has a NUC_SEQUENCE_COLUMN column. + * + * @since July 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +bool view_has_nuc_sequence_column(Obiview_p view); + + +/** + * @brief Internal function checking if a view has a QUALITY_COLUMN column. + * + * The function checks that the view has a column with the name attributed to obligatory + * quality columns. + * + * @param view The view. + * + * @returns A boolean value indicating whether the view has a QUALITY_COLUMN column. + * + * @since July 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +bool view_has_quality_column(Obiview_p view); + + +/** + * @brief Internal function checking if a view has a ID_COLUMN column. + * + * The function checks that the view has a column with the name attributed to obligatory + * id columns. + * + * @param view The view. + * + * @returns A boolean value indicating whether the view has a ID_COLUMN column. + * + * @since July 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +bool view_has_id_column(Obiview_p view); + + +/** + * @brief Internal function checking if a view has a DEFINITION_COLUMN column. + * + * The function checks that the view has a column with the name attributed to obligatory + * definition columns. + * + * @param view The view. + * + * @returns A boolean value indicating whether the view has a DEFINITION_COLUMN column. + * + * @since July 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +bool view_has_definition_column(Obiview_p view); + + +/** + * @brief Internal function checking that the quality column of a view and the sequence column associated to it + * correspond properly: + * - when a line is defined for either column, it must also be defined for the other column + * - when a line is defined, the lengths of the sequence and of the quality must be equal + * + * @param view The view. + * + * @returns A boolean value indicating whether the sequence and quality columns correspond properly. + * + * @since July 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +bool view_check_quality_matches_seq_column(Obiview_p view); + + +/** + * @brief Internal function checking one predicate function on a view. + * + * @param view The view. + * @param predicate_function The predicate function to use. + * + * @returns The boolean value returned by the predicate function. + * + * @since July 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +bool view_check_one_predicate(Obiview_p view, bool (*predicate_function)(Obiview_p view)); + + +/** + * @brief Internal function checking all the predicates associated with a view. + * + * @param view The view. + * + * @retval 0 if all the predicates are OK. + * @retval -1 if at least one predicate was found to be false. + * + * @since July 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int view_check_all_predicates(Obiview_p view); + + /************************************************************************ * * D E F I N I T I O N O F T H E P R I V A T E F U N C T I O N S @@ -229,11 +339,11 @@ int create_obiview_file(OBIDMS_p dms, const char* view_name) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError creating an obiview file"); -// free(file_name); TODO +// free(file_name); return -1; } - //free(file_name); TODO + //free(file_name); // Truncate file to the right size file_size = get_platform_view_file_size(); @@ -419,6 +529,111 @@ int prepare_to_get_value_from_column(Obiview_p view, index_t* line_nb_p) } + +/****** PREDICATE FUNCTIONS *******/ + +bool view_has_nuc_sequence_column(Obiview_p view) +{ + if (obi_view_get_column(view, NUC_SEQUENCE_COLUMN) != NULL) + return true; + else + return false; +} + + +bool view_has_quality_column(Obiview_p view) +{ + if (obi_view_get_column(view, QUALITY_COLUMN) != NULL) + return true; + else + return false; +} + + +bool view_has_id_column(Obiview_p view) +{ + if (obi_view_get_column(view, ID_COLUMN) != NULL) + return true; + else + return false; +} + + +bool view_has_definition_column(Obiview_p view) +{ + if (obi_view_get_column(view, DEFINITION_COLUMN) != NULL) + return true; + else + return false; +} + + +bool view_check_quality_matches_seq_column(Obiview_p view) // TODO Print error if there is one? +{ + index_t i, j; + index_t nb_elements_per_line; + int qual_len; + const uint8_t* qual; + char* seq; + OBIDMS_column_p qual_column; + OBIDMS_column_p seq_column; + + qual_column = obi_view_get_column(view, QUALITY_COLUMN); + if (qual_column == NULL) + return false; + + seq_column = obi_view_get_column(view, NUC_SEQUENCE_COLUMN); // TODO Get associated nuc column + if (seq_column == NULL) + return false; + + nb_elements_per_line = (qual_column->header)->nb_elements_per_line; + // Check that the quality and the sequence columns have the same number of elements per line + if (nb_elements_per_line != (seq_column->header)->nb_elements_per_line) + return false; + + for (i=0; i < (view->infos)->line_count; i++) + { + for (j=0; j < nb_elements_per_line; j++) + { + qual = obi_column_get_obiqual_int_with_elt_idx(qual_column, i, j, &qual_len); + seq = obi_column_get_obiseq_with_elt_idx(seq_column, i, j); + if ((qual != OBIQual_int_NA) && (seq != OBISeq_NA)) + { + // Test that the lengths of the quality and the sequence are equal + if (qual_len != (int)strlen(seq)) + return false; + } + // Test if one value is NA and not the other + else if (((qual == OBIQual_int_NA) && (seq != OBISeq_NA)) || ((qual != OBIQual_int_NA) && (seq == OBISeq_NA))) + return false; + } + } + return true; +} + + +bool view_check_one_predicate(Obiview_p view, bool (*predicate_function)(Obiview_p view)) +{ + return predicate_function(view); +} + + +int view_check_all_predicates(Obiview_p view) +{ + int i; + + for (i=0; i < view->nb_predicates; i++) + { + if (view_check_one_predicate(view, (view->predicate_functions)[i]) == false) + return -1; + } + return 0; +} + + +// TODO predicate function that goes through each line / each elements + + /********************************************************************** * * D E F I N I T I O N O F T H E P U B L I C F U N C T I O N S @@ -581,6 +796,8 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl strcpy((view->infos)->comments, comments); (view->infos)->creation_date = time(NULL); view->read_only = 0; + view->nb_predicates = 0; + view->predicate_functions = NULL; // Store reference for line selection if (view->line_selection == NULL) @@ -665,6 +882,17 @@ Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p v } } + // Add predicate functions of the view type + view->nb_predicates = 5; // TODO macro? + + view->predicate_functions = malloc((view->nb_predicates) * sizeof(bool (*) (bool))); + + (view->predicate_functions)[0] = view_has_nuc_sequence_column; + (view->predicate_functions)[1] = view_has_quality_column; + (view->predicate_functions)[2] = view_has_id_column; + (view->predicate_functions)[3] = view_has_definition_column; + (view->predicate_functions)[4] = view_check_quality_matches_seq_column; + return view; } @@ -704,11 +932,11 @@ Obiview_infos_p obi_view_map_file(OBIDMS_p dms, const char* view_name) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError opening an obiview file"); -// free(file_name); TODO +// free(file_name); return NULL; } - //free(file_name); TODO + //free(file_name); // Map the view infos structure file_size = get_platform_view_file_size(); @@ -750,11 +978,11 @@ int obi_view_unmap_file(OBIDMS_p dms, Obiview_infos_p view_infos) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError opening an obiview file"); - // free(file_name); TODO + // free(file_name); return -1; } - //free(file_name); TODO + //free(file_name); // Unmap the view infos structure file_size = get_platform_view_file_size(); @@ -819,6 +1047,8 @@ Obiview_p obi_open_view(OBIDMS_p dms, const char* view_name) view->dms = dms; view->new_line_selection = NULL; view->read_only = true; + view->nb_predicates = 0; + view->predicate_functions = NULL; return view; } @@ -1159,6 +1389,8 @@ int obi_save_and_close_view(Obiview_p view) { if (!(view->read_only)) { + if (view_check_all_predicates(view) < 0) + return -1; // TODO reverse view (delete files) if (obi_save_view(view) < 0) return -1; } diff --git a/src/obiview.h b/src/obiview.h index 1f018e3..04cf454 100644 --- a/src/obiview.h +++ b/src/obiview.h @@ -99,24 +99,28 @@ typedef struct Obiview_infos { * @brief Structure for an opened view. */ typedef struct Obiview { - Obiview_infos_p infos; /**< A pointer on the mapped view informations. - */ - OBIDMS_p dms; /**< A pointer on the DMS to which the view belongs. - */ - bool read_only; /**< Whether the view is read-only or can be modified. - */ - OBIDMS_column_p line_selection; /**< A pointer on the column containing the line selection - * associated with the view if there is one. - * This line selection is read-only, and when a line from the view is read, - * it is this line selection that is used. - */ - OBIDMS_column_p new_line_selection; /**< A pointer on the column containing the new line selection being built - * to associate with the view, if there is one. - * When a line is selected with obi_select_line() or obi_select_lines(), - * it is recorded in this line selection. - */ - OBIDMS_column_p columns[MAX_NB_OPENED_COLUMNS]; /**< Array of pointers on all the columns of the view. - */ + Obiview_infos_p infos; /**< A pointer on the mapped view informations. + */ + OBIDMS_p dms; /**< A pointer on the DMS to which the view belongs. + */ + bool read_only; /**< Whether the view is read-only or can be modified. + */ + OBIDMS_column_p line_selection; /**< A pointer on the column containing the line selection + * associated with the view if there is one. + * This line selection is read-only, and when a line from the view is read, + * it is this line selection that is used. + */ + OBIDMS_column_p new_line_selection; /**< A pointer on the column containing the new line selection being built + * to associate with the view, if there is one. + * When a line is selected with obi_select_line() or obi_select_lines(), + * it is recorded in this line selection. + */ + OBIDMS_column_p columns[MAX_NB_OPENED_COLUMNS]; /**< Array of pointers on all the columns of the view. + */ + int nb_predicates; /**< Number of predicates to test when closing the view. + */ + bool (**predicate_functions)(struct Obiview* view); /**< Array of pointers on all predicate functions to test when closing the view. + */ } Obiview_t, *Obiview_p;