When closing a view, it is now automatically checked that all OBI_QUAL

columns correspond to their associated OBI_SEQ column
This commit is contained in:
Celine Mercier
2016-11-25 12:04:57 +01:00
parent 70e056a2aa
commit f897e87600
2 changed files with 125 additions and 101 deletions

View File

@ -368,7 +368,7 @@ char* 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
* @brief Internal function checking that all the quality columns of a view and their associated sequence columns
* 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
@ -381,7 +381,7 @@ char* view_has_definition_column(Obiview_p view);
* @since July 2016
* @author Celine Mercier (celine.mercier@metabarcoding.org)
*/
char* view_check_quality_matches_seq_column(Obiview_p view);
char* view_check_qual_match_seqs(Obiview_p view);
/**
@ -960,9 +960,9 @@ char* view_has_definition_column(Obiview_p view)
}
char* view_check_quality_matches_seq_column(Obiview_p view) // TODO Print error if there is one?
char* view_check_qual_match_seqs(Obiview_p view)
{
index_t i, j;
index_t i, j, k;
index_t nb_elements_per_line;
int qual_len;
const uint8_t* qual;
@ -970,68 +970,84 @@ char* view_check_quality_matches_seq_column(Obiview_p view) // TODO Print error
OBIDMS_column_p qual_column;
OBIDMS_column_p seq_column;
char* predicate;
bool at_least_one_qual_col;
predicate = (char*) malloc((strlen("The sequences and sequence quality arrays match.") + 1) * sizeof(char));
if (predicate == NULL)
// Go through all columns in the view and check the predicate for all quality columns
at_least_one_qual_col = false;
for (i=0; i < ((view->infos)->column_count); i++)
{
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError allocating memory for predicate character string.");
return NULL;
}
strcpy(predicate, "The sequences and sequence quality arrays match.");
qual_column = obi_view_get_column(view, QUALITY_COLUMN);
if (qual_column == NULL)
{
obidebug(1, "\nError checking the predicate: %s", predicate);
return NULL;
}
seq_column = obi_view_get_column(view, ((qual_column->header)->associated_column).column_name);
//seq_column = obi_open_column(view->dms, ((qual_column->header)->associated_column).column_name, ((qual_column->header)->associated_column).version);
// TODO discuss the fact that it's opened outside of the context of the view or not -> problem if alias. Open from full refs maybe
// TODO if outside of view, make function that opens a column from a column reference structure?
if (seq_column == NULL)
{
obidebug(1, "\nError checking the predicate: %s", predicate);
return NULL;
}
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)
{
obidebug(1, "\nError checking the predicate: %s", predicate);
return NULL;
}
for (i=0; i < (view->infos)->line_count; i++)
{
for (j=0; j < nb_elements_per_line; j++)
// Check if it's a quality column
if ((((view->columns)[i])->header)->returned_data_type == OBI_QUAL)
{
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))
at_least_one_qual_col = true;
// Check that the quality arrays match the sequences of the associated column
qual_column = (view->columns)[i];
seq_column = obi_open_column(view->dms, ((qual_column->header)->associated_column).column_name, ((qual_column->header)->associated_column).version);
if (seq_column == NULL)
{
// Test that the lengths of the quality and the sequence are equal
if (qual_len != (int)strlen(seq))
{
obidebug(1, "\nError checking the predicate: %s", predicate);
return NULL;
}
}
// 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)))
{
obidebug(1, "\nError checking the predicate: %s", predicate);
obidebug(1, "\nError checking the predicate: The sequences and sequence quality arrays match.");
return NULL;
}
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)
{
obidebug(1, "\nError checking the predicate: The sequences and sequence quality arrays match.");
return NULL;
}
// Check each sequence and its sequence
for (j=0; j < (view->infos)->line_count; j++)
{
for (k=0; k < nb_elements_per_line; k++)
{
qual = obi_get_qual_int_with_elt_idx_and_col_p_in_view(view, qual_column, j, k, &qual_len);
seq = obi_get_seq_with_elt_idx_and_col_p_in_view(view, seq_column, j, k);
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))
{
obidebug(1, "\nError checking the predicate: The sequences and sequence quality arrays match.");
return NULL;
}
}
// 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)))
{
obidebug(1, "\nError checking the predicate: The sequences and sequence quality arrays match.");
return NULL;
}
}
}
obi_close_column(seq_column);
}
}
//obi_close_column(seq_column);
if (at_least_one_qual_col)
{
predicate = (char*) malloc((strlen("The sequences and sequence quality arrays match.") + 1) * sizeof(char));
if (predicate == NULL)
{
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError allocating memory for predicate character string.");
return NULL;
}
strcpy(predicate, "The sequences and sequence quality arrays match.");
}
else
{
predicate = (char*) malloc(1 * sizeof(char));
if (predicate == NULL)
{
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError allocating memory for predicate character string.");
return NULL;
}
strcpy(predicate, "");
}
return predicate;
}
@ -1051,11 +1067,11 @@ char* view_check_all_predicates(Obiview_p view)
char* all_predicates_string = NULL;
char** all_predicates = NULL;
if (view->nb_predicates == 0) // TODO or no error? discuss
if (view->nb_predicates == 0)
{
obi_set_errno(OBIVIEW_ERROR);
obidebug(1, "\nError trying to check predicates of a view with no predicates.");
return NULL;
all_predicates_string = (char*) malloc(1*sizeof(char));
strcpy(all_predicates_string, "");
return all_predicates_string;
}
size_to_allocate = 0;
@ -1073,7 +1089,6 @@ char* view_check_all_predicates(Obiview_p view)
{
// Initialize predicate in predicate array
all_predicates[i] = NULL;
// Check the predicate
predicate = view_check_one_predicate(view, (view->predicate_functions)[i]);
if (predicate == NULL)
@ -1105,7 +1120,8 @@ char* view_check_all_predicates(Obiview_p view)
strcpy(all_predicates_string, all_predicates[0]);
for (i=1; i < view->nb_predicates; i++)
{
strcat(all_predicates_string, "\n");
if (strlen(all_predicates_string)) // First predicate not empty
strcat(all_predicates_string, "\n");
strcat(all_predicates_string, all_predicates[i]);
}
@ -1271,16 +1287,6 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl
// Fill informations
strcpy((view->infos)->view_type, (view_to_clone->infos)->view_type);
strcpy((view->infos)->created_from, (view_to_clone->infos)->name);
// Copy predicates
view->nb_predicates = view_to_clone->nb_predicates;
if (view->nb_predicates > 0)
{
view->predicate_functions = malloc((view->nb_predicates) * sizeof(char* (*) (Obiview_p)));
for (i=0; i<(view->nb_predicates); i++)
(view->predicate_functions)[i] = (view_to_clone->predicate_functions)[i];
}
else
view->predicate_functions = NULL;
// Write comment specifying the name of the cloned view
clone_comment = (char*) malloc((strlen((view_to_clone->infos)->name) + 15)*sizeof(char));
@ -1313,8 +1319,6 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl
view->line_selection = NULL;
((view->infos)->created_from)[0] = '\0';
((view->infos)->view_type)[0] = '\0';
view->nb_predicates = 0;
view->predicate_functions = NULL;
//view->columns = NULL; // TODO
}
@ -1322,6 +1326,18 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl
strcpy((view->infos)->name, view_name);
(view->infos)->creation_date = time(NULL);
// Fill automatic predicate functions
view->nb_predicates = 1;
view->predicate_functions = malloc((view->nb_predicates) * sizeof(char* (*) (Obiview_p)));
if (view->predicate_functions == NULL)
{
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError allocating memory for view predicates");
return NULL;
}
(view->predicate_functions)[0] = view_check_qual_match_seqs;
// Write comments
if (write_comments_to_view_file(view, comments) < 0)
{
obidebug(1, "\nError writing comments when creating a view");
@ -1403,9 +1419,10 @@ Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p v
{
Obiview_p view;
OBIDMS_column_p associated_nuc_column;
int nb_predicates;
if (view_to_clone != NULL)
{ // Check that the view to clone is already a NUC_SEQS view (TODO discuss possibility of transforming type of a view)
{ // Check that the view to clone is already a NUC_SEQS view
if (strcmp((view_to_clone->infos)->view_type, VIEW_TYPE_NUC_SEQS))
{
obi_set_errno(OBIVIEW_ERROR);
@ -1452,25 +1469,34 @@ Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p v
}
}
// Add predicate functions of the view type
// Add predicate functions specific to the view type
// TODO macros?
if (quality_column)
view->nb_predicates = 5;
nb_predicates = view->nb_predicates + 4;
else
view->nb_predicates = 3;
nb_predicates = view->nb_predicates + 3;
view->predicate_functions = malloc((view->nb_predicates) * sizeof(char* (*) (Obiview_p)));
if (view->nb_predicates == 0)
view->predicate_functions = malloc(nb_predicates * sizeof(char* (*) (Obiview_p)));
else
view->predicate_functions = realloc(view->predicate_functions, nb_predicates * sizeof(char* (*) (Obiview_p)));
(view->predicate_functions)[0] = view_has_nuc_sequence_column;
(view->predicate_functions)[1] = view_has_id_column;
(view->predicate_functions)[2] = view_has_definition_column;
if (quality_column)
if (view->predicate_functions == NULL)
{
(view->predicate_functions)[3] = view_has_quality_column;
(view->predicate_functions)[4] = view_check_quality_matches_seq_column;
obi_set_errno(OBI_MALLOC_ERROR);
obidebug(1, "\nError allocating memory for view predicates");
return NULL;
}
(view->predicate_functions)[(view->nb_predicates)] = view_has_nuc_sequence_column;
(view->predicate_functions)[(view->nb_predicates) + 1] = view_has_id_column;
(view->predicate_functions)[(view->nb_predicates) + 2] = view_has_definition_column;
if (quality_column)
(view->predicate_functions)[(view->nb_predicates) + 3] = view_has_quality_column;
view->nb_predicates = nb_predicates;
return view;
}
@ -1825,8 +1851,6 @@ int obi_view_delete_column(Obiview_p view, const char* column_name)
int i;
bool found;
// TODO check that not deleting an obligatory column?
// Check that the view is not read-only
if (view->read_only)
{
@ -2020,19 +2044,16 @@ int obi_save_and_close_view(Obiview_p view)
if (!(view->read_only))
{
if (view->nb_predicates > 0)
predicates = view_check_all_predicates(view);
if (predicates == NULL)
{
predicates = view_check_all_predicates(view);
if (predicates == NULL)
{
obidebug(1, "\nView predicates not respected");
return -1; // TODO reverse view (delete files)
}
else
{
write_comments_to_view_file(view, predicates);
free(predicates);
}
obidebug(1, "\nView predicates not respected");
return -1; // TODO reverse view (delete files)
}
else
{
write_comments_to_view_file(view, predicates);
free(predicates);
}
if (obi_save_view(view) < 0)
return -1;

View File

@ -464,7 +464,7 @@ int obi_save_view(Obiview_p view);
/**
* @brief Closes an opened view.
*
* @warning Use obi_save_and_close_view() to automatically save the view if it's not already saved in the view file.
* @warning Uses obi_save_and_close_view() to automatically save the view if it's not already saved in the view file.
*
* @param view A pointer on the view.
*
@ -481,6 +481,9 @@ int obi_close_view(Obiview_p view);
/**
* @brief Closes an opened view, and saves it if it is not read-only (meaning it is not already saved in the view file).
*
* The predicates associated with the view are checked before saving it, and -1 is returned if at
* least one predicate is not respected.
*
* @param view A pointer on the view.
*
* @returns A value indicating the success of the operation.