diff --git a/BioFVM/BioFVM_microenvironment.cpp b/BioFVM/BioFVM_microenvironment.cpp index e18c9ff43..93b19c872 100644 --- a/BioFVM/BioFVM_microenvironment.cpp +++ b/BioFVM/BioFVM_microenvironment.cpp @@ -1472,7 +1472,6 @@ void load_initial_conditions_from_csv(std::string filename) bool header_provided = false; if( c == 'X' || c == 'x' ) { - // do not support this with a header yet if ((line.c_str()[2] != 'Y' && line.c_str()[2] != 'y') || (line.c_str()[4] != 'Z' && line.c_str()[4] != 'z')) { std::cout << "ERROR: Header row starts with x but then not y,z? What is this? Exiting now." << std::endl; @@ -1518,20 +1517,11 @@ void load_initial_conditions_from_csv(std::string filename) } std::cout << "Loading substrate initial conditions from CSV file " << filename << " ... " << std::endl; - std::vector voxel_set = {}; // set to check that no voxel value is set twice - + std::vector voxel_is_set(microenvironment.number_of_voxels(), false); // set to check that no voxel value is set twice + while (std::getline(file, line)) { - get_row_from_substrate_initial_condition_csv(voxel_set, line, substrate_indices, header_provided); - } - - if (voxel_set.size() != microenvironment.number_of_voxels()) - { - std::cout << "ERROR : Wrong number of voxels supplied in the .csv file specifying BioFVM initial conditions." << std::endl - << "\tExpected: " << microenvironment.number_of_voxels() << std::endl - << "\tFound: " << voxel_set.size() << std::endl - << "\tRemember, your table should have dimensions #voxels x (3 + #densities)." << std::endl; - exit(-1); + get_row_from_substrate_initial_condition_csv(voxel_is_set, line, substrate_indices, header_provided); } file.close(); @@ -1539,11 +1529,11 @@ void load_initial_conditions_from_csv(std::string filename) return; } -void get_row_from_substrate_initial_condition_csv(std::vector &voxel_set, const std::string line, const std::vector substrate_indices, const bool header_provided) +void get_row_from_substrate_initial_condition_csv(std::vector &voxel_is_set, const std::string line, const std::vector substrate_indices, const bool header_provided) { static bool warning_issued = false; std::vector data; - csv_to_vector(line.c_str(), data); + substrate_csv_to_vector(line.c_str(), data); if (!(warning_issued) && !(header_provided) && (data.size() != (microenvironment.number_of_densities() + 3))) { @@ -1557,19 +1547,17 @@ void get_row_from_substrate_initial_condition_csv(std::vector &voxel_set, c std::vector position = {data[0], data[1], data[2]}; int voxel_ind = microenvironment.mesh.nearest_voxel_index(position); - for (unsigned int ci = 0; ci < substrate_indices.size(); ci++) // column index, counting from the first substrate (or just the index of the vector substrate_indices) + if (voxel_is_set[voxel_ind]) { - microenvironment.density_vector(voxel_ind)[substrate_indices[ci]] = data[ci + 3]; + std::cout << "ERROR : the csv-supplied initial conditions for BioFVM repeat the same voxel. Fix the .csv file and try again." << std::endl + << "\tPosition that was repeated: " << position << std::endl; + exit(-1); } - for (unsigned int j = 0; j < voxel_set.size(); j++) + voxel_is_set[voxel_ind] = true; + for (unsigned int ci = 0; ci < substrate_indices.size(); ci++) // column index, counting from the first substrate (or just the index of the vector substrate_indices) { - if (voxel_ind == voxel_set[j]) - { - std::cout << "ERROR : the csv-supplied initial conditions for BioFVM repeat the same voxel. Fix the .csv file and try again." << std::endl - << "\tPosition that was repeated: " << position << std::endl; - exit(-1); - } + microenvironment.density_vector(voxel_ind)[substrate_indices[ci]] = data[ci + 3]; } - voxel_set.push_back(voxel_ind); } + }; diff --git a/BioFVM/BioFVM_microenvironment.h b/BioFVM/BioFVM_microenvironment.h index 6fec93728..d5a310d17 100644 --- a/BioFVM/BioFVM_microenvironment.h +++ b/BioFVM/BioFVM_microenvironment.h @@ -367,7 +367,7 @@ void set_microenvironment_initial_condition( void ); void load_initial_conditions_from_matlab( std::string filename ); void load_initial_conditions_from_csv( std::string filename ); -void get_row_from_substrate_initial_condition_csv(std::vector &voxel_set, const std::string line, const std::vector substrate_indices, const bool header_provided); +void get_row_from_substrate_initial_condition_csv(std::vector &voxel_is_set, const std::string line, const std::vector substrate_indices, const bool header_provided); }; #endif diff --git a/BioFVM/BioFVM_vector.cpp b/BioFVM/BioFVM_vector.cpp index e12a3672d..45a011991 100644 --- a/BioFVM/BioFVM_vector.cpp +++ b/BioFVM/BioFVM_vector.cpp @@ -376,6 +376,46 @@ void csv_to_vector( const char* buffer , std::vector& vect ) return; } +void substrate_csv_to_vector(const char* buffer, std::vector& vect) +{ + vect.clear(); + + const char* start = buffer; + const char* end = buffer; + + while (*end != '\0') + { + if (*end == ',') + { + if (start == end) + { + // Empty field: treat as 0 + vect.push_back(0.0); + } + else + { + vect.push_back(strtod(start, nullptr)); + } + end++; + start = end; + } + else + { + end++; + } + } + + // Handle the last field (could be empty at end of line) + if (start == end) + { + vect.push_back(0.0); + } + else + { + vect.push_back(strtod(start, nullptr)); + } +} + char* vector_to_csv( const std::vector& vect ) { static int datum_size = 16; // format = %.7e, 1 (sign) + 1 (lead) + 1 (decimal) + 7 (figs) + 2 (e, sign) + 3 (exponent) + 1 (delimiter) = 16 diff --git a/BioFVM/BioFVM_vector.h b/BioFVM/BioFVM_vector.h index e3c36d449..d70b90684 100644 --- a/BioFVM/BioFVM_vector.h +++ b/BioFVM/BioFVM_vector.h @@ -129,7 +129,9 @@ void double_axpy_div( std::vector* y, std::vector& a1 , std::vec // turn a delimited character array (e.g., csv) into a vector of doubles -void csv_to_vector( const char* buffer , std::vector& vect ); +void csv_to_vector( const char* buffer , std::vector& vect ); +void substrate_csv_to_vector(const char* buffer, std::vector& vect); + char* vector_to_csv( const std::vector& vect ); void vector_to_csv_safe( const std::vector& vect , char*& buffer ); void vector_to_csv( const std::vector& vect , char*& buffer );