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:
221
src/obiview.c
221
src/obiview.c
@ -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;
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user